summaryrefslogtreecommitdiffstats
path: root/filter
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /filter
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'filter')
-rw-r--r--filter/AllLangMoTarget_flt.mk13
-rw-r--r--filter/Configuration_filter.mk934
-rw-r--r--filter/CppunitTest_filter_dialogs_test.mk68
-rw-r--r--filter/CppunitTest_filter_msfilter.mk44
-rw-r--r--filter/CppunitTest_filter_pdf.mk48
-rw-r--r--filter/CppunitTest_filter_priority.mk41
-rw-r--r--filter/CppunitTest_filter_svg.mk47
-rw-r--r--filter/CppunitTest_filter_textfilterdetect.mk44
-rw-r--r--filter/CppunitTest_filter_xslt.mk41
-rw-r--r--filter/CustomTarget_svg.mk63
-rw-r--r--filter/IwyuFilter_filter.yaml56
-rw-r--r--filter/JunitTest_filter_complex.mk33
-rw-r--r--filter/Library_filterconfig.mk61
-rw-r--r--filter/Library_graphicfilter.mk53
-rw-r--r--filter/Library_icg.mk56
-rw-r--r--filter/Library_msfilter.mk72
-rw-r--r--filter/Library_odfflatxml.mk36
-rw-r--r--filter/Library_pdffilter.mk66
-rw-r--r--filter/Library_storagefd.mk34
-rw-r--r--filter/Library_svgfilter.mk79
-rw-r--r--filter/Library_t602filter.mk47
-rw-r--r--filter/Library_textfd.mk36
-rw-r--r--filter/Library_xmlfa.mk42
-rw-r--r--filter/Library_xmlfd.mk42
-rw-r--r--filter/Library_xsltdlg.mk60
-rw-r--r--filter/Library_xsltfilter.mk52
-rw-r--r--filter/Makefile14
-rw-r--r--filter/Module_filter.mk72
-rw-r--r--filter/Package_docbook.mk27
-rw-r--r--filter/Package_xhtml.mk26
-rw-r--r--filter/Package_xslt.mk70
-rw-r--r--filter/README.md25
-rw-r--r--filter/UIConfig_filter.mk28
-rw-r--r--filter/inc/strings.hrc76
-rw-r--r--filter/inc/strings.hxx24
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/Helper.java431
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/TypeDetection.java546
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/TypeDetection.props31
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/files.csv117
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/makefile.mk109
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/preselectedFilter.csv6
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/preselectedType.csv6
-rw-r--r--filter/qa/complex/filter/detection/typeDetection/serviceName.csv6
-rw-r--r--filter/qa/complex/filter/misc/FinalizedMandatoryTest.java304
-rw-r--r--filter/qa/complex/filter/misc/TypeDetection6FileFormat.java127
-rw-r--r--filter/qa/complex/filter/misc/TypeDetection6FileFormat.xcu42
-rw-r--r--filter/qa/cppunit/data/xslt/copy.xslt9
-rw-r--r--filter/qa/cppunit/msfilter-test.cxx76
-rw-r--r--filter/qa/cppunit/priority-test.cxx85
-rw-r--r--filter/qa/cppunit/xslt-test.cxx207
-rw-r--r--filter/qa/data/picture.pdfbin0 -> 13829 bytes
-rw-r--r--filter/qa/pdf.cxx347
-rw-r--r--filter/qa/unit/data/TransparentText.odgbin0 -> 9354 bytes
-rw-r--r--filter/qa/unit/data/attributeRedefinedTest.odpbin0 -> 12610 bytes
-rw-r--r--filter/qa/unit/data/calc.otsbin0 -> 9564 bytes
-rw-r--r--filter/qa/unit/data/custom-bullet.fodp36
-rw-r--r--filter/qa/unit/data/empty.doc0
-rw-r--r--filter/qa/unit/data/empty.odp0
-rw-r--r--filter/qa/unit/data/empty.ods0
-rw-r--r--filter/qa/unit/data/empty.odt0
-rw-r--r--filter/qa/unit/data/empty.pptx0
-rw-r--r--filter/qa/unit/data/filter-dialogs-test.txt49
-rw-r--r--filter/qa/unit/data/impress.otpbin0 -> 15382 bytes
-rw-r--r--filter/qa/unit/data/preserve-jpg.odtbin0 -> 10052 bytes
-rw-r--r--filter/qa/unit/data/semi-transparent-fill.odgbin0 -> 10597 bytes
-rw-r--r--filter/qa/unit/data/semi-transparent-line.odgbin0 -> 8874 bytes
-rw-r--r--filter/qa/unit/data/shape-nographic.odpbin0 -> 14769 bytes
-rw-r--r--filter/qa/unit/data/tdf114428.xhtml9
-rw-r--r--filter/qa/unit/data/writer.ottbin0 -> 10017 bytes
-rw-r--r--filter/qa/unit/filter-dialogs-test.cxx61
-rw-r--r--filter/qa/unit/svg.cxx380
-rw-r--r--filter/qa/unit/textfilterdetect.cxx199
-rw-r--r--filter/source/config/cache/basecontainer.cxx476
-rw-r--r--filter/source/config/cache/basecontainer.hxx256
-rw-r--r--filter/source/config/cache/cacheitem.cxx325
-rw-r--r--filter/source/config/cache/cacheitem.hxx177
-rw-r--r--filter/source/config/cache/cacheupdatelistener.cxx182
-rw-r--r--filter/source/config/cache/cacheupdatelistener.hxx113
-rw-r--r--filter/source/config/cache/configflush.cxx112
-rw-r--r--filter/source/config/cache/configflush.hxx89
-rw-r--r--filter/source/config/cache/constant.hxx153
-rw-r--r--filter/source/config/cache/contenthandlerfactory.cxx103
-rw-r--r--filter/source/config/cache/contenthandlerfactory.hxx99
-rw-r--r--filter/source/config/cache/filtercache.cxx2236
-rw-r--r--filter/source/config/cache/filtercache.hxx939
-rw-r--r--filter/source/config/cache/filterconfig1.component42
-rw-r--r--filter/source/config/cache/filterfactory.cxx498
-rw-r--r--filter/source/config/cache/filterfactory.hxx135
-rw-r--r--filter/source/config/cache/frameloaderfactory.cxx102
-rw-r--r--filter/source/config/cache/frameloaderfactory.hxx98
-rw-r--r--filter/source/config/cache/querytokenizer.cxx69
-rw-r--r--filter/source/config/cache/querytokenizer.hxx92
-rw-r--r--filter/source/config/cache/typedetection.cxx1204
-rw-r--r--filter/source/config/cache/typedetection.hxx350
-rw-r--r--filter/source/config/fragments/contenthandlers/com_sun_star_comp_framework_SoundHandler.xcu20
-rw-r--r--filter/source/config/fragments/contenthandlers/com_sun_star_comp_framework_oxt_handler.xcu20
-rw-r--r--filter/source/config/fragments/filters/ADO_rowset_XML.xcu30
-rw-r--r--filter/source/config/fragments/filters/AbiWord.xcu30
-rw-r--r--filter/source/config/fragments/filters/AppleKeynote.xcu29
-rw-r--r--filter/source/config/fragments/filters/AppleNumbers.xcu29
-rw-r--r--filter/source/config/fragments/filters/ApplePages.xcu29
-rw-r--r--filter/source/config/fragments/filters/BMP___MS_Windows.xcu30
-rw-r--r--filter/source/config/fragments/filters/BroadBand_eBook.xcu29
-rw-r--r--filter/source/config/fragments/filters/CGM___Computer_Graphics_Metafile.xcu30
-rw-r--r--filter/source/config/fragments/filters/ClarisWorks.xcu30
-rw-r--r--filter/source/config/fragments/filters/ClarisWorks_Calc.xcu30
-rw-r--r--filter/source/config/fragments/filters/ClarisWorks_Draw.xcu30
-rw-r--r--filter/source/config/fragments/filters/ClarisWorks_Impress.xcu30
-rw-r--r--filter/source/config/fragments/filters/Claris_Resolve_Calc.xcu30
-rw-r--r--filter/source/config/fragments/filters/CorelDrawDocument.xcu30
-rw-r--r--filter/source/config/fragments/filters/CorelPresentationExchange.xcu30
-rw-r--r--filter/source/config/fragments/filters/DIF.xcu30
-rw-r--r--filter/source/config/fragments/filters/DXF___AutoCAD_Interchange.xcu30
-rw-r--r--filter/source/config/fragments/filters/DocBook_File.xcu30
-rw-r--r--filter/source/config/fragments/filters/DosWord.xcu28
-rw-r--r--filter/source/config/fragments/filters/EMF___MS_Windows_Metafile.xcu30
-rw-r--r--filter/source/config/fragments/filters/EPS___Encapsulated_PostScript.xcu30
-rw-r--r--filter/source/config/fragments/filters/EPUB.xcu30
-rw-r--r--filter/source/config/fragments/filters/FictionBook_2.xcu29
-rw-r--r--filter/source/config/fragments/filters/FreehandDocument.xcu13
-rw-r--r--filter/source/config/fragments/filters/GIF___Graphics_Interchange.xcu30
-rw-r--r--filter/source/config/fragments/filters/HTML.xcu30
-rw-r--r--filter/source/config/fragments/filters/HTML_MasterDoc.xcu30
-rw-r--r--filter/source/config/fragments/filters/HTML__StarCalc_.xcu30
-rw-r--r--filter/source/config/fragments/filters/HTML__StarWriter_.xcu30
-rw-r--r--filter/source/config/fragments/filters/JPG___JPEG.xcu30
-rw-r--r--filter/source/config/fragments/filters/Lotus.xcu30
-rw-r--r--filter/source/config/fragments/filters/LotusWordPro.xcu30
-rw-r--r--filter/source/config/fragments/filters/MET___OS_2_Metafile.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_2003_XML.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_2003_XML_Orcus.xcu19
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_4_0.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_4_0_Vorlage_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_5_0_95.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_5_0_95_Vorlage_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_95.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_95_Vorlage_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_97.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Excel_97_Vorlage_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Multiplan.xcu29
-rw-r--r--filter/source/config/fragments/filters/MS_PowerPoint_97.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_PowerPoint_97_AutoPlay.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_PowerPoint_97_Vorlage.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_WinWord_5.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_WinWord_6_0.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Word_2003_XML.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Word_2007_XML.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Word_2007_XML_Template.xcu28
-rw-r--r--filter/source/config/fragments/filters/MS_Word_2007_XML_VBA.xcu18
-rw-r--r--filter/source/config/fragments/filters/MS_Word_95.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Word_95_Vorlage.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Word_97.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Word_97_Vorlage.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Works.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Works_Calc.xcu30
-rw-r--r--filter/source/config/fragments/filters/MS_Write.xcu30
-rw-r--r--filter/source/config/fragments/filters/MWAW_Bitmap.xcu29
-rw-r--r--filter/source/config/fragments/filters/MWAW_Database.xcu29
-rw-r--r--filter/source/config/fragments/filters/MWAW_Drawing.xcu29
-rw-r--r--filter/source/config/fragments/filters/MWAW_Presentation.xcu29
-rw-r--r--filter/source/config/fragments/filters/MWAW_Spreadsheet.xcu29
-rw-r--r--filter/source/config/fragments/filters/MWAW_Text_Document.xcu29
-rw-r--r--filter/source/config/fragments/filters/MacWrite.xcu30
-rw-r--r--filter/source/config/fragments/filters/Mac_Word.xcu30
-rw-r--r--filter/source/config/fragments/filters/Mac_Works.xcu30
-rw-r--r--filter/source/config/fragments/filters/Mac_Works_Calc.xcu30
-rw-r--r--filter/source/config/fragments/filters/Mariner_Write.xcu30
-rw-r--r--filter/source/config/fragments/filters/MathML_XML__Math_.xcu30
-rw-r--r--filter/source/config/fragments/filters/MathType_3_x.xcu30
-rw-r--r--filter/source/config/fragments/filters/ODG_FlatXML.xcu30
-rw-r--r--filter/source/config/fragments/filters/ODP_FlatXML.xcu30
-rw-r--r--filter/source/config/fragments/filters/ODS_FlatXML.xcu30
-rw-r--r--filter/source/config/fragments/filters/ODT_FlatXML.xcu30
-rw-r--r--filter/source/config/fragments/filters/OOXML_Text.xcu31
-rw-r--r--filter/source/config/fragments/filters/OOXML_Text_Template.xcu31
-rw-r--r--filter/source/config/fragments/filters/PBM___Portable_Bitmap.xcu30
-rw-r--r--filter/source/config/fragments/filters/PCT___Mac_Pict.xcu30
-rw-r--r--filter/source/config/fragments/filters/PCX___Zsoft_Paintbrush.xcu30
-rw-r--r--filter/source/config/fragments/filters/PGM___Portable_Graymap.xcu30
-rw-r--r--filter/source/config/fragments/filters/PNG___Portable_Network_Graphic.xcu30
-rw-r--r--filter/source/config/fragments/filters/PPM___Portable_Pixelmap.xcu30
-rw-r--r--filter/source/config/fragments/filters/PSD___Adobe_Photoshop.xcu30
-rw-r--r--filter/source/config/fragments/filters/PageMakerDocument.xcu13
-rw-r--r--filter/source/config/fragments/filters/PalmDoc.xcu29
-rw-r--r--filter/source/config/fragments/filters/Palm_Text_Document.xcu29
-rw-r--r--filter/source/config/fragments/filters/Plucker_eBook.xcu29
-rw-r--r--filter/source/config/fragments/filters/PocketWord_File.xcu29
-rw-r--r--filter/source/config/fragments/filters/PowerPoint3.xcu28
-rw-r--r--filter/source/config/fragments/filters/PublisherDocument.xcu30
-rw-r--r--filter/source/config/fragments/filters/QPro.xcu30
-rw-r--r--filter/source/config/fragments/filters/QXPDocument.xcu13
-rw-r--r--filter/source/config/fragments/filters/RAS___Sun_Rasterfile.xcu30
-rw-r--r--filter/source/config/fragments/filters/Rich_Text_Format.xcu30
-rw-r--r--filter/source/config/fragments/filters/Rich_Text_Format__StarCalc_.xcu30
-rw-r--r--filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu30
-rw-r--r--filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu30
-rw-r--r--filter/source/config/fragments/filters/SVM___StarView_Metafile.xcu30
-rw-r--r--filter/source/config/fragments/filters/SYLK.xcu30
-rw-r--r--filter/source/config/fragments/filters/StarBaseReport.xcu38
-rw-r--r--filter/source/config/fragments/filters/StarBaseReportChart.xcu40
-rw-r--r--filter/source/config/fragments/filters/StarOffice_Drawing.xcu29
-rw-r--r--filter/source/config/fragments/filters/StarOffice_Presentation.xcu29
-rw-r--r--filter/source/config/fragments/filters/StarOffice_Spreadsheet.xcu29
-rw-r--r--filter/source/config/fragments/filters/StarOffice_Writer.xcu29
-rw-r--r--filter/source/config/fragments/filters/StarOffice_XML__Base_.xcu30
-rw-r--r--filter/source/config/fragments/filters/StarOffice_XML__Calc_.xcu30
-rw-r--r--filter/source/config/fragments/filters/StarOffice_XML__Chart_.xcu30
-rw-r--r--filter/source/config/fragments/filters/StarOffice_XML__Draw_.xcu30
-rw-r--r--filter/source/config/fragments/filters/StarOffice_XML__Impress_.xcu30
-rw-r--r--filter/source/config/fragments/filters/StarOffice_XML__Math_.xcu30
-rw-r--r--filter/source/config/fragments/filters/StarOffice_XML__Writer_.xcu30
-rw-r--r--filter/source/config/fragments/filters/T602Document.xcu30
-rw-r--r--filter/source/config/fragments/filters/TGA___Truevision_TARGA.xcu30
-rw-r--r--filter/source/config/fragments/filters/TIF___Tag_Image_File.xcu30
-rw-r--r--filter/source/config/fragments/filters/Text.xcu31
-rw-r--r--filter/source/config/fragments/filters/Text__StarWriter_Web_.xcu31
-rw-r--r--filter/source/config/fragments/filters/Text___txt___csv__StarCalc_.xcu31
-rw-r--r--filter/source/config/fragments/filters/Text__encoded_.xcu31
-rw-r--r--filter/source/config/fragments/filters/Text__encoded___StarWriter_GlobalDocument_.xcu31
-rw-r--r--filter/source/config/fragments/filters/Text__encoded___StarWriter_Web_.xcu31
-rw-r--r--filter/source/config/fragments/filters/UOF_presentation.xcu30
-rw-r--r--filter/source/config/fragments/filters/UOF_spreadsheet.xcu30
-rw-r--r--filter/source/config/fragments/filters/UOF_text.xcu30
-rw-r--r--filter/source/config/fragments/filters/VisioDocument.xcu30
-rw-r--r--filter/source/config/fragments/filters/WEBP___WebP.xcu30
-rw-r--r--filter/source/config/fragments/filters/WMF___MS_Windows_Metafile.xcu30
-rw-r--r--filter/source/config/fragments/filters/WPS_Lotus_Calc.xcu30
-rw-r--r--filter/source/config/fragments/filters/WPS_QPro_Calc.xcu30
-rw-r--r--filter/source/config/fragments/filters/WordPerfect.xcu30
-rw-r--r--filter/source/config/fragments/filters/WordPerfectGraphics.xcu30
-rw-r--r--filter/source/config/fragments/filters/WriteNow.xcu30
-rw-r--r--filter/source/config/fragments/filters/XBM___X_Consortium.xcu30
-rw-r--r--filter/source/config/fragments/filters/XHTML_Calc_File.xcu30
-rw-r--r--filter/source/config/fragments/filters/XHTML_Draw_File.xcu30
-rw-r--r--filter/source/config/fragments/filters/XHTML_Impress_File.xcu30
-rw-r--r--filter/source/config/fragments/filters/XHTML_Writer_File.xcu30
-rw-r--r--filter/source/config/fragments/filters/XPM.xcu30
-rw-r--r--filter/source/config/fragments/filters/ZMFDocument.xcu13
-rw-r--r--filter/source/config/fragments/filters/calc8.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc8_template.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_Gnumeric.xcu29
-rw-r--r--filter/source/config/fragments/filters/calc_HTML_WebQuery.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_MS_Excel_2007_Binary.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_MS_Excel_2007_VBA_XML.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_MS_Excel_2007_XML.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_MS_Excel_2007_XML_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_OOXML.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_OOXML_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_StarOffice_XML_Calc_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_jpg_Export.xcu20
-rw-r--r--filter/source/config/fragments/filters/calc_pdf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_png_Export.xcu20
-rw-r--r--filter/source/config/fragments/filters/calc_svg_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/calc_webp_Export.xcu20
-rw-r--r--filter/source/config/fragments/filters/chart8.xcu30
-rw-r--r--filter/source/config/fragments/filters/dBase.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw8.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw8_template.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base16.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base4.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_StarOffice_XML_Draw_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_bmp_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_emf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_eps_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_gif_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_html_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_jpg_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_pdf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_png_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_svg_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_tif_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_webp_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/draw_wmf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress8.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress8_draw.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress8_template.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_AutoPlay.xcu28
-rw-r--r--filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_Template.xcu28
-rw-r--r--filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_VBA.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_OOXML.xcu29
-rw-r--r--filter/source/config/fragments/filters/impress_OOXML_AutoPlay.xcu28
-rw-r--r--filter/source/config/fragments/filters/impress_OOXML_Template.xcu29
-rw-r--r--filter/source/config/fragments/filters/impress_StarOffice_XML_Draw.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_StarOffice_XML_Impress_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_bmp_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_emf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_eps_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_gif_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_html_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_jpg_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_pdf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_png_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_svg_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_tif_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_webp_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/impress_wmf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/math8.xcu30
-rw-r--r--filter/source/config/fragments/filters/math_pdf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/mov__MOV.xcu21
-rw-r--r--filter/source/config/fragments/filters/writer8.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer8_template.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_MIZI_Hwp_97.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_StarOffice_XML_Writer_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_globaldocument_StarOffice_XML_Writer.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_globaldocument_StarOffice_XML_Writer_GlobalDocument.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_globaldocument_pdf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_indexing_export.xcu22
-rw-r--r--filter/source/config/fragments/filters/writer_jpg_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_layout_dump.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_pdf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_png_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_svg_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_web_HTML_help.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_web_StarOffice_XML_Writer.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_web_StarOffice_XML_Writer_Web_Template.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_web_jpg_Export.xcu21
-rw-r--r--filter/source/config/fragments/filters/writer_web_pdf_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/writer_web_png_Export.xcu21
-rw-r--r--filter/source/config/fragments/filters/writer_web_webp_Export.xcu21
-rw-r--r--filter/source/config/fragments/filters/writer_webp_Export.xcu30
-rw-r--r--filter/source/config/fragments/filters/writerglobal8.xcu30
-rw-r--r--filter/source/config/fragments/filters/writerglobal8_HTML.xcu30
-rw-r--r--filter/source/config/fragments/filters/writerglobal8_template.xcu20
-rw-r--r--filter/source/config/fragments/filters/writerglobal8_writer.xcu30
-rw-r--r--filter/source/config/fragments/filters/writerweb8_writer.xcu30
-rw-r--r--filter/source/config/fragments/filters/writerweb8_writer_template.xcu30
-rw-r--r--filter/source/config/fragments/frameloaders/com_sun_star_comp_chart2_ChartFrameLoader.xcu20
-rw-r--r--filter/source/config/fragments/frameloaders/com_sun_star_frame_Bibliography.xcu20
-rw-r--r--filter/source/config/fragments/frameloaders/com_sun_star_sdb_ContentLoader.xcu20
-rw-r--r--filter/source/config/fragments/frameloaders/org_openoffice_comp_dbflt_DBContentLoader2.xcu20
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/bmp_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/bmp_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/dxf_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/emf_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/emf_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/eps_Export.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/eps_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/gif_Export.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/gif_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/jpg_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/jpg_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/met_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/mov_Import.xcu18
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pbm_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base16.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base4.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pct_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pcx_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pdf_Export.xcu17
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pdf_Import.xcu17
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/pgm_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/png_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/png_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/ppm_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/psd_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/ras_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/svg_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/svm_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/svm_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/tga_Import.xcu28
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/tif_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/tif_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/webp_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/webp_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/wmf_Export.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/wmf_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/xbm_Import.xcu27
-rw-r--r--filter/source/config/fragments/internalgraphicfilters/xpm_Import.xcu27
-rw-r--r--filter/source/config/fragments/langfilter.xsl57
-rw-r--r--filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu27
-rw-r--r--filter/source/config/fragments/types/MS_Excel_2007_VBA_XML.xcu27
-rw-r--r--filter/source/config/fragments/types/MS_Excel_2007_XML.xcu27
-rw-r--r--filter/source/config/fragments/types/MS_Excel_2007_XML_Template.xcu27
-rw-r--r--filter/source/config/fragments/types/MS_PowerPoint_2007_XML.xcu27
-rw-r--r--filter/source/config/fragments/types/MS_PowerPoint_2007_XML_AutoPlay.xcu27
-rw-r--r--filter/source/config/fragments/types/MS_PowerPoint_2007_XML_Template.xcu27
-rw-r--r--filter/source/config/fragments/types/MS_PowerPoint_2007_XML_VBA.xcu28
-rw-r--r--filter/source/config/fragments/types/MWAW_Bitmap.xcu27
-rw-r--r--filter/source/config/fragments/types/MWAW_Database.xcu27
-rw-r--r--filter/source/config/fragments/types/MWAW_Drawing.xcu27
-rw-r--r--filter/source/config/fragments/types/MWAW_Presentation.xcu27
-rw-r--r--filter/source/config/fragments/types/MWAW_Spreadsheet.xcu27
-rw-r--r--filter/source/config/fragments/types/MWAW_Text_Document.xcu27
-rw-r--r--filter/source/config/fragments/types/Palm_Text_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/StarBase.xcu29
-rw-r--r--filter/source/config/fragments/types/StarBaseReport.xcu43
-rw-r--r--filter/source/config/fragments/types/StarBaseReportChart.xcu41
-rw-r--r--filter/source/config/fragments/types/StarOffice_Drawing.xcu27
-rw-r--r--filter/source/config/fragments/types/StarOffice_Presentation.xcu27
-rw-r--r--filter/source/config/fragments/types/StarOffice_Spreadsheet.xcu27
-rw-r--r--filter/source/config/fragments/types/StarOffice_Writer.xcu27
-rw-r--r--filter/source/config/fragments/types/Unified_Office_Format_presentation.xcu29
-rw-r--r--filter/source/config/fragments/types/Unified_Office_Format_spreadsheet.xcu29
-rw-r--r--filter/source/config/fragments/types/Unified_Office_Format_text.xcu29
-rw-r--r--filter/source/config/fragments/types/XHTML_File.xcu29
-rw-r--r--filter/source/config/fragments/types/bmp_MS_Windows.xcu29
-rw-r--r--filter/source/config/fragments/types/calc8.xcu29
-rw-r--r--filter/source/config/fragments/types/calc8_template.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_ADO_rowset_XML.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_AppleNumbers.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_ClarisWorks.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_Claris_Resolve.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_DIF.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_Gnumeric.xcu17
-rw-r--r--filter/source/config/fragments/types/calc_HTML.xcu35
-rw-r--r--filter/source/config/fragments/types/calc_Lotus.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_2003_XML.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_40.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_40_VorlageTemplate.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_5095.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_5095_VorlageTemplate.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_95.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_95_VorlageTemplate.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_97.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Excel_97_VorlageTemplate.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_MS_Multiplan.xcu25
-rw-r--r--filter/source/config/fragments/types/calc_MS_Works_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_Mac_Works.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_ODS_FlatXML.xcu31
-rw-r--r--filter/source/config/fragments/types/calc_OOXML.xcu27
-rw-r--r--filter/source/config/fragments/types/calc_OOXML_Template.xcu27
-rw-r--r--filter/source/config/fragments/types/calc_QPro.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_SYLK.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_StarOffice_XML_Calc.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_StarOffice_XML_Calc_Template.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_WPS_Lotus_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_WPS_QPro_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/calc_dBase.xcu29
-rw-r--r--filter/source/config/fragments/types/chart8.xcu29
-rw-r--r--filter/source/config/fragments/types/chart_StarOffice_XML_Chart.xcu29
-rw-r--r--filter/source/config/fragments/types/component_Bibliography.xcu29
-rw-r--r--filter/source/config/fragments/types/component_DB.xcu29
-rw-r--r--filter/source/config/fragments/types/draw8.xcu29
-rw-r--r--filter/source/config/fragments/types/draw8_template.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_ClarisWorks.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_CorelDraw_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_Corel_Presentation_Exchange.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_Freehand_Document.xcu12
-rw-r--r--filter/source/config/fragments/types/draw_ODG_FlatXML.xcu31
-rw-r--r--filter/source/config/fragments/types/draw_PageMaker_Document.xcu12
-rw-r--r--filter/source/config/fragments/types/draw_Publisher_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_QXP_Document.xcu12
-rw-r--r--filter/source/config/fragments/types/draw_StarOffice_XML_Draw.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_StarOffice_XML_Draw_Template.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_Visio_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_WordPerfect_Graphics.xcu29
-rw-r--r--filter/source/config/fragments/types/draw_ZMF_Document.xcu12
-rw-r--r--filter/source/config/fragments/types/dxf_AutoCAD_Interchange.xcu29
-rw-r--r--filter/source/config/fragments/types/emf_MS_Windows_Metafile.xcu29
-rw-r--r--filter/source/config/fragments/types/eps_Encapsulated_PostScript.xcu29
-rw-r--r--filter/source/config/fragments/types/generic_HTML.xcu30
-rw-r--r--filter/source/config/fragments/types/generic_Text.xcu28
-rw-r--r--filter/source/config/fragments/types/gif_Graphics_Interchange.xcu29
-rw-r--r--filter/source/config/fragments/types/graphic_HTML.xcu29
-rw-r--r--filter/source/config/fragments/types/impress8.xcu29
-rw-r--r--filter/source/config/fragments/types/impress8_template.xcu29
-rw-r--r--filter/source/config/fragments/types/impress_AppleKeynote.xcu29
-rw-r--r--filter/source/config/fragments/types/impress_CGM_Computer_Graphics_Metafile.xcu29
-rw-r--r--filter/source/config/fragments/types/impress_ClarisWorks.xcu29
-rw-r--r--filter/source/config/fragments/types/impress_MS_PowerPoint_97.xcu29
-rw-r--r--filter/source/config/fragments/types/impress_MS_PowerPoint_97_AutoPlay.xcu29
-rw-r--r--filter/source/config/fragments/types/impress_MS_PowerPoint_97_Vorlage.xcu29
-rw-r--r--filter/source/config/fragments/types/impress_ODP_FlatXML.xcu31
-rw-r--r--filter/source/config/fragments/types/impress_OOXML_Presentation.xcu27
-rw-r--r--filter/source/config/fragments/types/impress_OOXML_Presentation_AutoPlay.xcu27
-rw-r--r--filter/source/config/fragments/types/impress_OOXML_Presentation_Template.xcu27
-rw-r--r--filter/source/config/fragments/types/impress_PowerPoint3.xcu22
-rw-r--r--filter/source/config/fragments/types/impress_StarOffice_XML_Impress.xcu29
-rw-r--r--filter/source/config/fragments/types/impress_StarOffice_XML_Impress_Template.xcu29
-rw-r--r--filter/source/config/fragments/types/jpg_JPEG.xcu29
-rw-r--r--filter/source/config/fragments/types/math8.xcu29
-rw-r--r--filter/source/config/fragments/types/math_MathML_XML_Math.xcu29
-rw-r--r--filter/source/config/fragments/types/math_MathType_3x.xcu29
-rw-r--r--filter/source/config/fragments/types/math_StarOffice_XML_Math.xcu29
-rw-r--r--filter/source/config/fragments/types/met_OS2_Metafile.xcu29
-rw-r--r--filter/source/config/fragments/types/mov_MOV.xcu20
-rw-r--r--filter/source/config/fragments/types/oxt_OpenOffice_Extension.xcu29
-rw-r--r--filter/source/config/fragments/types/pbm_Portable_Bitmap.xcu29
-rw-r--r--filter/source/config/fragments/types/pcd_Photo_CD_Base.xcu29
-rw-r--r--filter/source/config/fragments/types/pcd_Photo_CD_Base16.xcu29
-rw-r--r--filter/source/config/fragments/types/pcd_Photo_CD_Base4.xcu29
-rw-r--r--filter/source/config/fragments/types/pct_Mac_Pict.xcu29
-rw-r--r--filter/source/config/fragments/types/pcx_Zsoft_Paintbrush.xcu29
-rw-r--r--filter/source/config/fragments/types/pdf_Portable_Document_Format.xcu29
-rw-r--r--filter/source/config/fragments/types/pgm_Portable_Graymap.xcu29
-rw-r--r--filter/source/config/fragments/types/png_Portable_Network_Graphic.xcu29
-rw-r--r--filter/source/config/fragments/types/ppm_Portable_Pixelmap.xcu29
-rw-r--r--filter/source/config/fragments/types/psd_Adobe_Photoshop.xcu29
-rw-r--r--filter/source/config/fragments/types/ras_Sun_Rasterfile.xcu29
-rw-r--r--filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu29
-rw-r--r--filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu29
-rw-r--r--filter/source/config/fragments/types/svm_StarView_Metafile.xcu29
-rw-r--r--filter/source/config/fragments/types/tga_Truevision_TARGA.xcu29
-rw-r--r--filter/source/config/fragments/types/tif_Tag_Image_File.xcu29
-rw-r--r--filter/source/config/fragments/types/wav_Wave_Audio_File.xcu29
-rw-r--r--filter/source/config/fragments/types/webp_WebP.xcu29
-rw-r--r--filter/source/config/fragments/types/wmf_MS_Windows_Metafile.xcu29
-rw-r--r--filter/source/config/fragments/types/writer8.xcu29
-rw-r--r--filter/source/config/fragments/types/writer8_template.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_AbiWord_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_ApplePages.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_BroadBand_eBook.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_ClarisWorks.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_DocBook_File.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_DosWord.xcu22
-rw-r--r--filter/source/config/fragments/types/writer_EPUB_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_FictionBook_2.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_LotusWordPro_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MIZI_Hwp_97.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_WinWord_5.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_WinWord_60.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_Word_2003_XML.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_Word_2007_XML.xcu27
-rw-r--r--filter/source/config/fragments/types/writer_MS_Word_2007_XML_Template.xcu27
-rw-r--r--filter/source/config/fragments/types/writer_MS_Word_2007_XML_VBA.xcu17
-rw-r--r--filter/source/config/fragments/types/writer_MS_Word_95.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_Word_95_Vorlage.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_Word_97.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_Word_97_Vorlage.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_Works_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MS_Write.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_MacWrite.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_Mac_Word.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_Mac_Works.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_Mariner_Write.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_ODT_FlatXML.xcu31
-rw-r--r--filter/source/config/fragments/types/writer_OOXML.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_OOXML_Template.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_PalmDoc.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_Plucker_eBook.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_PocketWord_File.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_Rich_Text_Format.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_StarOffice_XML_Writer.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_StarOffice_XML_Writer_Template.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_T602_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_WordPerfect_Document.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_WriteNow.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_globaldocument_StarOffice_XML_Writer_GlobalDocument.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_indexing_export_xml.xcu21
-rw-r--r--filter/source/config/fragments/types/writer_layout_dump_xml.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_web_HTML_help.xcu29
-rw-r--r--filter/source/config/fragments/types/writer_web_StarOffice_XML_Writer_Web_Template.xcu29
-rw-r--r--filter/source/config/fragments/types/writerglobal8.xcu29
-rw-r--r--filter/source/config/fragments/types/writerglobal8_template.xcu19
-rw-r--r--filter/source/config/fragments/types/writerweb8_writer_template.xcu29
-rw-r--r--filter/source/config/fragments/types/xbm_X_Consortium.xcu29
-rw-r--r--filter/source/config/fragments/types/xpm_XPM.xcu29
-rw-r--r--filter/source/config/tools/merge/FCFGMerge.cfg112
-rwxr-xr-xfilter/source/config/tools/merge/pyAltFCFGMerge590
-rw-r--r--filter/source/docbook/DocBookTemplate.stwbin0 -> 6688 bytes
-rw-r--r--filter/source/docbook/docbooktosoffheadings.xsl1416
-rw-r--r--filter/source/docbook/sofftodocbookheadings.xsl1152
-rw-r--r--filter/source/graphic/GraphicExportFilter.cxx235
-rw-r--r--filter/source/graphic/GraphicExportFilter.hxx79
-rw-r--r--filter/source/graphic/graphicfilter.component26
-rw-r--r--filter/source/graphicfilter/icgm/actimpr.cxx1041
-rw-r--r--filter/source/graphicfilter/icgm/bitmap.cxx433
-rw-r--r--filter/source/graphicfilter/icgm/bitmap.hxx81
-rw-r--r--filter/source/graphicfilter/icgm/bundles.cxx141
-rw-r--r--filter/source/graphicfilter/icgm/bundles.hxx166
-rw-r--r--filter/source/graphicfilter/icgm/cgm.cxx741
-rw-r--r--filter/source/graphicfilter/icgm/cgm.hxx151
-rw-r--r--filter/source/graphicfilter/icgm/cgmtypes.hxx127
-rw-r--r--filter/source/graphicfilter/icgm/chart.cxx57
-rw-r--r--filter/source/graphicfilter/icgm/chart.hxx84
-rw-r--r--filter/source/graphicfilter/icgm/class0.cxx128
-rw-r--r--filter/source/graphicfilter/icgm/class1.cxx225
-rw-r--r--filter/source/graphicfilter/icgm/class2.cxx233
-rw-r--r--filter/source/graphicfilter/icgm/class3.cxx134
-rw-r--r--filter/source/graphicfilter/icgm/class4.cxx911
-rw-r--r--filter/source/graphicfilter/icgm/class5.cxx532
-rw-r--r--filter/source/graphicfilter/icgm/class7.cxx210
-rw-r--r--filter/source/graphicfilter/icgm/classx.cxx249
-rw-r--r--filter/source/graphicfilter/icgm/elements.cxx336
-rw-r--r--filter/source/graphicfilter/icgm/elements.hxx136
-rw-r--r--filter/source/graphicfilter/icgm/outact.hxx108
-rw-r--r--filter/source/msfilter/countryid.cxx319
-rw-r--r--filter/source/msfilter/dffpropset.cxx1360
-rw-r--r--filter/source/msfilter/dffrecordheader.cxx43
-rw-r--r--filter/source/msfilter/escherex.cxx5295
-rw-r--r--filter/source/msfilter/eschesdo.cxx1237
-rw-r--r--filter/source/msfilter/eschesdo.hxx138
-rw-r--r--filter/source/msfilter/mscodec.cxx642
-rw-r--r--filter/source/msfilter/msdffimp.cxx7610
-rw-r--r--filter/source/msfilter/msfilter.component26
-rw-r--r--filter/source/msfilter/msocximex.cxx146
-rw-r--r--filter/source/msfilter/msoleexp.cxx340
-rw-r--r--filter/source/msfilter/mstoolbar.cxx824
-rw-r--r--filter/source/msfilter/msvbahelper.cxx768
-rw-r--r--filter/source/msfilter/rtfutil.cxx401
-rw-r--r--filter/source/msfilter/svdfppt.cxx7832
-rw-r--r--filter/source/msfilter/svxmsbas2.cxx80
-rw-r--r--filter/source/msfilter/util.cxx1340
-rw-r--r--filter/source/msfilter/viscache.hxx52
-rw-r--r--filter/source/odfflatxml/OdfFlatXml.cxx260
-rw-r--r--filter/source/odfflatxml/odfflatxml.component17
-rw-r--r--filter/source/pdf/impdialog.cxx1638
-rw-r--r--filter/source/pdf/impdialog.hxx419
-rw-r--r--filter/source/pdf/pdfdecomposer.cxx123
-rw-r--r--filter/source/pdf/pdfdialog.cxx139
-rw-r--r--filter/source/pdf/pdfdialog.hxx72
-rw-r--r--filter/source/pdf/pdfexport.cxx1374
-rw-r--r--filter/source/pdf/pdfexport.hxx145
-rw-r--r--filter/source/pdf/pdffilter.component38
-rw-r--r--filter/source/pdf/pdffilter.cxx295
-rw-r--r--filter/source/pdf/pdffilter.hxx70
-rw-r--r--filter/source/pdf/pdfinteract.cxx97
-rw-r--r--filter/source/pdf/pdfinteract.hxx61
-rw-r--r--filter/source/storagefilterdetect/filterdetect.cxx192
-rw-r--r--filter/source/storagefilterdetect/filterdetect.hxx56
-rw-r--r--filter/source/storagefilterdetect/storagefd.component16
-rw-r--r--filter/source/svg/.eslintrc.js250
-rw-r--r--filter/source/svg/gentoken.py60
-rwxr-xr-xfilter/source/svg/js2hxx.py149
-rw-r--r--filter/source/svg/presentation_engine.js19575
-rw-r--r--filter/source/svg/svgexport.cxx2877
-rw-r--r--filter/source/svg/svgfilter.component32
-rw-r--r--filter/source/svg/svgfilter.cxx847
-rw-r--r--filter/source/svg/svgfilter.hxx321
-rw-r--r--filter/source/svg/svgfontexport.cxx321
-rw-r--r--filter/source/svg/svgfontexport.hxx72
-rw-r--r--filter/source/svg/svgwriter.cxx4096
-rw-r--r--filter/source/svg/svgwriter.hxx406
-rw-r--r--filter/source/svg/test/odfserializer.cxx128
-rw-r--r--filter/source/svg/test/odfserializer.hxx33
-rw-r--r--filter/source/svg/tokens.txt403
-rw-r--r--filter/source/t602/t602filter.component31
-rw-r--r--filter/source/t602/t602filter.cxx1137
-rw-r--r--filter/source/t602/t602filter.hxx255
-rw-r--r--filter/source/textfilterdetect/filterdetect.cxx247
-rw-r--r--filter/source/textfilterdetect/filterdetect.hxx59
-rw-r--r--filter/source/textfilterdetect/textfd.component17
-rw-r--r--filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx391
-rw-r--r--filter/source/xmlfilteradaptor/XmlFilterAdaptor.hxx106
-rw-r--r--filter/source/xmlfilteradaptor/xmlfa.component27
-rw-r--r--filter/source/xmlfilterdetect/filterdetect.cxx246
-rw-r--r--filter/source/xmlfilterdetect/filterdetect.hxx59
-rw-r--r--filter/source/xmlfilterdetect/xmlfd.component26
-rw-r--r--filter/source/xslt/common/copy.xsl26
-rw-r--r--filter/source/xslt/common/math.xsl580
-rw-r--r--filter/source/xslt/common/measure_conversion.xsl479
-rw-r--r--filter/source/xslt/export/common/ooo2ms_docpr.xsl130
-rw-r--r--filter/source/xslt/export/spreadsheetml/formular.xsl631
-rw-r--r--filter/source/xslt/export/spreadsheetml/ooo2spreadsheetml.xsl408
-rw-r--r--filter/source/xslt/export/spreadsheetml/style_mapping.xsl381
-rw-r--r--filter/source/xslt/export/spreadsheetml/styles.xsl686
-rw-r--r--filter/source/xslt/export/spreadsheetml/table.xsl928
-rw-r--r--filter/source/xslt/export/uof/odf2uof_presentation.xsl3392
-rw-r--r--filter/source/xslt/export/uof/odf2uof_spreadsheet.xsl6245
-rw-r--r--filter/source/xslt/export/uof/odf2uof_text.xsl4456
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml.xsl209
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_border.xsl144
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_custom_draw.xsl275
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_draw.xsl1760
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_field.xsl726
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_list.xsl349
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_page.xsl392
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_path.xsl849
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_settings.xsl308
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_table.xsl407
-rw-r--r--filter/source/xslt/export/wordml/ooo2wordml_text.xsl1270
-rw-r--r--filter/source/xslt/import/common/ms2ooo_docpr.xsl92
-rw-r--r--filter/source/xslt/import/spreadsheetml/adorowset2ods.xsl216
-rw-r--r--filter/source/xslt/import/spreadsheetml/spreadsheetml2ooo.xsl9152
-rw-r--r--filter/source/xslt/import/uof/uof2odf_presentation.xsl3494
-rw-r--r--filter/source/xslt/import/uof/uof2odf_spreadsheet.xsl9071
-rw-r--r--filter/source/xslt/import/uof/uof2odf_text.xsl4667
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo.xsl256
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_custom_draw.xsl275
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_draw.xsl2170
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_field.xsl1581
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_list.xsl648
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_page.xsl402
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_path.xsl1809
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_props.xsl268
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_settings.xsl60
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_table.xsl1277
-rw-r--r--filter/source/xslt/import/wordml/wordml2ooo_text.xsl1049
-rw-r--r--filter/source/xslt/odf2xhtml/export/common/body.xsl428
-rw-r--r--filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl832
-rw-r--r--filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl380
-rw-r--r--filter/source/xslt/odf2xhtml/export/common/table/table.xsl155
-rw-r--r--filter/source/xslt/odf2xhtml/export/common/table/table_cells.xsl270
-rw-r--r--filter/source/xslt/odf2xhtml/export/common/table/table_columns.xsl232
-rw-r--r--filter/source/xslt/odf2xhtml/export/common/table/table_rows.xsl203
-rw-r--r--filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl579
-rw-r--r--filter/source/xslt/odf2xhtml/export/xhtml/body.xsl3022
-rw-r--r--filter/source/xslt/odf2xhtml/export/xhtml/header.xsl480
-rw-r--r--filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl186
-rw-r--r--filter/source/xslt/odf2xhtml/export/xhtml/table.xsl213
-rw-r--r--filter/source/xsltdialog/typedetectionexport.cxx264
-rw-r--r--filter/source/xsltdialog/typedetectionexport.hxx41
-rw-r--r--filter/source/xsltdialog/typedetectionimport.cxx316
-rw-r--r--filter/source/xsltdialog/typedetectionimport.hxx92
-rw-r--r--filter/source/xsltdialog/xmlfiltercommon.hxx83
-rw-r--r--filter/source/xsltdialog/xmlfilterdialogcomponent.cxx285
-rw-r--r--filter/source/xsltdialog/xmlfilterjar.cxx361
-rw-r--r--filter/source/xsltdialog/xmlfilterjar.hxx52
-rw-r--r--filter/source/xsltdialog/xmlfiltersettingsdialog.cxx1384
-rw-r--r--filter/source/xsltdialog/xmlfiltersettingsdialog.hxx97
-rw-r--r--filter/source/xsltdialog/xmlfiltertabdialog.cxx263
-rw-r--r--filter/source/xsltdialog/xmlfiltertabdialog.hxx54
-rw-r--r--filter/source/xsltdialog/xmlfiltertabpagebasic.cxx128
-rw-r--r--filter/source/xsltdialog/xmlfiltertabpagebasic.hxx43
-rw-r--r--filter/source/xsltdialog/xmlfiltertabpagexslt.cxx165
-rw-r--r--filter/source/xsltdialog/xmlfiltertabpagexslt.hxx56
-rw-r--r--filter/source/xsltdialog/xmlfiltertestdialog.cxx697
-rw-r--r--filter/source/xsltdialog/xmlfiltertestdialog.hxx81
-rw-r--r--filter/source/xsltdialog/xsltdlg.component26
-rw-r--r--filter/source/xsltfilter/LibXSLTTransformer.cxx571
-rw-r--r--filter/source/xsltfilter/LibXSLTTransformer.hxx185
-rw-r--r--filter/source/xsltfilter/OleHandler.cxx214
-rw-r--r--filter/source/xsltfilter/OleHandler.hxx93
-rw-r--r--filter/source/xsltfilter/XSLTFilter.cxx659
-rw-r--r--filter/source/xsltfilter/xsltfilter.component30
-rw-r--r--filter/uiconfig/ui/pdfgeneralpage.ui1038
-rw-r--r--filter/uiconfig/ui/pdflinkspage.ui197
-rw-r--r--filter/uiconfig/ui/pdfoptionsdialog.ui399
-rw-r--r--filter/uiconfig/ui/pdfsecuritypage.ui595
-rw-r--r--filter/uiconfig/ui/pdfsignpage.ui307
-rw-r--r--filter/uiconfig/ui/pdfuserinterfacepage.ui381
-rw-r--r--filter/uiconfig/ui/pdfviewpage.ui491
-rw-r--r--filter/uiconfig/ui/testxmlfilter.ui411
-rw-r--r--filter/uiconfig/ui/warnpdfdialog.ui128
-rw-r--r--filter/uiconfig/ui/xmlfiltersettings.ui294
-rw-r--r--filter/uiconfig/ui/xmlfiltertabpagegeneral.ui217
-rw-r--r--filter/uiconfig/ui/xmlfiltertabpagetransformation.ui254
-rw-r--r--filter/uiconfig/ui/xsltfilterdialog.ui153
732 files changed, 181672 insertions, 0 deletions
diff --git a/filter/AllLangMoTarget_flt.mk b/filter/AllLangMoTarget_flt.mk
new file mode 100644
index 000000000..3c491bc95
--- /dev/null
+++ b/filter/AllLangMoTarget_flt.mk
@@ -0,0 +1,13 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+
+$(eval $(call gb_AllLangMoTarget_AllLangMoTarget,flt))
+
+$(eval $(call gb_AllLangMoTarget_set_polocation,flt,filter))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Configuration_filter.mk b/filter/Configuration_filter.mk
new file mode 100644
index 000000000..a58b8396c
--- /dev/null
+++ b/filter/Configuration_filter.mk
@@ -0,0 +1,934 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+# this deviates from Configuration.mk in rather bizarre ways
+
+# most of the rules here use some weird merge program, and this is sort of
+# semi-integrated with the stuff from Configuration.mk; not exactly pretty...
+
+filter_MERGE_TARGET := $(call gb_ExternalExecutable_get_dependencies,python) \
+ $(SRCDIR)/filter/source/config/tools/merge/pyAltFCFGMerge
+filter_MERGE := $(call gb_ExternalExecutable_get_command,python) \
+ $(SRCDIR)/filter/source/config/tools/merge/pyAltFCFGMerge \
+ $(if $(verbose),-verbose)
+
+### filter configuration rules: generic stuff #######################
+
+### types
+
+filter_XcuFilterTypesTarget_get_clean_target = \
+ $(WORKDIR)/Clean/XcuFilterTypesTarget/$(1)
+
+$(call gb_XcuFilterTypesTarget_get_target,%) : $(filter_MERGE_TARGET)
+ $(call gb_Output_announce,$*,$(true),FIT,1)
+ $(call gb_Trace_StartRange,$*,FIT)
+ $(call gb_Helper_abbreviate_dirs,\
+ mkdir -p $(dir $@) && \
+ RESPONSEFILE=`$(gb_MKTEMP)` && \
+ echo "items=$(basename $(notdir $(filter %.xcu,$^)))" \
+ | sed "s/ /$(COMMA)/g" > $${RESPONSEFILE} && \
+ $(filter_MERGE) tempdir=$(TMPDIR) \
+ share_subdir_name=$(LIBO_SHARE_FOLDER) \
+ fragmentsdir=$(dir $(firstword $(filter %.xcu,$^))).. \
+ outdir=$(dir $@) pkg=$@ xmlpackage=Types tcfg=$${RESPONSEFILE} && \
+ rm -f $${RESPONSEFILE})
+ $(call gb_Trace_EndRange,$*,FIT)
+
+$(call filter_XcuFilterTypesTarget_get_clean_target,%) :
+ $(call gb_Output_announce,$*,$(false),FIT,1)
+ rm -f $(call gb_XcuFilterTypesTarget_get_target,$*)
+
+# $(call filter_Configuration__add_module,configuration,module,prefix,xcufiles,target,cleantarget)
+define filter_Configuration__add_module
+$(call gb_Configuration_get_target,$(1)) : $(5)
+$(call gb_Configuration_get_clean_target,$(1)) : $(6)
+$(if $(4),,$(error filter_Configuration__add_module: no input files))
+$(5) : \
+ $(addprefix $(SRCDIR)/$(3)/,$(addsuffix .xcu,$(4))) \
+ $(gb_Module_CURRENTMAKEFILE)
+
+endef
+
+# $(call filter_Configuration_add_types,configuration,typesfile,prefix,xcufiles)
+define filter_Configuration_add_types
+$(call filter_Configuration__add_module,$(1),$(2),$(3),$(4),\
+ $(call gb_XcuFilterTypesTarget_get_target,$(2)),\
+ $(call filter_XcuFilterTypesTarget_get_clean_target,$(2)))
+
+endef
+
+### filters
+
+filter_XcuFilterFiltersTarget_get_clean_target = \
+ $(WORKDIR)/Clean/XcuFilterFiltersTarget/$(1)
+
+$(call gb_XcuFilterFiltersTarget_get_target,%) : $(filter_MERGE_TARGET)
+ $(call gb_Output_announce,$*,$(true),FIF,1)
+ $(call gb_Trace_StartRange,$*,FIF)
+ $(call gb_Helper_abbreviate_dirs,\
+ mkdir -p $(dir $@) && \
+ RESPONSEFILE=`$(gb_MKTEMP)` && \
+ echo "items=$(basename $(notdir $(filter %.xcu,$^)))" \
+ | sed "s/ /$(COMMA)/g" > $${RESPONSEFILE} && \
+ $(filter_MERGE) tempdir=$(TMPDIR) \
+ share_subdir_name=$(LIBO_SHARE_FOLDER) \
+ fragmentsdir=$(dir $(firstword $(filter %.xcu,$^))).. \
+ outdir=$(dir $@) pkg=$@ xmlpackage=Filter fcfg=$${RESPONSEFILE} && \
+ rm -f $${RESPONSEFILE})
+ $(call gb_Trace_EndRange,$*,FIF)
+
+$(call filter_XcuFilterFiltersTarget_get_clean_target,%) :
+ $(call gb_Output_announce,$*,$(false),FIF,1)
+ rm -f $(call gb_XcuFilterFiltersTarget_get_target,$*)
+
+# $(call filter_Configuration_add_filters,configuration,typesfile,prefix,xcufiles)
+define filter_Configuration_add_filters
+$(call filter_Configuration__add_module,$(1),$(2),$(3),$(4),\
+ $(call gb_XcuFilterFiltersTarget_get_target,$(2)),\
+ $(call filter_XcuFilterFiltersTarget_get_clean_target,$(2)))
+$(call filter_Configuration_add_ui_filters,$(1),$(3),$(4))
+
+endef
+
+### others (frameloaders, contenthandlers)
+
+filter_XcuFilterOthersTarget_get_clean_target = \
+ $(WORKDIR)/Clean/XcuFilterOthersTarget/$(1)
+
+$(call gb_XcuFilterOthersTarget_get_target,%) : $(filter_MERGE_TARGET)
+ $(call gb_Output_announce,$*,$(true),FIO,1)
+ $(call gb_Trace_StartRange,$*,FIO)
+ $(call gb_Helper_abbreviate_dirs,\
+ mkdir -p $(dir $@) && \
+ RESPONSEFILE=`$(gb_MKTEMP)` && \
+ RESPONSEFILE2=`$(gb_MKTEMP)` && \
+ echo "items=$(strip $(foreach xcu,$(filter %.xcu,$^),$(if $(filter frameloaders,$(notdir $(patsubst %/,%,$(dir $(xcu))))),$(basename $(notdir $(xcu),)))))" \
+ | sed "s/ /$(COMMA)/g" > $${RESPONSEFILE} && \
+ echo "items=$(strip $(foreach xcu,$(filter %.xcu,$^),$(if $(filter contenthandlers,$(notdir $(patsubst %/,%,$(dir $(xcu))))),$(basename $(notdir $(xcu),)))))" \
+ | sed "s/ /$(COMMA)/g" > $${RESPONSEFILE2} && \
+ $(filter_MERGE) tempdir=$(TMPDIR) \
+ share_subdir_name=$(LIBO_SHARE_FOLDER) \
+ fragmentsdir=$(dir $(firstword $(filter %.xcu,$^))).. \
+ outdir=$(dir $@) pkg=$@ xmlpackage=Misc \
+ lcfg=$${RESPONSEFILE} ccfg=$${RESPONSEFILE2} && \
+ rm -f $${RESPONSEFILE} $${RESPONSEFILE2})
+ $(call gb_Trace_EndRange,$*,FIO)
+
+$(call filter_XcuFilterOthersTarget_get_clean_target,%) :
+ $(call gb_Output_announce,$*,$(false),FIO,1)
+ rm -f $(call gb_XcuFilterOthersTarget_get_target,$*)
+
+# $(call filter_Configuration_add_others,configuration,typesfile,prefix,xcufiles)
+define filter_Configuration_add_others
+$(call filter_Configuration__add_module,$(1),$(2),$(3),$(4),\
+ $(call gb_XcuFilterOthersTarget_get_target,$(2)),\
+ $(call filter_XcuFilterOthersTarget_get_clean_target,$(2)))
+
+endef
+
+### internal filters
+
+filter_XcuFilterInternalTarget_get_clean_target = \
+ $(WORKDIR)/Clean/XcuFilterInternalTarget/$(1)
+
+$(call gb_XcuFilterInternalTarget_get_target,%) : $(filter_MERGE_TARGET)
+ $(call gb_Output_announce,$*,$(true),FII,1)
+ $(call gb_Trace_StartRange,$*,FII)
+ $(call gb_Helper_abbreviate_dirs,\
+ mkdir -p $(dir $@) && \
+ RESPONSEFILE=`$(gb_MKTEMP)` && \
+ echo "items=$(basename $(notdir $(filter %.xcu,$^)))" \
+ | sed "s/ /$(COMMA)/g" > $${RESPONSEFILE} && \
+ $(filter_MERGE) tempdir=$(TMPDIR) \
+ share_subdir_name=$(LIBO_SHARE_FOLDER) \
+ fragmentsdir=$(dir $(firstword $(filter %.xcu,$^))).. \
+ outdir=$(dir $@) pkg=$@ xmlpackage=GraphicFilter \
+ fcfg=$${RESPONSEFILE} subdir_filters=internalgraphicfilters && \
+ rm -f $${RESPONSEFILE})
+ $(call gb_Trace_EndRange,$*,FII)
+
+$(call filter_XcuFilterInternalTarget_get_clean_target,%) :
+ $(call gb_Output_announce,$*,$(false),FII,1)
+ rm -f $(call gb_XcuFilterInternalTarget_get_target,$*)
+
+# $(call filter_Configuration_add_internal_filters,configuration,typesfile,prefix,xcufiles)
+define filter_Configuration_add_internal_filters
+$(call filter_Configuration__add_module,$(1),$(2),$(3),$(4),\
+ $(call gb_XcuFilterInternalTarget_get_target,$(2)),\
+ $(call filter_XcuFilterInternalTarget_get_clean_target,$(2)))
+
+endef
+
+
+### filter configuration rules: l10n stuff: #########################
+
+# Configuration fcfg_langpack
+# => $(lang)/org/openoffice/TypeDetection/Filter.xcu
+# xslt=> filter_ui.xcu
+# merge=> *.xcu $(ALL_UI_FILTERS) [if WITH_LANG]
+# cfgex=> source/%.xcu
+# merge=> source/*.xcu [if !WITH_LANG]
+
+filter_XSLT_langfilter := \
+ $(SRCDIR)/filter/source/config/fragments/langfilter.xsl
+filter_XcuFilterUiTarget = $(WORKDIR)/XcuFilterUiTarget/filter_ui.xcu
+filter_XcuFilterUiCleanTarget = $(WORKDIR)/Clean/XcuFilterUiTarget/filter_ui.xcu
+filter_XCU_filter := org/openoffice/TypeDetection/Filter.xcu
+filter_XcuResTarget_get_target = \
+ $(call gb_XcuResTarget_get_target,fcfg_langpack/$(1)/$(filter_XCU_filter))
+filter_XcuResTarget_get_clean_target = \
+ $(call gb_XcuResTarget_get_clean_target,fcfg_langpack/$(1)/$(filter_XCU_filter))
+
+$(filter_XcuFilterUiTarget) : $(filter_MERGE_TARGET)
+ $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),$(true),FIU,1)
+ $(call gb_Trace_StartRange,$(subst $(WORKDIR)/,,$@),FIU)
+ $(call gb_Helper_abbreviate_dirs,\
+ mkdir -p $(dir $@) && \
+ RESPONSEFILE=`$(gb_MKTEMP)` && \
+ echo "items=$(basename $(notdir $(filter %.xcu,$^)))" \
+ | sed "s/ /$(COMMA)/g" > $${RESPONSEFILE} && \
+ $(filter_MERGE) tempdir=$(TMPDIR) \
+ share_subdir_name=$(LIBO_SHARE_FOLDER) \
+ fragmentsdir=$(dir $(firstword $(filter %.xcu,$^))).. \
+ pkg=$@ xmlpackage=Filter fcfg=$${RESPONSEFILE} languagepack=true \
+ && rm -f $${RESPONSEFILE})
+ $(call gb_Trace_EndRange,$(subst $(WORKDIR)/,,$@),FIU)
+
+$(filter_XcuFilterUiCleanTarget) :
+ $(call gb_Output_announce,$(filter_XcuFilterUiTarget),$(false),FIU,1)
+ $(call gb_Helper_abbreviate_dirs,\
+ rm -f $(filter_XcuFilterUiTarget))
+
+$(call gb_Configuration_get_clean_target,fcfg_langpack) : \
+ $(filter_XcuFilterUiCleanTarget)
+
+# this is _not_ a pattern rule:
+# there is already a pattern rule for gb_XcuResTarget_get_target,
+# so generate non-pattern rules which have higher priority even in GNUmake 3.81
+define filter_XcuResTarget__rule
+$$(call filter_XcuResTarget_get_target,$(1)) : \
+ $(filter_XSLT_langfilter) $(filter_XcuFilterUiTarget) \
+ | $(call gb_ExternalExecutable_get_dependencies,xsltproc)
+ $$(call gb_Output_announce,$(1),$(true),XCU,1)
+ $$(call gb_Trace_StartRange,$(1),XCU)
+ $$(call gb_Helper_abbreviate_dirs,\
+ mkdir -p $$(dir $$@) && \
+ $(subst $$,$$$$,$(call gb_ExternalExecutable_get_command,xsltproc)) --nonet --stringparam lang $(1) \
+ $(filter_XSLT_langfilter) \
+ $(filter_XcuFilterUiTarget) > $$@)
+ $$(call gb_Trace_EndRange,$(1),XCU)
+
+endef
+
+$(foreach lang,$(gb_Configuration_LANGS),$(eval \
+ $(call filter_XcuResTarget__rule,$(lang))))
+
+define filter_Configuration_Configuration
+$(call gb_Configuration_Configuration,$(1))
+
+$(call gb_Configuration_get_target,$(1)) : \
+ $(foreach lang,$(gb_Configuration_LANGS),$(call filter_XcuResTarget_get_target,$(lang)))
+$(call gb_Configuration_get_clean_target,$(1)) : \
+ $(foreach lang,$(gb_Configuration_LANGS),$(call filter_XcuResTarget_get_clean_target,$(lang)))
+
+endef
+
+
+# $(call filter_Configuration_add_ui_filter,configuration,prefix,xcufile)
+define filter_Configuration_add_ui_filter
+ifeq ($(WITH_LANG),)
+$(filter_XcuFilterUiTarget) : $(SRCDIR)/$(2)/$(3)
+else
+$(call gb_XcuMergeTarget_XcuMergeTarget,$(2)/$(3),$(1),$(2),$(3))
+$(filter_XcuFilterUiTarget) : \
+ $(call gb_XcuMergeTarget_get_target,$(2)/$(3))
+endif
+$(call gb_Configuration_get_clean_target,$(1)) : \
+ $(call gb_XcuMergeTarget_get_clean_target,$(2)/$(3))
+
+endef
+
+# $(call filter_Configuration_add_ui_filters,configuration,prefix,xcufile)
+define filter_Configuration_add_ui_filters
+$(foreach xcu,$(3),$(call filter_Configuration_add_ui_filter,$(1),$(2),$(xcu).xcu))
+
+endef
+
+
+### the filter configuration ########################################
+
+$(eval $(call filter_Configuration_Configuration,fcfg_langpack))
+
+# fcfg_base
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_base_types.xcu,filter/source/config/fragments/types,\
+ writer_web_HTML_help \
+ oxt_OpenOffice_Extension \
+ wav_Wave_Audio_File \
+ component_Bibliography \
+ component_DB \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_base_filters.xcu,filter/source/config/fragments/filters,\
+ writer_web_HTML_help \
+))
+
+$(eval $(call filter_Configuration_add_others,fcfg_langpack,fcfg_base_others.xcu,filter/source/config/fragments,\
+ frameloaders/com_sun_star_frame_Bibliography \
+ frameloaders/com_sun_star_sdb_ContentLoader \
+ contenthandlers/com_sun_star_comp_framework_SoundHandler \
+ contenthandlers/com_sun_star_comp_framework_oxt_handler \
+))
+
+# fcfg_database
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_database_types.xcu,filter/source/config/fragments/types,\
+ StarBase \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_database_filters.xcu,filter/source/config/fragments/filters,\
+ StarOffice_XML__Base_ \
+))
+
+$(eval $(call filter_Configuration_add_others,fcfg_langpack,fcfg_database_others.xcu,filter/source/config/fragments,\
+ frameloaders/org_openoffice_comp_dbflt_DBContentLoader2 \
+))
+
+# fcfg_reportbuilder
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_reportbuilder_types.xcu,filter/source/config/fragments/types,\
+ StarBaseReport \
+ StarBaseReportChart \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_reportbuilder_filters.xcu,filter/source/config/fragments/filters,\
+ StarBaseReport \
+ StarBaseReportChart \
+))
+
+# fcfg_writer
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_writer_types.xcu,filter/source/config/fragments/types,\
+ generic_HTML \
+ calc_MS_Excel_40 \
+ calc_MS_Excel_5095 \
+ calc_MS_Excel_95 \
+ writer_MS_WinWord_5 \
+ writer_MS_WinWord_60 \
+ writer_MS_Word_95 \
+ writer_MS_Word_95_Vorlage \
+ writer_MS_Word_97 \
+ writer_MS_Word_97_Vorlage \
+ writer_ODT_FlatXML \
+ writer_Rich_Text_Format \
+ writer_StarOffice_XML_Writer \
+ writer_WordPerfect_Document \
+ writer_MS_Works_Document \
+ writer_MS_Write \
+ writer_DosWord \
+ writer_ClarisWorks \
+ writer_Mac_Word \
+ writer_Mac_Works \
+ writer_MacWrite \
+ writer_Mariner_Write \
+ writer_WriteNow \
+ writer_AbiWord_Document \
+ writer_T602_Document \
+ writer_LotusWordPro_Document \
+ generic_Text \
+ writer_MIZI_Hwp_97 \
+ writer_StarOffice_XML_Writer_Template \
+ pdf_Portable_Document_Format \
+ writer8_template \
+ writer8 \
+ writer_MS_Word_2007_XML \
+ writer_MS_Word_2007_XML_Template \
+ writer_MS_Word_2007_XML_VBA \
+ writer_OOXML \
+ writer_OOXML_Template \
+ writer_layout_dump_xml \
+ writer_indexing_export_xml \
+ writer_BroadBand_eBook \
+ writer_FictionBook_2 \
+ writer_PalmDoc \
+ writer_Plucker_eBook \
+ writer_ApplePages \
+ MWAW_Text_Document \
+ Palm_Text_Document \
+ StarOffice_Writer \
+ writer_EPUB_Document \
+ writer_PocketWord_File \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_writer_filters.xcu,filter/source/config/fragments/filters,\
+ HTML__StarWriter_ \
+ MS_WinWord_5 \
+ MS_WinWord_6_0 \
+ MS_Word_95 \
+ MS_Word_95_Vorlage \
+ MS_Word_97 \
+ MS_Word_97_Vorlage \
+ ODT_FlatXML \
+ Rich_Text_Format \
+ StarOffice_XML__Writer_ \
+ WordPerfect \
+ MS_Works \
+ MS_Write \
+ DosWord \
+ ClarisWorks \
+ Mac_Word \
+ Mac_Works \
+ MacWrite \
+ Mariner_Write \
+ WriteNow \
+ AbiWord \
+ T602Document \
+ LotusWordPro \
+ Text \
+ Text__encoded_ \
+ writer_MIZI_Hwp_97 \
+ writer_StarOffice_XML_Writer_Template \
+ writer_pdf_Export\
+ writer8\
+ writer8_template \
+ MS_Word_2007_XML \
+ MS_Word_2007_XML_Template \
+ MS_Word_2007_XML_VBA \
+ OOXML_Text \
+ OOXML_Text_Template \
+ writer_layout_dump \
+ writer_indexing_export \
+ BroadBand_eBook \
+ FictionBook_2 \
+ PalmDoc \
+ Plucker_eBook \
+ ApplePages \
+ MWAW_Text_Document \
+ Palm_Text_Document \
+ StarOffice_Writer \
+ EPUB \
+ PocketWord_File \
+))
+
+# fcfg_web
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_web_types.xcu,filter/source/config/fragments/types,\
+ generic_HTML \
+ generic_Text \
+ writer_web_HTML_help \
+ writer_StarOffice_XML_Writer \
+ writer_web_StarOffice_XML_Writer_Web_Template \
+ pdf_Portable_Document_Format \
+ writerweb8_writer_template \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_web_filters.xcu,filter/source/config/fragments/filters,\
+ HTML \
+ Text__StarWriter_Web_ \
+ Text__encoded___StarWriter_Web_ \
+ writer_web_HTML_help \
+ writer_web_StarOffice_XML_Writer \
+ writer_web_StarOffice_XML_Writer_Web_Template \
+ writer_web_pdf_Export\
+ writer_web_png_Export\
+ writer_web_jpg_Export\
+ writer_web_webp_Export\
+ writerweb8_writer_template\
+ writerweb8_writer \
+))
+
+# fcfg_global
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_global_types.xcu,filter/source/config/fragments/types,\
+ generic_Text \
+ writer_StarOffice_XML_Writer \
+ writer_globaldocument_StarOffice_XML_Writer_GlobalDocument \
+ pdf_Portable_Document_Format \
+ writerglobal8 \
+ writerglobal8_template \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_global_filters.xcu,filter/source/config/fragments/filters,\
+ Text__encoded___StarWriter_GlobalDocument_ \
+ writer_globaldocument_StarOffice_XML_Writer \
+ writer_globaldocument_StarOffice_XML_Writer_GlobalDocument \
+ writer_globaldocument_pdf_Export \
+ writerglobal8 \
+ writerglobal8_template \
+ writerglobal8_writer \
+ writerglobal8_HTML \
+))
+
+# fcfg_calc
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_calc_types.xcu,filter/source/config/fragments/types,\
+ calc_DIF \
+ calc_ODS_FlatXML \
+ calc_HTML \
+ generic_HTML \
+ generic_Text \
+ calc_Gnumeric \
+ calc_Lotus \
+ calc_QPro \
+ calc_MS_Excel_40 \
+ calc_MS_Excel_40_VorlageTemplate \
+ calc_MS_Excel_5095 \
+ calc_MS_Excel_5095_VorlageTemplate \
+ calc_MS_Excel_95 \
+ calc_MS_Excel_95_VorlageTemplate \
+ calc_MS_Excel_97 \
+ calc_MS_Excel_97_VorlageTemplate \
+ writer_Rich_Text_Format \
+ calc_SYLK \
+ calc_StarOffice_XML_Calc \
+ calc_StarOffice_XML_Calc_Template \
+ pdf_Portable_Document_Format \
+ calc_dBase\
+ calc8 \
+ calc8_template \
+ MS_Excel_2007_XML \
+ MS_Excel_2007_VBA_XML \
+ MS_Excel_2007_XML_Template \
+ MS_Excel_2007_Binary \
+ calc_OOXML \
+ calc_OOXML_Template \
+ calc_MS_Works_Document \
+ calc_WPS_Lotus_Document \
+ calc_WPS_QPro_Document \
+ calc_ClarisWorks \
+ calc_Claris_Resolve \
+ calc_Mac_Works \
+ calc_AppleNumbers \
+ MWAW_Database \
+ MWAW_Spreadsheet \
+ StarOffice_Spreadsheet \
+ calc_MS_Multiplan \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_calc_filters.xcu,filter/source/config/fragments/filters,\
+ DIF \
+ HTML__StarCalc_ \
+ ODS_FlatXML \
+ Lotus \
+ QPro \
+ MS_Excel_4_0 \
+ MS_Excel_4_0_Vorlage_Template \
+ MS_Excel_5_0_95 \
+ MS_Excel_5_0_95_Vorlage_Template \
+ MS_Excel_95 \
+ MS_Excel_95_Vorlage_Template \
+ MS_Excel_97 \
+ MS_Excel_97_Vorlage_Template \
+ MS_Excel_2003_XML_Orcus \
+ Rich_Text_Format__StarCalc_ \
+ SYLK \
+ StarOffice_XML__Calc_ \
+ Text___txt___csv__StarCalc_ \
+ calc_HTML_WebQuery \
+ calc_StarOffice_XML_Calc_Template \
+ calc_pdf_Export \
+ dBase \
+ calc8 \
+ calc8_template \
+ calc_Gnumeric \
+ calc_MS_Excel_2007_XML \
+ calc_MS_Excel_2007_VBA_XML \
+ calc_MS_Excel_2007_XML_Template \
+ calc_MS_Excel_2007_Binary \
+ calc_OOXML \
+ calc_OOXML_Template \
+ MS_Works_Calc \
+ WPS_Lotus_Calc \
+ WPS_QPro_Calc \
+ ClarisWorks_Calc \
+ Claris_Resolve_Calc \
+ Mac_Works_Calc \
+ AppleNumbers \
+ MWAW_Database \
+ MWAW_Spreadsheet \
+ StarOffice_Spreadsheet \
+ MS_Multiplan \
+))
+
+# fcfg_draw
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_draw_types.xcu,filter/source/config/fragments/types,\
+ draw_ODG_FlatXML \
+ draw_StarOffice_XML_Draw \
+ draw_StarOffice_XML_Draw_Template \
+ pdf_Portable_Document_Format \
+ draw8 \
+ draw8_template \
+ draw_WordPerfect_Graphics \
+ draw_Visio_Document \
+ draw_Publisher_Document \
+ draw_CorelDraw_Document \
+ draw_Corel_Presentation_Exchange \
+ draw_Freehand_Document \
+ draw_Visio_Document \
+ draw_ClarisWorks \
+ draw_PageMaker_Document \
+ draw_QXP_Document \
+ draw_ZMF_Document \
+ MWAW_Bitmap \
+ MWAW_Drawing \
+ StarOffice_Drawing \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_draw_filters.xcu,filter/source/config/fragments/filters,\
+ ODG_FlatXML \
+ StarOffice_XML__Draw_ \
+ draw_StarOffice_XML_Draw_Template \
+ draw_pdf_Export \
+ draw8 \
+ draw8_template \
+ WordPerfectGraphics \
+ VisioDocument \
+ PublisherDocument \
+ CorelDrawDocument \
+ CorelPresentationExchange \
+ FreehandDocument \
+ ClarisWorks_Draw \
+ PageMakerDocument \
+ QXPDocument \
+ ZMFDocument \
+ MWAW_Bitmap \
+ MWAW_Drawing \
+ StarOffice_Drawing \
+))
+
+# fcfg_impress
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_impress_types.xcu,filter/source/config/fragments/types,\
+ draw_StarOffice_XML_Draw \
+ impress_AppleKeynote \
+ impress_MS_PowerPoint_97 \
+ impress_MS_PowerPoint_97_AutoPlay \
+ impress_MS_PowerPoint_97_Vorlage \
+ impress_ODP_FlatXML \
+ impress_StarOffice_XML_Impress \
+ impress_StarOffice_XML_Impress_Template \
+ pdf_Portable_Document_Format \
+ impress8 \
+ impress8_template \
+ draw8 \
+ MS_PowerPoint_2007_XML \
+ MS_PowerPoint_2007_XML_AutoPlay \
+ MS_PowerPoint_2007_XML_Template \
+ MS_PowerPoint_2007_XML_VBA \
+ impress_OOXML_Presentation \
+ impress_OOXML_Presentation_Template \
+ impress_OOXML_Presentation_AutoPlay \
+ impress_ClarisWorks \
+ StarOffice_Presentation \
+ MWAW_Presentation \
+ impress_PowerPoint3 \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_impress_filters.xcu,filter/source/config/fragments/filters,\
+ AppleKeynote \
+ MS_PowerPoint_97 \
+ MS_PowerPoint_97_AutoPlay \
+ MS_PowerPoint_97_Vorlage \
+ impress_StarOffice_XML_Draw \
+ ODP_FlatXML \
+ StarOffice_XML__Impress_ \
+ impress_StarOffice_XML_Impress_Template \
+ impress_pdf_Export \
+ impress8 \
+ impress8_template \
+ impress8_draw \
+ impress_MS_PowerPoint_2007_XML \
+ impress_MS_PowerPoint_2007_XML_AutoPlay \
+ impress_MS_PowerPoint_2007_XML_Template \
+ impress_MS_PowerPoint_2007_XML_VBA \
+ impress_OOXML \
+ impress_OOXML_Template \
+ impress_OOXML_AutoPlay \
+ ClarisWorks_Impress \
+ StarOffice_Presentation \
+ MWAW_Presentation \
+ PowerPoint3 \
+))
+
+# fcfg_chart
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_chart_types.xcu,filter/source/config/fragments/types,\
+ chart_StarOffice_XML_Chart \
+ chart8 \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_chart_filters.xcu,filter/source/config/fragments/filters,\
+ StarOffice_XML__Chart_ \
+ chart8 \
+))
+
+$(eval $(call filter_Configuration_add_others,fcfg_langpack,fcfg_chart_others.xcu,filter/source/config/fragments,\
+ frameloaders/com_sun_star_comp_chart2_ChartFrameLoader \
+))
+
+# fcfg_math
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_math_types.xcu,filter/source/config/fragments/types,\
+ math_MathML_XML_Math \
+ math_MathType_3x \
+ math_StarOffice_XML_Math \
+ pdf_Portable_Document_Format \
+ math8 \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_math_filters.xcu,filter/source/config/fragments/filters,\
+ MathML_XML__Math_ \
+ MathType_3_x \
+ StarOffice_XML__Math_ \
+ math_pdf_Export \
+ math8 \
+))
+
+# fcfg_drawgraphics
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_drawgraphics_types.xcu,filter/source/config/fragments/types,\
+ bmp_MS_Windows \
+ dxf_AutoCAD_Interchange \
+ emf_MS_Windows_Metafile \
+ eps_Encapsulated_PostScript \
+ gif_Graphics_Interchange \
+ graphic_HTML \
+ jpg_JPEG \
+ met_OS2_Metafile \
+ mov_MOV \
+ pbm_Portable_Bitmap \
+ pcd_Photo_CD_Base \
+ pcd_Photo_CD_Base16 \
+ pcd_Photo_CD_Base4 \
+ pct_Mac_Pict \
+ pcx_Zsoft_Paintbrush \
+ pgm_Portable_Graymap \
+ png_Portable_Network_Graphic \
+ ppm_Portable_Pixelmap \
+ psd_Adobe_Photoshop \
+ ras_Sun_Rasterfile \
+ svg_Scalable_Vector_Graphics_Draw \
+ svg_Scalable_Vector_Graphics \
+ svm_StarView_Metafile \
+ tga_Truevision_TARGA \
+ tif_Tag_Image_File \
+ webp_WebP \
+ wmf_MS_Windows_Metafile \
+ xbm_X_Consortium \
+ xpm_XPM \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_drawgraphics_filters.xcu,filter/source/config/fragments/filters,\
+ BMP___MS_Windows \
+ DXF___AutoCAD_Interchange \
+ EMF___MS_Windows_Metafile \
+ EPS___Encapsulated_PostScript \
+ GIF___Graphics_Interchange \
+ JPG___JPEG \
+ MET___OS_2_Metafile \
+ mov__MOV \
+ PBM___Portable_Bitmap \
+ PCT___Mac_Pict \
+ PCX___Zsoft_Paintbrush \
+ PGM___Portable_Graymap \
+ PNG___Portable_Network_Graphic \
+ PPM___Portable_Pixelmap \
+ PSD___Adobe_Photoshop \
+ RAS___Sun_Rasterfile \
+ SVG___Scalable_Vector_Graphics_Draw \
+ SVG___Scalable_Vector_Graphics \
+ SVM___StarView_Metafile \
+ TGA___Truevision_TARGA \
+ TIF___Tag_Image_File \
+ WEBP___WebP \
+ WMF___MS_Windows_Metafile \
+ XBM___X_Consortium \
+ XPM \
+ draw_PCD_Photo_CD_Base \
+ draw_PCD_Photo_CD_Base16 \
+ draw_PCD_Photo_CD_Base4 \
+ draw_bmp_Export \
+ draw_emf_Export \
+ draw_eps_Export \
+ draw_gif_Export \
+ draw_html_Export \
+ draw_jpg_Export \
+ draw_png_Export \
+ draw_svg_Export \
+ draw_tif_Export \
+ draw_webp_Export \
+ draw_wmf_Export \
+))
+
+# fcfg_impressgraphics
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_impressgraphics_types.xcu,filter/source/config/fragments/types,\
+ bmp_MS_Windows \
+ emf_MS_Windows_Metafile \
+ eps_Encapsulated_PostScript \
+ gif_Graphics_Interchange \
+ graphic_HTML \
+ impress_CGM_Computer_Graphics_Metafile \
+ jpg_JPEG \
+ met_OS2_Metafile \
+ pbm_Portable_Bitmap \
+ pct_Mac_Pict \
+ pgm_Portable_Graymap \
+ png_Portable_Network_Graphic \
+ ppm_Portable_Pixelmap \
+ ras_Sun_Rasterfile \
+ svg_Scalable_Vector_Graphics_Draw \
+ svg_Scalable_Vector_Graphics \
+ svm_StarView_Metafile \
+ tif_Tag_Image_File \
+ wmf_MS_Windows_Metafile \
+ webp_WebP \
+ xpm_XPM \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_impressgraphics_filters.xcu,filter/source/config/fragments/filters,\
+ CGM___Computer_Graphics_Metafile \
+ impress_bmp_Export \
+ impress_emf_Export \
+ impress_eps_Export \
+ impress_gif_Export \
+ impress_html_Export \
+ impress_jpg_Export \
+ impress_png_Export \
+ impress_svg_Export \
+ impress_tif_Export \
+ impress_webp_Export \
+ impress_wmf_Export \
+))
+
+# fcfg_writergraphics
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_writergraphics_types.xcu,filter/source/config/fragments/types,\
+ jpg_JPEG \
+ png_Portable_Network_Graphic \
+ svg_Scalable_Vector_Graphics \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_writergraphics_filters.xcu,filter/source/config/fragments/filters,\
+ writer_jpg_Export \
+ writer_png_Export \
+ writer_svg_Export \
+ writer_webp_Export \
+))
+
+# fcfg_calcgraphics
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_calcgraphics_types.xcu,filter/source/config/fragments/types,\
+ png_Portable_Network_Graphic \
+ svg_Scalable_Vector_Graphics \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_calcgraphics_filters.xcu,filter/source/config/fragments/filters,\
+ calc_jpg_Export \
+ calc_png_Export \
+ calc_svg_Export \
+ calc_webp_Export \
+))
+
+# fcfg_internalgraphics
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_internalgraphics_types.xcu,filter/source/config/fragments/types,\
+ bmp_MS_Windows \
+ dxf_AutoCAD_Interchange \
+ emf_MS_Windows_Metafile \
+ eps_Encapsulated_PostScript \
+ gif_Graphics_Interchange \
+ jpg_JPEG \
+ met_OS2_Metafile \
+ mov_MOV \
+ pbm_Portable_Bitmap \
+ pcd_Photo_CD_Base \
+ pcd_Photo_CD_Base16 \
+ pcd_Photo_CD_Base4 \
+ pct_Mac_Pict \
+ pcx_Zsoft_Paintbrush \
+ pgm_Portable_Graymap \
+ png_Portable_Network_Graphic \
+ ppm_Portable_Pixelmap \
+ psd_Adobe_Photoshop \
+ ras_Sun_Rasterfile \
+ svg_Scalable_Vector_Graphics \
+ svm_StarView_Metafile \
+ tga_Truevision_TARGA \
+ tif_Tag_Image_File \
+ webp_WebP \
+ wmf_MS_Windows_Metafile \
+ xbm_X_Consortium \
+ xpm_XPM \
+))
+
+$(eval $(call filter_Configuration_add_internal_filters,fcfg_langpack,fcfg_internalgraphics_filters.xcu,filter/source/config/fragments/internalgraphicfilters,\
+ bmp_Export \
+ bmp_Import \
+ dxf_Import \
+ emf_Export \
+ emf_Import \
+ eps_Export \
+ eps_Import \
+ gif_Export \
+ gif_Import \
+ jpg_Export \
+ jpg_Import \
+ met_Import \
+ pbm_Import \
+ pcd_Import_Base \
+ pcd_Import_Base4 \
+ pcd_Import_Base16 \
+ pct_Import \
+ pcx_Import \
+ pdf_Export \
+ pdf_Import \
+ pgm_Import \
+ png_Export \
+ png_Import \
+ ppm_Import \
+ psd_Import \
+ ras_Import \
+ svg_Export \
+ svg_Import \
+ svm_Export \
+ svm_Import \
+ tga_Import \
+ tif_Export \
+ tif_Import \
+ webp_Export \
+ webp_Import \
+ wmf_Export \
+ wmf_Import \
+ xbm_Import \
+ xpm_Import \
+ mov_Import \
+))
+
+# fcfg_xslt
+$(eval $(call filter_Configuration_add_types,fcfg_langpack,fcfg_xslt_types.xcu,filter/source/config/fragments/types,\
+ calc_ADO_rowset_XML \
+ calc_MS_Excel_2003_XML \
+ writer_DocBook_File \
+ writer_MS_Word_2003_XML \
+ XHTML_File \
+ Unified_Office_Format_text \
+ Unified_Office_Format_spreadsheet \
+ Unified_Office_Format_presentation \
+))
+
+$(eval $(call filter_Configuration_add_filters,fcfg_langpack,fcfg_xslt_filters.xcu,filter/source/config/fragments/filters,\
+ ADO_rowset_XML \
+ DocBook_File \
+ MS_Excel_2003_XML \
+ MS_Word_2003_XML \
+ XHTML_Calc_File \
+ XHTML_Draw_File \
+ XHTML_Impress_File \
+ XHTML_Writer_File \
+ UOF_text \
+ UOF_spreadsheet \
+ UOF_presentation \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/CppunitTest_filter_dialogs_test.mk b/filter/CppunitTest_filter_dialogs_test.mk
new file mode 100644
index 000000000..7ae73639c
--- /dev/null
+++ b/filter/CppunitTest_filter_dialogs_test.mk
@@ -0,0 +1,68 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# 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/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitScreenShot,filter_dialogs_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_dialogs_test, \
+ filter/qa/unit/filter-dialogs-test \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_dialogs_test))
+
+$(eval $(call gb_CppunitTest_set_include,filter_dialogs_test,\
+ -I$(SRCDIR)/filter/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_dialogs_test, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ drawinglayer \
+ editeng \
+ i18nlangtag \
+ i18nutil \
+ msfilter \
+ oox \
+ sal \
+ salhelper \
+ sax \
+ sfx \
+ sot \
+ svl \
+ svt \
+ test \
+ tl \
+ tk \
+ ucbhelper \
+ unotest \
+ utl \
+ vcl \
+ xo \
+))
+
+$(eval $(call gb_CppunitTest_use_external,filter_dialogs_test,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_ure,filter_dialogs_test))
+$(eval $(call gb_CppunitTest_use_vcl_non_headless_with_windows,filter_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_rdb,filter_dialogs_test,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_dialogs_test))
+
+$(eval $(call gb_CppunitTest_use_uiconfigs,filter_dialogs_test,\
+ filter \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/CppunitTest_filter_msfilter.mk b/filter/CppunitTest_filter_msfilter.mk
new file mode 100644
index 000000000..cf4347342
--- /dev/null
+++ b/filter/CppunitTest_filter_msfilter.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,filter_msfilter))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_msfilter))
+$(eval $(call gb_CppunitTest_use_ure,filter_msfilter))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_msfilter))
+
+$(eval $(call gb_CppunitTest_use_externals,filter_msfilter, \
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_msfilter, \
+ tl \
+ comphelper \
+ unotest \
+ cppuhelper \
+ cppu \
+ msfilter \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_components,filter_msfilter,\
+ configmgr/source/configmgr \
+ filter/source/config/cache/filterconfig1 \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_msfilter, \
+ filter/qa/cppunit/msfilter-test \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/CppunitTest_filter_pdf.mk b/filter/CppunitTest_filter_pdf.mk
new file mode 100644
index 000000000..e5c16ec60
--- /dev/null
+++ b/filter/CppunitTest_filter_pdf.mk
@@ -0,0 +1,48 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# 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/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,filter_pdf))
+
+$(eval $(call gb_CppunitTest_use_externals,filter_pdf,\
+ boost_headers \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_pdf, \
+ filter/qa/pdf \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_pdf, \
+ basegfx \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ test \
+ tl \
+ unotest \
+ utl \
+ vcl \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_pdf))
+
+$(eval $(call gb_CppunitTest_use_ure,filter_pdf))
+$(eval $(call gb_CppunitTest_use_vcl,filter_pdf))
+
+$(eval $(call gb_CppunitTest_use_rdb,filter_pdf,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,filter_pdf,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_pdf))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/CppunitTest_filter_priority.mk b/filter/CppunitTest_filter_priority.mk
new file mode 100644
index 000000000..d942f5d01
--- /dev/null
+++ b/filter/CppunitTest_filter_priority.mk
@@ -0,0 +1,41 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,filter_priority))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_priority))
+$(eval $(call gb_CppunitTest_use_ure,filter_priority))
+$(eval $(call gb_CppunitTest_use_vcl,filter_priority))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_priority))
+
+$(eval $(call gb_CppunitTest_use_external,filter_priority,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_priority, \
+ comphelper \
+ unotest \
+ cppuhelper \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_components,filter_priority,\
+ configmgr/source/configmgr \
+ filter/source/config/cache/filterconfig1 \
+ framework/util/fwk \
+ i18npool/util/i18npool \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_priority, \
+ filter/qa/cppunit/priority-test \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/CppunitTest_filter_svg.mk b/filter/CppunitTest_filter_svg.mk
new file mode 100644
index 000000000..ec0841929
--- /dev/null
+++ b/filter/CppunitTest_filter_svg.mk
@@ -0,0 +1,47 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# 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/.
+#
+#*************************************************************************
+
+$(eval $(call gb_CppunitTest_CppunitTest,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_externals,filter_svg,\
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_svg, \
+ filter/qa/unit/svg \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_svg, \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ test \
+ unotest \
+ utl \
+ tl \
+))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_ure,filter_svg))
+$(eval $(call gb_CppunitTest_use_vcl,filter_svg))
+
+$(eval $(call gb_CppunitTest_use_rdb,filter_svg,services))
+
+$(eval $(call gb_CppunitTest_use_custom_headers,filter_svg,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_svg))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/CppunitTest_filter_textfilterdetect.mk b/filter/CppunitTest_filter_textfilterdetect.mk
new file mode 100644
index 000000000..6fb22f8b0
--- /dev/null
+++ b/filter/CppunitTest_filter_textfilterdetect.mk
@@ -0,0 +1,44 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,filter_textfilterdetect))
+
+$(eval $(call gb_CppunitTest_use_api,filter_textfilterdetect,\
+ offapi \
+ udkapi \
+))
+
+$(eval $(call gb_CppunitTest_use_external,filter_textfilterdetect,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_textfilterdetect, \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ sfx \
+ test \
+ textfd \
+ tl \
+ unotest \
+ utl \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_textfilterdetect, \
+ filter/qa/unit/textfilterdetect \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,filter_textfilterdetect))
+
+$(eval $(call gb_CppunitTest_use_vcl,filter_textfilterdetect))
+
+$(eval $(call gb_CppunitTest_use_rdb,filter_textfilterdetect,services))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_textfilterdetect))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/CppunitTest_filter_xslt.mk b/filter/CppunitTest_filter_xslt.mk
new file mode 100644
index 000000000..8bf69a0ae
--- /dev/null
+++ b/filter/CppunitTest_filter_xslt.mk
@@ -0,0 +1,41 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,filter_xslt))
+
+$(eval $(call gb_CppunitTest_use_sdk_api,filter_xslt))
+$(eval $(call gb_CppunitTest_use_ure,filter_xslt))
+$(eval $(call gb_CppunitTest_use_vcl,filter_xslt))
+
+$(eval $(call gb_CppunitTest_use_configuration,filter_xslt))
+
+$(eval $(call gb_CppunitTest_use_external,filter_xslt,boost_headers))
+
+$(eval $(call gb_CppunitTest_use_libraries,filter_xslt, \
+ comphelper \
+ test \
+ unotest \
+ cppuhelper \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_CppunitTest_use_components,filter_xslt,\
+ configmgr/source/configmgr \
+ filter/source/xsltfilter/xsltfilter \
+ i18npool/util/i18npool \
+ ucb/source/core/ucb1 \
+ ucb/source/ucp/file/ucpfile1 \
+))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,filter_xslt, \
+ filter/qa/cppunit/xslt-test \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/CustomTarget_svg.mk b/filter/CustomTarget_svg.mk
new file mode 100644
index 000000000..065e26e1b
--- /dev/null
+++ b/filter/CustomTarget_svg.mk
@@ -0,0 +1,63 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+#
+# 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/.
+#
+
+$(eval $(call gb_CustomTarget_CustomTarget,filter/source/svg))
+
+filter_SVGSRC := $(SRCDIR)/filter/source/svg
+filter_SVGWORK := $(call gb_CustomTarget_get_workdir,filter/source/svg)
+
+filter_SRC_svg_Tokens := $(filter_SVGSRC)/tokens.txt
+filter_SRC_svg_GenToken := $(filter_SVGSRC)/gentoken.py
+filter_SRC_svg_PresentationEngine := $(filter_SVGSRC)/presentation_engine.js
+filter_SRC_svg_Js2Hxx := $(filter_SVGSRC)/js2hxx.py
+
+filter_GEN_svg_Tokens_gperf := $(filter_SVGWORK)/tokens.gperf
+filter_GEN_svg_Tokens_hxx := $(filter_SVGWORK)/tokens.hxx
+filter_GEN_svg_Tokens_cxx := $(filter_SVGWORK)/tokens.cxx
+filter_GEN_svg_Script_hxx := $(filter_SVGWORK)/svgscript.hxx
+
+$(filter_GEN_svg_Tokens_gperf) : \
+ $(call gb_ExternalExecutable_get_dependencies,python) \
+ $(filter_SRC_svg_GenToken) $(filter_SRC_svg_Tokens) \
+ | $(filter_SVGWORK)/.dir
+ $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),build,GPF,3)
+ $(call gb_Helper_abbreviate_dirs, \
+ $(call gb_ExternalExecutable_get_command,python) \
+ $(filter_SRC_svg_GenToken) \
+ $(filter_SRC_svg_Tokens) $(filter_GEN_svg_Tokens_hxx) \
+ $(filter_GEN_svg_Tokens_gperf))
+
+# dummy rule: both files generated by recipe above
+$(filter_GEN_svg_Tokens_hxx) : $(filter_GEN_svg_Tokens_gperf)
+
+$(filter_GEN_svg_Tokens_cxx) : $(filter_GEN_svg_Tokens_gperf)
+ $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),build,GPF,1)
+ $(call gb_Helper_abbreviate_dirs, \
+ $(GPERF) --compare-strncmp -C -m 20 --switch=2 --readonly-tables $(filter_GEN_svg_Tokens_gperf) \
+ | sed -e "s/(char\*)0/(char\*)0$(COMMA) 0/g" \
+ > $(filter_GEN_svg_Tokens_cxx))
+
+$(filter_GEN_svg_Script_hxx) : \
+ $(call gb_ExternalExecutable_get_dependencies,python) \
+ $(filter_SRC_svg_PresentationEngine) $(filter_SRC_svg_Js2Hxx) \
+ | $(filter_SVGWORK)/.dir
+ $(call gb_Output_announce,$(subst $(WORKDIR)/,,$@),build,PY ,1)
+ $(call gb_Helper_abbreviate_dirs, \
+ $(call gb_ExternalExecutable_get_command,python) $(filter_SRC_svg_Js2Hxx) \
+ $(filter_SRC_svg_PresentationEngine) \
+ $(filter_GEN_svg_Script_hxx))
+
+$(call gb_CustomTarget_get_target,filter/source/svg) : \
+ $(filter_GEN_svg_Tokens_gperf) \
+ $(filter_GEN_svg_Tokens_hxx) \
+ $(filter_GEN_svg_Tokens_cxx) \
+ $(filter_GEN_svg_Script_hxx) \
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/IwyuFilter_filter.yaml b/filter/IwyuFilter_filter.yaml
new file mode 100644
index 000000000..14ae4e91a
--- /dev/null
+++ b/filter/IwyuFilter_filter.yaml
@@ -0,0 +1,56 @@
+---
+assumeFilename: filter/source/msfilter/msdffimp.cxx
+excludelist:
+ filter/source/graphicfilter/icgm/cgm.cxx:
+ # OSL_BIGENDIAN is being checked
+ - osl/endian.h
+ filter/source/graphicfilter/ieps/ieps.cxx:
+ # Needed on WIN32
+ - o3tl/char16_t2wchar_t.hxx
+ filter/source/msfilter/mscodec.cxx:
+ # Actually used
+ - com/sun/star/beans/NamedValue.hpp
+ filter/source/msfilter/msdffimp.cxx:
+ # Needed for rtl::math::round
+ - rtl/math.hxx
+ filter/source/msfilter/mstoolbar.cxx:
+ # Needed for template
+ - com/sun/star/frame/XModel.hpp
+ filter/source/msfilter/svdfppt.cxx:
+ # OSL_BIGENDIAN is being checked
+ - osl/endian.h
+ filter/source/pdf/impdialog.cxx:
+ # Actually used
+ - com/sun/star/beans/XMaterialHolder.hpp
+ filter/source/pdf/pdfexport.cxx:
+ # Needed for direct member access
+ - com/sun/star/security/XCertificate.hpp
+ filter/source/pdf/pdfinteract.cxx:
+ # Actually used
+ - com/sun/star/task/XInteractionRequest.hpp
+ filter/source/svg/svgfilter.cxx:
+ # Actually used
+ - com/sun/star/io/IOException.hpp
+ filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx:
+ # Actually used
+ - comphelper/scopeguard.hxx
+ filter/source/xmlfilterdetect/filterdetect.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ filter/source/xsltdialog/typedetectionimport.cxx:
+ # Actually used
+ - com/sun/star/xml/sax/XAttributeList.hpp
+ filter/source/xsltdialog/xmlfilterjar.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ filter/source/xsltdialog/xmlfiltertabdialog.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ filter/source/xsltdialog/xmlfiltersettingsdialog.cxx:
+ # Actually used
+ - com/sun/star/uno/XComponentContext.hpp
+ filter/source/xsltfilter/LibXSLTTransformer.cxx:
+ # Actually used
+ - com/sun/star/io/XInputStream.hpp
+ - com/sun/star/io/XOutputStream.hpp
+ - com/sun/star/io/XStreamListener.hpp
diff --git a/filter/JunitTest_filter_complex.mk b/filter/JunitTest_filter_complex.mk
new file mode 100644
index 000000000..c8f22e1bc
--- /dev/null
+++ b/filter/JunitTest_filter_complex.mk
@@ -0,0 +1,33 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_JunitTest_JunitTest,filter_complex))
+
+$(eval $(call gb_JunitTest_use_unoapi_jars,filter_complex))
+
+$(eval $(call gb_JunitTest_add_sourcefiles,filter_complex,\
+ filter/qa/complex/filter/misc/FinalizedMandatoryTest \
+ filter/qa/complex/filter/misc/TypeDetection6FileFormat \
+))
+
+$(eval $(call gb_JunitTest_add_classes,filter_complex,\
+ complex.filter.misc.FinalizedMandatoryTest \
+ complex.filter.misc.TypeDetection6FileFormat \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_filterconfig.mk b/filter/Library_filterconfig.mk
new file mode 100644
index 000000000..38251aa31
--- /dev/null
+++ b/filter/Library_filterconfig.mk
@@ -0,0 +1,61 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,filterconfig))
+
+$(eval $(call gb_Library_set_componentfile,filterconfig,filter/source/config/cache/filterconfig1,services))
+
+$(eval $(call gb_Library_use_external,filterconfig,boost_headers))
+
+$(eval $(call gb_Library_use_custom_headers,filterconfig,officecfg/registry))
+
+$(eval $(call gb_Library_use_sdk_api,filterconfig))
+
+$(eval $(call gb_Library_set_include,filterconfig,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/filter/inc \
+))
+
+$(eval $(call gb_Library_use_libraries,filterconfig,\
+ fwk \
+ utl \
+ tl \
+ comphelper \
+ cppuhelper \
+ cppu \
+ sal \
+ salhelper \
+ i18nlangtag \
+))
+
+
+$(eval $(call gb_Library_add_exception_objects,filterconfig,\
+ filter/source/config/cache/basecontainer \
+ filter/source/config/cache/cacheitem \
+ filter/source/config/cache/cacheupdatelistener \
+ filter/source/config/cache/configflush \
+ filter/source/config/cache/contenthandlerfactory \
+ filter/source/config/cache/filtercache \
+ filter/source/config/cache/filterfactory \
+ filter/source/config/cache/frameloaderfactory \
+ filter/source/config/cache/querytokenizer \
+ filter/source/config/cache/typedetection \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_graphicfilter.mk b/filter/Library_graphicfilter.mk
new file mode 100644
index 000000000..34f9662d0
--- /dev/null
+++ b/filter/Library_graphicfilter.mk
@@ -0,0 +1,53 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,graphicfilter))
+
+$(eval $(call gb_Library_set_componentfile,graphicfilter,filter/source/graphic/graphicfilter,services))
+
+$(eval $(call gb_Library_use_external,graphicfilter,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,graphicfilter))
+
+$(eval $(call gb_Library_set_include,graphicfilter,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/filter/inc \
+))
+
+$(eval $(call gb_Library_use_libraries,graphicfilter,\
+ svt \
+ sfx \
+ tk \
+ vcl \
+ utl \
+ tl \
+ svl \
+ i18nlangtag \
+ comphelper \
+ basegfx \
+ cppuhelper \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,graphicfilter,\
+ filter/source/graphic/GraphicExportFilter \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_icg.mk b/filter/Library_icg.mk
new file mode 100644
index 000000000..44cb742a6
--- /dev/null
+++ b/filter/Library_icg.mk
@@ -0,0 +1,56 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,icg))
+
+$(eval $(call gb_Library_set_plugin_for_nodep,icg,sd))
+
+$(eval $(call gb_Library_use_external,icg,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,icg))
+
+$(eval $(call gb_Library_use_libraries,icg,\
+ comphelper \
+ cppuhelper \
+ tk \
+ vcl \
+ utl \
+ tl \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,icg,\
+ filter/source/graphicfilter/icgm/actimpr \
+ filter/source/graphicfilter/icgm/bitmap \
+ filter/source/graphicfilter/icgm/bundles \
+ filter/source/graphicfilter/icgm/cgm \
+ filter/source/graphicfilter/icgm/chart \
+ filter/source/graphicfilter/icgm/class0 \
+ filter/source/graphicfilter/icgm/class1 \
+ filter/source/graphicfilter/icgm/class2 \
+ filter/source/graphicfilter/icgm/class3 \
+ filter/source/graphicfilter/icgm/class4 \
+ filter/source/graphicfilter/icgm/class5 \
+ filter/source/graphicfilter/icgm/class7 \
+ filter/source/graphicfilter/icgm/classx \
+ filter/source/graphicfilter/icgm/elements \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_msfilter.mk b/filter/Library_msfilter.mk
new file mode 100644
index 000000000..0429a6e31
--- /dev/null
+++ b/filter/Library_msfilter.mk
@@ -0,0 +1,72 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,msfilter))
+
+$(eval $(call gb_Library_set_componentfile,msfilter,filter/source/msfilter/msfilter,services))
+
+$(eval $(call gb_Library_use_external,msfilter,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,msfilter))
+
+$(eval $(call gb_Library_add_defs,msfilter,\
+ -DMSFILTER_DLLIMPLEMENTATION \
+))
+
+$(eval $(call gb_Library_use_libraries,msfilter,\
+ svxcore \
+ editeng \
+ sfx \
+ xo \
+ sb \
+ salhelper \
+ svt \
+ tk \
+ vcl \
+ svl \
+ sot \
+ xmlscript \
+ utl \
+ tl \
+ comphelper \
+ basegfx \
+ cppuhelper \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,msfilter,\
+ filter/source/msfilter/countryid \
+ filter/source/msfilter/dffpropset \
+ filter/source/msfilter/dffrecordheader \
+ filter/source/msfilter/escherex \
+ filter/source/msfilter/eschesdo \
+ filter/source/msfilter/mscodec \
+ filter/source/msfilter/msdffimp \
+ filter/source/msfilter/msocximex \
+ filter/source/msfilter/msoleexp \
+ filter/source/msfilter/mstoolbar \
+ filter/source/msfilter/msvbahelper \
+ filter/source/msfilter/svdfppt \
+ filter/source/msfilter/svxmsbas2 \
+ filter/source/msfilter/rtfutil \
+ filter/source/msfilter/util \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_odfflatxml.mk b/filter/Library_odfflatxml.mk
new file mode 100644
index 000000000..176530035
--- /dev/null
+++ b/filter/Library_odfflatxml.mk
@@ -0,0 +1,36 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+#
+# 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/.
+#
+
+$(eval $(call gb_Library_Library,odfflatxml))
+
+$(eval $(call gb_Library_set_componentfile,odfflatxml,filter/source/odfflatxml/odfflatxml,services))
+
+$(eval $(call gb_Library_use_sdk_api,odfflatxml))
+
+$(eval $(call gb_Library_set_include,odfflatxml,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/filter/inc \
+))
+
+$(eval $(call gb_Library_use_libraries,odfflatxml,\
+ xo \
+ tl \
+ ucbhelper \
+ comphelper \
+ cppuhelper \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,odfflatxml,\
+ filter/source/odfflatxml/OdfFlatXml \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_pdffilter.mk b/filter/Library_pdffilter.mk
new file mode 100644
index 000000000..178a479d7
--- /dev/null
+++ b/filter/Library_pdffilter.mk
@@ -0,0 +1,66 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,pdffilter))
+
+$(eval $(call gb_Library_set_componentfile,pdffilter,filter/source/pdf/pdffilter,services))
+
+$(eval $(call gb_Library_use_external,pdffilter,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,pdffilter))
+
+$(eval $(call gb_Library_set_include,pdffilter,\
+ -I$(SRCDIR)/filter/inc \
+ $$(INCLUDE) \
+))
+
+$(eval $(call gb_Library_use_custom_headers,pdffilter,\
+ officecfg/registry \
+))
+
+$(eval $(call gb_Library_use_libraries,pdffilter,\
+ svt \
+ svx \
+ sfx \
+ tk \
+ vcl \
+ utl \
+ tl \
+ svl \
+ i18nlangtag \
+ comphelper \
+ basegfx \
+ cppuhelper \
+ cppu \
+ sal \
+ salhelper \
+ drawinglayer \
+ drawinglayercore \
+))
+
+$(eval $(call gb_Library_add_exception_objects,pdffilter,\
+ filter/source/pdf/impdialog \
+ filter/source/pdf/pdfdecomposer \
+ filter/source/pdf/pdfdialog \
+ filter/source/pdf/pdfexport \
+ filter/source/pdf/pdffilter \
+ filter/source/pdf/pdfinteract \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_storagefd.mk b/filter/Library_storagefd.mk
new file mode 100644
index 000000000..4d2fd1dfe
--- /dev/null
+++ b/filter/Library_storagefd.mk
@@ -0,0 +1,34 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# 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/.
+#
+#*************************************************************************
+
+$(eval $(call gb_Library_Library,storagefd))
+
+$(eval $(call gb_Library_set_componentfile,storagefd,filter/source/storagefilterdetect/storagefd,services))
+
+$(eval $(call gb_Library_use_external,storagefd,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,storagefd))
+
+$(eval $(call gb_Library_use_libraries,storagefd,\
+ comphelper \
+ cppuhelper \
+ cppu \
+ sal \
+ sfx \
+ tl \
+ utl \
+))
+
+$(eval $(call gb_Library_add_exception_objects,storagefd,\
+ filter/source/storagefilterdetect/filterdetect \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_svgfilter.mk b/filter/Library_svgfilter.mk
new file mode 100644
index 000000000..37372b9d0
--- /dev/null
+++ b/filter/Library_svgfilter.mk
@@ -0,0 +1,79 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,svgfilter))
+
+$(eval $(call gb_Library_use_custom_headers,svgfilter,filter/source/svg))
+
+$(eval $(call gb_Library_set_componentfile,svgfilter,filter/source/svg/svgfilter,services))
+
+$(eval $(call gb_Library_add_defs,svgfilter,\
+ -DBOOST_ALL_NO_LIB \
+ -DUSE_MODERN_SPIRIT \
+ -DFILTER_DLLIMPLEMENTATION \
+))
+
+ifeq ($(COM),MSC)
+$(eval $(call gb_Library_add_defs,svgfilter,\
+ -D_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING \
+ -D_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING \
+))
+endif
+
+$(eval $(call gb_Library_set_include,svgfilter,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/filter/inc \
+))
+
+$(eval $(call gb_Library_use_sdk_api,svgfilter))
+
+$(eval $(call gb_Library_use_libraries,svgfilter,\
+ svxcore \
+ editeng \
+ xo \
+ svt \
+ vcl \
+ svl \
+ utl \
+ tl \
+ i18nlangtag \
+ sax \
+ salhelper \
+ comphelper \
+ drawinglayercore \
+ drawinglayer \
+ basegfx \
+ cppuhelper \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_use_externals,svgfilter,\
+ boost_headers \
+ libxml2 \
+))
+
+$(eval $(call gb_Library_add_exception_objects,svgfilter,\
+ filter/source/svg/svgfilter \
+ filter/source/svg/svgexport \
+ filter/source/svg/svgfontexport \
+ filter/source/svg/svgwriter \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_t602filter.mk b/filter/Library_t602filter.mk
new file mode 100644
index 000000000..f8ad92b96
--- /dev/null
+++ b/filter/Library_t602filter.mk
@@ -0,0 +1,47 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,t602filter))
+
+$(eval $(call gb_Library_set_include,t602filter,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/filter/inc \
+))
+
+$(eval $(call gb_Library_set_componentfile,t602filter,filter/source/t602/t602filter,services))
+
+$(eval $(call gb_Library_use_external,t602filter,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,t602filter))
+
+$(eval $(call gb_Library_use_libraries,t602filter,\
+ xo \
+ tl \
+ utl \
+ cppuhelper \
+ cppu \
+ sal \
+ i18nlangtag \
+))
+
+$(eval $(call gb_Library_add_exception_objects,t602filter,\
+ filter/source/t602/t602filter \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_textfd.mk b/filter/Library_textfd.mk
new file mode 100644
index 000000000..d3318dcbd
--- /dev/null
+++ b/filter/Library_textfd.mk
@@ -0,0 +1,36 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# 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/.
+#
+#*************************************************************************
+
+$(eval $(call gb_Library_Library,textfd))
+
+$(eval $(call gb_Library_set_componentfile,textfd,filter/source/textfilterdetect/textfd,services))
+
+$(eval $(call gb_Library_use_external,textfd,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,textfd))
+
+$(eval $(call gb_Library_use_libraries,textfd,\
+ comphelper \
+ ucbhelper \
+ cppuhelper \
+ cppu \
+ sal \
+ sfx \
+ tl \
+ utl \
+ svt \
+))
+
+$(eval $(call gb_Library_add_exception_objects,textfd,\
+ filter/source/textfilterdetect/filterdetect \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_xmlfa.mk b/filter/Library_xmlfa.mk
new file mode 100644
index 000000000..35a2dd9ff
--- /dev/null
+++ b/filter/Library_xmlfa.mk
@@ -0,0 +1,42 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,xmlfa))
+
+$(eval $(call gb_Library_set_componentfile,xmlfa,filter/source/xmlfilteradaptor/xmlfa,services))
+
+$(eval $(call gb_Library_use_external,xmlfa,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,xmlfa))
+
+$(eval $(call gb_Library_use_libraries,xmlfa,\
+ comphelper \
+ cppuhelper \
+ cppu \
+ sal \
+ tl \
+ utl \
+ xo \
+))
+
+$(eval $(call gb_Library_add_exception_objects,xmlfa,\
+ filter/source/xmlfilteradaptor/XmlFilterAdaptor \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_xmlfd.mk b/filter/Library_xmlfd.mk
new file mode 100644
index 000000000..a5c1d190c
--- /dev/null
+++ b/filter/Library_xmlfd.mk
@@ -0,0 +1,42 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,xmlfd))
+
+$(eval $(call gb_Library_set_componentfile,xmlfd,filter/source/xmlfilterdetect/xmlfd,services))
+
+$(eval $(call gb_Library_use_external,xmlfd,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,xmlfd))
+
+$(eval $(call gb_Library_use_libraries,xmlfd,\
+ ucbhelper \
+ cppuhelper \
+ cppu \
+ sal \
+ svl \
+ utl \
+ tl \
+))
+
+$(eval $(call gb_Library_add_exception_objects,xmlfd,\
+ filter/source/xmlfilterdetect/filterdetect \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_xsltdlg.mk b/filter/Library_xsltdlg.mk
new file mode 100644
index 000000000..fd5f480e7
--- /dev/null
+++ b/filter/Library_xsltdlg.mk
@@ -0,0 +1,60 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,xsltdlg))
+
+$(eval $(call gb_Library_set_componentfile,xsltdlg,filter/source/xsltdialog/xsltdlg,services))
+
+$(eval $(call gb_Library_use_external,xsltdlg,boost_headers))
+
+$(eval $(call gb_Library_use_sdk_api,xsltdlg))
+
+$(eval $(call gb_Library_set_include,xsltdlg,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/filter/inc \
+))
+
+$(eval $(call gb_Library_use_libraries,xsltdlg,\
+ sfx \
+ svt \
+ tk \
+ vcl \
+ svl \
+ utl \
+ tl \
+ i18nlangtag \
+ comphelper \
+ cppuhelper \
+ cppu \
+ sal \
+))
+
+$(eval $(call gb_Library_add_exception_objects,xsltdlg,\
+ filter/source/xsltdialog/typedetectionexport \
+ filter/source/xsltdialog/typedetectionimport \
+ filter/source/xsltdialog/xmlfilterdialogcomponent \
+ filter/source/xsltdialog/xmlfilterjar \
+ filter/source/xsltdialog/xmlfiltersettingsdialog \
+ filter/source/xsltdialog/xmlfiltertabdialog \
+ filter/source/xsltdialog/xmlfiltertabpagebasic \
+ filter/source/xsltdialog/xmlfiltertabpagexslt \
+ filter/source/xsltdialog/xmlfiltertestdialog \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Library_xsltfilter.mk b/filter/Library_xsltfilter.mk
new file mode 100644
index 000000000..42f426c94
--- /dev/null
+++ b/filter/Library_xsltfilter.mk
@@ -0,0 +1,52 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Library_Library,xsltfilter))
+
+$(eval $(call gb_Library_set_componentfile,xsltfilter,filter/source/xsltfilter/xsltfilter,services))
+
+$(eval $(call gb_Library_use_sdk_api,xsltfilter))
+
+$(eval $(call gb_Library_use_libraries,xsltfilter,\
+ xo \
+ tl \
+ package2 \
+ sax \
+ comphelper \
+ ucbhelper \
+ cppuhelper \
+ cppu \
+ salhelper \
+ sal \
+))
+
+$(eval $(call gb_Library_use_externals,xsltfilter,\
+ boost_headers \
+ libxml2 \
+ libxslt \
+ libexslt \
+))
+
+$(eval $(call gb_Library_add_exception_objects,xsltfilter,\
+ filter/source/xsltfilter/LibXSLTTransformer \
+ filter/source/xsltfilter/OleHandler \
+ filter/source/xsltfilter/XSLTFilter \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Makefile b/filter/Makefile
new file mode 100644
index 000000000..0997e6284
--- /dev/null
+++ b/filter/Makefile
@@ -0,0 +1,14 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
+
+include $(module_directory)/../solenv/gbuild/partial_build.mk
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Module_filter.mk b/filter/Module_filter.mk
new file mode 100644
index 000000000..c28c72705
--- /dev/null
+++ b/filter/Module_filter.mk
@@ -0,0 +1,72 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Module_Module,filter))
+
+$(eval $(call gb_Module_add_targets,filter,\
+ Configuration_filter \
+ CustomTarget_svg \
+ Library_filterconfig \
+ Library_icg \
+ Library_msfilter \
+ Library_odfflatxml \
+ Library_pdffilter \
+ Library_storagefd \
+ Library_svgfilter \
+ Library_graphicfilter \
+ Library_t602filter \
+ Library_textfd \
+ Library_xmlfa \
+ Library_xmlfd \
+ Library_xsltdlg \
+ Library_xsltfilter \
+ Package_docbook \
+ Package_xhtml \
+ Package_xslt \
+ UIConfig_filter \
+))
+
+$(eval $(call gb_Module_add_l10n_targets,filter,\
+ AllLangMoTarget_flt \
+))
+
+$(eval $(call gb_Module_add_check_targets,filter,\
+ CppunitTest_filter_xslt \
+ CppunitTest_filter_priority \
+ CppunitTest_filter_msfilter \
+ CppunitTest_filter_textfilterdetect \
+ CppunitTest_filter_pdf \
+))
+
+ifneq ($(DISABLE_CVE_TESTS),TRUE)
+$(eval $(call gb_Module_add_check_targets,filter,\
+ CppunitTest_filter_svg \
+))
+endif
+
+# TODO
+#$(eval $(call gb_Module_add_subsequentcheck_targets,filter,\
+ JunitTest_filter_complex \
+))
+
+# screenshots
+$(eval $(call gb_Module_add_screenshot_targets,filter,\
+ CppunitTest_filter_dialogs_test \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Package_docbook.mk b/filter/Package_docbook.mk
new file mode 100644
index 000000000..6548fd6a1
--- /dev/null
+++ b/filter/Package_docbook.mk
@@ -0,0 +1,27 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Package_Package,filter_docbook,$(SRCDIR)/filter/source/docbook))
+
+$(eval $(call gb_Package_add_files,filter_docbook,$(LIBO_SHARE_FOLDER)/xslt/docbook,\
+ DocBookTemplate.stw \
+ docbooktosoffheadings.xsl \
+ sofftodocbookheadings.xsl \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Package_xhtml.mk b/filter/Package_xhtml.mk
new file mode 100644
index 000000000..91f9ff9ac
--- /dev/null
+++ b/filter/Package_xhtml.mk
@@ -0,0 +1,26 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Package_Package,filter_xhtml,$(SRCDIR)/filter/source/xslt))
+
+$(eval $(call gb_Package_add_file,filter_xhtml,$(LIBO_SHARE_FOLDER)/xslt/export/xhtml/body.xsl,odf2xhtml/export/xhtml/body.xsl))
+$(eval $(call gb_Package_add_file,filter_xhtml,$(LIBO_SHARE_FOLDER)/xslt/export/xhtml/header.xsl,odf2xhtml/export/xhtml/header.xsl))
+$(eval $(call gb_Package_add_file,filter_xhtml,$(LIBO_SHARE_FOLDER)/xslt/export/xhtml/opendoc2xhtml.xsl,odf2xhtml/export/xhtml/opendoc2xhtml.xsl))
+$(eval $(call gb_Package_add_file,filter_xhtml,$(LIBO_SHARE_FOLDER)/xslt/export/xhtml/table.xsl,odf2xhtml/export/xhtml/table.xsl))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/Package_xslt.mk b/filter/Package_xslt.mk
new file mode 100644
index 000000000..3fe8ff92f
--- /dev/null
+++ b/filter/Package_xslt.mk
@@ -0,0 +1,70 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+$(eval $(call gb_Package_Package,filter_xslt,$(SRCDIR)/filter/source/xslt))
+
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/common/copy.xsl,common/copy.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/common/math.xsl,common/math.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/common/measure_conversion.xsl,common/measure_conversion.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/ooo2ms_docpr.xsl,export/common/ooo2ms_docpr.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/spreadsheetml/formular.xsl,export/spreadsheetml/formular.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/spreadsheetml/ooo2spreadsheetml.xsl,export/spreadsheetml/ooo2spreadsheetml.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/spreadsheetml/style_mapping.xsl,export/spreadsheetml/style_mapping.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/spreadsheetml/styles.xsl,export/spreadsheetml/styles.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/spreadsheetml/table.xsl,export/spreadsheetml/table.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/uof/odf2uof_presentation.xsl,export/uof/odf2uof_presentation.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/uof/odf2uof_spreadsheet.xsl,export/uof/odf2uof_spreadsheet.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/uof/odf2uof_text.xsl,export/uof/odf2uof_text.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml.xsl,export/wordml/ooo2wordml.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_border.xsl,export/wordml/ooo2wordml_border.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_custom_draw.xsl,export/wordml/ooo2wordml_custom_draw.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_draw.xsl,export/wordml/ooo2wordml_draw.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_field.xsl,export/wordml/ooo2wordml_field.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_list.xsl,export/wordml/ooo2wordml_list.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_page.xsl,export/wordml/ooo2wordml_page.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_path.xsl,export/wordml/ooo2wordml_path.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_settings.xsl,export/wordml/ooo2wordml_settings.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_table.xsl,export/wordml/ooo2wordml_table.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/wordml/ooo2wordml_text.xsl,export/wordml/ooo2wordml_text.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/common/ms2ooo_docpr.xsl,import/common/ms2ooo_docpr.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/spreadsheetml/spreadsheetml2ooo.xsl,import/spreadsheetml/spreadsheetml2ooo.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/spreadsheetml/adorowset2ods.xsl,import/spreadsheetml/adorowset2ods.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/uof/uof2odf_presentation.xsl,import/uof/uof2odf_presentation.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/uof/uof2odf_spreadsheet.xsl,import/uof/uof2odf_spreadsheet.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/uof/uof2odf_text.xsl,import/uof/uof2odf_text.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo.xsl,import/wordml/wordml2ooo.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_custom_draw.xsl,import/wordml/wordml2ooo_custom_draw.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_draw.xsl,import/wordml/wordml2ooo_draw.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_field.xsl,import/wordml/wordml2ooo_field.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_list.xsl,import/wordml/wordml2ooo_list.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_page.xsl,import/wordml/wordml2ooo_page.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_path.xsl,import/wordml/wordml2ooo_path.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_props.xsl,import/wordml/wordml2ooo_props.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_settings.xsl,import/wordml/wordml2ooo_settings.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_table.xsl,import/wordml/wordml2ooo_table.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/import/wordml/wordml2ooo_text.xsl,import/wordml/wordml2ooo_text.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/body.xsl,odf2xhtml/export/common/body.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/styles/style_collector.xsl,odf2xhtml/export/common/styles/style_collector.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/styles/style_mapping_css.xsl,odf2xhtml/export/common/styles/style_mapping_css.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/table/table.xsl,odf2xhtml/export/common/table/table.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/table/table_cells.xsl,odf2xhtml/export/common/table/table_cells.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/table/table_columns.xsl,odf2xhtml/export/common/table/table_columns.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/table/table_rows.xsl,odf2xhtml/export/common/table/table_rows.xsl))
+$(eval $(call gb_Package_add_file,filter_xslt,$(LIBO_SHARE_FOLDER)/xslt/export/common/table_of_content.xsl,odf2xhtml/export/common/table_of_content.xsl))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/README.md b/filter/README.md
new file mode 100644
index 000000000..19caeb73e
--- /dev/null
+++ b/filter/README.md
@@ -0,0 +1,25 @@
+# LibreOffice Filters
+
+Filter registration and some simple filters (also descriptions).
+
+Desperate splitting of code into small shared libraries for historical
+reasons presumably (OS/2 and Windows 3.x). The libraries produced from
+the code in each subdirectory of `filter/source/graphicfilter` are
+graphic format import or export filters. But they don't have uniform
+API. Some have either a `GraphicImport` or `GraphicExport` entry point,
+and are loaded and used in a uniform fashion from code in
+`svtools/source/filter/filter.cxx`. Others have different API and are
+loaded from other places. For instance `icgm` has `ImportCGM`, and is
+loaded and used by `sd/source/filter/cgm/sdcgmfilter.cxx` (!).
+Svgreader is used for "File -> Open" and then to choose the svg file.
+For "Insert -> Picture -> From File", see `svgio/source/svgreader` directory.
+
+## Filter Configuration
+
+The filter configuration consists of two parts, the type definition in
+`filter/source/config/fragments/types/` and the actual filter definition
+in `filter/source/config/fragments/filters/`.
+
+Each file type e.g. text file should be represented by exactly one
+type definition. This type can then be referenced by several different
+filters, e.g. calc text, writer text.
diff --git a/filter/UIConfig_filter.mk b/filter/UIConfig_filter.mk
new file mode 100644
index 000000000..7d34128f5
--- /dev/null
+++ b/filter/UIConfig_filter.mk
@@ -0,0 +1,28 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_UIConfig_UIConfig,filter))
+
+$(eval $(call gb_UIConfig_add_uifiles,filter,\
+ filter/uiconfig/ui/pdfgeneralpage \
+ filter/uiconfig/ui/pdflinkspage \
+ filter/uiconfig/ui/pdfoptionsdialog \
+ filter/uiconfig/ui/pdfsecuritypage \
+ filter/uiconfig/ui/pdfsignpage \
+ filter/uiconfig/ui/pdfuserinterfacepage \
+ filter/uiconfig/ui/pdfviewpage \
+ filter/uiconfig/ui/testxmlfilter \
+ filter/uiconfig/ui/warnpdfdialog \
+ filter/uiconfig/ui/xmlfiltersettings \
+ filter/uiconfig/ui/xmlfiltertabpagegeneral \
+ filter/uiconfig/ui/xmlfiltertabpagetransformation \
+ filter/uiconfig/ui/xsltfilterdialog \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/filter/inc/strings.hrc b/filter/inc/strings.hrc
new file mode 100644
index 000000000..eecfdb33e
--- /dev/null
+++ b/filter/inc/strings.hrc
@@ -0,0 +1,76 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#define NC_(Context, String) TranslateId(Context, reinterpret_cast<char const *>(u8##String))
+
+#define STR_UNKNOWN_APPLICATION NC_("STR_UNKNOWN_APPLICATION", "Unknown")
+#define STR_IMPORT_ONLY NC_("STR_IMPORT_ONLY", "import filter")
+#define STR_IMPORT_EXPORT NC_("STR_IMPORT_EXPORT", "import/export filter")
+#define STR_EXPORT_ONLY NC_("STR_EXPORT_ONLY", "export filter")
+#define STR_WARN_DELETE NC_("STR_WARN_DELETE", "Do you really want to delete the XML Filter '%s'? This action cannot be undone.")
+#define STR_ERROR_FILTER_NAME_EXISTS NC_("STR_ERROR_FILTER_NAME_EXISTS", "An XML filter with the name '%s' already exists. Please enter a different name.")
+#define STR_ERROR_TYPE_NAME_EXISTS NC_("STR_ERROR_TYPE_NAME_EXISTS", "The name for the user interface '%s1' is already used by the XML filter '%s2'. Please enter a different name.")
+#define STR_ERROR_EXPORT_XSLT_NOT_FOUND NC_("STR_ERROR_EXPORT_XSLT_NOT_FOUND", "The XSLT for export cannot be found. Please enter a valid path.")
+#define STR_ERROR_IMPORT_XSLT_NOT_FOUND NC_("STR_ERROR_IMPORT_XSLT_NOT_FOUND", "The XSLT for import cannot be found. Please enter a valid path.")
+#define STR_ERROR_IMPORT_TEMPLATE_NOT_FOUND NC_("STR_ERROR_IMPORT_TEMPLATE_NOT_FOUND", "The given import template cannot be found. Please enter a valid path.")
+#define STR_DEFAULT_FILTER_NAME NC_("STR_DEFAULT_FILTER_NAME", "New Filter")
+#define STR_DEFAULT_UI_NAME NC_("STR_DEFAULT_UI_NAME", "Untitled")
+#define STR_UNDEFINED_FILTER NC_("STR_UNDEFINED_FILTER", "undefined filter")
+#define STR_FILTER_HAS_BEEN_SAVED NC_("STR_FILTER_HAS_BEEN_SAVED", "The XML filter '%s' has been saved as package '%s'. ")
+#define STR_FILTERS_HAVE_BEEN_SAVED NC_("STR_FILTERS_HAVE_BEEN_SAVED", "%s XML filters have been saved in the package '%s'.")
+#define STR_FILTER_PACKAGE NC_("STR_FILTER_PACKAGE", "XSLT filter package")
+#define STR_FILTER_INSTALLED NC_("STR_FILTER_INSTALLED", "The XML filter '%s' has been installed successfully.")
+#define STR_FILTERS_INSTALLED NC_("STR_FILTERS_INSTALLED", "%s XML filters have been installed successfully.")
+#define STR_NO_FILTERS_FOUND NC_("STR_NO_FILTERS_FOUND", "No XML filter could be installed because the package '%s' does not contain any XML filters.")
+#define STR_XML_FILTER_LISTBOX NC_("STR_XML_FILTER_LISTBOX", "XML Filter List")
+
+#define T602FILTER_STR_IMPORT_DIALOG_TITLE NC_("T602FILTER_STR_IMPORT_DIALOG_TITLE", "Settings for T602 import")
+#define T602FILTER_STR_ENCODING_LABEL NC_("T602FILTER_STR_ENCODING_LABEL", "Encoding")
+#define T602FILTER_STR_ENCODING_AUTO NC_("T602FILTER_STR_ENCODING_AUTO", "Automatic")
+#define T602FILTER_STR_ENCODING_CP852 NC_("T602FILTER_STR_ENCODING_CP852", "CP852 (Latin2)")
+#define T602FILTER_STR_ENCODING_CP895 NC_("T602FILTER_STR_ENCODING_CP895", "CP895 (KEYB2CS, Kamenicky)")
+#define T602FILTER_STR_ENCODING_KOI8CS2 NC_("T602FILTER_STR_ENCODING_KOI8CS2", "KOI8 CS2")
+#define T602FILTER_STR_CYRILLIC_MODE NC_("T602FILTER_STR_CYRILLIC_MODE", "Mode for Russian language (Cyrillic)")
+#define T602FILTER_STR_REFORMAT_TEXT NC_("T602FILTER_STR_REFORMAT_TEXT", "Reformat the text")
+#define T602FILTER_STR_DOT_COMMANDS NC_("T602FILTER_STR_DOT_COMMANDS", "Display dot commands")
+#define T602FILTER_STR_CANCEL_BUTTON NC_("T602FILTER_STR_CANCEL_BUTTON", "Cancel")
+#define T602FILTER_STR_OK_BUTTON NC_("T602FILTER_STR_OK_BUTTON", "OK")
+
+#define PDF_PROGRESS_BAR NC_("PDF_PROGRESS_BAR", "Export as PDF")
+
+//strings used in encryption UI
+//password dialog title
+#define STR_PDF_EXPORT_UDPWD NC_("STR_PDF_EXPORT_UDPWD", "Set open password")
+//password dialog title
+#define STR_PDF_EXPORT_ODPWD NC_("STR_PDF_EXPORT_ODPWD", "Set permission password")
+#define STR_WARN_PASSWORD_PDFA NC_("STR_WARN_PASSWORD_PDFA", "PDF/A does not allow encryption. The exported PDF file will not be password protected.")
+#define STR_WARN_TRANSP_PDFA_SHORT NC_("STR_WARN_TRANSP_PDFA_SHORT", "PDF/A transparency")
+#define STR_WARN_TRANSP_PDFA NC_("STR_WARN_TRANSP_PDFA", "PDF/A forbids transparency. A transparent object was painted opaque instead.")
+#define STR_WARN_TRANSP_VERSION_SHORT NC_("STR_WARN_TRANSP_VERSION_SHORT", "PDF version conflict")
+#define STR_WARN_TRANSP_VERSION NC_("STR_WARN_TRANSP_VERSION", "Transparency is not supported in PDF versions earlier than PDF 1.4. A transparent object was painted opaque instead")
+#define STR_WARN_FORMACTION_PDFA_SHORT NC_("STR_WARN_FORMACTION_PDFA_SHORT", "PDF/A form action")
+#define STR_WARN_FORMACTION_PDFA NC_("STR_WARN_FORMACTION_PDFA", "A form control contained an action not supported by the PDF/A standard. The action was skipped")
+#define STR_WARN_TRANSP_CONVERTED NC_("STR_WARN_TRANSP_CONVERTED", "Some objects were converted to an image in order to remove transparencies, because the target PDF format does not support transparencies. Possibly better results can be achieved if you remove the transparent objects before exporting.")
+#define STR_WARN_TRANSP_CONVERTED_SHORT NC_("STR_WARN_TRANSP_CONVERTED_SHORT", "Transparencies removed")
+#define STR_ERR_SIGNATURE_FAILED NC_("STR_ERR_SIGNATURE_FAILED", "Signature generation failed")
+#define STR_ERR_PDF_EXPORT_ABORTED NC_("STR_ERR_PDF_EXPORT_ABORTED", "PDF export aborted")
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/inc/strings.hxx b/filter/inc/strings.hxx
new file mode 100644
index 000000000..eeeb161b9
--- /dev/null
+++ b/filter/inc/strings.hxx
@@ -0,0 +1,24 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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/.
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+inline constexpr OUStringLiteral STR_APPL_NAME_WRITER = u"%PRODUCTNAME Writer (.sxw)";
+inline constexpr OUStringLiteral STR_APPL_NAME_CALC = u"%PRODUCTNAME Calc (.sxc)";
+inline constexpr OUStringLiteral STR_APPL_NAME_IMPRESS = u"%PRODUCTNAME Impress (.sxi)";
+inline constexpr OUStringLiteral STR_APPL_NAME_DRAW = u"%PRODUCTNAME Draw (.sxd)";
+inline constexpr OUStringLiteral STR_APPL_NAME_OASIS_WRITER = u"%PRODUCTNAME Writer (.odt)";
+inline constexpr OUStringLiteral STR_APPL_NAME_OASIS_CALC = u"%PRODUCTNAME Calc (.ods)";
+inline constexpr OUStringLiteral STR_APPL_NAME_OASIS_IMPRESS = u"%PRODUCTNAME Impress (.odp)";
+inline constexpr OUStringLiteral STR_APPL_NAME_OASIS_DRAW = u"%PRODUCTNAME Draw (.odg)";
+inline constexpr OUStringLiteral STR_DEFAULT_EXTENSION = u"xml";
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/filter/qa/complex/filter/detection/typeDetection/Helper.java b/filter/qa/complex/filter/detection/typeDetection/Helper.java
new file mode 100644
index 000000000..23eb07fc4
--- /dev/null
+++ b/filter/qa/complex/filter/detection/typeDetection/Helper.java
@@ -0,0 +1,431 @@
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+package complex.filter.detection.typeDetection;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.io.NotConnectedException;
+import com.sun.star.io.XInputStream;
+
+import helper.StreamSimulator;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Iterator;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.util.ArrayList;
+
+import lib.TestParameters;
+import share.LogWriter;
+import util.PropertyName;
+import util.utils;
+
+
+
+/** Helper class for "TypeDetection"
+ * This class do file handling.
+ */
+public class Helper {
+
+ /** The runner log writer
+ * @member m_log for log purposes
+ * @member m_sTestDocPath directory for searching files to load
+ * @member m_vFiles list of all files described in "files.csv"
+ * @member m_hFileURLs contains the position of a file name in the m_vFiles Vector
+ * @member m_hFileTypes contains the position of a file type in the m_vFiles Vector
+ * @member m_param the test parameters
+ */
+
+ private final LogWriter m_log;
+
+ private final String m_sTestDocPath;
+
+ private final ArrayList<ArrayList<String>> m_vFiles;
+
+ private final HashMap<String,String> m_hFileURLs = new HashMap<String,String>();
+
+ private final HashMap<String,String> m_hFileTypes = new HashMap<String,String>();
+
+ private final TestParameters m_param;
+
+ /**
+ * construct a new instance of this class
+ * It creates the "todo" list and position lists for <code>URL</code> and
+ * and <code>Type</code> inside the "todo" list
+ *
+ * @param param the test parameters
+ *
+ * @param log the log writer
+ */
+
+ public Helper(TestParameters param, LogWriter log) {
+
+ m_param = param;
+ m_log = log;
+
+
+ // get all files from the given directory
+ m_sTestDocPath = (String)param.get("TestDocumentPath");
+
+ // get all files from "files.csv"
+ m_vFiles = getToDoList((String)m_param.get("csv.files"));
+
+ createFilesList();
+ }
+
+
+ /** Reads a comma separated file (CSV). Every line of the file is
+ * represented by an <code>Vector</code> entry. Every data entry of a row is
+ * also stored in a <code>Vector</code>. So the returned value is a
+ * <code>Vector[][]</code> where the first dimension represents a row
+ * and the second dimension includes the data values.
+ * @param csvFileName the name of the csv file
+ * @return Vector filled with Vector filled with data of a row
+ */
+ public ArrayList<ArrayList<String>> getToDoList(String csvFileName){
+
+ try {
+
+ ArrayList<ArrayList<String>> vAll = new ArrayList<ArrayList<String>>();
+ ArrayList<String> vFields = new ArrayList<String>();
+
+ // get content of file
+ ArrayList<String> content = getCSVFileContent(csvFileName);
+
+ // remove superfluous content like "#" started lines
+ content = removeSuperfluousContent(content);
+
+ // replace all place holders in file
+ content = replacePlaceHolder(content);
+
+ // create Enumeration
+ Iterator<String> contentEnum = content.iterator();
+
+ // the first line contains field names of the columns
+ // split line by ";"
+ StringTokenizer fields = new StringTokenizer(
+ contentEnum.next(),";");
+ int fieldCount = 0;
+ while (fields.hasMoreElements()){
+ vFields.add(fields.nextToken());
+ fieldCount++;
+ }
+
+ // fill vData with data of CSV-row
+ while (contentEnum.hasNext()){
+ ArrayList<String> vData = new ArrayList<String>();
+
+ StringTokenizer data = new StringTokenizer(
+ contentEnum.next(),";", true);
+
+ // example: data = "firstData;secondData;;forthData"
+ // => three tokens => missing one data because the imagine
+ // "thirdData" was not received by data.nextToken()
+ // Therefore here comes a special handling for empty data
+ boolean nextIsData = false;
+ int dataCount = 0;
+ while (data.hasMoreTokens()) {
+ String myToken = data.nextToken();
+ // if the "thirdData" will be received, myToken=";" but
+ // vData must add an empty String
+ if (myToken.equals(";")){
+ if (nextIsData ) {
+ vData.add("");
+ dataCount++;
+ nextIsData = false;
+ }
+ nextIsData = true;
+ } else {
+ vData.add(myToken);
+ dataCount++;
+ nextIsData = false;
+ }
+ }
+ for (int i=dataCount; i < fieldCount; i++) vData.add("");
+ vAll.add(vData);
+ }
+
+
+ return vAll;
+
+ } catch(ClassCastException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ /** The csv files "files", "preselectedFilter", "preselectedType" and
+ * "serviceName" are delivered beside this class. This function seeks for
+ * the csv files and read them.
+ * @param csvFileName the name of the csv file
+ * @return a Vector containing the content of the file. <null/> if the file
+ * cannot be read
+ */
+
+ private ArrayList<String> getCSVFileContent(String csvFileName) {
+ try {
+ ArrayList<String> content = new ArrayList<String>();
+ BufferedReader br;
+ String line;
+ if ( m_param.getBool(PropertyName.DEBUG_IS_ACTIVE) ) {
+ System.out.println("Looking for "+csvFileName);
+ }
+
+ URL url = getClassURL(csvFileName);
+
+ if (url != null) {
+ URLConnection connection = url.openConnection();
+ InputStream in = connection.getInputStream();
+
+ br = new BufferedReader(new InputStreamReader(in));
+ try {
+ while( ( line = br.readLine() ) != null ) {
+ content.add( line );
+ }
+ } catch (IOException e) {
+ br.close();
+ return null;
+ }
+ br.close();
+ return content;
+ }
+
+ }catch (IOException e) {
+ }catch(NullPointerException e) {
+ return null;
+ }
+ return null;
+ }
+
+ /** returns a XInputStream of given file
+ * @param filePath the path to the file which should be loaded
+ * @return the XInputStream, <null/> if the
+ * file cannot be read
+ * @throws NotConnectedException was thrown if it was not possible to open <CODE>filePath</CODE>
+ */
+ public XInputStream getFileStream( String filePath )
+ throws NotConnectedException {
+ return new StreamSimulator(filePath, true, m_param);
+ }
+
+ /** replaces place holder in preselectedFilter.
+ * Because of filter names depend on StarOffice version like
+ * "StarOffice 6.0 Textdokument" or ""StarSuite 7 Textdokument"
+ * The filter names must be changed. The place holder will be replaced
+ * by an equivalent in "typeDetection.props"
+ * @param content the content of a csv file
+ * @return changed file content
+ */
+ private ArrayList<String> replacePlaceHolder(ArrayList<String> content){
+
+ ArrayList<String> vReturn = new ArrayList<String>();
+
+ ArrayList<String> placeHolders = new ArrayList<String>();
+ Iterator<String> paramsIter = m_param.keySet().iterator();
+ String placeHolder = (String)m_param.get("placeHolder");
+
+ // get all place holders from typeDetection.csv
+ while (paramsIter.hasNext()){
+ String holderKey = paramsIter.next();
+ if (holderKey.startsWith(placeHolder)){
+ placeHolders.add(holderKey);
+ }
+ }
+
+ // replace all occurrences of place holders in 'CSVData'
+ Iterator<String> cont = content.iterator();
+
+ while( cont.hasNext() ) {
+
+ String line = cont.next();
+ String newLine = line;
+ Iterator<String> holders = placeHolders.iterator();
+
+ while( holders.hasNext() ) {
+
+ String holder = holders.next();
+ int startPos = line.indexOf(holder);
+
+ if (startPos > -1){
+ try{
+ String holderValue = (String) m_param.get(holder);
+
+ newLine = newLine.substring(0,startPos) + holderValue +
+ newLine.substring(startPos + holder.length());
+
+ } catch (java.lang.IndexOutOfBoundsException e){
+ m_log.println("ERROR: problems while creating placeholder" +
+ " replaced list: "+ e);
+ }
+ }
+ }
+ vReturn.add(newLine);
+ }
+ return vReturn;
+ }
+
+ /** Removes lines of an ascii file content which starts with "#"
+ * or are empty
+ * @param content content of a csv file
+ * @return a stripped Vector
+ */
+ private ArrayList<String> removeSuperfluousContent(ArrayList<String> content){
+ ArrayList<String> newContent = new ArrayList<String>();
+ Iterator<String> cont = content.iterator();
+ while( cont.hasNext() ) {
+ String line = cont.next();
+ if (( ! line.startsWith( "#" ))&& ( line.length() != 0 )) {
+ newContent.add( line );
+ }
+ }
+ return newContent;
+ }
+
+ /** returns a <code>MediaDescriptor</code> filled with given properties and
+ * values.
+ * @param propNames String Array of property names
+ * @param values Object Array of property values
+ * @return <code>PropertyValue[]<code>
+ * @see com.sun.star.beans.PropertyValue
+ * @see com.sun.star.document.MediaDescriptor
+ */
+ public PropertyValue[] createMediaDescriptor(String[] propNames, Object[] values) {
+ PropertyValue[] props = new PropertyValue[propNames.length] ;
+
+ for (int i = 0; i < props.length; i++) {
+ props[i] = new PropertyValue() ;
+ props[i].Name = propNames[i] ;
+ if (values != null && i < values.length) {
+ props[i].Value = values[i] ;
+ }
+ }
+
+ return props ;
+ }
+
+ /** Appends system file separator if needed
+ * @param s the system path
+ * @return system path with ending system file separator
+ */
+ public String ensureEndingFileSep(String s){
+ if(s != null && !s.equals("") && !s.endsWith(File.separator)){
+ s = s.trim() + File.separator;
+ }else if(s == null)
+ s = "";
+ return s;
+ }
+
+ /** Returns the file URL for the given file name assembled by
+ * "TestDocumentPath" of typeDetection.props and "fileURL" of files.csv
+ * @param fileAlias the alias name of the file
+ * @return file URL
+ * @throws FileAliasNotFoundException was thrown if alias does not exist
+ */
+ public String getURLforfileAlias(String fileAlias)
+ throws FileAliasNotFoundException{
+ try{
+ String fileURL = m_hFileURLs.get(fileAlias).toString();
+ return utils.getFullURL(ensureEndingFileSep(m_sTestDocPath) + fileURL);
+ } catch (NullPointerException e){
+ throw new FileAliasNotFoundException(fileAlias, e);
+ }
+
+ }
+
+ /** Returns the file type for the given file name containing in files.csv
+ * @param fileAlias the alias name of the file
+ * @return file type
+ * @throws FileAliasNotFoundException was thrown if not alias was thrown
+ */
+ public String getTypeforfileAlias(String fileAlias)
+ throws FileAliasNotFoundException{
+ try{
+ return m_hFileTypes.get(fileAlias).toString();
+ } catch (NullPointerException e){
+ throw new FileAliasNotFoundException(fileAlias, e);
+ }
+ }
+
+ /**
+ * Fills the Hashtable m_hFileURLs with all file names and their URL
+ * and the Hashtable m_hFileTypes with all file names and their file
+ * type name. This information is extracted from "files.csv"
+ * This is for faster access to get fileURL and fileType of fileAlias
+ */
+ private void createFilesList(){
+ for (int i = 0; i < m_vFiles.size();i++){
+ ArrayList<String> toDo = m_vFiles.get(i);
+ m_hFileURLs.put(toDo.get(0), toDo.get(1));
+ m_hFileTypes.put(toDo.get(0), toDo.get(2));
+ }
+ }
+
+
+ /** Validate the returned file type for the file alias with the
+ * possible file types
+ * @param currentFileType the returned file type
+ * @param fileTypes all possible file types
+ * @return true if valid
+ */
+ public boolean checkFileType(String currentFileType, String fileTypes){
+
+ StringTokenizer data = new StringTokenizer(fileTypes,":", true);
+
+ boolean found = false;
+ while (data.hasMoreElements()) {
+
+ String actualFileType = data.nextElement().toString();
+
+ found = found || currentFileType.equals(actualFileType);
+ }
+ return found;
+ }
+
+ /** creates an input/output parameter of <code>PropertyValue[]<code>.
+ * @return PropertyValue[][]
+ * @param PropVal a PropertyValue
+ */
+ public PropertyValue[][] createInOutPropertyValue(PropertyValue[] PropVal){
+ PropertyValue[][] dummy = new PropertyValue[1][];
+ dummy[0] = PropVal;
+ return dummy;
+ }
+
+ private URL getClassURL(String fileName){
+ String PackagePath = this.getClass().getPackage().getName().replace('.','/');
+ return this.getClass().getResource("/" + PackagePath +"/" + fileName);
+ }
+
+ public String getClassURLString(String fileName){
+ return getClassURL(fileName).toString().replaceAll("file:","");
+ }
+
+
+}
+
+/** This exception should be thrown if a method seeks for an invalid alias name */
+class FileAliasNotFoundException extends java.lang.Exception{
+ /** throws error message with wrong alias name
+ * @param fileAlias the alias name
+ */
+ public FileAliasNotFoundException(String fileAlias, Throwable cause){
+ super("Could not get '"+fileAlias +"'", cause);
+ }
+}
diff --git a/filter/qa/complex/filter/detection/typeDetection/TypeDetection.java b/filter/qa/complex/filter/detection/typeDetection/TypeDetection.java
new file mode 100644
index 000000000..2c7a6934a
--- /dev/null
+++ b/filter/qa/complex/filter/detection/typeDetection/TypeDetection.java
@@ -0,0 +1,546 @@
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.filter.detection.typeDetection;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.document.XTypeDetection;
+import com.sun.star.io.NotConnectedException;
+import com.sun.star.io.XInputStream;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+import complexlib.ComplexTestCase;
+import java.io.File;
+
+import java.util.Iterator;
+import java.util.ArrayList;
+import util.utils;
+
+
+
+/** Check "TypeDetection"
+ * <p>
+ * This test will check the file type detection. This will be done by filling
+ * properties of a <code>MediaDescriptor</code>.
+ *
+ * In the test method <code>checkByURLonly</code> the
+ * <code>MediaDescriptor</code> was filled at once with the URL of a test
+ * file. At second it was filled with a <code>XInputStream</code> from test
+ * file. In both subtests the returned file type must match with an expected
+ * type.
+ *
+ * In the test method <code>checkPreselectedType</code> the
+ * <code>MediaDescriptor</code> was filled with the URL of the test file and
+ * with the name of a type which should be used. The returned type of the
+ * <code>TypeDetection<code> must match with an expected type.
+ *
+ * In the test method <code>checkPreselectedFilter</code> the
+ * <code>MediaDescriptor</code> was filled with the URL of the test file and
+ * with the name of a filter which should be used. The returned type of the
+ * <code>TypeDetection<code> must match with an expected type.
+ *
+ * In the test method <code>checkPreselectedDocService</code> the
+ * <code>MediaDescriptor</code> was filled with the URL of the test file and
+ * with the name of a document service which should be used. The returned type
+ * of the <code>TypeDetection<code> must match with an expected type.
+ *
+ *
+ * To get information on which test file should support which type, filter and
+ * document service, this information was collected from configuration files:
+ * <UL>
+ * <LI><a href="#TypeDetection.props">TypeDetection.props</a></LI>
+ * <LI><a href="#files.csv">files.csv</a></LI>
+ * <LI><a href="#preselectedFilter.csv">preselectedFilter.csv</a></LI>
+ * <LI><a href="#preselectedType.csv">preselectedType.csv</a></LI>
+ * <LI><a href="#serviceName.csv">serviceName.csv</a></LI>
+ * </UL>
+ * <p>
+ * <h3><A name="TypeDetection.props"></A>
+ * <code>typeDetection.props</code></h3>
+ * At first there will be the <code>typeDetection.props</code>. Here the following
+ * properties should be set (with example values):
+ *
+ * TestDocumentPath=file:///path/to/my/testdocuments
+ * placeHolder=%
+ * %SO6productname=StarOffice
+ * %SO6formatversion=6.0
+ *
+ * <code>TestDocumentPath</code>: this is the path to your test documents. If
+ * you have grouped your documents ie. by writer, calc, ... then it should be
+ * the root path. To specify the particular sub folders you have to use
+ * <code>csv.files</code>
+ * <p>
+ * <code>files.csv</code>: In this file all test documents are listed.
+ * Syntax: fileAlias;fileURL;defaultURLFileType;StreamFileTypes
+ * Example:
+ *
+ * Writer6_1;Writer/Writer6.sxw;writer_StarOffice_XML_Writer;writer_StarOffice_XML_Writer
+ * text1;Writer/Text.txt:generic_Text:generic_Text
+ *
+ * The first example shows you the following:
+ * <code>Writer6_1</code> is a free chosen name
+ * <code>Writer/Writer6.sxw</code> is the document path. This will be assembled
+ * by <code>TestDocumentPath</code> from <code>typeDetection.props</code>.
+ * <code>writer_StarOffice_XML_Writer</code>: this is the default file type of
+ * this file
+ *
+ * The second example displays two document types for
+ * <code>XInputStream</CODE> (<code>generic_Text</CODE>). These
+ * two document types are listed by a colon ':' as separator.
+ * This is needed because XInputStream can detect a text file as
+ * generic_Text.
+ * <p>
+ *
+ * <H3><A name="preselectedFilter.csv"</a>
+ * <code>preselectedFilter.csv</code></H3>
+ * In this file you can choose a special
+ * filter to detect the document. This makes sense ie. for csv-files: You can
+ * open csv files as Writer or as Calc. To check this case you have to specify
+ * in <code>csv.files</code> a fileAlias like ?csv_writer? and ?csv_calc? with
+ * the same fileURL and its specific defaultFileType.
+ * The returned file type by <code>TypeDetection</code> must be equal to the
+ * corresponding <code>defaultFileType</code> from <code>csv.files</code>
+ *
+ * Syntax: fileAlias;FilterName;FilterOptions;FilterData
+ * Example: Writer6_1;%SO6productname %SO6formatversion Textdocument;
+ *
+ * The example shows the following:
+ * <code>Writer6_1</code> is the same as in <code>csv.files</code>
+ * <code>%SO6productname %SO6formatversion Textdokument</code> is the filter
+ * name which should be used. Here we have a special: <code>%SO6productname
+ * %SO6formatversion</code> will be replaced by the equals of
+ * <code>typeDetection.props</code>. The filter names depends on the Office
+ * name and version. So a future Office could be called ?StarSuite 8?.
+ * <code>FilterOptions</code> is not relevant for this filter. But ie. for csv
+ * filter this entry could be used to specify the separator of the csv file.
+ * <code>FilterData<code> if filter needs some FilterData arguments you can
+ * specify them here
+ *
+ * <p>
+ * <H3><a name="preselectedType.csv"></A>
+ * <code>preselectedType.csv</code></H3>
+ * In this file you can preselect the type
+ * <code>TypeDetection</code> should use.
+ * The file type returned by <code>TypeDetection</code> must be equal to the
+ * preselected file type.
+ * Note: If you try to use invalid types you will get a failed test because
+ * <code>TypeDetection</code> tries to find out the type itself.
+ *
+ * Syntax: fileAlias;fileType
+ * Example: Writer6_1;writer_StarOffice_XML_Writer
+ *
+ * This example shows the following:
+ * <code>Writer6_1</code> is the same as in <code>csv.files</code>
+ * <code>writer_StarOffice_XML_Writer</code> is the file type which was used as
+ * parameter in <code>MediaDescriptor</code>. This type must be returned from
+ * <code>TypeDetection</code>
+ *
+ * <p>
+ * <H3><a name="serviceName.csv"></A>
+ * <code>serviceName.csv</code></H3> In this file you can preselect a service name
+ * to detect the file type. The file type returned by
+ * <code>TypeDetection</code> must be equal to the corresponding
+ * <code>defaultFileType</code> from <code>csv.files</code>
+ *
+ * Syntax: fileAlias;serviceName
+ * Example: Writer6_1;com.sun.star.text.FormatDetector
+ *
+ * This example shows the following:
+ * <code>Writer6_1</code> is the same as in <code>csv.files</code>
+ * <code>com.sun.star.text.FormatDetector</code> is the service name which was
+ * used as parameter in <code>MediaDescriptor</code>.
+ *
+ *
+ * <p>
+ * All these files will be copied by make file beside of
+ * <code>typeDetection.class</code>.
+ * @see com.sun.star.document.XTypeDetection
+ * @see com.sun.star.document.MediaDescriptor
+ */
+public class TypeDetection extends ComplexTestCase {
+
+ /**
+ * @member m_xDetection the object to test
+ * @member helper instance of helper class
+ */
+
+ static XTypeDetection m_xDetection;
+ static Helper helper = null;
+
+ /**
+ * A function to tell the framework, which test functions are available.
+ * @return All test methods.
+ */
+ @Override
+ public String[] getTestMethodNames() {
+ return new String[]{"checkByURLonly",
+ "checkPreselectedType",
+ "checkPreselectedFilter",
+ "checkPreselectedDocService",
+ "checkStreamLoader",
+ "checkStreamLoader"};
+
+ }
+
+ /** Create the environment for following tests.
+ * Use either a component loader from desktop or
+ * from frame
+ * @throws Exception Exception
+ */
+ public void before() throws Exception {
+
+ // create TypeDetection
+ XMultiServiceFactory xMSF = param.getMSF();
+ assure("Could not get XMultiServiceFactory", xMSF != null);
+
+ Object oInterface = xMSF.createInstance(
+ "com.sun.star.document.TypeDetection");
+
+ if (oInterface == null) {
+ failed("Service wasn't created") ;
+ }
+
+ XInterface oObj = (XInterface) oInterface ;
+ log.println("ImplName: "+utils.getImplName(oObj));
+
+ m_xDetection = UnoRuntime.queryInterface(XTypeDetection.class, oInterface);
+ Iterator<String> k = param.keySet().iterator();
+ while (k.hasNext()){
+ String kName = k.next();
+ log.println(kName + ":" + param.get(kName).toString());
+ }
+ // create instance of helper class
+ helper = new Helper(param, log);
+
+ }
+
+ /**
+ * close the environment
+ */
+ public void after() {
+ }
+
+ /**
+ * The <code>MediaDescriptor</code> was filled with the URL of a file. The
+ * <code>type</code> of the file is known and must be returned by
+ * <code>MediaDescriptor</code>
+ *
+ * Syntax of files.csv:
+ * fileAlias;fileURL;fileType
+ *
+ */
+ public void checkByURLonly() {
+ try{
+ log.println("### checkByURLonly() ###");
+ ArrayList<ArrayList<String>> CSVData = helper.getToDoList(
+ (String)param.get("csv.files"));
+ Iterator<ArrayList<String>> allToDos = CSVData.iterator();
+
+ while (allToDos.hasNext()){
+ ArrayList<String> toDo = allToDos.next();
+
+ String fileAlias = toDo.get(0);
+ String fileURL = toDo.get(1);
+ String URLfileType = toDo.get(2);
+ String StreamfileType = toDo.get(3);
+
+ fileURL = utils.getFullURL(helper.ensureEndingFileSep(
+ (String)param.get("TestDocumentPath")) + fileURL);
+
+ log.println("actual '"+ fileAlias +
+ "' ['" + URLfileType + "']: '" + fileURL);
+
+ checkMediaDescriptorURL(fileAlias, fileURL, URLfileType);
+ checkMediaDescriptorXInputStream(fileAlias, fileURL, StreamfileType);
+ }
+
+ } catch (ClassCastException e){
+ failed(e.toString(), ContinueWithTest.YES);
+ }
+ }
+
+ /** To check the <CODE>TypeDetection</CODE> by URL the <CODE>MediaDescriptor</CODE>
+ * was filled at first with the URL only, at second with <CODE>XInputStream</CODE>
+ * only. The <CODE>TypeDetection</CODE> must return the expected value
+ * @param fileAlias the alias name of the test file
+ * @param fileURL the URL of the test file
+ * @param fileType the expected type of the test file
+ * @see com.sun.star.document.MediaDescriptor
+ */
+ private void checkMediaDescriptorURL(
+ String fileAlias, String fileURL, String fileType){
+
+ PropertyValue[] MediaDescriptor = helper.createMediaDescriptor(
+ new String[] {"URL"},
+ new Object[] {fileURL});
+ log.println("check only by URL...");
+
+ String type = m_xDetection.queryTypeByDescriptor(
+ helper.createInOutPropertyValue(MediaDescriptor), true);
+
+ boolean fileTypeOK = helper.checkFileType(type, fileType);
+
+ assure("\nURL-test : " + fileAlias + ":\n\treturned type: '" + type +
+ "'\n\texpected type: '" + fileType + "'",fileTypeOK ,ContinueWithTest.YES);
+ }
+
+ /** Fills a MediaDescriptor with a <code>XInputStream</code> of the test
+ * file given by URL.
+ * Then the MediaDescriptor was used as parameter for TypeDetection.
+ * The TypeDetection must return expected type
+ * @param fileAlias the alias name of the test file
+ * @param fileURL the URL of the test file
+ * @param fileType the expected type of the test file
+ * @see com.sun.star.document.MediaDescriptor
+ * @see com.sun.star.io.XInputStream
+ */
+ private void checkMediaDescriptorXInputStream(
+ String fileAlias, String fileURL, String fileType){
+
+ XInputStream xStream = null;
+
+ try{
+ xStream = helper.getFileStream( fileURL );
+ } catch (NotConnectedException e) {
+ failed("Could not get XInputStream from file :'" + fileURL + "'",ContinueWithTest.YES);
+ return;
+ }
+
+ PropertyValue[] MediaDescriptor = helper.createMediaDescriptor(
+ new String[] {"InputStream"},
+ new Object[] {xStream});
+ log.println("check only by XInputStream...");
+
+ String type = m_xDetection.queryTypeByDescriptor(
+ helper.createInOutPropertyValue(MediaDescriptor), true);
+
+ boolean fileTypeOK = helper.checkFileType(type, fileType);
+
+ assure("\nXInputStream-test: " + fileAlias + ":\n\treturned type: '" + type +
+ "'\n\texpected type: '" + fileType + "'", fileTypeOK, ContinueWithTest.YES);
+
+ }
+
+ /**
+ * The <code>MediaDescriptor</code> was filled with the URL of a file. The
+ * <code>type</code> of the file is known and must be returned by
+ * <code>MediaDescriptor</code>
+ *
+ * Syntax of files.csv:
+ * fileAlias;fileURL;fileType
+ *
+ */
+ public void checkPreselectedType() {
+ try{
+ log.println("### checkPreselectedType() ###");
+
+ ArrayList<ArrayList<String>> CSVData = helper.getToDoList(
+ (String)param.get("csv.preselectedType"));
+ Iterator<ArrayList<String>> allToDos = CSVData.iterator();
+
+ while (allToDos.hasNext()){
+ try{
+ ArrayList<String> toDo = allToDos.next();
+
+ String fileAlias = toDo.get(0);
+ String fileURL = helper.getURLforfileAlias(fileAlias);
+ String preselectFileType = toDo.get(1);
+ String expectedFileType = toDo.get(2);
+
+ PropertyValue[] MediaDescriptor = helper.createMediaDescriptor(
+ new String[] {"URL", "MediaType"},
+ new Object[] {fileURL, preselectFileType});
+ log.println("check '" + fileAlias + "' with MediaType: '" +
+ preselectFileType + "'");
+
+ String type = m_xDetection.queryTypeByDescriptor(
+ helper.createInOutPropertyValue(MediaDescriptor), true);
+
+ boolean fileTypeOK = helper.checkFileType(type, expectedFileType);
+
+ assure("\n" + fileAlias + ":\n\treturned type: '" + type +
+ "'\n\texpected type: '" + expectedFileType + "'",
+ fileTypeOK, ContinueWithTest.YES);
+
+ } catch (FileAliasNotFoundException e){
+ failed(e.toString(),ContinueWithTest.YES);
+ }
+
+ }
+
+ } catch (ClassCastException e){
+ failed(e.toString(), ContinueWithTest.YES);
+ }
+ }
+
+
+ /**
+ * Check loading from a stream. The source for the stream is the
+ * first fileAlias that matches "*.txt" in the file list
+ * of the given directory.
+ */
+ public void checkPreselectedFilter() {
+ try{
+ log.println("### checkPreselectedFilter() ###");
+
+ ArrayList<ArrayList<String>> CSVData = helper.getToDoList(
+ (String)param.get("csv.preselectedFilter"));
+ Iterator<ArrayList<String>> allToDos = CSVData.iterator();
+
+ while (allToDos.hasNext()){
+ try{
+ ArrayList<String> toDo = allToDos.next();
+
+ String fileAlias = toDo.get(0);
+ String fileURL = helper.getURLforfileAlias(fileAlias);
+ String filterName = toDo.get(1);
+ String filterOptions = toDo.get(2);
+ String filterData = toDo.get(3);
+ String expectedType = toDo.get(4);
+
+ PropertyValue[] MediaDescriptor = helper.createMediaDescriptor(
+ new String[] {"URL","FilterName",
+ "FilterOptions","FilterData"},
+ new Object[] {fileURL, filterName,
+ filterOptions, filterData});
+
+ log.println("check '" + fileAlias + "' with filter: '" +
+ filterName + "'");
+
+ String type = m_xDetection.queryTypeByDescriptor(
+ helper.createInOutPropertyValue(MediaDescriptor), true);
+
+ boolean fileTypeOK = helper.checkFileType(type, expectedType);
+
+ assure("\n" + fileAlias + ":\n\treturned type: '" + type +
+ "'\n\texpected type: '" + expectedType + "'",
+ fileTypeOK,ContinueWithTest.YES);
+
+ } catch (FileAliasNotFoundException e){
+ failed(e.toString(),ContinueWithTest.YES);
+ }
+
+ }
+
+ } catch (ClassCastException e){
+ failed(e.toString(), ContinueWithTest.YES);
+ }
+ }
+
+ /**
+ * Check URL encoding. The first fileAlias that matches "*.sxw"
+ * is used as source for several encodings.
+ */
+ public void checkPreselectedDocService() {
+ try{
+ log.println("### checkPreselectedDocService() ###");
+
+ ArrayList<ArrayList<String>> CSVData = helper.getToDoList((String)param.get("csv.serviceName"));
+ Iterator<ArrayList<String>> allToDos = CSVData.iterator();
+
+ while (allToDos.hasNext()){
+ try{
+ ArrayList<String> toDo = allToDos.next();
+
+ String fileAlias = toDo.get(0);
+ String fileURL = helper.getURLforfileAlias(fileAlias);
+ String serviceName = toDo.get(1);
+ String fileType = helper.getTypeforfileAlias(fileAlias);
+
+ PropertyValue[] MediaDescriptor = helper.createMediaDescriptor(
+ new String[] {"URL", "DocumentService"},
+ new Object[] {fileURL, serviceName});
+ log.println("check " + fileAlias);
+
+ String type = m_xDetection.queryTypeByDescriptor(
+ helper.createInOutPropertyValue(MediaDescriptor), true);
+
+ boolean fileTypeOK = helper.checkFileType(type, fileType);
+
+ assure("\n" + fileAlias + ":\n\treturned type: '" + type +
+ "'\t\nexpected type: '" + fileType + "'",
+ fileTypeOK, ContinueWithTest.YES);
+
+ } catch (FileAliasNotFoundException e){
+ failed(e.toString(),ContinueWithTest.YES);
+ }
+
+ }
+
+ } catch (ClassCastException e){
+ failed(e.toString(), ContinueWithTest.YES);
+ }
+ }
+
+ public void checkStreamLoader(){
+ try{
+
+ /*
+ * As files, use the typeDetection.props and one of the csv files.
+ * Those can, via dmake, simply set rights on others.
+ *
+ */
+ log.println("### checkStreamLoader() ###");
+ String[] urls = new String[] {
+ helper.getClassURLString("TypeDetection.props"),
+ helper.getClassURLString("files.csv") };
+
+ for (int j=0; j<urls.length; j++){
+ String fileURL = urls[j];
+ File file = new File(fileURL);
+ fileURL = utils.getFullURL(fileURL);
+
+ PropertyValue[] MediaDescriptor = helper.createMediaDescriptor(
+ new String[] {"URL"},
+ new Object[] {fileURL});
+
+ if (file.canWrite()) log.println("check writable file...");
+ else log.println("check readonly file...");
+
+ PropertyValue[][] inOut = helper.createInOutPropertyValue(MediaDescriptor);
+ PropertyValue[] in = inOut[0];
+ log.println("in-Parameter:");
+ for (int i=0; i < in.length; i++){
+ log.println("["+i+"] '" + in[i].Name + "':'" + in[i].Value.toString()+"'");
+ }
+
+ String type = m_xDetection.queryTypeByDescriptor(inOut, true);
+
+ PropertyValue[] out = inOut[0];
+
+ log.println("out-Parameter");
+ boolean bReadOnly = false;
+ for (int i=0; i < out.length; i++){
+ if ((out[i].Name.equals("ReadOnly")) && (out[i].Value.toString().equals("true"))) bReadOnly = true;
+ log.println("["+i+"] '" + out[i].Name + "':'" + out[i].Value.toString()+"'");
+ }
+
+ if (file.canWrite() && bReadOnly)
+ assure("\nStreamLoader: file '"+ fileURL +"' is writable but out-Parameter does contain 'ReadOnly' property", false, ContinueWithTest.YES);
+ else if ((!file.canWrite()) && (!bReadOnly))
+ assure("\nStreamLoader: file '"+ fileURL +"'is readonly but out-Parameter does not contain 'ReadOnly' property", false, ContinueWithTest.YES);
+ else assure("all ok", true, ContinueWithTest.YES);
+
+ }
+
+ } catch (ClassCastException e){
+ failed(e.toString(), ContinueWithTest.YES);
+ }
+
+ }
+}
diff --git a/filter/qa/complex/filter/detection/typeDetection/TypeDetection.props b/filter/qa/complex/filter/detection/typeDetection/TypeDetection.props
new file mode 100644
index 000000000..af845dd00
--- /dev/null
+++ b/filter/qa/complex/filter/detection/typeDetection/TypeDetection.props
@@ -0,0 +1,31 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+# UNIX:
+#TestDocumentPath=file:///net/margritte/usr/qaapi/dev/cws/filtercfg/docTypes
+# WINDOWS
+TestDocumentPath=//margritte/qaapi/dev/cws/filtercfg/docTypes
+
+csv.files=files.csv
+csv.preselectedFilter=preselectedFilter.csv
+csv.preselectedType=preselectedType.csv
+csv.serviceName=serviceName.csv
+csv.streamFileTypes=streamFileTypes.csv
+placeHolder=%
+%SO6productname=StarOffice
+%SO6formatversion=6.0
diff --git a/filter/qa/complex/filter/detection/typeDetection/files.csv b/filter/qa/complex/filter/detection/typeDetection/files.csv
new file mode 100644
index 000000000..8e558590b
--- /dev/null
+++ b/filter/qa/complex/filter/detection/typeDetection/files.csv
@@ -0,0 +1,117 @@
+fileAlias;fileURL;defaultFileType;streamFileType
+#**************************************************************
+#** N O T E
+#**
+#** The detection for template filter and writer_text_encoded
+#** will be changed on following childworkspace
+#**
+#**************************************************************
+###################################
+# W R I T E R D O C U M E N T S
+#################################
+rtf1;Writer/AoE2a.rtf;writer_Rich_Text_Format;writer_Rich_Text_Format;writer_Rich_Text_Format
+text1;Writer/Text_DOS.txt;generic_Text;generic_Text
+Word2000_document;Writer/Word2000.doc;writer_MS_Word_97;writer_MS_Word_97
+Word2000_template;Writer/Word2000_template.dot;writer_MS_Word_97_Vorlage;writer_MS_Word_97_Vorlage
+Word6_document;Writer/Word6.doc;writer_MS_WinWord_60;writer_MS_WinWord_60
+Word6_template;Writer/Word6_template.dot;writer_MS_Word_95_Vorlage;writer_MS_Word_95_Vorlage
+Word95_document;Writer/Word95.doc;writer_MS_WinWord_60;writer_MS_WinWord_60
+Word97_document;Writer/Word97.doc;writer_MS_Word_97;writer_MS_Word_97
+Word97_template;Writer/Word97_template.dot;writer_MS_Word_97_Vorlage;writer_MS_Word_97_Vorlage
+WordXP_document;Writer/WordXP.doc;writer_MS_Word_97;writer_MS_Word_97
+WordXP_template;Writer/WordXP_template.dot;writer_MS_Word_97_Vorlage;writer_MS_Word_97_Vorlage
+Writer3_document;Writer/Writer3.sdw;writer_StarWriter_30;writer_StarWriter_30_VorlageTemplate
+Writer3_template;Writer/Writer3_template.vor;writer_StarWriter_30_VorlageTemplate;writer_StarWriter_30_VorlageTemplate
+Writer4_document;Writer/Writer4.sdw;writer_StarWriter_40;writer_StarWriter_40_VorlageTemplate
+Writer4_template;Writer/Writer4_template.vor;writer_StarWriter_40_VorlageTemplate;writer_StarWriter_40_VorlageTemplate
+Writer5_document;Writer/Writer5.sdw;writer_StarWriter_50;writer_StarWriter_50_VorlageTemplate
+Writer5_template;Writer/Writer5_template.vor;writer_StarWriter_50_VorlageTemplate;writer_StarWriter_50_VorlageTemplate
+Writer6_document;Writer/Writer6.sxw;writer_StarOffice_XML_Writer;writer_StarOffice_XML_Writer
+Writer6_template;Writer/Writer6_template.stw;writer_StarOffice_XML_Writer_Template;writer_StarOffice_XML_Writer
+Writer6_html;Writer/WriterWeb.html;generic_HTML;generic_HTML
+ApiPro3;Writer/AmiPro_3x.sam;generic_Text;generic_Text
+Applix;Writer/Applix.aw;generic_Text;generic_Text
+Text2;Writer/Counterstrike I.txt;generic_Text;generic_Text
+FrameMake_document;Writer/FrameMaker.mif;generic_Text;generic_Text
+WordPro_Hangul;Writer/HangulWordPro.hwp;generic_Text;generic_Text
+Ichitaro;Writer/Ichitaro.jtd;writer_JustSystem_Ichitaro_10;writer_JustSystem_Ichitaro_10
+MacWord5_document;Writer/MacWord_5.mcw;generic_Text;generic_Text
+rtf2;Writer/RTF.rtf;writer_Rich_Text_Format;writer_Rich_Text_Format
+wps2000_document;Writer/WPS_2000.wps;writer_WPSSystem_WPS2000_10;writer_WPSSystem_WPS2000_10
+WinWord2_document;Writer/WinWord_2x.doc;generic_Text;generic_Text
+WinWord6_95_document;Writer/WinWord_6_95.doc;writer_MS_WinWord_60;writer_MS_WinWord_60
+WinWord97_2000_XP_document;Writer/Winword_97_2000_xp.doc;writer_MS_Word_97;writer_MS_Word_97
+WordPerfect;Writer/WordPerfect.wpd;generic_Text;generic_Text
+csv2;Writer/Text_CSV.txt;generic_Text;generic_Text
+###################################
+# C A L C D O C U M E N T S
+##################################
+csv1;Calc/Text_CSV.csv;generic_Text;generic_Text
+Calc1;Calc/Calc1.SDC;calc_StarCalc_10;calc_StarCalc_10
+Calc2_document;Calc/Calc3.SDC;calc_StarCalc_30_VorlageTemplate;calc_StarCalc_30
+Calc2_template;Calc/Calc3.vor;calc_StarCalc_30;calc_StarCalc_30
+Calc4_document;Calc/Calc4.sdc;calc_StarCalc_40;calc_StarCalc_40
+Calc4_template;Calc/Calc4.vor;calc_StarCalc_40_VorlageTemplate;calc_StarCalc_40
+Calc5_document;Calc/Calc5.sdc;calc_StarCalc_50;calc_StarCalc_50
+Calc5_template;Calc/Calc5.vor;calc_StarCalc_50_VorlageTemplate;calc_StarCalc_50
+Calc6_document;Calc/Calc_6.stc;calc_StarOffice_XML_Calc;calc_StarOffice_XML_Calc
+Calc6_template;Calc/Calc_6.sxc;calc_StarOffice_XML_Calc_Template;calc_StarOffice_XML_Calc
+dif;Calc/DIF.DIF;calc_DIF;generic_Text
+Excel2;Calc/Excel2.XLS;calc_MS_Excel_40;calc_MS_Excel_40
+Excel3;Calc/Excel3.XLS;calc_MS_Excel_40;calc_MS_Excel_40
+Excel4_document;Calc/Excel4.XLS;calc_MS_Excel_40;calc_MS_Excel_40
+Excel4_template;Calc/Excel4.XLT;calc_MS_Excel_40_VorlageTemplate;calc_MS_Excel_40
+Exel95_document;Calc/Excel5_95.XLS;calc_MS_Excel_5095;calc_MS_Excel_5095
+Exel95_template;Calc/Excel5_template.XLT;calc_MS_Excel_5095;calc_MS_Excel_5095
+Excel97_document;Calc/Excel97_2000_XP.xls;calc_MS_Excel_97;calc_MS_Excel_97
+#Excel97_1dummy;Calc/Excel97_2000_XP.dummy;calc_MS_Excel_97;calc_MS_Excel_97
+Excel97_template;Calc/Excel97_2000_XP.xlt;calc_MS_Excel_97;calc_MS_Excel_97
+Calc_html;Calc/HTML_Calc.html;generic_HTML;generic_HTML
+Calc_rtf;Calc/RTF_StarOffice_Calc.rtf;writer_Rich_Text_Format;writer_Rich_Text_Format
+slk;Calc/SYLK.SLK;calc_SYLK;generic_Text
+Webpagequery;Calc/Webpagequery.html;generic_HTML;generic_HTML
+dbase;Calc/dbase.DBF;calc_dBase;generic_Text
+######################################################
+# D R A W
+######################################################
+draw6_document;Draw/draw1.sxd;draw_StarOffice_XML_Draw;draw_StarOffice_XML_Draw
+draw6_template;Draw/draw2.std;draw_StarOffice_XML_Draw_Template;draw_StarOffice_XML_Draw
+draw5_document;Draw/draw3.sda;draw_StarDraw_50;draw_StarDraw_50_Vorlage
+draw5_template;Draw/draw4.vor;draw_StarDraw_50_Vorlage;draw_StarDraw_50_Vorlage
+draw3_document;Draw/draw5.sdd;draw_StarDraw_30;draw_StarDraw_30
+draw3_template;Draw/draw6.vor;draw_StarDraw_30;draw_StarDraw_30
+######################################################
+# I M P R E S S
+######################################################
+Impress6_document;Impress/imp1.sxi;impress_StarOffice_XML_Impress;impress_StarOffice_XML_Impress
+Impress4_document;Impress/imp10.sdd;impress_StarImpress_40;impress_StarImpress_40
+Impress4_template;Impress/imp11.vor;iimpress_StarImpress_40_Vorlage;impress_StarImpress_40
+Impress6_template;Impress/imp2.sti;impress_StarOffice_XML_Impress_Template;impress_StarOffice_XML_Impress
+PowerPoint97_document;Impress/imp3.ppt;impress_MS_PowerPoint_97;impress_MS_PowerPoint_97
+PowerPoint97_template;Impress/imp4.pot;impress_MS_PowerPoint_97_Vorlage;impress_MS_PowerPoint_97
+DrawImpress6_document;Impress/imp5.sxd;draw_StarOffice_XML_Draw;draw_StarOffice_XML_Draw
+DrawImpress5_document;Impress/imp6.sda;draw_StarDraw_50;draw_StarDraw_50_Vorlage
+DrawImpress3_document;Impress/imp7.sdd;draw_StarDraw_30;draw_StarDraw_30
+Impress5_document;Impress/imp8.sdd;impress_StarImpress_50;impress_StarImpress_50
+Impress5_template;Impress/imp9.vor;impress_StarImpress_50_Vorlage;impress_StarImpress_50
+#######################################################
+# G R A P H I C S
+######################################################
+bitmap;Graphics/pic.bmp;bmp_MS_Windows;bmp_MS_Windows
+emf;Graphics/pic.emf;emf_MS_Windows_Metafile;emf_MS_Windows_Metafile:generic_Text
+eps;Graphics/pic.eps;eps_Encapsulated_PostScript;eps_Encapsulated_PostScript
+gif;Graphics/pic.gif;gif_Graphics_Interchange;gif_Graphics_Interchange
+jpg;Graphics/pic.jpg;jpg_JPEG;jpg_JPEG
+met;Graphics/pic.met;met_OS2_Metafile;met_OS2_Metafile:generic_Text
+pbm;Graphics/pic.pbm;pbm_Portable_Bitmap;pbm_Portable_Bitmap
+pct;Graphics/pic.pct;pct_Mac_Pict;pct_Mac_Pict
+pgm;Graphics/pic.pgm;pgm_Portable_Graymap;pgm_Portable_Graymap
+png;Graphics/pic.png;png_Portable_Network_Graphic;png_Portable_Network_Graphic
+ppm;Graphics/pic.ppm;ppm_Portable_Pixelmap;ppm_Portable_Pixelmap
+ras;Graphics/pic.ras;ras_Sun_Rasterfile;ras_Sun_Rasterfile
+svm;Graphics/pic.svm;svm_StarView_Metafile;svm_StarView_Metafile:generic_Text
+tif;Graphics/pic.tif;tif_Tag_Image_File;tif_Tag_Image_File:generic_Text
+webp;Graphics/pic.webp;webp_WebP;webp_WebP
+wmf;Graphics/pic.wmf;wmf_MS_Windows_Metafile;wmf_MS_Windows_Metafile:generic_Text
+
+
diff --git a/filter/qa/complex/filter/detection/typeDetection/makefile.mk b/filter/qa/complex/filter/detection/typeDetection/makefile.mk
new file mode 100644
index 000000000..94dca18d6
--- /dev/null
+++ b/filter/qa/complex/filter/detection/typeDetection/makefile.mk
@@ -0,0 +1,109 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+PRJ = ..$/..$/..$/..$/..
+PRJNAME = filter
+TARGET = TypeDetection
+PACKAGE = complex$/filter$/detection$/typeDetection
+
+# --- Settings -----------------------------------------------------
+.INCLUDE: settings.mk
+
+
+#----- compile .java files -----------------------------------------
+
+JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar
+JAVAFILES = TypeDetection.java Helper.java
+JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class)
+
+#----- make a jar from compiled files ------------------------------
+
+MAXLINELENGTH = 100000
+
+JARCLASSDIRS = $(PACKAGE)
+JARTARGET = $(TARGET).jar
+JARCOMPRESS = TRUE
+
+# --- Parameters for the test --------------------------------------
+
+# start an office if the parameter is set for the makefile
+.IF "$(OFFICE)" == ""
+CT_APPEXECCOMMAND =
+.ELSE
+CT_APPEXECCOMMAND = -AppExecutionCommand "$(OFFICE)$/soffice --accept=socket,host=localhost,port=8100;urp;"
+.ENDIF
+
+# test base is java complex
+CT_TESTBASE = -TestBase java_complex
+
+# test looks something like the.full.package.TestName
+CT_TEST = -o $(PACKAGE:s\$/\.\).TypeDetection
+
+# start the runner application
+CT_APP = org.openoffice.Runner
+
+# --- Targets ------------------------------------------------------
+
+.IF "$(depend)" == ""
+ CHMOD $(CLASSDIR)$/$(PACKAGE)$/TypeDetection.props \
+ $(CLASSDIR)$/$(PACKAGE)$/preselectedFilter.csv \
+ $(CLASSDIR)$/$(PACKAGE)$/preselectedType.csv \
+ $(CLASSDIR)$/$(PACKAGE)$/serviceName.csv \
+ $(CLASSDIR)$/$(PACKAGE)$/files.csv : ALLTAR
+.ELSE
+ CHMOD $(CLASSDIR)$/$(PACKAGE)$/TypeDetection.props \
+ $(CLASSDIR)$/$(PACKAGE)$/preselectedFilter.csv \
+ $(CLASSDIR)$/$(PACKAGE)$/preselectedType.csv \
+ $(CLASSDIR)$/$(PACKAGE)$/serviceName.csv \
+ $(CLASSDIR)$/$(PACKAGE)$/files.csv : ALLDEP
+.ENDIF
+
+.INCLUDE : target.mk
+
+$(CLASSDIR)$/$(PACKAGE)$/preselectedFilter.csv : preselectedFilter.csv
+ cp preselectedFilter.csv $(CLASSDIR)$/$(PACKAGE)$/preselectedFilter.csv
+ jar uf $(CLASSDIR)$/$(JARTARGET) -C $(CLASSDIR) $(PACKAGE)$/preselectedFilter.csv
+
+$(CLASSDIR)$/$(PACKAGE)$/preselectedType.csv : preselectedType.csv
+ cp preselectedType.csv $(CLASSDIR)$/$(PACKAGE)$/preselectedType.csv
+ jar uf $(CLASSDIR)$/$(JARTARGET) -C $(CLASSDIR) $(PACKAGE)$/preselectedType.csv
+
+$(CLASSDIR)$/$(PACKAGE)$/serviceName.csv : serviceName.csv
+ cp serviceName.csv $(CLASSDIR)$/$(PACKAGE)$/serviceName.csv
+ jar uf $(CLASSDIR)$/$(JARTARGET) -C $(CLASSDIR) $(PACKAGE)$/serviceName.csv
+
+$(CLASSDIR)$/$(PACKAGE)$/files.csv : files.csv
+ cp files.csv $(CLASSDIR)$/$(PACKAGE)$/files.csv
+ jar uf $(CLASSDIR)$/$(JARTARGET) -C $(CLASSDIR) $(PACKAGE)$/files.csv
+
+$(CLASSDIR)$/$(PACKAGE)$/TypeDetection.props : TypeDetection.props
+ cp TypeDetection.props $(CLASSDIR)$/$(PACKAGE)$/TypeDetection.props
+ jar uf $(CLASSDIR)$/$(JARTARGET) -C $(CLASSDIR) $(PACKAGE)$/TypeDetection.props
+
+# --- chmod --------------------------------------------------------
+
+CHMOD :
+ chmod 444 $(CLASSDIR)$/$(PACKAGE)$/*.csv
+ chmod 666 $(CLASSDIR)$/$(PACKAGE)$/*.props
+
+RUN: run
+
+run:
+ java -cp $(CLASSPATH) $(CT_APP) $(CT_TESTBASE) $(CT_APPEXECCOMMAND) $(CT_TEST)
+
+
+
diff --git a/filter/qa/complex/filter/detection/typeDetection/preselectedFilter.csv b/filter/qa/complex/filter/detection/typeDetection/preselectedFilter.csv
new file mode 100644
index 000000000..ccf4d864c
--- /dev/null
+++ b/filter/qa/complex/filter/detection/typeDetection/preselectedFilter.csv
@@ -0,0 +1,6 @@
+fileAlias;FilterName;FilterOptions;FilterData;expectedFileType
+text1;%SO6productname %SO6formatversion Textdokument;;;generic_Text
+csv1;%SO6productname %SO6formatversion Textdokument;;;generic_Text
+csv1;Text - txt - csv (StarCalc);;;generic_Text
+csv2;%SO6productname %SO6formatversion Textdokument;;;generic_Text
+csv2;Text - txt - csv (StarCalc);;;generic_Text
diff --git a/filter/qa/complex/filter/detection/typeDetection/preselectedType.csv b/filter/qa/complex/filter/detection/typeDetection/preselectedType.csv
new file mode 100644
index 000000000..07abce185
--- /dev/null
+++ b/filter/qa/complex/filter/detection/typeDetection/preselectedType.csv
@@ -0,0 +1,6 @@
+fileAlias;preselectFileType;expectFileType
+csv1;generic_Text;generic_Text
+csv1;generic_Text;generic_Text
+#csv2;generic_Text
+#csv2;generic_Text
+text1;generic_Text;generic_Text \ No newline at end of file
diff --git a/filter/qa/complex/filter/detection/typeDetection/serviceName.csv b/filter/qa/complex/filter/detection/typeDetection/serviceName.csv
new file mode 100644
index 000000000..1e174fa85
--- /dev/null
+++ b/filter/qa/complex/filter/detection/typeDetection/serviceName.csv
@@ -0,0 +1,6 @@
+fileAlias;serviceName;expectedType
+text1;com.sun.star.text.FormatDetector
+csv1;com.sun.star.text.FormatDetector;generic_Text
+csv1;com.sun.star.comp.filters.PlainTextFilterDetect;generic_Text
+csv2;com.sun.star.text.FormatDetector;generic_Text
+csv2;com.sun.star.comp.filters.PlainTextFilterDetect;generic_Text
diff --git a/filter/qa/complex/filter/misc/FinalizedMandatoryTest.java b/filter/qa/complex/filter/misc/FinalizedMandatoryTest.java
new file mode 100644
index 000000000..28a71aaab
--- /dev/null
+++ b/filter/qa/complex/filter/misc/FinalizedMandatoryTest.java
@@ -0,0 +1,304 @@
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.filter.misc;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.container.XNameContainer;
+import com.sun.star.container.XNameReplace;
+import com.sun.star.lang.WrappedTargetRuntimeException;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+import com.sun.star.util.XFlushable;
+
+
+/**
+ * This complex test checks the functionality of the properties "Finalized" and "Mandatory" of
+ * the services <CODE>com.sun.star.document.FilterFactory</CODE> and
+ * <CODE>com.sun.star.document.TypeDetection</CODE>.
+ *
+ * Each of these services represent a container of <CODE>PropertyValue[]</CODE>.
+ * The <CODE>PropertyValue[]</CODE> contains among others the properties called
+ * <CODE>Finalized</CODE> and <CODE>Mandatory</CODE>. If the property
+ * <CODE>Finalized</CODE> is set to <CODE>true</CODE>, a filter can be removed
+ * but will not be able to be changed.
+ * If the property <CODE>Mandatory</CODE> is set to <CODE>true</CODE>, the filter
+ * can not be removed.
+ *
+ * Every filter, which is registered to the office, will be tested. For every filter-test
+ * a new instance of the mentioned services will be created.
+
+ * During the test the property <CODE>UIName</CODE>
+ * will be changed and the service will be flushed. The test checks for expected exceptions:
+ * If the property <CODE>Finalized</CODE> equals
+ * <CODE>true</CODE> the tests check if an <CODE>Exception</CODE> must be thrown.
+ * The next step of the test is the removal of the filter was removed, then the service
+ * will be flushed. The test checks for expected exceptions: If the property
+ * <CODE>Mandatory</CODE> equals <CODE>true</CODE>, an <CODE>Exception</CODE> must
+ * be thrown.
+ * This test results <CODE>false</CODE> state if there is no filter available with:
+ * <CODE>Finalized=true</CODE>
+ * <CODE>Finalized=false</CODE>
+ * <CODE>Mandatory=true</CODE>
+ * <CODE>Mandatory=false</CODE>
+ */
+public class FinalizedMandatoryTest
+{
+
+ XMultiServiceFactory xMSF;
+
+ /** Create the environment for following tests.
+ * Use either a component loader from desktop or
+ * from frame
+ * @throws Exception Exception
+ */
+ @Before public void before() throws Exception
+ {
+
+ // create TypeDetection
+ xMSF = getMSF();
+ assertNotNull("Could not get XMultiServiceFactory", xMSF);
+
+ }
+
+ /**
+ * Creates an instance for the given <CODE>serviceName</CODE>
+ * @param serviceName the name of the service which should be created
+ * @throws Exception was thrown if creation fails
+ * @return <CODE>XInterface</CODE> of service
+ */
+ private XInterface getTestObject(String serviceName) throws Exception
+ {
+
+ Object oInterface = xMSF.createInstance(serviceName);
+
+ assertNotNull("Service wasn't created", oInterface);
+ return (XInterface) oInterface;
+ }
+
+ /**
+ * call the function <CODE>checkReadonlySupport</CODE> to test <CODE>com.sun.star.document.FilterFactory</CODE>
+ * @see com.sun.star.document.FilterFactory
+ */
+ @Test public void checkReadonlySupportFilterFactory() throws Exception
+ {
+ checkReadonlySupport("com.sun.star.document.FilterFactory");
+ }
+
+ /*
+ * call the function <CODE>checkReadonlySupport</CODE> to test <CODE>com.sun.star.document.TypeDetection</CODE>
+ * @see com.sun.star.document.TypeDetection
+ */
+ @Test public void checkReadonlySupportTypeDetection() throws Exception
+ {
+ checkReadonlySupport("com.sun.star.document.TypeDetection");
+ }
+
+ /*
+ * test the given service <CODE>serviceName</CODE>.
+ * For every filter a new instance was created and the tests started.
+ * @param serviceName the name of the service to test
+ */
+ private void checkReadonlySupport(String serviceName) throws Exception
+ {
+ System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ System.out.println("testing service '" + serviceName + "'");
+
+ XInterface oObj = null;
+ oObj = getTestObject(serviceName);
+ System.out.println("ImplName: " + util.utils.getImplName(oObj));
+
+ boolean mandatoryTrue = false;
+ boolean mandatoryFalse = false;
+ boolean finalizedTrue = false;
+ boolean finalizedFalse = false;
+
+
+ XNameAccess xNA = UnoRuntime.queryInterface(XNameAccess.class, oObj);
+ String[] filterNames = xNA.getElementNames();
+
+ // XNameContainer; XNameReplace
+ String filterName = filterNames[0];
+ Object[] instance = null;
+
+ for (int i = 0; i < filterNames.length; i++)
+ {
+ System.out.println("------------------------------------------------");
+ filterName = filterNames[i];
+ System.out.println(filterName);
+
+ // testobject must new created for every test.
+ // We change in a loop the container and try to flush this changes.
+ // If we get an expected exception this container is corrupt. It's
+ // similar to a document which could not be saved because of invalid
+ // content. While you don't remove the invalid content you will never
+ // be able to save the document. Same here.
+ oObj = getTestObject(serviceName);
+
+ xNA = UnoRuntime.queryInterface(XNameAccess.class, oObj);
+ XNameContainer xNC = UnoRuntime.queryInterface(XNameContainer.class, oObj);
+ XNameReplace xNR = UnoRuntime.queryInterface(XNameReplace.class, oObj);
+ XFlushable xFlush = UnoRuntime.queryInterface(XFlushable.class, oObj);
+
+ instance = (Object[]) xNA.getByName(filterName);
+ PropertyValue[] props = (PropertyValue[]) instance;
+
+ printPropertyValues(props);
+
+ boolean isMandatory = ((Boolean) getPropertyValueValue(props, "Mandatory")).booleanValue();
+ boolean isFinalized = ((Boolean) getPropertyValueValue(props, "Finalized")).booleanValue();
+
+ // memory if every state is available
+ mandatoryTrue |= isMandatory;
+ mandatoryFalse |= !isMandatory;
+
+ finalizedTrue |= isFinalized;
+ finalizedFalse |= !isFinalized;
+
+ //change the filter
+ setPropertyValueValue((PropertyValue[]) instance, "UIName", "dummy");
+
+ // 1a.) try to change the filter in the container
+ xNR.replaceByName(filterName, instance);
+
+ // 1b.) try to write the changed filter to the configuration.
+ // This must result in an exception if the filter is finalized.
+ boolean flushError = false;
+ try
+ {
+ xFlush.flush();
+ }
+ catch (WrappedTargetRuntimeException e)
+ {
+ flushError = true;
+ assertTrue("Unexpected exception while flushing changed filter '" + filterName + "'", isFinalized);
+ }
+ assertTrue("Expected exception was not thrown while flushing changed filter '" + filterName + "' Finalized:" + isFinalized,
+ !(flushError ^ isFinalized));
+
+
+
+ // 2a.) try to remove the filter from the container
+ xNC.removeByName(filterName);
+ // 1b.) try to write the changed filter to the configuration.
+ // This must result in an exception if the filter is mandatory
+ flushError = false;
+ try
+ {
+ xFlush.flush();
+ }
+ catch (WrappedTargetRuntimeException e)
+ {
+ flushError = true;
+ assertTrue("Unexpected exception while flushing removed filter '" + filterName + "'", isMandatory);
+ }
+ assertTrue("Expected exception was not thrown while flushing removed filter '" + filterName + "' Mandatory:" + isMandatory,
+ !(flushError ^ isMandatory));
+ }
+ String preMsg = "Could not find filter with state ";
+ String postMsg = " Please check if such filter is installed!";
+ assertTrue(preMsg + "'Mandatory=true'" + postMsg, mandatoryTrue);
+ assertTrue(preMsg + "'Mandatory=false'" + postMsg, mandatoryFalse);
+ assertTrue(preMsg + "'Finalized=true'" + postMsg, finalizedTrue);
+ assertTrue(preMsg + "'Finalized=false'" + postMsg, finalizedFalse);
+ }
+
+ /**
+ * print all properties with its values to <CODE>logger</CODE>. For debug purposes.
+ * @see stats.SimpleLogWriter
+ * @see com.sun.star.beans.PropertyValue
+ * @param props Sequence of PropertyValue
+ */
+ protected void printPropertyValues(PropertyValue[] props)
+ {
+ int i = 0;
+ while (i < props.length)
+ {
+ System.out.println(props[i].Name + ":" + props[i].Value.toString());
+ i++;
+ }
+ if (i < props.length)
+ {
+ System.out.println(props[i].Name + ":" + props[i].Value.toString());
+ }
+ }
+
+ /**
+ * returns the value of the specified (<CODE>pName</CODE>) property from a sequence of <CODE>PropertyValue</CODE>
+ * @param props a sequence of <CODE>PropertyValue</CODE>
+ * @param pName the name of the property the value should be returned
+ * @return the value of the property
+ */
+ protected Object getPropertyValueValue(PropertyValue[] props, String pName)
+ {
+ int i = 0;
+ while (i < props.length && !props[i].Name.equals(pName))
+ {
+ i++;
+ }
+ return i < props.length ? props[i].Value : null;
+ }
+
+ /**
+ * set a value of the specified (<CODE>pName</CODE>) property inside a sequence of <CODE>PropertyValue</CODE>
+ * @param props sequence of <CODE>PropertyValue</CODE>
+ * @param pName name of the property which should be changed
+ * @param pValue the value the property should be assigned
+ */
+ protected void setPropertyValueValue(PropertyValue[] props, String pName, Object pValue)
+ {
+ int i = 0;
+ while (i < props.length && !props[i].Name.equals(pName))
+ {
+ i++;
+ }
+ props[i].Value = pValue;
+ }
+
+ private XMultiServiceFactory getMSF()
+ {
+ return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager());
+ }
+
+ // setup and close connections
+ @BeforeClass
+ public static void setUpConnection() throws Exception
+ {
+ System.out.println("setUpConnection()");
+ connection.setUp();
+ }
+
+ @AfterClass
+ public static void tearDownConnection()
+ throws InterruptedException, com.sun.star.uno.Exception
+ {
+ System.out.println("tearDownConnection()");
+ connection.tearDown();
+ }
+ private static final OfficeConnection connection = new OfficeConnection();
+}
diff --git a/filter/qa/complex/filter/misc/TypeDetection6FileFormat.java b/filter/qa/complex/filter/misc/TypeDetection6FileFormat.java
new file mode 100644
index 000000000..009fd52cf
--- /dev/null
+++ b/filter/qa/complex/filter/misc/TypeDetection6FileFormat.java
@@ -0,0 +1,127 @@
+/*
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+package complex.filter.misc;
+
+import com.sun.star.container.XNameAccess;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+
+import util.utils;
+
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+
+
+public class TypeDetection6FileFormat
+{
+
+ XMultiServiceFactory xMSF;
+
+ /** Create the environment for following tests.
+ * Use either a component loader from desktop or
+ * from frame
+ * @throws Exception Exception
+ */
+ @Before public void before() throws Exception
+ {
+ xMSF = getMSF();
+ assertNotNull("Could not get XMultiServiceFactory", xMSF);
+ }
+
+ /**
+ * call the function <CODE>checkFileFormatSupport</CODE> to test <CODE>com.sun.star.document.FilterFactory</CODE>
+ * @see com.sun.star.document.FilterFactory
+ */
+ @Test public void checkFilterFactory() throws Exception
+ {
+ checkFileFormatSupport("com.sun.star.document.FilterFactory");
+ }
+
+ /**
+ * call the function <CODE>checkFileFormatSupport</CODE> to test <CODE>com.sun.star.document.TypeDetection</CODE>
+ * @see com.sun.star.document.TypeDetection
+ */
+ @Test public void checkTypeDetection() throws Exception
+ {
+ checkFileFormatSupport("com.sun.star.document.TypeDetection");
+ }
+
+ /**
+ * test the given service <CODE>serviceName</CODE>.
+ * The serve was created and the filter 'TypeDetection6FileFormat' was searched
+ * @param serviceName the name of the service to test
+ */
+ private void checkFileFormatSupport(String serviceName) throws Exception
+ {
+ System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+ System.out.println("testing service '" + serviceName + "'");
+
+ XInterface oObj = null;
+ oObj = getTestObject(serviceName);
+ System.out.println("ImplName: " + utils.getImplName(oObj));
+ XNameAccess xNA = UnoRuntime.queryInterface(XNameAccess.class, oObj);
+ String msg = "Could not find filter 'TypeDetection6FileFormat'!";
+ msg += "\nMaybe 'TypeDetection6FileFormat.xcu' is not registered.";
+ assertTrue(msg, xNA.hasByName("TypeDetection6FileFormat"));
+ }
+
+ /**
+ * Creates an instance for the given <CODE>serviceName</CODE>
+ * @param serviceName the name of the service which should be created
+ * @throws Exception was thrown if creation fails
+ * @return <CODE>XInterface</CODE> of service
+ */
+ public XInterface getTestObject(String serviceName) throws Exception
+ {
+
+ Object oInterface = xMSF.createInstance(serviceName);
+
+ if (oInterface == null)
+ {
+ fail("Service wasn't created");
+ throw new Exception("could not create service '" + serviceName + "'");
+ }
+ return (XInterface) oInterface;
+ }
+
+ private XMultiServiceFactory getMSF()
+ {
+ return UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager());
+ }
+
+ // setup and close connections
+ @BeforeClass public static void setUpConnection() throws Exception {
+ System.out.println("setUpConnection()");
+ connection.setUp();
+ }
+
+ @AfterClass public static void tearDownConnection()
+ throws InterruptedException, com.sun.star.uno.Exception
+ {
+ System.out.println("tearDownConnection()");
+ connection.tearDown();
+ }
+
+ private static final OfficeConnection connection = new OfficeConnection();
+
+}
diff --git a/filter/qa/complex/filter/misc/TypeDetection6FileFormat.xcu b/filter/qa/complex/filter/misc/TypeDetection6FileFormat.xcu
new file mode 100644
index 000000000..2206e6942
--- /dev/null
+++ b/filter/qa/complex/filter/misc/TypeDetection6FileFormat.xcu
@@ -0,0 +1,42 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<?xml version="1.0" encoding="UTF-8"?>
+<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="TypeDetection" oor:package="org.openoffice.Office">
+ <node oor:name="Types">
+ <node oor:name="TypeDetection6FileFormat" oor:op="replace">
+ <prop oor:name="UIName">
+ <value xml:lang="x-no-translate">TypeDetection 6 FileFormat</value>
+ <value xml:lang="en-US">TypeDetection 6 FileFormat</value>
+ </prop>
+ <prop oor:name="Data">
+ <value>1,,,,,,</value>
+ </prop>
+ </node>
+ </node>
+ <node oor:name="Filters">
+ <node oor:name="TypeDetection6FileFormat" oor:op="replace">
+ <prop oor:name="UIName">
+ <value xml:lang="x-no-translate">FilterFactory 6 FileFormat</value>
+ <value xml:lang="en-US">FilterFactory 6 FileFormat</value>
+ </prop>
+ <prop oor:name="Data">
+ <value>0,TypeDetection6FileFormat,,,,,</value>
+ </prop>
+ </node>
+ </node>
+</oor:component-data>
diff --git a/filter/qa/cppunit/data/xslt/copy.xslt b/filter/qa/cppunit/data/xslt/copy.xslt
new file mode 100644
index 000000000..d46172a41
--- /dev/null
+++ b/filter/qa/cppunit/data/xslt/copy.xslt
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+<xsl:template match="/">
+ <xsl:copy-of select="/"/>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/qa/cppunit/msfilter-test.cxx b/filter/qa/cppunit/msfilter-test.cxx
new file mode 100644
index 000000000..439aad88b
--- /dev/null
+++ b/filter/qa/cppunit/msfilter-test.cxx
@@ -0,0 +1,76 @@
+/* -*- 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 <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <sal/types.h>
+#include <tools/color.hxx>
+#include <filter/msfilter/util.hxx>
+
+#include <unotest/bootstrapfixturebase.hxx>
+
+namespace {
+
+class MSFilterTest
+ : public test::BootstrapFixtureBase
+{
+public:
+ void testTransColToIco();
+
+ CPPUNIT_TEST_SUITE(MSFilterTest);
+ CPPUNIT_TEST(testTransColToIco);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void MSFilterTest::testTransColToIco()
+{
+ const sal_uInt32 aStdCol[] = {
+ 0xeeeeee, 0xffff99, 0xff6600, 0xff3333, 0xff00cc, 0xff33ff, 0x9900ff, 0x6666ff, 0x00ccff, 0x66ffff, 0x33ff99, 0x99ff66, 0xccff00,
+ 0xdddddd, 0xffff66, 0xffcc00, 0xff9999, 0xff66cc, 0xff99ff, 0xcc66ff, 0x9999ff, 0x9999ff, 0x99ffff, 0x66ff99, 0x99ff99, 0xccff66,
+ 0xcccccc, 0xffff00, 0xff9900, 0xff6666, 0xff3399, 0xff66ff, 0x9933ff, 0x3333ff, 0x3399ff, 0x00ffff, 0x00ff66, 0x66ff66, 0x99ff33,
+ 0xb2b2b2, 0xcc9900, 0xff3300, 0xff0000, 0xff0066, 0xff00ff, 0x6600ff, 0x0000ff, 0x0066ff, 0x00cccc, 0x00cc33, 0x00cc00, 0x66ff00,
+ 0x999999, 0x996600, 0xcc3300, 0xcc0000, 0xcc0066, 0xcc00cc, 0x6600cc, 0x0000cc, 0x0066cc, 0x009999, 0x009933, 0x009900, 0x66cc00,
+ 0x808080, 0x663300, 0x801900, 0x990000, 0x990066, 0x990099, 0x330099, 0x000099, 0x006699, 0x006666, 0x007826, 0x006600, 0x669900,
+ 0x666666, 0x333300, 0x461900, 0x330000, 0x330033, 0x660066, 0x000033, 0x000066, 0x000080, 0x003333, 0x00331a, 0x003300, 0x193300,
+ 0x333333, 0x666633, 0x661900, 0x663333, 0x660033, 0x663366, 0x330066, 0x333366, 0x003366, 0x336666, 0x006633, 0x336633, 0x336600 };
+
+ const sal_uInt16 aExpected[] = {
+ 8, 7, 6, 6, 5, 5, 5, 2, 3, 3, 10, 4, 7,
+ 16, 7, 7, 6, 5, 5, 5, 2, 2, 3, 4, 4, 7,
+ 16, 7, 7, 6, 12, 5, 12, 2, 10, 3, 4, 4, 14,
+ 16, 14, 6, 6, 6, 5, 2, 2, 2, 3, 4, 4, 4,
+ 15, 14, 6, 6, 12, 5, 12, 2, 10, 10, 11, 11, 14,
+ 15, 1, 13, 13, 12, 12, 9, 9, 10, 10, 11, 11, 14,
+ 15, 14, 13, 13, 12, 12, 9, 9, 9, 10, 10, 11, 11,
+ 1, 14, 13, 13, 1, 12, 1, 9, 1, 10, 1, 11, 1 };
+
+ for( size_t i = 0; i < SAL_N_ELEMENTS(aStdCol); ++i)
+ {
+ const OString sMessage = "Index of unmatched color: " + OString::number(i);
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(sMessage.getStr(), aExpected[i],
+ static_cast<sal_uInt16>(msfilter::util::TransColToIco( Color(ColorTransparency, aStdCol[i]) )));
+ }
+
+ // tdf#92471
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), static_cast<sal_uInt16>(msfilter::util::TransColToIco( Color( 0x6666ff ))));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), static_cast<sal_uInt16>(msfilter::util::TransColToIco( Color( 0x6566ff ))));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), static_cast<sal_uInt16>(msfilter::util::TransColToIco( Color( 0x6665ff ))));
+ CPPUNIT_ASSERT_EQUAL(sal_uInt16(2), static_cast<sal_uInt16>(msfilter::util::TransColToIco( Color( 0x6666fe ))));
+
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(MSFilterTest);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/qa/cppunit/priority-test.cxx b/filter/qa/cppunit/priority-test.cxx
new file mode 100644
index 000000000..18e63c318
--- /dev/null
+++ b/filter/qa/cppunit/priority-test.cxx
@@ -0,0 +1,85 @@
+/* -*- 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/.
+ */
+
+// Unit test to check that we get the right filters for the right extensions.
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <sal/types.h>
+
+#include <com/sun/star/document/XTypeDetection.hpp>
+#include <comphelper/processfactory.hxx>
+
+#include <unotest/bootstrapfixturebase.hxx>
+
+
+using namespace css;
+
+namespace {
+
+class PriorityFilterTest
+ : public test::BootstrapFixtureBase
+{
+public:
+ void testPriority();
+
+ CPPUNIT_TEST_SUITE(PriorityFilterTest);
+ CPPUNIT_TEST(testPriority);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void PriorityFilterTest::testPriority()
+{
+ uno::Reference<document::XTypeDetection> xDetection(
+ comphelper::getProcessServiceFactory()->createInstance("com.sun.star.document.TypeDetection"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_MESSAGE("No type detection component", xDetection.is());
+
+ static struct {
+ const char *pURL;
+ const char *pFormat;
+ } const aToCheck[] = {
+ { "file:///tmp/foo.xls", "calc_MS_Excel_97" }
+ // TODO: expand this to check more of these priorities
+ };
+
+ for (size_t i = 0; i < SAL_N_ELEMENTS(aToCheck); i++)
+ {
+ OUString aURL = OUString::createFromAscii(aToCheck[i].pURL);
+ try
+ {
+ OUString aTypeName = xDetection->queryTypeByURL(aURL);
+
+ OUString aFormatCorrect = OUString::createFromAscii(aToCheck[i].pFormat);
+ OUString aMsg = "Mis-matching formats "
+ "'" +
+ aTypeName +
+ "' should be '" +
+ aFormatCorrect +
+ "'";
+ CPPUNIT_ASSERT_EQUAL_MESSAGE(OUStringToOString(aMsg,
+ RTL_TEXTENCODING_UTF8).getStr(),
+ aFormatCorrect, aTypeName);
+ }
+ catch (const uno::Exception &e)
+ {
+ OUString aMsg = "Exception querying for type: '" + e.Message + "'";
+ CPPUNIT_FAIL(OUStringToOString(aMsg, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ }
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PriorityFilterTest);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/qa/cppunit/xslt-test.cxx b/filter/qa/cppunit/xslt-test.cxx
new file mode 100644
index 000000000..4e0c621d6
--- /dev/null
+++ b/filter/qa/cppunit/xslt-test.cxx
@@ -0,0 +1,207 @@
+/* -*- 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 <sal/config.h>
+
+#include <condition_variable>
+#include <mutex>
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/plugin/TestPlugIn.h>
+
+#include <sal/types.h>
+#include <sal/log.hxx>
+
+#include <rtl/ref.hxx>
+
+#include <osl/file.hxx>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/io/XStreamListener.hpp>
+#include <com/sun/star/ucb/SimpleFileAccess.hpp>
+#include <com/sun/star/xml/xslt/XSLTTransformer.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+#include <test/bootstrapfixture.hxx>
+
+
+using namespace ::com::sun::star;
+
+
+namespace {
+
+class XsltFilterTest
+ : public test::BootstrapFixture
+{
+public:
+ void testXsltCopyOld();
+ void testXsltCopyNew();
+
+ CPPUNIT_TEST_SUITE(XsltFilterTest);
+ CPPUNIT_TEST(testXsltCopyOld);
+ CPPUNIT_TEST(testXsltCopyNew);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+class Listener : public ::cppu::WeakImplHelper<io::XStreamListener>
+{
+public:
+ Listener() : m_bDone(false) {}
+
+ void wait() {
+ std::unique_lock<std::mutex> g(m_mutex);
+ m_cond.wait(g, [this]() { return m_bDone; });
+ }
+
+private:
+ std::mutex m_mutex;
+ std::condition_variable m_cond;
+ bool m_bDone;
+
+ virtual void SAL_CALL disposing(const lang::EventObject&) noexcept override {}
+ virtual void SAL_CALL started() noexcept override {}
+ virtual void SAL_CALL closed() noexcept override { notifyDone(); }
+ virtual void SAL_CALL terminated() noexcept override { notifyDone(); }
+ virtual void SAL_CALL error(const uno::Any& e) override
+ {
+ notifyDone(); // set on error too, otherwise main thread waits forever
+ SAL_WARN("filter.xslt", e);
+ CPPUNIT_FAIL("exception while in XSLT");
+ }
+
+ void notifyDone() {
+ std::scoped_lock<std::mutex> g(m_mutex);
+ m_bDone = true;
+ m_cond.notify_all();
+ }
+};
+
+void XsltFilterTest::testXsltCopyNew()
+{
+ OUString tempDirURL;
+ osl_getTempDirURL(&tempDirURL.pData);
+ oslFileHandle tempFile;
+ OUString tempURL;
+ osl::File::RC rc = osl::File::createTempFile(nullptr, &tempFile, &tempURL);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, rc);
+ osl_closeFile(tempFile); // close it so xSFA can open it on WNT
+
+ OUString source(
+ m_directories.getURLFromSrc(u"/filter/source/xsltfilter/xsltfilter.component"));
+ uno::Sequence<uno::Any> args{
+ uno::Any(beans::NamedValue("StylesheetURL",
+ uno::Any(m_directories.getURLFromSrc(u"/filter/qa/cppunit/data/xslt/copy.xslt")))),
+ uno::Any(beans::NamedValue("SourceURL", uno::Any(source))),
+ uno::Any(beans::NamedValue("TargetURL", uno::Any(tempURL))),
+ uno::Any(beans::NamedValue("SourceBaseURL",
+ uno::Any(m_directories.getURLFromSrc(u"/filter/source/xsltfilter/")))),
+ uno::Any(beans::NamedValue("TargetBaseURL", uno::Any(tempDirURL))),
+ uno::Any(beans::NamedValue("SystemType", uno::Any(OUString()))),
+ uno::Any(beans::NamedValue("PublicType", uno::Any(OUString())))
+ };
+
+ uno::Reference<ucb::XSimpleFileAccess3> xSFA =
+ ucb::SimpleFileAccess::create(getComponentContext());
+
+ uno::Reference<io::XInputStream> xIn = xSFA->openFileRead(source);
+ uno::Reference<io::XOutputStream> xOut = xSFA->openFileWrite(tempURL);
+
+ rtl::Reference<Listener> xListener = new Listener();
+
+ uno::Reference<xml::xslt::XXSLTTransformer> xXslt(
+ xml::xslt::XSLTTransformer::create(getComponentContext(), args));
+
+ xXslt->addListener(xListener);
+ xXslt->setInputStream(xIn);
+ xXslt->setOutputStream(xOut);
+
+ xXslt->start();
+
+ xListener->wait();
+
+ xIn->closeInput();
+ xOut->closeOutput();
+
+ osl::File foo(tempURL); // apparently it's necessary to open it again?
+ foo.open(osl_File_OpenFlag_Read);
+ sal_uInt64 size(0);
+ foo.getSize(size);
+ CPPUNIT_ASSERT(size > 1000); // check that something happened
+ foo.close();
+ osl_removeFile(tempURL.pData);
+}
+
+void XsltFilterTest::testXsltCopyOld()
+{
+ OUString tempDirURL;
+ osl_getTempDirURL(&tempDirURL.pData);
+ oslFileHandle tempFile;
+ OUString tempURL;
+ osl::File::RC rc = osl::File::createTempFile(nullptr, &tempFile, &tempURL);
+ CPPUNIT_ASSERT_EQUAL(osl::FileBase::E_None, rc);
+ osl_closeFile(tempFile); // close it so xSFA can open it on WNT
+
+ OUString source(
+ m_directories.getURLFromSrc(u"/filter/source/xsltfilter/xsltfilter.component"));
+ uno::Sequence<uno::Any> args{
+ uno::Any(beans::NamedValue("StylesheetURL",
+ uno::Any(m_directories.getURLFromSrc(u"/filter/qa/cppunit/data/xslt/copy.xslt")))),
+ uno::Any(beans::NamedValue("SourceURL", uno::Any(source))),
+ uno::Any(beans::NamedValue("TargetURL", uno::Any(tempURL))),
+ uno::Any(beans::NamedValue("SourceBaseURL",
+ uno::Any(m_directories.getURLFromSrc(u"/filter/source/xsltfilter/")))),
+ uno::Any(beans::NamedValue("TargetBaseURL", uno::Any(tempDirURL))),
+ uno::Any(beans::NamedValue("SystemType", uno::Any(OUString()))),
+ uno::Any(beans::NamedValue("PublicType", uno::Any(OUString())))
+ };
+
+ uno::Reference<ucb::XSimpleFileAccess3> xSFA =
+ ucb::SimpleFileAccess::create(getComponentContext());
+
+ uno::Reference<io::XInputStream> xIn = xSFA->openFileRead(source);
+ uno::Reference<io::XOutputStream> xOut = xSFA->openFileWrite(tempURL);
+
+ rtl::Reference<Listener> xListener = new Listener();
+
+ uno::Reference<xml::xslt::XXSLTTransformer> xXslt(
+ getMultiServiceFactory()->createInstance(
+ "com.sun.star.comp.documentconversion.LibXSLTTransformer"),
+ uno::UNO_QUERY_THROW);
+
+ uno::Reference<lang::XInitialization> xInit(xXslt, uno::UNO_QUERY_THROW);
+ xInit->initialize(args);
+ xXslt->addListener(xListener);
+ xXslt->setInputStream(xIn);
+ xXslt->setOutputStream(xOut);
+
+ xXslt->start();
+
+ xListener->wait();
+
+ xIn->closeInput();
+ xOut->closeOutput();
+
+ osl::File foo(tempURL); // apparently it's necessary to open it again?
+ foo.open(osl_File_OpenFlag_Read);
+ sal_uInt64 size(0);
+ foo.getSize(size);
+ CPPUNIT_ASSERT(size > 1000); // check that something happened
+ foo.close();
+ osl_removeFile(tempURL.pData);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(XsltFilterTest);
+
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/qa/data/picture.pdf b/filter/qa/data/picture.pdf
new file mode 100644
index 000000000..79af2b349
--- /dev/null
+++ b/filter/qa/data/picture.pdf
Binary files differ
diff --git a/filter/qa/pdf.cxx b/filter/qa/pdf.cxx
new file mode 100644
index 000000000..ec5460b9f
--- /dev/null
+++ b/filter/qa/pdf.cxx
@@ -0,0 +1,347 @@
+/* -*- 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 <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <tools/stream.hxx>
+#include <unotools/streamwrap.hxx>
+#include <vcl/filter/PDFiumLibrary.hxx>
+#include <tools/helpers.hxx>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+/// Covers filter/source/pdf/ fixes.
+class Test : public test::BootstrapFixture, public unotest::MacrosTest
+{
+private:
+ uno::Reference<lang::XComponent> mxComponent;
+
+public:
+ void setUp() override;
+ void tearDown() override;
+ uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
+};
+
+void Test::setUp()
+{
+ test::BootstrapFixture::setUp();
+ MacrosTest::setUpNssGpg(m_directories, "filter_pdf");
+
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+}
+
+void Test::tearDown()
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+
+ test::BootstrapFixture::tearDown();
+}
+
+constexpr OUStringLiteral DATA_DIRECTORY = u"/filter/qa/data/";
+
+CPPUNIT_TEST_FIXTURE(Test, testSignCertificateSubjectName)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ return;
+
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxComponentContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
+ = xSecurityContext->getSecurityEnvironment();
+ uno::Sequence<beans::PropertyValue> aFilterData{
+ comphelper::makePropertyValue("SignPDF", true),
+ comphelper::makePropertyValue(
+ "SignCertificateSubjectName",
+ OUString(
+ "CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA Test,ST=England,C=UK")),
+ };
+ if (!GetValidCertificate(xSecurityEnvironment->getPersonalCertificates(), aFilterData))
+ {
+ return;
+ }
+
+ // Given an empty document:
+ getComponent().set(
+ loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"));
+
+ // When exporting to PDF, and referring to a certificate using a subject name:
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory = getMultiServiceFactory();
+ uno::Reference<document::XFilter> xFilter(
+ xFactory->createInstance("com.sun.star.document.PDFFilter"), uno::UNO_QUERY);
+ uno::Reference<document::XExporter> xExporter(xFilter, uno::UNO_QUERY);
+ xExporter->setSourceDocument(getComponent());
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
+
+ uno::Sequence<beans::PropertyValue> aDescriptor{
+ comphelper::makePropertyValue("FilterName", OUString("writer_pdf_Export")),
+ comphelper::makePropertyValue("FilterData", aFilterData),
+ comphelper::makePropertyValue("OutputStream", xOutputStream),
+ };
+ xFilter->filter(aDescriptor);
+
+ // Then make sure the resulting PDF has a signature:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPDFium->openDocument(aStream.GetData(), aStream.GetSize(), OString());
+ // Without the accompanying fix in place, this test would have failed, as signing was enabled
+ // without configuring a certificate, so the whole export failed.
+ CPPUNIT_ASSERT(pPdfDocument);
+ CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getSignatureCount());
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testPdfDecompositionSize)
+{
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ return;
+
+ // Given an empty Writer document:
+ getComponent().set(
+ loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"));
+
+ // When inserting a 267 points wide PDF image into the document:
+ uno::Sequence<beans::PropertyValue> aArgs = {
+ comphelper::makePropertyValue("FileName",
+ m_directories.getURLFromSrc(DATA_DIRECTORY) + "picture.pdf"),
+ };
+ dispatchCommand(getComponent(), ".uno:InsertGraphic", aArgs);
+
+ // Then make sure that its size is correct:
+ uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(getComponent(), uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> xDrawPage = xDrawPageSupplier->getDrawPage();
+ uno::Reference<beans::XPropertySet> xShape(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+ auto xGraphic = xShape->getPropertyValue("Graphic").get<uno::Reference<graphic::XGraphic>>();
+ CPPUNIT_ASSERT(xGraphic.is());
+ Graphic aGraphic(xGraphic);
+ basegfx::B2DRange aRange = aGraphic.getVectorGraphicData()->getRange();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 9437
+ // - Actual : 34176
+ // i.e. the width was too large, it used all width of the body frame.
+ // 9437 mm100 is 267.507 points from the file.
+#if defined MACOSX
+ // TODO the bitmap size is larger (75486) on macOS, but that should not affect the logic size.
+ (void)aRange;
+#else
+ // Unfortunately, this test is DPI-dependent.
+ // Use some allowance (~1/2 pt) to let it pass on non-default DPI.
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(9437, aRange.getWidth(), 20.0);
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testWatermarkColor)
+{
+ // Given an empty Writer document:
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ return;
+ getComponent().set(
+ loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"));
+
+ // When exporting that as PDF with a red watermark:
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory = getMultiServiceFactory();
+ uno::Reference<document::XFilter> xFilter(
+ xFactory->createInstance("com.sun.star.document.PDFFilter"), uno::UNO_QUERY);
+ uno::Reference<document::XExporter> xExporter(xFilter, uno::UNO_QUERY);
+ xExporter->setSourceDocument(getComponent());
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
+ uno::Sequence<beans::PropertyValue> aFilterData{
+ comphelper::makePropertyValue("Watermark", OUString("X")),
+ comphelper::makePropertyValue("WatermarkColor", static_cast<sal_Int32>(0xff0000)),
+ };
+ uno::Sequence<beans::PropertyValue> aDescriptor{
+ comphelper::makePropertyValue("FilterName", OUString("writer_pdf_Export")),
+ comphelper::makePropertyValue("FilterData", aFilterData),
+ comphelper::makePropertyValue("OutputStream", xOutputStream),
+ };
+ xFilter->filter(aDescriptor);
+
+ // Then make sure that the watermark color is correct:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPDFium->openDocument(aStream.GetData(), aStream.GetSize(), OString());
+ CPPUNIT_ASSERT(pPdfDocument);
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPage = pPdfDocument->openPage(0);
+ CPPUNIT_ASSERT_EQUAL(1, pPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(1, pPageObject->getFormObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject = pPageObject->getFormObject(0);
+ Color aFillColor = pFormObject->getFillColor();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: rgba[ff0000ff]
+ // - Actual : rgba[00ff00ff]
+ // i.e. the color was the (default) green, not red.
+ CPPUNIT_ASSERT_EQUAL(Color(ColorTransparency, 0xff0000), aFillColor);
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testWatermarkFontHeight)
+{
+ // Given an empty Writer document:
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ return;
+ getComponent().set(
+ loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"));
+
+ // When exporting that as PDF with a 100pt-sized watermark:
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory = getMultiServiceFactory();
+ uno::Reference<document::XFilter> xFilter(
+ xFactory->createInstance("com.sun.star.document.PDFFilter"), uno::UNO_QUERY);
+ uno::Reference<document::XExporter> xExporter(xFilter, uno::UNO_QUERY);
+ xExporter->setSourceDocument(getComponent());
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
+ sal_Int32 nExpectedFontSize = 100;
+ uno::Sequence<beans::PropertyValue> aFilterData{
+ comphelper::makePropertyValue("Watermark", OUString("X")),
+ comphelper::makePropertyValue("WatermarkFontHeight", nExpectedFontSize),
+ };
+ uno::Sequence<beans::PropertyValue> aDescriptor{
+ comphelper::makePropertyValue("FilterName", OUString("writer_pdf_Export")),
+ comphelper::makePropertyValue("FilterData", aFilterData),
+ comphelper::makePropertyValue("OutputStream", xOutputStream),
+ };
+ xFilter->filter(aDescriptor);
+
+ // Then make sure that the watermark font size is correct:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPDFium->openDocument(aStream.GetData(), aStream.GetSize(), OString());
+ CPPUNIT_ASSERT(pPdfDocument);
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPage = pPdfDocument->openPage(0);
+ CPPUNIT_ASSERT_EQUAL(1, pPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(1, pPageObject->getFormObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject = pPageObject->getFormObject(0);
+ sal_Int32 nFontSize = pFormObject->getFontSize();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 100
+ // - Actual : 594
+ // i.e. the font size was automatic, could not specify an explicit size.
+ CPPUNIT_ASSERT_EQUAL(nExpectedFontSize, nFontSize);
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testWatermarkFontName)
+{
+ // Given an empty Writer document:
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ return;
+ getComponent().set(
+ loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"));
+
+ // When exporting that as PDF with a serif watermark:
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory = getMultiServiceFactory();
+ uno::Reference<document::XFilter> xFilter(
+ xFactory->createInstance("com.sun.star.document.PDFFilter"), uno::UNO_QUERY);
+ uno::Reference<document::XExporter> xExporter(xFilter, uno::UNO_QUERY);
+ xExporter->setSourceDocument(getComponent());
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
+ OUString aExpectedFontName("Liberation Serif");
+ uno::Sequence<beans::PropertyValue> aFilterData{
+ comphelper::makePropertyValue("Watermark", OUString("X")),
+ comphelper::makePropertyValue("WatermarkFontName", aExpectedFontName),
+ };
+ uno::Sequence<beans::PropertyValue> aDescriptor{
+ comphelper::makePropertyValue("FilterName", OUString("writer_pdf_Export")),
+ comphelper::makePropertyValue("FilterData", aFilterData),
+ comphelper::makePropertyValue("OutputStream", xOutputStream),
+ };
+ xFilter->filter(aDescriptor);
+
+ // Then make sure that the watermark font name is correct:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPDFium->openDocument(aStream.GetData(), aStream.GetSize(), OString());
+ CPPUNIT_ASSERT(pPdfDocument);
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPage = pPdfDocument->openPage(0);
+ CPPUNIT_ASSERT_EQUAL(1, pPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(1, pPageObject->getFormObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject = pPageObject->getFormObject(0);
+ OUString aFontName = pFormObject->getFontName();
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: Liberation Serif
+ // - Actual : Helvetica
+ // i.e. the font name was sans, could not specify an explicit name.
+ CPPUNIT_ASSERT_EQUAL(aExpectedFontName, aFontName);
+}
+
+CPPUNIT_TEST_FIXTURE(Test, testWatermarkRotateAngle)
+{
+ // Given an empty Writer document:
+ std::shared_ptr<vcl::pdf::PDFium> pPDFium = vcl::pdf::PDFiumLibrary::get();
+ if (!pPDFium)
+ return;
+ getComponent().set(
+ loadFromDesktop("private:factory/swriter", "com.sun.star.text.TextDocument"));
+
+ // When exporting that as PDF with a rotated watermark:
+ uno::Reference<css::lang::XMultiServiceFactory> xFactory = getMultiServiceFactory();
+ uno::Reference<document::XFilter> xFilter(
+ xFactory->createInstance("com.sun.star.document.PDFFilter"), uno::UNO_QUERY);
+ uno::Reference<document::XExporter> xExporter(xFilter, uno::UNO_QUERY);
+ xExporter->setSourceDocument(getComponent());
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));
+ // 45.0 degrees, counter-clockwise.
+ sal_Int32 nExpectedRotateAngle = 45;
+ uno::Sequence<beans::PropertyValue> aFilterData{
+ comphelper::makePropertyValue("Watermark", OUString("X")),
+ comphelper::makePropertyValue("WatermarkRotateAngle", nExpectedRotateAngle * 10),
+ };
+ uno::Sequence<beans::PropertyValue> aDescriptor{
+ comphelper::makePropertyValue("FilterName", OUString("writer_pdf_Export")),
+ comphelper::makePropertyValue("FilterData", aFilterData),
+ comphelper::makePropertyValue("OutputStream", xOutputStream),
+ };
+ xFilter->filter(aDescriptor);
+
+ // Then make sure that the watermark rotation angle is correct:
+ std::unique_ptr<vcl::pdf::PDFiumDocument> pPdfDocument
+ = pPDFium->openDocument(aStream.GetData(), aStream.GetSize(), OString());
+ CPPUNIT_ASSERT(pPdfDocument);
+ std::unique_ptr<vcl::pdf::PDFiumPage> pPage = pPdfDocument->openPage(0);
+ CPPUNIT_ASSERT_EQUAL(1, pPage->getObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pPageObject = pPage->getObject(0);
+ CPPUNIT_ASSERT_EQUAL(1, pPageObject->getFormObjectCount());
+ std::unique_ptr<vcl::pdf::PDFiumPageObject> pFormObject = pPageObject->getFormObject(0);
+ basegfx::B2DHomMatrix aMatrix = pFormObject->getMatrix();
+ basegfx::B2DTuple aScale;
+ basegfx::B2DTuple aTranslate;
+ double fRotate{};
+ double fShearX{};
+ aMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
+ sal_Int32 nActualRotateAngle = NormAngle360(basegfx::rad2deg<1>(fRotate));
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 45
+ // - Actual : 270
+ // i.e. the rotation angle was 270 for an A4 page, not the requested 45 degrees.
+ CPPUNIT_ASSERT_EQUAL(nExpectedRotateAngle, nActualRotateAngle);
+}
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/qa/unit/data/TransparentText.odg b/filter/qa/unit/data/TransparentText.odg
new file mode 100644
index 000000000..d3027d17d
--- /dev/null
+++ b/filter/qa/unit/data/TransparentText.odg
Binary files differ
diff --git a/filter/qa/unit/data/attributeRedefinedTest.odp b/filter/qa/unit/data/attributeRedefinedTest.odp
new file mode 100644
index 000000000..dfb814bfb
--- /dev/null
+++ b/filter/qa/unit/data/attributeRedefinedTest.odp
Binary files differ
diff --git a/filter/qa/unit/data/calc.ots b/filter/qa/unit/data/calc.ots
new file mode 100644
index 000000000..d16d2307f
--- /dev/null
+++ b/filter/qa/unit/data/calc.ots
Binary files differ
diff --git a/filter/qa/unit/data/custom-bullet.fodp b/filter/qa/unit/data/custom-bullet.fodp
new file mode 100644
index 000000000..4139260f9
--- /dev/null
+++ b/filter/qa/unit/data/custom-bullet.fodp
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<office:document xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.presentation">
+ <office:automatic-styles>
+ <style:page-layout style:name="PM1">
+ <style:page-layout-properties fo:margin-top="0cm" fo:margin-bottom="0cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:page-width="28cm" fo:page-height="15.75cm" style:print-orientation="landscape"/>
+ </style:page-layout>
+ <style:style style:name="gr1" style:family="graphic" style:parent-style-name="standard">
+ <style:graphic-properties draw:stroke="none" svg:stroke-color="#000000" draw:fill="none" draw:fill-color="#ffffff" draw:auto-grow-height="true" draw:auto-grow-width="false" fo:max-height="0cm" fo:min-height="0cm"/>
+ </style:style>
+ <text:list-style style:name="L1">
+ <text:list-level-style-bullet text:level="1" text:bullet-char="-">
+ <style:list-level-properties text:min-label-width="0.6cm"/>
+ <style:text-properties fo:font-family="OpenSymbol" style:font-style-name="Regular" style:font-charset="x-symbol" style:use-window-font-color="true" fo:font-size="45%"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Default" style:page-layout-name="PM1">
+ </style:master-page>
+ </office:master-styles>
+ <office:body>
+ <office:presentation>
+ <draw:page draw:name="page1" draw:master-page-name="Default">
+ <draw:frame draw:style-name="gr1" draw:text-style-name="P8" draw:layer="layout" svg:width="9.525cm" svg:height="0.962cm" svg:x="3.175cm" svg:y="2.54cm">
+ <draw:text-box>
+ <text:list text:style-name="L1">
+ <text:list-item>
+ <text:p>hello</text:p>
+ </text:list-item>
+ </text:list>
+ </draw:text-box>
+ </draw:frame>
+ </draw:page>
+ </office:presentation>
+ </office:body>
+</office:document>
diff --git a/filter/qa/unit/data/empty.doc b/filter/qa/unit/data/empty.doc
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/filter/qa/unit/data/empty.doc
diff --git a/filter/qa/unit/data/empty.odp b/filter/qa/unit/data/empty.odp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/filter/qa/unit/data/empty.odp
diff --git a/filter/qa/unit/data/empty.ods b/filter/qa/unit/data/empty.ods
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/filter/qa/unit/data/empty.ods
diff --git a/filter/qa/unit/data/empty.odt b/filter/qa/unit/data/empty.odt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/filter/qa/unit/data/empty.odt
diff --git a/filter/qa/unit/data/empty.pptx b/filter/qa/unit/data/empty.pptx
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/filter/qa/unit/data/empty.pptx
diff --git a/filter/qa/unit/data/filter-dialogs-test.txt b/filter/qa/unit/data/filter-dialogs-test.txt
new file mode 100644
index 000000000..22792ad28
--- /dev/null
+++ b/filter/qa/unit/data/filter-dialogs-test.txt
@@ -0,0 +1,49 @@
+# -*- 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/.
+#
+
+# This file contains all dialogs that the unit tests in the module
+# will work on if it is in script mode. It will read one-by-one,
+# try to open it and create a screenshot that will be saved in
+# workdir/screenshots using the pattern of the ui-file name.
+#
+# Syntax:
+# - empty lines are allowed
+# - lines starting with '#' are treated as comment
+# - all other lines should contain a *.ui filename in the same
+# notation as in the dialog constructors (see code)
+
+#
+# The 'known' dialogs which have a hard-coded representation
+# in registerKnownDialogsByID/createDialogByID
+#
+
+# No known dialogs in filter for now
+
+#
+# Dialogs without a hard-coded representation. These will
+# be visualized using a fallback based on weld::Builder
+#
+
+# currently deactivated, leads to problems and the test to not work
+# This is typically a hint that these should be hard-coded in the
+# test case since they need some document and model data to work
+
+filter/ui/pdfoptionsdialog.ui
+filter/ui/xsltfilterdialog.ui
+filter/ui/pdfgeneralpage.ui
+filter/ui/pdfviewpage.ui
+filter/ui/pdfuserinterfacepage.ui
+filter/ui/pdfsecuritypage.ui
+filter/ui/pdflinkspage.ui
+filter/ui/pdfsignpage.ui
+filter/ui/xmlfiltertabpagegeneral.ui
+filter/ui/xmlfiltertabpagetransformation.ui
+filter/ui/testxmlfilter.ui
+filter/ui/warnpdfdialog.ui
+filter/ui/xmlfiltersettings.ui
diff --git a/filter/qa/unit/data/impress.otp b/filter/qa/unit/data/impress.otp
new file mode 100644
index 000000000..199a5f9d4
--- /dev/null
+++ b/filter/qa/unit/data/impress.otp
Binary files differ
diff --git a/filter/qa/unit/data/preserve-jpg.odt b/filter/qa/unit/data/preserve-jpg.odt
new file mode 100644
index 000000000..83768bd47
--- /dev/null
+++ b/filter/qa/unit/data/preserve-jpg.odt
Binary files differ
diff --git a/filter/qa/unit/data/semi-transparent-fill.odg b/filter/qa/unit/data/semi-transparent-fill.odg
new file mode 100644
index 000000000..713f48991
--- /dev/null
+++ b/filter/qa/unit/data/semi-transparent-fill.odg
Binary files differ
diff --git a/filter/qa/unit/data/semi-transparent-line.odg b/filter/qa/unit/data/semi-transparent-line.odg
new file mode 100644
index 000000000..2d28a694c
--- /dev/null
+++ b/filter/qa/unit/data/semi-transparent-line.odg
Binary files differ
diff --git a/filter/qa/unit/data/shape-nographic.odp b/filter/qa/unit/data/shape-nographic.odp
new file mode 100644
index 000000000..43186d614
--- /dev/null
+++ b/filter/qa/unit/data/shape-nographic.odp
Binary files differ
diff --git a/filter/qa/unit/data/tdf114428.xhtml b/filter/qa/unit/data/tdf114428.xhtml
new file mode 100644
index 000000000..f08f0fa4a
--- /dev/null
+++ b/filter/qa/unit/data/tdf114428.xhtml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Title of document</title>
+ </head>
+ <body>hello world</body>
+</html>
diff --git a/filter/qa/unit/data/writer.ott b/filter/qa/unit/data/writer.ott
new file mode 100644
index 000000000..1ded03150
--- /dev/null
+++ b/filter/qa/unit/data/writer.ott
Binary files differ
diff --git a/filter/qa/unit/filter-dialogs-test.cxx b/filter/qa/unit/filter-dialogs-test.cxx
new file mode 100644
index 000000000..946a1961d
--- /dev/null
+++ b/filter/qa/unit/filter-dialogs-test.cxx
@@ -0,0 +1,61 @@
+/* -*- 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 <sal/config.h>
+#include <test/screenshot_test.hxx>
+#include <vcl/abstdlg.hxx>
+
+using namespace ::com::sun::star;
+
+/// Test opening a dialog in filter
+class FilterDialogsTest : public ScreenshotTest
+{
+private:
+ /// helper method to populate KnownDialogs, called in setUp(). Needs to be
+ /// written and has to add entries to KnownDialogs
+ virtual void registerKnownDialogsByID(mapType& rKnownDialogs) override;
+
+ /// dialog creation for known dialogs by ID. Has to be implemented for
+ /// each registered known dialog
+ virtual VclPtr<VclAbstractDialog> createDialogByID(sal_uInt32 nID) override;
+
+public:
+ FilterDialogsTest();
+
+ // try to open a dialog
+ void openAnyDialog();
+
+ CPPUNIT_TEST_SUITE(FilterDialogsTest);
+ CPPUNIT_TEST(openAnyDialog);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+FilterDialogsTest::FilterDialogsTest() {}
+
+void FilterDialogsTest::registerKnownDialogsByID(mapType& /*rKnownDialogs*/)
+{
+ // fill map of known dialogs
+}
+
+VclPtr<VclAbstractDialog> FilterDialogsTest::createDialogByID(sal_uInt32 /*nID*/)
+{
+ return nullptr;
+}
+
+void FilterDialogsTest::openAnyDialog()
+{
+ /// process input file containing the UXMLDescriptions of the dialogs to dump
+ processDialogBatchFile(u"filter/qa/unit/data/filter-dialogs-test.txt");
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(FilterDialogsTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/qa/unit/svg.cxx b/filter/qa/unit/svg.cxx
new file mode 100644
index 000000000..22695acd6
--- /dev/null
+++ b/filter/qa/unit/svg.cxx
@@ -0,0 +1,380 @@
+/* -*- 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 <sal/config.h>
+
+#include <string_view>
+
+#include <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+#include <test/xmltesttools.hxx>
+
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/text/ControlCharacter.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+#include <unotools/streamwrap.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <tools/stream.hxx>
+
+using namespace ::com::sun::star;
+
+constexpr OUStringLiteral DATA_DIRECTORY = u"/filter/qa/unit/data/";
+
+/// SVG filter tests.
+class SvgFilterTest : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
+{
+private:
+ uno::Reference<lang::XComponent> mxComponent;
+
+public:
+ void setUp() override;
+ void tearDown() override;
+ void registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) override;
+ uno::Reference<lang::XComponent>& getComponent() { return mxComponent; }
+ void load(std::u16string_view rURL);
+};
+
+void SvgFilterTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+}
+
+void SvgFilterTest::tearDown()
+{
+ if (mxComponent.is())
+ mxComponent->dispose();
+
+ test::BootstrapFixture::tearDown();
+}
+
+void SvgFilterTest::load(std::u16string_view rFileName)
+{
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + rFileName;
+ mxComponent = loadFromDesktop(aURL);
+}
+
+void SvgFilterTest::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx)
+{
+ xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("svg"), BAD_CAST("http://www.w3.org/2000/svg"));
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testPreserveJpg)
+{
+#if !defined(MACOSX)
+ // Load a document with a jpeg image in it.
+ load(u"preserve-jpg.odt");
+
+ // Select the image.
+ dispatchCommand(getComponent(), ".uno:JumpToNextFrame", {});
+
+ // Export the selection to SVG.
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("writer_svg_Export");
+ aMediaDescriptor["SelectionOnly"] <<= true;
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Make sure that the original JPG data is reused and we don't perform a PNG re-compress.
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ OUString aAttributeValue = getXPath(pXmlDoc, "//svg:image", "href");
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expression: aAttributeValue.startsWith("data:image/jpeg")
+ // i.e. the SVG export result re-compressed the image as PNG, even if the original and the
+ // transformed image is the same, so there is no need for that.
+ CPPUNIT_ASSERT(aAttributeValue.startsWith("data:image/jpeg"));
+#endif
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testSemiTransparentLine)
+{
+ // Load a document with a semi-transparent line shape.
+ load(u"semi-transparent-line.odg");
+
+ // Export it to SVG.
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("draw_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Get the style of the group around the actual <path> element.
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ OUString aStyle = getXPath(
+ pXmlDoc, "//svg:g[@class='com.sun.star.drawing.LineShape']/svg:g/svg:g", "style");
+ // Without the accompanying fix in place, this test would have failed, as the style was
+ // "mask:url(#mask1)", not "opacity: <value>".
+ CPPUNIT_ASSERT(aStyle.startsWith("opacity: ", &aStyle));
+ int nPercent = std::round(aStyle.toDouble() * 100);
+ // Make sure that the line is still 30% opaque, rather than completely invisible.
+ CPPUNIT_ASSERT_EQUAL(30, nPercent);
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testSemiTransparentFillWithTransparentLine)
+{
+ // Load a document with a shape with semi-transparent fill and line
+ load(u"semi-transparent-fill.odg");
+
+ // Export it to SVG.
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("draw_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Get the style of the group around the actual <path> element.
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ OUString aStyle = getXPath(
+ pXmlDoc, "//svg:g[@class='com.sun.star.drawing.EllipseShape']/svg:g/svg:g", "style");
+ CPPUNIT_ASSERT(aStyle.startsWith("opacity: ", &aStyle));
+ int nPercent = std::round(aStyle.toDouble() * 100);
+ // Make sure that the line is still 50% opaque
+ CPPUNIT_ASSERT_EQUAL(50, nPercent);
+
+ // Get the stroke of the fill of the EllipseShape (it must be "none")
+ OUString aStroke = getXPath(
+ pXmlDoc, "//svg:g[@class='com.sun.star.drawing.EllipseShape']/svg:g/svg:path", "stroke");
+ // Without the accompanying fix in place, this test would have failed, as the stroke was
+ // "rgb(255,255,255)", not "none".
+ CPPUNIT_ASSERT_EQUAL(OUString("none"), aStroke);
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testSemiTransparentText)
+{
+ // Two shapes, one with transparent text and the other one with
+ // opaque text. We expect both to be exported to the SVG with the
+ // correct transparency factor applied for the first shape.
+
+ // Load draw document with transparent text in one box
+ load(u"TransparentText.odg");
+
+ // Export to SVG.
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("draw_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+
+ // We expect 2 groups of class "TextShape" that
+ // have some svg:text node inside.
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 2
+ // - Actual : 1
+ // i.e. the 2nd shape lots its text.
+
+ assertXPath(pXmlDoc, "//svg:g[@class='TextShape']//svg:text", 2);
+
+ // First shape has semi-transparent text.
+ assertXPath(pXmlDoc, "//svg:text[1]/svg:tspan/svg:tspan/svg:tspan[@fill-opacity='0.8']");
+
+ // Second shape has normal text.
+ assertXPath(pXmlDoc, "//svg:text[2]/svg:tspan/svg:tspan/svg:tspan[@fill-opacity]", 0);
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testSemiTransparentMultiParaText)
+{
+ // Given a shape with semi-transparent, multi-paragraph text:
+ getComponent()
+ = loadFromDesktop("private:factory/simpress", "com.sun.star.drawing.DrawingDocument");
+ uno::Reference<lang::XMultiServiceFactory> xFactory(getComponent(), uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xShape(
+ xFactory->createInstance("com.sun.star.drawing.TextShape"), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY);
+ uno::Reference<drawing::XShapes> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+ uno::UNO_QUERY);
+ xDrawPage->add(xShape);
+ xShape->setSize(awt::Size(10000, 10000));
+ uno::Reference<text::XSimpleText> xShapeText(xShape, uno::UNO_QUERY);
+ uno::Reference<text::XTextCursor> xCursor = xShapeText->createTextCursor();
+ xShapeText->insertString(xCursor, "foo", /*bAbsorb=*/false);
+ xShapeText->insertControlCharacter(xCursor, text::ControlCharacter::APPEND_PARAGRAPH,
+ /*bAbsorb=*/false);
+ xShapeText->insertString(xCursor, "bar", /*bAbsorb=*/false);
+ uno::Reference<beans::XPropertySet> xShapeProps(xShape, uno::UNO_QUERY);
+ xShapeProps->setPropertyValue("CharColor", uno::Any(static_cast<sal_Int32>(0xff0000)));
+ xShapeProps->setPropertyValue("CharTransparence", uno::Any(static_cast<sal_Int16>(20)));
+
+ // When exporting to SVG:
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("draw_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ // Then make sure that the two semi-tranparent paragraphs have the same X position:
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ assertXPath(pXmlDoc, "(//svg:g[@class='TextShape']//svg:tspan[@class='TextPosition'])[1]", "x",
+ "250");
+ assertXPath(pXmlDoc,
+ "(//svg:g[@class='TextShape']//svg:tspan[@class='TextPosition'])[1]/svg:tspan",
+ "fill-opacity", "0.8");
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 250
+ // - Actual : 8819
+ // i.e. the X position of the second paragraph was wrong.
+ assertXPath(pXmlDoc, "(//svg:g[@class='TextShape']//svg:tspan[@class='TextPosition'])[2]", "x",
+ "250");
+ assertXPath(pXmlDoc,
+ "(//svg:g[@class='TextShape']//svg:tspan[@class='TextPosition'])[2]/svg:tspan",
+ "fill-opacity", "0.8");
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testShapeNographic)
+{
+ // Load a document containing a 3D shape.
+ load(u"shape-nographic.odp");
+
+ // Export to SVG.
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("impress_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+
+ // Without the accompanying fix in place, this test would have failed with:
+ // An uncaught exception of type com.sun.star.io.IOException
+ // - SfxBaseModel::impl_store <private:stream> failed: 0xc10(Error Area:Io Class:Write Code:16)
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testCustomBullet)
+{
+ // Given a presentation with a custom bullet:
+ load(u"custom-bullet.fodp");
+
+ // When exporting that to SVG:
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("impress_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Then make sure the bullet glyph is not lost:
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 1
+ // - Actual : 0
+ // - XPath '//svg:g[@class='BulletChars']//svg:path' number of nodes is incorrect
+ // i.e. the custom bullet used '<use transform="scale(285,285)"
+ // xlink:href="#bullet-char-template-45"/>', but nobody produced a bullet-char-template-45,
+ // instead we need the path of the glyph inline.
+ CPPUNIT_ASSERT(!getXPath(pXmlDoc, "//svg:g[@class='BulletChars']//svg:path", "d").isEmpty());
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, attributeRedefinedTest)
+{
+ // Load document containing empty paragraphs with ids.
+ load(u"attributeRedefinedTest.odp");
+
+ // Export to SVG.
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("impress_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+
+ // We expect four paragraph
+ // 2 empty paragraphs with ids
+ // 2 paragraphs with text
+ // Without the accompanying fix the test would have failed with
+ // Expected : 4
+ // Actual : 2
+ // i.e. 2 of the empty paragraph do not get generated even if there
+ // is id imported for the paragraphs
+ // If we don't create the empty paragraphs the id attribute gets redefined like this:
+ // <tspan id="id14" id="id15" id="id17" class="TextParagraph" font-family="Bahnschrift Light" font-size="1129px" font-weight="400">
+
+ OString xPath = "//svg:g[@class='TextShape']//svg:text[@class='SVGTextShape']//"
+ "svg:tspan[@class='TextParagraph']";
+ assertXPath(pXmlDoc, xPath, 4);
+
+ //assert that each tspan element with TextParagraph class has id and the tspan element of
+ //each empty paragraph does not contain tspan element with class TextPosition
+ assertXPath(pXmlDoc, xPath + "[1]", "id", "id4");
+ assertXPath(pXmlDoc, xPath + "[2]", "id", "id5");
+ assertXPath(pXmlDoc, xPath + "[2]//svg:tspan[@class='TextPosition']", 0);
+ assertXPath(pXmlDoc, xPath + "[3]", "id", "id6");
+ assertXPath(pXmlDoc, xPath + "[3]//svg:tspan[@class='TextPosition']", 0);
+ assertXPath(pXmlDoc, xPath + "[4]", "id", "id7");
+}
+
+CPPUNIT_TEST_FIXTURE(SvgFilterTest, testTab)
+{
+ // Given a shape with "A\tB" text:
+ getComponent() = loadFromDesktop("private:factory/simpress",
+ "com.sun.star.presentation.PresentationDocument");
+ uno::Reference<lang::XMultiServiceFactory> xFactory(getComponent(), uno::UNO_QUERY);
+ uno::Reference<drawing::XShape> xShape(
+ xFactory->createInstance("com.sun.star.drawing.TextShape"), uno::UNO_QUERY);
+ uno::Reference<drawing::XDrawPagesSupplier> xDrawPagesSupplier(getComponent(), uno::UNO_QUERY);
+ uno::Reference<drawing::XShapes> xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+ uno::UNO_QUERY);
+ xDrawPage->add(xShape);
+ xShape->setSize(awt::Size(10000, 10000));
+ uno::Reference<text::XTextRange> xShapeText(xShape, uno::UNO_QUERY);
+ xShapeText->setString("A\tB");
+
+ // When exporting that document to SVG:
+ uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY_THROW);
+ SvMemoryStream aStream;
+ uno::Reference<io::XOutputStream> xOut = new utl::OOutputStreamWrapper(aStream);
+ utl::MediaDescriptor aMediaDescriptor;
+ aMediaDescriptor["FilterName"] <<= OUString("impress_svg_Export");
+ aMediaDescriptor["OutputStream"] <<= xOut;
+ xStorable->storeToURL("private:stream", aMediaDescriptor.getAsConstPropertyValueList());
+
+ // Then make sure the the tab is not lost:
+ aStream.Seek(STREAM_SEEK_TO_BEGIN);
+ xmlDocUniquePtr pXmlDoc = parseXmlStream(&aStream);
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: 2
+ // - Actual : 1
+ // i.e. the 2nd text portion was not positioned, which looked as if the tab is lost.
+ assertXPath(pXmlDoc, "//svg:g[@class='TextShape']//svg:tspan[@class='TextPosition']", 2);
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/qa/unit/textfilterdetect.cxx b/filter/qa/unit/textfilterdetect.cxx
new file mode 100644
index 000000000..3c8daf2f2
--- /dev/null
+++ b/filter/qa/unit/textfilterdetect.cxx
@@ -0,0 +1,199 @@
+/* -*- 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 <test/bootstrapfixture.hxx>
+#include <unotest/macros_test.hxx>
+
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/sheet/XCellRangesAccess.hpp>
+#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <sfx2/docfac.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <unotools/streamwrap.hxx>
+#include <tools/stream.hxx>
+
+namespace com::sun::star::io
+{
+class XInputStream;
+}
+
+using namespace com::sun::star;
+
+namespace
+{
+/// Test class for PlainTextFilterDetect.
+class TextFilterDetectTest : public test::BootstrapFixture, public unotest::MacrosTest
+{
+public:
+ void setUp() override;
+};
+
+void TextFilterDetectTest::setUp()
+{
+ test::BootstrapFixture::setUp();
+
+ mxDesktop.set(frame::Desktop::create(mxComponentContext));
+}
+
+constexpr OUStringLiteral DATA_DIRECTORY = u"/filter/qa/unit/data/";
+
+CPPUNIT_TEST_FIXTURE(TextFilterDetectTest, testTdf114428)
+{
+ uno::Reference<document::XExtendedFilterDetection> xDetect(
+ getMultiServiceFactory()->createInstance("com.sun.star.comp.filters.PlainTextFilterDetect"),
+ uno::UNO_QUERY);
+ OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf114428.xhtml";
+ SvFileStream aStream(aURL, StreamMode::READ);
+ uno::Reference<io::XInputStream> xStream(new utl::OStreamWrapper(aStream));
+ uno::Sequence<beans::PropertyValue> aDescriptor
+ = { comphelper::makePropertyValue("DocumentService",
+ OUString("com.sun.star.text.TextDocument")),
+ comphelper::makePropertyValue("InputStream", xStream),
+ comphelper::makePropertyValue("TypeName", OUString("generic_HTML")) };
+ xDetect->detect(aDescriptor);
+ utl::MediaDescriptor aMediaDesc(aDescriptor);
+ OUString aFilterName = aMediaDesc.getUnpackedValueOrDefault("FilterName", OUString());
+ // This was empty, XML declaration caused HTML detect to not handle XHTML.
+ CPPUNIT_ASSERT_EQUAL(OUString("HTML (StarWriter)"), aFilterName);
+}
+
+CPPUNIT_TEST_FIXTURE(TextFilterDetectTest, testEmptyFile)
+{
+ const OUString sDataDirectory = m_directories.getURLFromSrc(DATA_DIRECTORY);
+ auto supportsService = [](const uno::Reference<lang::XComponent>& x, const OUString& s) {
+ return uno::Reference<lang::XServiceInfo>(x, uno::UNO_QUERY_THROW)->supportsService(s);
+ };
+
+ // Given an empty file, with a pptx extension
+ // When loading the file
+ auto xComponent = loadFromDesktop(sDataDirectory + "empty.pptx");
+
+ // Then make sure it is opened in Impress.
+ // Without the accompanying fix in place, this test would have failed, as it was opened in
+ // Writer instead.
+ CPPUNIT_ASSERT(supportsService(xComponent, "com.sun.star.presentation.PresentationDocument"));
+ xComponent->dispose();
+
+ // Now also test ODT
+ xComponent = loadFromDesktop(sDataDirectory + "empty.odt");
+ // Make sure it opens in Writer.
+ CPPUNIT_ASSERT(supportsService(xComponent, "com.sun.star.text.TextDocument"));
+ xComponent->dispose();
+
+ // ... and ODS
+ xComponent = loadFromDesktop(sDataDirectory + "empty.ods");
+ // Make sure it opens in Calc.
+ CPPUNIT_ASSERT(supportsService(xComponent, "com.sun.star.sheet.SpreadsheetDocument"));
+ xComponent->dispose();
+
+ // ... and ODP
+ xComponent = loadFromDesktop(sDataDirectory + "empty.odp");
+ // Without the accompanying fix in place, this test would have failed, as it was opened in
+ // Writer instead.
+ CPPUNIT_ASSERT(supportsService(xComponent, "com.sun.star.presentation.PresentationDocument"));
+ xComponent->dispose();
+
+ // ... and DOC
+ // Without the accompanying fix in place, this test would have failed, the import filter aborted
+ // loading.
+ xComponent = loadFromDesktop(sDataDirectory + "empty.doc");
+ CPPUNIT_ASSERT(supportsService(xComponent, "com.sun.star.text.TextDocument"));
+ {
+ uno::Reference<frame::XModel> xModel(xComponent, uno::UNO_QUERY);
+ uno::Sequence<beans::PropertyValue> aArgs = xModel->getArgs();
+ comphelper::SequenceAsHashMap aMap(aArgs);
+ OUString aFilterName;
+ aMap["FilterName"] >>= aFilterName;
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: MS Word 97
+ // - Actual : MS WinWord 6.0
+ // i.e. opening worked, but saving back failed instead of producing a WW8 binary file.
+ CPPUNIT_ASSERT_EQUAL(OUString("MS Word 97"), aFilterName);
+ }
+ xComponent->dispose();
+
+ // Now test with default templates set
+
+ SfxObjectFactory::SetStandardTemplate("com.sun.star.presentation.PresentationDocument",
+ sDataDirectory + "impress.otp");
+ SfxObjectFactory::SetStandardTemplate("com.sun.star.text.TextDocument",
+ sDataDirectory + "writer.ott");
+ SfxObjectFactory::SetStandardTemplate("com.sun.star.sheet.SpreadsheetDocument",
+ sDataDirectory + "calc.ots");
+
+ xComponent = loadFromDesktop(sDataDirectory + "empty.pptx");
+ {
+ uno::Reference<drawing::XDrawPagesSupplier> xDoc(xComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPages> xPages(xDoc->getDrawPages(), uno::UNO_SET_THROW);
+ uno::Reference<drawing::XDrawPage> xPage(xPages->getByIndex(0), uno::UNO_QUERY_THROW);
+ uno::Reference<text::XTextRange> xBox(xPage->getByIndex(0), uno::UNO_QUERY_THROW);
+
+ // Make sure the template's text was loaded
+ CPPUNIT_ASSERT_EQUAL(OUString("Title of Impress template"), xBox->getString());
+ }
+ xComponent->dispose();
+
+ xComponent = loadFromDesktop(sDataDirectory + "empty.odt");
+ {
+ uno::Reference<text::XTextDocument> xDoc(xComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<container::XEnumerationAccess> xEA(xDoc->getText(), uno::UNO_QUERY_THROW);
+ uno::Reference<container::XEnumeration> xEnum(xEA->createEnumeration(), uno::UNO_SET_THROW);
+ uno::Reference<text::XTextRange> xParagraph(xEnum->nextElement(), uno::UNO_QUERY_THROW);
+
+ // Make sure the template's text was loaded
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Writer template’s first line"), xParagraph->getString());
+ }
+ xComponent->dispose();
+
+ xComponent = loadFromDesktop(sDataDirectory + "empty.ods");
+ {
+ uno::Reference<sheet::XSpreadsheetDocument> xDoc(xComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<sheet::XCellRangesAccess> xRA(xDoc->getSheets(), uno::UNO_QUERY_THROW);
+ uno::Reference<text::XTextRange> xC(xRA->getCellByPosition(0, 0, 0), uno::UNO_QUERY_THROW);
+
+ // Make sure the template's text was loaded
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Calc template’s first cell"), xC->getString());
+ }
+ xComponent->dispose();
+
+ xComponent = loadFromDesktop(sDataDirectory + "empty.odp");
+ {
+ uno::Reference<drawing::XDrawPagesSupplier> xDoc(xComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<drawing::XDrawPages> xPages(xDoc->getDrawPages(), uno::UNO_SET_THROW);
+ uno::Reference<drawing::XDrawPage> xPage(xPages->getByIndex(0), uno::UNO_QUERY_THROW);
+ uno::Reference<text::XTextRange> xBox(xPage->getByIndex(0), uno::UNO_QUERY_THROW);
+
+ // Make sure the template's text was loaded
+ CPPUNIT_ASSERT_EQUAL(OUString("Title of Impress template"), xBox->getString());
+ }
+ xComponent->dispose();
+
+ xComponent = loadFromDesktop(sDataDirectory + "empty.doc");
+ {
+ uno::Reference<text::XTextDocument> xDoc(xComponent, uno::UNO_QUERY_THROW);
+ uno::Reference<container::XEnumerationAccess> xEA(xDoc->getText(), uno::UNO_QUERY_THROW);
+ uno::Reference<container::XEnumeration> xEnum(xEA->createEnumeration(), uno::UNO_SET_THROW);
+ uno::Reference<text::XTextRange> xParagraph(xEnum->nextElement(), uno::UNO_QUERY_THROW);
+
+ // Make sure the template's text was loaded
+ CPPUNIT_ASSERT_EQUAL(OUString(u"Writer template’s first line"), xParagraph->getString());
+ }
+ xComponent->dispose();
+}
+}
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/basecontainer.cxx b/filter/source/config/cache/basecontainer.cxx
new file mode 100644
index 000000000..0dee9d4ba
--- /dev/null
+++ b/filter/source/config/cache/basecontainer.cxx
@@ -0,0 +1,476 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "basecontainer.hxx"
+
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/uno/Type.h>
+#include <comphelper/enumhelper.hxx>
+#include <comphelper/sequence.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <osl/diagnose.h>
+
+#define LOAD_IMPLICIT
+
+namespace filter::config{
+
+BaseContainer::BaseContainer()
+ : m_eType()
+ , m_lListener (m_aMutex)
+{
+ GetTheFilterCache().load(FilterCache::E_CONTAINS_STANDARD);
+}
+
+
+BaseContainer::~BaseContainer()
+{
+}
+
+
+void BaseContainer::init(const OUString& sImplementationName,
+ const css::uno::Sequence< OUString >& lServiceNames ,
+ FilterCache::EItemType eType )
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ m_sImplementationName = sImplementationName;
+ m_lServiceNames = lServiceNames ;
+ m_eType = eType ;
+ // <- SAFE
+}
+
+
+void BaseContainer::impl_loadOnDemand()
+{
+#ifdef LOAD_IMPLICIT
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // A generic container needs all items of a set of our cache!
+ // Of course it can block for a while, till the cache is really filled.
+ // Note: don't load all sets supported by the cache here!
+
+ FilterCache::EFillState eRequiredState = FilterCache::E_CONTAINS_NOTHING;
+ switch(m_eType)
+ {
+ case FilterCache::E_TYPE :
+ eRequiredState = FilterCache::E_CONTAINS_TYPES;
+ break;
+
+ case FilterCache::E_FILTER :
+ eRequiredState = FilterCache::E_CONTAINS_FILTERS;
+ break;
+
+ case FilterCache::E_FRAMELOADER :
+ eRequiredState = FilterCache::E_CONTAINS_FRAMELOADERS;
+ break;
+
+ case FilterCache::E_CONTENTHANDLER :
+ eRequiredState = FilterCache::E_CONTAINS_CONTENTHANDLERS;
+ break;
+ }
+
+ GetTheFilterCache().load(eRequiredState);
+ // <- SAFE
+#endif
+}
+
+
+void BaseContainer::impl_initFlushMode()
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+ if (!m_pFlushCache)
+ m_pFlushCache = GetTheFilterCache().clone();
+ if (!m_pFlushCache)
+ throw css::uno::RuntimeException( "Can not create write copy of internal used cache on demand.",
+ static_cast< OWeakObject* >(this));
+ // <- SAFE
+}
+
+
+FilterCache* BaseContainer::impl_getWorkingCache() const
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+ if (m_pFlushCache)
+ return m_pFlushCache.get();
+ else
+ return &GetTheFilterCache();
+ // <- SAFE
+}
+
+
+OUString SAL_CALL BaseContainer::getImplementationName()
+{
+ return m_sImplementationName;
+}
+
+
+sal_Bool SAL_CALL BaseContainer::supportsService(const OUString& sServiceName)
+{
+ return cppu::supportsService(this, sServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL BaseContainer::getSupportedServiceNames()
+{
+ return m_lServiceNames;
+}
+
+
+void SAL_CALL BaseContainer::insertByName(const OUString& sItem ,
+ const css::uno::Any& aValue)
+{
+ if (sItem.isEmpty())
+ throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
+ static_cast< css::container::XNameContainer* >(this),
+ 1);
+
+ CacheItem aItem;
+ try
+ {
+ aItem << aValue;
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
+ }
+
+ impl_loadOnDemand();
+
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ // create write copy of used cache on demand ...
+ impl_initFlushMode();
+
+ FilterCache* pCache = impl_getWorkingCache();
+ if (pCache->hasItem(m_eType, sItem))
+ throw css::container::ElementExistException(OUString(), static_cast< css::container::XNameContainer* >(this));
+ pCache->setItem(m_eType, sItem, aItem);
+ // <- SAFE ----------------------------------
+}
+
+
+void SAL_CALL BaseContainer::removeByName(const OUString& sItem)
+{
+ impl_loadOnDemand();
+
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ // create write copy of used cache on demand ...
+ impl_initFlushMode();
+
+ FilterCache* pCache = impl_getWorkingCache();
+ pCache->removeItem(m_eType, sItem); // throw exceptions automatically
+ // <- SAFE ----------------------------------
+}
+
+
+void SAL_CALL BaseContainer::replaceByName(const OUString& sItem ,
+ const css::uno::Any& aValue)
+{
+ if (sItem.isEmpty())
+ throw css::lang::IllegalArgumentException("empty value not allowed as item name.",
+ static_cast< css::container::XNameContainer* >(this),
+ 1);
+
+ CacheItem aItem;
+ try
+ {
+ aItem << aValue;
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::lang::IllegalArgumentException(ex.Message, static_cast< css::container::XNameContainer* >(this), 2);
+ }
+
+ impl_loadOnDemand();
+
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ // create write copy of used cache on demand ...
+ impl_initFlushMode();
+
+ FilterCache* pCache = impl_getWorkingCache();
+ if (!pCache->hasItem(m_eType, sItem))
+ throw css::container::NoSuchElementException(OUString(), static_cast< css::container::XNameContainer* >(this));
+ pCache->setItem(m_eType, sItem, aItem);
+ // <- SAFE ----------------------------------
+}
+
+
+css::uno::Any SAL_CALL BaseContainer::getByName(const OUString& sItem)
+{
+ if (sItem.isEmpty())
+ throw css::container::NoSuchElementException( "An empty item can't be part of this cache!",
+ static_cast< css::container::XNameAccess* >(this));
+
+ css::uno::Any aValue;
+
+ impl_loadOnDemand();
+
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ try
+ {
+ FilterCache* pCache = impl_getWorkingCache();
+ aValue = pCache->getItemWithStateProps(m_eType, sItem);
+ }
+ catch(const css::container::NoSuchElementException&)
+ {
+ throw;
+ }
+ catch(const css::uno::Exception&)
+ {
+ // TODO invalid cache!? How should it be handled right?
+ }
+
+ // <- SAFE
+
+ return aValue;
+}
+
+
+css::uno::Sequence< OUString > SAL_CALL BaseContainer::getElementNames()
+{
+ css::uno::Sequence< OUString > lNames;
+
+ impl_loadOnDemand();
+
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ try
+ {
+ FilterCache* pCache = impl_getWorkingCache();
+ std::vector<OUString> lKeys = pCache->getItemNames(m_eType);
+ lNames = comphelper::containerToSequence(lKeys);
+ }
+ catch(const css::uno::Exception&)
+ {
+ // invalid cache!?
+ lNames.realloc(0);
+ }
+
+ // <- SAFE
+
+ return lNames;
+}
+
+
+sal_Bool SAL_CALL BaseContainer::hasByName(const OUString& sItem)
+{
+ bool bHasOne = false;
+
+ impl_loadOnDemand();
+
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ try
+ {
+ FilterCache* pCache = impl_getWorkingCache();
+ bHasOne = pCache->hasItem(m_eType, sItem);
+ }
+ catch(const css::uno::Exception&)
+ {
+ // invalid cache!?
+ bHasOne = false;
+ }
+
+ // <- SAFE
+
+ return bHasOne;
+}
+
+
+css::uno::Type SAL_CALL BaseContainer::getElementType()
+{
+ // no lock necessary - because the type of our items
+ // is fix! no internal call or member needed ...
+ return cppu::UnoType<css::uno::Sequence< css::beans::PropertyValue >>::get();
+}
+
+
+sal_Bool SAL_CALL BaseContainer::hasElements()
+{
+ bool bHasSome = false;
+
+ impl_loadOnDemand();
+
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ try
+ {
+ FilterCache* pCache = impl_getWorkingCache();
+ bHasSome = pCache->hasItems(m_eType);
+ }
+ catch(const css::uno::Exception&)
+ {
+ // invalid cache?!
+ bHasSome = false;
+ }
+
+ // <- SAFE
+
+ return bHasSome;
+}
+
+
+css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByQuery(const OUString& /* sQuery */ )
+{
+ OSL_FAIL("not pure virtual ... but not really implemented .-)");
+
+ return new ::comphelper::OEnumerationByName(this, {});
+}
+
+
+css::uno::Reference< css::container::XEnumeration > SAL_CALL BaseContainer::createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties)
+{
+ std::vector<OUString> lKeys;
+
+ impl_loadOnDemand();
+
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ try
+ {
+ // search the key names of all items, where its properties match
+ // the given ones in its minimum
+ FilterCache* pCache = impl_getWorkingCache();
+ lKeys = pCache->getMatchingItemsByProps(m_eType, o3tl::span<const css::beans::NamedValue>( lProperties.getConstArray(), lProperties.getLength() ));
+ }
+ catch(const css::uno::Exception&)
+ {
+ // invalid cache, internal failure, wrong conversion ...!?
+ // doesn't matter
+ lKeys.clear();
+ }
+
+ // <- SAFE
+
+ // create a specialized enumeration helper, which
+ // provides the collected information outside.
+ // It hold a reference to us ... and call our container interface directly.
+ // be aware of some direct callbacks if it will be created :-)
+
+ /* Note: It's not allowed to return NULL. Because an empty enumeration
+ transport the same information but make no trouble outside.
+ Further its easier to work directly with the return value
+ instead of checking of NULL returns! */
+
+ return new ::comphelper::OEnumerationByName(this, std::move(lKeys));
+}
+
+
+void SAL_CALL BaseContainer::flush()
+{
+ // SAFE ->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ if (!m_pFlushCache)
+ throw css::lang::WrappedTargetRuntimeException(
+ "Can not guarantee cache consistency. Special flush container does not exists!",
+ static_cast< OWeakObject* >(this),
+ css::uno::Any());
+
+ try
+ {
+ m_pFlushCache->flush();
+ // Take over all changes into the global cache and
+ // forget the clone.
+ /* TODO
+ -think about me
+ If the global cache gets this information via listener,
+ we should remove this method!
+ */
+ GetTheFilterCache().takeOver(*m_pFlushCache);
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ // Don't remove the clone. May be the outside
+ // user wish to repair it now and calls flush()
+ // later again ...
+
+ throw css::lang::WrappedTargetRuntimeException( "Flush rejected by internal container.",
+ static_cast< OWeakObject* >(this),
+ css::uno::Any(ex));
+ }
+
+ m_pFlushCache.reset();
+
+ aLock.clear();
+ // <- SAFE
+
+ // notify listener outside the lock!
+ // The used listener helper lives if we live
+ // and is threadsafe by itself.
+ // Further it's not a good idea to hold the own lock
+ // if an outside object is called :-)
+ css::lang::EventObject aSource (static_cast< css::util::XFlushable* >(this));
+ comphelper::OInterfaceContainerHelper2* pContainer = m_lListener.getContainer(cppu::UnoType<css::util::XFlushListener>::get());
+ if (!pContainer)
+ return;
+
+ comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
+ while (pIterator.hasMoreElements())
+ {
+ try
+ {
+ // ... this pointer can be interesting to find out, where will be called as listener
+ // Don't optimize it to a direct iterator cast :-)
+ css::util::XFlushListener* pListener = static_cast<css::util::XFlushListener*>(pIterator.next());
+ pListener->flushed(aSource);
+ }
+ catch(const css::uno::Exception&)
+ {
+ // ignore any "damaged" flush listener!
+ // May its remote reference is broken ...
+ pIterator.remove();
+ }
+ }
+}
+
+
+void SAL_CALL BaseContainer::addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
+{
+ // no locks necessary
+ // used helper lives if we live and is threadsafe by itself ...
+ m_lListener.addInterface(cppu::UnoType<css::util::XFlushListener>::get(), xListener);
+}
+
+
+void SAL_CALL BaseContainer::removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener)
+{
+ // no locks necessary
+ // used helper lives if we live and is threadsafe by itself ...
+ m_lListener.removeInterface(cppu::UnoType<css::util::XFlushListener>::get(), xListener);
+}
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/basecontainer.hxx b/filter/source/config/cache/basecontainer.hxx
new file mode 100644
index 000000000..6691c1b49
--- /dev/null
+++ b/filter/source/config/cache/basecontainer.hxx
@@ -0,0 +1,256 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+
+#include "filtercache.hxx"
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/container/XContainerQuery.hpp>
+#include <com/sun/star/util/XFlushable.hpp>
+#include <comphelper/multicontainer2.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/weakref.hxx>
+#include <rtl/ustring.hxx>
+
+
+namespace filter::config {
+
+
+/** @short implements the interface css::container::XNameContainer
+ on top of a FilterCache reference.
+
+ @descr This class can be used as base for own service implementations,
+ which must provide read/write access to the filter configuration.
+ Parameters regulate read/write access, which sub set of information
+ should be available etc.
+
+ @attention The base class BaseLock must be the first of declared ones.
+ Otherwise we can't be sure, that our own mutex member (which is
+ present by this base class!) was full initialized inside our own
+ ctor as first!
+ */
+class BaseContainer : public cppu::BaseMutex
+ , public ::cppu::WeakImplHelper< css::lang::XServiceInfo ,
+ css::container::XNameContainer , // => XNameReplace => XNameAccess => XElementAccess
+ css::container::XContainerQuery ,
+ css::util::XFlushable >
+{
+
+ // member
+
+ protected:
+
+ /** @short the implementation name of our derived class, which we provide
+ at the interface XServiceInfo of our class... */
+ OUString m_sImplementationName;
+
+ /** @short the list of supported uno service names of our derived class, which we provide
+ at the interface XServiceInfo of our class... */
+ css::uno::Sequence< OUString > m_lServiceNames;
+
+ /** @short local filter cache, which is used to collect changes on the
+ filter configuration first and flush it later.
+
+ @descr Normally this member isn't used nor initialized. That's true,
+ if this container is used for reading only. The first write access
+ (e.g. by calling insertByName()) creates a copy of the current
+ global cache m_rCache to initialize the m_pFlushCache member.
+
+ Afterwards only the flush cache copy is used. Inside flush() this
+ copy will be removed and m_rCache can be used again.
+
+ m_pFlushCache and m_rCache must not be synchronized manually here.
+ m_rCache listen on the global configuration, where m_pFlushCache
+ write its data. m_rCache update itself automatically.
+ */
+ std::unique_ptr<FilterCache> m_pFlushCache;
+
+ /** @short specify, which sub container of the used filter cache
+ must be wrapped by this container interface. */
+ FilterCache::EItemType m_eType;
+
+ /** @short holds all listener, which are registered at this instance. */
+ comphelper::OMultiTypeInterfaceContainerHelper2 m_lListener;
+
+
+ // native interface
+
+ public:
+
+
+ // ctor/dtor
+
+ /** @short standard ctor.
+
+ @descr Because mostly this class is used as base class for own service
+ implementations in combination with an ImplInheritanceHelper template...
+ there is no way to provide some initializing data through the ctor :-(
+ This base class will be created inside its default ctor and must be
+ initialized with its needed parameters explicitly by calling: "init()".
+
+ @see init()
+ */
+ BaseContainer();
+
+
+ /** @short standard dtor.
+ */
+ virtual ~BaseContainer() override;
+
+
+ /** @short initialize this generic instance with some specialized values
+ from our derived object.
+
+ @descr Because an outside class must use ImplInheritanceHelper template to
+ use us a base class... and there is no way to pass such initializing
+ parameters through a required default ctor... we must be initialized
+ by this special method. Of course this method must be called first before
+ any other interface method is used.
+
+ @param rxContext
+ reference to the uno service manager, which created this service instance.
+
+ @param sImplementationName
+ the implementation name of our derived class, which we provide
+ at the interface XServiceInfo of our class...
+
+ @param lServiceNames
+ the list of supported uno service names of our derived class, which we provide
+ at the interface XServiceInfo of our class...
+
+ @param eType
+ specify, which sub container of the used filter cache
+ must be wrapped by this container interface.
+ */
+ void init( const OUString& sImplementationName,
+ const css::uno::Sequence< OUString >& lServiceNames ,
+ FilterCache::EItemType eType );
+
+
+ // helper
+
+ protected:
+
+
+ /** @short check if the underlying configuration data was already loaded
+ and do it if necessary automatically.
+ */
+ void impl_loadOnDemand();
+
+
+ /** @short it creates the global instance m_pFilterCache, which is a copy
+ of the global instance m_rCache, and will be used to change the
+ configuration.
+
+ @descr If no exception occurs, its guaranteed, that the member m_rFlushCache
+ was initialized right and can be used further.
+
+ @throws css::uno::RuntimeException
+ */
+ void impl_initFlushMode();
+
+
+ /** @short returns a pointer to the current used cache member.
+
+ @descr It's a point to the FilterCache instance behind m_pFlushCache
+ or m_rCache.
+
+ @note The lifetime of this pointer is restricted to the time, where
+ the mutex of this BaseContainer instance is locked.
+ Otherwise may be the interface method flush() will destroy
+ m_pFlushCache and the here returned pointer will be invalid!
+
+ Use:
+
+ Guard aLock(m_aLock);
+ FilterCache* p = impl_getWorkingCache();
+ p->doSomething();
+ aLock.clear();
+ // after this point p can't b e guaranteed any longer!
+ */
+ FilterCache* impl_getWorkingCache() const;
+
+
+ // uno interface
+
+ public:
+
+
+ // XServiceInfo
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+
+ // XNameContainer
+
+ virtual void SAL_CALL insertByName(const OUString& sItem ,
+ const css::uno::Any& aValue) override;
+
+ virtual void SAL_CALL removeByName(const OUString& sItem) override;
+
+
+ // XNameReplace
+
+ virtual void SAL_CALL replaceByName(const OUString& sItem ,
+ const css::uno::Any& aValue) override;
+
+
+ // XElementAccess
+
+ virtual css::uno::Any SAL_CALL getByName(const OUString& sItem) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override;
+
+ virtual sal_Bool SAL_CALL hasByName(const OUString& sItem) override;
+
+ virtual css::uno::Type SAL_CALL getElementType() override;
+
+ virtual sal_Bool SAL_CALL hasElements() override;
+
+
+ // XContainerQuery
+
+ // must be implemented really by derived class...
+ // We implement return of an empty result here only!
+ // But we show an assertion :-)
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByQuery(const OUString& sQuery) override;
+
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByProperties(const css::uno::Sequence< css::beans::NamedValue >& lProperties) override;
+
+
+ // XFlushable
+
+ virtual void SAL_CALL flush() override;
+
+ virtual void SAL_CALL addFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener) override;
+
+ virtual void SAL_CALL removeFlushListener(const css::uno::Reference< css::util::XFlushListener >& xListener) override;
+};
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/cacheitem.cxx b/filter/source/config/cache/cacheitem.cxx
new file mode 100644
index 000000000..595d3891a
--- /dev/null
+++ b/filter/source/config/cache/cacheitem.cxx
@@ -0,0 +1,325 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "cacheitem.hxx"
+#include "constant.hxx"
+
+#include <com/sun/star/uno/Sequence.h>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <osl/diagnose.h>
+#include <comphelper/sequence.hxx>
+
+
+namespace filter::config{
+
+CacheItem::CacheItem()
+{
+}
+
+
+void CacheItem::update(const CacheItem& rUpdateItem)
+{
+ for (auto const& elem : rUpdateItem)
+ (*this)[elem.first] = elem.second;
+}
+
+
+void CacheItem::validateUINames(const OUString& sActLocale)
+{
+ if (sActLocale.isEmpty())
+ return;
+
+ // 1) check UINames first
+ const_iterator pUINames = find(PROPNAME_UINAMES);
+ const_iterator pUIName = find(PROPNAME_UINAME );
+
+ ::comphelper::SequenceAsHashMap lUINames;
+ if (pUINames != end())
+ lUINames << pUINames->second;
+
+ OUString sUIName;
+ if (pUIName != end())
+ pUIName->second >>= sUIName;
+
+ if (!sUIName.isEmpty())
+ {
+ // 1a) set UIName inside list of UINames for current locale
+ lUINames[sActLocale] <<= sUIName;
+ }
+ else if (!lUINames.empty())
+ {
+ // 1b) or get it from this list, if it not exist!
+ lUINames[sActLocale] >>= sUIName;
+ }
+
+ (*this)[PROPNAME_UINAMES] <<= lUINames.getAsConstPropertyValueList();
+ (*this)[PROPNAME_UINAME ] <<= sUIName;
+}
+
+
+css::uno::Sequence< css::beans::PropertyValue > CacheItem::getAsPackedPropertyValueList(bool bFinalized, bool bMandatory) const
+{
+ sal_Int32 c = static_cast<sal_Int32>(size());
+ sal_Int32 i = 0;
+
+ css::uno::Sequence< css::beans::PropertyValue > lList(c+2);
+ css::beans::PropertyValue* pList = lList.getArray();
+
+ for (const_iterator pProp = begin();
+ pProp != end() ;
+ ++pProp )
+ {
+ const OUString& rName = pProp->first.maString;
+ const css::uno::Any& rValue = pProp->second;
+
+ if (!rValue.hasValue())
+ continue;
+ assert (rName != PROPNAME_FINALIZED && rName != PROPNAME_MANDATORY);
+
+ pList[i].Name = rName ;
+ pList[i].Value = rValue;
+ ++i;
+ }
+ pList[i].Name = PROPNAME_FINALIZED ;
+ pList[i].Value <<= bFinalized;
+ ++i;
+ pList[i].Name = PROPNAME_MANDATORY ;
+ pList[i].Value <<= bMandatory;
+ ++i;
+ lList.realloc(i);
+
+ return lList;
+}
+
+
+static bool isSubSet(const css::uno::Any& aSubSet,
+ const css::uno::Any& aSet )
+{
+ const css::uno::Type& aT1 = aSubSet.getValueType();
+ const css::uno::Type& aT2 = aSet.getValueType();
+
+ if (!aT1.equals(aT2))
+ {
+ return false;
+ }
+
+ if (aSubSet.hasValue() && aSet.hasValue())
+ {
+ css::uno::TypeClass aTypeClass = aT1.getTypeClass();
+ switch(aTypeClass)
+ {
+
+ case css::uno::TypeClass_BOOLEAN :
+ case css::uno::TypeClass_BYTE :
+ case css::uno::TypeClass_SHORT :
+ case css::uno::TypeClass_UNSIGNED_SHORT :
+ case css::uno::TypeClass_LONG :
+ case css::uno::TypeClass_UNSIGNED_LONG :
+ case css::uno::TypeClass_HYPER :
+ case css::uno::TypeClass_UNSIGNED_HYPER :
+ case css::uno::TypeClass_FLOAT :
+ case css::uno::TypeClass_DOUBLE :
+ {
+ bool bIs = (aSubSet == aSet);
+ return bIs;
+ }
+
+
+ case css::uno::TypeClass_STRING :
+ return aSubSet == aSet;
+ break;
+
+
+ case css::uno::TypeClass_STRUCT :
+ {
+ css::beans::PropertyValue p1;
+ css::beans::PropertyValue p2;
+
+ if (
+ (aSubSet >>= p1) &&
+ (aSet >>= p2)
+ )
+ {
+ bool bIs = (p1.Name == p2.Name) && isSubSet(p1.Value, p2.Value);
+ return bIs;
+ }
+
+ css::beans::NamedValue n1;
+ css::beans::NamedValue n2;
+
+ if (
+ (aSubSet >>= n1) &&
+ (aSet >>= n2)
+ )
+ {
+ bool bIs = (n1.Name == n2.Name) && isSubSet(n1.Value, n2.Value);
+ return bIs;
+ }
+ }
+ break;
+
+
+ case css::uno::TypeClass_SEQUENCE :
+ {
+ css::uno::Sequence< OUString > uno_s1;
+ css::uno::Sequence< OUString > uno_s2;
+
+ if (
+ (aSubSet >>= uno_s1) &&
+ (aSet >>= uno_s2)
+ )
+ {
+ auto s2Begin = uno_s2.getConstArray();
+ auto s2End = uno_s2.getConstArray() + uno_s2.getLength();
+
+ for (auto const& elem : uno_s1)
+ {
+ if (::std::find(s2Begin, s2End, elem) == s2End)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ css::uno::Sequence< css::beans::PropertyValue > uno_p1;
+ css::uno::Sequence< css::beans::PropertyValue > uno_p2;
+
+ if (
+ (aSubSet >>= uno_p1) &&
+ (aSet >>= uno_p2)
+ )
+ {
+ ::comphelper::SequenceAsHashMap stl_p1(uno_p1);
+ ::comphelper::SequenceAsHashMap stl_p2(uno_p2);
+
+ for (auto const& elem : stl_p1)
+ {
+ ::comphelper::SequenceAsHashMap::const_iterator it2 = stl_p2.find(elem.first);
+ if (it2 == stl_p2.end())
+ {
+ return false;
+ }
+ if (!isSubSet(elem.second, it2->second))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ css::uno::Sequence< css::beans::NamedValue > uno_n1;
+ css::uno::Sequence< css::beans::NamedValue > uno_n2;
+
+ if (
+ (aSubSet >>= uno_n1) &&
+ (aSet >>= uno_n2)
+ )
+ {
+ ::comphelper::SequenceAsHashMap stl_n1(uno_n1);
+ ::comphelper::SequenceAsHashMap stl_n2(uno_n2);
+
+ for (auto const& elem : stl_n1)
+ {
+ ::comphelper::SequenceAsHashMap::const_iterator it2 = stl_n2.find(elem.first);
+ if (it2 == stl_n2.end())
+ {
+ return false;
+ }
+ if (!isSubSet(elem.second, it2->second))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+ OSL_FAIL("isSubSet() ... this point should not be reached!");
+ return false;
+}
+
+
+bool CacheItem::haveProps(o3tl::span< const css::beans::NamedValue > lProps) const
+{
+ for (auto const& prop : lProps)
+ {
+ // i) one required property does not exist at this item => return false
+ const_iterator pItThis = find(prop.Name);
+ if (pItThis == end())
+ {
+ return false;
+ }
+
+ // ii) one item does not have the right value => return false
+ if (!isSubSet(prop.Value, pItThis->second))
+ {
+ return false;
+ }
+ }
+
+ // this method was not broken before =>
+ // the given property set seems to match with our
+ // own properties in its minimum => return TRUE
+ return true;
+}
+
+
+bool CacheItem::dontHaveProps(o3tl::span< const css::beans::NamedValue > lProps) const
+{
+ for (auto const& prop : lProps)
+ {
+ // i) one item does not exist in general
+ // => continue with next one, because
+ // "excluding" means... "don't have it".
+ // And "not exists" matches to "don't have it".
+ const_iterator pItThis = find(prop.Name);
+ if (pItThis == end())
+ {
+ continue;
+ }
+
+ // ii) one item have the right value => return false
+ // because this item has the requested property...
+ // But we checked for "don't have it" here.
+ if (isSubSet(prop.Value, pItThis->second))
+ {
+ return false;
+ }
+ }
+
+ // this method was not broken before =>
+ // That means: this item has no matching property
+ // of the given set. It "don't have" it ... => return true.
+ return true;
+}
+
+FlatDetectionInfo::FlatDetectionInfo() :
+ bMatchByExtension(false), bMatchByPattern(false), bPreselectedByDocumentService(false) {}
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/cacheitem.hxx b/filter/source/config/cache/cacheitem.hxx
new file mode 100644
index 000000000..b20bf72c8
--- /dev/null
+++ b/filter/source/config/cache/cacheitem.hxx
@@ -0,0 +1,177 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <unordered_map>
+#include <com/sun/star/uno/Sequence.h>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <vector>
+#include <comphelper/sequenceashashmap.hxx>
+#include <o3tl/span.hxx>
+
+namespace filter::config {
+
+
+/** @short represent an item of a FilterCache
+ instance.
+
+ @descr This class is not threadsafe tp perform
+ operations, which use many instances of
+ this class! Synchronizations must be done outside.
+ */
+class CacheItem : public ::comphelper::SequenceAsHashMap
+{
+
+ public:
+
+
+ /** @short creates an empty item.
+ */
+ CacheItem();
+
+
+ /** @short update only properties, which are given by the
+ specified rItem.
+
+ @descr Update means: - add new properties
+ - change existing values
+
+ @param rUpdateItem
+ another cache item, which contains some special
+ properties, which should by used for updating
+ this one.
+ */
+ void update(const CacheItem& rUpdateItem);
+
+
+ /** @short check, if the given properties exist
+ at this item.
+
+ @descr All properties are compared in its minimum.
+ E.g: string lists => only the requested items
+ are checked. Additional existing items are ignored.
+
+ @param lProps
+ contains all properties, which must exist at this item.
+
+ @return sal_True if all given properties exists
+ at this item; sal_False otherwise.
+ */
+ bool haveProps(o3tl::span< const css::beans::NamedValue > lProps) const;
+
+
+ /** @short check, if the given properties don't exist
+ at this item.
+
+ @descr All properties are compared in its minimum.
+ E.g: string lists => only the requested items
+ are checked. Additional existing items are ignored.
+
+ @param lProps
+ contains all properties, which should not exist at this item.
+
+ @return sal_False if at least on property exists at this item(!);
+ sal_True otherwise.
+ */
+ bool dontHaveProps(o3tl::span< const css::beans::NamedValue > lProps) const;
+
+
+ /** @short because we know two UIName properties
+ (a list with all locales and the value
+ for the current locale only), we must be sure
+ that the correspond together.
+
+ @param sActLocale
+ must specify the current office locale.
+ It's needed to address the UIName property inside
+ the list of possible ones.
+ */
+ void validateUINames(const OUString& sActLocale);
+
+
+ /** @short convert this structure to a seq< PropertyValue >
+ and ignore all empty properties!
+
+ @descr Normally the converter routines of the base class
+ SequenceAsHashMap do this job already.
+ But it doesn't provide a "pack" mechanism to
+ ignore properties with empty (means "void") values.
+
+ @return css::uno::Sequence< css::beans::PropertyValue >
+ as a list of all properties of this cacheitem,
+ where empty properties was removed.
+ */
+ css::uno::Sequence< css::beans::PropertyValue > getAsPackedPropertyValueList(bool bFinalized, bool bMandatory) const;
+};
+
+
+/** @short represent an item list of a FilterCache
+ instance.
+ */
+typedef std::unordered_map< OUString,
+ CacheItem > CacheItemList;
+
+
+/** @short supports registration of multiple key to
+ another string information.
+
+ @descr E.g. a list of internal type names can be registered
+ to an extension. Organization as an hash makes it
+ faster than searching inside vectors.
+
+ On the other side e.g. URLPattern can't be really addressed
+ by a hash value ... because the use wildcards. But
+ there we need key-value pairs too, which can't be provided
+ by a pure vector!
+ */
+typedef std::unordered_map< OUString,
+ std::vector<OUString> > CacheItemRegistration;
+
+
+/** @short is used to collect all matching types of a URL
+ during type detection.
+
+ @descr Every type in this list is combined with an information,
+ which property matched to the given URL. The user of this
+ structure can decide then, if a deep detection should be
+ suppressed e.g. if a URLPattern was used.
+ */
+struct FlatDetectionInfo
+{
+ // the internal type name
+ OUString sType;
+
+ // this type was found by a matching the URL extension
+ bool bMatchByExtension;
+
+ // this type was found by a matching URL Pattern
+ bool bMatchByPattern;
+
+ // the user selected this type implicit by selecting a corresponding office module
+ bool bPreselectedByDocumentService;
+
+ FlatDetectionInfo();
+};
+
+typedef ::std::vector< FlatDetectionInfo > FlatDetection;
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/cacheupdatelistener.cxx b/filter/source/config/cache/cacheupdatelistener.cxx
new file mode 100644
index 000000000..c613d0549
--- /dev/null
+++ b/filter/source/config/cache/cacheupdatelistener.cxx
@@ -0,0 +1,182 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "cacheupdatelistener.hxx"
+#include "configflush.hxx"
+
+#include <com/sun/star/util/XChangesNotifier.hpp>
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <unotools/configpaths.hxx>
+#include <rtl/ustring.hxx>
+#include <comphelper/processfactory.hxx>
+#include <utility>
+
+
+namespace filter::config{
+
+CacheUpdateListener::CacheUpdateListener(FilterCache &rFilterCache,
+ css::uno::Reference< css::uno::XInterface > xConfigAccess,
+ FilterCache::EItemType eConfigType)
+ : m_rCache(rFilterCache)
+ , m_xConfig(std::move(xConfigAccess))
+ , m_eConfigType(eConfigType)
+{
+}
+
+CacheUpdateListener::~CacheUpdateListener()
+{
+}
+
+void CacheUpdateListener::startListening()
+{
+ // SAFE ->
+ std::unique_lock aLock(m_aMutex);
+ css::uno::Reference< css::util::XChangesNotifier > xNotifier(m_xConfig, css::uno::UNO_QUERY);
+ aLock.unlock();
+ // <- SAFE
+
+ if (!xNotifier.is())
+ return;
+
+ css::uno::Reference< css::util::XChangesListener > xThis(this);
+ xNotifier->addChangesListener(xThis);
+}
+
+
+void CacheUpdateListener::stopListening()
+{
+ // SAFE ->
+ std::unique_lock aLock(m_aMutex);
+ css::uno::Reference< css::util::XChangesNotifier > xNotifier(m_xConfig, css::uno::UNO_QUERY);
+ aLock.unlock();
+ // <- SAFE
+
+ if (!xNotifier.is())
+ return;
+
+ css::uno::Reference< css::util::XChangesListener > xThis(this);
+ xNotifier->removeChangesListener(xThis);
+}
+
+
+void SAL_CALL CacheUpdateListener::changesOccurred(const css::util::ChangesEvent& aEvent)
+{
+ // SAFE ->
+ std::unique_lock aLock(m_aMutex);
+
+ // disposed ?
+ if ( ! m_xConfig.is())
+ return;
+
+ FilterCache::EItemType eType = m_eConfigType;
+
+ aLock.unlock();
+ // <- SAFE
+
+ std::vector<OUString> lChangedItems;
+ sal_Int32 c = aEvent.Changes.getLength();
+ sal_Int32 i = 0;
+
+ for (i=0; i<c; ++i)
+ {
+ const css::util::ElementChange& aChange = aEvent.Changes[i];
+
+ OUString sOrgPath ;
+ OUString sTempPath;
+
+ OUString sProperty;
+ OUString sNode ;
+ OUString sLocale ;
+
+ /* at least we must be able to retrieve 2 path elements
+ But sometimes the original path can contain 3 of them ... in case
+ a localized value was changed.
+ =>
+ 1) Filters/Filter["filtername"]/Property
+ 2) Filters/Filter["filtername"]/LocalizedProperty/Locale
+ */
+
+ aChange.Accessor >>= sOrgPath;
+ if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sLocale))
+ continue;
+ sOrgPath = sTempPath;
+ if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sProperty))
+ {
+ sNode = sLocale;
+ sProperty.clear();
+ sLocale.clear();
+ }
+ else
+ {
+ sOrgPath = sTempPath;
+ if ( ! ::utl::splitLastFromConfigurationPath(sOrgPath, sTempPath, sNode))
+ {
+ sNode = sProperty;
+ sProperty = sLocale;
+ sLocale.clear();
+ }
+ }
+
+ if ( sNode.isEmpty() )
+ continue;
+
+ auto pIt = ::std::find(lChangedItems.cbegin(), lChangedItems.cend(), sNode);
+ if (pIt == lChangedItems.cend())
+ lChangedItems.push_back(sNode);
+ }
+
+ bool bNotifyRefresh = false;
+ for (auto const& changedItem : lChangedItems)
+ {
+ try
+ {
+ m_rCache.refreshItem(eType, changedItem);
+ }
+ catch(const css::container::NoSuchElementException&)
+ {
+ // can be ignored! Because we must be aware that
+ // sItem was removed from the configuration and we forced an update of the cache.
+ // But we know, that the cache is up-to-date know and has thrown this exception afterwards .-)
+ }
+ // NO FLUSH! Otherwise we start a never ending story here .-)
+ bNotifyRefresh = true;
+ }
+
+ // notify sfx cache about the changed filter cache .-)
+ if (bNotifyRefresh)
+ {
+ rtl::Reference< ConfigFlush > xRefreshBroadcaster = new ConfigFlush();
+ xRefreshBroadcaster->refresh();
+ }
+}
+
+
+void SAL_CALL CacheUpdateListener::disposing(const css::lang::EventObject& aEvent)
+{
+ // SAFE ->
+ std::unique_lock aLock(m_aMutex);
+ if (aEvent.Source == m_xConfig)
+ m_xConfig.clear();
+ // <- SAFE
+}
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/cacheupdatelistener.hxx b/filter/source/config/cache/cacheupdatelistener.hxx
new file mode 100644
index 000000000..3870b9916
--- /dev/null
+++ b/filter/source/config/cache/cacheupdatelistener.hxx
@@ -0,0 +1,113 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "filtercache.hxx"
+#include <com/sun/star/util/XChangesListener.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <mutex>
+
+
+namespace filter::config {
+
+
+/** @short implements a listener, which will update the
+ global filter cache, if the underlying configuration
+ wa changed by other processes.
+ */
+class CacheUpdateListener : public ::cppu::WeakImplHelper< css::util::XChangesListener >
+{
+
+ // member
+
+ private:
+
+ std::mutex m_aMutex;
+
+ /** @short reference to the singleton(!) filter cache implementation,
+ which should be updated by this thread. */
+ FilterCache &m_rCache;
+
+ /** @short holds the configuration access, where we listen alive. */
+ css::uno::Reference< css::uno::XInterface > m_xConfig;
+
+ /** @short every instance of this update listener listen on
+ a special sub set of the filter configuration.
+ So it should know, which type of configuration entry
+ it must put into the filter cache, if the configuration notifies changes ... */
+ FilterCache::EItemType m_eConfigType;
+
+
+ // native interface
+
+ public:
+
+
+ // ctor/dtor
+
+ /** @short initialize new instance of this class.
+
+ @descr Listening won't be started here. It can be done
+ by calling startListening() on this instance.
+
+ @see startListening()
+
+ @param xConfigAccess
+ the configuration access, where this instance should listen for changes.
+
+ @param eConfigType
+ specify the type of configuration.
+ */
+ CacheUpdateListener(FilterCache &rFilterCache,
+ css::uno::Reference< css::uno::XInterface > xConfigAccess,
+ FilterCache::EItemType eConfigType);
+
+
+ /** @short standard dtor.
+ */
+ virtual ~CacheUpdateListener() override;
+
+
+ /** @short starts listening.
+ */
+ void startListening();
+
+
+ /** @short stop listening.
+ */
+ void stopListening();
+
+
+ // uno interface
+
+ public:
+
+
+ // XChangesListener
+
+ virtual void SAL_CALL changesOccurred(const css::util::ChangesEvent& aEvent) override;
+
+
+ // lang.XEventListener
+ virtual void SAL_CALL disposing(const css::lang::EventObject& aEvent) override;
+};
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/configflush.cxx b/filter/source/config/cache/configflush.cxx
new file mode 100644
index 000000000..34ac28782
--- /dev/null
+++ b/filter/source/config/cache/configflush.cxx
@@ -0,0 +1,112 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "configflush.hxx"
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+
+namespace filter::config{
+
+ConfigFlush::ConfigFlush()
+ : m_lListener(m_aMutex)
+{
+}
+
+ConfigFlush::~ConfigFlush()
+{
+}
+
+OUString SAL_CALL ConfigFlush::getImplementationName()
+{
+ return "com.sun.star.comp.filter.config.ConfigFlush";
+ // <- SAFE
+}
+
+sal_Bool SAL_CALL ConfigFlush::supportsService(const OUString& sServiceName)
+{
+ return cppu::supportsService(this, sServiceName);
+}
+
+css::uno::Sequence< OUString > SAL_CALL ConfigFlush::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.FilterConfigRefresh" };
+}
+
+void SAL_CALL ConfigFlush::refresh()
+{
+ // notify listener outside the lock!
+ // The used listener helper lives if we live
+ // and is threadsafe by itself.
+ // Further it's not a good idea to hold the own lock
+ // if an outside object is called :-)
+ css::lang::EventObject aSource (static_cast< css::util::XRefreshable* >(this));
+ comphelper::OInterfaceContainerHelper2* pContainer = m_lListener.getContainer(cppu::UnoType<css::util::XRefreshListener>::get());
+ if (!pContainer)
+ return;
+
+ comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
+ while (pIterator.hasMoreElements())
+ {
+ try
+ {
+ // ... this pointer can be interesting to find out, where will be called as listener
+ // Don't optimize it to a direct iterator cast :-)
+ css::util::XRefreshListener* pListener = static_cast<css::util::XRefreshListener*>(pIterator.next());
+ pListener->refreshed(aSource);
+ }
+ catch(const css::uno::Exception&)
+ {
+ // ignore any "damaged" flush listener!
+ // May its remote reference is broken ...
+ pIterator.remove();
+ }
+ }
+}
+
+
+void SAL_CALL ConfigFlush::addRefreshListener(const css::uno::Reference< css::util::XRefreshListener >& xListener)
+{
+ // no locks necessary
+ // used helper lives if we live and is threadsafe by itself ...
+ m_lListener.addInterface(cppu::UnoType<css::util::XRefreshListener>::get(),
+ xListener);
+}
+
+
+void SAL_CALL ConfigFlush::removeRefreshListener(const css::uno::Reference< css::util::XRefreshListener >& xListener)
+{
+ // no locks necessary
+ // used helper lives if we live and is threadsafe by itself ...
+ m_lListener.removeInterface(cppu::UnoType<css::util::XRefreshListener>::get(),
+ xListener);
+}
+
+
+} // namespace filter::config
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_ConfigFlush_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new filter::config::ConfigFlush());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/configflush.hxx b/filter/source/config/cache/configflush.hxx
new file mode 100644
index 000000000..d03351673
--- /dev/null
+++ b/filter/source/config/cache/configflush.hxx
@@ -0,0 +1,89 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/util/XRefreshable.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <comphelper/multicontainer2.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+
+
+namespace filter::config {
+
+
+/** @short supports registration of XRefreshListener
+ on the global filter configuration.
+
+ @descr Such refresh listener will be called in case the
+ type/filter configuration will be changed at runtime.
+ */
+class ConfigFlush final : public cppu::BaseMutex
+ , public ::cppu::WeakImplHelper<
+ css::util::XRefreshable,
+ css::lang::XServiceInfo
+ >
+{
+ /** @short holds all listener, which are registered at this instance. */
+ comphelper::OMultiTypeInterfaceContainerHelper2 m_lListener;
+
+
+ // native interface
+
+ public:
+
+
+ // ctor/dtor
+
+ /** @short standard ctor.
+ */
+ ConfigFlush();
+
+
+ /** @short standard dtor.
+ */
+ virtual ~ConfigFlush() override;
+
+
+ // uno interface
+
+ public:
+
+
+ // XServiceInfo
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+
+ // XRefreshable
+
+ virtual void SAL_CALL refresh() override;
+
+ virtual void SAL_CALL addRefreshListener(const css::uno::Reference< css::util::XRefreshListener >& xListener) override;
+
+ virtual void SAL_CALL removeRefreshListener(const css::uno::Reference< css::util::XRefreshListener >& xListener) override;
+};
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/constant.hxx b/filter/source/config/cache/constant.hxx
new file mode 100644
index 000000000..86e6e6de9
--- /dev/null
+++ b/filter/source/config/cache/constant.hxx
@@ -0,0 +1,153 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <rtl/ustring.hxx>
+
+/* disable impl_loadOnDemand function of BaseContainer for certain
+ functions, where it the feature "impl_loadItemOnDemand() of class FilterCache
+ can be used instead of loadAll()!*/
+// #define LOAD_IMPLICIT
+
+
+/** @short used to identify a some generic item properties against the
+ configuration API and can be used at all name containers
+ (based on this filtercache) too.
+ */
+inline constexpr OUStringLiteral PROPNAME_NAME = u"Name";
+
+/** @short used to identify a type item property against the
+ configuration API and can be used at all name containers
+ (based on this filtercache) too.
+ */
+inline constexpr OUStringLiteral PROPNAME_UINAME = u"UIName";
+inline constexpr OUStringLiteral PROPNAME_UINAMES = u"UINames";
+inline constexpr OUStringLiteral PROPNAME_PREFERRED = u"Preferred";
+inline constexpr OUStringLiteral PROPNAME_PREFERREDFILTER = u"PreferredFilter";
+inline constexpr OUStringLiteral PROPNAME_DETECTSERVICE = u"DetectService";
+inline constexpr OUStringLiteral PROPNAME_MEDIATYPE = u"MediaType";
+inline constexpr OUStringLiteral PROPNAME_CLIPBOARDFORMAT = u"ClipboardFormat";
+inline constexpr OUStringLiteral PROPNAME_URLPATTERN = u"URLPattern";
+inline constexpr OUStringLiteral PROPNAME_EXTENSIONS = u"Extensions";
+
+/** @short used to identify a filter item property against the
+ configuration API and can be used at all name containers
+ (based on this filtercache) too.
+ */
+inline constexpr OUStringLiteral PROPNAME_TYPE = u"Type";
+inline constexpr OUStringLiteral PROPNAME_DOCUMENTSERVICE = u"DocumentService";
+inline constexpr OUStringLiteral PROPNAME_FILTERSERVICE = u"FilterService";
+inline constexpr OUStringLiteral PROPNAME_UICOMPONENT = u"UIComponent";
+inline constexpr OUStringLiteral PROPNAME_FLAGS = u"Flags";
+inline constexpr OUStringLiteral PROPNAME_USERDATA = u"UserData";
+inline constexpr OUStringLiteral PROPNAME_TEMPLATENAME = u"TemplateName";
+inline constexpr OUStringLiteral PROPNAME_FILEFORMATVERSION = u"FileFormatVersion";
+inline constexpr OUStringLiteral PROPNAME_EXPORTEXTENSION = u"ExportExtension";
+inline constexpr OUStringLiteral PROPNAME_ENABLED = u"Enabled";
+
+/** @short used to identify a frame loader or detect service item
+ property against the configuration API and can be used
+ at all name containers (based on this filtercache) too.
+ */
+inline constexpr OUStringLiteral PROPNAME_TYPES = u"Types";
+
+/** @short used to identify the list of sorted filters for a specific
+ office module
+ */
+inline constexpr OUStringLiteral PROPNAME_SORTEDFILTERLIST = u"SortedFilterList";
+
+/** @short implicit properties. which are used at the container interface only.
+ */
+inline constexpr OUStringLiteral PROPNAME_FINALIZED = u"Finalized";
+inline constexpr OUStringLiteral PROPNAME_MANDATORY = u"Mandatory";
+
+/** @short used to identify a set of items against the configuration API. */
+inline constexpr OUStringLiteral CFGSET_TYPES = u"Types";
+inline constexpr OUStringLiteral CFGSET_FILTERS = u"Filters";
+inline constexpr OUStringLiteral CFGSET_FRAMELOADERS = u"FrameLoaders";
+inline constexpr OUStringLiteral CFGSET_CONTENTHANDLERS = u"ContentHandlers";
+
+/** @short used to address some configuration keys directly.
+
+ @descr Such direct keys should be used with function
+ FilterCache::impl_getDirectCFGValue() only!
+
+ @TODO define these direct keys ...
+ */
+inline constexpr OUStringLiteral CFGDIRECTKEY_OFFICELOCALE = u"/org.openoffice.Setup/L10N/ooLocale";
+inline constexpr OUStringLiteral CFGDIRECTKEY_DEFAULTFRAMELOADER = u"/org.openoffice.TypeDetection.Misc/Defaults/DefaultFrameLoader";
+#define CFGDIRECTKEY_PRODUCTNAME "/org.openoffice.Setup/Product/ooName"
+
+// Note that these flag bits have parallel names in
+// comphelper/inc/comphelper/documentconstants.hxx . See that file for
+// documentation on their meaning.
+
+/** @short names of filter flags, sorted in alphabetical order */
+inline constexpr OUStringLiteral FLAGNAME_3RDPARTYFILTER = u"3RDPARTYFILTER";
+inline constexpr OUStringLiteral FLAGNAME_ALIEN = u"ALIEN";
+inline constexpr OUStringLiteral FLAGNAME_CONSULTSERVICE = u"CONSULTSERVICE";
+inline constexpr OUStringLiteral FLAGNAME_DEFAULT = u"DEFAULT";
+inline constexpr OUStringLiteral FLAGNAME_ENCRYPTION = u"ENCRYPTION";
+inline constexpr OUStringLiteral FLAGNAME_EXPORT = u"EXPORT";
+inline constexpr OUStringLiteral FLAGNAME_GPGENCRYPTION = u"GPGENCRYPTION";
+inline constexpr OUStringLiteral FLAGNAME_IMPORT = u"IMPORT";
+inline constexpr OUStringLiteral FLAGNAME_INTERNAL = u"INTERNAL";
+inline constexpr OUStringLiteral FLAGNAME_NOTINFILEDIALOG = u"NOTINFILEDIALOG";
+inline constexpr OUStringLiteral FLAGNAME_NOTINSTALLED = u"NOTINSTALLED";
+inline constexpr OUStringLiteral FLAGNAME_OWN = u"OWN";
+inline constexpr OUStringLiteral FLAGNAME_PACKED = u"PACKED";
+inline constexpr OUStringLiteral FLAGNAME_PASSWORDTOMODIFY = u"PASSWORDTOMODIFY";
+inline constexpr OUStringLiteral FLAGNAME_PREFERRED = u"PREFERRED";
+inline constexpr OUStringLiteral FLAGNAME_STARTPRESENTATION = u"STARTPRESENTATION";
+inline constexpr OUStringLiteral FLAGNAME_READONLY = u"READONLY";
+inline constexpr OUStringLiteral FLAGNAME_SUPPORTSSELECTION = u"SUPPORTSSELECTION";
+inline constexpr OUStringLiteral FLAGNAME_TEMPLATE = u"TEMPLATE";
+inline constexpr OUStringLiteral FLAGNAME_TEMPLATEPATH = u"TEMPLATEPATH";
+inline constexpr OUStringLiteral FLAGNAME_COMBINED = u"COMBINED";
+inline constexpr OUStringLiteral FLAGNAME_SUPPORTSSIGNING = u"SUPPORTSSIGNING";
+inline constexpr OUStringLiteral FLAGNAME_EXOTIC = u"EXOTIC";
+
+/** @short some uno service names.
+ */
+inline constexpr OUStringLiteral SERVICE_CONFIGURATIONUPDATEACCESS = u"com.sun.star.configuration.ConfigurationUpdateAccess";
+inline constexpr OUStringLiteral SERVICE_CONFIGURATIONACCESS = u"com.sun.star.configuration.ConfigurationAccess";
+
+/** @short some configuration paths.
+ */
+inline constexpr OUStringLiteral CFGPACKAGE_TD_TYPES = u"/org.openoffice.TypeDetection.Types";
+inline constexpr OUStringLiteral CFGPACKAGE_TD_FILTERS = u"/org.openoffice.TypeDetection.Filter";
+inline constexpr OUStringLiteral CFGPACKAGE_TD_OTHERS = u"/org.openoffice.TypeDetection.Misc";
+inline constexpr OUStringLiteral CFGPACKAGE_TD_OLD = u"/org.openoffice.Office.TypeDetection";
+
+/** @short some default values.
+ */
+inline constexpr OUStringLiteral DEFAULT_OFFICELOCALE = u"en-US";
+
+/** @short used for the queries of the FilterFactory service.
+ */
+inline constexpr OUStringLiteral QUERY_IDENTIFIER_MATCHBYDOCUMENTSERVICE = u"matchByDocumentService";
+inline constexpr OUStringLiteral QUERY_IDENTIFIER_GETPREFERREDFILTERFORTYPE = u"getDefaultFilterForType";
+inline constexpr OUStringLiteral QUERY_IDENTIFIER_GET_SORTED_FILTERLIST = u"getSortedFilterList()";
+
+inline constexpr OUStringLiteral QUERY_PARAM_IFLAGS = u"iflags";
+inline constexpr OUStringLiteral QUERY_PARAM_EFLAGS = u"eflags";
+inline constexpr OUStringLiteral QUERY_PARAM_MODULE = u"module";
+#define QUERY_CONSTVALUE_ALL "all"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/contenthandlerfactory.cxx b/filter/source/config/cache/contenthandlerfactory.cxx
new file mode 100644
index 000000000..089f8db5f
--- /dev/null
+++ b/filter/source/config/cache/contenthandlerfactory.cxx
@@ -0,0 +1,103 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "contenthandlerfactory.hxx"
+
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <comphelper/sequence.hxx>
+
+
+namespace filter::config{
+
+ContentHandlerFactory::ContentHandlerFactory(const css::uno::Reference< css::uno::XComponentContext >& rxContext)
+ : m_xContext(rxContext)
+{
+ BaseContainer::init("com.sun.star.comp.filter.config.ContentHandlerFactory" ,
+ { "com.sun.star.frame.ContentHandlerFactory" },
+ FilterCache::E_CONTENTHANDLER );
+}
+
+
+ContentHandlerFactory::~ContentHandlerFactory()
+{
+}
+
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL ContentHandlerFactory::createInstance(const OUString& sHandler)
+{
+ return createInstanceWithArguments(sHandler, css::uno::Sequence< css::uno::Any >());
+}
+
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL ContentHandlerFactory::createInstanceWithArguments(const OUString& sHandler ,
+ const css::uno::Sequence< css::uno::Any >& lArguments)
+{
+ css::uno::Reference< css::uno::XInterface > xHandler;
+
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ auto & cache = GetTheFilterCache();
+
+ // search handler on cache
+ CacheItem aHandler = cache.getItem(FilterCache::E_CONTENTHANDLER, sHandler);
+
+ // create service instance
+ xHandler = m_xContext->getServiceManager()->createInstanceWithContext(sHandler, m_xContext);
+
+ // initialize filter
+ css::uno::Reference< css::lang::XInitialization > xInit(xHandler, css::uno::UNO_QUERY);
+ if (xInit.is())
+ {
+ // format: lInitData[0] = seq<PropertyValue>, which contains all configuration properties of this handler
+ // lInitData[1] = lArguments[0]
+ // ...
+ // lInitData[n] = lArguments[n-1]
+ css::uno::Sequence< css::beans::PropertyValue > lConfig;
+ aHandler >> lConfig;
+
+ ::std::vector< css::uno::Any > stlArguments(comphelper::sequenceToContainer< ::std::vector< css::uno::Any > >(lArguments));
+ stlArguments.insert(stlArguments.begin(), css::uno::Any(lConfig));
+
+ xInit->initialize(comphelper::containerToSequence(stlArguments));
+ }
+
+ return xHandler;
+ // <- SAFE
+}
+
+
+css::uno::Sequence< OUString > SAL_CALL ContentHandlerFactory::getAvailableServiceNames()
+{
+ // must be the same list as ((XNameAccess*)this)->getElementNames() return!
+ return BaseContainer::getElementNames();
+}
+
+} // namespace filter::config
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_ContentHandlerFactory_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new filter::config::ContentHandlerFactory(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/contenthandlerfactory.hxx b/filter/source/config/cache/contenthandlerfactory.hxx
new file mode 100644
index 000000000..5c3ecd760
--- /dev/null
+++ b/filter/source/config/cache/contenthandlerfactory.hxx
@@ -0,0 +1,99 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "basecontainer.hxx"
+#include <com/sun/star/frame/XLoaderFactory.hpp>
+#include <cppuhelper/implbase.hxx>
+
+
+namespace filter::config {
+
+
+/** @short implements the service <type scope="com.sun.star.document">ContentHandlerFactory</type>.
+ */
+class ContentHandlerFactory : public ::cppu::ImplInheritanceHelper< BaseContainer ,
+ css::frame::XLoaderFactory >
+{
+
+ // native interface
+
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+
+ public:
+
+
+ // ctor/dtor
+
+ /** @short standard ctor to connect this interface wrapper to
+ the global filter cache instance ...
+
+ @param rxContext
+ reference to the uno service manager, which created this service instance.
+ */
+ explicit ContentHandlerFactory(const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+
+
+ /** @short standard dtor.
+ */
+ virtual ~ContentHandlerFactory() override;
+
+
+ // uno interface
+
+ public:
+
+
+ // XMultiServiceFactory
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const OUString& sHandler) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const OUString& sHandler ,
+ const css::uno::Sequence< css::uno::Any >& lArguments) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
+
+
+ public:
+
+ // Overrides to resolve ambiguity
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override
+ { return BaseContainer::getByName(aName); }
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
+ { return BaseContainer::getElementNames(); }
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
+ { return BaseContainer::hasByName(aName); }
+
+ virtual css::uno::Type SAL_CALL getElementType() override
+ { return BaseContainer::getElementType(); }
+ virtual sal_Bool SAL_CALL hasElements() override
+ { return BaseContainer::hasElements(); }
+
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByQuery( const OUString& Query ) override
+ { return BaseContainer::createSubSetEnumerationByQuery(Query); }
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByProperties( const css::uno::Sequence< css::beans::NamedValue >& Properties ) override
+ { return BaseContainer::createSubSetEnumerationByProperties(Properties); }
+
+
+};
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/filtercache.cxx b/filter/source/config/cache/filtercache.cxx
new file mode 100644
index 000000000..b32586162
--- /dev/null
+++ b/filter/source/config/cache/filtercache.cxx
@@ -0,0 +1,2236 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <memory>
+#include <tools/diagnose_ex.h>
+#include "filtercache.hxx"
+#include "constant.hxx"
+#include "cacheupdatelistener.hxx"
+
+/*TODO see using below ... */
+#define AS_ENABLE_FILTER_UINAMES
+
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XProperty.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/document/CorruptedFilterConfigurationException.hpp>
+#include <comphelper/sequence.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include <unotools/configmgr.hxx>
+#include <unotools/configpaths.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/uri.hxx>
+#include <sal/log.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/wldcrd.hxx>
+#include <i18nlangtag/languagetag.hxx>
+
+#include <officecfg/Setup.hxx>
+#include <o3tl/string_view.hxx>
+
+
+namespace filter::config{
+
+FilterCache::FilterCache()
+ : m_eFillState(E_CONTAINS_NOTHING )
+{
+ int i = 0;
+ OUString sStandardProps[10];
+
+ sStandardProps[i++] = PROPNAME_USERDATA;
+ sStandardProps[i++] = PROPNAME_TEMPLATENAME;
+ sStandardProps[i++] = PROPNAME_ENABLED;
+ // E_READ_UPDATE only above
+ sStandardProps[i++] = PROPNAME_TYPE;
+ sStandardProps[i++] = PROPNAME_FILEFORMATVERSION;
+ sStandardProps[i++] = PROPNAME_UICOMPONENT;
+ sStandardProps[i++] = PROPNAME_FILTERSERVICE;
+ sStandardProps[i++] = PROPNAME_DOCUMENTSERVICE;
+ sStandardProps[i++] = PROPNAME_EXPORTEXTENSION;
+ sStandardProps[i++] = PROPNAME_FLAGS; // must be last.
+ assert(i == SAL_N_ELEMENTS(sStandardProps));
+
+ // E_READ_NOTHING -> creative nothingness.
+ m_aStandardProps[E_READ_STANDARD] =
+ css::uno::Sequence< OUString >(sStandardProps + 3, 7);
+ m_aStandardProps[E_READ_UPDATE] =
+ css::uno::Sequence< OUString >(sStandardProps, 3);
+ m_aStandardProps[E_READ_ALL] =
+ css::uno::Sequence< OUString >(sStandardProps,
+ SAL_N_ELEMENTS(sStandardProps));
+
+ i = 0;
+ OUString sTypeProps[7];
+ sTypeProps[i++] = PROPNAME_MEDIATYPE;
+ // E_READ_UPDATE only above
+ sTypeProps[i++] = PROPNAME_PREFERREDFILTER;
+ sTypeProps[i++] = PROPNAME_DETECTSERVICE;
+ sTypeProps[i++] = PROPNAME_URLPATTERN;
+ sTypeProps[i++] = PROPNAME_EXTENSIONS;
+ sTypeProps[i++] = PROPNAME_PREFERRED;
+ sTypeProps[i++] = PROPNAME_CLIPBOARDFORMAT;
+ assert(i == SAL_N_ELEMENTS(sTypeProps));
+
+ // E_READ_NOTHING -> more creative nothingness.
+ m_aTypeProps[E_READ_STANDARD] =
+ css::uno::Sequence< OUString >(sTypeProps + 1, 6);
+ m_aTypeProps[E_READ_UPDATE] =
+ css::uno::Sequence< OUString >(sTypeProps, 1);
+ m_aTypeProps[E_READ_ALL] =
+ css::uno::Sequence< OUString >(sTypeProps,
+ SAL_N_ELEMENTS(sTypeProps));
+}
+
+
+FilterCache::~FilterCache()
+{
+ if (m_xTypesChglisteners.is())
+ m_xTypesChglisteners->stopListening();
+ if (m_xFiltersChgListener.is())
+ m_xFiltersChgListener->stopListening();
+}
+
+
+std::unique_ptr<FilterCache> FilterCache::clone() const
+{
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ auto pClone = std::make_unique<FilterCache>();
+
+ // Don't copy the configuration access points here.
+ // They will be created on demand inside the cloned instance,
+ // if they are needed.
+
+ pClone->m_lTypes = m_lTypes;
+ pClone->m_lFilters = m_lFilters;
+ pClone->m_lFrameLoaders = m_lFrameLoaders;
+ pClone->m_lContentHandlers = m_lContentHandlers;
+ pClone->m_lExtensions2Types = m_lExtensions2Types;
+ pClone->m_lURLPattern2Types = m_lURLPattern2Types;
+
+ pClone->m_sActLocale = m_sActLocale;
+
+ pClone->m_eFillState = m_eFillState;
+
+ pClone->m_lChangedTypes = m_lChangedTypes;
+ pClone->m_lChangedFilters = m_lChangedFilters;
+ pClone->m_lChangedFrameLoaders = m_lChangedFrameLoaders;
+ pClone->m_lChangedContentHandlers = m_lChangedContentHandlers;
+
+ return pClone;
+ // <- SAFE ----------------------------------
+}
+
+
+void FilterCache::takeOver(const FilterCache& rClone)
+{
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ // a)
+ // Don't copy the configuration access points here!
+ // We must use our own ones...
+
+ // b)
+ // Further we can ignore the uno service manager.
+ // We should already have a valid instance.
+
+ // c)
+ // Take over only changed items!
+ // Otherwise we risk the following scenario:
+ // c1) clone_1 contains changed filters
+ // c2) clone_2 container changed types
+ // c3) clone_1 take over changed filters and unchanged types
+ // c4) clone_2 take over unchanged filters(!) and changed types(!)
+ // c5) c4 overwrites c3!
+
+ if (!rClone.m_lChangedTypes.empty())
+ m_lTypes = rClone.m_lTypes;
+ if (!rClone.m_lChangedFilters.empty())
+ m_lFilters = rClone.m_lFilters;
+ if (!rClone.m_lChangedFrameLoaders.empty())
+ m_lFrameLoaders = rClone.m_lFrameLoaders;
+ if (!rClone.m_lChangedContentHandlers.empty())
+ m_lContentHandlers = rClone.m_lContentHandlers;
+
+ m_lChangedTypes.clear();
+ m_lChangedFilters.clear();
+ m_lChangedFrameLoaders.clear();
+ m_lChangedContentHandlers.clear();
+
+ m_sActLocale = rClone.m_sActLocale;
+
+ m_eFillState = rClone.m_eFillState;
+
+ // renew all dependencies and optimizations
+ // Because we can't be sure, that changed filters on one clone
+ // and changed types of another clone work together.
+ // But here we can check against the later changes...
+ impl_validateAndOptimize();
+ // <- SAFE ----------------------------------
+}
+
+void FilterCache::load(EFillState eRequired)
+{
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ // check if required fill state is already reached ...
+ // There is nothing to do then.
+ if ((m_eFillState & eRequired) == eRequired)
+ return;
+
+ // Otherwise load the missing items.
+
+
+ // a) load some const values from configuration.
+ // These values are needed there for loading
+ // config items ...
+ // Further we load some std items from the
+ // configuration so we can try to load the first
+ // office document with a minimal set of values.
+ if (m_eFillState == E_CONTAINS_NOTHING)
+ {
+ impl_getDirectCFGValue(CFGDIRECTKEY_OFFICELOCALE) >>= m_sActLocale;
+ if (m_sActLocale.isEmpty())
+ {
+ m_sActLocale = DEFAULT_OFFICELOCALE;
+ }
+
+ // Support the old configuration support. Read it only one times during office runtime!
+ impl_readOldFormat();
+ }
+
+
+ // b) If the required fill state was not reached
+ // but std values was already loaded ...
+ // we must load some further missing items.
+ impl_load(eRequired);
+ // <- SAFE
+}
+
+bool FilterCache::isFillState(FilterCache::EFillState eState) const
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+ return ((m_eFillState & eState) == eState);
+ // <- SAFE
+}
+
+
+std::vector<OUString> FilterCache::getMatchingItemsByProps( EItemType eType ,
+ o3tl::span< const css::beans::NamedValue > lIProps,
+ o3tl::span< const css::beans::NamedValue > lEProps) const
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // search for right list
+ // An exception is thrown - "eType" is unknown.
+ // => rList will be valid everytimes next line is reached.
+ const CacheItemList& rList = impl_getItemList(eType);
+
+ std::vector<OUString> lKeys;
+ lKeys.reserve(rList.size());
+
+ // search items, which provides all needed properties of set "lIProps"
+ // but not of set "lEProps"!
+ for (auto const& elem : rList)
+ {
+ if (
+ (elem.second.haveProps(lIProps) ) &&
+ (elem.second.dontHaveProps(lEProps))
+ )
+ {
+ lKeys.push_back(elem.first);
+ }
+ }
+
+ return lKeys;
+ // <- SAFE
+}
+
+
+bool FilterCache::hasItems(EItemType eType) const
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // search for right list
+ // An exception is thrown - "eType" is unknown.
+ // => rList will be valid everytimes next line is reached.
+ const CacheItemList& rList = impl_getItemList(eType);
+
+ return !rList.empty();
+ // <- SAFE
+}
+
+
+std::vector<OUString> FilterCache::getItemNames(EItemType eType) const
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // search for right list
+ // An exception is thrown - "eType" is unknown.
+ // => rList will be valid everytimes next line is reached.
+ const CacheItemList& rList = impl_getItemList(eType);
+
+ std::vector<OUString> lKeys;
+ for (auto const& elem : rList)
+ {
+ lKeys.push_back(elem.first);
+ }
+ return lKeys;
+ // <- SAFE
+}
+
+
+bool FilterCache::hasItem( EItemType eType,
+ const OUString& sItem)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // search for right list
+ // An exception is thrown - "eType" is unknown.
+ // => rList will be valid everytimes next line is reached.
+ const CacheItemList& rList = impl_getItemList(eType);
+
+ // if item could not be found - check if it can be loaded
+ // from the underlying configuration layer. Might it was not already
+ // loaded into this FilterCache object before.
+ CacheItemList::const_iterator pIt = rList.find(sItem);
+ if (pIt != rList.end())
+ return true;
+
+ try
+ {
+ impl_loadItemOnDemand(eType, sItem);
+ // no exception => item could be loaded!
+ return true;
+ }
+ catch(const css::container::NoSuchElementException&)
+ {}
+
+ return false;
+ // <- SAFE
+}
+
+
+CacheItem FilterCache::getItem( EItemType eType,
+ const OUString& sItem)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ CacheItem aItem = impl_getItem(eType, sItem);
+ // <- SAFE
+ return aItem;
+}
+
+
+CacheItem& FilterCache::impl_getItem( EItemType eType,
+ const OUString& sItem)
+{
+ // search for right list
+ // An exception is thrown if "eType" is unknown.
+ // => rList will be valid everytimes next line is reached.
+ CacheItemList& rList = impl_getItemList(eType);
+
+ // check if item exists ...
+ CacheItemList::iterator pIt = rList.find(sItem);
+ if (pIt == rList.end())
+ {
+ // ... or load it on demand from the
+ // underlying configuration layer.
+ // Note: NoSuchElementException is thrown automatically here if
+ // item could not be loaded!
+ pIt = impl_loadItemOnDemand(eType, sItem);
+ }
+
+ /* Workaround for #137955#
+ Draw types and filters are installed ... but draw was disabled during setup.
+ We must suppress accessing these filters. Otherwise the office can crash.
+ Solution for the next major release: do not install those filters !
+ */
+ if (eType == E_FILTER)
+ {
+ CacheItem& rFilter = pIt->second;
+ OUString sDocService;
+ rFilter[PROPNAME_DOCUMENTSERVICE] >>= sDocService;
+
+ // In Standalone-Impress the module WriterWeb is not installed
+ // but it is there to load help pages
+ bool bIsHelpFilter = sItem == "writer_web_HTML_help";
+
+ if ( !bIsHelpFilter && !impl_isModuleInstalled(sDocService) )
+ {
+ OUString sMsg("The requested filter '" + sItem +
+ "' exists ... but it should not; because the corresponding LibreOffice module was not installed.");
+ throw css::container::NoSuchElementException(sMsg, css::uno::Reference< css::uno::XInterface >());
+ }
+ }
+
+ return pIt->second;
+}
+
+
+void FilterCache::removeItem( EItemType eType,
+ const OUString& sItem)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // search for right list
+ // An exception is thrown - "eType" is unknown.
+ // => rList will be valid everytimes next line is reached.
+ CacheItemList& rList = impl_getItemList(eType);
+
+ CacheItemList::iterator pItem = rList.find(sItem);
+ if (pItem == rList.end())
+ pItem = impl_loadItemOnDemand(eType, sItem); // throws NoSuchELementException!
+ rList.erase(pItem);
+
+ impl_addItem2FlushList(eType, sItem);
+}
+
+
+void FilterCache::setItem( EItemType eType ,
+ const OUString& sItem ,
+ const CacheItem& aValue)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // search for right list
+ // An exception is thrown - "eType" is unknown.
+ // => rList will be valid everytimes next line is reached.
+ CacheItemList& rList = impl_getItemList(eType);
+
+ // name must be part of the property set too ... otherwise our
+ // container query can't work correctly
+ CacheItem aItem = aValue;
+ aItem[PROPNAME_NAME] <<= sItem;
+ aItem.validateUINames(m_sActLocale);
+
+ // remove implicit properties as e.g. FINALIZED or MANDATORY
+ // They can't be saved here and must be read on demand later, if they are needed.
+ removeStatePropsFromItem(aItem);
+
+ rList[sItem] = aItem;
+
+ impl_addItem2FlushList(eType, sItem);
+}
+
+
+void FilterCache::refreshItem( EItemType eType,
+ const OUString& sItem)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+ impl_loadItemOnDemand(eType, sItem);
+}
+
+
+css::uno::Any FilterCache::getItemWithStateProps( EItemType eType,
+ const OUString& sItem)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ const CacheItem& rItem = impl_getItem(eType, sItem);
+
+ // Note: Opening of the configuration layer throws some exceptions
+ // if it failed. So we mustn't check any reference here...
+ css::uno::Reference< css::container::XNameAccess > xPackage;
+ css::uno::Reference< css::container::XNameAccess > xSet;
+ switch(eType)
+ {
+ case E_TYPE :
+ {
+ xPackage.set(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY_THROW);
+ xPackage->getByName(CFGSET_TYPES) >>= xSet;
+ }
+ break;
+
+ case E_FILTER :
+ {
+ xPackage.set(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY_THROW);
+ xPackage->getByName(CFGSET_FILTERS) >>= xSet;
+ }
+ break;
+
+ case E_FRAMELOADER :
+ {
+ /* TODO
+ Hack -->
+ The default frame loader can't be located inside the normal set of frame loaders.
+ It's an atomic property inside the misc cfg package. So we can't retrieve the information
+ about FINALIZED and MANDATORY very easy ... :-(
+ => set it to readonly/required everytimes :-)
+ */
+ css::uno::Any aDirectValue = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER);
+ OUString sDefaultFrameLoader;
+ if (
+ (aDirectValue >>= sDefaultFrameLoader) &&
+ (!sDefaultFrameLoader.isEmpty() ) &&
+ (sItem == sDefaultFrameLoader )
+ )
+ {
+ css::uno::Sequence aProps = rItem.getAsPackedPropertyValueList(true, true);
+ return css::uno::Any(aProps);
+ }
+ /* <-- HACK */
+
+ xPackage.set(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY_THROW);
+ xPackage->getByName(CFGSET_FRAMELOADERS) >>= xSet;
+ }
+ break;
+
+ case E_CONTENTHANDLER :
+ {
+ xPackage.set(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY_THROW);
+ xPackage->getByName(CFGSET_CONTENTHANDLERS) >>= xSet;
+ }
+ break;
+ default: break;
+ }
+
+ bool bFinalized, bMandatory;
+ try
+ {
+ css::uno::Reference< css::beans::XProperty > xItem;
+ xSet->getByName(sItem) >>= xItem;
+ css::beans::Property aDescription = xItem->getAsProperty();
+
+ bFinalized = ((aDescription.Attributes & css::beans::PropertyAttribute::READONLY ) == css::beans::PropertyAttribute::READONLY );
+ bMandatory = ((aDescription.Attributes & css::beans::PropertyAttribute::REMOVABLE) != css::beans::PropertyAttribute::REMOVABLE);
+
+ }
+ catch(const css::container::NoSuchElementException&)
+ {
+ /* Ignore exceptions for missing elements inside configuration.
+ May by the following reason exists:
+ - The item does not exists inside the new configuration package org.openoffice.TypeDetection - but
+ we got it from the old package org.openoffice.Office/TypeDetection. We don't migrate such items
+ automatically to the new format. Because it will disturb e.g. the deinstallation of an external filter
+ package. Because such external filter can remove the old file - but not the automatically created new one ...
+
+ => mark item as FINALIZED / MANDATORY, we don't support writing to the old format
+ */
+ bFinalized = true;
+ bMandatory = true;
+ }
+
+ css::uno::Sequence<css::beans::PropertyValue> aProps = rItem.getAsPackedPropertyValueList(bFinalized, bMandatory);
+
+ return css::uno::Any(aProps);
+ // <- SAFE
+}
+
+
+void FilterCache::removeStatePropsFromItem(CacheItem& rItem)
+{
+ CacheItem::iterator pIt = rItem.find(PROPNAME_FINALIZED);
+ if (pIt != rItem.end())
+ rItem.erase(pIt);
+ pIt = rItem.find(PROPNAME_MANDATORY);
+ if (pIt != rItem.end())
+ rItem.erase(pIt);
+}
+
+
+void FilterCache::flush()
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // renew all dependencies and optimizations
+ impl_validateAndOptimize();
+
+ if (!m_lChangedTypes.empty())
+ {
+ css::uno::Reference< css::container::XNameAccess > xConfig(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::container::XNameAccess > xSet ;
+
+ xConfig->getByName(CFGSET_TYPES) >>= xSet;
+ impl_flushByList(xSet, E_TYPE, m_lTypes, m_lChangedTypes);
+
+ css::uno::Reference< css::util::XChangesBatch > xFlush(xConfig, css::uno::UNO_QUERY);
+ xFlush->commitChanges();
+ }
+
+ if (!m_lChangedFilters.empty())
+ {
+ css::uno::Reference< css::container::XNameAccess > xConfig(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::container::XNameAccess > xSet ;
+
+ xConfig->getByName(CFGSET_FILTERS) >>= xSet;
+ impl_flushByList(xSet, E_FILTER, m_lFilters, m_lChangedFilters);
+
+ css::uno::Reference< css::util::XChangesBatch > xFlush(xConfig, css::uno::UNO_QUERY);
+ xFlush->commitChanges();
+ }
+
+ /*TODO FrameLoader/ContentHandler must be flushed here too ... */
+}
+
+
+void FilterCache::impl_flushByList(const css::uno::Reference< css::container::XNameAccess >& xSet ,
+ EItemType eType ,
+ const CacheItemList& rCache,
+ const std::vector<OUString>& lItems)
+{
+ css::uno::Reference< css::container::XNameContainer > xAddRemoveSet(xSet, css::uno::UNO_QUERY);
+ css::uno::Reference< css::lang::XSingleServiceFactory > xFactory(xSet, css::uno::UNO_QUERY);
+
+ for (auto const& item : lItems)
+ {
+ EItemFlushState eState = impl_specifyFlushOperation(xSet, rCache, item);
+ switch(eState)
+ {
+ case E_ITEM_REMOVED :
+ {
+ xAddRemoveSet->removeByName(item);
+ }
+ break;
+
+ case E_ITEM_ADDED :
+ {
+ css::uno::Reference< css::container::XNameReplace > xItem (xFactory->createInstance(), css::uno::UNO_QUERY);
+
+ // special case. no exception - but not a valid item => set must be finalized or mandatory!
+ // Reject flush operation by throwing an exception. At least one item couldn't be flushed.
+ if (!xItem.is())
+ throw css::uno::Exception("Can not add item. Set is finalized or mandatory!",
+ css::uno::Reference< css::uno::XInterface >());
+
+ CacheItemList::const_iterator pItem = rCache.find(item);
+ impl_saveItem(xItem, eType, pItem->second);
+ xAddRemoveSet->insertByName(item, css::uno::Any(xItem));
+ }
+ break;
+
+ case E_ITEM_CHANGED :
+ {
+ css::uno::Reference< css::container::XNameReplace > xItem;
+ xSet->getByName(item) >>= xItem;
+
+ // special case. no exception - but not a valid item => it must be finalized or mandatory!
+ // Reject flush operation by throwing an exception. At least one item couldn't be flushed.
+ if (!xItem.is())
+ throw css::uno::Exception("Can not change item. It's finalized or mandatory!",
+ css::uno::Reference< css::uno::XInterface >());
+
+ CacheItemList::const_iterator pItem = rCache.find(item);
+ impl_saveItem(xItem, eType, pItem->second);
+ }
+ break;
+ default: break;
+ }
+ }
+}
+
+
+void FilterCache::detectFlatForURL(const css::util::URL& aURL ,
+ FlatDetection& rFlatTypes) const
+{
+ // extract extension from URL, so it can be used directly as key into our hash map!
+ // Note further: It must be converted to lower case, because the optimize hash
+ // (which maps extensions to types) work with lower case key strings!
+ INetURLObject aParser (aURL.Main);
+ OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT ,
+ true ,
+ INetURLObject::DecodeMechanism::WithCharset);
+ sExtension = sExtension.toAsciiLowerCase();
+
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+
+ // i) Step over all well known URL pattern
+ // and add registered types to the return list too
+ // Do it as first one - because: if a type match by a
+ // pattern a following deep detection can be suppressed!
+ // Further we can stop after first match ...
+ for (auto const& pattern : m_lURLPattern2Types)
+ {
+ WildCard aPatternCheck(pattern.first);
+ if (aPatternCheck.Matches(aURL.Main))
+ {
+ const std::vector<OUString>& rTypesForPattern = pattern.second;
+
+ FlatDetectionInfo aInfo;
+ aInfo.sType = *(rTypesForPattern.begin());
+ aInfo.bMatchByPattern = true;
+
+ rFlatTypes.push_back(aInfo);
+// return;
+ }
+ }
+
+
+ // ii) search types matching to the given extension.
+ // Copy every matching type without changing its order!
+ // Because preferred types was added as first one during
+ // loading configuration.
+ CacheItemRegistration::const_iterator pExtReg = m_lExtensions2Types.find(sExtension);
+ if (pExtReg != m_lExtensions2Types.end())
+ {
+ const std::vector<OUString>& rTypesForExtension = pExtReg->second;
+ for (auto const& elem : rTypesForExtension)
+ {
+ FlatDetectionInfo aInfo;
+ aInfo.sType = elem;
+ aInfo.bMatchByExtension = true;
+
+ rFlatTypes.push_back(aInfo);
+ }
+ }
+
+ // <- SAFE ----------------------------------
+}
+
+const CacheItemList& FilterCache::impl_getItemList(EItemType eType) const
+{
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ switch(eType)
+ {
+ case E_TYPE : return m_lTypes ;
+ case E_FILTER : return m_lFilters ;
+ case E_FRAMELOADER : return m_lFrameLoaders ;
+ case E_CONTENTHANDLER : return m_lContentHandlers;
+
+ }
+
+ throw css::uno::RuntimeException("unknown sub container requested.",
+ css::uno::Reference< css::uno::XInterface >());
+ // <- SAFE ----------------------------------
+}
+
+CacheItemList& FilterCache::impl_getItemList(EItemType eType)
+{
+ // SAFE -> ----------------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ switch(eType)
+ {
+ case E_TYPE : return m_lTypes ;
+ case E_FILTER : return m_lFilters ;
+ case E_FRAMELOADER : return m_lFrameLoaders ;
+ case E_CONTENTHANDLER : return m_lContentHandlers;
+
+ }
+
+ throw css::uno::RuntimeException("unknown sub container requested.",
+ css::uno::Reference< css::uno::XInterface >());
+ // <- SAFE ----------------------------------
+}
+
+css::uno::Reference< css::uno::XInterface > FilterCache::impl_openConfig(EConfigProvider eProvider)
+{
+ osl::MutexGuard aLock(m_aMutex);
+
+ OUString sPath ;
+ css::uno::Reference< css::uno::XInterface >* pConfig = nullptr;
+ css::uno::Reference< css::uno::XInterface > xOld ;
+ OString sRtlLog ;
+
+ switch(eProvider)
+ {
+ case E_PROVIDER_TYPES :
+ {
+ if (m_xConfigTypes.is())
+ return m_xConfigTypes;
+ sPath = CFGPACKAGE_TD_TYPES;
+ pConfig = &m_xConfigTypes;
+ sRtlLog = "impl_openconfig(E_PROVIDER_TYPES)";
+ }
+ break;
+
+ case E_PROVIDER_FILTERS :
+ {
+ if (m_xConfigFilters.is())
+ return m_xConfigFilters;
+ sPath = CFGPACKAGE_TD_FILTERS;
+ pConfig = &m_xConfigFilters;
+ sRtlLog = "impl_openconfig(E_PROVIDER_FILTERS)";
+ }
+ break;
+
+ case E_PROVIDER_OTHERS :
+ {
+ if (m_xConfigOthers.is())
+ return m_xConfigOthers;
+ sPath = CFGPACKAGE_TD_OTHERS;
+ pConfig = &m_xConfigOthers;
+ sRtlLog = "impl_openconfig(E_PROVIDER_OTHERS)";
+ }
+ break;
+
+ case E_PROVIDER_OLD :
+ {
+ // This special provider is used to work with
+ // the old configuration format only. It's not cached!
+ sPath = CFGPACKAGE_TD_OLD;
+ pConfig = &xOld;
+ sRtlLog = "impl_openconfig(E_PROVIDER_OLD)";
+ }
+ break;
+
+ default : throw css::uno::RuntimeException("These configuration node is not supported here for open!", nullptr);
+ }
+
+ {
+ SAL_INFO( "filter.config", "" << sRtlLog);
+ *pConfig = impl_createConfigAccess(sPath ,
+ false, // bReadOnly
+ true ); // bLocalesMode
+ }
+
+
+ // Start listening for changes on that configuration access.
+ switch(eProvider)
+ {
+ case E_PROVIDER_TYPES:
+ {
+ m_xTypesChglisteners.set(new CacheUpdateListener(*this, *pConfig, FilterCache::E_TYPE));
+ m_xTypesChglisteners->startListening();
+ }
+ break;
+ case E_PROVIDER_FILTERS:
+ {
+ m_xFiltersChgListener.set(new CacheUpdateListener(*this, *pConfig, FilterCache::E_FILTER));
+ m_xFiltersChgListener->startListening();
+ }
+ break;
+ default:
+ break;
+ }
+
+ return *pConfig;
+}
+
+css::uno::Any FilterCache::impl_getDirectCFGValue(const OUString& sDirectKey)
+{
+ OUString sRoot;
+ OUString sKey ;
+
+ if (
+ (!::utl::splitLastFromConfigurationPath(sDirectKey, sRoot, sKey)) ||
+ (sRoot.isEmpty() ) ||
+ (sKey.isEmpty() )
+ )
+ return css::uno::Any();
+
+ css::uno::Reference< css::uno::XInterface > xCfg = impl_createConfigAccess(sRoot ,
+ true , // bReadOnly
+ false); // bLocalesMode
+ if (!xCfg.is())
+ return css::uno::Any();
+
+ css::uno::Reference< css::container::XNameAccess > xAccess(xCfg, css::uno::UNO_QUERY);
+ if (!xAccess.is())
+ return css::uno::Any();
+
+ css::uno::Any aValue;
+ try
+ {
+ aValue = xAccess->getByName(sKey);
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION( "filter.config", "");
+ aValue.clear();
+ }
+
+ return aValue;
+}
+
+
+css::uno::Reference< css::uno::XInterface > FilterCache::impl_createConfigAccess(const OUString& sRoot ,
+ bool bReadOnly ,
+ bool bLocalesMode)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ css::uno::Reference< css::uno::XInterface > xCfg;
+
+ if (!utl::ConfigManager::IsFuzzing())
+ {
+ try
+ {
+ css::uno::Reference< css::lang::XMultiServiceFactory > xConfigProvider(
+ css::configuration::theDefaultProvider::get( comphelper::getProcessComponentContext() ) );
+
+ ::std::vector< css::uno::Any > lParams;
+ css::beans::NamedValue aParam;
+
+ // set root path
+ aParam.Name = "nodepath";
+ aParam.Value <<= sRoot;
+ lParams.push_back(css::uno::Any(aParam));
+
+ // enable "all locales mode" ... if required
+ if (bLocalesMode)
+ {
+ aParam.Name = "locale";
+ aParam.Value <<= OUString("*");
+ lParams.push_back(css::uno::Any(aParam));
+ }
+
+ // open it
+ if (bReadOnly)
+ xCfg = xConfigProvider->createInstanceWithArguments(SERVICE_CONFIGURATIONACCESS,
+ comphelper::containerToSequence(lParams));
+ else
+ xCfg = xConfigProvider->createInstanceWithArguments(SERVICE_CONFIGURATIONUPDATEACCESS,
+ comphelper::containerToSequence(lParams));
+
+ // If configuration could not be opened... but factory method did not throw an exception
+ // trigger throwing of our own CorruptedFilterConfigurationException.
+ // Let message empty. The normal exception text show enough information to the user.
+ if (! xCfg.is())
+ throw css::uno::Exception(
+ "Got NULL reference on opening configuration file ... but no exception.",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::document::CorruptedFilterConfigurationException(
+ "filter configuration, caught: " + ex.Message,
+ css::uno::Reference< css::uno::XInterface >(),
+ ex.Message);
+ }
+ }
+
+ return xCfg;
+ // <- SAFE
+}
+
+
+void FilterCache::impl_validateAndOptimize()
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // First check if any filter or type could be read
+ // from the underlying configuration!
+ bool bSomeTypesShouldExist = ((m_eFillState & E_CONTAINS_STANDARD ) == E_CONTAINS_STANDARD );
+ bool bAllFiltersShouldExist = ((m_eFillState & E_CONTAINS_FILTERS ) == E_CONTAINS_FILTERS );
+
+#if OSL_DEBUG_LEVEL > 0
+
+ sal_Int32 nWarnings = 0;
+
+// sal_Bool bAllTypesShouldExist = ((m_eFillState & E_CONTAINS_TYPES ) == E_CONTAINS_TYPES );
+ bool bAllLoadersShouldExist = ((m_eFillState & E_CONTAINS_FRAMELOADERS ) == E_CONTAINS_FRAMELOADERS );
+ bool bAllHandlersShouldExist = ((m_eFillState & E_CONTAINS_CONTENTHANDLERS) == E_CONTAINS_CONTENTHANDLERS);
+#endif
+
+ if (
+ (
+ bSomeTypesShouldExist && m_lTypes.empty()
+ ) ||
+ (
+ bAllFiltersShouldExist && m_lFilters.empty()
+ )
+ )
+ {
+ throw css::document::CorruptedFilterConfigurationException(
+ "filter configuration: the list of types or filters is empty",
+ css::uno::Reference< css::uno::XInterface >(),
+ "The list of types or filters is empty." );
+ }
+
+ // Create a log for all detected problems, which
+ // occur in the next few lines.
+ // If there are some real errors throw a RuntimException!
+ // If there are some warnings only, show an assertion.
+ sal_Int32 nErrors = 0;
+ OUStringBuffer sLog(256);
+
+ for (auto const& elem : m_lTypes)
+ {
+ const OUString & sType = elem.first;
+ const CacheItem & aType = elem.second;
+
+ // get its registration for file Extensions AND(!) URLPattern ...
+ // It doesn't matter if these items exists or if our
+ // used index access create some default ones ...
+ // only in case there is no filled set of Extensions AND
+ // no filled set of URLPattern -> we must try to remove this invalid item
+ // from this cache!
+ css::uno::Sequence< OUString > lExtensions;
+ css::uno::Sequence< OUString > lURLPattern;
+ auto it = aType.find(PROPNAME_EXTENSIONS);
+ if (it != aType.end())
+ it->second >>= lExtensions;
+ it = aType.find(PROPNAME_URLPATTERN);
+ if (it != aType.end())
+ it->second >>= lURLPattern;
+ sal_Int32 ce = lExtensions.getLength();
+ sal_Int32 cu = lURLPattern.getLength();
+
+#if OSL_DEBUG_LEVEL > 0
+
+ OUString sInternalTypeNameCheck;
+ it = aType.find(PROPNAME_NAME);
+ if (it != aType.end())
+ it->second >>= sInternalTypeNameCheck;
+ if (sInternalTypeNameCheck != sType)
+ {
+ sLog.append("Warning\t:\t" "The type \"" + sType + "\" does support the property \"Name\" correctly.\n");
+ ++nWarnings;
+ }
+
+ if (!ce && !cu)
+ {
+ sLog.append("Warning\t:\t" "The type \"" + sType + "\" does not contain any URL pattern nor any extensions.\n");
+ ++nWarnings;
+ }
+#endif
+
+ // create an optimized registration for this type to
+ // its set list of extensions/url pattern. If it's a "normal" type
+ // set it at the end of this optimized list. But if it's
+ // a "Preferred" one - set it to the front of this list.
+ // Of course multiple "Preferred" registrations can occur
+ // (they shouldn't - but they can!) ... Ignore it. The last
+ // preferred type is usable in the same manner then every
+ // other type!
+ bool bPreferred = false;
+ it = aType.find(PROPNAME_PREFERRED);
+ if (it != aType.end())
+ it->second >>= bPreferred;
+
+ const OUString* pExtensions = lExtensions.getConstArray();
+ for (sal_Int32 e=0; e<ce; ++e)
+ {
+ // Note: We must be sure that address the right hash entry
+ // does not depend from any upper/lower case problems ...
+ OUString sNormalizedExtension = pExtensions[e].toAsciiLowerCase();
+
+ std::vector<OUString>& lTypesForExtension = m_lExtensions2Types[sNormalizedExtension];
+ if (::std::find(lTypesForExtension.begin(), lTypesForExtension.end(), sType) != lTypesForExtension.end())
+ continue;
+
+ if (bPreferred)
+ lTypesForExtension.insert(lTypesForExtension.begin(), sType);
+ else
+ lTypesForExtension.push_back(sType);
+ }
+
+ const OUString* pURLPattern = lURLPattern.getConstArray();
+ for (sal_Int32 u=0; u<cu; ++u)
+ {
+ std::vector<OUString>& lTypesForURLPattern = m_lURLPattern2Types[pURLPattern[u]];
+ if (::std::find(lTypesForURLPattern.begin(), lTypesForURLPattern.end(), sType) != lTypesForURLPattern.end())
+ continue;
+
+ if (bPreferred)
+ lTypesForURLPattern.insert(lTypesForURLPattern.begin(), sType);
+ else
+ lTypesForURLPattern.push_back(sType);
+ }
+
+#if OSL_DEBUG_LEVEL > 0
+
+ // Don't check cross references between types and filters, if
+ // not all filters read from disk!
+ // OK - this cache can read single filters on demand too ...
+ // but then the fill state of this cache should not be set to E_CONTAINS_FILTERS!
+ if (!bAllFiltersShouldExist)
+ continue;
+
+ OUString sPrefFilter;
+ it = aType.find(PROPNAME_PREFERREDFILTER);
+ if (it != aType.end())
+ it->second >>= sPrefFilter;
+ if (sPrefFilter.isEmpty())
+ {
+ // OK - there is no filter for this type. But that's not an error.
+ // Maybe it can be handled by a ContentHandler...
+ // But at this time it's not guaranteed that there is any ContentHandler
+ // or FrameLoader inside this cache... but on disk...
+ bool bReferencedByLoader = true;
+ bool bReferencedByHandler = true;
+ if (bAllLoadersShouldExist)
+ bReferencedByLoader = !impl_searchFrameLoaderForType(sType).isEmpty();
+
+ if (bAllHandlersShouldExist)
+ bReferencedByHandler = !impl_searchContentHandlerForType(sType).isEmpty();
+
+ if (
+ (!bReferencedByLoader ) &&
+ (!bReferencedByHandler)
+ )
+ {
+ sLog.append("Warning\t:\t" "The type \"" + sType + "\" is not used by any filter, loader or content handler.\n");
+ ++nWarnings;
+ }
+ }
+
+ if (!sPrefFilter.isEmpty())
+ {
+ CacheItemList::const_iterator pIt2 = m_lFilters.find(sPrefFilter);
+ if (pIt2 == m_lFilters.end())
+ {
+ if (bAllFiltersShouldExist)
+ {
+ ++nWarnings; // preferred filters can point to a non-installed office module ! no error ... it's a warning only .-(
+ sLog.append("error\t:\t");
+ }
+ else
+ {
+ ++nWarnings;
+ sLog.append("warning\t:\t");
+ }
+
+ sLog.append("The type \"" + sType + "\" points to an invalid filter \"" + sPrefFilter + "\".\n");
+ continue;
+ }
+
+ CacheItem aPrefFilter = pIt2->second;
+ OUString sFilterTypeReg;
+ aPrefFilter[PROPNAME_TYPE] >>= sFilterTypeReg;
+ if (sFilterTypeReg != sType)
+ {
+ sLog.append("error\t:\t" "The preferred filter \"" +
+ sPrefFilter + "\" of type \"" + sType +
+ "\" is registered for another type \"" + sFilterTypeReg +
+ "\".\n");
+ ++nErrors;
+ }
+
+ sal_Int32 nFlags = 0;
+ aPrefFilter[PROPNAME_FLAGS] >>= nFlags;
+ if (!(static_cast<SfxFilterFlags>(nFlags) & SfxFilterFlags::IMPORT))
+ {
+ sLog.append("error\t:\t" "The preferred filter \"" + sPrefFilter + "\" of type \"" +
+ sType + "\" is not an IMPORT filter!\n");
+ ++nErrors;
+ }
+
+ OUString sInternalFilterNameCheck;
+ aPrefFilter[PROPNAME_NAME] >>= sInternalFilterNameCheck;
+ if (sInternalFilterNameCheck != sPrefFilter)
+ {
+ sLog.append("Warning\t:\t" "The filter \"" + sPrefFilter +
+ "\" does support the property \"Name\" correctly.\n");
+ ++nWarnings;
+ }
+ }
+#endif
+ }
+
+ // create dependencies between the global default frame loader
+ // and all types (and of course if registered filters), which
+ // does not registered for any other loader.
+ css::uno::Any aDirectValue = impl_getDirectCFGValue(CFGDIRECTKEY_DEFAULTFRAMELOADER);
+ OUString sDefaultFrameLoader;
+
+ if (
+ (!(aDirectValue >>= sDefaultFrameLoader)) ||
+ (sDefaultFrameLoader.isEmpty() )
+ )
+ {
+ sLog.append("error\t:\t" "There is no valid default frame loader!?\n");
+ ++nErrors;
+ }
+
+ // a) get list of all well known types
+ // b) step over all well known frame loader services
+ // and remove all types from list a), which already
+ // referenced by a loader b)
+ std::vector<OUString> lTypes = getItemNames(E_TYPE);
+ for (auto & frameLoader : m_lFrameLoaders)
+ {
+ // Note: of course the default loader must be ignored here.
+ // Because we replace its registration later completely with all
+ // types, which are not referenced by any other loader.
+ // So we can avoid our code against the complexity of a diff!
+ OUString sLoader = frameLoader.first;
+ if (sLoader == sDefaultFrameLoader)
+ continue;
+
+ CacheItem& rLoader = frameLoader.second;
+ css::uno::Any& rTypesReg = rLoader[PROPNAME_TYPES];
+ const css::uno::Sequence<OUString> lTypesReg = rTypesReg.get<css::uno::Sequence<OUString> >();
+
+ for (auto const& typeReg : lTypesReg)
+ {
+ auto pTypeCheck = ::std::find(lTypes.begin(), lTypes.end(), typeReg);
+ if (pTypeCheck != lTypes.end())
+ lTypes.erase(pTypeCheck);
+ }
+ }
+
+ CacheItem& rDefaultLoader = m_lFrameLoaders[sDefaultFrameLoader];
+ rDefaultLoader[PROPNAME_NAME ] <<= sDefaultFrameLoader;
+ rDefaultLoader[PROPNAME_TYPES] <<= comphelper::containerToSequence(lTypes);
+
+ OUString sLogOut = sLog.makeStringAndClear();
+ OSL_ENSURE(!nErrors, OUStringToOString(sLogOut,RTL_TEXTENCODING_UTF8).getStr());
+ if (nErrors>0)
+ throw css::document::CorruptedFilterConfigurationException(
+ "filter configuration: " + sLogOut,
+ css::uno::Reference< css::uno::XInterface >(),
+ sLogOut);
+#if OSL_DEBUG_LEVEL > 0
+ OSL_ENSURE(!nWarnings, OUStringToOString(sLogOut,RTL_TEXTENCODING_UTF8).getStr());
+#endif
+
+ // <- SAFE
+}
+
+void FilterCache::impl_addItem2FlushList( EItemType eType,
+ const OUString& sItem)
+{
+ std::vector<OUString>* pList = nullptr;
+ switch(eType)
+ {
+ case E_TYPE :
+ pList = &m_lChangedTypes;
+ break;
+
+ case E_FILTER :
+ pList = &m_lChangedFilters;
+ break;
+
+ case E_FRAMELOADER :
+ pList = &m_lChangedFrameLoaders;
+ break;
+
+ case E_CONTENTHANDLER :
+ pList = &m_lChangedContentHandlers;
+ break;
+
+ default : throw css::uno::RuntimeException("unsupported item type", nullptr);
+ }
+
+ auto pItem = ::std::find(pList->cbegin(), pList->cend(), sItem);
+ if (pItem == pList->cend())
+ pList->push_back(sItem);
+}
+
+FilterCache::EItemFlushState FilterCache::impl_specifyFlushOperation(const css::uno::Reference< css::container::XNameAccess >& xSet ,
+ const CacheItemList& rList,
+ const OUString& sItem)
+{
+ bool bExistsInConfigLayer = xSet->hasByName(sItem);
+ bool bExistsInMemory = (rList.find(sItem) != rList.end());
+
+ EItemFlushState eState( E_ITEM_UNCHANGED );
+
+ // !? ... such situation can occur, if an item was added and(!) removed before it was flushed :-)
+ if (!bExistsInConfigLayer && !bExistsInMemory)
+ eState = E_ITEM_UNCHANGED;
+ else if (!bExistsInConfigLayer && bExistsInMemory)
+ eState = E_ITEM_ADDED;
+ else if (bExistsInConfigLayer && bExistsInMemory)
+ eState = E_ITEM_CHANGED;
+ else if (bExistsInConfigLayer && !bExistsInMemory)
+ eState = E_ITEM_REMOVED;
+
+ return eState;
+}
+
+void FilterCache::impl_load(EFillState eRequiredState)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ // Attention: Detect services are part of the standard set!
+ // So there is no need to handle it separately.
+
+
+ // a) The standard set of config value is needed.
+ if (
+ ((eRequiredState & E_CONTAINS_STANDARD) == E_CONTAINS_STANDARD) &&
+ ((m_eFillState & E_CONTAINS_STANDARD) != E_CONTAINS_STANDARD)
+ )
+ {
+ // Attention! If config couldn't be opened successfully
+ // and exception is thrown automatically and must be forwarded
+ // to our caller...
+ css::uno::Reference< css::container::XNameAccess > xTypes(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY_THROW);
+ {
+ SAL_INFO( "filter.config", "FilterCache::load std");
+ impl_loadSet(xTypes, E_TYPE, E_READ_STANDARD, &m_lTypes);
+ }
+ }
+
+
+ // b) We need all type information ...
+ if (
+ ((eRequiredState & E_CONTAINS_TYPES) == E_CONTAINS_TYPES) &&
+ ((m_eFillState & E_CONTAINS_TYPES) != E_CONTAINS_TYPES)
+ )
+ {
+ // Attention! If config couldn't be opened successfully
+ // and exception is thrown automatically and must be forwarded
+ // to our call...
+ css::uno::Reference< css::container::XNameAccess > xTypes(impl_openConfig(E_PROVIDER_TYPES), css::uno::UNO_QUERY_THROW);
+ {
+ SAL_INFO( "filter.config", "FilterCache::load all types");
+ impl_loadSet(xTypes, E_TYPE, E_READ_UPDATE, &m_lTypes);
+ }
+ }
+
+
+ // c) We need all filter information ...
+ if (
+ ((eRequiredState & E_CONTAINS_FILTERS) == E_CONTAINS_FILTERS) &&
+ ((m_eFillState & E_CONTAINS_FILTERS) != E_CONTAINS_FILTERS)
+ )
+ {
+ // Attention! If config couldn't be opened successfully
+ // and exception is thrown automatically and must be forwarded
+ // to our call...
+ css::uno::Reference< css::container::XNameAccess > xFilters(impl_openConfig(E_PROVIDER_FILTERS), css::uno::UNO_QUERY_THROW);
+ {
+ SAL_INFO( "filter.config", "FilterCache::load all filters");
+ impl_loadSet(xFilters, E_FILTER, E_READ_ALL, &m_lFilters);
+ }
+ }
+
+
+ // c) We need all frame loader information ...
+ if (
+ ((eRequiredState & E_CONTAINS_FRAMELOADERS) == E_CONTAINS_FRAMELOADERS) &&
+ ((m_eFillState & E_CONTAINS_FRAMELOADERS) != E_CONTAINS_FRAMELOADERS)
+ )
+ {
+ // Attention! If config couldn't be opened successfully
+ // and exception is thrown automatically and must be forwarded
+ // to our call...
+ css::uno::Reference< css::container::XNameAccess > xLoaders(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY_THROW);
+ {
+ SAL_INFO( "filter.config", "FilterCache::load all frame loader");
+ impl_loadSet(xLoaders, E_FRAMELOADER, E_READ_ALL, &m_lFrameLoaders);
+ }
+ }
+
+
+ // d) We need all content handler information...
+ if (
+ ((eRequiredState & E_CONTAINS_CONTENTHANDLERS) == E_CONTAINS_CONTENTHANDLERS) &&
+ ((m_eFillState & E_CONTAINS_CONTENTHANDLERS) != E_CONTAINS_CONTENTHANDLERS)
+ )
+ {
+ // Attention! If config couldn't be opened successfully
+ // and exception is thrown automatically and must be forwarded
+ // to our call...
+ css::uno::Reference< css::container::XNameAccess > xHandlers(impl_openConfig(E_PROVIDER_OTHERS), css::uno::UNO_QUERY_THROW);
+ {
+ SAL_INFO( "filter.config", "FilterCache::load all content handler");
+ impl_loadSet(xHandlers, E_CONTENTHANDLER, E_READ_ALL, &m_lContentHandlers);
+ }
+ }
+
+ // update fill state. Note: it's a bit field, which combines different parts.
+ m_eFillState = static_cast<EFillState>(static_cast<sal_Int32>(m_eFillState) | static_cast<sal_Int32>(eRequiredState));
+
+ // any data read?
+ // yes! => validate it and update optimized structures.
+ impl_validateAndOptimize();
+
+ // <- SAFE
+}
+
+void FilterCache::impl_loadSet(const css::uno::Reference< css::container::XNameAccess >& xConfig,
+ EItemType eType ,
+ EReadOption eOption,
+ CacheItemList* pCache )
+{
+ // get access to the right configuration set
+ OUString sSetName;
+ switch(eType)
+ {
+ case E_TYPE :
+ sSetName = CFGSET_TYPES;
+ break;
+
+ case E_FILTER :
+ sSetName = CFGSET_FILTERS;
+ break;
+
+ case E_FRAMELOADER :
+ sSetName = CFGSET_FRAMELOADERS;
+ break;
+
+ case E_CONTENTHANDLER :
+ sSetName = CFGSET_CONTENTHANDLERS;
+ break;
+ default: break;
+ }
+
+ css::uno::Reference< css::container::XNameAccess > xSet;
+ css::uno::Sequence< OUString > lItems;
+
+ try
+ {
+ css::uno::Any aVal = xConfig->getByName(sSetName);
+ if (!(aVal >>= xSet) || !xSet.is())
+ {
+ OUString sMsg("Could not open configuration set \"" + sSetName + "\".");
+ throw css::uno::Exception(sMsg, css::uno::Reference< css::uno::XInterface >());
+ }
+ lItems = xSet->getElementNames();
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::document::CorruptedFilterConfigurationException(
+ "filter configuration, caught: " + ex.Message,
+ css::uno::Reference< css::uno::XInterface >(),
+ ex.Message);
+ }
+
+ // get names of all existing sub items of this set
+ // step over it and fill internal cache structures.
+
+ // But don't update optimized structures like e.g. hash
+ // for mapping extensions to its types!
+
+ const OUString* pItems = lItems.getConstArray();
+ sal_Int32 c = lItems.getLength();
+ for (sal_Int32 i=0; i<c; ++i)
+ {
+ CacheItemList::iterator pItem = pCache->find(pItems[i]);
+ switch(eOption)
+ {
+ // a) read a standard set of properties only or read all
+ case E_READ_STANDARD :
+ case E_READ_ALL :
+ {
+ try
+ {
+ (*pCache)[pItems[i]] = impl_loadItem(xSet, eType, pItems[i], eOption);
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::document::CorruptedFilterConfigurationException(
+ "filter configuration, caught: " + ex.Message,
+ css::uno::Reference< css::uno::XInterface >(),
+ ex.Message);
+ }
+ }
+ break;
+
+ // b) read optional properties only!
+ // All items must already exist inside our cache.
+ // But they must be updated.
+ case E_READ_UPDATE :
+ {
+ if (pItem == pCache->end())
+ {
+ OUString sMsg("item \"" + pItems[i] + "\" not found for update!");
+ throw css::uno::Exception(sMsg, css::uno::Reference< css::uno::XInterface >());
+ }
+ try
+ {
+ CacheItem aItem = impl_loadItem(xSet, eType, pItems[i], eOption);
+ pItem->second.update(aItem);
+ }
+ catch(const css::uno::Exception& ex)
+ {
+ throw css::document::CorruptedFilterConfigurationException(
+ "filter configuration, caught: " + ex.Message,
+ css::uno::Reference< css::uno::XInterface >(),
+ ex.Message);
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+}
+
+void FilterCache::impl_readPatchUINames(const css::uno::Reference< css::container::XNameAccess >& xNode,
+ CacheItem& rItem)
+{
+
+ // SAFE -> ----------------------------------
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ OUString sActLocale = m_sActLocale ;
+ aLock.clear();
+ // <- SAFE ----------------------------------
+
+ css::uno::Any aVal = xNode->getByName(PROPNAME_UINAME);
+ css::uno::Reference< css::container::XNameAccess > xUIName;
+ if (!(aVal >>= xUIName) && !xUIName.is())
+ return;
+
+ const ::std::vector< OUString > lLocales(comphelper::sequenceToContainer< ::std::vector< OUString >>(
+ xUIName->getElementNames()));
+ ::std::vector< OUString >::const_iterator pLocale ;
+ ::comphelper::SequenceAsHashMap lUINames;
+
+ for (auto const& locale : lLocales)
+ {
+ OUString sValue;
+ xUIName->getByName(locale) >>= sValue;
+
+ lUINames[locale] <<= sValue;
+ }
+
+ aVal <<= lUINames.getAsConstPropertyValueList();
+ rItem[PROPNAME_UINAMES] = aVal;
+
+ // find right UIName for current office locale
+ // Use fallbacks too!
+ pLocale = LanguageTag::getFallback(lLocales, sActLocale);
+ if (pLocale == lLocales.end())
+ {
+#if OSL_DEBUG_LEVEL > 0
+ if ( sActLocale == "en-US" )
+ return;
+ OUString sName = rItem.getUnpackedValueOrDefault(PROPNAME_NAME, OUString());
+
+ SAL_WARN("filter.config", "Fallback scenario for filter or type '" << sName << "' and locale '" <<
+ sActLocale << "' failed. Please check your filter configuration.");
+#endif
+ return;
+ }
+
+ const OUString& sLocale = *pLocale;
+ ::comphelper::SequenceAsHashMap::const_iterator pUIName = lUINames.find(sLocale);
+ if (pUIName != lUINames.end())
+ rItem[PROPNAME_UINAME] = pUIName->second;
+}
+
+void FilterCache::impl_savePatchUINames(const css::uno::Reference< css::container::XNameReplace >& xNode,
+ const CacheItem& rItem)
+{
+ css::uno::Reference< css::container::XNameContainer > xAdd (xNode, css::uno::UNO_QUERY);
+
+ css::uno::Sequence< css::beans::PropertyValue > lUINames = rItem.getUnpackedValueOrDefault(PROPNAME_UINAMES, css::uno::Sequence< css::beans::PropertyValue >());
+ sal_Int32 c = lUINames.getLength();
+ const css::beans::PropertyValue* pUINames = lUINames.getConstArray();
+
+ for (sal_Int32 i=0; i<c; ++i)
+ {
+ if (xNode->hasByName(pUINames[i].Name))
+ xNode->replaceByName(pUINames[i].Name, pUINames[i].Value);
+ else
+ xAdd->insertByName(pUINames[i].Name, pUINames[i].Value);
+ }
+}
+
+/*-----------------------------------------------
+ TODO
+ clarify, how the real problem behind the
+ wrong constructed CacheItem instance (which
+ will force a crash during destruction)
+ can be solved ...
+-----------------------------------------------*/
+CacheItem FilterCache::impl_loadItem(const css::uno::Reference< css::container::XNameAccess >& xSet ,
+ EItemType eType ,
+ const OUString& sItem ,
+ EReadOption eOption)
+{
+ // try to get an API object, which points directly to the
+ // requested item. If it fail an exception should occur and
+ // break this operation. Of course returned API object must be
+ // checked too.
+ css::uno::Reference< css::container::XNameAccess > xItem;
+ css::uno::Any aVal = xSet->getByName(sItem);
+ if (!(aVal >>= xItem) || !xItem.is())
+ {
+ throw css::uno::RuntimeException("found corrupted item \"" + sItem + "\".",
+ css::uno::Reference< css::uno::XInterface >());
+ }
+
+ // set too. Of course it's already used as key into the e.g. outside
+ // used hash map... but some of our API methods provide
+ // this property set as result only. But the user of this CacheItem
+ // should know, which value the key names has :-) IT'S IMPORTANT!
+ CacheItem aItem;
+ aItem[PROPNAME_NAME] <<= sItem;
+ switch(eType)
+ {
+ case E_TYPE :
+ {
+ assert(eOption >= 0 && eOption <= E_READ_ALL);
+ css::uno::Sequence< OUString > &rNames = m_aTypeProps[eOption];
+
+ // read standard properties of a filter
+ if (rNames.hasElements())
+ {
+ css::uno::Reference< css::beans::XMultiPropertySet >
+ xPropSet( xItem, css::uno::UNO_QUERY_THROW);
+ css::uno::Sequence< css::uno::Any > aValues = xPropSet->getPropertyValues(rNames);
+
+ for (sal_Int32 i = 0; i < aValues.getLength(); i++)
+ aItem[rNames[i]] = aValues[i];
+ }
+
+ // read optional properties of a type
+ // no else here! Is an additional switch ...
+ if (eOption == E_READ_UPDATE || eOption == E_READ_ALL)
+ impl_readPatchUINames(xItem, aItem);
+ }
+ break;
+
+
+ case E_FILTER :
+ {
+ assert(eOption >= 0 && eOption <= E_READ_ALL);
+ css::uno::Sequence< OUString > &rNames = m_aStandardProps[eOption];
+
+ // read standard properties of a filter
+ if (rNames.hasElements())
+ {
+ css::uno::Reference< css::beans::XMultiPropertySet >
+ xPropSet( xItem, css::uno::UNO_QUERY_THROW);
+ css::uno::Sequence< css::uno::Any > aValues = xPropSet->getPropertyValues(rNames);
+
+ for (sal_Int32 i = 0; i < rNames.getLength(); i++)
+ {
+ const OUString &rPropName = rNames[i];
+ if (i != rNames.getLength() - 1 || rPropName != PROPNAME_FLAGS)
+ aItem[rPropName] = aValues[i];
+ else
+ {
+ assert(rPropName == PROPNAME_FLAGS);
+ // special handling for flags! Convert it from a list of names to its
+ // int representation ...
+ css::uno::Sequence< OUString > lFlagNames;
+ if (aValues[i] >>= lFlagNames)
+ aItem[rPropName] <<= static_cast<sal_Int32>(FilterCache::impl_convertFlagNames2FlagField(lFlagNames));
+ }
+ }
+ }
+//TODO remove it if moving of filter uinames to type uinames
+// will be finished really
+#ifdef AS_ENABLE_FILTER_UINAMES
+ if (eOption == E_READ_UPDATE || eOption == E_READ_ALL)
+ impl_readPatchUINames(xItem, aItem);
+#endif // AS_ENABLE_FILTER_UINAMES
+ }
+ break;
+
+ case E_FRAMELOADER :
+ case E_CONTENTHANDLER :
+ aItem[PROPNAME_TYPES] = xItem->getByName(PROPNAME_TYPES);
+ break;
+ default: break;
+ }
+
+ return aItem;
+}
+
+CacheItemList::iterator FilterCache::impl_loadItemOnDemand( EItemType eType,
+ const OUString& sItem)
+{
+ CacheItemList* pList = nullptr;
+ css::uno::Reference< css::uno::XInterface > xConfig ;
+ OUString sSet ;
+
+ switch(eType)
+ {
+ case E_TYPE :
+ {
+ pList = &m_lTypes;
+ xConfig = impl_openConfig(E_PROVIDER_TYPES);
+ sSet = CFGSET_TYPES;
+ }
+ break;
+
+ case E_FILTER :
+ {
+ pList = &m_lFilters;
+ xConfig = impl_openConfig(E_PROVIDER_FILTERS);
+ sSet = CFGSET_FILTERS;
+ }
+ break;
+
+ case E_FRAMELOADER :
+ {
+ pList = &m_lFrameLoaders;
+ xConfig = impl_openConfig(E_PROVIDER_OTHERS);
+ sSet = CFGSET_FRAMELOADERS;
+ }
+ break;
+
+ case E_CONTENTHANDLER :
+ {
+ pList = &m_lContentHandlers;
+ xConfig = impl_openConfig(E_PROVIDER_OTHERS);
+ sSet = CFGSET_CONTENTHANDLERS;
+ }
+ break;
+ }
+
+ if (!pList)
+ throw css::container::NoSuchElementException();
+
+ css::uno::Reference< css::container::XNameAccess > xRoot(xConfig, css::uno::UNO_QUERY_THROW);
+ css::uno::Reference< css::container::XNameAccess > xSet ;
+ xRoot->getByName(sSet) >>= xSet;
+
+ CacheItemList::iterator pItemInCache = pList->find(sItem);
+ bool bItemInConfig = xSet->hasByName(sItem);
+
+ if (bItemInConfig)
+ {
+ (*pList)[sItem] = impl_loadItem(xSet, eType, sItem, E_READ_ALL);
+ }
+ else
+ {
+ if (pItemInCache != pList->end())
+ pList->erase(pItemInCache);
+ // OK - this item does not exists inside configuration.
+ // And we already updated our internal cache.
+ // But the outside code needs this NoSuchElementException
+ // to know, that this item does notexists.
+ // Nobody checks the iterator!
+ throw css::container::NoSuchElementException();
+ }
+
+ return pList->find(sItem);
+}
+
+void FilterCache::impl_saveItem(const css::uno::Reference< css::container::XNameReplace >& xItem,
+ EItemType eType,
+ const CacheItem & aItem)
+{
+ // This function changes the properties of aItem one-by-one; but it also
+ // listens to the configuration changes and reloads the whole item from the
+ // configuration on change, so use a copy of aItem throughout:
+ CacheItem copiedItem(aItem);
+
+ CacheItem::const_iterator pIt;
+ switch(eType)
+ {
+
+ case E_TYPE :
+ {
+ pIt = copiedItem.find(PROPNAME_PREFERREDFILTER);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_PREFERREDFILTER, pIt->second);
+ pIt = copiedItem.find(PROPNAME_DETECTSERVICE);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_DETECTSERVICE, pIt->second);
+ pIt = copiedItem.find(PROPNAME_URLPATTERN);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_URLPATTERN, pIt->second);
+ pIt = copiedItem.find(PROPNAME_EXTENSIONS);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_EXTENSIONS, pIt->second);
+ pIt = copiedItem.find(PROPNAME_PREFERRED);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_PREFERRED, pIt->second);
+ pIt = copiedItem.find(PROPNAME_MEDIATYPE);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_MEDIATYPE, pIt->second);
+ pIt = copiedItem.find(PROPNAME_CLIPBOARDFORMAT);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_CLIPBOARDFORMAT, pIt->second);
+
+ css::uno::Reference< css::container::XNameReplace > xUIName;
+ xItem->getByName(PROPNAME_UINAME) >>= xUIName;
+ impl_savePatchUINames(xUIName, copiedItem);
+ }
+ break;
+
+
+ case E_FILTER :
+ {
+ pIt = copiedItem.find(PROPNAME_TYPE);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_TYPE, pIt->second);
+ pIt = copiedItem.find(PROPNAME_FILEFORMATVERSION);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_FILEFORMATVERSION, pIt->second);
+ pIt = copiedItem.find(PROPNAME_UICOMPONENT);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_UICOMPONENT, pIt->second);
+ pIt = copiedItem.find(PROPNAME_FILTERSERVICE);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_FILTERSERVICE, pIt->second);
+ pIt = copiedItem.find(PROPNAME_DOCUMENTSERVICE);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_DOCUMENTSERVICE, pIt->second);
+ pIt = copiedItem.find(PROPNAME_USERDATA);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_USERDATA, pIt->second);
+ pIt = copiedItem.find(PROPNAME_TEMPLATENAME);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_TEMPLATENAME, pIt->second);
+
+ // special handling for flags! Convert it from an integer flag field back
+ // to a list of names ...
+ pIt = copiedItem.find(PROPNAME_FLAGS);
+ if (pIt != copiedItem.end())
+ {
+ sal_Int32 nFlags = 0;
+ pIt->second >>= nFlags;
+ css::uno::Any aFlagNameList;
+ aFlagNameList <<= FilterCache::impl_convertFlagField2FlagNames(static_cast<SfxFilterFlags>(nFlags));
+ xItem->replaceByName(PROPNAME_FLAGS, aFlagNameList);
+ }
+
+//TODO remove it if moving of filter uinames to type uinames
+// will be finished really
+#ifdef AS_ENABLE_FILTER_UINAMES
+ css::uno::Reference< css::container::XNameReplace > xUIName;
+ xItem->getByName(PROPNAME_UINAME) >>= xUIName;
+ impl_savePatchUINames(xUIName, copiedItem);
+#endif // AS_ENABLE_FILTER_UINAMES
+ }
+ break;
+
+
+ case E_FRAMELOADER :
+ case E_CONTENTHANDLER :
+ {
+ pIt = copiedItem.find(PROPNAME_TYPES);
+ if (pIt != copiedItem.end())
+ xItem->replaceByName(PROPNAME_TYPES, pIt->second);
+ }
+ break;
+ default: break;
+ }
+}
+
+/*-----------------------------------------------
+ static! => no locks necessary
+-----------------------------------------------*/
+css::uno::Sequence< OUString > FilterCache::impl_convertFlagField2FlagNames(SfxFilterFlags nFlags)
+{
+ std::vector<OUString> lFlagNames;
+
+ if (nFlags & SfxFilterFlags::STARONEFILTER ) lFlagNames.emplace_back(FLAGNAME_3RDPARTYFILTER );
+ if (nFlags & SfxFilterFlags::ALIEN ) lFlagNames.emplace_back(FLAGNAME_ALIEN );
+ if (nFlags & SfxFilterFlags::CONSULTSERVICE ) lFlagNames.emplace_back(FLAGNAME_CONSULTSERVICE );
+ if (nFlags & SfxFilterFlags::DEFAULT ) lFlagNames.emplace_back(FLAGNAME_DEFAULT );
+ if (nFlags & SfxFilterFlags::ENCRYPTION ) lFlagNames.emplace_back(FLAGNAME_ENCRYPTION );
+ if (nFlags & SfxFilterFlags::EXPORT ) lFlagNames.emplace_back(FLAGNAME_EXPORT );
+ if (nFlags & SfxFilterFlags::IMPORT ) lFlagNames.emplace_back(FLAGNAME_IMPORT );
+ if (nFlags & SfxFilterFlags::INTERNAL ) lFlagNames.emplace_back(FLAGNAME_INTERNAL );
+ if (nFlags & SfxFilterFlags::NOTINFILEDLG ) lFlagNames.emplace_back(FLAGNAME_NOTINFILEDIALOG );
+ if (nFlags & SfxFilterFlags::MUSTINSTALL ) lFlagNames.emplace_back(FLAGNAME_NOTINSTALLED );
+ if (nFlags & SfxFilterFlags::OWN ) lFlagNames.emplace_back(FLAGNAME_OWN );
+ if (nFlags & SfxFilterFlags::PACKED ) lFlagNames.emplace_back(FLAGNAME_PACKED );
+ if (nFlags & SfxFilterFlags::PASSWORDTOMODIFY ) lFlagNames.emplace_back(FLAGNAME_PASSWORDTOMODIFY );
+ if (nFlags & SfxFilterFlags::PREFERED ) lFlagNames.emplace_back(FLAGNAME_PREFERRED );
+ if (nFlags & SfxFilterFlags::STARTPRESENTATION) lFlagNames.emplace_back(FLAGNAME_STARTPRESENTATION);
+ if (nFlags & SfxFilterFlags::OPENREADONLY ) lFlagNames.emplace_back(FLAGNAME_READONLY );
+ if (nFlags & SfxFilterFlags::SUPPORTSSELECTION) lFlagNames.emplace_back(FLAGNAME_SUPPORTSSELECTION);
+ if (nFlags & SfxFilterFlags::TEMPLATE ) lFlagNames.emplace_back(FLAGNAME_TEMPLATE );
+ if (nFlags & SfxFilterFlags::TEMPLATEPATH ) lFlagNames.emplace_back(FLAGNAME_TEMPLATEPATH );
+ if (nFlags & SfxFilterFlags::COMBINED ) lFlagNames.emplace_back(FLAGNAME_COMBINED );
+ if (nFlags & SfxFilterFlags::SUPPORTSSIGNING) lFlagNames.emplace_back(FLAGNAME_SUPPORTSSIGNING);
+ if (nFlags & SfxFilterFlags::GPGENCRYPTION) lFlagNames.emplace_back(FLAGNAME_GPGENCRYPTION);
+ if (nFlags & SfxFilterFlags::EXOTIC) lFlagNames.emplace_back(FLAGNAME_EXOTIC);
+
+ return comphelper::containerToSequence(lFlagNames);
+}
+
+/*-----------------------------------------------
+ static! => no locks necessary
+-----------------------------------------------*/
+SfxFilterFlags FilterCache::impl_convertFlagNames2FlagField(const css::uno::Sequence< OUString >& lNames)
+{
+ SfxFilterFlags nField = SfxFilterFlags::NONE;
+
+ const OUString* pNames = lNames.getConstArray();
+ sal_Int32 c = lNames.getLength();
+ for (sal_Int32 i=0; i<c; ++i)
+ {
+ if (pNames[i] == FLAGNAME_3RDPARTYFILTER)
+ {
+ nField |= SfxFilterFlags::STARONEFILTER;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_ALIEN)
+ {
+ nField |= SfxFilterFlags::ALIEN;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_CONSULTSERVICE)
+ {
+ nField |= SfxFilterFlags::CONSULTSERVICE;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_DEFAULT)
+ {
+ nField |= SfxFilterFlags::DEFAULT;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_ENCRYPTION)
+ {
+ nField |= SfxFilterFlags::ENCRYPTION;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_EXOTIC)
+ {
+ nField |= SfxFilterFlags::EXOTIC;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_EXPORT)
+ {
+ nField |= SfxFilterFlags::EXPORT;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_GPGENCRYPTION)
+ {
+ nField |= SfxFilterFlags::GPGENCRYPTION;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_IMPORT)
+ {
+ nField |= SfxFilterFlags::IMPORT;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_INTERNAL)
+ {
+ nField |= SfxFilterFlags::INTERNAL;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_NOTINFILEDIALOG)
+ {
+ nField |= SfxFilterFlags::NOTINFILEDLG;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_NOTINSTALLED)
+ {
+ nField |= SfxFilterFlags::MUSTINSTALL;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_OWN)
+ {
+ nField |= SfxFilterFlags::OWN;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_PACKED)
+ {
+ nField |= SfxFilterFlags::PACKED;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_PASSWORDTOMODIFY)
+ {
+ nField |= SfxFilterFlags::PASSWORDTOMODIFY;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_PREFERRED)
+ {
+ nField |= SfxFilterFlags::PREFERED;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_STARTPRESENTATION)
+ {
+ nField |= SfxFilterFlags::STARTPRESENTATION;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_SUPPORTSSIGNING)
+ {
+ nField |= SfxFilterFlags::SUPPORTSSIGNING;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_READONLY)
+ {
+ nField |= SfxFilterFlags::OPENREADONLY;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_SUPPORTSSELECTION)
+ {
+ nField |= SfxFilterFlags::SUPPORTSSELECTION;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_TEMPLATE)
+ {
+ nField |= SfxFilterFlags::TEMPLATE;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_TEMPLATEPATH)
+ {
+ nField |= SfxFilterFlags::TEMPLATEPATH;
+ continue;
+ }
+ if (pNames[i] == FLAGNAME_COMBINED)
+ {
+ nField |= SfxFilterFlags::COMBINED;
+ continue;
+ }
+ }
+
+ return nField;
+}
+
+
+void FilterCache::impl_interpretDataVal4Type(const OUString& sValue,
+ sal_Int32 nProp ,
+ CacheItem& rItem )
+{
+ switch(nProp)
+ {
+ // Preferred
+ case 0: rItem[PROPNAME_PREFERRED] <<= (sValue.toInt32() == 1);
+ break;
+ // MediaType
+ case 1: rItem[PROPNAME_MEDIATYPE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ break;
+ // ClipboardFormat
+ case 2: rItem[PROPNAME_CLIPBOARDFORMAT] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ break;
+ // URLPattern
+ case 3: rItem[PROPNAME_URLPATTERN] <<= comphelper::containerToSequence(impl_tokenizeString(sValue, ';'));
+ break;
+ // Extensions
+ case 4: rItem[PROPNAME_EXTENSIONS] <<= comphelper::containerToSequence(impl_tokenizeString(sValue, ';'));
+ break;
+ }
+}
+
+
+void FilterCache::impl_interpretDataVal4Filter(const OUString& sValue,
+ sal_Int32 nProp ,
+ CacheItem& rItem )
+{
+ switch(nProp)
+ {
+ // Order
+ case 0: {
+ sal_Int32 nOrder = sValue.toInt32();
+ if (nOrder > 0)
+ {
+ SAL_WARN( "filter.config", "FilterCache::impl_interpretDataVal4Filter()\nCan not move Order value from filter to type on demand!");
+ }
+ }
+ break;
+ // Type
+ case 1: rItem[PROPNAME_TYPE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ break;
+ // DocumentService
+ case 2: rItem[PROPNAME_DOCUMENTSERVICE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ break;
+ // FilterService
+ case 3: rItem[PROPNAME_FILTERSERVICE] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ break;
+ // Flags
+ case 4: rItem[PROPNAME_FLAGS] <<= sValue.toInt32();
+ break;
+ // UserData
+ case 5: rItem[PROPNAME_USERDATA] <<= comphelper::containerToSequence(impl_tokenizeString(sValue, ';'));
+ break;
+ // FileFormatVersion
+ case 6: rItem[PROPNAME_FILEFORMATVERSION] <<= sValue.toInt32();
+ break;
+ // TemplateName
+ case 7: rItem[PROPNAME_TEMPLATENAME] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ break;
+ // [optional!] UIComponent
+ case 8: rItem[PROPNAME_UICOMPONENT] <<= ::rtl::Uri::decode(sValue, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8);
+ break;
+ }
+}
+
+/*-----------------------------------------------
+ TODO work on a cache copy first, which can be flushed afterwards
+ That would be useful to guarantee a consistent cache.
+-----------------------------------------------*/
+void FilterCache::impl_readOldFormat()
+{
+ // Attention: Opening/Reading of this old configuration format has to be handled gracefully.
+ // It's optional and should not disturb our normal work!
+ // E.g. we must check, if the package exists...
+ try
+ {
+ css::uno::Reference< css::uno::XInterface > xInt = impl_openConfig(E_PROVIDER_OLD);
+ css::uno::Reference< css::container::XNameAccess > xCfg(xInt, css::uno::UNO_QUERY_THROW);
+
+ OUString TYPES_SET("Types");
+
+ // May be there is no type set ...
+ if (xCfg->hasByName(TYPES_SET))
+ {
+ css::uno::Reference< css::container::XNameAccess > xSet;
+ xCfg->getByName(TYPES_SET) >>= xSet;
+ const css::uno::Sequence< OUString > lItems = xSet->getElementNames();
+ for (const OUString& rName : lItems)
+ m_lTypes[rName] = impl_readOldItem(xSet, E_TYPE, rName);
+ }
+
+ OUString FILTER_SET("Filters");
+ // May be there is no filter set ...
+ if (xCfg->hasByName(FILTER_SET))
+ {
+ css::uno::Reference< css::container::XNameAccess > xSet;
+ xCfg->getByName(FILTER_SET) >>= xSet;
+ const css::uno::Sequence< OUString > lItems = xSet->getElementNames();
+ for (const OUString& rName : lItems)
+ m_lFilters[rName] = impl_readOldItem(xSet, E_FILTER, rName);
+ }
+ }
+ /* corrupt filter addon? Because it's external (optional) code... we can ignore it. Addon won't work then...
+ but that seems to be acceptable.
+ see #139088# for further information
+ */
+ catch(const css::uno::Exception&)
+ {
+ }
+}
+
+CacheItem FilterCache::impl_readOldItem(const css::uno::Reference< css::container::XNameAccess >& xSet ,
+ EItemType eType,
+ const OUString& sItem)
+{
+ css::uno::Reference< css::container::XNameAccess > xItem;
+ xSet->getByName(sItem) >>= xItem;
+ if (!xItem.is())
+ throw css::uno::Exception("Can not read old item.", css::uno::Reference< css::uno::XInterface >());
+
+ CacheItem aItem;
+ aItem[PROPNAME_NAME] <<= sItem;
+
+ // Installed flag ...
+ // Isn't used any longer!
+
+ // UIName
+ impl_readPatchUINames(xItem, aItem);
+
+ // Data
+ OUString sData;
+ std::vector<OUString> lData;
+ xItem->getByName( "Data" ) >>= sData;
+ lData = impl_tokenizeString(sData, ',');
+ if (
+ (sData.isEmpty()) ||
+ (lData.empty() )
+ )
+ {
+ throw css::uno::Exception( "Can not read old item property DATA.", css::uno::Reference< css::uno::XInterface >());
+ }
+
+ sal_Int32 nProp = 0;
+ for (auto const& prop : lData)
+ {
+ switch(eType)
+ {
+ case E_TYPE :
+ impl_interpretDataVal4Type(prop, nProp, aItem);
+ break;
+
+ case E_FILTER :
+ impl_interpretDataVal4Filter(prop, nProp, aItem);
+ break;
+ default: break;
+ }
+ ++nProp;
+ }
+
+ return aItem;
+}
+
+
+std::vector<OUString> FilterCache::impl_tokenizeString(std::u16string_view sData ,
+ sal_Unicode cSeparator)
+{
+ std::vector<OUString> lData ;
+ sal_Int32 nToken = 0;
+ do
+ {
+ OUString sToken( o3tl::getToken(sData, 0, cSeparator, nToken) );
+ lData.push_back(sToken);
+ }
+ while(nToken >= 0);
+ return lData;
+}
+
+#if OSL_DEBUG_LEVEL > 0
+
+
+OUString FilterCache::impl_searchFrameLoaderForType(const OUString& sType) const
+{
+ for (auto const& frameLoader : m_lFrameLoaders)
+ {
+ const OUString& sItem = frameLoader.first;
+ ::comphelper::SequenceAsHashMap lProps(frameLoader.second);
+ const css::uno::Sequence<OUString> lTypes =
+ lProps[PROPNAME_TYPES].get<css::uno::Sequence<OUString> >();
+
+ if (::std::find(lTypes.begin(), lTypes.end(), sType) != lTypes.end())
+ return sItem;
+ }
+
+ return OUString();
+}
+
+
+OUString FilterCache::impl_searchContentHandlerForType(const OUString& sType) const
+{
+ for (auto const& contentHandler : m_lContentHandlers)
+ {
+ const OUString& sItem = contentHandler.first;
+ ::comphelper::SequenceAsHashMap lProps(contentHandler.second);
+ const css::uno::Sequence<OUString> lTypes =
+ lProps[PROPNAME_TYPES].get<css::uno::Sequence<OUString> >();
+ if (::std::find(lTypes.begin(), lTypes.end(), sType) != lTypes.end())
+ return sItem;
+ }
+
+ return OUString();
+}
+#endif
+
+
+bool FilterCache::impl_isModuleInstalled(const OUString& sModule)
+{
+ css::uno::Reference< css::container::XNameAccess > xCfg;
+
+ // SAFE ->
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ if (!m_xModuleCfg.is())
+ {
+ m_xModuleCfg = officecfg::Setup::Office::Factories::get();
+ }
+
+ xCfg = m_xModuleCfg;
+ }
+ // <- SAFE
+
+ if (xCfg.is())
+ return xCfg->hasByName(sModule);
+
+ return false;
+}
+
+} // namespace filter
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/filtercache.hxx b/filter/source/config/cache/filtercache.hxx
new file mode 100644
index 000000000..2f647c33e
--- /dev/null
+++ b/filter/source/config/cache/filtercache.hxx
@@ -0,0 +1,939 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "cacheitem.hxx"
+#include <com/sun/star/util/URL.hpp>
+#include <com/sun/star/uno/XInterface.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/uno/Any.h>
+#include <comphelper/documentconstants.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+
+
+namespace filter::config {
+
+class CacheUpdateListener;
+
+
+/** @short implements a cache, which contains all
+ elements of our filter and type detection
+ configuration.
+
+ @descr The cache itself is threadsafe implemented.
+ Because it should be used as a singleton only.
+ To do so please use reference mechanism as wrapper
+ around this FilterCache class.
+
+ @attention Because we use a trick to get a full initialized
+ mutex lock during initialization time (means during
+ the constructor runs), the base class FilterCacheLock
+ must be the first of all declared one!
+ Further we make it public. So any user of this class
+ can lock us from outside too.
+ */
+class FilterCache : public cppu::BaseMutex
+{
+
+ // public types
+
+ public:
+
+
+ /** @short identify the type of a container item.
+
+ @descr Because the cache interface is a generic one
+ every group of container items must be specified.
+ */
+ enum EItemType
+ {
+ E_TYPE ,
+ E_FILTER ,
+ E_FRAMELOADER ,
+ E_CONTENTHANDLER
+ };
+
+
+ /** @short indicates, which items already exists inside this cache
+ and which not.
+
+ @descr This cache supports a 2-step load mechanism.
+ First only types (and only some special properties of every type!)
+ but no filters/frame loaders/content handlers will be read.
+ That should be enough to work with this cache e.g. for loading
+ the first document. After this first document was loaded successfully,
+ a special "load-on-demand-thread" will be started to fill this cache
+ with ALL other information, which was not read before.
+ That's the second step. All operations on top of this cache will be
+ blocked then.
+ */
+ enum EFillState
+ {
+ E_CONTAINS_NOTHING = 0,
+ E_CONTAINS_STANDARD = 1,
+ E_CONTAINS_TYPES = 2,
+ E_CONTAINS_FILTERS = 4,
+ E_CONTAINS_FRAMELOADERS = 8,
+ E_CONTAINS_CONTENTHANDLERS = 16
+ };
+
+
+ // private types
+
+ private:
+
+
+ /** @short regulate, which properties of a configured item
+ will be read.
+
+ @descr To perform reading of all configuration items,
+ only standard properties will be handled. At a second
+ step all optional properties will be read and added to
+ our internal structures. Of course the combination of
+ both options can be used too, to get all properties
+ at the same time.
+ */
+ enum EReadOption
+ {
+ E_READ_STANDARD = 1,
+ E_READ_UPDATE = 2,
+ E_READ_ALL = 3
+ };
+
+
+ /** @short indicates the state of a configuration set item.
+
+ @descr Inside method flush we check:
+ <ul>
+ <li>if the item exists inside config layer but not inside our cache => REMOVED</li>
+ <li>if the item exists inside config layer and inside our cache => CHANGED</li>
+ <li>if the item does not exists inside config layer but inside our cache => ADDED.</li>
+ </ul>
+ */
+ enum EItemFlushState
+ {
+ /// indicates an unchanged item (can occur e.g. if an item was added and(!) removed before it was flushed ...
+ E_ITEM_UNCHANGED = 0,
+ /// indicates an item, which exists inside config layer but not inside our own cache
+ E_ITEM_REMOVED = 1,
+ /// indicates an item, which exists inside config layer and inside our own cache
+ E_ITEM_CHANGED = 2,
+ /// indicates an item, which does not exists inside config layer but inside our own cache
+ E_ITEM_ADDED = 3
+ };
+
+
+ /** TODO document me */
+ enum EConfigProvider
+ {
+ E_PROVIDER_TYPES = 0,
+ E_PROVIDER_FILTERS = 1,
+ E_PROVIDER_OTHERS = 2,
+ E_PROVIDER_OLD = 3
+ };
+
+
+ // member
+
+ private:
+
+
+ /** @short holds the used configuration provider alive, which
+ provides access to the list of types. */
+ mutable css::uno::Reference< css::uno::XInterface > m_xConfigTypes;
+
+
+ /** @short holds the used configuration provider alive, which
+ provides access to the list of filters. */
+ mutable css::uno::Reference< css::uno::XInterface > m_xConfigFilters;
+
+
+ /** @short holds the used configuration provider alive, which
+ provides access to the list of other values needed
+ by our type detection framework. */
+ mutable css::uno::Reference< css::uno::XInterface > m_xConfigOthers;
+
+
+ /** @short contains all loaded types with its properties. */
+ mutable CacheItemList m_lTypes;
+
+
+ /** @short contains all loaded filters with its properties. */
+ mutable CacheItemList m_lFilters;
+
+
+ /** @short contains all loaded frame loader with its properties. */
+ mutable CacheItemList m_lFrameLoaders;
+
+
+ /** @short contains all loaded content handler with its properties. */
+ mutable CacheItemList m_lContentHandlers;
+
+
+ /** @short optimize mapping of URL extensions to a type representation,
+ by using extensions as key and a list of internal
+ type names as value. */
+ mutable CacheItemRegistration m_lExtensions2Types;
+
+
+ /** @short optimize mapping of URL pattern to a type representation,
+ by using patterns as key and a list of internal
+ type names as value. */
+ mutable CacheItemRegistration m_lURLPattern2Types;
+
+
+ /** @short contains the current locale of the office and will be
+ used to work with localized configuration values. */
+ OUString m_sActLocale;
+
+
+ /** @short contains status, which cache items/properties
+ was already loaded from the underlying configuration.
+
+ @descr This information can be used to detect missing
+ information and load it on demand.
+
+ @see EFillState
+ @see load()
+ */
+ EFillState m_eFillState;
+
+
+ /** TODO document me ... */
+ std::vector<OUString> m_lChangedTypes;
+ std::vector<OUString> m_lChangedFilters;
+ std::vector<OUString> m_lChangedFrameLoaders;
+ std::vector<OUString> m_lChangedContentHandlers;
+
+ /// standard property names for filter config keyed by EReadOption
+ css::uno::Sequence< OUString > m_aStandardProps[4];
+
+ /// type property names for filter config keyed by EReadOption
+ css::uno::Sequence< OUString > m_aTypeProps[4];
+
+ /// readonly access to the module configuration of OOo
+ css::uno::Reference< css::container::XNameAccess > m_xModuleCfg;
+
+ rtl::Reference< CacheUpdateListener > m_xTypesChglisteners;
+ rtl::Reference< CacheUpdateListener > m_xFiltersChgListener;
+
+
+ // interface
+
+ public:
+
+
+ // ctor/dtor
+
+ /** @short standard ctor
+
+ @descr It's not allowed to do anything here...
+ especially is forbidden to start operations,
+ which needs a FilterCache instance too!
+ Why? Because this FilterCache instance will be
+ used as a singleton! And if during this ctor any
+ action related to this FilterCache singleton is
+ started... a race will be the result.
+
+ The first method after construction of a new
+ singleton reference should be "load()". There
+ a special fill state of this cache can be forced.
+ */
+ FilterCache();
+
+
+ /** @short standard dtor.
+ */
+ ~FilterCache();
+
+
+ /** @short creates a copy of this container.
+
+ @descr Such copy can be used then to modify items (add/change/remove)
+ without the risk to damage the original container.
+ After its changed data was flushed to the configuration it can be
+ removed.
+
+ The original container will get these new data automatically
+ because it listen for changes on the internal used configuration layer.
+ If the new data are needed immediately inside the original container,
+ the method takeOver() can be used to copy all changes back.
+ The may be following notifications of the configuration will be superfluous then.
+ But they can't be stopped...
+
+ All internal structures will be copied here. But the internal used
+ configuration (update) access won't be copied. The cloned instance contains
+ a different one.
+ */
+ std::unique_ptr<FilterCache> clone() const;
+
+
+ /** @short copy the cache content or rClone back to this instance.
+ */
+ void takeOver(const FilterCache& rClone);
+
+
+ /** @short force special fill state of this cache.
+
+ @descr This method checks, if all requested items/properties already
+ exist. Only missing information will be read.
+ Otherwise this method does nothing!
+
+ This method must be called from every user of this cache
+ every time it needs a filled cache. Normally we load
+ only standard information into this cache on startup.
+
+ @throw An exception if the cache could not be filled really
+ or seems to be invalid afterwards. But there is no reaction
+ at all if this method does nothing inside, because the cache
+ is already fully filled!
+ */
+ void load(EFillState eRequired);
+
+
+ /** @short return the current fill state of this cache.
+
+ @descr This information can be used e.g. to start
+ a search on top of this cache with a minimum on
+ information ... and do it again, if some other
+ cache items seems to be available after calling of "loadAll()"
+ on this cache and first search does not had any valid results.
+
+ @return sal_True if the required fill state exists for this cache; FALSE
+ otherwise.
+
+ @throws css::uno::Exception
+ */
+ bool isFillState(EFillState eRequired) const;
+
+
+ /** @short return a list of key names for items, which match
+ the specified criteria.
+
+ @descr The returned key names can be used at another method "getItem()"
+ of this cache to get further information about this item.
+
+ @attention Please note: because this cache can be used inside multithreaded
+ environments, such returned key name can point to an already removed
+ item! Please be aware of some "NoSuchElementExceptions" if you try to
+ call any other method of this cache in relation to this key name.
+
+ @param eType
+ specify the sub container of this cache, which should be used for
+ searching. see also EItemType.
+
+ @param lIProps
+ specify the property set, which must exist at the searched items
+ as minimum.
+
+ @param lEProps
+ specify the property set, which must not(!) exist at the searched items
+ as minimum.
+
+ @return [std::vector<OUString>]
+ a list of key names, which identify items of the queried sub container.
+ May be an empty list.
+
+ @throw [css::uno::Exception]
+ if some input parameter are wrong or the cache itself is not valid
+ any longer, because any operation before damage it.
+ */
+ std::vector<OUString> getMatchingItemsByProps( EItemType eType,
+ o3tl::span< const css::beans::NamedValue > lIProps,
+ o3tl::span< const css::beans::NamedValue > lEProps = {}) const;
+
+
+ /** @short indicates if the requested sub container
+ contains some items.
+
+ @descr We don't provide any information about the count
+ of such items. Because we don't implement any index
+ based interface! The information "we have items or not"
+ must be enough for the outside code ... till somewhere
+ give us a good reason. :-)
+
+ @param eType
+ specify the sub container of this cache, which should be used.
+ see also EItemType.
+
+ @return [sal_Bool]
+ True, if the requested sub container contains some items;
+ False otherwise.
+
+ @throw [css::uno::Exception]
+ if some input parameter are wrong or the cache itself is not valid
+ any longer, because any operation before damage it.
+ */
+ bool hasItems(EItemType eType) const;
+
+
+ /** @short return a list of all key names, which represent
+ an item inside the specified sub container.
+
+ @attention Please note: because this cache can be used inside multithreaded
+ environments, such returned key names can point to some already removed
+ items! Please be aware of some "NoSuchElementExceptions" if you try to
+ call any other method of this cache in relation to this key names.
+
+ @param eType
+ specify the sub container of this cache, which should be used for
+ searching. see also EItemType.
+
+ @return [std::vector<OUString>]
+ a list of key names, which can be used to access the item properties
+ using some other methods of this cache.
+
+ @throw [css::uno::Exception]
+ if some input parameter are wrong or the cache itself is not valid
+ any longer, because any operation before damage it.
+ */
+ std::vector<OUString> getItemNames(EItemType eType) const;
+
+
+ /** @short check if the required item exist inside this container.
+
+ @attention This method exists to supports some UNO container interfaces
+ only. (e.g. XNameAccess.hasByName()). But inside multithreaded
+ environments there is no guarantee, that this item still exists, if
+ it's really requested e.g. by calling getItem()!
+ Be aware of some NoSuchElementExistExceptions ...
+
+ @param eType
+ specify the sub container of this cache, which should be used.
+ see also EItemType.
+
+ @param sItem
+ the key name of the requested item inside the specified sub container.
+
+ @throw [css::uno::Exception]
+ if some input parameter are wrong or the cache itself is not valid
+ any longer, because any operation before damage it.
+ */
+ bool hasItem( EItemType eType,
+ const OUString& sItem);
+
+
+ /** @short return an item, which match the specified type and name.
+
+ @descr Because this cache can be used inside multithreaded environments
+ the caller must be aware of some exceptions - especially a "NoSuchElementExcepotion".
+ May another thread already removed the required item before ...
+
+ @param eType
+ specify the sub container of this cache, which should be used for
+ searching. see also EItemType.
+
+ @param sItem
+ specify the requested item by its key name.
+
+ @return [CacheItem]
+ the required item if it could be located ...
+ But we throw an exception if the required item does not exist!
+
+ @throw [css::container::NoSuchElementException]
+ if the required item does not still exist.
+
+ @throw [css::uno::Exception]
+ if some input parameter are wrong or the cache itself is not valid
+ any longer, because any operation before damage it.
+ */
+ CacheItem getItem( EItemType eType,
+ const OUString& sItem);
+
+
+ /** TODO document me ...
+
+ @throws css::uno::Exception
+ */
+ void removeItem( EItemType eType,
+ const OUString& sItem);
+
+
+ /** TODO document me ...
+
+ @throws css::uno::Exception
+ */
+ void setItem( EItemType eType ,
+ const OUString& sItem ,
+ const CacheItem& aValue);
+
+
+ /** TODO document me ...
+
+ @throws css::uno::Exception
+ */
+ void refreshItem( EItemType eType,
+ const OUString& sItem);
+
+
+ /** @short add some implicit properties to the given
+ cache item reference.
+
+ @descr Such properties can e.g. finalized or mandatory.
+ They are not persistent and not really part of e.g. a
+ filter not. But they are attributes of a configuration
+ entry and can influence our container interface.
+
+ @attention These properties are not part of the normal CacheItem
+ returned by the method getItem(). Because getItem() is
+ used internally too but these specialized properties
+ are needed at our container services only. So these
+ function sets are different to allow different handling.
+
+ @param eType
+ specify the sub container of this cache, which should be used for
+ searching. see also EItemType.
+
+ @param sItem
+ specify the requested item by its key name.
+
+ @param rItem
+ contains already the normal properties of this item,
+ and will be used as out parameter to add the implicit
+ attributes there.
+
+ @throw [css::uno::Exception]
+ if an internal error occurred.
+ Note: if the item is missing inside the underlying configuration
+ no exception will be thrown. In such case the item is marked as
+ finalized/mandatory automatically
+ Reason: maybe the item comes from the old configuration package and
+ was not migrated to the new one. So we can't provide write access
+ to such items...
+ */
+ css::uno::Any getItemWithStateProps( EItemType eType,
+ const OUString& sItem);
+
+ /** TODO document me
+
+ @throws css::uno::Exception
+ */
+ static void removeStatePropsFromItem(CacheItem& aValue);
+
+
+ /** @short force writing of all changes (which was made after
+ last flush was called) back to the configuration.
+
+ @descr TODO
+
+ @throw [css::uno::Exception]
+ if the cache itself is not valid
+ any longer, because any operation before damage it.
+ */
+ void flush();
+
+
+ /** @short supports a flat type detection for given URL.
+
+ @descr Because such detection works on our optimized internal
+ structures (e.g. mapping from extensions/pattern to type names),
+ it should be made inside this cache.
+
+ @param aURL
+ URL of the content, which type should be detected.
+ It's already parsed and split into its different parts,
+ like e.g.: main, jump marks etcpp.
+
+ @param rFlatTypes
+ used as [out] parameter to add all types, which match to the given
+ URL. Further an information is added for every type. It indicates, how
+ this type is related to the specified URL (means e.g. if it matches
+ by extension or URLPattern...).
+
+ @attention Please note: because this cache can be used inside multithreaded
+ environments, such returned key names can point to some already removed
+ items! Please be aware of some "NoSuchElementExceptions" if you try to
+ call any other method of this cache in relation to this key names.
+
+ @throw [css::uno::Exception]
+ if the cache itself is not valid
+ any longer, because any operation before damage it.
+ */
+ void detectFlatForURL(const css::util::URL& aURL ,
+ FlatDetection& rFlatTypes) const;
+
+
+ // private helper
+
+ private:
+
+
+ /** @short return a reference to one of our internal
+ sub container, which contains items of the
+ requested type.
+
+ @param eType
+ specify, which sub container is needed outside.
+
+ @return [CacheItemList&]
+ a reference(!) to the right sub container member.
+
+ @throw [css::uno::Exception]
+ if the required list does not exist.
+ */
+ const CacheItemList& impl_getItemList(EItemType eType) const;
+
+ CacheItemList& impl_getItemList(EItemType eType);
+
+ CacheItem& impl_getItem( EItemType eType, const OUString& sItem);
+
+ /** @short return a valid configuration update access
+ to the underlying configuration package, which
+ is fix for this cache.
+
+ @descr It checks first, if the internal member m_xConfig already
+ points to an open update access. If not - it opens a new one.
+ Doing so this method can be called every time a configuration
+ access is needed.
+
+ @param eProvider
+ specify the needed configuration provider.
+ see EConfigProvider for further information ...
+
+ @throws css::uno::Exception
+
+ @attention If a configuration access was opened successfully
+ all necessary listener connections will be established
+ too. So this cache will be informed about outside updates.
+ */
+ css::uno::Reference< css::uno::XInterface > impl_openConfig(EConfigProvider eProvide);
+
+
+ /** @short tries to open the requested configuration root
+ using the specified modi.
+
+ @param sRoot
+ specify the configuration root, which should be opened.
+
+ @param bReadOnly
+ enable/disable write access on the returned configuration
+ object.
+
+ @param bLocalesMode
+ enable/disable special handling of localized configuration
+ items by the returned configuration object.
+
+ @return A valid reference, if the configuration access could be opened
+ and initialized within the requested modes successfully;
+ a NULL reference otherwise.
+ */
+ css::uno::Reference< css::uno::XInterface > impl_createConfigAccess(const OUString& sRoot ,
+ bool bReadOnly ,
+ bool bLocalesMode);
+
+
+ /** @short reads the specified configuration key
+ and return its value.
+
+ @descr The specified key must be an absolute configuration path,
+ which can be split into its package and relative path tokens.
+
+ @attention Because this function might opens a new configuration
+ read access for reading one key value only, it should
+ be used in rare cases only. It's an easy way... but an
+ expensive one.
+
+ @param sDirectKey
+ the absolute configuration path, which should be read.
+
+ @return [css::uno::Any]
+ the value of the requested key.
+ Can be empty if an internal error occurred or if the requested
+ key does not exists!
+ */
+ css::uno::Any impl_getDirectCFGValue(const OUString& sDirectKey);
+
+
+ /** @short load the underlying configuration into this cache.
+
+ @descr Which items should be read can be regulate by the
+ parameter eRequiredState. That provides the possibility
+ to load standard values on startup only and update this
+ cache later on demand with all available information.
+
+ @param eRequiredState
+ indicates, which fill state this cache should have afterwards.
+
+ @throws css::uno::Exception
+ */
+ void impl_load(EFillState eRequiredState);
+
+
+ /** @short validate the whole cache and create
+ structures for optimized items access.
+
+ @descr Wrong cache items will be removed automatically.
+ Wrong dependencies will be corrected automatically.
+ If something could not be repaired - an exception
+ is thrown.
+ Further some optimized structures will be created.
+ E.g.: a hash to map extensions to her types.
+
+ @attention There is no exception, if the cache could be repaired
+ but contained wrong elements before!
+
+ @throw [css::uno::Exception]
+ if cache is invalid and could not be repaired.
+ */
+ void impl_validateAndOptimize();
+
+ private:
+
+
+ /** @short read the specified config set into the cache.
+
+ @descr This method provides the following mechanism for reading:
+ a) read only standard properties of set items
+ b) read anything
+ c) read only optional properties and update already existing
+ items of the specified cache
+
+ @param xConfig
+ API which provides access to the required configuration set.
+
+ @param eType
+ specify the type of config item, which must be interpreted.
+ Of course this information can be used to locate the right set
+ at the given xConfig API object.
+
+ @param eOption
+ regulate reading of standard/optional or all properties.
+
+ @param pCache
+ points to the cache member, which should be filled or updated.
+
+ @throw [css::uno::Exception]
+ if an unrecoverable error occurs inside this operation.
+ */
+ void impl_loadSet(const css::uno::Reference< css::container::XNameAccess >& xConfig,
+ EItemType eType ,
+ EReadOption eOption,
+ CacheItemList* pCache );
+
+
+ /** @short read the specified container item from the given configuration set.
+
+ @descr It's not added to any internal structures here. That must be done
+ outside this method.
+
+ @param xSet
+ provides access to the configuration set, which includes all items.
+
+ @param eType
+ specify, which container item type must be read.
+
+ @param sItem
+ means the internal name, which can be used to address the item
+ properties relative to the given configuration set.
+
+ @param eOption
+ regulate, which properties of the requested item should be read.
+ See definition of EReadOption for further information.
+
+ @throw [css::uno::Exception]
+ if an unrecoverable error occurs inside this operation.
+ */
+ CacheItem impl_loadItem(const css::uno::Reference< css::container::XNameAccess >& xSet ,
+ EItemType eType ,
+ const OUString& sItem ,
+ EReadOption eOption);
+
+
+ /** @short try to load the requested item on demand from the underlying configuration
+ layer.
+
+ @descr The outside code has to be sure, that the item does not already exists
+ inside this cache. Otherwise it will be loaded twice. This method
+ doesn't check such constellations!
+
+ @param eType
+ specify the type of config item, which must be interpreted.
+ Of course this information can be used to locate the right set
+ at the given xConfig API object.
+
+ @param sItem
+ the set node name of the requested item.
+
+ @return An iterator, which points directly to the new cached item.
+ Is a valid iterator if no exception occurred here!
+ But to improve robustness - it should be checked :-)
+
+ @throw [css::container::NoSuchElementException]
+ if the item does not exists inside the configuration layer too!
+
+ @throw [css::uno::Exception]
+ if an unrecoverable error occurs inside this operation.
+ */
+ CacheItemList::iterator impl_loadItemOnDemand( EItemType eType,
+ const OUString& sItem);
+
+
+ /** TODO
+
+ @throws css::uno::Exception
+ */
+ static void impl_saveItem(const css::uno::Reference< css::container::XNameReplace >& xSet ,
+ EItemType eType ,
+ const CacheItem & aValue);
+
+
+ /** TODO
+
+ @throws css::uno::Exception
+ */
+ void impl_addItem2FlushList( EItemType eType,
+ const OUString& sItem);
+
+
+ /** TODO
+
+ @throws css::uno::Exception
+ */
+ static void impl_flushByList(const css::uno::Reference< css::container::XNameAccess >& xSet ,
+ EItemType eType ,
+ const CacheItemList& rCache,
+ const std::vector<OUString>& lItems);
+
+
+ /** @short specify, which save operation is necessary for the specified item.
+
+ @desrc If an item of this cache will be added/removed or modified it will
+ be changed inside memory only first. But we save its name inside a special
+ list of changed items. If at least the method flush() is called, we use
+ this list to check if the item was changed/added or removed. This method
+ checks the exist state of the requested item inside our own cache
+ and inside the underlying configuration layer to find out, if the item
+ must be removed/added or modified inside the configuration layer.
+
+ @param xSet
+ points directly to the configuration set, where the item should resist
+ (if it exists!).
+
+ @param rList
+ points to our internal cache list, where the item should resist
+ (if it exists!).
+
+ @param sItem
+ the internal name of the item, which should be checked.
+
+ @return An enum value of type EItemFlushState, which indicates the needed
+ API operation for updating the underlying configuration layer.
+
+ @throws An exception if anything failed inside this operation.
+ e.g. the given configuration set was not open.
+ */
+ static EItemFlushState impl_specifyFlushOperation(const css::uno::Reference< css::container::XNameAccess >& xSet ,
+ const CacheItemList& rList,
+ const OUString& sItem);
+
+
+ /** TODO
+
+ @throws css::uno::Exception
+ */
+ void impl_readPatchUINames(const css::uno::Reference< css::container::XNameAccess >& xNode,
+ CacheItem& rItem);
+
+
+ /** TODO
+
+ @throws css::uno::Exception
+ */
+ static void impl_savePatchUINames(const css::uno::Reference< css::container::XNameReplace >& xNode,
+ const CacheItem& rItem);
+
+ /** TODO */
+ void impl_readOldFormat();
+
+ /** TODO
+
+ @throws css::uno::Exception
+ */
+ CacheItem impl_readOldItem(const css::uno::Reference< css::container::XNameAccess >& xSet ,
+ EItemType eType,
+ const OUString& sItem);
+
+
+ /** TODO */
+ static void impl_interpretDataVal4Type(const OUString& sValue,
+ sal_Int32 nProp ,
+ CacheItem& rItem );
+
+
+ /** TODO */
+ static void impl_interpretDataVal4Filter(const OUString& sValue,
+ sal_Int32 nProp ,
+ CacheItem& rItem );
+
+
+ /** TODO */
+ static std::vector<OUString> impl_tokenizeString(std::u16string_view sData ,
+ sal_Unicode cSeparator);
+
+
+#if OSL_DEBUG_LEVEL > 0
+ /** TODO */
+ OUString impl_searchFrameLoaderForType(const OUString& sType) const;
+ OUString impl_searchContentHandlerForType(const OUString& sType) const;
+#endif
+
+
+ /** @short check if the specified OOo module is installed.
+
+ @param sModule
+ the long name of the module (e.g. "com.sun.star.text.TextDocument").
+
+ @return sal_True if the requested module is installed; sal_False otherwise.
+ */
+ bool impl_isModuleInstalled(const OUString& sModule);
+
+
+ /** @short convert a list of flag names to its int representation.
+
+ @param lNames
+ the list of flag names.
+
+ @return the converted flag field.
+ */
+ static SfxFilterFlags impl_convertFlagNames2FlagField(const css::uno::Sequence< OUString >& lNames);
+
+
+ /** @short convert a flag field value to its list representation of flag names.
+
+ @param nFlags
+ the flag field value
+
+ @return [seq< string >]
+ the converted flag name list.
+ */
+ static css::uno::Sequence< OUString > impl_convertFlagField2FlagNames(SfxFilterFlags nFlags);
+};
+
+FilterCache& GetTheFilterCache();
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/filterconfig1.component b/filter/source/config/cache/filterconfig1.component
new file mode 100644
index 000000000..711c0e38f
--- /dev/null
+++ b/filter/source/config/cache/filterconfig1.component
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.filter.config.ConfigFlush"
+ constructor="filter_ConfigFlush_get_implementation" single-instance="true">
+ <service name="com.sun.star.document.FilterConfigRefresh"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.filter.config.ContentHandlerFactory"
+ constructor="filter_ContentHandlerFactory_get_implementation">
+ <service name="com.sun.star.frame.ContentHandlerFactory"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.filter.config.FilterFactory"
+ constructor="filter_FilterFactory_get_implementation">
+ <service name="com.sun.star.document.FilterFactory"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.filter.config.FrameLoaderFactory"
+ constructor="filter_FrameLoaderFactory_get_implementation">
+ <service name="com.sun.star.frame.FrameLoaderFactory"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.filter.config.TypeDetection"
+ constructor="filter_TypeDetection_get_implementation">
+ <service name="com.sun.star.document.TypeDetection"/>
+ </implementation>
+</component>
diff --git a/filter/source/config/cache/filterfactory.cxx b/filter/source/config/cache/filterfactory.cxx
new file mode 100644
index 000000000..e083614c0
--- /dev/null
+++ b/filter/source/config/cache/filterfactory.cxx
@@ -0,0 +1,498 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "filterfactory.hxx"
+#include "constant.hxx"
+
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <comphelper/enumhelper.hxx>
+#include <comphelper/sequence.hxx>
+#include <officecfg/Setup.hxx>
+#include <officecfg/TypeDetection/UISort.hxx>
+
+
+namespace filter::config{
+
+FilterCache& GetTheFilterCache()
+{
+ static FilterCache CACHE;
+ return CACHE;
+}
+
+/** @short define all possible parts of a filter query.
+
+ @descr syntax: "<query>[:<param>[=<value>]]"
+ e.g.: "_query_writer:default_first:use_order:sort_prop=uiname"
+
+ argument description default
+ -----------------------------------------------------------------------------------------------
+ iflags=<mask> include filters by given mask 0
+ eflags=<mask> exclude filters by given mask 0
+ sort_prop=<[name,uiname]> sort by internal name or uiname name
+ descending sort descending false
+ use_order use order flag of filters for sorting false
+ default_first set default filter on top of return list false
+ case_sensitive compare "sort_prop" case sensitive false
+ */
+
+FilterFactory::FilterFactory(const css::uno::Reference< css::uno::XComponentContext >& rxContext)
+ : m_xContext(rxContext)
+{
+ static const css::uno::Sequence<OUString> sServiceNames { "com.sun.star.document.FilterFactory" };
+ BaseContainer::init("com.sun.star.comp.filter.config.FilterFactory" ,
+ sServiceNames,
+ FilterCache::E_FILTER );
+}
+
+
+FilterFactory::~FilterFactory()
+{
+}
+
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL FilterFactory::createInstance(const OUString& sFilter)
+{
+ return createInstanceWithArguments(sFilter, css::uno::Sequence< css::uno::Any >());
+}
+
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL FilterFactory::createInstanceWithArguments(const OUString& sFilter ,
+ const css::uno::Sequence< css::uno::Any >& lArguments)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ auto & cache = GetTheFilterCache();
+
+ // search filter on cache
+ CacheItem aFilter = cache.getItem(FilterCache::E_FILTER, sFilter);
+ OUString sFilterService;
+ aFilter[PROPNAME_FILTERSERVICE] >>= sFilterService;
+
+ // create service instance
+ css::uno::Reference< css::uno::XInterface > xFilter;
+ if (!sFilterService.isEmpty())
+ xFilter = m_xContext->getServiceManager()->createInstanceWithContext(sFilterService, m_xContext);
+
+ // initialize filter
+ css::uno::Reference< css::lang::XInitialization > xInit(xFilter, css::uno::UNO_QUERY);
+ if (xInit.is())
+ {
+ // format: lInitData[0] = seq<PropertyValue>, which contains all configuration properties of this filter
+ // lInitData[1] = lArguments[0]
+ // ...
+ // lInitData[n] = lArguments[n-1]
+ css::uno::Sequence< css::beans::PropertyValue > lConfig;
+ aFilter >> lConfig;
+
+ ::std::vector< css::uno::Any > stlArguments(comphelper::sequenceToContainer< ::std::vector< css::uno::Any > >(lArguments));
+ stlArguments.insert(stlArguments.begin(), css::uno::Any(lConfig));
+
+ xInit->initialize(comphelper::containerToSequence(stlArguments));
+ }
+
+ return xFilter;
+ // <- SAFE
+}
+
+
+css::uno::Sequence< OUString > SAL_CALL FilterFactory::getAvailableServiceNames()
+{
+ /* Attention: Instead of getElementNames() this method have to return only filter names,
+ which can be created as UNO Services really. That's why we search for filters,
+ which don't have a valid value for the property "FilterService".
+ Of course we can't check for corrupted service names here. We can check
+ for empty strings only...
+ */
+ css::beans::NamedValue lEProps[] {
+ { PROPNAME_FILTERSERVICE, css::uno::Any(OUString()) } };
+
+ std::vector<OUString> lUNOFilters;
+ try
+ {
+ lUNOFilters = GetTheFilterCache().getMatchingItemsByProps(FilterCache::E_FILTER, {}, lEProps);
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception&)
+ { lUNOFilters.clear(); }
+
+ return comphelper::containerToSequence(lUNOFilters);
+}
+
+
+css::uno::Reference< css::container::XEnumeration > SAL_CALL FilterFactory::createSubSetEnumerationByQuery(const OUString& sQuery)
+{
+ // reject old deprecated queries ...
+ if (sQuery.startsWith("_filterquery_"))
+ throw css::uno::RuntimeException(
+ "Use of deprecated and now unsupported query!",
+ static_cast< css::container::XContainerQuery* >(this));
+
+ // convert "_query_xxx:..." to "getByDocService=xxx:..."
+ OUString sNewQuery(sQuery);
+ sal_Int32 pos = sNewQuery.indexOf("_query_");
+ if (pos != -1)
+ {
+ OSL_FAIL("DEPRECATED!\nPlease use new query format: 'matchByDocumentService=...'");
+ OUString sPatchedQuery(OUString::Concat("matchByDocumentService=") + sNewQuery.subView(7));
+ sNewQuery = sPatchedQuery;
+ }
+
+ // analyze query and split it into its tokens
+ QueryTokenizer lTokens(sNewQuery);
+ std::vector<OUString> lEnumSet;
+
+ // start query
+ // (see attention comment below!)
+ if (lTokens.valid())
+ {
+ // SAFE -> ----------------------
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ // May be not all filters was loaded ...
+ // But we need it now!
+ impl_loadOnDemand();
+ }
+ // <- SAFE ----------------------
+
+ if (lTokens.find(QUERY_IDENTIFIER_GETPREFERREDFILTERFORTYPE) != lTokens.end())
+ OSL_FAIL("DEPRECATED!\nPlease use prop search at the TypeDetection container!");
+ else
+ if (lTokens.find(QUERY_IDENTIFIER_MATCHBYDOCUMENTSERVICE) != lTokens.end())
+ lEnumSet = impl_queryMatchByDocumentService(lTokens);
+ else
+ if (lTokens.find(QUERY_IDENTIFIER_GET_SORTED_FILTERLIST) != lTokens.end())
+ lEnumSet = impl_getSortedFilterList(lTokens);
+ }
+
+ // pack list of item names as an enum list
+ // Attention: Do not return empty reference for empty list!
+ // The outside check "hasMoreElements()" should be enough, to detect this state :-)
+ return new ::comphelper::OEnumerationByName(this, std::move(lEnumSet));
+}
+
+
+std::vector<OUString> FilterFactory::impl_queryMatchByDocumentService(const QueryTokenizer& lTokens) const
+{
+ // analyze query
+ QueryTokenizer::const_iterator pIt;
+
+ OUString sDocumentService;
+ sal_Int32 nIFlags = 0;
+ sal_Int32 nEFlags = 0;
+
+ pIt = lTokens.find(QUERY_IDENTIFIER_MATCHBYDOCUMENTSERVICE);
+ if (pIt != lTokens.end())
+ sDocumentService = pIt->second;
+
+#define COMP_HACK
+#ifdef COMP_HACK
+ if ( sDocumentService == "writer" )
+ {
+ OSL_FAIL("DEPRECATED!\nPlease use right document service for filter query!");
+ sDocumentService = "com.sun.star.text.TextDocument";
+ }
+ else if ( sDocumentService == "web" )
+ {
+ OSL_FAIL("DEPRECATED!\nPlease use right document service for filter query!");
+ sDocumentService = "com.sun.star.text.WebDocument";
+ }
+ else if ( sDocumentService == "global" )
+ {
+ OSL_FAIL("DEPRECATED!\nPlease use right document service for filter query!");
+ sDocumentService = "com.sun.star.text.GlobalDocument";
+ }
+ else if ( sDocumentService == "calc" )
+ {
+ OSL_FAIL("DEPRECATED!\nPlease use right document service for filter query!");
+ sDocumentService = "com.sun.star.sheet.SpreadsheetDocument";
+ }
+ else if ( sDocumentService == "draw" )
+ {
+ OSL_FAIL("DEPRECATED!\nPlease use right document service for filter query!");
+ sDocumentService = "com.sun.star.drawing.DrawingDocument";
+ }
+ else if ( sDocumentService == "impress" )
+ {
+ OSL_FAIL("DEPRECATED!\nPlease use right document service for filter query!");
+ sDocumentService = "com.sun.star.presentation.PresentationDocument";
+ }
+ else if ( sDocumentService == "math" )
+ {
+ OSL_FAIL("DEPRECATED!\nPlease use right document service for filter query!");
+ sDocumentService = "com.sun.star.formula.FormulaProperties";
+ }
+#endif
+
+ pIt = lTokens.find(QUERY_PARAM_IFLAGS);
+ if (pIt != lTokens.end())
+ nIFlags = pIt->second.toInt32();
+
+ pIt = lTokens.find(QUERY_PARAM_EFLAGS);
+ if (pIt != lTokens.end())
+ nEFlags = pIt->second.toInt32();
+
+ // SAFE -> ----------------------
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ // search suitable filters
+ FilterCache* pCache = impl_getWorkingCache();
+ std::vector<OUString> lFilterNames = pCache->getItemNames(FilterCache::E_FILTER);
+ std::vector<OUString> lResult ;
+
+ for (auto const& filterName : lFilterNames)
+ {
+ try
+ {
+ const CacheItem aFilter = pCache->getItem(FilterCache::E_FILTER, filterName);
+
+ // "matchByDocumentService=" => any filter will be addressed here
+ // "matchByDocumentService=all" => any filter will be addressed here
+ // "matchByDocumentService=com.sun.star..." => only filter matching this document service will be addressed
+ OUString sCheckValue = aFilter.getUnpackedValueOrDefault(PROPNAME_DOCUMENTSERVICE, OUString());
+ if (
+ (!sDocumentService.isEmpty() ) &&
+ (sDocumentService != QUERY_CONSTVALUE_ALL ) &&
+ (sCheckValue != sDocumentService )
+ )
+ {
+ continue; // ignore filter -> try next one!
+ }
+
+ // "iflags=" => not allowed
+ // "iflags=-1" => not allowed
+ // "iflags=0" => not useful
+ // "iflags=283648" => only filter, which has set these flag field will be addressed
+ sal_Int32 nCheckValue = aFilter.getUnpackedValueOrDefault(PROPNAME_FLAGS, sal_Int32(0));
+ if (
+ (nIFlags > 0 ) &&
+ ((nCheckValue & nIFlags) != nIFlags)
+ )
+ {
+ continue; // ignore filter -> try next one!
+ }
+
+ // "eflags=" => not allowed
+ // "eflags=-1" => not allowed
+ // "eflags=0" => not useful
+ // "eflags=283648" => only filter, which has not set these flag field will be addressed
+ if (
+ (nEFlags > 0 ) &&
+ ((nCheckValue & nEFlags) == nEFlags)
+ )
+ {
+ continue; // ignore filter -> try next one!
+ }
+
+ // OK - this filter passed all checks.
+ // It match the query ...
+ lResult.push_back(filterName);
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception&)
+ { continue; }
+ }
+
+ aLock.clear();
+ // <- SAFE ----------------------
+
+ return lResult;
+}
+
+namespace {
+
+class stlcomp_removeIfMatchFlags
+{
+ private:
+ FilterCache* m_pCache ;
+ sal_Int32 m_nFlags ;
+ bool m_bIFlags;
+
+ public:
+ stlcomp_removeIfMatchFlags(FilterCache* pCache ,
+ sal_Int32 nFlags ,
+ bool bIFlags)
+ : m_pCache (pCache )
+ , m_nFlags (nFlags )
+ , m_bIFlags(bIFlags)
+ {}
+
+ bool operator() (const OUString& sFilter) const
+ {
+ try
+ {
+ const CacheItem aFilter = m_pCache->getItem(FilterCache::E_FILTER, sFilter);
+ sal_Int32 nFlags = aFilter.getUnpackedValueOrDefault(PROPNAME_FLAGS, (sal_Int32(0)));
+
+ bool bMatch = false;
+ if (m_bIFlags)
+ // IFlags are interpreted as ALL_FLAGS_MUST_MATCH !
+ bMatch = ((nFlags & m_nFlags) == m_nFlags);
+ else
+ // EFlags are interpreted as AT_LEAST_ONE_FLAG_MUST_MATCH !
+ bMatch = !(nFlags & m_nFlags);
+ // We are asked for bRemove ! And bMatch = !bRemove => so bRemove = !bMatch .-)
+ return !bMatch;
+ }
+ catch(const css::container::NoSuchElementException &)
+ {
+ return true;
+ }
+ }
+};
+
+}
+
+std::vector<OUString> FilterFactory::impl_getSortedFilterList(const QueryTokenizer& lTokens) const
+{
+ // analyze the given query parameter
+ QueryTokenizer::const_iterator pIt1;
+
+ OUString sModule;
+ sal_Int32 nIFlags = -1;
+ sal_Int32 nEFlags = -1;
+
+ pIt1 = lTokens.find(QUERY_PARAM_MODULE);
+ if (pIt1 != lTokens.end())
+ sModule = pIt1->second;
+ pIt1 = lTokens.find(QUERY_PARAM_IFLAGS);
+ if (pIt1 != lTokens.end())
+ nIFlags = pIt1->second.toInt32();
+ pIt1 = lTokens.find(QUERY_PARAM_EFLAGS);
+ if (pIt1 != lTokens.end())
+ nEFlags = pIt1->second.toInt32();
+
+ // simple search for filters of one specific module.
+ std::vector<OUString> lFilterList;
+ if (!sModule.isEmpty())
+ lFilterList = impl_getSortedFilterListForModule(sModule, nIFlags, nEFlags);
+ else
+ {
+ // more complex search for all filters
+ // We check first, which office modules are installed...
+ const css::uno::Sequence<OUString> lModules = impl_getListOfInstalledModules();
+ for (auto const& module : lModules)
+ {
+ std::vector<OUString> lFilters4Module = impl_getSortedFilterListForModule(module, nIFlags, nEFlags);
+ for (auto const& filter4Module : lFilters4Module)
+ {
+ lFilterList.push_back(filter4Module);
+ }
+ }
+ }
+
+ return lFilterList;
+}
+
+
+css::uno::Sequence<OUString> FilterFactory::impl_getListOfInstalledModules()
+{
+ css::uno::Reference< css::container::XNameAccess > xModuleConfig = officecfg::Setup::Office::Factories::get();
+ return xModuleConfig->getElementNames();
+}
+
+
+std::vector<OUString> FilterFactory::impl_getSortedFilterListForModule(const OUString& sModule,
+ sal_Int32 nIFlags,
+ sal_Int32 nEFlags) const
+{
+ std::vector<OUString> lSortedFilters = impl_readSortedFilterListFromConfig(sModule);
+
+ // get all filters for the requested module
+ css::beans::NamedValue lIProps[] { { PROPNAME_DOCUMENTSERVICE, css::uno::Any(sModule) } };
+
+ // SAFE -> ----------------------
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ FilterCache* pCache = impl_getWorkingCache();
+ std::vector<OUString> lOtherFilters = pCache->getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
+ aLock.clear();
+ // <- SAFE ----------------------
+
+ // bring "other" filters in an alphabetical order
+ // It's needed below.
+ ::std::sort(lOtherFilters.begin(), lOtherFilters.end());
+
+ // merge both lists together
+ std::vector<OUString> lMergedFilters = lSortedFilters;
+ const auto itlSortedFiltersEnd = lSortedFilters.cend();
+ for (auto const& otherFilter : lOtherFilters)
+ {
+ if (::std::find(lSortedFilters.cbegin(), lSortedFilters.cend(), otherFilter) == itlSortedFiltersEnd)
+ lMergedFilters.push_back(otherFilter);
+ }
+
+ // remove all filters from this merged list, which does not fit the flag specification
+ if (nIFlags != -1)
+ {
+ auto pItToErase = ::std::remove_if(lMergedFilters.begin(), lMergedFilters.end(), stlcomp_removeIfMatchFlags(pCache, nIFlags, true));
+ lMergedFilters.erase(pItToErase, lMergedFilters.end());
+ }
+ if (nEFlags != -1)
+ {
+ auto pItToErase = ::std::remove_if(lMergedFilters.begin(), lMergedFilters.end(), stlcomp_removeIfMatchFlags(pCache, nEFlags, false));
+ lMergedFilters.erase(pItToErase, lMergedFilters.end());
+ }
+
+ // sort the default filter to the front of this list
+ // TODO
+
+ return lMergedFilters;
+}
+
+
+std::vector<OUString> FilterFactory::impl_readSortedFilterListFromConfig(const OUString& sModule)
+{
+ try
+ {
+ css::uno::Reference< css::container::XNameAccess > xUISortConfig = officecfg::TypeDetection::UISort::ModuleDependendFilterOrder::get();
+ // don't check the module name here. If it does not exists, an exception is thrown and caught below.
+ // We return an empty list as result then.
+ css::uno::Reference< css::container::XNameAccess > xModule;
+ xUISortConfig->getByName(sModule) >>= xModule;
+ if (xModule.is()) // only to be on the safe side of life if the exception was not thrown .-)
+ {
+ // Note: conversion of the returned Any to std::vector<OUString> throws
+ // an IllegalArgumentException if the type does not match ...
+ // but it resets the std::vector<OUString> to a length of 0 if the Any is empty!
+ std::vector<OUString> lSortedFilters(
+ comphelper::sequenceToContainer< std::vector<OUString> >(xModule->getByName(PROPNAME_SORTEDFILTERLIST).get<css::uno::Sequence<OUString> >()));
+ return lSortedFilters;
+ }
+ }
+ catch(const css::uno::RuntimeException&)
+ { throw; }
+ catch(const css::uno::Exception&)
+ {}
+
+ return std::vector<OUString>();
+}
+
+} // namespace filter
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_FilterFactory_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new filter::config::FilterFactory(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/filterfactory.hxx b/filter/source/config/cache/filterfactory.hxx
new file mode 100644
index 000000000..9be370f4d
--- /dev/null
+++ b/filter/source/config/cache/filterfactory.hxx
@@ -0,0 +1,135 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "basecontainer.hxx"
+#include "querytokenizer.hxx"
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <cppuhelper/implbase.hxx>
+
+
+namespace filter::config {
+
+
+/** @short implements the service <type scope="com.sun.star.document">FilterFactory</type>.
+ */
+class FilterFactory : public ::cppu::ImplInheritanceHelper< BaseContainer ,
+ css::lang::XMultiServiceFactory >
+{
+
+ // native interface
+
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+
+ public:
+
+
+ // ctor/dtor
+
+ /** @short standard ctor to connect this interface wrapper to
+ the global filter cache instance ...
+
+ @param rxContext
+ reference to the uno service manager, which created this service instance.
+ */
+ explicit FilterFactory(const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+
+
+ /** @short standard dtor.
+ */
+ virtual ~FilterFactory() override;
+
+
+ // uno interface
+
+ public:
+
+
+ // XMultiServiceFactory
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const OUString& sFilter) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const OUString& sFilter ,
+ const css::uno::Sequence< css::uno::Any >& lArguments) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
+
+
+ // XContainerQuery
+
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByQuery(const OUString& sQuery) override;
+
+
+ // internal helper!
+
+ private:
+
+
+ /** @short implement the container string query: "matchByDocumentService=:iflags=:eflags=:..."
+
+ @param lTokens
+ the list of query tokens and its values.
+
+ @return A string list of internal filter names, including
+ all filters, which match this query.
+ */
+ std::vector<OUString> impl_queryMatchByDocumentService(const QueryTokenizer& lTokens) const;
+
+
+ /** TODO document me
+ */
+ static css::uno::Sequence<OUString> impl_getListOfInstalledModules();
+
+
+ /** @short implement the container string query:
+ "getSortedFilterList()[:module=<xxx>]:[iflags=<xxx>][:eflags=<xxx>]"
+
+ @param lTokens
+ the list of query tokens and its values.
+
+ @return A string list of internal filter names, including
+ all filters, which match this query.
+ */
+ std::vector<OUString> impl_getSortedFilterList(const QueryTokenizer& lTokens) const;
+
+
+ /** TODO document me
+ */
+ std::vector<OUString> impl_getSortedFilterListForModule(const OUString& sModule,
+ sal_Int32 nIFlags,
+ sal_Int32 nEFlags) const;
+
+
+ /** @short read a specialized and sorted list of filter names from
+ the configuration (matching the specified module)
+
+ @param sModule
+ the module for which the sorted list should be retrieved for.
+
+ @return A string list of internal filter names.
+ Can be empty.
+ */
+ static std::vector<OUString> impl_readSortedFilterListFromConfig(const OUString& sModule);
+
+};
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/frameloaderfactory.cxx b/filter/source/config/cache/frameloaderfactory.cxx
new file mode 100644
index 000000000..ebe482366
--- /dev/null
+++ b/filter/source/config/cache/frameloaderfactory.cxx
@@ -0,0 +1,102 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "frameloaderfactory.hxx"
+
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <comphelper/sequence.hxx>
+
+
+namespace filter::config{
+
+FrameLoaderFactory::FrameLoaderFactory(const css::uno::Reference< css::uno::XComponentContext >& rxContext)
+ : m_xContext(rxContext)
+{
+ BaseContainer::init("com.sun.star.comp.filter.config.FrameLoaderFactory" ,
+ { "com.sun.star.frame.FrameLoaderFactory" },
+ FilterCache::E_FRAMELOADER );
+}
+
+
+FrameLoaderFactory::~FrameLoaderFactory()
+{
+}
+
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL FrameLoaderFactory::createInstance(const OUString& sLoader)
+{
+ return createInstanceWithArguments(sLoader, css::uno::Sequence< css::uno::Any >());
+}
+
+
+css::uno::Reference< css::uno::XInterface > SAL_CALL FrameLoaderFactory::createInstanceWithArguments(const OUString& sLoader ,
+ const css::uno::Sequence< css::uno::Any >& lArguments)
+{
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ auto & cache = GetTheFilterCache();
+
+ // search loader on cache
+ CacheItem aLoader = cache.getItem(m_eType, sLoader);
+
+ // create service instance
+ css::uno::Reference< css::uno::XInterface > xLoader = m_xContext->getServiceManager()->createInstanceWithContext(sLoader, m_xContext);
+
+ // initialize filter
+ css::uno::Reference< css::lang::XInitialization > xInit(xLoader, css::uno::UNO_QUERY);
+ if (xInit.is())
+ {
+ // format: lInitData[0] = seq<PropertyValue>, which contains all configuration properties of this loader
+ // lInitData[1] = lArguments[0]
+ // ...
+ // lInitData[n] = lArguments[n-1]
+ css::uno::Sequence< css::beans::PropertyValue > lConfig;
+ aLoader >> lConfig;
+
+ ::std::vector< css::uno::Any > stlArguments(comphelper::sequenceToContainer< ::std::vector<css::uno::Any> >(lArguments));
+ stlArguments.insert(stlArguments.begin(), css::uno::Any(lConfig));
+
+ xInit->initialize(comphelper::containerToSequence(stlArguments));
+ }
+
+ return xLoader;
+ // <- SAFE
+}
+
+
+css::uno::Sequence< OUString > SAL_CALL FrameLoaderFactory::getAvailableServiceNames()
+{
+ // must be the same list as ((XNameAccess*)this)->getElementNames() return!
+ return BaseContainer::getElementNames();
+}
+
+} // namespace filter::config
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_FrameLoaderFactory_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new filter::config::FrameLoaderFactory(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/frameloaderfactory.hxx b/filter/source/config/cache/frameloaderfactory.hxx
new file mode 100644
index 000000000..2b9098b1a
--- /dev/null
+++ b/filter/source/config/cache/frameloaderfactory.hxx
@@ -0,0 +1,98 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "basecontainer.hxx"
+#include <com/sun/star/frame/XLoaderFactory.hpp>
+#include <cppuhelper/implbase.hxx>
+
+
+namespace filter::config {
+
+
+/** @short implements the service <type scope="com.sun.star.document">FrameLoaderFactory</type>.
+ */
+class FrameLoaderFactory : public ::cppu::ImplInheritanceHelper< BaseContainer ,
+ css::frame::XLoaderFactory >
+{
+
+ // native interface
+
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+
+ public:
+
+
+ // ctor/dtor
+
+ /** @short standard ctor to connect this interface wrapper to
+ the global filter cache instance ...
+
+ @param rxContext
+ reference to the uno service manager, which created this service instance.
+ */
+ explicit FrameLoaderFactory(const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+
+
+ /** @short standard dtor.
+ */
+ virtual ~FrameLoaderFactory() override;
+
+
+ // uno interface
+
+ public:
+
+
+ // XMultiServiceFactory
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance(const OUString& sLoader) override;
+
+ virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments(const OUString& sLoader ,
+ const css::uno::Sequence< css::uno::Any >& lArguments) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames() override;
+
+
+ public:
+
+ // Overrides to resolve ambiguity
+ virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) override
+ { return BaseContainer::getByName(aName); }
+ virtual css::uno::Sequence< OUString > SAL_CALL getElementNames() override
+ { return BaseContainer::getElementNames(); }
+ virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) override
+ { return BaseContainer::hasByName(aName); }
+
+ virtual css::uno::Type SAL_CALL getElementType() override
+ { return BaseContainer::getElementType(); }
+ virtual sal_Bool SAL_CALL hasElements() override
+ { return BaseContainer::hasElements(); }
+
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByQuery( const OUString& Query ) override
+ { return BaseContainer::createSubSetEnumerationByQuery(Query); }
+ virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createSubSetEnumerationByProperties( const css::uno::Sequence< css::beans::NamedValue >& Properties ) override
+ { return BaseContainer::createSubSetEnumerationByProperties(Properties); }
+
+};
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/querytokenizer.cxx b/filter/source/config/cache/querytokenizer.cxx
new file mode 100644
index 000000000..f5b021f53
--- /dev/null
+++ b/filter/source/config/cache/querytokenizer.cxx
@@ -0,0 +1,69 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "querytokenizer.hxx"
+
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+
+
+namespace filter::config{
+
+
+QueryTokenizer::QueryTokenizer(std::u16string_view sQuery)
+ : m_bValid(true)
+{
+ sal_Int32 token = 0;
+ while(token != -1)
+ {
+ std::u16string_view sToken = o3tl::getToken(sQuery,0, ':', token);
+ if (!sToken.empty())
+ {
+ sal_Int32 nIdx{ 0 };
+ const OUString sKey{ o3tl::getToken(sToken, 0, '=', nIdx) };
+ const OUString sVal{ o3tl::getToken(sToken, 0, ':', nIdx) };
+
+ if (sKey.isEmpty())
+ m_bValid = false;
+ OSL_ENSURE(m_bValid, "QueryTokenizer::QueryTokenizer() Found non boolean query parameter ... but its key is empty. Will be ignored!");
+
+ if (find(sKey) != end())
+ m_bValid = false;
+ OSL_ENSURE(m_bValid, "QueryTokenizer::QueryTokenizer() Query contains same param more than once. Last one wins :-)");
+
+ (*this)[sKey] = sVal;
+ }
+ }
+}
+
+
+QueryTokenizer::~QueryTokenizer()
+{
+ /*TODO*/
+}
+
+
+bool QueryTokenizer::valid() const
+{
+ return m_bValid;
+}
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/querytokenizer.hxx b/filter/source/config/cache/querytokenizer.hxx
new file mode 100644
index 000000000..0c7e79b3d
--- /dev/null
+++ b/filter/source/config/cache/querytokenizer.hxx
@@ -0,0 +1,92 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <rtl/ustring.hxx>
+#include <unordered_map>
+
+
+namespace filter::config {
+
+
+/** @short It can be used to split any query string (which can be used at the
+ related interface <type scope="css::container">XContainerQuery</type>)
+ into its different tokens using a fix schema.
+
+ @descr All queries implemented of the services
+ <ul>
+ <li><type scope="css::document">TypeDetection</type></li>
+ <li><type scope="css::document">FilterFactory</type></li>
+ <li><type scope="css::document">ExtendedTypeDetectionFactory</type></li>
+ <li><type scope="css::frame">FrameLoaderFactory</type></li>
+ <li><type scope="css::frame">ContentHandlerFactory</type></li>
+ </ul>
+ uses this schema.
+
+ @attention This class is not threadsafe implemented. Because it's not necessary.
+ But you have to make sure that it's not used as such :-)
+ */
+class QueryTokenizer : public std::unordered_map< OUString, OUString >
+{
+
+ // member
+
+ private:
+
+ /** @short Because the given query can contain errors,
+ it should be checked outside.
+
+ TODO May it's a good idea to describe the real problem
+ more detailed ...
+ */
+ bool m_bValid;
+
+
+ // interface
+
+ public:
+
+ /** @short create a new tokenizer instance with a
+ a new query.
+
+ @descr The given query is immediately analyzed
+ and separated into its token, which can
+ be access by some specialized method later.
+
+ @param sQuery
+ the query string.
+ */
+ explicit QueryTokenizer(std::u16string_view sQuery);
+
+
+ /** @short destruct an instance of this class.
+ */
+ virtual ~QueryTokenizer();
+
+
+ /** @short can be used to check if analyzing of given query
+ was successful or not.
+ */
+ bool valid() const;
+};
+
+} // namespace filter::config
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/typedetection.cxx b/filter/source/config/cache/typedetection.cxx
new file mode 100644
index 000000000..ae8c194fa
--- /dev/null
+++ b/filter/source/config/cache/typedetection.cxx
@@ -0,0 +1,1204 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "typedetection.hxx"
+#include "constant.hxx"
+
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/util/URLTransformer.hpp>
+#include <com/sun/star/util/XURLTransformer.hpp>
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <o3tl/string_view.hxx>
+#include <tools/wldcrd.hxx>
+#include <sal/log.hxx>
+#include <framework/interaction.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <comphelper/fileurl.hxx>
+#include <comphelper/sequence.hxx>
+#include <utility>
+
+#define DEBUG_TYPE_DETECTION 0
+
+#if DEBUG_TYPE_DETECTION
+#include <iostream>
+using std::cout;
+using std::endl;
+#endif
+
+using namespace com::sun::star;
+
+namespace filter::config{
+
+TypeDetection::TypeDetection(const css::uno::Reference< css::uno::XComponentContext >& rxContext)
+ : m_xContext(rxContext)
+ , m_xTerminateListener(new TerminateDetection(this))
+ , m_bCancel(false)
+{
+ css::frame::Desktop::create(m_xContext)->addTerminateListener(m_xTerminateListener);
+ BaseContainer::init("com.sun.star.comp.filter.config.TypeDetection" ,
+ { "com.sun.star.document.TypeDetection" },
+ FilterCache::E_TYPE );
+}
+
+
+TypeDetection::~TypeDetection()
+{
+ css::frame::Desktop::create(m_xContext)->removeTerminateListener(m_xTerminateListener);
+}
+
+
+OUString SAL_CALL TypeDetection::queryTypeByURL(const OUString& sURL)
+{
+ OUString sType;
+
+ // SAFE ->
+ osl::MutexGuard aLock(m_aMutex);
+
+ css::util::URL aURL;
+ aURL.Complete = sURL;
+ css::uno::Reference< css::util::XURLTransformer > xParser( css::util::URLTransformer::create(m_xContext) );
+ xParser->parseStrict(aURL);
+
+ // set std types as minimum requirement first!
+ // Only in case no type was found for given URL,
+ // use optional types too ...
+ auto & cache = GetTheFilterCache();
+ FlatDetection lFlatTypes;
+ cache.detectFlatForURL(aURL, lFlatTypes);
+
+ if (
+ (lFlatTypes.empty() ) &&
+ (!cache.isFillState(FilterCache::E_CONTAINS_TYPES))
+ )
+ {
+ cache.load(FilterCache::E_CONTAINS_TYPES);
+ cache.detectFlatForURL(aURL, lFlatTypes);
+ }
+
+ // first item is guaranteed as "preferred" one!
+ if (!lFlatTypes.empty())
+ {
+ const FlatDetectionInfo& aMatch = *(lFlatTypes.begin());
+ sType = aMatch.sType;
+ }
+
+ return sType;
+ // <- SAFE
+}
+
+namespace {
+
+/**
+ * Rank format types in order of complexity. More complex formats are
+ * ranked higher so that they get tested sooner over simpler formats.
+ *
+ * Guidelines to determine how complex a format is (subject to change):
+ *
+ * 1) compressed text (XML, HTML, etc)
+ * 2) binary
+ * 3) non-compressed text
+ * 3.1) structured text
+ * 3.1.1) dialect of a structured text (e.g. docbook XML)
+ * 3.1.2) generic structured text (e.g. generic XML)
+ * 3.2) non-structured text
+ *
+ * In each category, rank them from strictly-structured to
+ * loosely-structured.
+ */
+int getFlatTypeRank(std::u16string_view rType)
+{
+ // List formats from more complex to less complex.
+ // TODO: Add more.
+ static const char* ranks[] = {
+
+ // Compressed XML (ODF XML zip formats)
+ "writer8_template",
+ "writer8",
+ "calc8_template",
+ "calc8",
+ "impress8_template",
+ "impress8",
+ "draw8_template",
+ "draw8",
+ "chart8",
+ "math8",
+ "writerglobal8_template",
+ "writerglobal8",
+ "writerweb8_writer_template",
+ "StarBase",
+
+ // Compressed XML (OOXML)
+ "writer_OOXML_Text_Template",
+ "writer_OOXML",
+ "writer_MS_Word_2007_Template",
+ "writer_MS_Word_2007",
+ "Office Open XML Spreadsheet Template",
+ "Office Open XML Spreadsheet",
+ "MS Excel 2007 XML Template",
+ "MS Excel 2007 XML",
+ "MS PowerPoint 2007 XML Template",
+ "MS PowerPoint 2007 XML AutoPlay",
+ "MS PowerPoint 2007 XML",
+
+ // Compressed XML (Uniform/Unified Office Format)
+ "Unified_Office_Format_text",
+ "Unified_Office_Format_spreadsheet",
+ "Unified_Office_Format_presentation",
+
+ // Compressed XML (StarOffice XML zip formats)
+ "calc_StarOffice_XML_Calc",
+ "calc_StarOffice_XML_Calc_Template",
+ "chart_StarOffice_XML_Chart",
+ "draw_StarOffice_XML_Draw",
+ "draw_StarOffice_XML_Draw_Template",
+ "impress_StarOffice_XML_Impress",
+ "impress_StarOffice_XML_Impress_Template",
+ "math_StarOffice_XML_Math",
+ "writer_StarOffice_XML_Writer",
+ "writer_StarOffice_XML_Writer_Template",
+ "writer_globaldocument_StarOffice_XML_Writer_GlobalDocument",
+ "writer_web_StarOffice_XML_Writer_Web_Template",
+
+ // Compressed text
+ "pdf_Portable_Document_Format",
+
+ // Binary
+ "writer_T602_Document",
+ "writer_WordPerfect_Document",
+ "writer_MS_Works_Document",
+ "writer_MS_Word_97_Vorlage",
+ "writer_MS_Word_97",
+ "writer_MS_Word_95_Vorlage",
+ "writer_MS_Word_95",
+ "writer_MS_WinWord_60",
+ "writer_MS_WinWord_5",
+ "MS Excel 2007 Binary",
+ "calc_MS_Excel_97_VorlageTemplate",
+ "calc_MS_Excel_97",
+ "calc_MS_Excel_95_VorlageTemplate",
+ "calc_MS_Excel_95",
+ "calc_MS_Excel_5095_VorlageTemplate",
+ "calc_MS_Excel_5095",
+ "calc_MS_Excel_40_VorlageTemplate",
+ "calc_MS_Excel_40",
+ "calc_Pocket_Excel_File",
+ "impress_MS_PowerPoint_97_Vorlage",
+ "impress_MS_PowerPoint_97_AutoPlay",
+ "impress_MS_PowerPoint_97",
+ "calc_Lotus",
+ "calc_QPro",
+ "calc_SYLK",
+ "calc_DIF",
+ "calc_dBase",
+
+ // Binary (raster and vector image files)
+ "emf_MS_Windows_Metafile",
+ "wmf_MS_Windows_Metafile",
+ "met_OS2_Metafile",
+ "svm_StarView_Metafile",
+ "sgv_StarDraw_20",
+ "tif_Tag_Image_File",
+ "tga_Truevision_TARGA",
+ "sgf_StarOffice_Writer_SGF",
+ "ras_Sun_Rasterfile",
+ "psd_Adobe_Photoshop",
+ "png_Portable_Network_Graphic",
+ "jpg_JPEG",
+ "mov_MOV",
+ "gif_Graphics_Interchange",
+ "bmp_MS_Windows",
+ "pcx_Zsoft_Paintbrush",
+ "pct_Mac_Pict",
+ "pcd_Photo_CD_Base",
+ "pcd_Photo_CD_Base4",
+ "pcd_Photo_CD_Base16",
+ "webp_WebP",
+ "impress_CGM_Computer_Graphics_Metafile", // There is binary and ascii variants ?
+ "draw_WordPerfect_Graphics",
+ "draw_Visio_Document",
+ "draw_Publisher_Document",
+ "draw_Corel_Presentation_Exchange",
+ "draw_CorelDraw_Document",
+ "writer_LotusWordPro_Document",
+ "writer_MIZI_Hwp_97", // Hanword (Hancom Office)
+
+ // Non-compressed XML
+ "writer_ODT_FlatXML",
+ "calc_ODS_FlatXML",
+ "impress_ODP_FlatXML",
+ "draw_ODG_FlatXML",
+ "calc_ADO_rowset_XML",
+ "calc_MS_Excel_2003_XML",
+ "writer_MS_Word_2003_XML",
+ "writer_DocBook_File",
+ "XHTML_File",
+ "svg_Scalable_Vector_Graphics",
+ "math_MathML_XML_Math",
+
+ // Non-compressed text
+ "dxf_AutoCAD_Interchange",
+ "eps_Encapsulated_PostScript",
+ "pbm_Portable_Bitmap", // There is 'raw' and 'ascii' variants.
+ "ppm_Portable_Pixelmap", // There is 'raw' and 'ascii' variants.
+ "pgm_Portable_Graymap", // There is 'raw' and 'ascii' variants.
+ "xpm_XPM",
+ "xbm_X_Consortium",
+ "writer_Rich_Text_Format",
+ "writer_web_HTML_help",
+ "generic_HTML",
+
+ "generic_Text", // Plain text (catch all)
+
+ // Anything ranked lower than generic_Text will never be used during
+ // type detection (since generic_Text catches all).
+
+ // Export only
+ "writer_layout_dump_xml",
+ "writer_indexing_export",
+ "graphic_HTML",
+
+ // Internal use only
+ "StarBaseReportChart",
+ "StarBaseReport",
+ "math_MathType_3x", // MathType equation embedded in Word doc.
+ };
+
+ size_t n = SAL_N_ELEMENTS(ranks);
+
+ for (size_t i = 0; i < n; ++i)
+ {
+ if (o3tl::equalsAscii(rType, ranks[i]))
+ return n - i - 1;
+ }
+
+ // Not ranked. Treat them equally. Unranked formats have higher priority
+ // than the ranked internal ones since they may be defined externally.
+ return n;
+}
+
+/**
+ * Types with matching pattern first, then extension, then custom ranks by
+ * types, then types that are supported by the document service come next.
+ * Lastly, sort them alphabetically.
+ */
+struct SortByPriority
+{
+ bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
+ {
+ if (r1.bMatchByPattern != r2.bMatchByPattern)
+ return r1.bMatchByPattern;
+
+ if (r1.bMatchByExtension != r2.bMatchByExtension)
+ return r1.bMatchByExtension;
+
+ int rank1 = getFlatTypeRank(r1.sType);
+ int rank2 = getFlatTypeRank(r2.sType);
+
+ if (rank1 != rank2)
+ return rank1 > rank2;
+
+ if (r1.bPreselectedByDocumentService != r2.bPreselectedByDocumentService)
+ return r1.bPreselectedByDocumentService;
+
+ // All things being equal, sort them alphabetically.
+ return r1.sType > r2.sType;
+ }
+};
+
+struct SortByType
+{
+ bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
+ {
+ return r1.sType > r2.sType;
+ }
+};
+
+struct EqualByType
+{
+ bool operator() (const FlatDetectionInfo& r1, const FlatDetectionInfo& r2) const
+ {
+ return r1.sType == r2.sType;
+ }
+};
+
+class FindByType
+{
+ OUString maType;
+public:
+ explicit FindByType(OUString aType) : maType(std::move(aType)) {}
+ bool operator() (const FlatDetectionInfo& rInfo) const
+ {
+ return rInfo.sType == maType;
+ }
+};
+
+#if DEBUG_TYPE_DETECTION
+void printFlatDetectionList(const char* caption, const FlatDetection& types)
+{
+ cout << "-- " << caption << " (size=" << types.size() << ")" << endl;
+ for (auto const& item : types)
+ {
+ cout << " type='" << item.sType << "'; match by extension (" << item.bMatchByExtension
+ << "); match by pattern (" << item.bMatchByPattern << "); pre-selected by doc service ("
+ << item.bPreselectedByDocumentService << ")" << endl;
+ }
+ cout << "--" << endl;
+}
+#endif
+
+}
+
+OUString SAL_CALL TypeDetection::queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor,
+ sal_Bool bAllowDeep )
+{
+ // make the descriptor more usable :-)
+ utl::MediaDescriptor stlDescriptor(lDescriptor);
+ OUString sType, sURL;
+
+ try
+ {
+ // SAFE -> ----------------------------------
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ // parse given URL to split it into e.g. main and jump marks ...
+ sURL = stlDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_URL, OUString());
+
+#if OSL_DEBUG_LEVEL > 0
+ if (stlDescriptor.find( "FileName" ) != stlDescriptor.end())
+ OSL_FAIL("Detect using of deprecated and already unsupported MediaDescriptor property \"FileName\"!");
+#endif
+
+ css::util::URL aURL;
+ aURL.Complete = sURL;
+ css::uno::Reference< css::util::XURLTransformer > xParser(css::util::URLTransformer::create(m_xContext));
+ xParser->parseStrict(aURL);
+
+ OUString aSelectedFilter = stlDescriptor.getUnpackedValueOrDefault(
+ utl::MediaDescriptor::PROP_FILTERNAME, OUString());
+ if (!aSelectedFilter.isEmpty())
+ {
+ // Caller specified the filter type. Honor it. Just get the default
+ // type for that filter, and bail out.
+ if (impl_validateAndSetFilterOnDescriptor(stlDescriptor, aSelectedFilter))
+ return stlDescriptor[utl::MediaDescriptor::PROP_TYPENAME].get<OUString>();
+ }
+
+ FlatDetection lFlatTypes;
+ impl_getAllFormatTypes(aURL, stlDescriptor, lFlatTypes);
+
+ aLock.clear();
+ // <- SAFE ----------------------------------
+
+ // Properly prioritize all candidate types.
+ std::stable_sort(lFlatTypes.begin(), lFlatTypes.end(), SortByPriority());
+ auto last = std::unique(lFlatTypes.begin(), lFlatTypes.end(), EqualByType());
+ lFlatTypes.erase(last, lFlatTypes.end());
+
+ OUString sLastChance;
+
+ // verify every flat detected (or preselected!) type
+ // by calling its registered deep detection service.
+ // But break this loop if a type match to the given descriptor
+ // by a URL pattern(!) or if deep detection isn't allowed from
+ // outside (bAllowDeep=sal_False) or break the whole detection by
+ // throwing an exception if creation of the might needed input
+ // stream failed by e.g. an IO exception ...
+ if (!lFlatTypes.empty())
+ sType = impl_detectTypeFlatAndDeep(stlDescriptor, lFlatTypes, bAllowDeep, sLastChance);
+
+ // flat detection failed
+ // pure deep detection failed
+ // => ask might existing InteractionHandler
+ // means: ask user for its decision
+ if (sType.isEmpty() && !m_bCancel)
+ sType = impl_askUserForTypeAndFilterIfAllowed(stlDescriptor);
+
+
+ // no real detected type - but a might valid one.
+ // update descriptor and set last chance for return.
+ if (sType.isEmpty() && !sLastChance.isEmpty() && !m_bCancel)
+ {
+ OSL_FAIL("set first flat detected type without a registered deep detection service as \"last chance\" ... nevertheless some other deep detections said \"NO\". I TRY IT!");
+ sType = sLastChance;
+ }
+ }
+ catch(const css::uno::RuntimeException&)
+ {
+ throw;
+ }
+ catch(const css::uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.config", "caught exception while querying type of " << sURL);
+ sType.clear();
+ }
+
+ // adapt media descriptor, so it contains the right values
+ // for type/filter name/document service/ etcpp.
+ impl_checkResultsAndAddBestFilter(stlDescriptor, sType); // Attention: sType is used as IN/OUT param here and will might be changed inside this method !!!
+ impl_validateAndSetTypeOnDescriptor(stlDescriptor, sType);
+
+ stlDescriptor >> lDescriptor;
+ return sType;
+}
+
+
+void TypeDetection::impl_checkResultsAndAddBestFilter(utl::MediaDescriptor& rDescriptor,
+ OUString& sType )
+{
+ // a)
+ // Don't overwrite a might preselected filter!
+ OUString sFilter = rDescriptor.getUnpackedValueOrDefault(
+ utl::MediaDescriptor::PROP_FILTERNAME,
+ OUString());
+ if (!sFilter.isEmpty())
+ return;
+
+ auto & cache = GetTheFilterCache();
+
+ // b)
+ // check a preselected document service too.
+ // Then we have to search a suitable filter within this module.
+ OUString sDocumentService = rDescriptor.getUnpackedValueOrDefault(
+ utl::MediaDescriptor::PROP_DOCUMENTSERVICE,
+ OUString());
+ if (!sDocumentService.isEmpty())
+ {
+ try
+ {
+ OUString sRealType = sType;
+
+ // SAFE ->
+ ::osl::ResettableMutexGuard aLock(m_aMutex);
+
+ // Attention: For executing next lines of code, We must be sure that
+ // all filters already loaded :-(
+ // That can disturb our "load on demand feature". But we have no other chance!
+ cache.load(FilterCache::E_CONTAINS_FILTERS);
+
+ css::beans::NamedValue lIProps[] {
+ { PROPNAME_DOCUMENTSERVICE, uno::Any(sDocumentService) },
+ { PROPNAME_TYPE, uno::Any(sRealType) } };
+ std::vector<OUString> lFilters = cache.getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
+
+ aLock.clear();
+ // <- SAFE
+
+ for (auto const& filter : lFilters)
+ {
+ // SAFE ->
+ aLock.reset();
+ try
+ {
+ CacheItem aFilter = cache.getItem(FilterCache::E_FILTER, filter);
+ sal_Int32 nFlags = 0;
+ aFilter[PROPNAME_FLAGS] >>= nFlags;
+
+ if (static_cast<SfxFilterFlags>(nFlags) & SfxFilterFlags::IMPORT)
+ sFilter = filter;
+ if (static_cast<SfxFilterFlags>(nFlags) & SfxFilterFlags::PREFERED)
+ break;
+ }
+ catch(const css::uno::Exception&) {}
+ aLock.clear();
+ // <- SAFE
+ }
+
+ if (!sFilter.isEmpty())
+ {
+ rDescriptor[utl::MediaDescriptor::PROP_TYPENAME ] <<= sRealType;
+ rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
+ sType = sRealType;
+ return;
+ }
+ }
+ catch(const css::uno::Exception&)
+ {}
+ }
+
+ // c)
+ // We can use the preferred filter for the specified type.
+ // Such preferred filter points:
+ // - to the default filter of the preferred application
+ // - or to any other filter if no preferred filter was set.
+ // Note: It's an optimization only!
+ // It's not guaranteed, that such preferred filter exists.
+ sFilter.clear();
+ try
+ {
+ // SAFE ->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ CacheItem aType = cache.getItem(FilterCache::E_TYPE, sType);
+ aType[PROPNAME_PREFERREDFILTER] >>= sFilter;
+ cache.getItem(FilterCache::E_FILTER, sFilter);
+
+ aLock.clear();
+ // <- SAFE
+
+ // no exception => found valid type and filter => set it on the given descriptor
+ rDescriptor[utl::MediaDescriptor::PROP_TYPENAME ] <<= sType ;
+ rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
+ return;
+ }
+ catch(const css::uno::Exception&)
+ {}
+
+ // d)
+ // Search for any import(!) filter, which is registered for this type.
+ sFilter.clear();
+ try
+ {
+ // SAFE ->
+ ::osl::ResettableMutexGuard aLock(m_aMutex);
+
+ // Attention: For executing next lines of code, We must be sure that
+ // all filters already loaded :-(
+ // That can disturb our "load on demand feature". But we have no other chance!
+ cache.load(FilterCache::E_CONTAINS_FILTERS);
+
+ css::beans::NamedValue lIProps[] {
+ { PROPNAME_TYPE, uno::Any(sType) } };
+ std::vector<OUString> lFilters = cache.getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
+
+ aLock.clear();
+ // <- SAFE
+
+ for (auto const& filter : lFilters)
+ {
+ sFilter = filter;
+
+ // SAFE ->
+ aLock.reset();
+ try
+ {
+ CacheItem aFilter = cache.getItem(FilterCache::E_FILTER, sFilter);
+ sal_Int32 nFlags = 0;
+ aFilter[PROPNAME_FLAGS] >>= nFlags;
+
+ if (static_cast<SfxFilterFlags>(nFlags) & SfxFilterFlags::IMPORT)
+ break;
+ }
+ catch(const css::uno::Exception&)
+ { continue; }
+ aLock.clear();
+ // <- SAFE
+
+ sFilter.clear();
+ }
+
+ if (!sFilter.isEmpty())
+ {
+ rDescriptor[utl::MediaDescriptor::PROP_TYPENAME ] <<= sType ;
+ rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
+ return;
+ }
+ }
+ catch(const css::uno::Exception&)
+ {}
+}
+
+
+bool TypeDetection::impl_getPreselectionForType(
+ const OUString& sPreSelType, const util::URL& aParsedURL, FlatDetection& rFlatTypes, bool bDocService)
+{
+ // Can be used to suppress execution of some parts of this method
+ // if it's already clear that detected type is valid or not.
+ // It's necessary to use shared code at the end, which update
+ // all return parameters consistency!
+ bool bBreakDetection = false;
+
+ // Further we must know if it matches by pattern
+ // Every flat detected type by pattern won't be detected deep!
+ bool bMatchByPattern = false;
+
+ // And we must know if a preselection must be preferred, because
+ // it matches by its extension too.
+ bool bMatchByExtension = false;
+
+ // validate type
+ OUString sType(sPreSelType);
+ CacheItem aType;
+ try
+ {
+ // SAFE -> --------------------------
+ osl::MutexGuard aLock(m_aMutex);
+ aType = GetTheFilterCache().getItem(FilterCache::E_TYPE, sType);
+ // <- SAFE --------------------------
+ }
+ catch(const css::container::NoSuchElementException&)
+ {
+ sType.clear();
+ bBreakDetection = true;
+ }
+
+ if (!bBreakDetection)
+ {
+ // We can't check a preselected type for a given stream!
+ // So we must believe, that it can work ...
+ if ( aParsedURL.Complete == "private:stream" )
+ bBreakDetection = true;
+ }
+
+ if (!bBreakDetection)
+ {
+ // extract extension from URL .. to check it case-insensitive !
+ INetURLObject aParser (aParsedURL.Main);
+ OUString sExtension = aParser.getExtension(INetURLObject::LAST_SEGMENT ,
+ true ,
+ INetURLObject::DecodeMechanism::WithCharset);
+ sExtension = sExtension.toAsciiLowerCase();
+
+ // otherwise we must know, if it matches to the given URL really.
+ // especially if it matches by its extension or pattern registration.
+ const css::uno::Sequence<OUString> lExtensions = aType[PROPNAME_EXTENSIONS].get<css::uno::Sequence<OUString> >();
+ const css::uno::Sequence<OUString> lURLPattern = aType[PROPNAME_URLPATTERN].get<css::uno::Sequence<OUString> >();
+
+ for (auto const& extension : lExtensions)
+ {
+ OUString sCheckExtension(extension.toAsciiLowerCase());
+ if (sCheckExtension == sExtension)
+ {
+ bBreakDetection = true;
+ bMatchByExtension = true;
+ break;
+ }
+ }
+
+ if (!bBreakDetection)
+ {
+ for (auto const& elem : lURLPattern)
+ {
+ WildCard aCheck(elem);
+ if (aCheck.Matches(aParsedURL.Main))
+ {
+ bMatchByPattern = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // if it's a valid type - set it on all return values!
+ if (!sType.isEmpty())
+ {
+ FlatDetection::iterator it = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(sType));
+ if (it != rFlatTypes.end())
+ {
+ if (bMatchByExtension)
+ it->bMatchByExtension = true;
+ if (bMatchByPattern)
+ it->bMatchByPattern = true;
+ if (bDocService)
+ it->bPreselectedByDocumentService = true;
+ }
+
+ return true;
+ }
+
+ // not valid!
+ return false;
+}
+
+void TypeDetection::impl_getPreselectionForDocumentService(
+ const OUString& sPreSelDocumentService, const util::URL& aParsedURL, FlatDetection& rFlatTypes)
+{
+ // get all filters, which match to this doc service
+ std::vector<OUString> lFilters;
+ try
+ {
+ // SAFE -> --------------------------
+ osl::MutexGuard aLock(m_aMutex);
+
+ // Attention: For executing next lines of code, We must be sure that
+ // all filters already loaded :-(
+ // That can disturb our "load on demand feature". But we have no other chance!
+ auto & cache = GetTheFilterCache();
+ cache.load(FilterCache::E_CONTAINS_FILTERS);
+
+ css::beans::NamedValue lIProps[] {
+ { PROPNAME_DOCUMENTSERVICE, css::uno::Any(sPreSelDocumentService) } };
+ lFilters = cache.getMatchingItemsByProps(FilterCache::E_FILTER, lIProps);
+ // <- SAFE --------------------------
+ }
+ catch (const css::container::NoSuchElementException&)
+ {
+ lFilters.clear();
+ }
+
+ // step over all filters, and check if its registered type
+ // match the given URL.
+ // But use temp. list of "preselected types" instead of incoming rFlatTypes list!
+ // The reason behind: we must filter the obtained results. And copying stl entries
+ // is an easier job than removing them .-)
+ for (auto const& filter : lFilters)
+ {
+ OUString aType = impl_getTypeFromFilter(filter);
+ if (aType.isEmpty())
+ continue;
+
+ impl_getPreselectionForType(aType, aParsedURL, rFlatTypes, true);
+ }
+}
+
+OUString TypeDetection::impl_getTypeFromFilter(const OUString& rFilterName)
+{
+ CacheItem aFilter;
+ try
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ aFilter = GetTheFilterCache().getItem(FilterCache::E_FILTER, rFilterName);
+ }
+ catch (const container::NoSuchElementException&)
+ {
+ return OUString();
+ }
+
+ OUString aType;
+ aFilter[PROPNAME_TYPE] >>= aType;
+ return aType;
+}
+
+void TypeDetection::impl_getAllFormatTypes(
+ const util::URL& aParsedURL, utl::MediaDescriptor const & rDescriptor, FlatDetection& rFlatTypes)
+{
+ rFlatTypes.clear();
+
+ // Get all filters that we have.
+ std::vector<OUString> aFilterNames;
+ try
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ auto & cache = GetTheFilterCache();
+ cache.load(FilterCache::E_CONTAINS_FILTERS);
+ aFilterNames = cache.getItemNames(FilterCache::E_FILTER);
+ }
+ catch (const container::NoSuchElementException&)
+ {
+ return;
+ }
+
+ // Retrieve the default type for each of these filters, and store them.
+ for (auto const& filterName : aFilterNames)
+ {
+ OUString aType = impl_getTypeFromFilter(filterName);
+
+ if (aType.isEmpty())
+ continue;
+
+ FlatDetectionInfo aInfo; // all flags set to false by default.
+ aInfo.sType = aType;
+ rFlatTypes.push_back(aInfo);
+ }
+
+ {
+ // Get all types that match the URL alone.
+ FlatDetection aFlatByURL;
+ GetTheFilterCache().detectFlatForURL(aParsedURL, aFlatByURL);
+ for (auto const& elem : aFlatByURL)
+ {
+ FlatDetection::iterator itPos = std::find_if(rFlatTypes.begin(), rFlatTypes.end(), FindByType(elem.sType));
+ if (itPos == rFlatTypes.end())
+ // Not in the list yet.
+ rFlatTypes.push_back(elem);
+ else
+ {
+ // Already in the list. Update the flags.
+ FlatDetectionInfo& rInfo = *itPos;
+ const FlatDetectionInfo& rThisInfo = elem;
+ if (rThisInfo.bMatchByExtension)
+ rInfo.bMatchByExtension = true;
+ if (rThisInfo.bMatchByPattern)
+ rInfo.bMatchByPattern = true;
+ if (rThisInfo.bPreselectedByDocumentService)
+ rInfo.bPreselectedByDocumentService = true;
+ }
+ }
+ }
+
+ // Remove duplicates.
+ std::stable_sort(rFlatTypes.begin(), rFlatTypes.end(), SortByType());
+ auto last = std::unique(rFlatTypes.begin(), rFlatTypes.end(), EqualByType());
+ rFlatTypes.erase(last, rFlatTypes.end());
+
+ // Mark pre-selected type (if any) to have it prioritized.
+ OUString sSelectedType = rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_TYPENAME, OUString());
+ if (!sSelectedType.isEmpty())
+ impl_getPreselectionForType(sSelectedType, aParsedURL, rFlatTypes, false);
+
+ // Mark all types preferred by the current document service, to have it prioritized.
+ OUString sSelectedDoc = rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_DOCUMENTSERVICE, OUString());
+ if (!sSelectedDoc.isEmpty())
+ impl_getPreselectionForDocumentService(sSelectedDoc, aParsedURL, rFlatTypes);
+}
+
+
+OUString TypeDetection::impl_detectTypeFlatAndDeep( utl::MediaDescriptor& rDescriptor ,
+ const FlatDetection& lFlatTypes ,
+ bool bAllowDeep ,
+ OUString& rLastChance )
+{
+ // reset it everytimes, so the outside code can distinguish between
+ // a set and a not set value.
+ rLastChance.clear();
+
+ // step over all possible types for this URL.
+ // solutions:
+ // a) no types => no detection
+ // b) deep detection not allowed => return first valid type of list (because it's the preferred or the first valid one)
+ // or(!) match by URLPattern => in such case a deep detection will be suppressed!
+ // c) type has no detect service => safe the first occurred type without a detect service
+ // as "last chance"(!). It will be used outside of this method
+ // if no further type could be detected.
+ // It must be the first one, because it can be a preferred type.
+ // Our types list was sorted by such criteria!
+ // d) detect service return a valid result => return its decision
+ // e) detect service return an invalid result
+ // or any needed information could not be
+ // obtained from the cache => ignore it, and continue with search
+
+ for (auto const& flatTypeInfo : lFlatTypes)
+ {
+ if (m_bCancel)
+ break;
+ OUString sFlatType = flatTypeInfo.sType;
+
+ if (!impl_validateAndSetTypeOnDescriptor(rDescriptor, sFlatType))
+ continue;
+
+ // b)
+ if (
+ (!bAllowDeep ) ||
+ (flatTypeInfo.bMatchByPattern)
+ )
+ {
+ return sFlatType;
+ }
+
+ try
+ {
+ // SAFE -> ----------------------------------
+ osl::ClearableMutexGuard aLock(m_aMutex);
+ CacheItem aType = GetTheFilterCache().getItem(FilterCache::E_TYPE, sFlatType);
+ aLock.clear();
+
+ OUString sDetectService;
+ aType[PROPNAME_DETECTSERVICE] >>= sDetectService;
+
+ // c)
+ if (sDetectService.isEmpty())
+ {
+ // flat detected types without any registered deep detection service and not
+ // preselected by the user can be used as LAST CHANCE in case no other type could
+ // be detected. Of course only the first type without deep detector can be used.
+ // Further ones has to be ignored.
+ if (rLastChance.isEmpty())
+ rLastChance = sFlatType;
+
+ continue;
+ }
+
+ OUString sDeepType = impl_askDetectService(sDetectService, rDescriptor);
+
+ // d)
+ if (!sDeepType.isEmpty())
+ return sDeepType;
+ }
+ catch(const css::container::NoSuchElementException&)
+ {}
+ // e)
+ }
+
+ return OUString();
+ // <- SAFE ----------------------------------
+}
+
+void TypeDetection::impl_seekStreamToZero(utl::MediaDescriptor const & rDescriptor)
+{
+ // try to seek to 0 ...
+ // But because XSeekable is an optional interface ... try it only .-)
+ css::uno::Reference< css::io::XInputStream > xStream = rDescriptor.getUnpackedValueOrDefault(
+ utl::MediaDescriptor::PROP_INPUTSTREAM,
+ css::uno::Reference< css::io::XInputStream >());
+ css::uno::Reference< css::io::XSeekable > xSeek(xStream, css::uno::UNO_QUERY);
+ if (!xSeek.is())
+ return;
+
+ try
+ {
+ xSeek->seek(0);
+ }
+ catch(const css::uno::RuntimeException&)
+ {
+ throw;
+ }
+ catch(const css::uno::Exception&)
+ {
+ }
+}
+
+OUString TypeDetection::impl_askDetectService(const OUString& sDetectService,
+ utl::MediaDescriptor& rDescriptor )
+{
+ // Open the stream and add it to the media descriptor if this method is called for the first time.
+ // All following requests to this method will detect, that there already exists a stream .-)
+ // Attention: This method throws an exception if the stream could not be opened.
+ // It's important to break any further detection in such case.
+ // Catch it on the highest detection level only !!!
+ impl_openStream(rDescriptor);
+
+ // seek to 0 is an optional feature to be more robust against
+ // "simple implemented detect services" .-)
+ impl_seekStreamToZero(rDescriptor);
+
+ css::uno::Reference< css::document::XExtendedFilterDetection > xDetector;
+ css::uno::Reference< css::uno::XComponentContext > xContext;
+
+ // SAFE ->
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ xContext = m_xContext;
+ }
+ // <- SAFE
+
+ try
+ {
+ // Attention! If e.g. an office module was not installed sometimes we
+ // find a registered detect service, which is referred inside the
+ // configuration ... but not really installed. On the other side we use
+ // third party components here, which can make trouble anyway. So we
+ // should handle errors during creation of such services more
+ // gracefully .-)
+ xDetector.set(
+ xContext->getServiceManager()->createInstanceWithContext(sDetectService, xContext),
+ css::uno::UNO_QUERY_THROW);
+ }
+ catch (...)
+ {
+ }
+
+ if ( ! xDetector.is())
+ return OUString();
+
+ OUString sDeepType;
+ try
+ {
+ // start deep detection
+ // Don't forget to convert stl descriptor to its uno representation.
+
+ /* Attention!
+ You have to use an explicit instance of this uno sequence...
+ Because it's used as an in out parameter. And in case of a temp. used object
+ we will run into memory corruptions!
+ */
+ css::uno::Sequence< css::beans::PropertyValue > lDescriptor;
+ rDescriptor >> lDescriptor;
+ sDeepType = xDetector->detect(lDescriptor);
+ rDescriptor << lDescriptor;
+ }
+ catch (...)
+ {
+ // We should ignore errors here.
+ // Thrown exceptions mostly will end in crash recovery...
+ // But might be we find another deep detection service which can detect the same
+ // document without a problem .-)
+ sDeepType.clear();
+ }
+
+ // seek to 0 is an optional feature to be more robust against
+ // "simple implemented detect services" .-)
+ impl_seekStreamToZero(rDescriptor);
+
+ // analyze the results
+ // a) detect service returns "" => return "" too and remove TYPE/FILTER prop from descriptor
+ // b) returned type is unknown => return "" too and remove TYPE/FILTER prop from descriptor
+ // c) returned type is valid => check TYPE/FILTER props inside descriptor and return the type
+
+ // this special helper checks for a valid type
+ // and set right values on the descriptor!
+ bool bValidType = impl_validateAndSetTypeOnDescriptor(rDescriptor, sDeepType);
+ if (bValidType)
+ return sDeepType;
+
+ return OUString();
+}
+
+
+OUString TypeDetection::impl_askUserForTypeAndFilterIfAllowed(utl::MediaDescriptor& rDescriptor)
+{
+ css::uno::Reference< css::task::XInteractionHandler > xInteraction =
+ rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_INTERACTIONHANDLER,
+ css::uno::Reference< css::task::XInteractionHandler >());
+
+ if (!xInteraction.is())
+ return OUString();
+
+ OUString sURL =
+ rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_URL,
+ OUString());
+
+ css::uno::Reference< css::io::XInputStream > xStream =
+ rDescriptor.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_INPUTSTREAM,
+ css::uno::Reference< css::io::XInputStream >());
+
+ // Don't disturb the user for "non existing files - means empty URLs" or
+ // if we were forced to detect a stream.
+ // Reason behind: we must be sure to ask user for "unknown contents" only...
+ // and not for "missing files". Especially if detection is done by a stream only
+ // we can't check if the stream points to an "existing content"!
+ if (
+ (sURL.isEmpty() ) || // "non existing file" ?
+ (!xStream.is() ) || // non existing file !
+ (sURL.equalsIgnoreAsciiCase("private:stream")) // not a good idea .-)
+ )
+ return OUString();
+
+ try
+ {
+ // create a new request to ask user for its decision about the usable filter
+ ::framework::RequestFilterSelect aRequest(sURL);
+ xInteraction->handle(aRequest.GetRequest());
+
+ // "Cancel" pressed? => return with error
+ if (aRequest.isAbort())
+ return OUString();
+
+ // "OK" pressed => verify the selected filter, get its corresponding
+ // type and return it. (BTW: We must update the media descriptor here ...)
+ // The user selected explicitly a filter ... but normally we are interested on
+ // a type here only. But we must be sure, that the selected filter is used
+ // too and no ambiguous filter registration disturb us .-)
+
+ OUString sFilter = aRequest.getFilter();
+ if (!impl_validateAndSetFilterOnDescriptor(rDescriptor, sFilter))
+ return OUString();
+
+ OUString sType;
+ rDescriptor[utl::MediaDescriptor::PROP_TYPENAME] >>= sType;
+ return sType;
+ }
+ catch(const css::uno::Exception&)
+ {}
+
+ return OUString();
+}
+
+
+void TypeDetection::impl_openStream(utl::MediaDescriptor& rDescriptor)
+{
+ bool bSuccess = false;
+ OUString sURL = rDescriptor.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_URL, OUString() );
+ bool bRequestedReadOnly = rDescriptor.getUnpackedValueOrDefault( utl::MediaDescriptor::PROP_READONLY, false );
+ if ( comphelper::isFileUrl( sURL ) )
+ {
+ // OOo uses own file locking mechanics in case of local file
+ bSuccess = rDescriptor.addInputStreamOwnLock();
+ }
+ else
+ bSuccess = rDescriptor.addInputStream();
+
+ if ( !bSuccess )
+ throw css::uno::Exception(
+ "Could not open stream for <" + sURL + ">",
+ static_cast<OWeakObject *>(this));
+
+ if ( !bRequestedReadOnly )
+ {
+ // The MediaDescriptor implementation adds ReadOnly argument if the file can not be opened for writing
+ // this argument should be either removed or an additional argument should be added so that application
+ // can separate the case when the user explicitly requests readonly document.
+ // The current solution is to remove it here.
+ rDescriptor.erase( utl::MediaDescriptor::PROP_READONLY );
+ }
+}
+
+
+void TypeDetection::impl_removeTypeFilterFromDescriptor(utl::MediaDescriptor& rDescriptor)
+{
+ utl::MediaDescriptor::iterator pItType = rDescriptor.find(utl::MediaDescriptor::PROP_TYPENAME );
+ utl::MediaDescriptor::iterator pItFilter = rDescriptor.find(utl::MediaDescriptor::PROP_FILTERNAME);
+ if (pItType != rDescriptor.end())
+ rDescriptor.erase(pItType);
+ if (pItFilter != rDescriptor.end())
+ rDescriptor.erase(pItFilter);
+}
+
+
+bool TypeDetection::impl_validateAndSetTypeOnDescriptor( utl::MediaDescriptor& rDescriptor,
+ const OUString& sType )
+{
+ // SAFE ->
+ {
+ osl::MutexGuard aLock(m_aMutex);
+ if (GetTheFilterCache().hasItem(FilterCache::E_TYPE, sType))
+ {
+ rDescriptor[utl::MediaDescriptor::PROP_TYPENAME] <<= sType;
+ return true;
+ }
+ }
+ // <- SAFE
+
+ // remove all related information from the descriptor
+ impl_removeTypeFilterFromDescriptor(rDescriptor);
+ return false;
+}
+
+
+bool TypeDetection::impl_validateAndSetFilterOnDescriptor( utl::MediaDescriptor& rDescriptor,
+ const OUString& sFilter )
+{
+ try
+ {
+ // SAFE ->
+ osl::ClearableMutexGuard aLock(m_aMutex);
+
+ auto & cache = GetTheFilterCache();
+ CacheItem aFilter = cache.getItem(FilterCache::E_FILTER, sFilter);
+ OUString sType;
+ aFilter[PROPNAME_TYPE] >>= sType;
+
+ aLock.clear();
+ // <- SAFE
+
+ // found valid type and filter => set it on the given descriptor
+ rDescriptor[utl::MediaDescriptor::PROP_TYPENAME ] <<= sType ;
+ rDescriptor[utl::MediaDescriptor::PROP_FILTERNAME] <<= sFilter;
+ return true;
+ }
+ catch(const css::container::NoSuchElementException&){}
+
+ // remove all related information from the descriptor
+ impl_removeTypeFilterFromDescriptor(rDescriptor);
+ return false;
+}
+
+} // namespace filter
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_TypeDetection_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new filter::config::TypeDetection(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/cache/typedetection.hxx b/filter/source/config/cache/typedetection.hxx
new file mode 100644
index 000000000..114410392
--- /dev/null
+++ b/filter/source/config/cache/typedetection.hxx
@@ -0,0 +1,350 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "basecontainer.hxx"
+#include <com/sun/star/document/XTypeDetection.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+#include <unotools/mediadescriptor.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <comphelper/compbase.hxx>
+
+namespace filter::config {
+
+class TerminateDetection;
+
+/** @short implements the service <type scope="com.sun.star.document">TypeDetection</type>.
+ */
+class TypeDetection : public ::cppu::ImplInheritanceHelper< BaseContainer ,
+ css::document::XTypeDetection >
+{
+
+// native interface
+
+ css::uno::Reference< css::uno::XComponentContext > m_xContext;
+ rtl::Reference<TerminateDetection> m_xTerminateListener;
+ bool m_bCancel;
+
+public:
+
+
+ // ctor/dtor
+
+ /** @short standard ctor to connect this interface wrapper to
+ the global filter cache instance ...
+
+ @param rxContext
+ reference to the uno service manager, which created this service instance.
+ */
+ explicit TypeDetection(const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+
+ void cancel()
+ {
+ m_bCancel = true;
+ }
+
+
+ /** @short standard dtor.
+ */
+ virtual ~TypeDetection() override;
+
+
+// private helper
+
+private:
+
+ bool impl_getPreselectionForType(
+ const OUString& sPreSelType, const css::util::URL& aParsedURL, FlatDetection& rFlatTypes, bool bDocService);
+
+ void impl_getPreselectionForDocumentService(
+ const OUString& sPreSelDocumentService, const css::util::URL& aParsedURL, FlatDetection& rFlatTypes);
+
+ OUString impl_getTypeFromFilter(const OUString& rFilterName);
+
+ /**
+ * Get all format types that we handle.
+ */
+ void impl_getAllFormatTypes(
+ const css::util::URL& aParsedURL, utl::MediaDescriptor const & rDescriptor,
+ FlatDetection& rFlatTypes);
+
+
+ /** @short make a combined flat/deep type detection
+
+ @descr It steps over all flat detected types (given by the parameter lFlatTypes),
+ try it and search for most suitable one.
+ The specified MediaDescriptor will be patched, so it contain
+ the right values every time. Using of any deep detection service
+ can be enabled/disabled. And last but not least: If the results
+ won't be really clear (because a flat detected type has no deep
+ detection service), a "suggested" type name will be returned as "rLastChance".
+ It can be used after e.g. all well known deep detection services
+ was used without getting any result. Then this "last-chance-type"
+ should be returned. Of course using of it can fail too ... but it's a try :-)
+
+ @param rDescriptor
+ provides any easy-to-use stl interface to the MediaDescriptor.
+ Note : Its content will be adapted to returned result of this method.
+ Means: The type/filter entries of it will be actualized or removed from it.
+
+ @param lFlatTypes
+ a list of all flat detected types, which should be checked here.
+ No other types are allowed here!
+
+ @param rLastChance
+ the internal name of a "suggested type" ... (see before)
+ Note: it will be reset to an empty string every time. So
+ a set value of "rLastChance" can be detected outside very easy.
+
+ @param bAllowDeep
+ enable/disable using of a might existing deep detection service.
+
+ @return The internal name of a detected type.
+ An empty value if detection failed. ... but see rLastChance
+ for additional returns!
+ */
+ OUString impl_detectTypeFlatAndDeep( utl::MediaDescriptor& rDescriptor ,
+ const FlatDetection& lFlatTypes ,
+ bool bAllowDeep ,
+ OUString& rLastChance );
+
+
+ /** @short seek a might existing stream to position 0.
+
+ @descr This is an optional action to be more robust
+ in case any detect service doesn't make this seek...
+ Normally it's part of any called detect service or filter...
+ but sometimes it's not done there.
+
+ @param rDescriptor
+ a stl representation of the MediaDescriptor as in/out parameter.
+ */
+ static void impl_seekStreamToZero(utl::MediaDescriptor const & rDescriptor);
+
+
+ /** @short make deep type detection for a specified
+ detect service (threadsafe!).
+
+ @descr It creates the right uno service, prepare the
+ needed MediaDescriptor, call the right interfaces,
+ and return the results.
+
+ @attention The results (means type and corresponding filter)
+ are already part of the in/out parameter pDescriptor.
+ (in case they were valid).
+
+ @param sDetectService
+ uno service name of the detect service.
+
+ @param rDescriptor
+ a stl representation of the MediaDescriptor as in/out parameter.
+ */
+ OUString impl_askDetectService(const OUString& sDetectService,
+ utl::MediaDescriptor& rDescriptor );
+
+
+ /** @short try to find an interaction handler and
+ ask him to select a possible filter for
+ this unknown format.
+
+ @descr If the user select a filter, it will be used as return value
+ without further checking against the given file content!
+
+ @param rDescriptor
+ a stl representation of the MediaDescriptor as in/out parameter.
+
+ @return [string]
+ a valid type name or an empty string if user canceled interaction.
+ */
+ OUString impl_askUserForTypeAndFilterIfAllowed(utl::MediaDescriptor& rDescriptor);
+
+
+ /** @short check if an input stream is already part of the
+ given MediaDescriptor and creates a new one if necessary.
+
+ @attention This method does further something special!
+ <ul>
+ <li>
+ If the given URL seem to be a streamable content, but creation of the stream
+ failed (might by an IOException), this method throws an exception.
+ (May be an existing interaction handler must be called here too ...)
+ The whole detection must be interrupted then and the interface method queryTypeByDescriptor()
+ must return an empty type name value.
+
+ That prevent us against multiple handling of the same error more than ones
+ (e.g. if we ask all detect services as fallback ...).
+ </li>
+ <li>
+ In case the stream already exists inside the descriptor this method does nothing.
+ </li>
+ <li>
+ In case the stream does not exists but can be created successfully, the stream will
+ be added to the descriptor.
+ </li>
+ </ul>
+
+ @param rDescriptor
+ provides any easy-to-use stl interface to the MediaDescriptor.
+ Note : Its content will be adapted to returned result of this method.
+ Means: The stream will be added to it.
+
+ @throw Any suitable exception if stream should be opened but operation was not successful.
+ Note: If an interactionHandler is part of the given descriptor too, it was already used.
+ Means: let the exception pass through the top most interface method!
+ */
+ void impl_openStream(utl::MediaDescriptor& rDescriptor);
+
+
+ /** @short validate the specified type and its relationships
+ and set all needed information related to this type
+ in the specified descriptor.
+
+ @descr Related information are: - corresponding filter
+ - media type
+ - ...
+
+ @param rDescriptor
+ provides access to the outside MediaDescriptor.
+
+ @param sType
+ the name of the type, which should be set on the descriptor.
+ Can be empty to remove any related value from the descriptor!
+
+ @return TRUE the specified type and its registrations was valid(!) and
+ could be set on the descriptor.
+ */
+ bool impl_validateAndSetTypeOnDescriptor( utl::MediaDescriptor& rDescriptor,
+ const OUString& sType );
+
+
+ /** @short validate the specified filter and its relationships
+ and set all needed information related to this filter
+ in the specified descriptor.
+
+ @descr Related information are: - corresponding type
+ - ...
+
+ @param rDescriptor
+ provides access to the outside MediaDescriptor.
+
+ @param sFilter
+ the name of the filter, which should be set on the descriptor.
+ Can be empty to remove any related value from the descriptor!
+
+ @return TRUE the specified type and its registrations was valid(!) and
+ could be set on the descriptor.
+ */
+ bool impl_validateAndSetFilterOnDescriptor( utl::MediaDescriptor& rDescriptor,
+ const OUString& sFilter );
+
+
+ /** @short remove anything related to a TYPE/FILTER entry from the
+ specified MediaDescriptor.
+
+ @descr This method works together with impl_validateAndSetTypeOnDescriptor()/
+ impl_validateAndSetFilterOnDescriptor(). All information, which can be
+ set by these two operations must be "removable" by this method.
+
+ @param rDescriptor
+ reference to the MediaDescriptor (represented by an easy-to-use
+ stl interface!), which should be patched.
+ */
+ static void impl_removeTypeFilterFromDescriptor(utl::MediaDescriptor& rDescriptor);
+
+
+ /** @short search the best suitable filter for the given type
+ and add it into the media descriptor.
+
+ @descr Normally this is a type detection only ...
+ but for some special features we must overwrite our detection
+ because a file must be loaded into a special (means preselected)
+ application.
+
+ E.g. CSV/TXT format are sometimes ugly to handle .-)
+
+ Note: If the descriptor already include a filter
+ (may be selected by a FilterSelect interaction or preselected
+ by the user itself) ... we don't change that here !
+
+ @param rDescriptor
+ reference to the MediaDescriptor (represented by an easy-to-use
+ stl interface!), which should be patched.
+
+ @param sType
+ the internal type name, where we search a filter for.
+ Used as IN/OUT parameter so we can overrule the detection result for
+ types too !
+
+ @note #i60158#
+ sometimes our text ascii and our csv filter can't work together.
+ Then we overwrite our detection hardly.
+ sType param is used as out parameter then too ... and
+ rDescriptor will be changed by selecting another filter.
+ (see code)
+ */
+ void impl_checkResultsAndAddBestFilter(utl::MediaDescriptor& rDescriptor,
+ OUString& sType );
+
+
+// uno interface
+
+public:
+
+
+ // XTypeDetection
+
+ virtual OUString SAL_CALL queryTypeByURL(const OUString& sURL) override;
+
+ virtual OUString SAL_CALL queryTypeByDescriptor(css::uno::Sequence< css::beans::PropertyValue >& lDescriptor,
+ sal_Bool bAllowDeep ) override;
+
+};
+
+class TerminateDetection : public comphelper::WeakComponentImplHelper<css::frame::XTerminateListener>
+{
+private:
+ TypeDetection* m_pTypeDetection;
+
+public:
+
+ using comphelper::WeakComponentImplHelperBase::disposing;
+ virtual void SAL_CALL disposing(const css::lang::EventObject&) override
+ {
+ }
+
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination(const css::lang::EventObject&) override
+ {
+ m_pTypeDetection->cancel();
+ }
+
+ virtual void SAL_CALL notifyTermination(const css::lang::EventObject&) override
+ {
+ }
+
+ TerminateDetection(TypeDetection* pTypeDetection)
+ : m_pTypeDetection(pTypeDetection)
+ {
+ }
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/config/fragments/contenthandlers/com_sun_star_comp_framework_SoundHandler.xcu b/filter/source/config/fragments/contenthandlers/com_sun_star_comp_framework_SoundHandler.xcu
new file mode 100644
index 000000000..f49e237d9
--- /dev/null
+++ b/filter/source/config/fragments/contenthandlers/com_sun_star_comp_framework_SoundHandler.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="com.sun.star.comp.framework.SoundHandler" oor:op="replace" >
+ <prop oor:name="Types"><value>wav_Wave_Audio_File</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/contenthandlers/com_sun_star_comp_framework_oxt_handler.xcu b/filter/source/config/fragments/contenthandlers/com_sun_star_comp_framework_oxt_handler.xcu
new file mode 100644
index 000000000..2ae506aea
--- /dev/null
+++ b/filter/source/config/fragments/contenthandlers/com_sun_star_comp_framework_oxt_handler.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="com.sun.star.comp.framework.OXTFileHandler" oor:op="replace" >
+ <prop oor:name="Types"><value>oxt_OpenOffice_Extension</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ADO_rowset_XML.xcu b/filter/source/config/fragments/filters/ADO_rowset_XML.xcu
new file mode 100644
index 000000000..c31848ef8
--- /dev/null
+++ b/filter/source/config/fragments/filters/ADO_rowset_XML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="ADO Rowset XML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Calc.XMLOasisImporter,com.sun.star.comp.Calc.XMLOasisExporter,../$(share_subdir_name)/xslt/import/spreadsheetml/adorowset2ods.xsl,</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_ADO_rowset_XML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ADO Rowset XML</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/AbiWord.xcu b/filter/source/config/fragments/filters/AbiWord.xcu
new file mode 100644
index 000000000..a309ac87d
--- /dev/null
+++ b/filter/source/config/fragments/filters/AbiWord.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="AbiWord" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER EXOTIC</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.AbiWordImportFilter</value></prop>
+ <prop oor:name="UserData"><value>ABW</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">AbiWord Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_AbiWord_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/AppleKeynote.xcu b/filter/source/config/fragments/filters/AppleKeynote.xcu
new file mode 100644
index 000000000..48a99ba7c
--- /dev/null
+++ b/filter/source/config/fragments/filters/AppleKeynote.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="Apple Keynote" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Impress.KeynoteImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Apple Keynote</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>impress_AppleKeynote</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.presentation.PresentationDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/AppleNumbers.xcu b/filter/source/config/fragments/filters/AppleNumbers.xcu
new file mode 100644
index 000000000..2bfa87072
--- /dev/null
+++ b/filter/source/config/fragments/filters/AppleNumbers.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="Apple Numbers" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Calc.NumbersImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Apple Numbers</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>calc_AppleNumbers</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.sheet.SpreadsheetDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/ApplePages.xcu b/filter/source/config/fragments/filters/ApplePages.xcu
new file mode 100644
index 000000000..25ca2f015
--- /dev/null
+++ b/filter/source/config/fragments/filters/ApplePages.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="Apple Pages" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Writer.PagesImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Apple Pages</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>writer_ApplePages</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/BMP___MS_Windows.xcu b/filter/source/config/fragments/filters/BMP___MS_Windows.xcu
new file mode 100644
index 000000000..36ce6bfb4
--- /dev/null
+++ b/filter/source/config/fragments/filters/BMP___MS_Windows.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="BMP - MS Windows" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">BMP - Windows Bitmap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>bmp_MS_Windows</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/BroadBand_eBook.xcu b/filter/source/config/fragments/filters/BroadBand_eBook.xcu
new file mode 100644
index 000000000..3a54aed07
--- /dev/null
+++ b/filter/source/config/fragments/filters/BroadBand_eBook.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="BroadBand eBook" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">BroadBand eBook</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>writer_BroadBand_eBook</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/CGM___Computer_Graphics_Metafile.xcu b/filter/source/config/fragments/filters/CGM___Computer_Graphics_Metafile.xcu
new file mode 100644
index 000000000..26fa9e638
--- /dev/null
+++ b/filter/source/config/fragments/filters/CGM___Computer_Graphics_Metafile.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="CGM - Computer Graphics Metafile" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">CGM - Computer Graphics Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>impress_CGM_Computer_Graphics_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ClarisWorks.xcu b/filter/source/config/fragments/filters/ClarisWorks.xcu
new file mode 100644
index 000000000..8288c34ff
--- /dev/null
+++ b/filter/source/config/fragments/filters/ClarisWorks.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="ClarisWorks" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ClarisWorks/AppleWorks Text Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_ClarisWorks</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ClarisWorks_Calc.xcu b/filter/source/config/fragments/filters/ClarisWorks_Calc.xcu
new file mode 100644
index 000000000..a6f817dc2
--- /dev/null
+++ b/filter/source/config/fragments/filters/ClarisWorks_Calc.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="ClarisWorks_Calc" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ClarisWorks/AppleWorks Spreadsheet</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_ClarisWorks</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ClarisWorks_Draw.xcu b/filter/source/config/fragments/filters/ClarisWorks_Draw.xcu
new file mode 100644
index 000000000..e69354c3f
--- /dev/null
+++ b/filter/source/config/fragments/filters/ClarisWorks_Draw.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="ClarisWorks_Draw" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.MWAWDrawImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ClarisWorks/AppleWorks Drawing</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_ClarisWorks</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ClarisWorks_Impress.xcu b/filter/source/config/fragments/filters/ClarisWorks_Impress.xcu
new file mode 100644
index 000000000..9318c5d95
--- /dev/null
+++ b/filter/source/config/fragments/filters/ClarisWorks_Impress.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="ClarisWorks_Impress" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Impress.MWAWPresentationImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ClarisWorks/AppleWorks Presentation</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>impress_ClarisWorks</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Claris_Resolve_Calc.xcu b/filter/source/config/fragments/filters/Claris_Resolve_Calc.xcu
new file mode 100644
index 000000000..17b802422
--- /dev/null
+++ b/filter/source/config/fragments/filters/Claris_Resolve_Calc.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Claris_Resolve_Calc" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ClarisResolve Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_Claris_Resolve</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/CorelDrawDocument.xcu b/filter/source/config/fragments/filters/CorelDrawDocument.xcu
new file mode 100644
index 000000000..14b6e2806
--- /dev/null
+++ b/filter/source/config/fragments/filters/CorelDrawDocument.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Corel Draw Document" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.CDRImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Corel Draw</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_CorelDraw_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/CorelPresentationExchange.xcu b/filter/source/config/fragments/filters/CorelPresentationExchange.xcu
new file mode 100644
index 000000000..0a402d2ea
--- /dev/null
+++ b/filter/source/config/fragments/filters/CorelPresentationExchange.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Corel Presentation Exchange" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.CMXImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Corel Presentation Exchange</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_Corel_Presentation_Exchange</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/DIF.xcu b/filter/source/config/fragments/filters/DIF.xcu
new file mode 100644
index 000000000..c075ff977
--- /dev/null
+++ b/filter/source/config/fragments/filters/DIF.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="DIF" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Calc.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Data Interchange Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_DIF</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/DXF___AutoCAD_Interchange.xcu b/filter/source/config/fragments/filters/DXF___AutoCAD_Interchange.xcu
new file mode 100644
index 000000000..652ee10e2
--- /dev/null
+++ b/filter/source/config/fragments/filters/DXF___AutoCAD_Interchange.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="DXF - AutoCAD Interchange" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">DXF - AutoCAD Interchange Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>dxf_AutoCAD_Interchange</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/DocBook_File.xcu b/filter/source/config/fragments/filters/DocBook_File.xcu
new file mode 100644
index 000000000..da278f4c6
--- /dev/null
+++ b/filter/source/config/fragments/filters/DocBook_File.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="DocBook File" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_DocBook_File</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Writer.XMLImporter,com.sun.star.comp.Writer.XMLExporter,../$(share_subdir_name)/xslt/docbook/docbooktosoffheadings.xsl,../$(share_subdir_name)/xslt/docbook/sofftodocbookheadings.xsl</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"><value>../$(share_subdir_name)/xslt/docbook/DocBookTemplate.stw</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">DocBook</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/DosWord.xcu b/filter/source/config/fragments/filters/DosWord.xcu
new file mode 100644
index 000000000..697032c91
--- /dev/null
+++ b/filter/source/config/fragments/filters/DosWord.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+-->
+
+<node oor:name="DosWord" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Writer.MSWorksImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Word for DOS</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>writer_DosWord</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/EMF___MS_Windows_Metafile.xcu b/filter/source/config/fragments/filters/EMF___MS_Windows_Metafile.xcu
new file mode 100644
index 000000000..852cb1f8b
--- /dev/null
+++ b/filter/source/config/fragments/filters/EMF___MS_Windows_Metafile.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="EMF - MS Windows Metafile" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EMF - Enhanced Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>emf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/EPS___Encapsulated_PostScript.xcu b/filter/source/config/fragments/filters/EPS___Encapsulated_PostScript.xcu
new file mode 100644
index 000000000..195b6af84
--- /dev/null
+++ b/filter/source/config/fragments/filters/EPS___Encapsulated_PostScript.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="EPS - Encapsulated PostScript" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EPS - Encapsulated PostScript</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>eps_Encapsulated_PostScript</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/EPUB.xcu b/filter/source/config/fragments/filters/EPUB.xcu
new file mode 100644
index 000000000..8ec0da9cd
--- /dev/null
+++ b/filter/source/config/fragments/filters/EPUB.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="EPUB" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Writer.EPUBExportUIComponent</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.EPUBExportFilter</value></prop>
+ <prop oor:name="UserData"><value>EPUB</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EPUB Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_EPUB_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/FictionBook_2.xcu b/filter/source/config/fragments/filters/FictionBook_2.xcu
new file mode 100644
index 000000000..68e4c1c34
--- /dev/null
+++ b/filter/source/config/fragments/filters/FictionBook_2.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="FictionBook 2" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">FictionBook 2.0</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>writer_FictionBook_2</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/FreehandDocument.xcu b/filter/source/config/fragments/filters/FreehandDocument.xcu
new file mode 100644
index 000000000..4502ac0ce
--- /dev/null
+++ b/filter/source/config/fragments/filters/FreehandDocument.xcu
@@ -0,0 +1,13 @@
+ <node oor:name="Freehand Document" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.FreehandImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Adobe/Macromedia Freehand</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_Freehand_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/GIF___Graphics_Interchange.xcu b/filter/source/config/fragments/filters/GIF___Graphics_Interchange.xcu
new file mode 100644
index 000000000..a62d53fd0
--- /dev/null
+++ b/filter/source/config/fragments/filters/GIF___Graphics_Interchange.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="GIF - Graphics Interchange" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">GIF - Graphics Interchange Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>gif_Graphics_Interchange</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/HTML.xcu b/filter/source/config/fragments/filters/HTML.xcu
new file mode 100644
index 000000000..68a64cb01
--- /dev/null
+++ b/filter/source/config/fragments/filters/HTML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="HTML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>HTML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>generic_HTML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">HTML Document</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/HTML_MasterDoc.xcu b/filter/source/config/fragments/filters/HTML_MasterDoc.xcu
new file mode 100644
index 000000000..1316b1d4f
--- /dev/null
+++ b/filter/source/config/fragments/filters/HTML_MasterDoc.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="HTML_MasterDoc" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>generic_HTML</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value>HTML</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">HTML Document (Master Document)</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT INTERNAL NOTINFILEDIALOG</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/HTML__StarCalc_.xcu b/filter/source/config/fragments/filters/HTML__StarCalc_.xcu
new file mode 100644
index 000000000..9e731b3bb
--- /dev/null
+++ b/filter/source/config/fragments/filters/HTML__StarCalc_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="HTML (StarCalc)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN USEOPTIONS</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Calc.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>generic_HTML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">HTML Document (Calc)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/HTML__StarWriter_.xcu b/filter/source/config/fragments/filters/HTML__StarWriter_.xcu
new file mode 100644
index 000000000..3a9d68347
--- /dev/null
+++ b/filter/source/config/fragments/filters/HTML__StarWriter_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="HTML (StarWriter)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>HTML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>generic_HTML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">HTML Document (Writer)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/JPG___JPEG.xcu b/filter/source/config/fragments/filters/JPG___JPEG.xcu
new file mode 100644
index 000000000..7e5794a38
--- /dev/null
+++ b/filter/source/config/fragments/filters/JPG___JPEG.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="JPG - JPEG" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>jpg_JPEG</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Lotus.xcu b/filter/source/config/fragments/filters/Lotus.xcu
new file mode 100644
index 000000000..44bf3a89c
--- /dev/null
+++ b/filter/source/config/fragments/filters/Lotus.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Lotus" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN PREFERRED</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Calc.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Lotus 1-2-3</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_Lotus</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/LotusWordPro.xcu b/filter/source/config/fragments/filters/LotusWordPro.xcu
new file mode 100644
index 000000000..8b065b0c2
--- /dev/null
+++ b/filter/source/config/fragments/filters/LotusWordPro.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="LotusWordPro" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.LotusWordProImportFilter</value></prop>
+ <prop oor:name="UserData"><value>WPD</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Lotus WordPro Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_LotusWordPro_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MET___OS_2_Metafile.xcu b/filter/source/config/fragments/filters/MET___OS_2_Metafile.xcu
new file mode 100644
index 000000000..1c1059b74
--- /dev/null
+++ b/filter/source/config/fragments/filters/MET___OS_2_Metafile.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MET - OS/2 Metafile" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">MET - OS/2 Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>met_OS2_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_2003_XML.xcu b/filter/source/config/fragments/filters/MS_Excel_2003_XML.xcu
new file mode 100644
index 000000000..a0fc95939
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_2003_XML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS Excel 2003 XML" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Calc.XMLOasisImporter,com.sun.star.comp.Calc.XMLOasisExporter,../$(share_subdir_name)/xslt/import/spreadsheetml/spreadsheetml2ooo.xsl,../$(share_subdir_name)/xslt/export/spreadsheetml/ooo2spreadsheetml.xsl</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_2003_XML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 2003 XML</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_2003_XML_Orcus.xcu b/filter/source/config/fragments/filters/MS_Excel_2003_XML_Orcus.xcu
new file mode 100644
index 000000000..2206b0274
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_2003_XML_Orcus.xcu
@@ -0,0 +1,19 @@
+<!--
+ * 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/.
+-->
+<node oor:name="MS Excel 2003 XML Orcus" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="Type"><value>calc_MS_Excel_2003_XML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 2003 XML</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_4_0.xcu b/filter/source/config/fragments/filters/MS_Excel_4_0.xcu
new file mode 100644
index 000000000..99dbdb06b
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_4_0.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 4.0" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 4.0</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_40</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_4_0_Vorlage_Template.xcu b/filter/source/config/fragments/filters/MS_Excel_4_0_Vorlage_Template.xcu
new file mode 100644
index 000000000..1e724cdcb
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_4_0_Vorlage_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 4.0 Vorlage/Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN TEMPLATE TEMPLATEPATH</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_40_VorlageTemplate</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 4.0 Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_5_0_95.xcu b/filter/source/config/fragments/filters/MS_Excel_5_0_95.xcu
new file mode 100644
index 000000000..56244a3e4
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_5_0_95.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 5.0/95" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 5.0</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_5095</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_5_0_95_Vorlage_Template.xcu b/filter/source/config/fragments/filters/MS_Excel_5_0_95_Vorlage_Template.xcu
new file mode 100644
index 000000000..4b8ec72a3
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_5_0_95_Vorlage_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 5.0/95 Vorlage/Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN TEMPLATE TEMPLATEPATH</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_5095_VorlageTemplate</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 5.0 Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_95.xcu b/filter/source/config/fragments/filters/MS_Excel_95.xcu
new file mode 100644
index 000000000..a6f424fbc
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_95.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 95" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 95</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_95</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_95_Vorlage_Template.xcu b/filter/source/config/fragments/filters/MS_Excel_95_Vorlage_Template.xcu
new file mode 100644
index 000000000..d4c39a3d2
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_95_Vorlage_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 95 Vorlage/Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN TEMPLATE TEMPLATEPATH</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_95_VorlageTemplate</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 95 Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_97.xcu b/filter/source/config/fragments/filters/MS_Excel_97.xcu
new file mode 100644
index 000000000..cd2dd38d8
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_97.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 97" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN PREFERRED ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Excel 97–2003</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_97</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MS_Excel_97_Vorlage_Template.xcu b/filter/source/config/fragments/filters/MS_Excel_97_Vorlage_Template.xcu
new file mode 100644
index 000000000..2dc342b06
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Excel_97_Vorlage_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 97 Vorlage/Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN TEMPLATE TEMPLATEPATH ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Excel_97_VorlageTemplate</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Excel 97–2003 Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Multiplan.xcu b/filter/source/config/fragments/filters/MS_Multiplan.xcu
new file mode 100644
index 000000000..780901d53
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Multiplan.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="Microsoft Multiplan" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Calc.MSWorksCalcImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Multiplan</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>calc_MS_Multiplan</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.sheet.SpreadsheetDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MS_PowerPoint_97.xcu b/filter/source/config/fragments/filters/MS_PowerPoint_97.xcu
new file mode 100644
index 000000000..eab7c73e3
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_PowerPoint_97.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS PowerPoint 97" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>sdfilt</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PowerPoint 97–2003</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>impress_MS_PowerPoint_97</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_PowerPoint_97_AutoPlay.xcu b/filter/source/config/fragments/filters/MS_PowerPoint_97_AutoPlay.xcu
new file mode 100644
index 000000000..24683ea1b
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_PowerPoint_97_AutoPlay.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS PowerPoint 97 AutoPlay" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN STARTPRESENTATION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>sdfilt</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PowerPoint 97–2003 AutoPlay</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>impress_MS_PowerPoint_97_AutoPlay</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_PowerPoint_97_Vorlage.xcu b/filter/source/config/fragments/filters/MS_PowerPoint_97_Vorlage.xcu
new file mode 100644
index 000000000..4de589b1d
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_PowerPoint_97_Vorlage.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS PowerPoint 97 Vorlage" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE TEMPLATEPATH ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>sdfilt</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>impress_MS_PowerPoint_97_Vorlage</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PowerPoint 97–2003 Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_WinWord_5.xcu b/filter/source/config/fragments/filters/MS_WinWord_5.xcu
new file mode 100644
index 000000000..a8656eda4
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_WinWord_5.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS WinWord 5" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>WW6</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft WinWord 1/2/5</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_WinWord_5</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_WinWord_6_0.xcu b/filter/source/config/fragments/filters/MS_WinWord_6_0.xcu
new file mode 100644
index 000000000..cdc6a6a5e
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_WinWord_6_0.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS WinWord 6.0" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CWW6</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Word 6.0</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_WinWord_60</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Word_2003_XML.xcu b/filter/source/config/fragments/filters/MS_Word_2003_XML.xcu
new file mode 100644
index 000000000..1db287f09
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Word_2003_XML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS Word 2003 XML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Writer.XMLOasisImporter,com.sun.star.comp.Writer.XMLOasisExporter,../$(share_subdir_name)/xslt/import/wordml/wordml2ooo.xsl,../$(share_subdir_name)/xslt/export/wordml/ooo2wordml.xsl</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Word_2003_XML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Word 2003 XML</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Word_2007_XML.xcu b/filter/source/config/fragments/filters/MS_Word_2007_XML.xcu
new file mode 100644
index 000000000..c4e6f828c
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Word_2007_XML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS Word 2007 XML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER ENCRYPTION PASSWORDTOMODIFY SUPPORTSSIGNING</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.WriterFilter</value></prop>
+ <prop oor:name="UserData"><value>OXML</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Word 2007–365</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Word_2007</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Word_2007_XML_Template.xcu b/filter/source/config/fragments/filters/MS_Word_2007_XML_Template.xcu
new file mode 100644
index 000000000..cd81c9943
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Word_2007_XML_Template.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS Word 2007 XML Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER TEMPLATE TEMPLATEPATH</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.WriterFilter</value></prop>
+ <prop oor:name="UserData"><value>OXML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Word 2007–365 Template</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Word_2007_Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Word_2007_XML_VBA.xcu b/filter/source/config/fragments/filters/MS_Word_2007_XML_VBA.xcu
new file mode 100644
index 000000000..0f1bdb723
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Word_2007_XML_VBA.xcu
@@ -0,0 +1,18 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="MS Word 2007 XML VBA" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER ENCRYPTION PASSWORDTOMODIFY SUPPORTSSIGNING</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.WriterFilter</value></prop>
+ <prop oor:name="UserData"><value>OXML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Word 2007–365 VBA</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Word_2007_VBA</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Word_95.xcu b/filter/source/config/fragments/filters/MS_Word_95.xcu
new file mode 100644
index 000000000..7db5ca087
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Word_95.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS Word 95" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CWW6</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Word 95</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Word_95</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Word_95_Vorlage.xcu b/filter/source/config/fragments/filters/MS_Word_95_Vorlage.xcu
new file mode 100644
index 000000000..3b2a105f8
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Word_95_Vorlage.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS Word 95 Vorlage" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE TEMPLATEPATH ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CWW6</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Word_95_Vorlage</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Word 95 Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Word_97.xcu b/filter/source/config/fragments/filters/MS_Word_97.xcu
new file mode 100644
index 000000000..5adec6272
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Word_97.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS Word 97" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN PREFERRED ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CWW8</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Word 97–2003</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Word_97</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Word_97_Vorlage.xcu b/filter/source/config/fragments/filters/MS_Word_97_Vorlage.xcu
new file mode 100644
index 000000000..2fc7a7b68
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Word_97_Vorlage.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS Word 97 Vorlage" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE TEMPLATEPATH ALIEN ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CWW8</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Word_97_Vorlage</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Word 97–2003 Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Works.xcu b/filter/source/config/fragments/filters/MS_Works.xcu
new file mode 100644
index 000000000..7a6377b8c
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Works.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS_Works" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MSWorksImportFilter</value></prop>
+ <prop oor:name="UserData"><value>WPS</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Works Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Works_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Works_Calc.xcu b/filter/source/config/fragments/filters/MS_Works_Calc.xcu
new file mode 100644
index 000000000..f563469a5
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Works_Calc.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS_Works_Calc" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Calc.MSWorksCalcImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Works Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_MS_Works_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MS_Write.xcu b/filter/source/config/fragments/filters/MS_Write.xcu
new file mode 100644
index 000000000..061613816
--- /dev/null
+++ b/filter/source/config/fragments/filters/MS_Write.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MS_Write" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MSWorksImportFilter</value></prop>
+ <prop oor:name="UserData"><value>WRI</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Write</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MS_Write</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MWAW_Bitmap.xcu b/filter/source/config/fragments/filters/MWAW_Bitmap.xcu
new file mode 100644
index 000000000..3e70cc62f
--- /dev/null
+++ b/filter/source/config/fragments/filters/MWAW_Bitmap.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Bitmap" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED EXOTIC</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Draw.MWAWDrawImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy Mac Bitmap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>MWAW_Bitmap</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.drawing.DrawingDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MWAW_Database.xcu b/filter/source/config/fragments/filters/MWAW_Database.xcu
new file mode 100644
index 000000000..075f3ed9e
--- /dev/null
+++ b/filter/source/config/fragments/filters/MWAW_Database.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Database" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED EXOTIC</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy Mac Database</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>MWAW_Database</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.sheet.SpreadsheetDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MWAW_Drawing.xcu b/filter/source/config/fragments/filters/MWAW_Drawing.xcu
new file mode 100644
index 000000000..1b9ec56d2
--- /dev/null
+++ b/filter/source/config/fragments/filters/MWAW_Drawing.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Drawing" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED EXOTIC</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Draw.MWAWDrawImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy Mac Drawing</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>MWAW_Drawing</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.drawing.DrawingDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MWAW_Presentation.xcu b/filter/source/config/fragments/filters/MWAW_Presentation.xcu
new file mode 100644
index 000000000..aae6598b2
--- /dev/null
+++ b/filter/source/config/fragments/filters/MWAW_Presentation.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Presentation" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED EXOTIC</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Impress.MWAWPresentationImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy Mac Presentation</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>MWAW_Presentation</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.presentation.PresentationDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MWAW_Spreadsheet.xcu b/filter/source/config/fragments/filters/MWAW_Spreadsheet.xcu
new file mode 100644
index 000000000..5461b7fe2
--- /dev/null
+++ b/filter/source/config/fragments/filters/MWAW_Spreadsheet.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Spreadsheet" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED EXOTIC</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy Mac Spreadsheet</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>MWAW_Spreadsheet</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.sheet.SpreadsheetDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MWAW_Text_Document.xcu b/filter/source/config/fragments/filters/MWAW_Text_Document.xcu
new file mode 100644
index 000000000..cfbd5556f
--- /dev/null
+++ b/filter/source/config/fragments/filters/MWAW_Text_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Text_Document" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED EXOTIC</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Writer.MWAWImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy Mac Text Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>MWAW_Text_Document</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/MacWrite.xcu b/filter/source/config/fragments/filters/MacWrite.xcu
new file mode 100644
index 000000000..79a297f33
--- /dev/null
+++ b/filter/source/config/fragments/filters/MacWrite.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MacWrite" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">MacWrite Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MacWrite</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Mac_Word.xcu b/filter/source/config/fragments/filters/Mac_Word.xcu
new file mode 100644
index 000000000..64d2edb2b
--- /dev/null
+++ b/filter/source/config/fragments/filters/Mac_Word.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Mac_Word" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Word for Mac (v1 - v5)</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_Mac_Word</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Mac_Works.xcu b/filter/source/config/fragments/filters/Mac_Works.xcu
new file mode 100644
index 000000000..beb2eadea
--- /dev/null
+++ b/filter/source/config/fragments/filters/Mac_Works.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Mac_Works" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Works for Mac Text Document (v1 - v4)</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_Mac_Works</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Mac_Works_Calc.xcu b/filter/source/config/fragments/filters/Mac_Works_Calc.xcu
new file mode 100644
index 000000000..ec3b959d2
--- /dev/null
+++ b/filter/source/config/fragments/filters/Mac_Works_Calc.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Mac_Works_Calc" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Works for Mac Spreadsheet (v1 - v4)</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_Mac_Works</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Mariner_Write.xcu b/filter/source/config/fragments/filters/Mariner_Write.xcu
new file mode 100644
index 000000000..df6689ccc
--- /dev/null
+++ b/filter/source/config/fragments/filters/Mariner_Write.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Mariner_Write" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Mariner Write Mac Classic v1.6 - v3.5</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_Mariner_Write</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MathML_XML__Math_.xcu b/filter/source/config/fragments/filters/MathML_XML__Math_.xcu
new file mode 100644
index 000000000..5a6e24adc
--- /dev/null
+++ b/filter/source/config/fragments/filters/MathML_XML__Math_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MathML XML (Math)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">MathML 2.0</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>math_MathML_XML_Math</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.formula.FormulaProperties</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/MathType_3_x.xcu b/filter/source/config/fragments/filters/MathType_3_x.xcu
new file mode 100644
index 000000000..b93bf39c4
--- /dev/null
+++ b/filter/source/config/fragments/filters/MathType_3_x.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="MathType 3.x" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN NOTINFILEDIALOG</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">MathType3.x</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>math_MathType_3x</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.formula.FormulaProperties</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ODG_FlatXML.xcu b/filter/source/config/fragments/filters/ODG_FlatXML.xcu
new file mode 100644
index 000000000..c246e0a47
--- /dev/null
+++ b/filter/source/config/fragments/filters/ODG_FlatXML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="OpenDocument Drawing Flat XML" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_ODG_FlatXML</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.comp.filter.OdfFlatXml,,com.sun.star.comp.Draw.XMLOasisImporter,com.sun.star.comp.Draw.XMLOasisExporter,,,true</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Flat XML ODF Drawing</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT EXPORT OWN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ODP_FlatXML.xcu b/filter/source/config/fragments/filters/ODP_FlatXML.xcu
new file mode 100644
index 000000000..e5052aa14
--- /dev/null
+++ b/filter/source/config/fragments/filters/ODP_FlatXML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="OpenDocument Presentation Flat XML" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>impress_ODP_FlatXML</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.comp.filter.OdfFlatXml,,com.sun.star.comp.Impress.XMLOasisImporter,com.sun.star.comp.Impress.XMLOasisExporter,,,true</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Flat XML ODF Presentation</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT EXPORT OWN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ODS_FlatXML.xcu b/filter/source/config/fragments/filters/ODS_FlatXML.xcu
new file mode 100644
index 000000000..d18197bdd
--- /dev/null
+++ b/filter/source/config/fragments/filters/ODS_FlatXML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="OpenDocument Spreadsheet Flat XML" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_ODS_FlatXML</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.comp.filter.OdfFlatXml,,com.sun.star.comp.Calc.XMLOasisImporter,com.sun.star.comp.Calc.XMLOasisExporter,,,true</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Flat XML ODF Spreadsheet</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT EXPORT OWN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ODT_FlatXML.xcu b/filter/source/config/fragments/filters/ODT_FlatXML.xcu
new file mode 100644
index 000000000..e113d742c
--- /dev/null
+++ b/filter/source/config/fragments/filters/ODT_FlatXML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="OpenDocument Text Flat XML" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_ODT_FlatXML</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.comp.filter.OdfFlatXml,,com.sun.star.comp.Writer.XMLOasisImporter,com.sun.star.comp.Writer.XMLOasisExporter,,,true</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Flat XML ODF Text Document</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT EXPORT OWN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/OOXML_Text.xcu b/filter/source/config/fragments/filters/OOXML_Text.xcu
new file mode 100644
index 000000000..ebaab6406
--- /dev/null
+++ b/filter/source/config/fragments/filters/OOXML_Text.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Office Open XML Text" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.WriterFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Office Open XML Text (Transitional)</value>
+ </prop>
+ <!-- ISO/IEC 29500:2008 -->
+ <prop oor:name="FileFormatVersion"><value>1</value></prop>
+ <prop oor:name="Type"><value>writer_OOXML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/OOXML_Text_Template.xcu b/filter/source/config/fragments/filters/OOXML_Text_Template.xcu
new file mode 100644
index 000000000..88fbf7047
--- /dev/null
+++ b/filter/source/config/fragments/filters/OOXML_Text_Template.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Office Open XML Text Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER TEMPLATE TEMPLATEPATH</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.WriterFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Office Open XML Text Template (Transitional)</value>
+ </prop>
+ <!-- ISO/IEC 29500:2008 -->
+ <prop oor:name="FileFormatVersion"><value>1</value></prop>
+ <prop oor:name="Type"><value>writer_OOXML_Text_Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PBM___Portable_Bitmap.xcu b/filter/source/config/fragments/filters/PBM___Portable_Bitmap.xcu
new file mode 100644
index 000000000..6d560bc44
--- /dev/null
+++ b/filter/source/config/fragments/filters/PBM___Portable_Bitmap.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="PBM - Portable Bitmap" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PBM - Portable Bitmap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pbm_Portable_Bitmap</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PCT___Mac_Pict.xcu b/filter/source/config/fragments/filters/PCT___Mac_Pict.xcu
new file mode 100644
index 000000000..92ae6cd23
--- /dev/null
+++ b/filter/source/config/fragments/filters/PCT___Mac_Pict.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="PCT - Mac Pict" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCT - Mac Pict</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pct_Mac_Pict</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PCX___Zsoft_Paintbrush.xcu b/filter/source/config/fragments/filters/PCX___Zsoft_Paintbrush.xcu
new file mode 100644
index 000000000..31122c365
--- /dev/null
+++ b/filter/source/config/fragments/filters/PCX___Zsoft_Paintbrush.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="PCX - Zsoft Paintbrush" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCX - Zsoft Paintbrush</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pcx_Zsoft_Paintbrush</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PGM___Portable_Graymap.xcu b/filter/source/config/fragments/filters/PGM___Portable_Graymap.xcu
new file mode 100644
index 000000000..f930bc8c1
--- /dev/null
+++ b/filter/source/config/fragments/filters/PGM___Portable_Graymap.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="PGM - Portable Graymap" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PGM - Portable Graymap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pgm_Portable_Graymap</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PNG___Portable_Network_Graphic.xcu b/filter/source/config/fragments/filters/PNG___Portable_Network_Graphic.xcu
new file mode 100644
index 000000000..b321ab6da
--- /dev/null
+++ b/filter/source/config/fragments/filters/PNG___Portable_Network_Graphic.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="PNG - Portable Network Graphic" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PNG - Portable Network Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>png_Portable_Network_Graphic</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PPM___Portable_Pixelmap.xcu b/filter/source/config/fragments/filters/PPM___Portable_Pixelmap.xcu
new file mode 100644
index 000000000..de35d2491
--- /dev/null
+++ b/filter/source/config/fragments/filters/PPM___Portable_Pixelmap.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="PPM - Portable Pixelmap" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PPM - Portable Pixelmap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>ppm_Portable_Pixelmap</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PSD___Adobe_Photoshop.xcu b/filter/source/config/fragments/filters/PSD___Adobe_Photoshop.xcu
new file mode 100644
index 000000000..ab2a457e9
--- /dev/null
+++ b/filter/source/config/fragments/filters/PSD___Adobe_Photoshop.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="PSD - Adobe Photoshop" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PSD - Adobe Photoshop</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>psd_Adobe_Photoshop</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PageMakerDocument.xcu b/filter/source/config/fragments/filters/PageMakerDocument.xcu
new file mode 100644
index 000000000..ad45de75b
--- /dev/null
+++ b/filter/source/config/fragments/filters/PageMakerDocument.xcu
@@ -0,0 +1,13 @@
+ <node oor:name="PageMaker Document" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>org.libreoffice.comp.Draw.PageMakerImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Adobe PageMaker</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_PageMaker_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PalmDoc.xcu b/filter/source/config/fragments/filters/PalmDoc.xcu
new file mode 100644
index 000000000..8e612f693
--- /dev/null
+++ b/filter/source/config/fragments/filters/PalmDoc.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="PalmDoc" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PalmDoc eBook</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>writer_PalmDoc</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/Palm_Text_Document.xcu b/filter/source/config/fragments/filters/Palm_Text_Document.xcu
new file mode 100644
index 000000000..4747d3588
--- /dev/null
+++ b/filter/source/config/fragments/filters/Palm_Text_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="Palm_Text_Document" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Palm Text Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>Palm_Text_Document</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/Plucker_eBook.xcu b/filter/source/config/fragments/filters/Plucker_eBook.xcu
new file mode 100644
index 000000000..b5942780d
--- /dev/null
+++ b/filter/source/config/fragments/filters/Plucker_eBook.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="Plucker eBook" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Plucker eBook</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>writer_Plucker_eBook</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/PocketWord_File.xcu b/filter/source/config/fragments/filters/PocketWord_File.xcu
new file mode 100644
index 000000000..1ce83aa68
--- /dev/null
+++ b/filter/source/config/fragments/filters/PocketWord_File.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="PocketWord File" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_PocketWord_File</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MSWorksImportFilter</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value>Pocket Word</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/PowerPoint3.xcu b/filter/source/config/fragments/filters/PowerPoint3.xcu
new file mode 100644
index 000000000..d1d19e6d2
--- /dev/null
+++ b/filter/source/config/fragments/filters/PowerPoint3.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+-->
+
+<node oor:name="PowerPoint 3" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.Impress.MWAWPresentationImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft PowerPoint 1-4 and 95's</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>impress_PowerPoint3</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.presentation.PresentationDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/PublisherDocument.xcu b/filter/source/config/fragments/filters/PublisherDocument.xcu
new file mode 100644
index 000000000..5dcc167e8
--- /dev/null
+++ b/filter/source/config/fragments/filters/PublisherDocument.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Publisher Document" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.MSPUBImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Publisher 98-2010</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_Publisher_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/QPro.xcu b/filter/source/config/fragments/filters/QPro.xcu
new file mode 100644
index 000000000..e3242644b
--- /dev/null
+++ b/filter/source/config/fragments/filters/QPro.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Quattro Pro 6.0" oor:op="replace" oor:finalized="true" oor:mandatory="true">
+ <prop oor:name="Flags"><value>IMPORT ALIEN PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Quattro Pro 6.0</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_QPro</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/QXPDocument.xcu b/filter/source/config/fragments/filters/QXPDocument.xcu
new file mode 100644
index 000000000..b0e645000
--- /dev/null
+++ b/filter/source/config/fragments/filters/QXPDocument.xcu
@@ -0,0 +1,13 @@
+ <node oor:name="QXP Document" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>org.libreoffice.comp.Draw.QXPImportFilter</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">QuarkXPress</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_QXP_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/RAS___Sun_Rasterfile.xcu b/filter/source/config/fragments/filters/RAS___Sun_Rasterfile.xcu
new file mode 100644
index 000000000..cd9f7b1d2
--- /dev/null
+++ b/filter/source/config/fragments/filters/RAS___Sun_Rasterfile.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="RAS - Sun Rasterfile" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">RAS - Sun Raster Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>ras_Sun_Rasterfile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Rich_Text_Format.xcu b/filter/source/config/fragments/filters/Rich_Text_Format.xcu
new file mode 100644
index 000000000..239408310
--- /dev/null
+++ b/filter/source/config/fragments/filters/Rich_Text_Format.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Rich Text Format" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.RtfFilter</value></prop>
+ <prop oor:name="UserData"><value>RTF</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Rich Text</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_Rich_Text_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Rich_Text_Format__StarCalc_.xcu b/filter/source/config/fragments/filters/Rich_Text_Format__StarCalc_.xcu
new file mode 100644
index 000000000..c74c65857
--- /dev/null
+++ b/filter/source/config/fragments/filters/Rich_Text_Format__StarCalc_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Rich Text Format (StarCalc)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Rich Text Format (Calc)</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_Rich_Text_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu b/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu
new file mode 100644
index 000000000..c5cae01dd
--- /dev/null
+++ b/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="SVG - Scalable Vector Graphics" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu b/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu
new file mode 100644
index 000000000..eb98d7f94
--- /dev/null
+++ b/filter/source/config/fragments/filters/SVG___Scalable_Vector_Graphics_Draw.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="SVG - Scalable Vector Graphics Draw" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVG - Scalable Vector Graphics Draw</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics_Draw</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/SVM___StarView_Metafile.xcu b/filter/source/config/fragments/filters/SVM___StarView_Metafile.xcu
new file mode 100644
index 000000000..89c542533
--- /dev/null
+++ b/filter/source/config/fragments/filters/SVM___StarView_Metafile.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="SVM - StarView Metafile" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVM - StarView Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>svm_StarView_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/SYLK.xcu b/filter/source/config/fragments/filters/SYLK.xcu
new file mode 100644
index 000000000..9ebb83643
--- /dev/null
+++ b/filter/source/config/fragments/filters/SYLK.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="SYLK" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SYLK</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_SYLK</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarBaseReport.xcu b/filter/source/config/fragments/filters/StarBaseReport.xcu
new file mode 100644
index 000000000..797d490f9
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarBaseReport.xcu
@@ -0,0 +1,38 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Base) Report" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT EXPORT OWN DEFAULT 3RDPARTYFILTER NOTINFILEDIALOG</value>
+ </prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion">
+ <value>6800</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>StarBaseReport</value>
+ </prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.report.ReportDefinition</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Database Report</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarBaseReportChart.xcu b/filter/source/config/fragments/filters/StarBaseReportChart.xcu
new file mode 100644
index 000000000..86233ac14
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarBaseReportChart.xcu
@@ -0,0 +1,40 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Base) Report Chart" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT EXPORT OWN DEFAULT NOTINFILEDIALOG</value>
+ </prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService">
+ <value>com.sun.star.comp.chart2.report.XMLFilter</value>
+ </prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion">
+ <value>6800</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>StarBaseReportChart</value>
+ </prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.chart2.ChartDocument</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Report Chart</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarOffice_Drawing.xcu b/filter/source/config/fragments/filters/StarOffice_Drawing.xcu
new file mode 100644
index 000000000..f820fe096
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_Drawing.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="StarOffice_Drawing" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Draw.StarOfficeDrawImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy StarOffice Drawing</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>StarOffice_Drawing</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.drawing.DrawingDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/StarOffice_Presentation.xcu b/filter/source/config/fragments/filters/StarOffice_Presentation.xcu
new file mode 100644
index 000000000..7179379d7
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_Presentation.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="StarOffice_Presentation" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Impress.StarOfficePresentationImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy StarOffice Presentation</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>StarOffice_Presentation</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.presentation.PresentationDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/StarOffice_Spreadsheet.xcu b/filter/source/config/fragments/filters/StarOffice_Spreadsheet.xcu
new file mode 100644
index 000000000..d6ac85576
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_Spreadsheet.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="StarOffice_Spreadsheet" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Calc.StarOfficeCalcImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy StarOffice Spreadsheet</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>StarOffice_Spreadsheet</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.sheet.SpreadsheetDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/StarOffice_Writer.xcu b/filter/source/config/fragments/filters/StarOffice_Writer.xcu
new file mode 100644
index 000000000..9522d73b0
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_Writer.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="StarOffice_Writer" oor:op="replace">
+ <prop oor:name="Flags">
+ <value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value>
+ </prop>
+ <prop oor:name="FilterService">
+ <value>org.libreoffice.comp.Writer.StarOfficeWriterImportFilter</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Legacy StarOffice Text Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion">
+ <value>0</value>
+ </prop>
+ <prop oor:name="Type">
+ <value>StarOffice_Writer</value>
+ </prop>
+ <prop oor:name="DocumentService">
+ <value>com.sun.star.text.TextDocument</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/StarOffice_XML__Base_.xcu b/filter/source/config/fragments/filters/StarOffice_XML__Base_.xcu
new file mode 100644
index 000000000..344843043
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_XML__Base_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Base)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT OWN DEFAULT 3RDPARTYFILTER ENCRYPTION EXOTIC</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>StarBase</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sdb.OfficeDatabaseDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Database</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarOffice_XML__Calc_.xcu b/filter/source/config/fragments/filters/StarOffice_XML__Calc_.xcu
new file mode 100644
index 000000000..6f658cbdd
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_XML__Calc_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Calc)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE OWN ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>calc_StarOffice_XML_Calc</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Spreadsheet</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarOffice_XML__Chart_.xcu b/filter/source/config/fragments/filters/StarOffice_XML__Chart_.xcu
new file mode 100644
index 000000000..3ad0cb8c0
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_XML__Chart_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Chart)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT OWN ALIEN NOTINFILEDIALOG ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.chart2.XMLFilter</value></prop>
+ <prop oor:name="UserData"><value>XML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>chart_StarOffice_XML_Chart</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.chart2.ChartDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Chart</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarOffice_XML__Draw_.xcu b/filter/source/config/fragments/filters/StarOffice_XML__Draw_.xcu
new file mode 100644
index 000000000..9fdd62b9a
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_XML__Draw_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Draw)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE OWN ALIEN PREFERRED ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>XML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>draw_StarOffice_XML_Draw</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Drawing</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarOffice_XML__Impress_.xcu b/filter/source/config/fragments/filters/StarOffice_XML__Impress_.xcu
new file mode 100644
index 000000000..1a2c24d22
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_XML__Impress_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Impress)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE OWN ALIEN PREFERRED ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>XML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>impress_StarOffice_XML_Impress</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Presentation</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarOffice_XML__Math_.xcu b/filter/source/config/fragments/filters/StarOffice_XML__Math_.xcu
new file mode 100644
index 000000000..569eb570b
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_XML__Math_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Math)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE OWN ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>math_StarOffice_XML_Math</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.formula.FormulaProperties</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Formula</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/StarOffice_XML__Writer_.xcu b/filter/source/config/fragments/filters/StarOffice_XML__Writer_.xcu
new file mode 100644
index 000000000..ba7db694d
--- /dev/null
+++ b/filter/source/config/fragments/filters/StarOffice_XML__Writer_.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarOffice XML (Writer)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE OWN ALIEN PREFERRED ENCRYPTION EXOTIC</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>writer_StarOffice_XML_Writer</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Text Document</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/T602Document.xcu b/filter/source/config/fragments/filters/T602Document.xcu
new file mode 100644
index 000000000..bf8a68fa6
--- /dev/null
+++ b/filter/source/config/fragments/filters/T602Document.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="T602Document" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED EXOTIC</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.T602ImportFilter</value></prop>
+ <prop oor:name="UserData"><value>602</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">T602 Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_T602_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/TGA___Truevision_TARGA.xcu b/filter/source/config/fragments/filters/TGA___Truevision_TARGA.xcu
new file mode 100644
index 000000000..246c3f566
--- /dev/null
+++ b/filter/source/config/fragments/filters/TGA___Truevision_TARGA.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="TGA - Truevision TARGA" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">TGA - Truevision Targa</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>tga_Truevision_TARGA</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/TIF___Tag_Image_File.xcu b/filter/source/config/fragments/filters/TIF___Tag_Image_File.xcu
new file mode 100644
index 000000000..367159fb4
--- /dev/null
+++ b/filter/source/config/fragments/filters/TIF___Tag_Image_File.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="TIF - Tag Image File" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">TIFF - Tagged Image File Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>tif_Tag_Image_File</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Text.xcu b/filter/source/config/fragments/filters/Text.xcu
new file mode 100644
index 000000000..7ce06bcd1
--- /dev/null
+++ b/filter/source/config/fragments/filters/Text.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Text" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>TEXT</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="ExportExtension"><value>txt</value></prop>
+ <prop oor:name="Type"><value>generic_Text</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Text</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Text__StarWriter_Web_.xcu b/filter/source/config/fragments/filters/Text__StarWriter_Web_.xcu
new file mode 100644
index 000000000..e3d1658fb
--- /dev/null
+++ b/filter/source/config/fragments/filters/Text__StarWriter_Web_.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Text (StarWriter/Web)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>TEXT</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="ExportExtension"><value>txt</value></prop>
+ <prop oor:name="Type"><value>generic_Text</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Text (Writer/Web)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Text___txt___csv__StarCalc_.xcu b/filter/source/config/fragments/filters/Text___txt___csv__StarCalc_.xcu
new file mode 100644
index 000000000..886552c7e
--- /dev/null
+++ b/filter/source/config/fragments/filters/Text___txt___csv__StarCalc_.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Text - txt - csv (StarCalc)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Calc.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="ExportExtension"><value>csv</value></prop>
+ <prop oor:name="Type"><value>generic_Text</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Text CSV</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Text__encoded_.xcu b/filter/source/config/fragments/filters/Text__encoded_.xcu
new file mode 100644
index 000000000..f4c6f0d30
--- /dev/null
+++ b/filter/source/config/fragments/filters/Text__encoded_.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Text (encoded)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Writer.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>TEXT_DLG</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="ExportExtension"><value>txt</value></prop>
+ <prop oor:name="Type"><value>generic_Text</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Text - Choose Encoding</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Text__encoded___StarWriter_GlobalDocument_.xcu b/filter/source/config/fragments/filters/Text__encoded___StarWriter_GlobalDocument_.xcu
new file mode 100644
index 000000000..2b6a8b011
--- /dev/null
+++ b/filter/source/config/fragments/filters/Text__encoded___StarWriter_GlobalDocument_.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Text (encoded) (StarWriter/GlobalDocument)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Writer.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>TEXT_DLG</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="ExportExtension"><value>txt</value></prop>
+ <prop oor:name="Type"><value>generic_Text</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Text - Choose Encoding (Master Document)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/Text__encoded___StarWriter_Web_.xcu b/filter/source/config/fragments/filters/Text__encoded___StarWriter_Web_.xcu
new file mode 100644
index 000000000..4e2d92d89
--- /dev/null
+++ b/filter/source/config/fragments/filters/Text__encoded___StarWriter_Web_.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Text (encoded) (StarWriter/Web)" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Writer.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>TEXT_DLG</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="ExportExtension"><value>txt</value></prop>
+ <prop oor:name="Type"><value>generic_Text</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Text - Choose Encoding (Writer/Web)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/UOF_presentation.xcu b/filter/source/config/fragments/filters/UOF_presentation.xcu
new file mode 100644
index 000000000..1f8be437b
--- /dev/null
+++ b/filter/source/config/fragments/filters/UOF_presentation.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="UOF presentation" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>Unified_Office_Format_presentation</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Impress.XMLOasisImporter,com.sun.star.comp.Impress.XMLOasisExporter,../$(share_subdir_name)/xslt/import/uof/uof2odf_presentation.xsl,../$(share_subdir_name)/xslt/export/uof/odf2uof_presentation.xsl</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Unified Office Format presentation</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/UOF_spreadsheet.xcu b/filter/source/config/fragments/filters/UOF_spreadsheet.xcu
new file mode 100644
index 000000000..91f564307
--- /dev/null
+++ b/filter/source/config/fragments/filters/UOF_spreadsheet.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="UOF spreadsheet" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>Unified_Office_Format_spreadsheet</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Calc.XMLOasisImporter,com.sun.star.comp.Calc.XMLOasisExporter,../$(share_subdir_name)/xslt/import/uof/uof2odf_spreadsheet.xsl,../$(share_subdir_name)/xslt/export/uof/odf2uof_spreadsheet.xsl</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Unified Office Format spreadsheet</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/UOF_text.xcu b/filter/source/config/fragments/filters/UOF_text.xcu
new file mode 100644
index 000000000..e4241f175
--- /dev/null
+++ b/filter/source/config/fragments/filters/UOF_text.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="UOF text" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>Unified_Office_Format_text</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Writer.XMLOasisImporter,com.sun.star.comp.Writer.XMLOasisExporter,../$(share_subdir_name)/xslt/import/uof/uof2odf_text.xsl,../$(share_subdir_name)/xslt/export/uof/odf2uof_text.xsl</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Unified Office Format text</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/VisioDocument.xcu b/filter/source/config/fragments/filters/VisioDocument.xcu
new file mode 100644
index 000000000..3b43b24db
--- /dev/null
+++ b/filter/source/config/fragments/filters/VisioDocument.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Visio Document" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.VisioImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Visio 2000-2013</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_Visio_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/WEBP___WebP.xcu b/filter/source/config/fragments/filters/WEBP___WebP.xcu
new file mode 100644
index 000000000..9c650e3de
--- /dev/null
+++ b/filter/source/config/fragments/filters/WEBP___WebP.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="WEBP - WebP" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/WMF___MS_Windows_Metafile.xcu b/filter/source/config/fragments/filters/WMF___MS_Windows_Metafile.xcu
new file mode 100644
index 000000000..12c2034ae
--- /dev/null
+++ b/filter/source/config/fragments/filters/WMF___MS_Windows_Metafile.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="WMF - MS Windows Metafile" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WMF - Windows Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>wmf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/WPS_Lotus_Calc.xcu b/filter/source/config/fragments/filters/WPS_Lotus_Calc.xcu
new file mode 100644
index 000000000..1d141826c
--- /dev/null
+++ b/filter/source/config/fragments/filters/WPS_Lotus_Calc.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="WPS_Lotus_Calc" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Calc.MSWorksCalcImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Lotus Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_WPS_Lotus_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/WPS_QPro_Calc.xcu b/filter/source/config/fragments/filters/WPS_QPro_Calc.xcu
new file mode 100644
index 000000000..f32b11820
--- /dev/null
+++ b/filter/source/config/fragments/filters/WPS_QPro_Calc.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="WPS_QPro_Calc" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Calc.MSWorksCalcImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">QuattroPro Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_WPS_QPro_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/WordPerfect.xcu b/filter/source/config/fragments/filters/WordPerfect.xcu
new file mode 100644
index 000000000..d26c30369
--- /dev/null
+++ b/filter/source/config/fragments/filters/WordPerfect.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="WordPerfect" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.WordPerfectImportFilter</value></prop>
+ <prop oor:name="UserData"><value>WPD</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WordPerfect Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_WordPerfect_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/WordPerfectGraphics.xcu b/filter/source/config/fragments/filters/WordPerfectGraphics.xcu
new file mode 100644
index 000000000..54f4f43db
--- /dev/null
+++ b/filter/source/config/fragments/filters/WordPerfectGraphics.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="WordPerfect Graphics" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.WPGImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WordPerfect Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_WordPerfect_Graphics</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/WriteNow.xcu b/filter/source/config/fragments/filters/WriteNow.xcu
new file mode 100644
index 000000000..600e5d617
--- /dev/null
+++ b/filter/source/config/fragments/filters/WriteNow.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="WriteNow" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WriteNow Document</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_WriteNow</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/XBM___X_Consortium.xcu b/filter/source/config/fragments/filters/XBM___X_Consortium.xcu
new file mode 100644
index 000000000..56d3ff5a9
--- /dev/null
+++ b/filter/source/config/fragments/filters/XBM___X_Consortium.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="XBM - X-Consortium" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">XBM - X Bitmap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>xbm_X_Consortium</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/XHTML_Calc_File.xcu b/filter/source/config/fragments/filters/XHTML_Calc_File.xcu
new file mode 100644
index 000000000..a13b05dc9
--- /dev/null
+++ b/filter/source/config/fragments/filters/XHTML_Calc_File.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="XHTML Calc File" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>XHTML_File</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Calc.XMLOasisImporter,com.sun.star.comp.Calc.XMLOasisExporter,,../$(share_subdir_name)/xslt/export/xhtml/opendoc2xhtml.xsl</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value>XHTML</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/XHTML_Draw_File.xcu b/filter/source/config/fragments/filters/XHTML_Draw_File.xcu
new file mode 100644
index 000000000..c63283a4e
--- /dev/null
+++ b/filter/source/config/fragments/filters/XHTML_Draw_File.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="XHTML Draw File" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>XHTML_File</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Draw.XMLOasisImporter,com.sun.star.comp.Draw.XMLOasisExporter,,../$(share_subdir_name)/xslt/export/xhtml/opendoc2xhtml.xsl</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value>XHTML</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/XHTML_Impress_File.xcu b/filter/source/config/fragments/filters/XHTML_Impress_File.xcu
new file mode 100644
index 000000000..f8431fe16
--- /dev/null
+++ b/filter/source/config/fragments/filters/XHTML_Impress_File.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="XHTML Impress File" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>XHTML_File</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Impress.XMLOasisImporter,com.sun.star.comp.Impress.XMLOasisExporter,,../$(share_subdir_name)/xslt/export/xhtml/opendoc2xhtml.xsl</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value>XHTML</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/XHTML_Writer_File.xcu b/filter/source/config/fragments/filters/XHTML_Writer_File.xcu
new file mode 100644
index 000000000..e50ec3077
--- /dev/null
+++ b/filter/source/config/fragments/filters/XHTML_Writer_File.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="XHTML Writer File" oor:op="replace">
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>XHTML_File</value></prop>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UserData"><value oor:separator=",">com.sun.star.documentconversion.XSLTFilter,,com.sun.star.comp.Writer.XMLOasisImporter,com.sun.star.comp.Writer.XMLOasisExporter,,../$(share_subdir_name)/xslt/export/xhtml/opendoc2xhtml.xsl,,true</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.XmlFilterAdaptor</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="UIName">
+ <value>XHTML</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/XPM.xcu b/filter/source/config/fragments/filters/XPM.xcu
new file mode 100644
index 000000000..8a67b710f
--- /dev/null
+++ b/filter/source/config/fragments/filters/XPM.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="XPM" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN EXOTIC</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">XPM - X PixMap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>xpm_XPM</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/ZMFDocument.xcu b/filter/source/config/fragments/filters/ZMFDocument.xcu
new file mode 100644
index 000000000..b72449df3
--- /dev/null
+++ b/filter/source/config/fragments/filters/ZMFDocument.xcu
@@ -0,0 +1,13 @@
+ <node oor:name="ZMF Document" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>org.libreoffice.comp.Draw.ZMFImportFilter</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Zoner Callisto/Draw</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>draw_ZMF_Document</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc8.xcu b/filter/source/config/fragments/filters/calc8.xcu
new file mode 100644
index 000000000..e6f0d6251
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc8.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc8" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE OWN DEFAULT ENCRYPTION PASSWORDTOMODIFY GPGENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>calc8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Spreadsheet</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc8_template.xcu b/filter/source/config/fragments/filters/calc8_template.xcu
new file mode 100644
index 000000000..4752a45f1
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc8_template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc8_template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE TEMPLATEPATH OWN ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>calc8_template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Spreadsheet Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_Gnumeric.xcu b/filter/source/config/fragments/filters/calc_Gnumeric.xcu
new file mode 100644
index 000000000..cc350fd62
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_Gnumeric.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Gnumeric Spreadsheet" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"/>
+ <prop oor:name="Type"><value>Gnumeric XML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Gnumeric Spreadsheet</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/calc_HTML_WebQuery.xcu b/filter/source/config/fragments/filters/calc_HTML_WebQuery.xcu
new file mode 100644
index 000000000..c91d92880
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_HTML_WebQuery.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_HTML_WebQuery" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN USEOPTIONS PREFERRED</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Calc.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>generic_HTML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Web Page Query (Calc)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_MS_Excel_2007_Binary.xcu b/filter/source/config/fragments/filters/calc_MS_Excel_2007_Binary.xcu
new file mode 100644
index 000000000..24743cf86
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_MS_Excel_2007_Binary.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Calc MS Excel 2007 Binary" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.xls.ExcelFilter</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>MS Excel 2007 Binary</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 2007 Binary</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_MS_Excel_2007_VBA_XML.xcu b/filter/source/config/fragments/filters/calc_MS_Excel_2007_VBA_XML.xcu
new file mode 100644
index 000000000..ffeee2c63
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_MS_Excel_2007_VBA_XML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Calc MS Excel 2007 VBA XML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.xls.ExcelFilter</value></prop>
+ <prop oor:name="UserData"><value>macro-enabled</value></prop>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>MS Excel 2007 VBA XML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Excel 2007–365 (macro-enabled)</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/calc_MS_Excel_2007_XML.xcu b/filter/source/config/fragments/filters/calc_MS_Excel_2007_XML.xcu
new file mode 100644
index 000000000..bc0ab95e2
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_MS_Excel_2007_XML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Calc MS Excel 2007 XML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED ENCRYPTION PASSWORDTOMODIFY SUPPORTSSIGNING</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.xls.ExcelFilter</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>MS Excel 2007 XML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Excel 2007–365</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/calc_MS_Excel_2007_XML_Template.xcu b/filter/source/config/fragments/filters/calc_MS_Excel_2007_XML_Template.xcu
new file mode 100644
index 000000000..515b89152
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_MS_Excel_2007_XML_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Calc MS Excel 2007 XML Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER TEMPLATE TEMPLATEPATH</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.xls.ExcelFilter</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>MS Excel 2007 XML Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Excel 2007–365 Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_OOXML.xcu b/filter/source/config/fragments/filters/calc_OOXML.xcu
new file mode 100644
index 000000000..2bc098129
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_OOXML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Calc Office Open XML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.xls.ExcelFilter</value></prop>
+ <prop oor:name="UserData"><value>OOXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>1</value></prop>
+ <prop oor:name="Type"><value>Office Open XML Spreadsheet</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Office Open XML Spreadsheet</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_OOXML_Template.xcu b/filter/source/config/fragments/filters/calc_OOXML_Template.xcu
new file mode 100644
index 000000000..b65a75608
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_OOXML_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Calc Office Open XML Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER TEMPLATE TEMPLATEPATH</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.xls.ExcelFilter</value></prop>
+ <prop oor:name="UserData"><value>OOXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>1</value></prop>
+ <prop oor:name="Type"><value>Office Open XML Spreadsheet Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Office Open XML Spreadsheet Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_StarOffice_XML_Calc_Template.xcu b/filter/source/config/fragments/filters/calc_StarOffice_XML_Calc_Template.xcu
new file mode 100644
index 000000000..3c05efa39
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_StarOffice_XML_Calc_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_StarOffice_XML_Calc_Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE TEMPLATEPATH OWN ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>calc_StarOffice_XML_Calc_Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Spreadsheet Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_jpg_Export.xcu b/filter/source/config/fragments/filters/calc_jpg_Export.xcu
new file mode 100644
index 000000000..80a72878f
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_jpg_Export.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="calc_jpg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>jpg_JPEG</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_pdf_Export.xcu b/filter/source/config/fragments/filters/calc_pdf_Export.xcu
new file mode 100644
index 000000000..897d6ddb7
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_pdf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_pdf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.PDF.PDFDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.PDF.PDFFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_png_Export.xcu b/filter/source/config/fragments/filters/calc_png_Export.xcu
new file mode 100644
index 000000000..bdc49e484
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_png_Export.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="calc_png_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PNG - Portable Network Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>png_Portable_Network_Graphic</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_svg_Export.xcu b/filter/source/config/fragments/filters/calc_svg_Export.xcu
new file mode 100644
index 000000000..703ce82e9
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_svg_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_svg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER INTERNAL NOTINFILEDIALOG</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/calc_webp_Export.xcu b/filter/source/config/fragments/filters/calc_webp_Export.xcu
new file mode 100644
index 000000000..a6e5d18a3
--- /dev/null
+++ b/filter/source/config/fragments/filters/calc_webp_Export.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="calc_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/chart8.xcu b/filter/source/config/fragments/filters/chart8.xcu
new file mode 100644
index 000000000..6bcfbd88d
--- /dev/null
+++ b/filter/source/config/fragments/filters/chart8.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="chart8" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT OWN DEFAULT NOTINFILEDIALOG NOTINCHOOSER PREFERRED ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.chart2.XMLFilter</value></prop>
+ <prop oor:name="UserData"><value>XML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>chart8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.chart2.ChartDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Chart</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/dBase.xcu b/filter/source/config/fragments/filters/dBase.xcu
new file mode 100644
index 000000000..59aaf31a9
--- /dev/null
+++ b/filter/source/config/fragments/filters/dBase.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="dBase" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.Calc.FilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">dBASE</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>calc_dBase</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.sheet.SpreadsheetDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw8.xcu b/filter/source/config/fragments/filters/draw8.xcu
new file mode 100644
index 000000000..3a9656ec4
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw8.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw8" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE OWN DEFAULT PREFERRED ENCRYPTION PASSWORDTOMODIFY GPGENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>XML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>draw8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Drawing</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw8_template.xcu b/filter/source/config/fragments/filters/draw8_template.xcu
new file mode 100644
index 000000000..ac4f262d5
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw8_template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw8_template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE TEMPLATEPATH OWN ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLV</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>draw8_template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Drawing Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base.xcu b/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base.xcu
new file mode 100644
index 000000000..a19508c37
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_PCD_Photo_CD_Base" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCD - Kodak Photo CD (768x512)</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pcd_Photo_CD_Base</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base16.xcu b/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base16.xcu
new file mode 100644
index 000000000..54fc3855d
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base16.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_PCD_Photo_CD_Base16" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCD - Kodak Photo CD (192x128)</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pcd_Photo_CD_Base16</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base4.xcu b/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base4.xcu
new file mode 100644
index 000000000..1674a92c0
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_PCD_Photo_CD_Base4.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_PCD_Photo_CD_Base4" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCD - Kodak Photo CD (384x256)</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pcd_Photo_CD_Base4</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_StarOffice_XML_Draw_Template.xcu b/filter/source/config/fragments/filters/draw_StarOffice_XML_Draw_Template.xcu
new file mode 100644
index 000000000..783027713
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_StarOffice_XML_Draw_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_StarOffice_XML_Draw_Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE TEMPLATEPATH OWN ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLV</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>draw_StarOffice_XML_Draw_Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Drawing Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_bmp_Export.xcu b/filter/source/config/fragments/filters/draw_bmp_Export.xcu
new file mode 100644
index 000000000..66f790853
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_bmp_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_bmp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">BMP - Windows Bitmap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>bmp_MS_Windows</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_emf_Export.xcu b/filter/source/config/fragments/filters/draw_emf_Export.xcu
new file mode 100644
index 000000000..b8d95ca8d
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_emf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_emf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EMF - Enhanced Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>emf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_eps_Export.xcu b/filter/source/config/fragments/filters/draw_eps_Export.xcu
new file mode 100644
index 000000000..821271e8b
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_eps_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_eps_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EPS - Encapsulated PostScript</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>eps_Encapsulated_PostScript</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_gif_Export.xcu b/filter/source/config/fragments/filters/draw_gif_Export.xcu
new file mode 100644
index 000000000..b86f272e3
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_gif_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_gif_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">GIF - Graphics Interchange Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>gif_Graphics_Interchange</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_html_Export.xcu b/filter/source/config/fragments/filters/draw_html_Export.xcu
new file mode 100644
index 000000000..179c7bb7e
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_html_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_html_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.draw.SdHtmlOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>graphic_HTML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">HTML Document (Draw)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_jpg_Export.xcu b/filter/source/config/fragments/filters/draw_jpg_Export.xcu
new file mode 100644
index 000000000..67b64bbf9
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_jpg_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_jpg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>jpg_JPEG</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_pdf_Export.xcu b/filter/source/config/fragments/filters/draw_pdf_Export.xcu
new file mode 100644
index 000000000..89816e454
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_pdf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_pdf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.PDF.PDFDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.PDF.PDFFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_png_Export.xcu b/filter/source/config/fragments/filters/draw_png_Export.xcu
new file mode 100644
index 000000000..5ba112cc5
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_png_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_png_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PNG - Portable Network Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>png_Portable_Network_Graphic</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_svg_Export.xcu b/filter/source/config/fragments/filters/draw_svg_Export.xcu
new file mode 100644
index 000000000..c7816f3d7
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_svg_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_svg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_tif_Export.xcu b/filter/source/config/fragments/filters/draw_tif_Export.xcu
new file mode 100644
index 000000000..43bae82fd
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_tif_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_tif_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">TIFF - Tagged Image File Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>tif_Tag_Image_File</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_webp_Export.xcu b/filter/source/config/fragments/filters/draw_webp_Export.xcu
new file mode 100644
index 000000000..e6da69197
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_webp_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/draw_wmf_Export.xcu b/filter/source/config/fragments/filters/draw_wmf_Export.xcu
new file mode 100644
index 000000000..308cd9bee
--- /dev/null
+++ b/filter/source/config/fragments/filters/draw_wmf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_wmf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WMF - Windows Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>wmf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress8.xcu b/filter/source/config/fragments/filters/impress8.xcu
new file mode 100644
index 000000000..527d83ed0
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress8.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress8" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE OWN DEFAULT PREFERRED ENCRYPTION PASSWORDTOMODIFY GPGENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>XML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>impress8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Presentation</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress8_draw.xcu b/filter/source/config/fragments/filters/impress8_draw.xcu
new file mode 100644
index 000000000..1f3e53c97
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress8_draw.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress8_draw" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE OWN ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>XML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>draw8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Drawing (Impress)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress8_template.xcu b/filter/source/config/fragments/filters/impress8_template.xcu
new file mode 100644
index 000000000..e2f4393d9
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress8_template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress8_template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE TEMPLATEPATH OWN ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLV</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>impress8_template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Presentation Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML.xcu b/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML.xcu
new file mode 100644
index 000000000..446316310
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Impress MS PowerPoint 2007 XML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED ENCRYPTION PASSWORDTOMODIFY SUPPORTSSIGNING</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.ppt.PowerPointImport</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>MS PowerPoint 2007 XML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PowerPoint 2007–365</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_AutoPlay.xcu b/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_AutoPlay.xcu
new file mode 100644
index 000000000..c5e5e767f
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_AutoPlay.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Impress MS PowerPoint 2007 XML AutoPlay" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED STARTPRESENTATION ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.ppt.PowerPointImport</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName"><value xml:lang="en-US">PowerPoint 2007–365 AutoPlay</value></prop>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>MS PowerPoint 2007 XML AutoPlay</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_Template.xcu b/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_Template.xcu
new file mode 100644
index 000000000..cba3ea325
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_Template.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Impress MS PowerPoint 2007 XML Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER TEMPLATE TEMPLATEPATH PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.ppt.PowerPointImport</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName"><value xml:lang="en-US">PowerPoint 2007–365 Template</value></prop>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>MS PowerPoint 2007 XML Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_VBA.xcu b/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_VBA.xcu
new file mode 100644
index 000000000..de44648c5
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_MS_PowerPoint_2007_XML_VBA.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Impress MS PowerPoint 2007 XML VBA" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED ENCRYPTION PASSWORDTOMODIFY SUPPORTSSIGNING</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.ppt.PowerPointImport</value></prop>
+ <prop oor:name="UserData"><value>macro-enabled</value></prop>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>MS PowerPoint 2007 XML VBA</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PowerPoint 2007–365 VBA</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/filters/impress_OOXML.xcu b/filter/source/config/fragments/filters/impress_OOXML.xcu
new file mode 100644
index 000000000..c585e4b26
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_OOXML.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Impress Office Open XML" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.ppt.PowerPointImport</value></prop>
+ <prop oor:name="UserData"><value>OOXML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Office Open XML Presentation</value></prop>
+ <!-- ISO/IEC 29500:2008 -->
+ <prop oor:name="FileFormatVersion"><value>1</value></prop>
+ <prop oor:name="Type"><value>Office Open XML Presentation</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/impress_OOXML_AutoPlay.xcu b/filter/source/config/fragments/filters/impress_OOXML_AutoPlay.xcu
new file mode 100644
index 000000000..dbadb8bd2
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_OOXML_AutoPlay.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Impress Office Open XML AutoPlay" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER PREFERRED STARTPRESENTATION ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.ppt.PowerPointImport</value></prop>
+ <prop oor:name="UserData"/>
+ <prop oor:name="UIName"><value xml:lang="en-US">Office Open XML Presentation AutoPlay</value></prop>
+ <prop oor:name="FileFormatVersion"/>
+ <prop oor:name="Type"><value>Office Open XML Presentation AutoPlay</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/impress_OOXML_Template.xcu b/filter/source/config/fragments/filters/impress_OOXML_Template.xcu
new file mode 100644
index 000000000..b0ce4c8ef
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_OOXML_Template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Impress Office Open XML Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT ALIEN 3RDPARTYFILTER TEMPLATE TEMPLATEPATH PREFERRED</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.oox.ppt.PowerPointImport</value></prop>
+ <prop oor:name="UserData"><value>OOXML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Office Open XML Presentation Template</value></prop>
+ <!-- ISO/IEC 29500:2008 -->
+ <prop oor:name="FileFormatVersion"><value>1</value></prop>
+ <prop oor:name="Type"><value>Office Open XML Presentation Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/impress_StarOffice_XML_Draw.xcu b/filter/source/config/fragments/filters/impress_StarOffice_XML_Draw.xcu
new file mode 100644
index 000000000..65ac76df6
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_StarOffice_XML_Draw.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_StarOffice_XML_Draw" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE OWN ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>XML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>draw_StarOffice_XML_Draw</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Drawing (Impress)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_StarOffice_XML_Impress_Template.xcu b/filter/source/config/fragments/filters/impress_StarOffice_XML_Impress_Template.xcu
new file mode 100644
index 000000000..02c142e66
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_StarOffice_XML_Impress_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_StarOffice_XML_Impress_Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE TEMPLATEPATH OWN ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLV</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>impress_StarOffice_XML_Impress_Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Presentation Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_bmp_Export.xcu b/filter/source/config/fragments/filters/impress_bmp_Export.xcu
new file mode 100644
index 000000000..2cb2aba76
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_bmp_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_bmp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">BMP - Windows Bitmap</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>bmp_MS_Windows</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_emf_Export.xcu b/filter/source/config/fragments/filters/impress_emf_Export.xcu
new file mode 100644
index 000000000..d90db357a
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_emf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_emf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EMF - Enhanced Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>emf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_eps_Export.xcu b/filter/source/config/fragments/filters/impress_eps_Export.xcu
new file mode 100644
index 000000000..6256970d1
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_eps_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_eps_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EPS - Encapsulated PostScript</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>eps_Encapsulated_PostScript</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_gif_Export.xcu b/filter/source/config/fragments/filters/impress_gif_Export.xcu
new file mode 100644
index 000000000..874770a85
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_gif_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_gif_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">GIF - Graphics Interchange Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>gif_Graphics_Interchange</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_html_Export.xcu b/filter/source/config/fragments/filters/impress_html_Export.xcu
new file mode 100644
index 000000000..65a5c5dad
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_html_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_html_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.draw.SdHtmlOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>graphic_HTML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">HTML Document (Impress)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_jpg_Export.xcu b/filter/source/config/fragments/filters/impress_jpg_Export.xcu
new file mode 100644
index 000000000..edbeee1b1
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_jpg_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_jpg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>jpg_JPEG</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_pdf_Export.xcu b/filter/source/config/fragments/filters/impress_pdf_Export.xcu
new file mode 100644
index 000000000..b95554753
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_pdf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_pdf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.PDF.PDFDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.PDF.PDFFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_png_Export.xcu b/filter/source/config/fragments/filters/impress_png_Export.xcu
new file mode 100644
index 000000000..f2de7528d
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_png_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_png_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PNG - Portable Network Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>png_Portable_Network_Graphic</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_svg_Export.xcu b/filter/source/config/fragments/filters/impress_svg_Export.xcu
new file mode 100644
index 000000000..21cb8aec2
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_svg_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_svg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_tif_Export.xcu b/filter/source/config/fragments/filters/impress_tif_Export.xcu
new file mode 100644
index 000000000..4951d6fcb
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_tif_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_tif_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">TIFF - Tagged Image File Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>tif_Tag_Image_File</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_webp_Export.xcu b/filter/source/config/fragments/filters/impress_webp_Export.xcu
new file mode 100644
index 000000000..00284a272
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_webp_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/impress_wmf_Export.xcu b/filter/source/config/fragments/filters/impress_wmf_Export.xcu
new file mode 100644
index 000000000..dbb65bdaf
--- /dev/null
+++ b/filter/source/config/fragments/filters/impress_wmf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_wmf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN SUPPORTSSELECTION</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WMF - Windows Metafile</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>wmf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.presentation.PresentationDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/math8.xcu b/filter/source/config/fragments/filters/math8.xcu
new file mode 100644
index 000000000..0287f7ffa
--- /dev/null
+++ b/filter/source/config/fragments/filters/math8.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="math8" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE OWN DEFAULT ENCRYPTION GPGENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>math8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.formula.FormulaProperties</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Formula</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/math_pdf_Export.xcu b/filter/source/config/fragments/filters/math_pdf_Export.xcu
new file mode 100644
index 000000000..dd81c453b
--- /dev/null
+++ b/filter/source/config/fragments/filters/math_pdf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="math_pdf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.PDF.PDFDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.PDF.PDFFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.formula.FormulaProperties</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/mov__MOV.xcu b/filter/source/config/fragments/filters/mov__MOV.xcu
new file mode 100644
index 000000000..168188449
--- /dev/null
+++ b/filter/source/config/fragments/filters/mov__MOV.xcu
@@ -0,0 +1,21 @@
+<!--
+ * 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/.
+ *
+-->
+ <node oor:name="MOV - MOV" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">MOV - QuickTime File Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>mov_MOV</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.drawing.DrawingDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer8.xcu b/filter/source/config/fragments/filters/writer8.xcu
new file mode 100644
index 000000000..def9d57d5
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer8.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer8" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE OWN DEFAULT PREFERRED ENCRYPTION PASSWORDTOMODIFY GPGENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>writer8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Text Document</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer8_template.xcu b/filter/source/config/fragments/filters/writer8_template.xcu
new file mode 100644
index 000000000..286b907a7
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer8_template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer8_template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE TEMPLATEPATH OWN ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLV</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>writer8_template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Text Document Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_MIZI_Hwp_97.xcu b/filter/source/config/fragments/filters/writer_MIZI_Hwp_97.xcu
new file mode 100644
index 000000000..2b717c8cb
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_MIZI_Hwp_97.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MIZI_Hwp_97" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT ALIEN 3RDPARTYFILTER EXOTIC</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.comp.hwpimport.HwpImportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Hangul WP 97</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_MIZI_Hwp_97</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_StarOffice_XML_Writer_Template.xcu b/filter/source/config/fragments/filters/writer_StarOffice_XML_Writer_Template.xcu
new file mode 100644
index 000000000..fc0066a4c
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_StarOffice_XML_Writer_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_StarOffice_XML_Writer_Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE TEMPLATEPATH OWN ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLV</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>writer_StarOffice_XML_Writer_Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Text Document Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_globaldocument_StarOffice_XML_Writer.xcu b/filter/source/config/fragments/filters/writer_globaldocument_StarOffice_XML_Writer.xcu
new file mode 100644
index 000000000..a01a61c5c
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_globaldocument_StarOffice_XML_Writer.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_globaldocument_StarOffice_XML_Writer" oor:op="replace">
+ <prop oor:name="Flags"><value>TEMPLATE ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>writer_StarOffice_XML_Writer</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Text Document</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_globaldocument_StarOffice_XML_Writer_GlobalDocument.xcu b/filter/source/config/fragments/filters/writer_globaldocument_StarOffice_XML_Writer_GlobalDocument.xcu
new file mode 100644
index 000000000..015aefe17
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_globaldocument_StarOffice_XML_Writer_GlobalDocument.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_globaldocument_StarOffice_XML_Writer_GlobalDocument" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE OWN ALIEN PREFERRED ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>writer_globaldocument_StarOffice_XML_Writer_GlobalDocument</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Master Document</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_globaldocument_pdf_Export.xcu b/filter/source/config/fragments/filters/writer_globaldocument_pdf_Export.xcu
new file mode 100644
index 000000000..93b9306e9
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_globaldocument_pdf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_globaldocument_pdf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.PDF.PDFDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.PDF.PDFFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_indexing_export.xcu b/filter/source/config/fragments/filters/writer_indexing_export.xcu
new file mode 100644
index 000000000..28cbe5b5b
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_indexing_export.xcu
@@ -0,0 +1,22 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="writer_indexing_export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.IndexingExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Writer Indexing Export XML</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_indexing_export_xml</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+</node>
diff --git a/filter/source/config/fragments/filters/writer_jpg_Export.xcu b/filter/source/config/fragments/filters/writer_jpg_Export.xcu
new file mode 100644
index 000000000..f3b1be924
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_jpg_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_jpg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>jpg_JPEG</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_layout_dump.xcu b/filter/source/config/fragments/filters/writer_layout_dump.xcu
new file mode 100644
index 000000000..e7ae50bcf
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_layout_dump.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_layout_dump" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Writer.LayoutDump</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Writer Layout XML</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_layout_dump_xml</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_pdf_Export.xcu b/filter/source/config/fragments/filters/writer_pdf_Export.xcu
new file mode 100644
index 000000000..749c28504
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_pdf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_pdf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.PDF.PDFDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.PDF.PDFFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_png_Export.xcu b/filter/source/config/fragments/filters/writer_png_Export.xcu
new file mode 100644
index 000000000..1ea189ee6
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_png_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_png_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PNG - Portable Network Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>png_Portable_Network_Graphic</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_svg_Export.xcu b/filter/source/config/fragments/filters/writer_svg_Export.xcu
new file mode 100644
index 000000000..c08576cdd
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_svg_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_svg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER INTERNAL NOTINFILEDIALOG</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_web_HTML_help.xcu b/filter/source/config/fragments/filters/writer_web_HTML_help.xcu
new file mode 100644
index 000000000..4e3cb6a6c
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_web_HTML_help.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_web_HTML_help" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT INTERNAL NOTINFILEDIALOG READONLY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>HTML_HELP</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Help content</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>writer_web_HTML_help</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_web_StarOffice_XML_Writer.xcu b/filter/source/config/fragments/filters/writer_web_StarOffice_XML_Writer.xcu
new file mode 100644
index 000000000..5cfbfc891
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_web_StarOffice_XML_Writer.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_web_StarOffice_XML_Writer" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT TEMPLATE ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>writer_StarOffice_XML_Writer</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 Text Document (Writer/Web)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_web_StarOffice_XML_Writer_Web_Template.xcu b/filter/source/config/fragments/filters/writer_web_StarOffice_XML_Writer_Web_Template.xcu
new file mode 100644
index 000000000..70b6a8f59
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_web_StarOffice_XML_Writer_Web_Template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_web_StarOffice_XML_Writer_Web_Template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT TEMPLATE TEMPLATEPATH OWN ALIEN ENCRYPTION</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLVWEB</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6200</value></prop>
+ <prop oor:name="Type"><value>writer_web_StarOffice_XML_Writer_Web_Template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenOffice.org 1.0 HTML Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_web_jpg_Export.xcu b/filter/source/config/fragments/filters/writer_web_jpg_Export.xcu
new file mode 100644
index 000000000..ddcc62b36
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_web_jpg_Export.xcu
@@ -0,0 +1,21 @@
+<!--
+ * 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/.
+ *
+-->
+ <node oor:name="writer_web_jpg_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>jpg_JPEG</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_web_pdf_Export.xcu b/filter/source/config/fragments/filters/writer_web_pdf_Export.xcu
new file mode 100644
index 000000000..00f86e544
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_web_pdf_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_web_pdf_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.comp.PDF.PDFDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.PDF.PDFFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_web_png_Export.xcu b/filter/source/config/fragments/filters/writer_web_png_Export.xcu
new file mode 100644
index 000000000..4c44173bf
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_web_png_Export.xcu
@@ -0,0 +1,21 @@
+<!--
+ * 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/.
+ *
+-->
+ <node oor:name="writer_web_png_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PNG - Portable Network Graphics</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>png_Portable_Network_Graphic</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_web_webp_Export.xcu b/filter/source/config/fragments/filters/writer_web_webp_Export.xcu
new file mode 100644
index 000000000..5273bb722
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_web_webp_Export.xcu
@@ -0,0 +1,21 @@
+<!--
+ * 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/.
+ *
+-->
+ <node oor:name="writer_web_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writer_webp_Export.xcu b/filter/source/config/fragments/filters/writer_webp_Export.xcu
new file mode 100644
index 000000000..ceb56a8c0
--- /dev/null
+++ b/filter/source/config/fragments/filters/writer_webp_Export.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_webp_Export" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN 3RDPARTYFILTER</value></prop>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="FilterService"><value>com.sun.star.comp.GraphicExportFilter</value></prop>
+ <prop oor:name="UserData"><value></value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.TextDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writerglobal8.xcu b/filter/source/config/fragments/filters/writerglobal8.xcu
new file mode 100644
index 000000000..ea2594d07
--- /dev/null
+++ b/filter/source/config/fragments/filters/writerglobal8.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writerglobal8" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE OWN PREFERRED ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>writerglobal8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Master Document</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writerglobal8_HTML.xcu b/filter/source/config/fragments/filters/writerglobal8_HTML.xcu
new file mode 100644
index 000000000..1e8534a86
--- /dev/null
+++ b/filter/source/config/fragments/filters/writerglobal8_HTML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writerglobal8_HTML" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT ALIEN</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>HTML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>0</value></prop>
+ <prop oor:name="Type"><value>generic_HTML</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">HTML (Writer/Global)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writerglobal8_template.xcu b/filter/source/config/fragments/filters/writerglobal8_template.xcu
new file mode 100644
index 000000000..699006015
--- /dev/null
+++ b/filter/source/config/fragments/filters/writerglobal8_template.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="writerglobal8_template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE TEMPLATEPATH OWN ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLV</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>writerglobal8_template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Master Document Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writerglobal8_writer.xcu b/filter/source/config/fragments/filters/writerglobal8_writer.xcu
new file mode 100644
index 000000000..24d06b212
--- /dev/null
+++ b/filter/source/config/fragments/filters/writerglobal8_writer.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writerglobal8_writer" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT TEMPLATE DEFAULT ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>writer8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.GlobalDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ODF Text Document</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writerweb8_writer.xcu b/filter/source/config/fragments/filters/writerweb8_writer.xcu
new file mode 100644
index 000000000..7e18ba6d9
--- /dev/null
+++ b/filter/source/config/fragments/filters/writerweb8_writer.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writerweb8_writer" oor:op="replace">
+ <prop oor:name="Flags"><value>EXPORT TEMPLATE ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXML</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>writer8</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Text (Writer/Web)</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/filters/writerweb8_writer_template.xcu b/filter/source/config/fragments/filters/writerweb8_writer_template.xcu
new file mode 100644
index 000000000..b6e9bbd3d
--- /dev/null
+++ b/filter/source/config/fragments/filters/writerweb8_writer_template.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writerweb8_writer_template" oor:op="replace">
+ <prop oor:name="Flags"><value>IMPORT EXPORT TEMPLATE TEMPLATEPATH OWN ENCRYPTION PASSWORDTOMODIFY</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="FilterService"/>
+ <prop oor:name="UserData"><value>CXMLVWEB</value></prop>
+ <prop oor:name="FileFormatVersion"><value>6800</value></prop>
+ <prop oor:name="Type"><value>writerweb8_writer_template</value></prop>
+ <prop oor:name="TemplateName"/>
+ <prop oor:name="DocumentService"><value>com.sun.star.text.WebDocument</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">HTML Document Template</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/frameloaders/com_sun_star_comp_chart2_ChartFrameLoader.xcu b/filter/source/config/fragments/frameloaders/com_sun_star_comp_chart2_ChartFrameLoader.xcu
new file mode 100644
index 000000000..0234d59ed
--- /dev/null
+++ b/filter/source/config/fragments/frameloaders/com_sun_star_comp_chart2_ChartFrameLoader.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="com.sun.star.comp.chart2.ChartFrameLoader" oor:op="replace" oor:finalized="true" oor:mandatory="true">
+ <prop oor:name="Types"><value>chart_StarOffice_XML_Chart chart8 chart_StarChart_50 chart_StarChart_40 chart_StarChart_30</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/frameloaders/com_sun_star_frame_Bibliography.xcu b/filter/source/config/fragments/frameloaders/com_sun_star_frame_Bibliography.xcu
new file mode 100644
index 000000000..b7d53d62e
--- /dev/null
+++ b/filter/source/config/fragments/frameloaders/com_sun_star_frame_Bibliography.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="com.sun.star.frame.Bibliography" oor:op="replace" >
+ <prop oor:name="Types"><value>component_Bibliography</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/frameloaders/com_sun_star_sdb_ContentLoader.xcu b/filter/source/config/fragments/frameloaders/com_sun_star_sdb_ContentLoader.xcu
new file mode 100644
index 000000000..6d10acbad
--- /dev/null
+++ b/filter/source/config/fragments/frameloaders/com_sun_star_sdb_ContentLoader.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="com.sun.star.sdb.ContentLoader" oor:op="replace" >
+ <prop oor:name="Types"><value>component_DB</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/frameloaders/org_openoffice_comp_dbflt_DBContentLoader2.xcu b/filter/source/config/fragments/frameloaders/org_openoffice_comp_dbflt_DBContentLoader2.xcu
new file mode 100644
index 000000000..62b6a6eee
--- /dev/null
+++ b/filter/source/config/fragments/frameloaders/org_openoffice_comp_dbflt_DBContentLoader2.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="org.openoffice.comp.dbflt.DBContentLoader2" oor:op="replace">
+ <prop oor:name="Types"><value>StarBase</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/bmp_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/bmp_Export.xcu
new file mode 100644
index 000000000..250504108
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/bmp_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="bmp_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>bmp_MS_Windows</value></prop>
+ <prop oor:name="FormatName"><value>SVBMP</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">BMP - Windows Bitmap</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/bmp_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/bmp_Import.xcu
new file mode 100644
index 000000000..7b5c54a64
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/bmp_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="bmp_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>bmp_MS_Windows</value></prop>
+ <prop oor:name="FormatName"><value>SVBMP</value></prop>
+ <prop oor:name="RealFilterName"><value>BMP - MS Windows</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">BMP - Windows Bitmap</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/dxf_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/dxf_Import.xcu
new file mode 100644
index 000000000..d4ce34e28
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/dxf_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="dxf_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>dxf_AutoCAD_Interchange</value></prop>
+ <prop oor:name="FormatName"><value>SVDXF</value></prop>
+ <prop oor:name="RealFilterName"><value>DXF - AutoCAD Interchange</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">DXF - AutoCAD Interchange Format</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/emf_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/emf_Export.xcu
new file mode 100644
index 000000000..631f90a50
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/emf_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="emf_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>emf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="FormatName"><value>SVEMF</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EMF - Enhanced Metafile</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/emf_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/emf_Import.xcu
new file mode 100644
index 000000000..e2d19bbf8
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/emf_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="emf_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>emf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="FormatName"><value>SVEMF</value></prop>
+ <prop oor:name="RealFilterName"><value>EMF - MS Windows Metafile</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EMF - Enhanced Metafile</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/eps_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/eps_Export.xcu
new file mode 100644
index 000000000..b89453e45
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/eps_Export.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="eps_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>eps_Encapsulated_PostScript</value></prop>
+ <prop oor:name="FormatName"><value>SVEEPS</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EPS - Encapsulated PostScript</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/eps_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/eps_Import.xcu
new file mode 100644
index 000000000..327834368
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/eps_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="eps_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>eps_Encapsulated_PostScript</value></prop>
+ <prop oor:name="FormatName"><value>SVIEPS</value></prop>
+ <prop oor:name="RealFilterName"><value>EPS - Encapsulated PostScript</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">EPS - Encapsulated PostScript</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/gif_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/gif_Export.xcu
new file mode 100644
index 000000000..f55d1ba55
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/gif_Export.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="gif_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>gif_Graphics_Interchange</value></prop>
+ <prop oor:name="FormatName"><value>SVEGIF</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">GIF - Graphics Interchange Format</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/gif_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/gif_Import.xcu
new file mode 100644
index 000000000..08bcff520
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/gif_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="gif_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>gif_Graphics_Interchange</value></prop>
+ <prop oor:name="FormatName"><value>SVIGIF</value></prop>
+ <prop oor:name="RealFilterName"><value>GIF - Graphics Interchange</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">GIF - Graphics Interchange Format</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/jpg_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/jpg_Export.xcu
new file mode 100644
index 000000000..82bfd4ec9
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/jpg_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="jpg_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>jpg_JPEG</value></prop>
+ <prop oor:name="FormatName"><value>SVEJPEG</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/jpg_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/jpg_Import.xcu
new file mode 100644
index 000000000..0e3ac03fe
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/jpg_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="jpg_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>jpg_JPEG</value></prop>
+ <prop oor:name="FormatName"><value>SVIJPEG</value></prop>
+ <prop oor:name="RealFilterName"><value>JPG - JPEG</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/met_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/met_Import.xcu
new file mode 100644
index 000000000..8e6aa1b9e
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/met_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="met_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>met_OS2_Metafile</value></prop>
+ <prop oor:name="FormatName"><value>SVMET</value></prop>
+ <prop oor:name="RealFilterName"><value>MET - OS/2 Metafile</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">MET - OS/2 Metafile</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/mov_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/mov_Import.xcu
new file mode 100644
index 000000000..3dd288603
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/mov_Import.xcu
@@ -0,0 +1,18 @@
+<!--
+ * 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/.
+ *
+-->
+ <node oor:name="mov_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>mov_MOV</value></prop>
+ <prop oor:name="FormatName"><value>SVMOV</value></prop>
+ <prop oor:name="RealFilterName"><value>MOV - MOV</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">MOV - QuickTime File Format</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pbm_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/pbm_Import.xcu
new file mode 100644
index 000000000..0e7f0b940
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pbm_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="pbm_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>pbm_Portable_Bitmap</value></prop>
+ <prop oor:name="FormatName"><value>SVPBM</value></prop>
+ <prop oor:name="RealFilterName"><value>PBM - Portable Bitmap</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PBM - Portable Bitmap</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base.xcu b/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base.xcu
new file mode 100644
index 000000000..29c7b846d
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="pcd_Import_Base" oor:op="replace" >
+ <prop oor:name="Type"><value>pcd_Photo_CD_Base</value></prop>
+ <prop oor:name="FormatName"><value>SVPCD</value></prop>
+ <prop oor:name="RealFilterName"><value>draw_PCD_Photo_CD_Base</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCD - Kodak Photo CD (768x512)</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base16.xcu b/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base16.xcu
new file mode 100644
index 000000000..b61fde810
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base16.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="pcd_Import_Base16" oor:op="replace" >
+ <prop oor:name="Type"><value>pcd_Photo_CD_Base16</value></prop>
+ <prop oor:name="FormatName"><value>SVPCD</value></prop>
+ <prop oor:name="RealFilterName"><value>draw_PCD_Photo_CD_Base16</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCD - Kodak Photo CD (192x128)</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base4.xcu b/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base4.xcu
new file mode 100644
index 000000000..15d51918a
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pcd_Import_Base4.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="pcd_Import_Base4" oor:op="replace" >
+ <prop oor:name="Type"><value>pcd_Photo_CD_Base4</value></prop>
+ <prop oor:name="FormatName"><value>SVPCD</value></prop>
+ <prop oor:name="RealFilterName"><value>draw_PCD_Photo_CD_Base4</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCD - Kodak Photo CD (384x256)</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pct_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/pct_Import.xcu
new file mode 100644
index 000000000..974bb3300
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pct_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="pct_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>pct_Mac_Pict</value></prop>
+ <prop oor:name="FormatName"><value>SVPICT</value></prop>
+ <prop oor:name="RealFilterName"><value>PCT - Mac Pict</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCT - Mac Pict</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pcx_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/pcx_Import.xcu
new file mode 100644
index 000000000..da49344d4
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pcx_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="pcx_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>pcx_Zsoft_Paintbrush</value></prop>
+ <prop oor:name="FormatName"><value>SVPCX</value></prop>
+ <prop oor:name="RealFilterName"><value>PCX - Zsoft Paintbrush</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PCX - Zsoft Paintbrush</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pdf_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/pdf_Export.xcu
new file mode 100644
index 000000000..d82c771da
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pdf_Export.xcu
@@ -0,0 +1,17 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="pdf_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="FormatName"><value>SVEPDF</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pdf_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/pdf_Import.xcu
new file mode 100644
index 000000000..a1cc9ce59
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pdf_Import.xcu
@@ -0,0 +1,17 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="pdf_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>pdf_Portable_Document_Format</value></prop>
+ <prop oor:name="FormatName"><value>SVIPDF</value></prop>
+ <prop oor:name="RealFilterName"><value>PDF - Portable Document Format</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/pgm_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/pgm_Import.xcu
new file mode 100644
index 000000000..0356e6954
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/pgm_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="pgm_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>pgm_Portable_Graymap</value></prop>
+ <prop oor:name="FormatName"><value>SVPBM</value></prop>
+ <prop oor:name="RealFilterName"><value>PGM - Portable Graymap</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PGM - Portable Graymap</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/png_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/png_Export.xcu
new file mode 100644
index 000000000..95fc65272
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/png_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="png_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>png_Portable_Network_Graphic</value></prop>
+ <prop oor:name="FormatName"><value>SVEPNG</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PNG - Portable Network Graphics</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/png_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/png_Import.xcu
new file mode 100644
index 000000000..cbc4c6507
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/png_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="png_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>png_Portable_Network_Graphic</value></prop>
+ <prop oor:name="FormatName"><value>SVIPNG</value></prop>
+ <prop oor:name="RealFilterName"><value>PNG - Portable Network Graphic</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PNG - Portable Network Graphics</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/ppm_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/ppm_Import.xcu
new file mode 100644
index 000000000..03134558c
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/ppm_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="ppm_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>ppm_Portable_Pixelmap</value></prop>
+ <prop oor:name="FormatName"><value>SVPBM</value></prop>
+ <prop oor:name="RealFilterName"><value>PPM - Portable Pixelmap</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PPM - Portable Pixelmap</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/psd_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/psd_Import.xcu
new file mode 100644
index 000000000..f51b0fa59
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/psd_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="psd_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>psd_Adobe_Photoshop</value></prop>
+ <prop oor:name="FormatName"><value>SVPSD</value></prop>
+ <prop oor:name="RealFilterName"><value>PSD - Adobe Photoshop</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">PSD - Adobe Photoshop</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/ras_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/ras_Import.xcu
new file mode 100644
index 000000000..7e9a3b2bb
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/ras_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="ras_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>ras_Sun_Rasterfile</value></prop>
+ <prop oor:name="FormatName"><value>SVRAS</value></prop>
+ <prop oor:name="RealFilterName"><value>RAS - Sun Rasterfile</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">RAS - Sun Raster Image</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/svg_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/svg_Export.xcu
new file mode 100644
index 000000000..11e70d478
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/svg_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="svg_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+ <prop oor:name="FormatName"><value>SVESVG</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu
new file mode 100644
index 000000000..3577bd98d
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/svg_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="svg_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>svg_Scalable_Vector_Graphics</value></prop>
+ <prop oor:name="FormatName"><value>SVISVG</value></prop>
+ <prop oor:name="RealFilterName"><value>SVG - Scalable Vector Graphics</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVG - Scalable Vector Graphics</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/svm_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/svm_Export.xcu
new file mode 100644
index 000000000..eeaa34cc4
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/svm_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="svm_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>svm_StarView_Metafile</value></prop>
+ <prop oor:name="FormatName"><value>SVMETAFILE</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVM - StarView Metafile</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/svm_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/svm_Import.xcu
new file mode 100644
index 000000000..74dd7ec30
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/svm_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="svm_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>svm_StarView_Metafile</value></prop>
+ <prop oor:name="FormatName"><value>SVMETAFILE</value></prop>
+ <prop oor:name="RealFilterName"><value>SVM - StarView Metafile</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">SVM - StarView Metafile</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/tga_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/tga_Import.xcu
new file mode 100644
index 000000000..922cdefbf
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/tga_Import.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+
+<node oor:name="tga_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>tga_Truevision_TARGA</value></prop>
+ <prop oor:name="FormatName"><value>SVTGA</value></prop>
+ <prop oor:name="RealFilterName"><value>TGA - Truevision TARGA</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">TGA - Truevision Targa</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+</node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/tif_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/tif_Export.xcu
new file mode 100644
index 000000000..6fc07ec72
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/tif_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="tif_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>tif_Tag_Image_File</value></prop>
+ <prop oor:name="FormatName"><value>SVTIFF</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">TIFF - Tagged Image File Format</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/tif_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/tif_Import.xcu
new file mode 100644
index 000000000..b77e6e6d6
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/tif_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="tif_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>tif_Tag_Image_File</value></prop>
+ <prop oor:name="FormatName"><value>SVTIFF</value></prop>
+ <prop oor:name="RealFilterName"><value>TIF - Tag Image File</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">TIFF - Tagged Image File Format</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/webp_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/webp_Export.xcu
new file mode 100644
index 000000000..70ff15429
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/webp_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="webp_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="FormatName"><value>SVEWEBP</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/webp_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/webp_Import.xcu
new file mode 100644
index 000000000..cdce5c9e4
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/webp_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="webp_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>webp_WebP</value></prop>
+ <prop oor:name="FormatName"><value>SVIWEBP</value></prop>
+ <prop oor:name="RealFilterName"><value>WEBP - WebP</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/wmf_Export.xcu b/filter/source/config/fragments/internalgraphicfilters/wmf_Export.xcu
new file mode 100644
index 000000000..a389687be
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/wmf_Export.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="wmf_Export" oor:op="replace" >
+ <prop oor:name="Type"><value>wmf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="FormatName"><value>SVWMF</value></prop>
+ <prop oor:name="RealFilterName"/>
+ <prop oor:name="UIComponent"><value>com.sun.star.svtools.SvFilterOptionsDialog</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WMF - Windows Metafile</value>
+ </prop>
+ <prop oor:name="Flags"><value>EXPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/wmf_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/wmf_Import.xcu
new file mode 100644
index 000000000..149d7ec86
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/wmf_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="wmf_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>wmf_MS_Windows_Metafile</value></prop>
+ <prop oor:name="FormatName"><value>SVWMF</value></prop>
+ <prop oor:name="RealFilterName"><value>WMF - MS Windows Metafile</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">WMF - Windows Metafile</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/xbm_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/xbm_Import.xcu
new file mode 100644
index 000000000..170cd89be
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/xbm_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="xbm_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>xbm_X_Consortium</value></prop>
+ <prop oor:name="FormatName"><value>SVIXBM</value></prop>
+ <prop oor:name="RealFilterName"><value>XBM - X-Consortium</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">XBM - X Bitmap</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/internalgraphicfilters/xpm_Import.xcu b/filter/source/config/fragments/internalgraphicfilters/xpm_Import.xcu
new file mode 100644
index 000000000..bdc51fd31
--- /dev/null
+++ b/filter/source/config/fragments/internalgraphicfilters/xpm_Import.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="xpm_Import" oor:op="replace" >
+ <prop oor:name="Type"><value>xpm_XPM</value></prop>
+ <prop oor:name="FormatName"><value>SVIXPM</value></prop>
+ <prop oor:name="RealFilterName"><value>XPM</value></prop>
+ <prop oor:name="UIComponent"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">XPM - X PixMap</value>
+ </prop>
+ <prop oor:name="Flags"><value>IMPORT</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/langfilter.xsl b/filter/source/config/fragments/langfilter.xsl
new file mode 100644
index 000000000..b26a522d1
--- /dev/null
+++ b/filter/source/config/fragments/langfilter.xsl
@@ -0,0 +1,57 @@
+<?xml version='1.0' encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:oor="http://openoffice.org/2001/registry">
+<xsl:output method="xml" indent="yes" omit-xml-declaration="no" version="1.0" encoding="UTF-8"/>
+<xsl:param name="lang"/>
+<xsl:template match="*">
+ <xsl:if test="count(.//*[@xml:lang=$lang])&gt;0">
+ <xsl:copy>
+ <xsl:apply-templates select="*|@*"/>
+ </xsl:copy>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="@oor:op|@oor:finalized|@oor:mandatory">
+</xsl:template>
+
+<xsl:template match="@*">
+ <xsl:copy>
+ <xsl:apply-templates select="*|@*"/>
+ </xsl:copy>
+</xsl:template>
+
+<xsl:template match="value">
+ <xsl:if test="@xml:lang=$lang">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|text()"/>
+ </xsl:copy>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match="text()">
+ <xsl:if test="../@xml:lang=$lang">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|text()"/>
+ </xsl:copy>
+ </xsl:if>
+</xsl:template>
+
+
+</xsl:stylesheet>
+
diff --git a/filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu b/filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu
new file mode 100644
index 000000000..14a03a846
--- /dev/null
+++ b/filter/source/config/fragments/types/MS_Excel_2007_Binary.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 2007 Binary" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xlsb</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>Calc MS Excel 2007 Binary</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Microsoft Excel 2007 Binary</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/MS_Excel_2007_VBA_XML.xcu b/filter/source/config/fragments/types/MS_Excel_2007_VBA_XML.xcu
new file mode 100644
index 000000000..70c99bbf7
--- /dev/null
+++ b/filter/source/config/fragments/types/MS_Excel_2007_VBA_XML.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 2007 VBA XML" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xlsm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel.sheet.macroEnabled.12</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>Calc MS Excel 2007 VBA XML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Microsoft Excel 2007–365 VBA XML</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/MS_Excel_2007_XML.xcu b/filter/source/config/fragments/types/MS_Excel_2007_XML.xcu
new file mode 100644
index 000000000..73d2daee3
--- /dev/null
+++ b/filter/source/config/fragments/types/MS_Excel_2007_XML.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 2007 XML" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xlsx</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>Calc MS Excel 2007 XML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Excel 2007–365</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/MS_Excel_2007_XML_Template.xcu b/filter/source/config/fragments/types/MS_Excel_2007_XML_Template.xcu
new file mode 100644
index 000000000..d0a828def
--- /dev/null
+++ b/filter/source/config/fragments/types/MS_Excel_2007_XML_Template.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS Excel 2007 XML Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xltx xltm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.spreadsheetml.template</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>Calc MS Excel 2007 XML Template</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Excel 2007–365 Template</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/MS_PowerPoint_2007_XML.xcu b/filter/source/config/fragments/types/MS_PowerPoint_2007_XML.xcu
new file mode 100644
index 000000000..75b9f95d4
--- /dev/null
+++ b/filter/source/config/fragments/types/MS_PowerPoint_2007_XML.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS PowerPoint 2007 XML" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pptx</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.presentationml.presentation</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Impress MS PowerPoint 2007 XML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">PowerPoint 2007–365</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_AutoPlay.xcu b/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_AutoPlay.xcu
new file mode 100644
index 000000000..7c8dc62e2
--- /dev/null
+++ b/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_AutoPlay.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS PowerPoint 2007 XML AutoPlay" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>ppsx</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.presentationml.slideshow</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Impress MS PowerPoint 2007 XML AutoPlay</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">PowerPoint 2007–365</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_Template.xcu b/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_Template.xcu
new file mode 100644
index 000000000..c64c11276
--- /dev/null
+++ b/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_Template.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS PowerPoint 2007 XML Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>potx potm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.presentationml.template</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Impress MS PowerPoint 2007 XML Template</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">PowerPoint 2007–365 Template</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_VBA.xcu b/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_VBA.xcu
new file mode 100644
index 000000000..51203bac1
--- /dev/null
+++ b/filter/source/config/fragments/types/MS_PowerPoint_2007_XML_VBA.xcu
@@ -0,0 +1,28 @@
+
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="MS PowerPoint 2007 XML VBA" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pptm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Impress MS PowerPoint 2007 XML VBA</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">PowerPoint 2007–365 VBA</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/MWAW_Bitmap.xcu b/filter/source/config/fragments/types/MWAW_Bitmap.xcu
new file mode 100644
index 000000000..532f10609
--- /dev/null
+++ b/filter/source/config/fragments/types/MWAW_Bitmap.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Bitmap" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Draw.MWAWDrawImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>*</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>MWAW_Bitmap</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy Mac Bitmap</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/MWAW_Database.xcu b/filter/source/config/fragments/types/MWAW_Database.xcu
new file mode 100644
index 000000000..491d23a6c
--- /dev/null
+++ b/filter/source/config/fragments/types/MWAW_Database.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Database" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>*</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>MWAW_Database</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy Mac Database</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/MWAW_Drawing.xcu b/filter/source/config/fragments/types/MWAW_Drawing.xcu
new file mode 100644
index 000000000..3edba277e
--- /dev/null
+++ b/filter/source/config/fragments/types/MWAW_Drawing.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Drawing" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Draw.MWAWDrawImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>*</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>MWAW_Drawing</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy Mac Drawing</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/MWAW_Presentation.xcu b/filter/source/config/fragments/types/MWAW_Presentation.xcu
new file mode 100644
index 000000000..2f96bff69
--- /dev/null
+++ b/filter/source/config/fragments/types/MWAW_Presentation.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Presentation" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Impress.MWAWImpressImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>*</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>MWAW_Presentation</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy Mac Presentation</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/MWAW_Spreadsheet.xcu b/filter/source/config/fragments/types/MWAW_Spreadsheet.xcu
new file mode 100644
index 000000000..5ebb8e8a8
--- /dev/null
+++ b/filter/source/config/fragments/types/MWAW_Spreadsheet.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Spreadsheet" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>*</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>MWAW_Spreadsheet</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy Mac Spreadsheet</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/MWAW_Text_Document.xcu b/filter/source/config/fragments/types/MWAW_Text_Document.xcu
new file mode 100644
index 000000000..6e2b1cdde
--- /dev/null
+++ b/filter/source/config/fragments/types/MWAW_Text_Document.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="MWAW_Text_Document" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Writer.MWAWImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>*</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>MWAW_Text_Document</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy Mac Text Document</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/Palm_Text_Document.xcu b/filter/source/config/fragments/types/Palm_Text_Document.xcu
new file mode 100644
index 000000000..e067f9f0a
--- /dev/null
+++ b/filter/source/config/fragments/types/Palm_Text_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="Palm_Text_Document" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>pdb</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/vnd.palm</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>Palm_Text_Document</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Palm Text Document</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/StarBase.xcu b/filter/source/config/fragments/types/StarBase.xcu
new file mode 100644
index 000000000..5f335c07f
--- /dev/null
+++ b/filter/source/config/fragments/types/StarBase.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarBase" oor:op="replace">
+ <prop oor:name="DetectService"><value>org.openoffice.comp.dbflt.DBTypeDetection</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/sdatabase*</value></prop>
+ <prop oor:name="Extensions"><value>odb</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.base</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>StarOffice XML (Base)</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenDocument Database</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>StarBase 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/StarBaseReport.xcu b/filter/source/config/fragments/types/StarBaseReport.xcu
new file mode 100644
index 000000000..0489dc789
--- /dev/null
+++ b/filter/source/config/fragments/types/StarBaseReport.xcu
@@ -0,0 +1,43 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarBaseReport" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.report.ORptTypeDetection</value>
+ </prop>
+ <prop oor:name="URLPattern">
+ <value>private:factory/sreport*</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>orp</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/vnd.sun.xml.report</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>false</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>StarOffice XML (Base) Report</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenDocument Database Report</value>
+ </prop>
+ <prop oor:name="ClipboardFormat">
+ <value>StarBaseReport 9.0</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/types/StarBaseReportChart.xcu b/filter/source/config/fragments/types/StarBaseReportChart.xcu
new file mode 100644
index 000000000..0ef9a5463
--- /dev/null
+++ b/filter/source/config/fragments/types/StarBaseReportChart.xcu
@@ -0,0 +1,41 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="StarBaseReportChart" oor:op="replace">
+ <prop oor:name="DetectService"/>
+ <prop oor:name="URLPattern">
+ <value/>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>odc</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/vnd.sun.xml.report.chart</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>false</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>StarOffice XML (Base) Report Chart</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">StarOffice XML (Base) Report Chart 9</value>
+ </prop>
+ <prop oor:name="ClipboardFormat">
+ <value>StarOffice XML (Base) Report Chart 9</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/types/StarOffice_Drawing.xcu b/filter/source/config/fragments/types/StarOffice_Drawing.xcu
new file mode 100644
index 000000000..cad6f68c3
--- /dev/null
+++ b/filter/source/config/fragments/types/StarOffice_Drawing.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="StarOffice_Drawing" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Draw.StarOfficeDrawImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>sda</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>StarOffice_Drawing</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy StarOffice Drawing</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/StarOffice_Presentation.xcu b/filter/source/config/fragments/types/StarOffice_Presentation.xcu
new file mode 100644
index 000000000..02c0f3af6
--- /dev/null
+++ b/filter/source/config/fragments/types/StarOffice_Presentation.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="StarOffice_Presentation" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Impress.StarOfficePresentationImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>sdd</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>StarOffice_Presentation</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy StarOffice Presentation</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/StarOffice_Spreadsheet.xcu b/filter/source/config/fragments/types/StarOffice_Spreadsheet.xcu
new file mode 100644
index 000000000..f4f472b94
--- /dev/null
+++ b/filter/source/config/fragments/types/StarOffice_Spreadsheet.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="StarOffice_Spreadsheet" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Calc.StarOfficeCalcImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>sdc</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>StarOffice_Spreadsheet</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy StarOffice Spreadsheet</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/StarOffice_Writer.xcu b/filter/source/config/fragments/types/StarOffice_Writer.xcu
new file mode 100644
index 000000000..ca10b9328
--- /dev/null
+++ b/filter/source/config/fragments/types/StarOffice_Writer.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="StarOffice_Writer" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Writer.StarOfficeWriterImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>sdw</value>
+ </prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>StarOffice_Writer</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Legacy StarOffice Text Document</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/Unified_Office_Format_presentation.xcu b/filter/source/config/fragments/types/Unified_Office_Format_presentation.xcu
new file mode 100644
index 000000000..11f2a392b
--- /dev/null
+++ b/filter/source/config/fragments/types/Unified_Office_Format_presentation.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Unified_Office_Format_presentation" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value oor:separator=";">uop;uof</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>Unified Office Format presentation</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>doctype:vnd.uof.presentation</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/Unified_Office_Format_spreadsheet.xcu b/filter/source/config/fragments/types/Unified_Office_Format_spreadsheet.xcu
new file mode 100644
index 000000000..71971bd1b
--- /dev/null
+++ b/filter/source/config/fragments/types/Unified_Office_Format_spreadsheet.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Unified_Office_Format_spreadsheet" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value oor:separator=";">uos;uof</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>Unified Office Format spreadsheet</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>doctype:vnd.uof.spreadsheet</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/Unified_Office_Format_text.xcu b/filter/source/config/fragments/types/Unified_Office_Format_text.xcu
new file mode 100644
index 000000000..be991d466
--- /dev/null
+++ b/filter/source/config/fragments/types/Unified_Office_Format_text.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="Unified_Office_Format_text" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value oor:separator=";">uot;uof</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>Unified Office Format text</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>doctype:vnd.uof.text</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/XHTML_File.xcu b/filter/source/config/fragments/types/XHTML_File.xcu
new file mode 100644
index 000000000..6117ca3fe
--- /dev/null
+++ b/filter/source/config/fragments/types/XHTML_File.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="XHTML_File" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>html xhtml</value></prop>
+ <prop oor:name="MediaType"><value>application/xhtml+xml</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>XHTML</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/bmp_MS_Windows.xcu b/filter/source/config/fragments/types/bmp_MS_Windows.xcu
new file mode 100644
index 000000000..7f60fae33
--- /dev/null
+++ b/filter/source/config/fragments/types/bmp_MS_Windows.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="bmp_MS_Windows" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>bmp</value></prop>
+ <prop oor:name="MediaType"><value>image/x-MS-bmp</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>BMP - MS Windows</value></prop>
+ <prop oor:name="UIName">
+ <value>BMP - Windows Bitmap</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc8.xcu b/filter/source/config/fragments/types/calc8.xcu
new file mode 100644
index 000000000..36c6601e7
--- /dev/null
+++ b/filter/source/config/fragments/types/calc8.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc8" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/scalc*</value></prop>
+ <prop oor:name="Extensions"><value>ods</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.spreadsheet</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>calc8</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Calc 8</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Calc 8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc8_template.xcu b/filter/source/config/fragments/types/calc8_template.xcu
new file mode 100644
index 000000000..293283bb4
--- /dev/null
+++ b/filter/source/config/fragments/types/calc8_template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc8_template" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>ots</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.spreadsheet-template</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>calc8_template</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Calc 8 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Calc 8 Template</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_ADO_rowset_XML.xcu b/filter/source/config/fragments/types/calc_ADO_rowset_XML.xcu
new file mode 100644
index 000000000..2f02f568e
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_ADO_rowset_XML.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_ADO_rowset_XML" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xml</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>ADO Rowset XML</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">ADO Rowset XML</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>doctype:urn:schemas-microsoft-com:rowset</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_AppleNumbers.xcu b/filter/source/config/fragments/types/calc_AppleNumbers.xcu
new file mode 100644
index 000000000..d2030b82a
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_AppleNumbers.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="calc_AppleNumbers" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Calc.NumbersImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>numbers</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/x-iwork-numbers-sffnumbers</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>Apple Numbers</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Apple Numbers</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/calc_ClarisWorks.xcu b/filter/source/config/fragments/types/calc_ClarisWorks.xcu
new file mode 100644
index 000000000..105bae43c
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_ClarisWorks.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_ClarisWorks" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>cwk</value></prop>
+ <prop oor:name="MediaType"><value>application/clarisworks</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>ClarisWorks_Calc</value></prop>
+ <prop oor:name="UIName">
+ <value>ClarisWorks/AppleWorks Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_Claris_Resolve.xcu b/filter/source/config/fragments/types/calc_Claris_Resolve.xcu
new file mode 100644
index 000000000..309eb47c6
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_Claris_Resolve.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_Claris_Resolve" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>cwk</value></prop>
+ <prop oor:name="MediaType"><value>application/clarisworks</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Claris_Resolve_Calc</value></prop>
+ <prop oor:name="UIName">
+ <value>ClarisResolve Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_DIF.xcu b/filter/source/config/fragments/types/calc_DIF.xcu
new file mode 100644
index 000000000..536e75d72
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_DIF.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_DIF" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>dif</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>DIF</value></prop>
+ <prop oor:name="UIName">
+ <value>Data Interchange Format</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_Gnumeric.xcu b/filter/source/config/fragments/types/calc_Gnumeric.xcu
new file mode 100644
index 000000000..4c158cc34
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_Gnumeric.xcu
@@ -0,0 +1,17 @@
+<!--
+ * 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/.
+-->
+<node oor:name="Gnumeric XML" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.sc.OrcusFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>gnumeric gnm</value></prop>
+ <prop oor:name="MediaType"><value>application/x-gnumeric</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>Gnumeric Spreadsheet</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Gnumeric Spreadsheet</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/calc_HTML.xcu b/filter/source/config/fragments/types/calc_HTML.xcu
new file mode 100644
index 000000000..51bf8f192
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_HTML.xcu
@@ -0,0 +1,35 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <!-- A special case: There are tools that export HTML with .xls
+ extension. Allow to detect these early to avoid going through the
+ whole list of detectors. This also avoids the risk of misdetection
+ as something else, as there are some formats that are text files and
+ the detection is just a heuristic (e.g., wp1 or wp42 supported by
+ libwpd). -->
+ <node oor:name="calc_HTML" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.PlainTextFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xls</value></prop>
+ <prop oor:name="MediaType"><value>text/html</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>HTML Table</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_Lotus.xcu b/filter/source/config/fragments/types/calc_Lotus.xcu
new file mode 100644
index 000000000..2b047e3f0
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_Lotus.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_Lotus" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wk1 wks 123</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.lotus-1-2-3</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Lotus</value></prop>
+ <prop oor:name="UIName">
+ <value>Lotus</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_2003_XML.xcu b/filter/source/config/fragments/types/calc_MS_Excel_2003_XML.xcu
new file mode 100644
index 000000000..a3ee903b9
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_2003_XML.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_2003_XML" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.sc.OrcusFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xml xls</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Microsoft Excel 2003 XML</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>doctype:Workbook</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_40.xcu b/filter/source/config/fragments/types/calc_MS_Excel_40.xcu
new file mode 100644
index 000000000..b99cfc485
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_40.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_40" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.ExcelBiffFormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xls xlw xlc xlm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Excel 4.0</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Excel 4.0</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_40_VorlageTemplate.xcu b/filter/source/config/fragments/types/calc_MS_Excel_40_VorlageTemplate.xcu
new file mode 100644
index 000000000..69304a7ad
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_40_VorlageTemplate.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_40_VorlageTemplate" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.ExcelBiffFormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xlt</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Excel 4.0 Vorlage/Template</value></prop>
+ <prop oor:name="UIName">
+ <value>MS Excel 4.0 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_5095.xcu b/filter/source/config/fragments/types/calc_MS_Excel_5095.xcu
new file mode 100644
index 000000000..c1e537132
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_5095.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_5095" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.ExcelBiffFormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xls xlc xlm xlw</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Excel 5.0/95</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Excel 5.0</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Biff5</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_5095_VorlageTemplate.xcu b/filter/source/config/fragments/types/calc_MS_Excel_5095_VorlageTemplate.xcu
new file mode 100644
index 000000000..ead4b0426
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_5095_VorlageTemplate.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_5095_VorlageTemplate" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.ExcelBiffFormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xlt</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Excel 5.0/95 Vorlage/Template</value></prop>
+ <prop oor:name="UIName">
+ <value>MS Excel 5.0 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Biff5</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_95.xcu b/filter/source/config/fragments/types/calc_MS_Excel_95.xcu
new file mode 100644
index 000000000..25e1d3380
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_95.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_95" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.ExcelBiffFormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xls xlc xlm xlw</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Excel 95</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Excel 95</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Biff5</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_95_VorlageTemplate.xcu b/filter/source/config/fragments/types/calc_MS_Excel_95_VorlageTemplate.xcu
new file mode 100644
index 000000000..fc3e68f96
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_95_VorlageTemplate.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_95_VorlageTemplate" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.ExcelBiffFormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xlt</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Excel 95 Vorlage/Template</value></prop>
+ <prop oor:name="UIName">
+ <value>MS Excel 95 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Biff5</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_97.xcu b/filter/source/config/fragments/types/calc_MS_Excel_97.xcu
new file mode 100644
index 000000000..56d5f2647
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_97.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_97" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.ExcelBiffFormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xls xlc xlm xlw xlk et</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Excel 97</value></prop>
+ <prop oor:name="UIName">
+ <value>Excel 97–2003</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Biff8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Excel_97_VorlageTemplate.xcu b/filter/source/config/fragments/types/calc_MS_Excel_97_VorlageTemplate.xcu
new file mode 100644
index 000000000..f8cd624f7
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Excel_97_VorlageTemplate.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Excel_97_VorlageTemplate" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.ExcelBiffFormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xlt ett</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-excel</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Excel 97 Vorlage/Template</value></prop>
+ <prop oor:name="UIName">
+ <value>Excel 97–2000 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Biff8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_MS_Multiplan.xcu b/filter/source/config/fragments/types/calc_MS_Multiplan.xcu
new file mode 100644
index 000000000..7f9b3c3c5
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Multiplan.xcu
@@ -0,0 +1,25 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="calc_MS_Multiplan" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Calc.MSWorksCalcImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions"><value>mp</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>Microsoft Multiplan</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Multiplan</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/calc_MS_Works_Document.xcu b/filter/source/config/fragments/types/calc_MS_Works_Document.xcu
new file mode 100644
index 000000000..f45dfe109
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_MS_Works_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_MS_Works_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Calc.MSWorksCalcImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wks wdb</value></prop>
+ <prop oor:name="MediaType"></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS_Works_Calc</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Works Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_Mac_Works.xcu b/filter/source/config/fragments/types/calc_Mac_Works.xcu
new file mode 100644
index 000000000..9a9d37342
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_Mac_Works.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_Mac_Works" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Calc.MWAWCalcImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wps</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-works</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Mac_Works_Calc</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Works for Mac Document (v1 - v4)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_ODS_FlatXML.xcu b/filter/source/config/fragments/types/calc_ODS_FlatXML.xcu
new file mode 100644
index 000000000..22064e799
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_ODS_FlatXML.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_ODS_FlatXML" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>fods ods xml</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.spreadsheet-flat-xml</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>OpenDocument Spreadsheet Flat XML</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenDocument Spreadsheet (Flat XML)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat">
+ <value>doctype:office:mimetype="application/vnd.oasis.opendocument.spreadsheet"</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_OOXML.xcu b/filter/source/config/fragments/types/calc_OOXML.xcu
new file mode 100644
index 000000000..5b17c1c1d
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_OOXML.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Office Open XML Spreadsheet" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xlsx xlsm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.spreadsheetml.sheet</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>Calc Office Open XML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Office Open XML Spreadsheet</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/calc_OOXML_Template.xcu b/filter/source/config/fragments/types/calc_OOXML_Template.xcu
new file mode 100644
index 000000000..677762fa7
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_OOXML_Template.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Office Open XML Spreadsheet Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xltx xltm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.spreadsheetml.template</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>Calc Office Open XML Template</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Office Open XML Spreadsheet Template</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/calc_QPro.xcu b/filter/source/config/fragments/types/calc_QPro.xcu
new file mode 100644
index 000000000..e43a63bae
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_QPro.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_QPro" oor:op="replace" oor:finalized="true" oor:mandatory="true">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wb2</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Quattro Pro 6.0</value></prop>
+ <prop oor:name="UIName">
+ <value>Quattro Pro 6.0</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_SYLK.xcu b/filter/source/config/fragments/types/calc_SYLK.xcu
new file mode 100644
index 000000000..4f0d72cab
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_SYLK.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_SYLK" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>slk sylk</value></prop>
+ <prop oor:name="MediaType"><value>text/spreadsheet</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>SYLK</value></prop>
+ <prop oor:name="UIName">
+ <value>SYLK</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_StarOffice_XML_Calc.xcu b/filter/source/config/fragments/types/calc_StarOffice_XML_Calc.xcu
new file mode 100644
index 000000000..79e57ae81
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_StarOffice_XML_Calc.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_StarOffice_XML_Calc" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>sxc</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.calc</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>StarOffice XML (Calc)</value></prop>
+ <prop oor:name="UIName">
+ <value>Calc 6.0</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Calc 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_StarOffice_XML_Calc_Template.xcu b/filter/source/config/fragments/types/calc_StarOffice_XML_Calc_Template.xcu
new file mode 100644
index 000000000..df5f73741
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_StarOffice_XML_Calc_Template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_StarOffice_XML_Calc_Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>stc</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.calc.template</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>calc_StarOffice_XML_Calc_Template</value></prop>
+ <prop oor:name="UIName">
+ <value>Calc 6.0 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Calc 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_WPS_Lotus_Document.xcu b/filter/source/config/fragments/types/calc_WPS_Lotus_Document.xcu
new file mode 100644
index 000000000..abea24321
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_WPS_Lotus_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_WPS_Lotus_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Calc.MSWorksCalcImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wk1 wk3 wk4 123</value></prop>
+ <prop oor:name="MediaType"></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>WPS_Lotus_Calc</value></prop>
+ <prop oor:name="UIName">
+ <value>Lotus Wk1-Wk3</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_WPS_QPro_Document.xcu b/filter/source/config/fragments/types/calc_WPS_QPro_Document.xcu
new file mode 100644
index 000000000..2c8529db0
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_WPS_QPro_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_WPS_QPro_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Calc.MSWorksCalcImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wb1 wb2 wq1 wq2</value></prop>
+ <prop oor:name="MediaType"></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>WPS_QPro_Calc</value></prop>
+ <prop oor:name="UIName">
+ <value>QuattroPro Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/calc_dBase.xcu b/filter/source/config/fragments/types/calc_dBase.xcu
new file mode 100644
index 000000000..d37ec5a64
--- /dev/null
+++ b/filter/source/config/fragments/types/calc_dBase.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="calc_dBase" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.calc.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>dbf</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>dBase</value></prop>
+ <prop oor:name="UIName">
+ <value>dBASE</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/chart8.xcu b/filter/source/config/fragments/types/chart8.xcu
new file mode 100644
index 000000000..5a2fd0c1d
--- /dev/null
+++ b/filter/source/config/fragments/types/chart8.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="chart8" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/schart*</value></prop>
+ <prop oor:name="Extensions"><value>odc</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.chart</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>chart8</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Chart 8</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Chart 8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/chart_StarOffice_XML_Chart.xcu b/filter/source/config/fragments/types/chart_StarOffice_XML_Chart.xcu
new file mode 100644
index 000000000..1292786f8
--- /dev/null
+++ b/filter/source/config/fragments/types/chart_StarOffice_XML_Chart.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="chart_StarOffice_XML_Chart" oor:op="replace" oor:finalized="true" oor:mandatory="true">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>sxs</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.chart</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>StarOffice XML (Chart)</value></prop>
+ <prop oor:name="UIName">
+ <value>Chart 6.0</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Chart 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/component_Bibliography.xcu b/filter/source/config/fragments/types/component_Bibliography.xcu
new file mode 100644
index 000000000..526a4b20b
--- /dev/null
+++ b/filter/source/config/fragments/types/component_Bibliography.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="component_Bibliography" oor:op="replace" >
+ <prop oor:name="URLPattern"><value>.component:Bibliography/*</value></prop>
+ <prop oor:name="Extensions"/>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="UIName">
+ <value>Bibliography component</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ <prop oor:name="DetectService"/>
+ <prop oor:name="PreferredFilter"/>
+ </node>
diff --git a/filter/source/config/fragments/types/component_DB.xcu b/filter/source/config/fragments/types/component_DB.xcu
new file mode 100644
index 000000000..0c1f3ac5a
--- /dev/null
+++ b/filter/source/config/fragments/types/component_DB.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="component_DB" oor:op="replace" >
+ <prop oor:name="URLPattern"><value>.component:DB*</value></prop>
+ <prop oor:name="Extensions"/>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="UIName">
+ <value>DB component</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ <prop oor:name="DetectService"/>
+ <prop oor:name="PreferredFilter"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw8.xcu b/filter/source/config/fragments/types/draw8.xcu
new file mode 100644
index 000000000..cf15c4923
--- /dev/null
+++ b/filter/source/config/fragments/types/draw8.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw8" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/sdraw*</value></prop>
+ <prop oor:name="Extensions"><value>odg</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.graphics</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>draw8</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Draw 8</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Draw 8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/draw8_template.xcu b/filter/source/config/fragments/types/draw8_template.xcu
new file mode 100644
index 000000000..b20422ad4
--- /dev/null
+++ b/filter/source/config/fragments/types/draw8_template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw8_template" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>otg</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.graphics-template</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>draw8_template</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Draw 8 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Draw 8 Template</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_ClarisWorks.xcu b/filter/source/config/fragments/types/draw_ClarisWorks.xcu
new file mode 100644
index 000000000..9581d21ab
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_ClarisWorks.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_ClarisWorks" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.MWAWDrawImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>cwk</value></prop>
+ <prop oor:name="MediaType"><value>application/clarisworks</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>ClarisWorks_Draw</value></prop>
+ <prop oor:name="UIName">
+ <value>ClarisWorks/AppleWorks Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_CorelDraw_Document.xcu b/filter/source/config/fragments/types/draw_CorelDraw_Document.xcu
new file mode 100644
index 000000000..57c637394
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_CorelDraw_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_CorelDraw_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.CDRImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>cdr</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.corel-draw</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Corel Draw Document</value></prop>
+ <prop oor:name="UIName">
+ <value>Corel Draw</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_Corel_Presentation_Exchange.xcu b/filter/source/config/fragments/types/draw_Corel_Presentation_Exchange.xcu
new file mode 100644
index 000000000..73b43832b
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_Corel_Presentation_Exchange.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_Corel_Presentation_Exchange" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.CMXImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>cmx</value></prop>
+ <prop oor:name="MediaType"><value>image/x-cmx</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Corel Presentation Exchange</value></prop>
+ <prop oor:name="UIName">
+ <value>Corel Presentation Exchange</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_Freehand_Document.xcu b/filter/source/config/fragments/types/draw_Freehand_Document.xcu
new file mode 100644
index 000000000..44308542c
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_Freehand_Document.xcu
@@ -0,0 +1,12 @@
+ <node oor:name="draw_Freehand_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.FreehandImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>fh fh1 fh2 fh3 fh4 fh5 fh6 fh7 fh8 fh9 fh10 fh11</value></prop>
+ <prop oor:name="MediaType"><value>image/x-freehand</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Freehand Document</value></prop>
+ <prop oor:name="UIName">
+ <value>Adobe/Macromedia Freehand</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_ODG_FlatXML.xcu b/filter/source/config/fragments/types/draw_ODG_FlatXML.xcu
new file mode 100644
index 000000000..e8272cd1a
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_ODG_FlatXML.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_ODG_FlatXML" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>fodg odg xml</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.graphics-flat-xml</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>OpenDocument Drawing Flat XML</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenDocument Drawing (Flat XML)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat">
+ <value>doctype:office:mimetype="application/vnd.oasis.opendocument.graphics"</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_PageMaker_Document.xcu b/filter/source/config/fragments/types/draw_PageMaker_Document.xcu
new file mode 100644
index 000000000..0ec1bf23b
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_PageMaker_Document.xcu
@@ -0,0 +1,12 @@
+ <node oor:name="draw_PageMaker_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>org.libreoffice.comp.Draw.PageMakerImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>p65 pm pm6 pmd</value></prop>
+ <prop oor:name="MediaType"><value>application/x-pagemaker</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>PageMaker Document</value></prop>
+ <prop oor:name="UIName">
+ <value>Adobe PageMaker</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_Publisher_Document.xcu b/filter/source/config/fragments/types/draw_Publisher_Document.xcu
new file mode 100644
index 000000000..cb56d145a
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_Publisher_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_Publisher_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.MSPUBImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pub</value></prop>
+ <prop oor:name="MediaType"><value>application/x-mspublisher</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Publisher Document</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Publisher 2003</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_QXP_Document.xcu b/filter/source/config/fragments/types/draw_QXP_Document.xcu
new file mode 100644
index 000000000..901efc34c
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_QXP_Document.xcu
@@ -0,0 +1,12 @@
+ <node oor:name="draw_QXP_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>org.libreoffice.comp.Draw.QXPImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>qxd qxt</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>QXP Document</value></prop>
+ <prop oor:name="UIName">
+ <value>QuarkXPress</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_StarOffice_XML_Draw.xcu b/filter/source/config/fragments/types/draw_StarOffice_XML_Draw.xcu
new file mode 100644
index 000000000..d2a4f1f6a
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_StarOffice_XML_Draw.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_StarOffice_XML_Draw" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>sxd</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.draw</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>StarOffice XML (Draw)</value></prop>
+ <prop oor:name="UIName">
+ <value>OpenOffice.org 1.0 Drawing</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Draw 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_StarOffice_XML_Draw_Template.xcu b/filter/source/config/fragments/types/draw_StarOffice_XML_Draw_Template.xcu
new file mode 100644
index 000000000..fcbb470d7
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_StarOffice_XML_Draw_Template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_StarOffice_XML_Draw_Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>std</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.draw.template</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>draw_StarOffice_XML_Draw_Template</value></prop>
+ <prop oor:name="UIName">
+ <value>Draw 6.0 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Draw 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_Visio_Document.xcu b/filter/source/config/fragments/types/draw_Visio_Document.xcu
new file mode 100644
index 000000000..b6c6992a3
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_Visio_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_Visio_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.VisioImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>vdx vsd vsdm vsdx</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.visio</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Visio Document</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Visio</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_WordPerfect_Graphics.xcu b/filter/source/config/fragments/types/draw_WordPerfect_Graphics.xcu
new file mode 100644
index 000000000..6e0a52ee7
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_WordPerfect_Graphics.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="draw_WordPerfect_Graphics" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.WPGImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wpg</value></prop>
+ <prop oor:name="MediaType"><value>image/x-wpg</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>WordPerfect Graphics</value></prop>
+ <prop oor:name="UIName">
+ <value>WordPerfect Graphics</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/draw_ZMF_Document.xcu b/filter/source/config/fragments/types/draw_ZMF_Document.xcu
new file mode 100644
index 000000000..ba67d5b96
--- /dev/null
+++ b/filter/source/config/fragments/types/draw_ZMF_Document.xcu
@@ -0,0 +1,12 @@
+ <node oor:name="draw_ZMF_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>org.libreoffice.comp.Draw.ZMFImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>zmf</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>ZMF Document</value></prop>
+ <prop oor:name="UIName">
+ <value>Zoner Callisto/Draw</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/dxf_AutoCAD_Interchange.xcu b/filter/source/config/fragments/types/dxf_AutoCAD_Interchange.xcu
new file mode 100644
index 000000000..a785f8569
--- /dev/null
+++ b/filter/source/config/fragments/types/dxf_AutoCAD_Interchange.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="dxf_AutoCAD_Interchange" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>dxf</value></prop>
+ <prop oor:name="MediaType"><value>image/vnd.dxf</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>DXF - AutoCAD Interchange</value></prop>
+ <prop oor:name="UIName">
+ <value>DXF - AutoCAD Interchange Format</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/emf_MS_Windows_Metafile.xcu b/filter/source/config/fragments/types/emf_MS_Windows_Metafile.xcu
new file mode 100644
index 000000000..2003217aa
--- /dev/null
+++ b/filter/source/config/fragments/types/emf_MS_Windows_Metafile.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="emf_MS_Windows_Metafile" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>emf emz</value></prop>
+ <prop oor:name="MediaType"><value>image/x-emf</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>EMF - MS Windows Metafile</value></prop>
+ <prop oor:name="UIName">
+ <value>EMF - Enhanced Meta File</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/eps_Encapsulated_PostScript.xcu b/filter/source/config/fragments/types/eps_Encapsulated_PostScript.xcu
new file mode 100644
index 000000000..7097c98aa
--- /dev/null
+++ b/filter/source/config/fragments/types/eps_Encapsulated_PostScript.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="eps_Encapsulated_PostScript" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>eps</value></prop>
+ <prop oor:name="MediaType"><value>image/x-eps</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>EPS - Encapsulated PostScript</value></prop>
+ <prop oor:name="UIName">
+ <value>EPS - Encapsulated PostScript</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/generic_HTML.xcu b/filter/source/config/fragments/types/generic_HTML.xcu
new file mode 100644
index 000000000..92ac87ffb
--- /dev/null
+++ b/filter/source/config/fragments/types/generic_HTML.xcu
@@ -0,0 +1,30 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="generic_HTML" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.PlainTextFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/swriter/web*</value></prop>
+ <!-- the last extension is used when the code wants to know the extension of this type -->
+ <prop oor:name="Extensions"><value>html xhtml htm</value></prop>
+ <prop oor:name="MediaType"><value>text/html</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>HTML</value></prop>
+ <prop oor:name="UIName">
+ <value>HTML Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/generic_Text.xcu b/filter/source/config/fragments/types/generic_Text.xcu
new file mode 100644
index 000000000..45df03f62
--- /dev/null
+++ b/filter/source/config/fragments/types/generic_Text.xcu
@@ -0,0 +1,28 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="generic_Text" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.PlainTextFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>csv tsv tab txt</value></prop>
+ <prop oor:name="MediaType"><value>text/plain</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="UIName">
+ <value>Text</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/gif_Graphics_Interchange.xcu b/filter/source/config/fragments/types/gif_Graphics_Interchange.xcu
new file mode 100644
index 000000000..9fbf3ec32
--- /dev/null
+++ b/filter/source/config/fragments/types/gif_Graphics_Interchange.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="gif_Graphics_Interchange" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>gif</value></prop>
+ <prop oor:name="MediaType"><value>image/gif</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>GIF - Graphics Interchange</value></prop>
+ <prop oor:name="UIName">
+ <value>GIF - Graphics Interchange</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/graphic_HTML.xcu b/filter/source/config/fragments/types/graphic_HTML.xcu
new file mode 100644
index 000000000..e918bbd50
--- /dev/null
+++ b/filter/source/config/fragments/types/graphic_HTML.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="graphic_HTML" oor:op="replace" >
+ <prop oor:name="DetectService"/>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>html htm</value></prop>
+ <prop oor:name="MediaType"><value>text/html</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>HTML</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/impress8.xcu b/filter/source/config/fragments/types/impress8.xcu
new file mode 100644
index 000000000..d26d404f4
--- /dev/null
+++ b/filter/source/config/fragments/types/impress8.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress8" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/simpress*</value></prop>
+ <prop oor:name="Extensions"><value>odp</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.presentation</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>impress8</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Impress 8</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Impress 8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/impress8_template.xcu b/filter/source/config/fragments/types/impress8_template.xcu
new file mode 100644
index 000000000..5c3170a97
--- /dev/null
+++ b/filter/source/config/fragments/types/impress8_template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress8_template" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>otp</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.presentation-template</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>impress8_template</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Impress 8 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Impress 8 Template</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/impress_AppleKeynote.xcu b/filter/source/config/fragments/types/impress_AppleKeynote.xcu
new file mode 100644
index 000000000..797df7ae0
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_AppleKeynote.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="impress_AppleKeynote" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Impress.KeynoteImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>key</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/x-iwork-keynote-sffkey</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>Apple Keynote</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Apple Keynote</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/impress_CGM_Computer_Graphics_Metafile.xcu b/filter/source/config/fragments/types/impress_CGM_Computer_Graphics_Metafile.xcu
new file mode 100644
index 000000000..5f96f709f
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_CGM_Computer_Graphics_Metafile.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_CGM_Computer_Graphics_Metafile" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>cgm</value></prop>
+ <prop oor:name="MediaType"><value>image/cgm</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>CGM - Computer Graphics Metafile</value></prop>
+ <prop oor:name="UIName">
+ <value>CGM - Computer Graphics Metafile</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/impress_ClarisWorks.xcu b/filter/source/config/fragments/types/impress_ClarisWorks.xcu
new file mode 100644
index 000000000..396a6d677
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_ClarisWorks.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_ClarisWorks" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Impress.MWAWPresentationImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>cwk</value></prop>
+ <prop oor:name="MediaType"><value>application/clarisworks</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>ClarisWorks_Impress</value></prop>
+ <prop oor:name="UIName">
+ <value>ClarisWorks/AppleWorks Presentation</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/impress_MS_PowerPoint_97.xcu b/filter/source/config/fragments/types/impress_MS_PowerPoint_97.xcu
new file mode 100644
index 000000000..0f1e119ac
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_MS_PowerPoint_97.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_MS_PowerPoint_97" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>ppt dps</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-powerpoint</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS PowerPoint 97</value></prop>
+ <prop oor:name="UIName">
+ <value>PowerPoint 97–2003</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/impress_MS_PowerPoint_97_AutoPlay.xcu b/filter/source/config/fragments/types/impress_MS_PowerPoint_97_AutoPlay.xcu
new file mode 100644
index 000000000..b9e4a739f
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_MS_PowerPoint_97_AutoPlay.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_MS_PowerPoint_97_AutoPlay" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pps</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-powerpoint</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS PowerPoint 97 AutoPlay</value></prop>
+ <prop oor:name="UIName">
+ <value>PowerPoint 97–2003</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/impress_MS_PowerPoint_97_Vorlage.xcu b/filter/source/config/fragments/types/impress_MS_PowerPoint_97_Vorlage.xcu
new file mode 100644
index 000000000..1cecfc87e
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_MS_PowerPoint_97_Vorlage.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_MS_PowerPoint_97_Vorlage" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pot dpt</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-powerpoint</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS PowerPoint 97 Vorlage</value></prop>
+ <prop oor:name="UIName">
+ <value>PowerPoint 97–2000 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/impress_ODP_FlatXML.xcu b/filter/source/config/fragments/types/impress_ODP_FlatXML.xcu
new file mode 100644
index 000000000..6e9792f98
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_ODP_FlatXML.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_ODP_FlatXML" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>fodp odp xml</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.presentation-flat-xml</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>OpenDocument Presentation Flat XML</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenDocument Presentation (Flat XML)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat">
+ <value>doctype:office:mimetype="application/vnd.oasis.opendocument.presentation"</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/types/impress_OOXML_Presentation.xcu b/filter/source/config/fragments/types/impress_OOXML_Presentation.xcu
new file mode 100644
index 000000000..6264ce716
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_OOXML_Presentation.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Office Open XML Presentation" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pptx pptm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.presentationml.presentation</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Impress Office Open XML</value></prop>
+ <prop oor:name="UIName"><value>Office Open XML Presentation</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/impress_OOXML_Presentation_AutoPlay.xcu b/filter/source/config/fragments/types/impress_OOXML_Presentation_AutoPlay.xcu
new file mode 100644
index 000000000..78c638dae
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_OOXML_Presentation_AutoPlay.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Office Open XML Presentation AutoPlay" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>ppsx</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.presentationml.slideshow</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Impress Office Open XML AutoPlay</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Office Open XML Presentation AutoPlay</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/impress_OOXML_Presentation_Template.xcu b/filter/source/config/fragments/types/impress_OOXML_Presentation_Template.xcu
new file mode 100644
index 000000000..c34d39541
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_OOXML_Presentation_Template.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<node oor:name="Office Open XML Presentation Template" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>potx potm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.presentationml.template</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Impress Office Open XML Template</value></prop>
+ <prop oor:name="UIName"><value>Office Open XML Presentation Template</value></prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/impress_PowerPoint3.xcu b/filter/source/config/fragments/types/impress_PowerPoint3.xcu
new file mode 100644
index 000000000..4c6885943
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_PowerPoint3.xcu
@@ -0,0 +1,22 @@
+<!--
+ * 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/.
+-->
+
+<node oor:name="impress_PowerPoint3" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Impress.MWAWPresentationImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>ppt pot</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>PowerPoint 3</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Microsoft PowerPoint 1-4</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/impress_StarOffice_XML_Impress.xcu b/filter/source/config/fragments/types/impress_StarOffice_XML_Impress.xcu
new file mode 100644
index 000000000..311c43b66
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_StarOffice_XML_Impress.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_StarOffice_XML_Impress" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>sxi</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.impress</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>StarOffice XML (Impress)</value></prop>
+ <prop oor:name="UIName">
+ <value>OpenOffice.org 1.0 Presentation</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Impress 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/impress_StarOffice_XML_Impress_Template.xcu b/filter/source/config/fragments/types/impress_StarOffice_XML_Impress_Template.xcu
new file mode 100644
index 000000000..2df7deae8
--- /dev/null
+++ b/filter/source/config/fragments/types/impress_StarOffice_XML_Impress_Template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="impress_StarOffice_XML_Impress_Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>sti</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.impress.template</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>impress_StarOffice_XML_Impress_Template</value></prop>
+ <prop oor:name="UIName">
+ <value>Impress 6.0 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Impress 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/jpg_JPEG.xcu b/filter/source/config/fragments/types/jpg_JPEG.xcu
new file mode 100644
index 000000000..45f587430
--- /dev/null
+++ b/filter/source/config/fragments/types/jpg_JPEG.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="jpg_JPEG" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>jpg jpeg jfif jif jpe</value></prop>
+ <prop oor:name="MediaType"><value>image/jpeg</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>JPG - JPEG</value></prop>
+ <prop oor:name="UIName">
+ <value>JPEG - Joint Photographic Experts Group</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/math8.xcu b/filter/source/config/fragments/types/math8.xcu
new file mode 100644
index 000000000..787f5baec
--- /dev/null
+++ b/filter/source/config/fragments/types/math8.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="math8" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/smath*</value></prop>
+ <prop oor:name="Extensions"><value>odf</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.formula</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>math8</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Math 8</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Math 8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/math_MathML_XML_Math.xcu b/filter/source/config/fragments/types/math_MathML_XML_Math.xcu
new file mode 100644
index 000000000..b8a4ae3ed
--- /dev/null
+++ b/filter/source/config/fragments/types/math_MathML_XML_Math.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="math_MathML_XML_Math" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.math.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>mml</value></prop>
+ <prop oor:name="MediaType"><value>application/mathml+xml</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MathML XML (Math)</value></prop>
+ <prop oor:name="UIName">
+ <value>MathML 2.0</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/math_MathType_3x.xcu b/filter/source/config/fragments/types/math_MathType_3x.xcu
new file mode 100644
index 000000000..21c22d15d
--- /dev/null
+++ b/filter/source/config/fragments/types/math_MathType_3x.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="math_MathType_3x" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.math.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xxx</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MathType 3.x</value></prop>
+ <prop oor:name="UIName">
+ <value>MathType3.x</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>DS Equation</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/math_StarOffice_XML_Math.xcu b/filter/source/config/fragments/types/math_StarOffice_XML_Math.xcu
new file mode 100644
index 000000000..c1d31ac8d
--- /dev/null
+++ b/filter/source/config/fragments/types/math_StarOffice_XML_Math.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="math_StarOffice_XML_Math" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>sxm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.math</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>StarOffice XML (Math)</value></prop>
+ <prop oor:name="UIName">
+ <value>OpenOffice.org 1.0 Formula</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Math 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/met_OS2_Metafile.xcu b/filter/source/config/fragments/types/met_OS2_Metafile.xcu
new file mode 100644
index 000000000..708a498ee
--- /dev/null
+++ b/filter/source/config/fragments/types/met_OS2_Metafile.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="met_OS2_Metafile" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>met</value></prop>
+ <prop oor:name="MediaType"><value>image/x-met</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MET - OS/2 Metafile</value></prop>
+ <prop oor:name="UIName">
+ <value>MET - OS/2 Metafile</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/mov_MOV.xcu b/filter/source/config/fragments/types/mov_MOV.xcu
new file mode 100644
index 000000000..7471a78a7
--- /dev/null
+++ b/filter/source/config/fragments/types/mov_MOV.xcu
@@ -0,0 +1,20 @@
+<!--
+ * 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/.
+ *
+-->
+ <node oor:name="mov_MOV" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>mov MOV</value></prop>
+ <prop oor:name="MediaType"><value>application/movie</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MOV - MOV</value></prop>
+ <prop oor:name="UIName">
+ <value>MOV - QuickTime File Format</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/oxt_OpenOffice_Extension.xcu b/filter/source/config/fragments/types/oxt_OpenOffice_Extension.xcu
new file mode 100644
index 000000000..ee11dad05
--- /dev/null
+++ b/filter/source/config/fragments/types/oxt_OpenOffice_Extension.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="oxt_OpenOffice_Extension" oor:op="replace" >
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>oxt</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="UIName">
+ <value>OpenOffice Extension</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ <prop oor:name="DetectService"><value>com.sun.star.comp.framework.OXTFileHandler</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ </node>
diff --git a/filter/source/config/fragments/types/pbm_Portable_Bitmap.xcu b/filter/source/config/fragments/types/pbm_Portable_Bitmap.xcu
new file mode 100644
index 000000000..28e489fdb
--- /dev/null
+++ b/filter/source/config/fragments/types/pbm_Portable_Bitmap.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="pbm_Portable_Bitmap" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pbm</value></prop>
+ <prop oor:name="MediaType"><value>image/x-portable-bitmap</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>PBM - Portable Bitmap</value></prop>
+ <prop oor:name="UIName">
+ <value>PBM - Portable Bitmap</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/pcd_Photo_CD_Base.xcu b/filter/source/config/fragments/types/pcd_Photo_CD_Base.xcu
new file mode 100644
index 000000000..6465a0f4f
--- /dev/null
+++ b/filter/source/config/fragments/types/pcd_Photo_CD_Base.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="pcd_Photo_CD_Base" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pcd</value></prop>
+ <prop oor:name="MediaType"><value>image/x-photo-cd</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>draw_PCD_Photo_CD_Base</value></prop>
+ <prop oor:name="UIName">
+ <value>PCD - Photo CD Base</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/pcd_Photo_CD_Base16.xcu b/filter/source/config/fragments/types/pcd_Photo_CD_Base16.xcu
new file mode 100644
index 000000000..4caacf6ef
--- /dev/null
+++ b/filter/source/config/fragments/types/pcd_Photo_CD_Base16.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="pcd_Photo_CD_Base16" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pcd</value></prop>
+ <prop oor:name="MediaType"><value>image/x-photo-cd</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>draw_PCD_Photo_CD_Base16</value></prop>
+ <prop oor:name="UIName">
+ <value>PCD - Photo CD Base16</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/pcd_Photo_CD_Base4.xcu b/filter/source/config/fragments/types/pcd_Photo_CD_Base4.xcu
new file mode 100644
index 000000000..8cb48b1f5
--- /dev/null
+++ b/filter/source/config/fragments/types/pcd_Photo_CD_Base4.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="pcd_Photo_CD_Base4" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pcd</value></prop>
+ <prop oor:name="MediaType"><value>image/x-photo-cd</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>draw_PCD_Photo_CD_Base4</value></prop>
+ <prop oor:name="UIName">
+ <value>PCD - Photo CD Base4</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/pct_Mac_Pict.xcu b/filter/source/config/fragments/types/pct_Mac_Pict.xcu
new file mode 100644
index 000000000..d2abc377d
--- /dev/null
+++ b/filter/source/config/fragments/types/pct_Mac_Pict.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="pct_Mac_Pict" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pct pict</value></prop>
+ <prop oor:name="MediaType"><value>image/x-pict</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>PCT - Mac Pict</value></prop>
+ <prop oor:name="UIName">
+ <value>PCT - Mac Pict</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/pcx_Zsoft_Paintbrush.xcu b/filter/source/config/fragments/types/pcx_Zsoft_Paintbrush.xcu
new file mode 100644
index 000000000..5365bd8aa
--- /dev/null
+++ b/filter/source/config/fragments/types/pcx_Zsoft_Paintbrush.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="pcx_Zsoft_Paintbrush" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pcx</value></prop>
+ <prop oor:name="MediaType"><value>image/x-pcx</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>PCX - Zsoft Paintbrush</value></prop>
+ <prop oor:name="UIName">
+ <value>PCX - Zsoft Paintbrush</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/pdf_Portable_Document_Format.xcu b/filter/source/config/fragments/types/pdf_Portable_Document_Format.xcu
new file mode 100644
index 000000000..056b42287
--- /dev/null
+++ b/filter/source/config/fragments/types/pdf_Portable_Document_Format.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="pdf_Portable_Document_Format" oor:op="replace" >
+ <prop oor:name="DetectService"/>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pdf</value></prop>
+ <prop oor:name="MediaType"><value>application/pdf</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>PDF - Portable Document Format</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/pgm_Portable_Graymap.xcu b/filter/source/config/fragments/types/pgm_Portable_Graymap.xcu
new file mode 100644
index 000000000..fd6c4c4ee
--- /dev/null
+++ b/filter/source/config/fragments/types/pgm_Portable_Graymap.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="pgm_Portable_Graymap" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>pgm</value></prop>
+ <prop oor:name="MediaType"><value>image/x-portable-graymap</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>PGM - Portable Graymap</value></prop>
+ <prop oor:name="UIName">
+ <value>PGM - Portable Graymap</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/png_Portable_Network_Graphic.xcu b/filter/source/config/fragments/types/png_Portable_Network_Graphic.xcu
new file mode 100644
index 000000000..7fe5e2adb
--- /dev/null
+++ b/filter/source/config/fragments/types/png_Portable_Network_Graphic.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="png_Portable_Network_Graphic" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>png</value></prop>
+ <prop oor:name="MediaType"><value>image/png</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>PNG - Portable Network Graphic</value></prop>
+ <prop oor:name="UIName">
+ <value>PNG - Portable Network Graphic</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/ppm_Portable_Pixelmap.xcu b/filter/source/config/fragments/types/ppm_Portable_Pixelmap.xcu
new file mode 100644
index 000000000..9fd7b8b9e
--- /dev/null
+++ b/filter/source/config/fragments/types/ppm_Portable_Pixelmap.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="ppm_Portable_Pixelmap" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>ppm</value></prop>
+ <prop oor:name="MediaType"><value>image/x-portable-pixmap</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>PPM - Portable Pixelmap</value></prop>
+ <prop oor:name="UIName">
+ <value>PPM - Portable Pixelmap</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/psd_Adobe_Photoshop.xcu b/filter/source/config/fragments/types/psd_Adobe_Photoshop.xcu
new file mode 100644
index 000000000..586541451
--- /dev/null
+++ b/filter/source/config/fragments/types/psd_Adobe_Photoshop.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="psd_Adobe_Photoshop" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>psd</value></prop>
+ <prop oor:name="MediaType"><value>image/vnd.adobe.photoshop</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>PSD - Adobe Photoshop</value></prop>
+ <prop oor:name="UIName">
+ <value>PSD - Adobe Photoshop</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/ras_Sun_Rasterfile.xcu b/filter/source/config/fragments/types/ras_Sun_Rasterfile.xcu
new file mode 100644
index 000000000..81b9238d1
--- /dev/null
+++ b/filter/source/config/fragments/types/ras_Sun_Rasterfile.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="ras_Sun_Rasterfile" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>ras</value></prop>
+ <prop oor:name="MediaType"><value>image/x-cmu-raster</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>RAS - Sun Rasterfile</value></prop>
+ <prop oor:name="UIName">
+ <value>RAS - Sun Raster Image</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
new file mode 100644
index 000000000..a2015a536
--- /dev/null
+++ b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="svg_Scalable_Vector_Graphics" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>svg svgz</value></prop>
+ <prop oor:name="MediaType"><value>image/svg+xml</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>SVG - Scalable Vector Graphics</value></prop>
+ <prop oor:name="UIName">
+ <value>SVG - Scalable Vector Graphics</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu
new file mode 100644
index 000000000..4b3b9cab5
--- /dev/null
+++ b/filter/source/config/fragments/types/svg_Scalable_Vector_Graphics_Draw.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="svg_Scalable_Vector_Graphics_Draw" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Draw.SVGFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>svg svgz</value></prop>
+ <prop oor:name="MediaType"><value>image/svg+xml</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>SVG - Scalable Vector Graphics Draw</value></prop>
+ <prop oor:name="UIName">
+ <value>SVG - Scalable Vector Graphics Draw</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/svm_StarView_Metafile.xcu b/filter/source/config/fragments/types/svm_StarView_Metafile.xcu
new file mode 100644
index 000000000..5d81959b5
--- /dev/null
+++ b/filter/source/config/fragments/types/svm_StarView_Metafile.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="svm_StarView_Metafile" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>svm</value></prop>
+ <prop oor:name="MediaType"><value>image/x-svm</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>SVM - StarView Metafile</value></prop>
+ <prop oor:name="UIName">
+ <value>SVM - StarView Meta File</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/tga_Truevision_TARGA.xcu b/filter/source/config/fragments/types/tga_Truevision_TARGA.xcu
new file mode 100644
index 000000000..248637d2f
--- /dev/null
+++ b/filter/source/config/fragments/types/tga_Truevision_TARGA.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="tga_Truevision_TARGA" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>tga</value></prop>
+ <prop oor:name="MediaType"><value>image/x-targa</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>TGA - Truevision TARGA</value></prop>
+ <prop oor:name="UIName">
+ <value>TGA - Truevision Targa</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/tif_Tag_Image_File.xcu b/filter/source/config/fragments/types/tif_Tag_Image_File.xcu
new file mode 100644
index 000000000..a84e66623
--- /dev/null
+++ b/filter/source/config/fragments/types/tif_Tag_Image_File.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="tif_Tag_Image_File" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>tif tiff</value></prop>
+ <prop oor:name="MediaType"><value>image/tiff</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>TIF - Tag Image File</value></prop>
+ <prop oor:name="UIName">
+ <value>TIFF - Tagged Image File Format</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/wav_Wave_Audio_File.xcu b/filter/source/config/fragments/types/wav_Wave_Audio_File.xcu
new file mode 100644
index 000000000..f30623270
--- /dev/null
+++ b/filter/source/config/fragments/types/wav_Wave_Audio_File.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="wav_Wave_Audio_File" oor:op="replace" >
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wav</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="UIName">
+ <value>Wave Audio File</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ <prop oor:name="DetectService"><value>com.sun.star.comp.framework.SoundHandler</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ </node>
diff --git a/filter/source/config/fragments/types/webp_WebP.xcu b/filter/source/config/fragments/types/webp_WebP.xcu
new file mode 100644
index 000000000..e58984fbe
--- /dev/null
+++ b/filter/source/config/fragments/types/webp_WebP.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="webp_WebP" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>webp</value></prop>
+ <prop oor:name="MediaType"><value>image/webp</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>WEBP - WebP</value></prop>
+ <prop oor:name="UIName">
+ <value>WEBP - WebP Image</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/wmf_MS_Windows_Metafile.xcu b/filter/source/config/fragments/types/wmf_MS_Windows_Metafile.xcu
new file mode 100644
index 000000000..7564dd057
--- /dev/null
+++ b/filter/source/config/fragments/types/wmf_MS_Windows_Metafile.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="wmf_MS_Windows_Metafile" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wmf wmz</value></prop>
+ <prop oor:name="MediaType"><value>image/x-wmf</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>WMF - MS Windows Metafile</value></prop>
+ <prop oor:name="UIName">
+ <value>WMF - Windows Metafile</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer8.xcu b/filter/source/config/fragments/types/writer8.xcu
new file mode 100644
index 000000000..8a2effbde
--- /dev/null
+++ b/filter/source/config/fragments/types/writer8.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer8" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/swriter</value></prop>
+ <prop oor:name="Extensions"><value>odt</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.text</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>writer8</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Writer 8</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer 8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer8_template.xcu b/filter/source/config/fragments/types/writer8_template.xcu
new file mode 100644
index 000000000..eeb4b3512
--- /dev/null
+++ b/filter/source/config/fragments/types/writer8_template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer8_template" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>ott</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.text-template</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>writer8_template</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Writer 8 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer 8 Template</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_AbiWord_Document.xcu b/filter/source/config/fragments/types/writer_AbiWord_Document.xcu
new file mode 100644
index 000000000..bb4527729
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_AbiWord_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_AbiWord_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.AbiWordImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>abw zabw</value></prop>
+ <prop oor:name="MediaType"><value>application/x-abiword</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>AbiWord</value></prop>
+ <prop oor:name="UIName">
+ <value>AbiWord Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_ApplePages.xcu b/filter/source/config/fragments/types/writer_ApplePages.xcu
new file mode 100644
index 000000000..823a766b5
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_ApplePages.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="writer_ApplePages" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Writer.PagesImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>pages</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/x-iwork-pages-sffpages</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>Apple Pages</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Apple Pages</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/writer_BroadBand_eBook.xcu b/filter/source/config/fragments/types/writer_BroadBand_eBook.xcu
new file mode 100644
index 000000000..129f33005
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_BroadBand_eBook.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="writer_BroadBand_eBook" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>lrf</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/x-sony-bbeb</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>BroadBand eBook</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>BroadBand eBook</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/writer_ClarisWorks.xcu b/filter/source/config/fragments/types/writer_ClarisWorks.xcu
new file mode 100644
index 000000000..f716ef01a
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_ClarisWorks.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_ClarisWorks" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>cwk</value></prop>
+ <prop oor:name="MediaType"><value>application/clarisworks</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>ClarisWorks</value></prop>
+ <prop oor:name="UIName">
+ <value>ClarisWorks/AppleWorks Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_DocBook_File.xcu b/filter/source/config/fragments/types/writer_DocBook_File.xcu
new file mode 100644
index 000000000..613588493
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_DocBook_File.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_DocBook_File" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xml</value></prop>
+ <prop oor:name="MediaType"><value>application/docbook+xml</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>DocBook File</value></prop>
+ <prop oor:name="UIName">
+ <value>DocBook</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>doctype:-//OASIS//DTD DocBook XML V4</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_DosWord.xcu b/filter/source/config/fragments/types/writer_DosWord.xcu
new file mode 100644
index 000000000..37333886a
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_DosWord.xcu
@@ -0,0 +1,22 @@
+<!--
+ * 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/.
+-->
+
+<node oor:name="writer_DosWord" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>com.sun.star.comp.Writer.MSWorksImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>doc</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>DosWord</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Word for DOS</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/writer_EPUB_Document.xcu b/filter/source/config/fragments/types/writer_EPUB_Document.xcu
new file mode 100644
index 000000000..51a0a73c2
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_EPUB_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_EPUB_Document" oor:op="replace" >
+ <prop oor:name="DetectService"/>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>epub</value></prop>
+ <prop oor:name="MediaType"><value>application/epub+zip</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>EPUB Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_FictionBook_2.xcu b/filter/source/config/fragments/types/writer_FictionBook_2.xcu
new file mode 100644
index 000000000..a6a543713
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_FictionBook_2.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="writer_FictionBook_2" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>fb2 zip</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/x-fictionbook+xml</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>FictionBook 2</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>FictionBook 2.0</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/writer_LotusWordPro_Document.xcu b/filter/source/config/fragments/types/writer_LotusWordPro_Document.xcu
new file mode 100644
index 000000000..ca30d232c
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_LotusWordPro_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_LotusWordPro_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.LotusWordProImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>lwp</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.lotus-wordpro</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>LotusWordPro</value></prop>
+ <prop oor:name="UIName">
+ <value>LotusWordPro Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MIZI_Hwp_97.xcu b/filter/source/config/fragments/types/writer_MIZI_Hwp_97.xcu
new file mode 100644
index 000000000..063795749
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MIZI_Hwp_97.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MIZI_Hwp_97" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.comp.hwpimport.HwpImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>hwp</value></prop>
+ <prop oor:name="MediaType"><value>application/x-hwp</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>writer_MIZI_Hwp_97</value></prop>
+ <prop oor:name="UIName">
+ <value>Hangul WP 97</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_WinWord_5.xcu b/filter/source/config/fragments/types/writer_MS_WinWord_5.xcu
new file mode 100644
index 000000000..87ee89e85
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_WinWord_5.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_WinWord_5" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.text.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>doc</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS WinWord 5</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft WinWord 1/2/5</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_WinWord_60.xcu b/filter/source/config/fragments/types/writer_MS_WinWord_60.xcu
new file mode 100644
index 000000000..21c3d854c
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_WinWord_60.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_WinWord_60" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.text.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>doc</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS WinWord 6.0</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Word 6.0</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Word_2003_XML.xcu b/filter/source/config/fragments/types/writer_MS_Word_2003_XML.xcu
new file mode 100644
index 000000000..60d132e20
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Word_2003_XML.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Word_2003_XML" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xml doc</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Word 2003 XML</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Word 2003 XML</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>doctype:wordDocument</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Word_2007_XML.xcu b/filter/source/config/fragments/types/writer_MS_Word_2007_XML.xcu
new file mode 100644
index 000000000..75cb091cd
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Word_2007_XML.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Word_2007" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>docx</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Word 2007 XML</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Word 2007–365</value></prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Word_2007_XML_Template.xcu b/filter/source/config/fragments/types/writer_MS_Word_2007_XML_Template.xcu
new file mode 100644
index 000000000..391cc20ce
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Word_2007_XML_Template.xcu
@@ -0,0 +1,27 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Word_2007_Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>dotx dotm</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Word 2007 XML Template</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Word 2007–365 Template</value></prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Word_2007_XML_VBA.xcu b/filter/source/config/fragments/types/writer_MS_Word_2007_XML_VBA.xcu
new file mode 100644
index 000000000..8a44c1e5f
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Word_2007_XML_VBA.xcu
@@ -0,0 +1,17 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="writer_MS_Word_2007_VBA" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>docm</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Word 2007 XML VBA</value></prop>
+ <prop oor:name="UIName"><value xml:lang="en-US">Word 2007–365 VBA</value></prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Word_95.xcu b/filter/source/config/fragments/types/writer_MS_Word_95.xcu
new file mode 100644
index 000000000..2051a5135
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Word_95.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Word_95" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.text.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>doc</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Word 95</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Word 95</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Word_95_Vorlage.xcu b/filter/source/config/fragments/types/writer_MS_Word_95_Vorlage.xcu
new file mode 100644
index 000000000..be6e9bbd5
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Word_95_Vorlage.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Word_95_Vorlage" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.text.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>dot</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Word 95 Vorlage</value></prop>
+ <prop oor:name="UIName">
+ <value>MS Word 95 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Word_97.xcu b/filter/source/config/fragments/types/writer_MS_Word_97.xcu
new file mode 100644
index 000000000..d1e250157
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Word_97.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Word_97" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.text.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>doc wps</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Word 97</value></prop>
+ <prop oor:name="UIName">
+ <value>Word 97–2003</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Word_97_Vorlage.xcu b/filter/source/config/fragments/types/writer_MS_Word_97_Vorlage.xcu
new file mode 100644
index 000000000..4aa82a4fb
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Word_97_Vorlage.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Word_97_Vorlage" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.text.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>dot wpt</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS Word 97 Vorlage</value></prop>
+ <prop oor:name="UIName">
+ <value>Word 97–2000 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Works_Document.xcu b/filter/source/config/fragments/types/writer_MS_Works_Document.xcu
new file mode 100644
index 000000000..51e50ed24
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Works_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Works_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MSWorksImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wps</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-works</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS_Works</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Works Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MS_Write.xcu b/filter/source/config/fragments/types/writer_MS_Write.xcu
new file mode 100644
index 000000000..48ae04b3c
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MS_Write.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MS_Write" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MSWorksImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wri</value></prop>
+ <prop oor:name="MediaType"><value>application/x-mswrite</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MS_Write</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Write</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_MacWrite.xcu b/filter/source/config/fragments/types/writer_MacWrite.xcu
new file mode 100644
index 000000000..9be82f113
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_MacWrite.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_MacWrite" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>mw mcw</value></prop>
+ <prop oor:name="MediaType"><value>application/macwriteii</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>MacWrite</value></prop>
+ <prop oor:name="UIName">
+ <value>MacWrite Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_Mac_Word.xcu b/filter/source/config/fragments/types/writer_Mac_Word.xcu
new file mode 100644
index 000000000..b598559da
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_Mac_Word.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_Mac_Word" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>doc</value></prop>
+ <prop oor:name="MediaType"><value>application/msword</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Mac_Word</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Word for Mac (v1 - v5)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_Mac_Works.xcu b/filter/source/config/fragments/types/writer_Mac_Works.xcu
new file mode 100644
index 000000000..9785ebc82
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_Mac_Works.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_Mac_Works" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wps</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.ms-works</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Mac_Works</value></prop>
+ <prop oor:name="UIName">
+ <value>Microsoft Works for Mac Document (v1 - v4)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_Mariner_Write.xcu b/filter/source/config/fragments/types/writer_Mariner_Write.xcu
new file mode 100644
index 000000000..d3df7576d
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_Mariner_Write.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_Mariner_Write" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>mwd</value></prop>
+ <prop oor:name="MediaType"><value></value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Mariner_Write</value></prop>
+ <prop oor:name="UIName">
+ <value>Mariner Write Mac Classic v1.6 - v3.5</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_ODT_FlatXML.xcu b/filter/source/config/fragments/types/writer_ODT_FlatXML.xcu
new file mode 100644
index 000000000..fc170564b
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_ODT_FlatXML.xcu
@@ -0,0 +1,31 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_ODT_FlatXML" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.XMLFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>fodt odt xml</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.text-flat-xml</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>OpenDocument Text Flat XML</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">OpenDocument Text (Flat XML)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat">
+ <value>doctype:office:mimetype="application/vnd.oasis.opendocument.text"</value>
+ </prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_OOXML.xcu b/filter/source/config/fragments/types/writer_OOXML.xcu
new file mode 100644
index 000000000..8d6a025fd
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_OOXML.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_OOXML" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>docx docm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.wordprocessingml.document</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Office Open XML Text</value></prop>
+ <prop oor:name="UIName">
+ <value>Office Open XML Text Document (Transitional)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_OOXML_Template.xcu b/filter/source/config/fragments/types/writer_OOXML_Template.xcu
new file mode 100644
index 000000000..39f499eb6
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_OOXML_Template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_OOXML_Text_Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.oox.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>dotx dotm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.openxmlformats-officedocument.wordprocessingml.template</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>Office Open XML Text Template</value></prop>
+ <prop oor:name="UIName">
+ <value>Office Open XML Text Template (Transitional)</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>MSWordDoc</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_PalmDoc.xcu b/filter/source/config/fragments/types/writer_PalmDoc.xcu
new file mode 100644
index 000000000..f45718ab8
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_PalmDoc.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="writer_PalmDoc" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>pdb</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/x-aportisdoc</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>PalmDoc</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>PalmDoc eBook</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/writer_Plucker_eBook.xcu b/filter/source/config/fragments/types/writer_Plucker_eBook.xcu
new file mode 100644
index 000000000..000d872a5
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_Plucker_eBook.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="writer_Plucker_eBook" oor:op="replace">
+ <prop oor:name="DetectService">
+ <value>org.libreoffice.comp.Writer.EBookImportFilter</value>
+ </prop>
+ <prop oor:name="Extensions">
+ <value>pdb</value>
+ </prop>
+ <prop oor:name="MediaType">
+ <value>application/prs.plucker</value>
+ </prop>
+ <prop oor:name="Preferred">
+ <value>true</value>
+ </prop>
+ <prop oor:name="PreferredFilter">
+ <value>Plucker eBook</value>
+ </prop>
+ <prop oor:name="UIName">
+ <value>Plucker eBook</value>
+ </prop>
+</node>
diff --git a/filter/source/config/fragments/types/writer_PocketWord_File.xcu b/filter/source/config/fragments/types/writer_PocketWord_File.xcu
new file mode 100644
index 000000000..3f146aba5
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_PocketWord_File.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_PocketWord_File" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MSWorksImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>psw</value></prop>
+ <prop oor:name="MediaType"><value>application/x-pocket-word</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>PocketWord File</value></prop>
+ <prop oor:name="UIName">
+ <value>Pocket Word</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>doctype:pwi</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_Rich_Text_Format.xcu b/filter/source/config/fragments/types/writer_Rich_Text_Format.xcu
new file mode 100644
index 000000000..76f28fb36
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_Rich_Text_Format.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_Rich_Text_Format" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.text.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>rtf</value></prop>
+ <prop oor:name="MediaType"><value>application/rtf</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>Rich Text Format</value></prop>
+ <prop oor:name="UIName">
+ <value>Rich Text Format</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_StarOffice_XML_Writer.xcu b/filter/source/config/fragments/types/writer_StarOffice_XML_Writer.xcu
new file mode 100644
index 000000000..e8dd8c275
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_StarOffice_XML_Writer.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_StarOffice_XML_Writer" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>sxw</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.writer</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>StarOffice XML (Writer)</value></prop>
+ <prop oor:name="UIName">
+ <value>OpenOffice.org 1.0 Text Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_StarOffice_XML_Writer_Template.xcu b/filter/source/config/fragments/types/writer_StarOffice_XML_Writer_Template.xcu
new file mode 100644
index 000000000..b5b19b58e
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_StarOffice_XML_Writer_Template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_StarOffice_XML_Writer_Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>stw</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.writer.template</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>writer_StarOffice_XML_Writer_Template</value></prop>
+ <prop oor:name="UIName">
+ <value>Writer 6.0 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_T602_Document.xcu b/filter/source/config/fragments/types/writer_T602_Document.xcu
new file mode 100644
index 000000000..e9b3df39c
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_T602_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_T602_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.T602ImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>602</value></prop>
+ <prop oor:name="MediaType"><value>application/x-t602</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>T602Document</value></prop>
+ <prop oor:name="UIName">
+ <value>T602 Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_WordPerfect_Document.xcu b/filter/source/config/fragments/types/writer_WordPerfect_Document.xcu
new file mode 100644
index 000000000..ba358d9b2
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_WordPerfect_Document.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_WordPerfect_Document" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.WordPerfectImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wpd</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.wordperfect</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>WordPerfect</value></prop>
+ <prop oor:name="UIName">
+ <value>WordPerfect Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_WriteNow.xcu b/filter/source/config/fragments/types/writer_WriteNow.xcu
new file mode 100644
index 000000000..b41b8af4b
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_WriteNow.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_WriteNow" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.Writer.MWAWImportFilter</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>wn nx^d</value></prop>
+ <prop oor:name="MediaType"><value></value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>WriteNow</value></prop>
+ <prop oor:name="UIName">
+ <value>WriteNow Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_globaldocument_StarOffice_XML_Writer_GlobalDocument.xcu b/filter/source/config/fragments/types/writer_globaldocument_StarOffice_XML_Writer_GlobalDocument.xcu
new file mode 100644
index 000000000..e920809e6
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_globaldocument_StarOffice_XML_Writer_GlobalDocument.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_globaldocument_StarOffice_XML_Writer_GlobalDocument" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>sxg</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.writer.global</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>writer_globaldocument_StarOffice_XML_Writer_GlobalDocument</value></prop>
+ <prop oor:name="UIName">
+ <value>Writer 6.0 Master Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer/Global 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_indexing_export_xml.xcu b/filter/source/config/fragments/types/writer_indexing_export_xml.xcu
new file mode 100644
index 000000000..4cda6e597
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_indexing_export_xml.xcu
@@ -0,0 +1,21 @@
+<!--
+ * 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/.
+ *
+-->
+
+<node oor:name="writer_indexing_export_xml" oor:op="replace" >
+ <prop oor:name="DetectService"/>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xml</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>Writer Indexing Export XML</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+</node>
diff --git a/filter/source/config/fragments/types/writer_layout_dump_xml.xcu b/filter/source/config/fragments/types/writer_layout_dump_xml.xcu
new file mode 100644
index 000000000..1f3a93de8
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_layout_dump_xml.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_layout_dump_xml" oor:op="replace" >
+ <prop oor:name="DetectService"/>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xml</value></prop>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"/>
+ <prop oor:name="UIName">
+ <value>Writer Layout Dump</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_web_HTML_help.xcu b/filter/source/config/fragments/types/writer_web_HTML_help.xcu
new file mode 100644
index 000000000..c558ebe6d
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_web_HTML_help.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_web_HTML_help" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.text.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"><value>vnd.sun.star.help://*</value></prop>
+ <prop oor:name="Extensions"/>
+ <prop oor:name="MediaType"/>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>writer_web_HTML_help</value></prop>
+ <prop oor:name="UIName">
+ <value>Help content</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/writer_web_StarOffice_XML_Writer_Web_Template.xcu b/filter/source/config/fragments/types/writer_web_StarOffice_XML_Writer_Web_Template.xcu
new file mode 100644
index 000000000..e81eebb28
--- /dev/null
+++ b/filter/source/config/fragments/types/writer_web_StarOffice_XML_Writer_Web_Template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writer_web_StarOffice_XML_Writer_Web_Template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>stw</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.sun.xml.writer.web</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>writer_web_StarOffice_XML_Writer_Web_Template</value></prop>
+ <prop oor:name="UIName">
+ <value>Writer/Web 6.0 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer/Web 6.0</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writerglobal8.xcu b/filter/source/config/fragments/types/writerglobal8.xcu
new file mode 100644
index 000000000..550a2a5ab
--- /dev/null
+++ b/filter/source/config/fragments/types/writerglobal8.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writerglobal8" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/swriter/GlobalDocument*</value></prop>
+ <prop oor:name="Extensions"><value>odm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.text-master</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>writerglobal8</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Writer 8 Master Document</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer/Global 8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writerglobal8_template.xcu b/filter/source/config/fragments/types/writerglobal8_template.xcu
new file mode 100644
index 000000000..10c866b5f
--- /dev/null
+++ b/filter/source/config/fragments/types/writerglobal8_template.xcu
@@ -0,0 +1,19 @@
+<!--
+ * 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/.
+-->
+ <node oor:name="writerglobal8_template" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"><value>private:factory/swriter/GlobalDocument*</value></prop>
+ <prop oor:name="Extensions"><value>otm</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.text-master-template</value></prop>
+ <prop oor:name="Preferred"><value>true</value></prop>
+ <prop oor:name="PreferredFilter"><value>writerglobal8_template</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Writer 8 Master Document Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer/Global 8 Template</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/writerweb8_writer_template.xcu b/filter/source/config/fragments/types/writerweb8_writer_template.xcu
new file mode 100644
index 000000000..9d1ace8ed
--- /dev/null
+++ b/filter/source/config/fragments/types/writerweb8_writer_template.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="writerweb8_writer_template" oor:op="replace">
+ <prop oor:name="DetectService"><value>com.sun.star.comp.filters.StorageFilterDetect</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>oth</value></prop>
+ <prop oor:name="MediaType"><value>application/vnd.oasis.opendocument.text-web</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>writerweb8_writer_template</value></prop>
+ <prop oor:name="UIName">
+ <value xml:lang="en-US">Writer/Web 8 Template</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"><value>Writer/Web 8</value></prop>
+ </node>
diff --git a/filter/source/config/fragments/types/xbm_X_Consortium.xcu b/filter/source/config/fragments/types/xbm_X_Consortium.xcu
new file mode 100644
index 000000000..55685d500
--- /dev/null
+++ b/filter/source/config/fragments/types/xbm_X_Consortium.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="xbm_X_Consortium" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xbm</value></prop>
+ <prop oor:name="MediaType"><value>image/x-xbitmap</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>XBM - X-Consortium</value></prop>
+ <prop oor:name="UIName">
+ <value>XBM - X Bitmap</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/fragments/types/xpm_XPM.xcu b/filter/source/config/fragments/types/xpm_XPM.xcu
new file mode 100644
index 000000000..585211ad8
--- /dev/null
+++ b/filter/source/config/fragments/types/xpm_XPM.xcu
@@ -0,0 +1,29 @@
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+ <node oor:name="xpm_XPM" oor:op="replace" >
+ <prop oor:name="DetectService"><value>com.sun.star.comp.draw.FormatDetector</value></prop>
+ <prop oor:name="URLPattern"/>
+ <prop oor:name="Extensions"><value>xpm</value></prop>
+ <prop oor:name="MediaType"><value>image/x-xpixmap</value></prop>
+ <prop oor:name="Preferred"><value>false</value></prop>
+ <prop oor:name="PreferredFilter"><value>XPM</value></prop>
+ <prop oor:name="UIName">
+ <value>XPM - X PixMap</value>
+ </prop>
+ <prop oor:name="ClipboardFormat"/>
+ </node>
diff --git a/filter/source/config/tools/merge/FCFGMerge.cfg b/filter/source/config/tools/merge/FCFGMerge.cfg
new file mode 100644
index 000000000..8a0b4b78f
--- /dev/null
+++ b/filter/source/config/tools/merge/FCFGMerge.cfg
@@ -0,0 +1,112 @@
+#
+# 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/.
+#
+# This file incorporates work covered by the following license notice:
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed
+# with this work for additional information regarding copyright
+# ownership. The ASF licenses this file to you under the Apache
+# License, Version 2.0 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.apache.org/licenses/LICENSE-2.0 .
+#
+
+#************************************************
+# Specify the verbose mode of this tool.
+# 1 = show errors only
+# 2 = show errors/warnings (default)
+# 3 = show errors/warnings and some generic infos
+# 4 = show anything (including detailed infos)
+#
+# [OPTIONAL]
+#************************************************
+
+loglevel = 2
+
+#************************************************
+# This extension is used for all XML files. It doesn't
+# matter if it's used for reading fragments or writing
+# XML packages.
+# Must be given without any additional signes like "."
+# or "*."!
+#
+# [REQUIRED]
+#************************************************
+
+extension_xcu=xcu
+
+#************************************************
+# This extension is used for all Package files. It doesn't
+# matter if it's used for reading such files or writing
+# it.
+# Must be given without any additional signes like "."
+# or "*."!
+#
+# [REQUIRED]
+#************************************************
+
+extension_pkg=pkg
+
+#************************************************
+# These values are used to generate a correct XML
+# header.
+# Note: The property "xmlpackage" must be specified
+# via command line. There exists more than one
+# possible value.
+#
+# [REQUIRED]
+#************************************************
+
+xmlversion = 1.0
+xmlencoding = UTF-8
+xmlpath = org.openoffice.TypeDetection
+#xmlpackage =
+
+#************************************************
+# These values are used to name the configuration
+# sets inside the generated XCM file for different
+# item groups like e.g. types, filters etcpp.
+#
+# [REQUIRED]
+#************************************************
+
+setname_types = Types
+setname_filters = Filters
+setname_frameloaders = FrameLoaders
+setname_contenthandlers = ContentHandlers
+
+subdir_types = types
+subdir_filters = filters
+subdir_frameloaders = frameloaders
+subdir_contenthandlers = contenthandlers
+
+#************************************************
+# This delimiter is used to split every
+# item list of the package configuration files
+# (which are temp. created by the make process)
+# into its tokens.
+#
+# [REQUIRED]
+#************************************************
+delimiter=,
+
+#************************************************
+# Enable/disable removing of leading/trailing whitespaces
+# during splitting stringlists.
+#
+# [REQUIRED]
+#************************************************
+trim=true
+
+#************************************************
+# Enable/disable removing of leading/trailing "-signs
+# during splitting stringlists.
+#
+# [REQUIRED]
+#************************************************
+decode=false
diff --git a/filter/source/config/tools/merge/pyAltFCFGMerge b/filter/source/config/tools/merge/pyAltFCFGMerge
new file mode 100755
index 000000000..7040108e8
--- /dev/null
+++ b/filter/source/config/tools/merge/pyAltFCFGMerge
@@ -0,0 +1,590 @@
+#!/usr/bin/env python
+#_____________________________________________
+# Caolan McNamara caolanm@redhat.com
+# converted from original java written by Andreas Schluens so we can continue
+# to build 680 OpenOffice.org series without java
+# this is not really a replacement for the existing java tool, just the
+# minimum required to make it work for now, the existing tool is still
+# the canonical base, changes to it will have to be mirrored here until
+# there is a java which is available for use by all
+#_____________________________________________
+
+import sys, string, os.path, codecs
+
+CFGFILE = os.environ["SRCDIR"] + "/filter/source/config/tools/merge/FCFGMerge.cfg"
+
+PROP_XMLVERSION = "xmlversion" # // <= global cfg file
+PROP_XMLENCODING = "xmlencoding" # // <= global cfg file
+PROP_XMLPATH = "xmlpath" # // <= global cfg file
+PROP_XMLPACKAGE = "xmlpackage" # // <= global cfg file
+PROP_SETNAME_TYPES = "setname_types" # // <= global cfg file
+PROP_SETNAME_FILTERS = "setname_filters" # // <= global cfg file
+PROP_SETNAME_LOADERS = "setname_frameloaders" # // <= global cfg file
+PROP_SETNAME_HANDLERS = "setname_contenthandlers" # // <= global cfg file
+PROP_SUBDIR_TYPES = "subdir_types" # // <= global cfg file
+PROP_SUBDIR_FILTERS = "subdir_filters" # // <= global cfg file
+PROP_SUBDIR_LOADERS = "subdir_frameloaders" # // <= global cfg file
+PROP_SUBDIR_HANDLERS = "subdir_contenthandlers" # // <= global cfg file
+PROP_EXTENSION_XCU = "extension_xcu" # // <= global cfg file
+PROP_EXTENSION_PKG = "extension_pkg" # // <= global cfg file
+PROP_DELIMITER = "delimiter" # // <= global cfg file
+PROP_TRIM = "trim" # // <= global cfg file
+PROP_DECODE = "decode" # // <= global cfg file
+PROP_FRAGMENTSDIR = "fragmentsdir" # // <= cmdline
+PROP_TEMPDIR = "tempdir" # // <= cmdline
+PROP_OUTDIR = "outdir" # // <= cmdline
+PROP_PKG = "pkg" # // <= cmdline
+PROP_TCFG = "tcfg" # // <= cmdline
+PROP_FCFG = "fcfg" # // <= cmdline
+PROP_LCFG = "lcfg" # // <= cmdline
+PROP_CCFG = "ccfg" # // <= cmdline
+PROP_LANGUAGEPACK = "languagepack" # // <= cmdline
+PROP_VERBOSE = "verbose" # // <= cmdline
+PROP_SHARE_SUBDIR_NAME = "share_subdir_name" # // <= cmdline
+PROP_ITEMS = "items" # // <= pkg cfg files!
+
+#---begin java.util.Properties copy---#
+r"""
+
+An incomplete clean room implementation of
+java.util.Properties written in Python.
+
+Copyright (C) 2002,2004 - Ollie Rutherfurd <oliver@rutherfurd.net>
+
+Based on:
+
+ http://java.sun.com/j2se/1.3/docs/api/java/util/Properties.html
+
+Missing:
+
+ - Currently, u\XXXX sequences are escaped when saving, but not unescaped
+ when read...
+
+License: Python License
+
+Example Usage:
+
+>>> from properties import Properties
+>>> props = Properties()
+>>> props['one'] = '1'
+>>> props['your name'] = "I don't know"
+>>> print('\n'.join(list(props.keys())))
+your name
+one
+>>> from StringIO import StringIO
+>>> buff = StringIO()
+>>> props.store(buff, "a little example...")
+>>> buff.seek(0)
+>>> print(buff.read())
+# a little example...
+your\ name=I\ don\'t\ know
+one=1
+>>> print(props['your name'])
+I don't know
+
+$Id: pyAltFCFGMerge,v 1.3 2007-12-07 10:57:44 vg Exp $
+
+"""
+
+__all__ = ['Properties']
+
+
+def dec2hex(n):
+ h = hex(n)[2:].upper()
+ return '\\u' + '0' * (4 - len(h)) + h
+
+
+def escapestr(s):
+ buff = []
+ # QUESTION: escape leading or trailing spaces?
+ for c in s:
+ if c == '\\':
+ buff.append('\\\\')
+ elif c == '\t':
+ buff.append('\\t')
+ elif c == '\n':
+ buff.append('\\n')
+ elif c == '\r':
+ buff.append('\\r')
+ elif c == ' ':
+ buff.append('\\ ')
+ elif c == "'":
+ buff.append("\\'")
+ elif c == '"':
+ buff.append('\\"')
+ elif c == '#':
+ buff.append('\\#')
+ elif c == '!':
+ buff.append('\\!')
+ elif c == '=':
+ buff.append('\\=')
+ elif 32 <= ord(c) <= 126:
+ buff.append(c)
+ else:
+ buff.append(dec2hex(c))
+
+ return ''.join(buff)
+
+
+# TODO: add support for \uXXXX?
+def unescapestr(line):
+ buff = []
+ escape = 0
+ for i in range(len(line)):
+ c = line[i]
+ if c == '\\':
+ if escape:
+ escape = 0
+ buff.append('\\')
+ continue
+ else:
+ # this is to deal with '\'
+ # acting as a line continuation
+ # character
+ if i == len(line) - 1:
+ buff.append('\\')
+ break
+ else:
+ escape = 1
+ continue
+ elif c == 'n':
+ if escape:
+ escape = 0
+ buff.append('\n')
+ continue
+ elif c == 'r':
+ if escape:
+ escape = 0
+ buff.append('\r')
+ continue
+ elif c == 't':
+ if escape:
+ escape = 0
+ buff.append('\t')
+ continue
+
+ buff.append(c)
+
+ # make sure escape doesn't stay one
+ # all expected escape sequences either break
+ # or continue, so this should be safe
+ if escape:
+ escape = 0
+
+ return ''.join(buff)
+
+
+class Properties(dict):
+ def __init__(self, defaults={}):
+ dict.__init__(self)
+ for n,v in list(defaults.items()):
+ self[n] = v
+
+ def __getittem__(self,key):
+ try:
+ return dict.__getittem__(self,key)
+ except KeyError:
+ return None
+
+ def read(self,filename):
+ """
+ Reads properties from a file (java Property class
+ reads from an input stream -- see load()).
+ """
+ f = None
+ try:
+ f = open(filename)
+ self.load(f)
+ finally:
+ if f:
+ f.close()
+
+ def load(self, buff):
+ """
+ Reads properties from a stream (StringIO, file, etc...)
+ """
+ props = readprops(buff)
+ for n,v in list(props.items()):
+ self[n] = v
+
+def readprops(buff):
+ name,value = None,''
+ props = {}
+ continued = 0
+
+ while 1:
+ line = buff.readline()
+ if not line:
+ break
+ line = line.strip()
+
+ # empty line
+ if not line:
+ continue
+
+ # comment
+ if line[0] in ('#','!'):
+ continue
+
+ # find name
+ i,escaped = 0,0
+ while i < len(line):
+ c = line[i]
+
+ if c == '\\':
+ if escaped:
+ escaped = 0
+ else:
+ escaped = 1
+ i += 1
+ continue
+
+ elif c in (' ', '\t', ':', '=') and not escaped:
+ name = unescapestr(line[:i])
+ break
+
+ # make sure escaped doesn't stay on
+ if escaped:
+ escaped = 0
+
+ i += 1
+
+ # no delimiter was found, name is entire line, there is no value
+ if name is None:
+ name = unescapestr(line.lstrip())
+
+ # skip delimiter
+ while line[i:i + 1] in ('\t', ' ', ':', '='):
+ i += 1
+
+ value = unescapestr(line[i:].strip())
+ while value[-1:] == '\\':
+ value = value[:-1] # remove \
+ line = buff.readline()
+ if not line:
+ break
+ value += unescapestr(line.strip())
+
+ props[name] = value
+
+ return props
+#---end java.util.Properties copy---#
+
+# It's a simple command line tool, which can merge different XML fragments
+# together. Such fragments must exist as files on disk, will be moved into
+# one file together on disk.
+
+def run(sCmdLine):
+ aCfg = ConfigHelper(CFGFILE, sCmdLine)
+ if aCfg.getValueWithDefault(PROP_VERBOSE,None) == None:
+ sys.stdout=None
+
+ printCopyright()
+
+ # help requested?
+ if aCfg.isHelp():
+ printHelp()
+ sys.exit(-1)
+
+ #create new merge object and start operation
+ aMerger = Merger(aCfg)
+ aMerger.merge()
+
+ sys.exit(0)
+
+def printOut(s):
+ if sys.stdout is None:
+ return
+ print(s)
+
+#prints out a copyright message on stdout.
+def printCopyright():
+ printOut("FCFGMerge")
+ printOut("Copyright: 2003 by Red Hat, Inc., based on FCFGMerge.java` by Sun")
+ printOut("All Rights Reserved.")
+
+# Prints out a help message on stdout.
+def printHelp():
+ printOut("____________________________________________________________")
+ printOut("usage: FCFGMerge cfg=<file name>" )
+ printOut("parameters:" )
+ printOut("\tcfg=<file name>" )
+ printOut("\t\tmust point to a system file, which contains" )
+ printOut("\t\tall necessary configuration data for the merge process.")
+ printOut("\tFurther cou can specify every parameter allowed in the" )
+ printOut("\tconfig file as command line parameter too, to overwrite" )
+ printOut("\tthe value from the file." )
+
+# Return a list of tokens given a base string and a string of
+# separators, optionally including the separators if asked for"""
+def StringTokenizer(mstring, separators, isSepIncluded = 0):
+ token = ''
+ tokenList = []
+ for c in mstring:
+ if c in separators:
+ if token != '':
+ tokenList.append(token)
+ token = ''
+ if isSepIncluded:
+ tokenList.append(c)
+ else:
+ token += c
+ if token:
+ tokenList.append(token)
+ return tokenList
+
+# Can be used to analyze command line parameters
+# and merge it together with might existing config
+# files. That provides the possibility to overwrite
+# config values via command line parameter.
+
+class ConfigHelper:
+ def __init__(self, sPropFile, lCommandLineArgs):
+ self.m_bEmpty = 1
+ # first load prop file, so its values can be overwritten
+ # by command line args later
+ # Do it only, if a valid file name was given.
+ # But in case this file name is wrong, throw an exception.
+ # So the outside code can react!
+ if sPropFile is not None and len(sPropFile) > 0:
+ self.props = Properties()
+ self.props.read(sPropFile)
+
+ count = 0
+ if lCommandLineArgs is not None:
+ count = len(lCommandLineArgs)
+ self.m_bEmpty = (count < 1)
+
+ # printOut(lCommandLineArgs, "and len is", count)
+ for arg in range(count):
+ # is it a named-value argument?
+ # Note: we ignore double "=" signs! => search from left to right
+ pos = lCommandLineArgs[arg].find('=')
+ if pos != -1:
+ sArg = lCommandLineArgs[arg][0:pos]
+ sValue = lCommandLineArgs[arg][pos + 1:]
+ self.props[sArg] = sValue
+ continue
+
+ # is it a boolean argument?
+ # Note: Because "--" and "-" will be interpreted as the same
+ # we search from right to left!
+ pos = lCommandLineArgs[arg].rfind('-')
+ if pos == -1:
+ pos = lCommandLineArgs[arg].rfind('/')
+ if pos != -1:
+ sArg = lCommandLineArgs[arg][pos + 1:]
+ self.props[sArg] = 1
+ continue
+
+ raise Exception("Invalid command line detected. The argument \"" + \
+ lCommandLineArgs[arg] + "\" use an unsupported format.")
+
+ def isHelp(self):
+ return ("help" in self.props) or ("?" in self.props) or ("?" in self.props)
+
+ def getValue(self, sProp):
+ if sProp not in self.props:
+ raise Exception("The requested config value \"" + sProp + "\" "\
+ "does not exists!");
+ return self.props[sProp];
+
+ def getValueWithDefault(self, sProp, default):
+ if sProp not in self.props:
+ return default;
+ return self.props[sProp];
+
+ def getStringList(self, sProp, sDelimiter, bTrim, bDecode):
+ if sProp not in self.props:
+ raise Exception("The requested config value \"" + sProp + "\" does "\
+ "not exists!");
+ sValue = self.props[sProp]
+
+ lValue = []
+ lTokens = StringTokenizer(sValue, sDelimiter)
+ for sToken in lTokens:
+ if bTrim:
+ sToken = sToken.strip()
+ # remove ""
+ if ((bDecode) and (sToken.find("\"") == 0) and \
+ (sToken.rfind("\"") == len(sToken) - 1)):
+ sToken = sToken[1, len(sToken) - 1]
+ lValue.append(sToken)
+
+ return lValue
+
+def generateHeader(sVersion, sEncoding, sPath, sPackage, bLanguagePack):
+ sHeader = "<?xml version=\""
+ sHeader += sVersion
+ sHeader += "\" encoding=\""
+ sHeader += sEncoding
+ sHeader += "\"?>\n"
+
+ if bLanguagePack:
+ sHeader += "<oor:component-data oor:package=\""
+ sHeader += sPath
+ sHeader += "\" oor:name=\""
+ sHeader += sPackage
+ sHeader += "\" xmlns:install=\"http://openoffice.org/2004/installation\""
+ sHeader += " xmlns:oor=\"http://openoffice.org/2001/registry\""
+ sHeader += " xmlns:xs=\"http://www.w3.org/2001/XMLSchema\""
+ sHeader += " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n"
+ else:
+ sHeader += "<oor:component-data xmlns:oor=\"http://openoffice.org/2001/registry\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" oor:package=\""
+ sHeader += sPath
+ sHeader += "\" oor:name=\""
+ sHeader += sPackage
+ sHeader += "\">\n"
+ return sHeader
+
+def generateFooter():
+ return "</oor:component-data>\n"
+
+# Can merge different xml fragments together.
+
+class Merger:
+ def __init__(self, aCfg):
+ self.m_aCfg = aCfg
+
+ self.m_aFragmentsDir = self.m_aCfg.getValue(PROP_FRAGMENTSDIR)
+
+ sDelimiter = self.m_aCfg.getValue(PROP_DELIMITER)
+ bTrim = self.m_aCfg.getValue(PROP_TRIM)
+ bDecode = self.m_aCfg.getValue(PROP_DECODE)
+
+ try:
+ aFcfg = ConfigHelper(self.m_aCfg.getValue(PROP_TCFG), None)
+ self.m_lTypes = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode)
+ except:
+ self.m_lTypes = []
+
+ try:
+ aFcfg = ConfigHelper(self.m_aCfg.getValue(PROP_FCFG), None)
+ self.m_lFilters = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode)
+ except:
+ self.m_lFilters = []
+
+ try:
+ aFcfg = ConfigHelper(self.m_aCfg.getValue(PROP_LCFG), None)
+ self.m_lLoaders = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode)
+ except:
+ self.m_lLoaders = []
+
+ try:
+ aFcfg = ConfigHelper(self.m_aCfg.getValue(PROP_CCFG), None)
+ self.m_lHandlers = aFcfg.getStringList(PROP_ITEMS, sDelimiter, bTrim, bDecode)
+ except:
+ self.m_lHandlers = []
+
+ # Merges the xml sets returned by getFragments(...), adds an xml header
+ # and footer and writes the result to a file.
+ def merge(self):
+ sPackage = self.m_aCfg.getValue(PROP_PKG)
+
+ printOut("create package \"" + sPackage + "\" ...")
+ printOut("generate package header ... ")
+
+ sBuffer = generateHeader(\
+ self.m_aCfg.getValue(PROP_XMLVERSION ),\
+ self.m_aCfg.getValue(PROP_XMLENCODING),\
+ self.m_aCfg.getValue(PROP_XMLPATH ),\
+ self.m_aCfg.getValue(PROP_XMLPACKAGE ),\
+ self.m_aCfg.getValueWithDefault(PROP_LANGUAGEPACK, False))
+
+ # counts all transferred fragments
+ # Can be used later to decide, if a generated package file
+ # contains "nothing"!
+ nItemCount = 0
+
+ for i in range(4):
+ sSetName = None
+ sSubDir = None
+ lFragments = None
+
+ try:
+ if i == 0: # types
+ printOut("generate set for types ... ")
+ sSetName = self.m_aCfg.getValue(PROP_SETNAME_TYPES)
+ sSubDir = self.m_aCfg.getValue(PROP_SUBDIR_TYPES)
+ lFragments = self.m_lTypes
+ elif i == 1: # filters
+ printOut("generate set for filter ... ")
+ sSetName = self.m_aCfg.getValue(PROP_SETNAME_FILTERS)
+ sSubDir = self.m_aCfg.getValue(PROP_SUBDIR_FILTERS)
+ lFragments = self.m_lFilters
+ elif i == 2: # loaders
+ printOut("generate set for frame loader ... ")
+ sSetName = self.m_aCfg.getValue(PROP_SETNAME_LOADERS)
+ sSubDir = self.m_aCfg.getValue(PROP_SUBDIR_LOADERS)
+ lFragments = self.m_lLoaders
+ elif i == 3: # handlers
+ printOut("generate set for content handler ... ")
+ sSetName = self.m_aCfg.getValue(PROP_SETNAME_HANDLERS)
+ sSubDir = self.m_aCfg.getValue(PROP_SUBDIR_HANDLERS)
+ lFragments = self.m_lHandlers
+ except:
+ continue
+
+ nItemCount = nItemCount + len(lFragments)
+
+ sBuffer = sBuffer + self.getFragments(\
+ os.path.join(self.m_aFragmentsDir, sSubDir), \
+ sSetName, lFragments, 1)
+
+ printOut("generate package footer ... ")
+ sBuffer = sBuffer + generateFooter()
+
+ # Attention!
+ # If the package seem to be empty, it makes no sense to generate a
+ # corresponding xml file. We should suppress writing of this file on
+ # disk completely ...
+ if nItemCount < 1:
+ printOut("Package is empty and will not result into a xml file on "\
+ "disk!? Please check configuration file.")
+ return
+ printOut("package contains " + str(nItemCount) + " items")
+
+ aPackage = codecs.open(sPackage, 'w', "utf-8")
+ printOut("write temp package \"" + sPackage)
+ aPackage.write(sBuffer)
+ aPackage.close()
+
+ # Reads the fragment files with the file names lFragments in directory aDir,
+ # formats them and returns a string that contains the merged fragments.
+ def getFragments(self, aDir, sSetName, lFragments, nPrettyTabs):
+ sBuffer = ''
+ sExtXcu = self.m_aCfg.getValue(PROP_EXTENSION_XCU);
+ sShareSubdirName = self.m_aCfg.getValue(PROP_SHARE_SUBDIR_NAME)
+ if len(sShareSubdirName) < 1:
+ raise Exception("no share subdir set")
+
+ if len(lFragments) < 1:
+ return sBuffer
+
+ for tabs in range(nPrettyTabs):
+ sBuffer = sBuffer + "\t"
+ sBuffer = sBuffer + "<node oor:name=\"" + sSetName + "\">\n"
+ nPrettyTabs = nPrettyTabs + 1
+
+ for sFragment in lFragments:
+ sFragPath = os.path.join(aDir, sFragment + "." + sExtXcu)
+ try:
+ aFragmentFile = codecs.open(sFragPath, "r", "utf-8")
+ except:
+ # handle simple files only and check for existence!
+ raise Exception("fragment \"" + sFragPath + "\" does not exists.")
+ printOut("merge fragment \"" + sFragPath + "\" ...")
+ data = aFragmentFile.read()
+ aFragmentFile.close()
+ data = data.replace("$(share_subdir_name)", sShareSubdirName)
+ sBuffer = sBuffer + data
+ sBuffer = sBuffer + "\n"
+
+ nPrettyTabs = nPrettyTabs - 1
+ for tabs in range(nPrettyTabs):
+ sBuffer = sBuffer + "\t"
+ sBuffer = sBuffer + "</node>\n"
+ return sBuffer
+
+run(sys.argv)
+
diff --git a/filter/source/docbook/DocBookTemplate.stw b/filter/source/docbook/DocBookTemplate.stw
new file mode 100644
index 000000000..ebc95f9f6
--- /dev/null
+++ b/filter/source/docbook/DocBookTemplate.stw
Binary files differ
diff --git a/filter/source/docbook/docbooktosoffheadings.xsl b/filter/source/docbook/docbooktosoffheadings.xsl
new file mode 100644
index 000000000..08d183863
--- /dev/null
+++ b/filter/source/docbook/docbooktosoffheadings.xsl
@@ -0,0 +1,1416 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:office="http://openoffice.org/2000/office" xmlns:style="http://openoffice.org/2000/style" xmlns:text="http://openoffice.org/2000/text" xmlns:table="http://openoffice.org/2000/table" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="http://openoffice.org/2000/meta" xmlns:number="http://openoffice.org/2000/datastyle" xmlns:svg="http://www.w3.org/2000/svg" xmlns:chart="http://openoffice.org/2000/chart" xmlns:dr3d="http://openoffice.org/2000/dr3d" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="http://openoffice.org/2000/form" xmlns:script="http://openoffice.org/2000/script" xmlns:config="http://openoffice.org/2001/config" office:class="text" office:version="1.0">
+ <xsl:decimal-format name="staff" digit="D"/>
+ <xsl:template match="/">
+ <xsl:element name="office:document">
+ <office:meta>
+ <dc:title>
+ <xsl:value-of select="/article/articleinfo/title"/>
+ </dc:title>
+ <dc:description></dc:description>
+ <dc:subject></dc:subject>
+ <dc:date>
+ <xsl:value-of select="article/articleinfo/pubdate"/>
+ </dc:date>
+ <dc:language>
+ <xsl:value-of select="article/@lang"/>
+ </dc:language>
+ <meta:user-defined meta:name="Info 1"/>
+ <meta:user-defined meta:name="Info 2"/>
+ <meta:user-defined meta:name="Info 3"/>
+ <meta:user-defined meta:name="Info 4"/>
+ </office:meta>
+ <office:font-decls>
+ <style:font-decl style:name="Tahoma1" fo:font-family="Tahoma"/>
+ <style:font-decl style:name="Thorndale" fo:font-family="Thorndale" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-decl style:name="Albany" fo:font-family="Albany" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ <style:font-decl style:name="Andale Sans UI" fo:font-family="'Andale Sans UI'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-decl style:name="MS Mincho" fo:font-family="'MS Mincho'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-decl style:name="Tahoma" fo:font-family="Tahoma" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-decls>
+ <office:styles>
+ <style:default-style style:family="graphics">
+ <style:properties draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false" style:use-window-font-color="true" fo:font-size="12pt" fo:language="en" fo:country="US" style:font-size-asian="12pt" style:language-asian="zxx" style:country-asian="none" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none">
+ <style:tab-stops/>
+ </style:properties>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="2.205cm" style:writing-mode="page" style:use-window-font-color="true" style:font-name="Thorndale" fo:font-size="12pt" fo:language="en" fo:country="US" style:font-name-asian="Andale Sans UI" style:font-size-asian="12pt" style:language-asian="zxx" style:country-asian="none" style:font-name-complex="Tahoma" style:font-size-complex="12pt" style:language-complex="zxx" style:country-complex="none" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:properties table:border-model="separating"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:properties fo:keep-together="always"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text">
+ <style:properties fo:margin-top="0cm" fo:margin-bottom="0.212cm"/>
+ </style:style>
+ <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text body" style:class="text">
+ <style:properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" fo:keep-with-next="true" style:font-name="Albany" fo:font-size="14pt" style:font-name-asian="MS Mincho" style:font-size-asian="14pt" style:font-name-complex="Tahoma" style:font-size-complex="14pt"/>
+ </style:style>
+ <style:style style:name="Heading 1" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text body" style:class="text">
+ <style:properties fo:font-size="115%" fo:font-weight="bold" style:font-size-asian="115%" style:font-weight-asian="bold" style:font-size-complex="115%" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Heading 2" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text body" style:class="text">
+ <style:properties fo:font-size="14pt" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-style-complex="italic" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Heading 3" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text body" style:class="text">
+ <style:properties fo:font-size="14pt" fo:font-weight="bold" style:font-size-asian="14pt" style:font-weight-asian="bold" style:font-size-complex="14pt" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Heading 4" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text body" style:class="text">
+ <style:properties fo:font-size="85%" fo:font-style="italic" fo:font-weight="bold" style:font-size-asian="85%" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-style-complex="italic" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text body" style:class="list">
+ <style:properties style:font-name-complex="Tahoma1"/>
+ </style:style>
+ <style:style style:name="Table Contents" style:family="paragraph" style:parent-style-name="Text body" style:class="extra">
+ <style:properties text:number-lines="false" text:line-number="0"/>
+ </style:style>
+ <style:style style:name="Table Heading" style:family="paragraph" style:parent-style-name="Table Contents" style:class="extra">
+ <style:properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0" fo:font-style="italic" fo:font-weight="bold" style:font-style-asian="italic" style:font-weight-asian="bold" style:font-style-complex="italic" style:font-weight-complex="bold"/>
+ </style:style>
+ <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
+ <style:properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" text:number-lines="false" text:line-number="0" fo:font-size="10pt" fo:font-style="italic" style:font-size-asian="10pt" style:font-style-asian="italic" style:font-size-complex="10pt" style:font-style-complex="italic"/>
+ </style:style>
+ <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"/>
+ <style:style style:name="Frame contents" style:family="paragraph" style:parent-style-name="Text body" style:class="extra"/>
+ <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra">
+ <style:properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="-0.499cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0" fo:font-size="10pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/>
+ </style:style>
+ <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index">
+ <style:properties text:number-lines="false" text:line-number="0" style:font-name-complex="Tahoma1"/>
+ </style:style>
+ <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text body" style:class="chapter">
+ <style:properties fo:text-align="center" style:justify-single-word="false" fo:font-size="14pt" fo:font-style="italic" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/>
+ </style:style>
+ <style:style style:name="Mediaobject" style:family="paragraph" style:class="text"/>
+ <style:style style:name="Object" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"/>
+ <style:style style:name="Section Title" style:family="paragraph" style:next-style-name="Text body" style:master-page-name="">
+ <style:properties fo:line-height="200%" fo:text-transform="capitalize" fo:font-size="14pt"/>
+ </style:style>
+ <style:style style:name="Appendix Title" style:family="paragraph" style:next-style-name="Text body" style:master-page-name="">
+ <style:properties fo:line-height="200%" fo:text-transform="capitalize" fo:font-size="14pt"/>
+ </style:style>
+ <style:style style:name="Section1 Title" style:family="paragraph" style:next-style-name="Text body" style:master-page-name="">
+ <style:properties fo:line-height="200%" fo:text-transform="capitalize" fo:font-size="14pt"/>
+ </style:style>
+ <style:style style:name="Section2 Title" style:family="paragraph" style:next-style-name="Text body" style:master-page-name="">
+ <style:properties fo:line-height="200%" fo:text-transform="capitalize" fo:font-size="13pt"/>
+ </style:style>
+ <style:style style:name="Section3 Title" style:family="paragraph" style:next-style-name="Text body" style:master-page-name="">
+ <style:properties fo:line-height="200%" fo:text-transform="capitalize" fo:font-size="12pt"/>
+ </style:style>
+ <style:style style:name="Section4 Title" style:family="paragraph" style:next-style-name="Text body" style:master-page-name="">
+ <style:properties fo:line-height="200%" fo:text-transform="capitalize" fo:font-size="12pt"/>
+ </style:style>
+ <style:style style:name="Section5 Title" style:family="paragraph" style:next-style-name="Text body" style:master-page-name="">
+ <style:properties fo:line-height="200%" fo:text-transform="capitalize" fo:font-size="12pt"/>
+ </style:style>
+ <style:style style:name="Document Title" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Document SubTitle">
+ <style:properties fo:text-align="center" style:justify-single-word="false" fo:font-size="20pt"/>
+ </style:style>
+ <style:style style:name="Document SubTitle" style:family="paragraph" style:parent-style-name="Document Title" style:next-style-name="Text body">
+ <style:properties fo:font-size="14pt"/>
+ </style:style>
+ <style:style style:name="Section SubTitle" style:family="paragraph" style:parent-style-name="Section Title"/>
+ <style:style style:name="CopyRight" style:family="paragraph" style:parent-style-name="Text body"/>
+ <style:style style:name="VarList Item" style:family="paragraph" style:parent-style-name="Text body" style:list-style-name="Var List" style:class="text">
+ <style:properties fo:margin-left="3cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false">
+ <style:tab-stops>
+ <style:tab-stop style:position="0cm"/>
+ </style:tab-stops>
+ </style:properties>
+ </style:style>
+ <style:style style:name="VarList Term" style:family="paragraph" style:parent-style-name="Text body" style:list-style-name="Var List" style:class="text">
+ <style:properties fo:margin-left="1cm" fo:margin-right="0cm" fo:text-indent="-4.5cm" style:auto-text-indent="false">
+ <style:tab-stops>
+ <style:tab-stop style:position="0cm"/>
+ </style:tab-stops>
+ </style:properties>
+ </style:style>
+ <style:style style:name="Footnote Symbol" style:family="text"/>
+ <style:style style:name="Numbering Symbols" style:family="text"/>
+ <style:style style:name="Bullet Symbols" style:family="text">
+ <style:properties fo:font-size="9pt" style:font-size-asian="9pt" style:font-size-complex="9pt"/>
+ </style:style>
+ <style:style style:name="Internet link" style:family="text">
+ <style:properties fo:color="#000080" style:text-underline-color="font-color" style:text-underline="single"/>
+ </style:style>
+ <style:style style:name="Endnote Symbol" style:family="text"/>
+ <style:style style:name="Emphasis" style:family="text">
+ <style:properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/>
+ </style:style>
+ <style:style style:name="Source Text" style:family="text"/>
+ <style:style style:name="Highlight" style:family="text">
+ <style:properties style:text-background-color="#fff000"/>
+ </style:style>
+ <style:style style:name="KeyCap" style:family="text">
+ <style:properties fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="Command" style:family="text">
+ <style:properties fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="Application" style:family="text">
+ <style:properties fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="FileName" style:family="text">
+ <style:properties fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="SuperScript" style:family="text">
+ <style:properties style:text-position="super 58%"/>
+ </style:style>
+ <style:style style:name="SubScript" style:family="text">
+ <style:properties style:text-position="sub 58%"/>
+ </style:style>
+ <style:style style:name="SystemItem" style:family="text">
+ <style:properties fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="ComputerOutput" style:family="text">
+ <style:properties fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="KeyCombo" style:family="text">
+ <style:properties fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="KeySym" style:family="text">
+ <style:properties fo:font-weight="bold"/>
+ </style:style>
+ <style:style style:name="GuiMenu" style:family="text">
+ <style:properties fo:color="#000fff" fo:font-style="italic"/>
+ </style:style>
+ <style:style style:name="GuiSubMenu" style:family="text">
+ <style:properties fo:color="#ff9966" fo:font-style="italic"/>
+ </style:style>
+ <style:style style:name="GuiButton" style:family="text">
+ <style:properties fo:color="#00f0ff" fo:font-style="italic"/>
+ </style:style>
+ <style:style style:name="GuiMenuItem" style:family="text">
+ <style:properties fo:color="#00ffff" fo:font-style="italic"/>
+ </style:style>
+ <style:style style:name="GuiLabel" style:family="text">
+ <style:properties fo:color="#00777f" fo:font-style="italic"/>
+ </style:style>
+ <style:style style:name="Frame" style:family="graphics">
+ <style:properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" fo:margin-left="0.201cm" fo:margin-right="0.201cm" fo:margin-top="0.201cm" fo:margin-bottom="0.201cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:padding="0.15cm" fo:border="0.002cm solid #000000"/>
+ </style:style>
+ <text:outline-style>
+ <text:outline-level-style text:level="1" style:num-format=""/>
+ <text:outline-level-style text:level="2" style:num-format=""/>
+ <text:outline-level-style text:level="3" style:num-format=""/>
+ <text:outline-level-style text:level="4" style:num-format=""/>
+ <text:outline-level-style text:level="5" style:num-format=""/>
+ <text:outline-level-style text:level="6" style:num-format=""/>
+ <text:outline-level-style text:level="7" style:num-format=""/>
+ <text:outline-level-style text:level="8" style:num-format=""/>
+ <text:outline-level-style text:level="9" style:num-format=""/>
+ <text:outline-level-style text:level="10" style:num-format=""/>
+ </text:outline-style>
+ <text:list-style style:name="Ordered List">
+ <text:list-level-style-number text:level="1" text:style-name="Numbering Symbols" style:num-suffix="." style:num-format="1">
+ <style:properties text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="0.501cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="1cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="1.501cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="2cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="6" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="2.501cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="7" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="3.001cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="8" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="3.502cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="9" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="4.001cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1">
+ <style:properties text:space-before="4.502cm" text:min-label-width="0.499cm"/>
+ </text:list-level-style-number>
+ </text:list-style>
+ <text:list-style style:name="UnOrdered List">
+ <text:list-level-style-bullet text:level="1" text:style-name="Bullet Symbols" text:bullet-char="•">
+ <style:properties text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:style-name="Bullet Symbols" text:bullet-char="•">
+ <style:properties text:space-before="0.501cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="1cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="1.501cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="2cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="2.501cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="3.001cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="3.502cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="4.001cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="4.502cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:list-style style:name="Var List">
+ <text:list-level-style-bullet text:level="1" text:style-name="Bullet Symbols" text:bullet-char="•">
+ <style:properties text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="2" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="0.501cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="3" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="1cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="4" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="1.501cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="5" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="2cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="6" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="2.501cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="7" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="3.001cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="8" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="3.502cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="9" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="4.001cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ <text:list-level-style-bullet text:level="10" text:style-name="Bullet Symbols" style:num-suffix="." text:bullet-char="•">
+ <style:properties text:space-before="4.502cm" text:min-label-width="0.499cm" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </text:list-level-style-bullet>
+ </text:list-style>
+ <text:footnotes-configuration text:citation-style-name="Footnote Symbol" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="page"/>
+ <text:endnotes-configuration text:citation-style-name="Endnote Symbol" text:master-page-name="Endnote" style:num-format="1" text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+ <style:page-master style:name="pm1">
+ <style:properties fo:page-width="20.999cm" fo:page-height="29.699cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2.54cm" fo:margin-bottom="2.54cm" fo:margin-left="3.175cm" fo:margin-right="3.175cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm">
+ <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-master>
+ <style:page-master style:name="pm2">
+ <style:properties fo:page-width="20.999cm" fo:page-height="29.699cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm">
+ <style:footnote-sep style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-master>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-master-name="pm1"/>
+ <style:master-page style:name="Endnote" style:page-master-name="pm2"/>
+ </office:master-styles>
+ <office:body>
+ <xsl:apply-templates/>
+ </office:body>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="subtitle">
+ <xsl:choose>
+ <xsl:when test="parent::table">
+ <xsl:apply-templates/>
+ </xsl:when>
+ <xsl:when test="parent::informaltable">
+ <xsl:apply-templates/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="text:p">
+ <xsl:attribute name="text:style-name">Section SubTitle</xsl:attribute>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+
+
+ <xsl:template match="title">
+ <xsl:choose>
+ <xsl:when test="parent::figure"></xsl:when>
+ <xsl:when test="parent::table"></xsl:when>
+ <xsl:when test="parent::sect1"></xsl:when>
+ <xsl:when test="parent::sect2"></xsl:when>
+ <xsl:when test="parent::sect3"></xsl:when>
+ <xsl:when test="parent::sect4"></xsl:when>
+ <xsl:when test="parent::sect5"></xsl:when>
+ <xsl:when test="parent::informaltable">
+ <xsl:apply-templates/>
+ </xsl:when>
+
+ <xsl:otherwise>
+ <xsl:element name="text:p">
+ <xsl:choose>
+
+ <xsl:when test="parent::appendix">
+ <xsl:attribute name="text:style-name">Appendix Title</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="articleinfo">
+ <xsl:element name="text:section">
+ <xsl:attribute name="text:style-name">ArticleInfo</xsl:attribute>
+ <xsl:attribute name="text:name">ArticleInfo</xsl:attribute>
+ <xsl:if test="/article/articleinfo/title !=''">
+ <xsl:element name="text:p">
+ <xsl:attribute name="text:style-name">Document Title</xsl:attribute>
+ <xsl:value-of select="/article/articleinfo/title"/>
+ </xsl:element>
+ <xsl:if test="/article/articleinfo/subtitle !=''">
+ <xsl:element name="text:p">
+ <xsl:attribute name="text:style-name">Document SubTitle</xsl:attribute>
+ <xsl:value-of select="/article/articleinfo/subtitle"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </xsl:element>
+
+ </xsl:template>
+
+ <xsl:template match="appendix">
+ <xsl:element name="text:section">
+ <xsl:attribute name="text:style-name">Appendix</xsl:attribute>
+ <xsl:attribute name="text:name">Appendix</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+
+ </xsl:template>
+
+<!--
+<xsl:template match="author">
+ <xsl:apply-templates/>
+</xsl:template>
+
+<xsl:template match="firstname">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:name">
+ <xsl:if test="ancestor::articleinfo/author">
+ <xsl:text disable-output-escaping="yes">articleinfo.author</xsl:text><xsl:value-of select="count(parent::author[preceding-sibling::author])"/><xsl:text disable-output-escaping="yes">.firstname</xsl:text><xsl:value-of select="count(preceding-sibling::firstname)"/>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+
+</xsl:template>-->
+
+ <xsl:template match="articleinfo/title">
+ <!-- <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.title</xsl:text>
+ </xsl:attribute>
+ </xsl:element>
+
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.title</xsl:text>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>--></xsl:template>
+
+ <xsl:template match="articleinfo/subtitle">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.subtitle</xsl:text>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.subtitle</xsl:text>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="articleinfo/edition">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.edition</xsl:text>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.edition</xsl:text>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="articleinfo/releaseinfo">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.releaseinfo_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::releaseinfo)"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.releaseinfo_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::releaseinfo)"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="author/firstname">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+
+ <xsl:attribute name="text:name">
+ <xsl:if test="ancestor::articleinfo">
+ <xsl:text disable-output-escaping="yes">articleinfo.author_</xsl:text>
+ <xsl:value-of select="count(parent::author[preceding-sibling::author])"/>
+ <xsl:text disable-output-escaping="yes">.firstname_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::firstname)"/>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:if test="ancestor::articleinfo">
+ <xsl:text disable-output-escaping="yes">articleinfo.author_</xsl:text>
+ <xsl:value-of select="count(parent::author[preceding-sibling::author])"/>
+ <xsl:text disable-output-escaping="yes">.firstname_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::firstname)"/>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+
+
+ <xsl:template match="articleinfo/copyright/year">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+
+ <xsl:attribute name="text:name">
+ <xsl:if test="ancestor::articleinfo/copyright">
+ <xsl:text disable-output-escaping="yes">articleinfo.copyright_</xsl:text>
+ <xsl:value-of select="count(parent::copyright[preceding-sibling::copyright])"/>
+ <xsl:text disable-output-escaping="yes">.year_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::year)"/>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:if test="ancestor::articleinfo/copyright">
+ <xsl:text disable-output-escaping="yes">articleinfo.copyright_</xsl:text>
+ <xsl:value-of select="count(parent::copyright[preceding-sibling::copyright])"/>
+ <xsl:text disable-output-escaping="yes">.year_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::year)"/>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="authorgroup">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="articleinfo/copyright/holder">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+
+ <xsl:attribute name="text:name">
+ <xsl:if test="ancestor::articleinfo/copyright">
+ <xsl:text disable-output-escaping="yes">articleinfo.copyright_</xsl:text>
+ <xsl:value-of select="count(parent::copyright[preceding-sibling::copyright])"/>
+ <xsl:text disable-output-escaping="yes">.holder_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::holder)"/>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:if test="ancestor::articleinfo/copyright">
+ <xsl:text disable-output-escaping="yes">articleinfo.copyright_</xsl:text>
+ <xsl:value-of select="count(parent::copyright[preceding-sibling::copyright])"/>
+ <xsl:text disable-output-escaping="yes">.holder_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::holder)"/>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+
+
+
+ <xsl:template name="affiliation">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="author/affiliation/address">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.author_</xsl:text>
+ <xsl:value-of select="count(ancestor::author[preceding-sibling::author])"/>
+ <xsl:text disable-output-escaping="yes">.affiliation_</xsl:text>
+ <xsl:value-of select="count(parent::affiliation[preceding-sibling::affiliation])"/>
+ <xsl:text disable-output-escaping="yes">.address_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::address)"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.author_</xsl:text>
+ <xsl:value-of select="count(ancestor::author[preceding-sibling::author])"/>
+ <xsl:text disable-output-escaping="yes">.affiliation_</xsl:text>
+ <xsl:value-of select="count(parent::affiliation[preceding-sibling::affiliation])"/>
+ <xsl:text disable-output-escaping="yes">.address_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::address)"/>
+
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="author/affiliation/orgname">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:if test="ancestor::articleinfo">
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.author_</xsl:text>
+ <xsl:value-of select="count(ancestor::author[preceding-sibling::author])"/>
+ <xsl:text disable-output-escaping="yes">.affiliation_</xsl:text>
+ <xsl:value-of select="count(parent::affiliation[preceding-sibling::affiliation])"/>
+ <xsl:text disable-output-escaping="yes">.orgname_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::orgname)"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:if test="ancestor::articleinfo">
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.author_</xsl:text>
+ <xsl:value-of select="count(ancestor::author[preceding-sibling::author])"/>
+ <xsl:text disable-output-escaping="yes">.affiliation_</xsl:text>
+ <xsl:value-of select="count(parent::affiliation[preceding-sibling::affiliation])"/>
+ <xsl:text disable-output-escaping="yes">.orgname_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::orgname)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+
+
+ <xsl:template match="author/surname">
+ <xsl:element name="text:variable-decls">
+ <xsl:element name="text:variable-decl">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.author_</xsl:text>
+ <xsl:value-of select="count(parent::author[preceding-sibling::author])"/>
+ <xsl:text disable-output-escaping="yes">.surname_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::surname)"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="text:p">
+ <xsl:element name="text:variable-set">
+ <xsl:attribute name="text:value-type">
+ <xsl:text>string</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="text:name">
+ <xsl:text disable-output-escaping="yes">articleinfo.author_</xsl:text>
+ <xsl:value-of select="count(parent::author[preceding-sibling::author])"/>
+ <xsl:text disable-output-escaping="yes">.surname_</xsl:text>
+ <xsl:value-of select="count(preceding-sibling::surname)"/>
+
+
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+
+
+
+
+ <xsl:template match="para">
+
+ <xsl:element name="text:p">
+
+ <xsl:choose>
+ <xsl:when test="ancestor-or-self::footnote">
+ <xsl:attribute name="text:style-name">Footnote</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ancestor-or-self::listitem">
+ <xsl:attribute name="text:style-name">VarList Item</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ancestor-or-self::informaltable">
+ <xsl:if test="ancestor-or-self::informaltable">
+ <xsl:attribute name="text:style-name">Table Contents</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::thead">
+ <xsl:attribute name="text:style-name">Table Heading</xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="ancestor-or-self::table">
+ <xsl:if test="ancestor-or-self::table">
+ <xsl:attribute name="text:style-name">Table Contents</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::thead">
+ <xsl:attribute name="text:style-name">Table Heading</xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:style-name">Text body</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:apply-templates/>
+ </xsl:element>
+
+ </xsl:template>
+
+ <xsl:template match="section">
+ <xsl:element name="text:h">
+ <xsl:attribute name="text:level">
+ <xsl:value-of select="count(ancestor-or-self::section)"/>
+ </xsl:attribute>
+ <xsl:value-of select="child::title"/>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="abstract">
+ <xsl:element name="text:h">
+ <xsl:attribute name="text:level">1</xsl:attribute>
+ <xsl:text>abstract</xsl:text>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+
+ <xsl:template match="appendix">
+ <xsl:element name="text:h">
+ <xsl:attribute name="text:level">1</xsl:attribute>
+ <xsl:text>appendix</xsl:text>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="sect1">
+ <xsl:element name="text:h">
+ <xsl:attribute name="text:level">1</xsl:attribute>
+ <xsl:attribute name="text:style-name">Heading 1</xsl:attribute>
+ <xsl:value-of select="child::title"/>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="sect2">
+ <xsl:element name="text:h">
+ <xsl:attribute name="text:level">2</xsl:attribute>
+ <xsl:attribute name="text:style-name">Heading 2</xsl:attribute>
+ <xsl:value-of select="child::title"/>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="sect3">
+ <xsl:element name="text:h">
+ <xsl:attribute name="text:level">3</xsl:attribute>
+ <xsl:attribute name="text:style-name">Heading 3</xsl:attribute>
+ <xsl:value-of select="child::title"/>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="sect4">
+ <xsl:element name="text:h">
+ <xsl:attribute name="text:level">4</xsl:attribute>
+ <xsl:attribute name="text:style-name">Heading 4</xsl:attribute>
+ <xsl:value-of select="child::title"/>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="sect5">
+ <xsl:element name="text:h">
+ <xsl:attribute name="text:level">5</xsl:attribute>
+ <xsl:value-of select="child::title"/>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+<!--<xsl:template match="sect5">
+ <xsl:element name="text:section">
+ <xsl:attribute name="text:style-name">Sect1</xsl:attribute>
+ <xsl:attribute name="text:name"><xsl:value-of select="@id"/></xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+</xsl:template>-->
+
+
+ <xsl:template match="informaltable">
+ <xsl:element name="table:table">
+ <xsl:attribute name="table:name"></xsl:attribute>
+ <xsl:attribute name="table:style-name">Table1</xsl:attribute>
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="table">
+ <xsl:variable name="tabletitle">
+ <xsl:value-of select="title"/>
+ </xsl:variable>
+ <xsl:element name="table:table">
+ <xsl:attribute name="table:name"></xsl:attribute>
+ <xsl:attribute name="table:style-name">Table1</xsl:attribute>
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="@id"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ <xsl:if test="not($tabletitle='')">
+ <xsl:element name="text:p">
+ <xsl:attribute name="text:style-name">Table</xsl:attribute>
+ <xsl:value-of select="$tabletitle"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="tgroup">
+ <xsl:element name="table:table-column">
+ <xsl:attribute name="table:style-name">Table1.A</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@cols >0">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="@cols"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="count(child::tbody/row/entry) div count(child::tbody/row)"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+
+ <xsl:template match="indexterm"></xsl:template>
+
+ <xsl:template match="thead">
+ <xsl:element name="table:table-header-rows">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="tbody">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="row">
+ <xsl:element name="table:table-row">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="entry">
+ <xsl:element name="table:table-cell">
+ <xsl:if test="ancestor-or-self::thead">
+ <xsl:attribute name="table:style-name">Table1.A1</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(ancestor-or-self::thead)">
+ <xsl:attribute name="table:style-name">Table1.A2</xsl:attribute>
+ </xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="@spanname">
+ <!--<xsl:if test="@spanname">-->
+ <xsl:variable name="sname">
+ <xsl:value-of select="@spanname"/>
+ </xsl:variable>
+ <xsl:attribute name="table:number-columns-spanned">
+ <xsl:variable name="colnamestart">
+ <xsl:value-of select="ancestor::tgroup/spanspec[@spanname=$sname]/@namest"/>
+ </xsl:variable>
+ <xsl:variable name="colnameend">
+ <xsl:value-of select="ancestor::tgroup/spanspec[@spanname=$sname]/@nameend"/>
+ </xsl:variable>
+ <xsl:variable name="colnumstart">
+ <xsl:value-of select="ancestor::tgroup/colspec[@colname=$colnamestart]/@colnum"/>
+ </xsl:variable>
+ <xsl:variable name="colnumend">
+ <xsl:value-of select="ancestor::tgroup/colspec[@colname=$colnameend]/@colnum"/>
+ </xsl:variable>
+ <xsl:value-of select="$colnumend - $colnumstart + 1"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@namest and @nameend">
+ <!--<xsl:if test="@namest and @nameend">-->
+ <xsl:variable name="colnamestart">
+ <xsl:value-of select="@namest"/>
+ </xsl:variable>
+ <xsl:variable name="colnameend">
+ <xsl:value-of select="@nameend"/>
+ </xsl:variable>
+
+ <xsl:attribute name="table:number-columns-spanned">
+ <xsl:variable name="colnumstart">
+ <xsl:value-of select="ancestor::tgroup/colspec[@colname=$colnamestart]/@colnum"/>
+ </xsl:variable>
+ <xsl:variable name="colnumend">
+ <xsl:value-of select="ancestor::tgroup/colspec[@colname=$colnameend]/@colnum"/>
+ </xsl:variable>
+ <xsl:value-of select="$colnumend - $colnumstart + 1"/>
+
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <!--
+ <xsl:if test="not(@namest = '' ) ">
+ <xsl:attribute name="table:number-columns-spanned">
+ <xsl:value-of select="(substring-after(@nameend,'c')-substring-after(@namest,'c'))+1"/>
+
+ </xsl:attribute>
+ </xsl:if>
+ -->
+ <xsl:choose>
+ <xsl:when test="not(child::para)">
+ <xsl:element name="text:p">
+ <xsl:if test="ancestor-or-self::thead">
+ <xsl:attribute name="text:style-name">Table Heading</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::tbody">
+ <xsl:attribute name="text:style-name">Table Contents</xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+
+
+
+
+
+
+ <xsl:template match="figure">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+<!-- lists Section -->
+
+ <xsl:template match="itemizedlist">
+ <xsl:element name="text:unordered-list">
+ <xsl:if test="not(ancestor::itemizedlist)">
+ <xsl:attribute name="text:style-name">L1</xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="variablelist">
+ <xsl:element name="text:unordered-list">
+ <xsl:attribute name="text:style-name">Var List</xsl:attribute>
+ <xsl:attribute name="text:continue-numbering">false</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="orderedlist">
+ <xsl:element name="text:ordered-list">
+ <xsl:attribute name="text:style-name">Ordered List</xsl:attribute>
+ <xsl:attribute name="text:continue-numbering">false</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="term">
+ <xsl:if test="parent::varlistentry">
+ <text:list-item>
+ <xsl:element name="text:p">
+ <xsl:attribute name="text:style-name">VarList Term</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </text:list-item>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="listitem">
+ <text:list-item>
+ <xsl:apply-templates/>
+ </text:list-item>
+ </xsl:template>
+
+<!-- end of lists-->
+
+ <xsl:template match="menuchoice">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="guimenuitem">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">GuiMenuItem</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="guibutton">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">GuiButton</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="guisubmenu">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">GuiSubMenu</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="emphasis">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">Emphasis</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="guimenu">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">GuiMenu</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="guisubmenu">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">GuiSubMenu</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="guilabel">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">GuiLabel</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="guibutton">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">GuiButton</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="keycap">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">KeyCap</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="keysym">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">KeySym</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="keycombo">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">KeyCombo</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="command">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">Command</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="application">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">Application</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="filename">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">FileName</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="systemitem">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">SystemItem</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="computeroutput">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">ComputerOutput</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="inlinegraphic">
+ <xsl:element name="draw:image">
+ <xsl:attribute name="draw:style-name">fr1</xsl:attribute>
+ <xsl:attribute name="draw:name"></xsl:attribute>
+ <xsl:attribute name="text:anchor-type"></xsl:attribute>
+ <xsl:attribute name="draw:z-index"></xsl:attribute>
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="@fileref"/>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:type"></xsl:attribute>
+ <xsl:attribute name="svg:width">
+ <!--<xsl:value-of select="@width"/>-->
+ <xsl:text>1cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="svg:height">
+ <xsl:text>1cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:show">
+ <xsl:text>embed</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:actuate">
+ <xsl:text>onLoad</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="draw:filter-name">
+ <xsl:text disable-output-escaping="yes">&lt;All formats&gt;</xsl:text>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="footnote">
+ <xsl:element name="text:footnote">
+ <!--<xsl:element name="text:footnote-citation">Aidan</xsl:element>-->
+ <xsl:element name="text:footnote-body">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="highlight">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">Highlight</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="ulink">
+ <xsl:element name="text:a">
+ <xsl:attribute name="xlink:type">
+ <xsl:text>simple</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="@url"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+
+ </xsl:template>
+
+ <xsl:template match="link">
+ <xsl:element name="text:a">
+ <xsl:attribute name="xlink:type">
+ <xsl:text>simple</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:href">
+ <xsl:text>#</xsl:text>
+ <xsl:value-of select="@linkend"/>
+ <xsl:text>%7Cregion</xsl:text>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+
+ </xsl:template>
+
+ <xsl:template match="olink">
+ <xsl:element name="text:a">
+ <xsl:attribute name="xlink:type">
+ <xsl:text>simple</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="@targetdocent"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="note">
+ <office:annotation>
+ <text:p>
+ <xsl:apply-templates/>
+ </text:p>
+ </office:annotation>
+ </xsl:template>
+
+ <xsl:template match="imageobject">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="textobject"></xsl:template>
+
+ <xsl:template match="caption">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+
+ <xsl:template match="imagedata">
+ <xsl:element name="draw:image">
+ <xsl:attribute name="draw:style-name">fr1</xsl:attribute>
+ <xsl:attribute name="draw:name"></xsl:attribute>
+ <xsl:attribute name="text:anchor-type"></xsl:attribute>
+ <xsl:attribute name="draw:z-index"></xsl:attribute>
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="@fileref"/>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:type"></xsl:attribute>
+ <xsl:attribute name="svg:width">
+ <!--<xsl:value-of select="@width"/>-->
+ <xsl:text>1cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="svg:height">
+ <xsl:text>1cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:show">
+ <xsl:text>embed</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:actuate">
+ <xsl:text>onLoad</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="draw:filter-name">
+ <xsl:text disable-output-escaping="yes">&lt;All formats&gt;</xsl:text>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="audioobject">
+ <xsl:element name="draw:plugin">
+ <xsl:attribute name="draw:style-name">fr1</xsl:attribute>
+ <xsl:attribute name="draw:name"></xsl:attribute>
+ <xsl:attribute name="text:anchor-type"></xsl:attribute>
+ <xsl:attribute name="draw:z-index"></xsl:attribute>
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="@fileref"/>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:type"></xsl:attribute>
+ <xsl:attribute name="svg:width">
+ <!--<xsl:value-of select="@width"/>-->
+ <xsl:text>1cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="svg:height">
+ <xsl:text>1cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:show">
+ <xsl:text>embed</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="xlink:actuate">
+ <xsl:text>onLoad</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="draw:filter-name">
+ <xsl:text disable-output-escaping="yes">&lt;All formats&gt;</xsl:text>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="remark">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="mediaobject">
+ <xsl:element name="text:p">
+ <xsl:attribute name="text:style-name">Mediaobject</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="superscript">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">SuperScript</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="subscript">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name">SubScript</xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="anchor">
+ <xsl:element name="text:bookmark">
+ <xsl:attribute name="text:name"><xsl:value-of select="@id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+
+<!-- Change Made By Kevin Fowlks (fowlks@msu.edu) July 2nd, 2003 -->
+ <xsl:template match="example">
+ <xsl:element name="text:p">
+ <xsl:attribute name="text:style-name">Example</xsl:attribute>
+ <xsl:value-of select="programlisting"/>
+ </xsl:element>
+ </xsl:template>
+</xsl:stylesheet> \ No newline at end of file
diff --git a/filter/source/docbook/sofftodocbookheadings.xsl b/filter/source/docbook/sofftodocbookheadings.xsl
new file mode 100644
index 000000000..784c050a2
--- /dev/null
+++ b/filter/source/docbook/sofftodocbookheadings.xsl
@@ -0,0 +1,1152 @@
+<?xml version='1.0' encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<xsl:stylesheet version="1.0" xmlns:style="http://openoffice.org/2000/style" xmlns:text="http://openoffice.org/2000/text" xmlns:office="http://openoffice.org/2000/office" xmlns:table="http://openoffice.org/2000/table" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="http://openoffice.org/2000/meta" xmlns:number="http://openoffice.org/2000/datastyle" xmlns:svg="http://www.w3.org/2000/svg" xmlns:chart="http://openoffice.org/2000/chart" xmlns:dr3d="http://openoffice.org/2000/dr3d" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="http://openoffice.org/2000/form" xmlns:script="http://openoffice.org/2000/script" xmlns:config="http://openoffice.org/2001/config" office:class="text" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="office meta table number dc fo xlink chart math script xsl draw svg dr3d form config text style">
+ <xsl:output method="xml" indent="yes" omit-xml-declaration="no" version="1.0" encoding="UTF-8" doctype-public="-//OASIS//DTD DocBook XML V4.1.2//EN" doctype-system="http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"/>
+
+
+ <!-- Heading will be mapped to sections.
+ In OpenDocument headings are not nested, they do not embrace their related content, the XML hierarchy has to be restructured.
+
+ Example of OpenDocument content:
+
+ <office:body>
+ <text:h text:style-name="Heading 1" text:level="1">Heading 1</text:h>
+ <text:p text:style-name="Text body">Heading 1 Content</text:p>
+ <text:h text:style-name="Heading 2" text:level="2">Heading 2</text:h>
+ <text:p text:style-name="Text body">Heading 2 Content</text:p>
+ <office:body>
+
+ Example of DocBook content:
+
+ <article lang="en-US">
+ <sect1>
+ <title>Heading 1</title>
+ <para>Heading 1 Content</para>
+ <sect2>
+ <title>Heading 2</title>
+ <para>Heading 2 Content</para>
+ </sect2>
+ </sect1>
+ </article>
+ -->
+
+ <!-- The key function "nestedContent" returns all ODF elements that are children of the current heading (i.e. text:h) or their parent office:body in case there is no text:h.
+ It works by matching all ODF elements, that text:h refer to (it's sibling or office:body childring)
+ Various keyed element sets of these matched elements are being generated. A set is identified by having the same last (closest) preceding text:h or if none existent the parent document.
+ All those elements, that have the current heading as last preceding heading (text:h) are returned as a nodeset.
+ -->
+ <xsl:key name="nestedContent"
+ match="text:p | table:table | text:span | text:ordered-list | office:annotation | text:unordered-list | text:footnote | text:a | text:list-item | draw:plugin | draw:text-box | text:footnote-body | text:section"
+ use="generate-id((.. | preceding::text:h)[last()])"/>
+
+ <!-- The key function "nestedHeadings" returns a nodeset of all heading (text:h) elements, which belong to this heading (follow and have a higher outline number than the current text:h, which ID is given to the function) -->
+ <xsl:key name="nestedHeadings"
+ match="text:h"
+ use="generate-id(preceding::text:h[@text:level &lt; current()/@text:level][1])"/>
+
+ <!-- The key function "getHeadingsByOutline" returns all headings of a certain outline level -->
+ <xsl:key name="getHeadingsByOutline"
+ match="text:h"
+ use="@text:level"/>
+
+ <!-- A further problem during mapping of Heading to sections is the quantity of levels. In OpenDocument there can exist more than 4 hierarchies (outline levels).
+ Furthermore an OpenDocument have not to start with heading outline level 1 nor does an outline level 2 have to follow.
+ Therefore all possible existing heading outline levels from 1 to 10 have to be mapped to the section1 to section4 in DocBook.
+ The lowest outline number is mapped section1, second is section2... until fourth and higher are all mapped to section4 -->
+
+ <!-- Each global variable hold the outline level which has been mapped to one of the four sections in DocBook -->
+ <xsl:variable name="section1_OutlineLevel">
+ <xsl:call-template name="findOutlineLevel">
+ <xsl:with-param name="candidateOutlineLevel" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="section2_OutlineLevel">
+ <xsl:call-template name="findOutlineLevel">
+ <xsl:with-param name="candidateOutlineLevel" select="$section1_OutlineLevel + 1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="section3_OutlineLevel">
+ <xsl:call-template name="findOutlineLevel">
+ <xsl:with-param name="candidateOutlineLevel" select="$section2_OutlineLevel + 1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="section4_OutlineLevel">
+ <xsl:call-template name="findOutlineLevel">
+ <xsl:with-param name="candidateOutlineLevel" select="$section3_OutlineLevel + 1"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <!-- get the minimum available heading outline level (usually '1') -->
+ <xsl:template name="findOutlineLevel">
+ <xsl:param name="candidateOutlineLevel"/>
+ <xsl:choose>
+ <xsl:when test="key('getHeadingsByOutline', $candidateOutlineLevel)[1]/@text:level != ''">
+ <xsl:value-of select="$candidateOutlineLevel"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$candidateOutlineLevel &lt; 11">
+ <xsl:call-template name="findOutlineLevel">
+ <xsl:with-param name="candidateOutlineLevel" select="$candidateOutlineLevel + 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- START -->
+ <xsl:template match="/*">
+ <xsl:element name="article">
+ <xsl:attribute name="lang">
+ <xsl:value-of select="/*/office:meta/dc:language"/>
+ </xsl:attribute>
+ <!-- page style header -->
+ <xsl:call-template name="page-style">
+ <xsl:with-param name="area" select="'header'"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="office:body"/>
+ <!-- page style footer -->
+ <xsl:call-template name="page-style"/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:key match="style:master-page" name="styleMasterPage" use="@style:name" />
+ <!-- using a simple heuristic for "standard" page-style heading/footer from page styles -->
+ <xsl:template name="page-style">
+ <xsl:param name="area"/>
+
+ <xsl:variable name="defaultPageStyle" select="key('styleMasterPage', 'Standard')"/>
+ <xsl:choose>
+ <xsl:when test="$area = 'header'">
+ <xsl:apply-templates select="$defaultPageStyle/style:header/*"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$defaultPageStyle/style:footer/*"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+ <xsl:template match="office:body">
+ <!-- here all children of office:body before the first heading are matched -->
+ <xsl:apply-templates select="key('nestedContent', generate-id())"/>
+ <!-- have to be descendant as text:h can be in a list:item in some list -->
+ <xsl:variable name="firstHeading" select="descendant::text:h[1]"/>
+ <!-- changing the context node from office:body to text:h as required for used key functions -->
+ <xsl:for-each select="descendant::text:h[@text:level=$section1_OutlineLevel][1]">
+ <!-- if the first heading is not of the section1 level -->
+ <xsl:if test="generate-id(.) != generate-id($firstHeading)">
+ <!-- create an anonymous section1 and embrace all headings preceding the first real existent section1 -->
+ <xsl:element name="sect1">
+ <title></title>
+ <!-- create sections for all the first section1 preluding headings -->
+ <xsl:for-each select="key('getHeadingsByOutline', $section1_OutlineLevel)[1]/preceding::text:h">
+ <xsl:call-template name="make-section">
+ <xsl:with-param name="previousSectionLevel" select="$section1_OutlineLevel"/>
+ <xsl:with-param name="currentSectionLevel">
+ <xsl:call-template name="getSectionLevel">
+ <xsl:with-param name="outlineLevel" select="@text:level"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ <!-- match all headings, which are mapped to section1 to create a nested section structure used in docbook (see first comment after copyright) -->
+ <xsl:apply-templates mode="recreateStructure" select="descendant::text:h[@text:level = $section1_OutlineLevel]"/>
+ </xsl:template>
+
+ <xsl:template match="text:h" mode="recreateStructure">
+ <!-- relate the current ODF outline level of the heading to one of the four docbook section levels-->
+ <xsl:variable name="currentSectionLevel">
+ <xsl:call-template name="getSectionLevel">
+ <xsl:with-param name="outlineLevel" select="@text:level"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <!-- heading with outline level 1 might be an Abstract -->
+ <xsl:when test="$currentSectionLevel = 1">
+ <xsl:choose>
+ <!-- when the content of a level 1 heading is 'Abstract' the <abstract> docbook element is used instead of <section1> -->
+ <xsl:when test=".='Abstract'">
+ <abstract>
+ <xsl:apply-templates select="key('nestedContent', generate-id())"/>
+ <xsl:apply-templates select="key('nestedHeadings', generate-id())" mode="recreateStructure"/>
+ </abstract>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="make-section">
+ <xsl:with-param name="currentSectionLevel" select="$currentSectionLevel"/>
+ <xsl:with-param name="previousSectionLevel" select="$currentSectionLevel"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="previousHeading" select="preceding::text:h[@text:level &lt; current()/@text:level][1]"/>
+ <xsl:choose>
+ <xsl:when test="$previousHeading/@text:level != ''">
+ <xsl:call-template name="make-section">
+ <xsl:with-param name="currentSectionLevel" select="$currentSectionLevel"/>
+ <xsl:with-param name="previousSectionLevel">
+ <xsl:call-template name="getSectionLevel">
+ <xsl:with-param name="outlineLevel" select="$previousHeading/@text:level"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="make-section">
+ <xsl:with-param name="currentSectionLevel" select="$currentSectionLevel"/>
+ <xsl:with-param name="previousSectionLevel" select="$currentSectionLevel"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="text:bookmark | text:bookmark-start">
+ <xsl:element name="anchor">
+ <xsl:attribute name="id">
+ <!-- ID have to be an NCName which have to start with a letter or '_'
+ in case of the frequent starting number a '_' will be added as prefix -->
+ <xsl:choose>
+ <xsl:when test="(starts-with(@text:name, '0') or
+ starts-with(@text:name, '1') or
+ starts-with(@text:name, '2') or
+ starts-with(@text:name, '3') or
+ starts-with(@text:name, '4') or
+ starts-with(@text:name, '5') or
+ starts-with(@text:name, '6') or
+ starts-with(@text:name, '7') or
+ starts-with(@text:name, '8') or
+ starts-with(@text:name, '9'))">
+ <xsl:value-of select="concat('_', @text:name)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@text:name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template name="getSectionLevel">
+ <xsl:param name="outlineLevel"/>
+ <xsl:choose>
+ <xsl:when test="$outlineLevel = $section1_OutlineLevel">1</xsl:when>
+ <xsl:when test="$outlineLevel = $section2_OutlineLevel">2</xsl:when>
+ <xsl:when test="$outlineLevel = $section3_OutlineLevel">3</xsl:when>
+ <xsl:otherwise>4</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- make-section creates the nested section hierarchy and
+ in case the difference between the parent section and the new section is higher than one
+ a section is inserted to keep the output format valid -->
+ <xsl:template name="make-section">
+ <xsl:param name="currentSectionLevel"/>
+ <xsl:param name="previousSectionLevel"/>
+ <xsl:choose>
+ <!-- empty title as it is an empty section between two headings with an outline level difference higher than 1 -->
+ <xsl:when test="$currentSectionLevel &gt; $previousSectionLevel+1">
+ <xsl:element name="{concat('sect', $previousSectionLevel + 1)}">
+ <title></title>
+ <xsl:call-template name="make-section">
+ <xsl:with-param name="currentSectionLevel" select="$currentSectionLevel"/>
+ <xsl:with-param name="previousSectionLevel" select="$previousSectionLevel +1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="{concat('sect', $currentSectionLevel)}">
+ <title>
+ <xsl:apply-templates/>
+ </title>
+ <xsl:apply-templates select="key('nestedContent', generate-id())"/>
+ <xsl:apply-templates select="key('nestedHeadings', generate-id())" mode="recreateStructure"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template match="office:meta">
+ <!--<xsl:apply-templates/>--></xsl:template>
+
+ <xsl:template match="meta:editing-cycles"></xsl:template>
+
+ <xsl:template match="meta:user-defined"></xsl:template>
+
+ <xsl:template match="meta:editing-duration"></xsl:template>
+
+ <xsl:template match="dc:language"></xsl:template>
+
+ <xsl:template match="dc:date">
+ <!--<pubdate>
+ <xsl:value-of select="substring-before(.,'T')"/>
+ </pubdate>--></xsl:template>
+
+ <xsl:template match="meta:creation-date"></xsl:template>
+
+ <xsl:template match="office:styles">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="office:script"></xsl:template>
+
+
+ <xsl:template match="office:settings"></xsl:template>
+
+ <xsl:template match="office:font-decls"></xsl:template>
+
+ <xsl:template match="text:section">
+ <xsl:choose>
+ <xsl:when test="@text:name='ArticleInfo'">
+ <articleinfo>
+ <title>
+ <xsl:value-of select="text:p[@text:style-name='Document Title']"/>
+ </title>
+ <subtitle>
+ <xsl:value-of select="text:p[@text:style-name='Document SubTitle']"/>
+ </subtitle>
+ <edition>
+ <xsl:value-of select="text:p/text:variable-set[@text:name='articleinfo.edition']"/>
+ </edition>
+ <xsl:for-each select="text:p/text:variable-set[substring-after(@text:name,'articleinfo.releaseinfo')]">
+ <releaseinfo>
+ <xsl:value-of select="."/>
+ </releaseinfo>
+ </xsl:for-each>
+ <xsl:call-template name="ArticleInfo">
+ <xsl:with-param name="level" select="0"/>
+ </xsl:call-template>
+ </articleinfo>
+ </xsl:when>
+ <xsl:when test="@text:name='Abstract'">
+ <abstract>
+ <xsl:apply-templates/>
+ </abstract>
+ </xsl:when>
+ <xsl:when test="@text:name='Appendix'">
+ <appendix>
+ <xsl:apply-templates/>
+ </appendix>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="{concat('sect', count(ancestor::text:section) + 1)}">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@text:name"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="ArticleInfo">
+ <xsl:param name="level"/>
+ <xsl:variable name="author">
+ <xsl:value-of select="concat('articleinfo.author_','', $level)"/>
+ </xsl:variable>
+ <xsl:if test="text:p/text:variable-set[contains(@text:name, $author )]">
+ <xsl:call-template name="Author">
+ <xsl:with-param name="AuthorLevel" select="0"/>
+ </xsl:call-template>
+ <xsl:call-template name="Copyright">
+ <xsl:with-param name="CopyrightLevel" select="0"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="Copyright">
+ <xsl:param name="CopyrightLevel"/>
+
+ <xsl:variable name="Copyright">
+ <xsl:value-of select="concat('articleinfo.copyright_','', $CopyrightLevel)"/>
+ </xsl:variable>
+
+ <xsl:if test="text:p/text:variable-set[contains(@text:name,$Copyright)]">
+ <copyright>
+ <xsl:call-template name="Year">
+ <xsl:with-param name="CopyrightLevel" select="$CopyrightLevel"/>
+ <xsl:with-param name="YearlLevel" select="0"/>
+ </xsl:call-template>
+ <xsl:call-template name="Holder">
+ <xsl:with-param name="CopyrightLevel" select="$CopyrightLevel"/>
+ <xsl:with-param name="HolderlLevel" select="0"/>
+
+ </xsl:call-template>
+ </copyright>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template name="Year">
+ <xsl:param name="CopyrightLevel"/>
+ <xsl:param name="YearLevel"/>
+ <xsl:variable name="Copyright">
+ <xsl:value-of select="concat('articleinfo.copyright_','', $CopyrightLevel)"/>
+ </xsl:variable>
+ <xsl:variable name="Year">
+ <xsl:value-of select="concat($Copyright,'',concat('.year_','',$YearLevel))"/>
+ </xsl:variable>
+
+ <xsl:if test="text:p/text:variable-set[@text:name=$Year]">
+ <orgname>
+ <xsl:value-of select="text:p/text:variable-set[@text:name=$Year]"/>
+ </orgname>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template name="Holder">
+ <xsl:param name="CopyrightLevel"/>
+ <xsl:param name="HolderLevel"/>
+ <xsl:variable name="Copyright">
+ <xsl:value-of select="concat('articleinfo.copyright_','', $CopyrightLevel)"/>
+ </xsl:variable>
+ <xsl:variable name="Holder">
+ <xsl:value-of select="concat($Copyright,'',concat('.holder_','',$HolderLevel))"/>
+ </xsl:variable>
+
+ <xsl:if test="text:p/text:variable-set[@text:name=$Holder]">
+ <orgname>
+ <xsl:value-of select="text:p/text:variable-set[@text:name=$Holder]"/>
+ </orgname>
+ </xsl:if>
+ </xsl:template>
+
+
+
+ <xsl:template name="Author">
+ <xsl:param name="AuthorLevel"/>
+ <xsl:variable name="Author">
+ <xsl:value-of select="concat('articleinfo.author_','', $AuthorLevel)"/>
+ </xsl:variable>
+ <xsl:if test="text:p/text:variable-set[contains(@text:name, $Author )]">
+ <author>
+ <xsl:call-template name="Surname">
+ <xsl:with-param name="AuthorLevel" select="$AuthorLevel"/>
+ <xsl:with-param name="SurnameLevel" select="0"/>
+ </xsl:call-template>
+ <xsl:call-template name="Firstname">
+ <xsl:with-param name="AuthorLevel" select="$AuthorLevel"/>
+ <xsl:with-param name="FirstnameLevel" select="0"/>
+ </xsl:call-template>
+ <xsl:call-template name="Affiliation">
+ <xsl:with-param name="AuthorLevel" select="$AuthorLevel"/>
+ <xsl:with-param name="AffilLevel" select="0"/>
+ </xsl:call-template>
+ </author>
+ <xsl:call-template name="Author">
+ <xsl:with-param name="AuthorLevel" select="$AuthorLevel+1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template name="Surname">
+ <xsl:param name="AuthorLevel"/>
+ <xsl:param name="SurnameLevel"/>
+ <xsl:variable name="Author">
+ <xsl:value-of select="concat('articleinfo.author_','', $AuthorLevel)"/>
+ </xsl:variable>
+ <xsl:variable name="Surname">
+ <xsl:value-of select="concat($Author,'',concat('.surname_','',$SurnameLevel))"/>
+ </xsl:variable>
+ <xsl:if test="text:p/text:variable-set[@text:name=$Surname]">
+ <surname>
+ <xsl:value-of select="text:p/text:variable-set[@text:name=$Surname]"/>
+ </surname>
+ <xsl:call-template name="Surname">
+ <xsl:with-param name="AuthorLevel" select="$AuthorLevel"/>
+ <xsl:with-param name="SurnameLevel" select="SurnameLevel+1"/>
+ </xsl:call-template>
+
+ </xsl:if>
+ </xsl:template>
+
+
+
+
+ <xsl:template name="Firstname">
+ <xsl:param name="AuthorLevel"/>
+ <xsl:param name="FirstnameLevel"/>
+ <xsl:variable name="Author">
+ <xsl:value-of select="concat('articleinfo.author_','', $AuthorLevel)"/>
+ </xsl:variable>
+ <xsl:variable name="Firstname">
+ <xsl:value-of select="concat($Author,'',concat('.firstname_','',$FirstnameLevel))"/>
+ </xsl:variable>
+ <xsl:if test="text:p/text:variable-set[@text:name=$Firstname]">
+ <firstname>
+ <xsl:value-of select="text:p/text:variable-set[@text:name=$Firstname]"/>
+ </firstname>
+ <xsl:call-template name="Surname">
+ <xsl:with-param name="AuthorLevel" select="$AuthorLevel"/>
+ <xsl:with-param name="FirstnameLevel" select="FirstnameLevel+1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+
+
+ <xsl:template name="Affiliation">
+ <xsl:param name="AuthorLevel"/>
+ <xsl:param name="AffilLevel"/>
+ <xsl:variable name="Author">
+ <xsl:value-of select="concat('articleinfo.author_','', $AuthorLevel)"/>
+ </xsl:variable>
+ <xsl:variable name="Affil">
+ <xsl:value-of select="concat($Author,'',concat('.affiliation_','',$AffilLevel))"/>
+ </xsl:variable>
+ <xsl:if test="text:p/text:variable-set[contains(@text:name,$Affil)]">
+ <affiliation>
+ <xsl:call-template name="Orgname">
+ <xsl:with-param name="AuthorLevel" select="$AuthorLevel"/>
+ <xsl:with-param name="AffilLevel" select="$AffilLevel"/>
+ <xsl:with-param name="OrgLevel" select="0"/>
+ </xsl:call-template>
+ <xsl:call-template name="Address">
+ <xsl:with-param name="AuthorLevel" select="$AuthorLevel"/>
+ <xsl:with-param name="AffilLevel" select="$AffilLevel"/>
+ <xsl:with-param name="AddressLevel" select="0"/>
+
+ </xsl:call-template>
+ </affiliation>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="Orgname">
+ <xsl:param name="AuthorLevel"/>
+ <xsl:param name="AffilLevel"/>
+ <xsl:param name="OrgLevel"/>
+
+ <xsl:variable name="Author">
+ <xsl:value-of select="concat('articleinfo.author_','', $AuthorLevel)"/>
+ </xsl:variable>
+ <xsl:variable name="Affil">
+ <xsl:value-of select="concat($Author,'',concat('.affiliation_','',$AffilLevel))"/>
+ </xsl:variable>
+ <xsl:variable name="Org">
+ <xsl:value-of select="concat($Affil,'',concat('.orgname_','',$OrgLevel))"/>
+ </xsl:variable>
+
+ <xsl:if test="text:p/text:variable-set[@text:name=$Org]">
+ <orgname>
+ <xsl:value-of select="text:p/text:variable-set[@text:name=$Org]"/>
+ </orgname>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="Address">
+ <xsl:param name="AuthorLevel"/>
+ <xsl:param name="AffilLevel"/>
+ <xsl:param name="AddressLevel"/>
+
+ <xsl:variable name="Author">
+ <xsl:value-of select="concat('articleinfo.author_','', $AuthorLevel)"/>
+ </xsl:variable>
+ <xsl:variable name="Affil">
+ <xsl:value-of select="concat($Author,'',concat('.affiliation_','',$AffilLevel))"/>
+ </xsl:variable>
+ <xsl:variable name="Address">
+ <xsl:value-of select="concat($Affil,'',concat('.address_','',$AddressLevel))"/>
+ </xsl:variable>
+
+ <xsl:if test="text:p/text:variable-set[@text:name=$Address]">
+ <address>
+ <xsl:value-of select="text:p/text:variable-set[@text:name=$Address]"/>
+ </address>
+ </xsl:if>
+ </xsl:template>
+
+
+
+
+ <xsl:template match="text:p[@text:style-name='Document Title']"></xsl:template>
+
+ <xsl:template match="text:p[@text:style-name='Document SubTitle']"></xsl:template>
+
+
+ <xsl:template match="text:p[@text:style-name='Section Title']">
+ <xsl:element name="title">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:p[@text:style-name='Appendix Title']">
+ <xsl:element name="title">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+
+<!--<xsl:template match="text:p[@text:style-name='VarList Item']">
+ <xsl:if test="not(preceding-sibling::text:p[@text:style-name='VarList Item'])">
+ <xsl:text disable-output-escaping="yes">&lt;listitem&gt;</xsl:text>
+ </xsl:if>
+ <para>
+ <xsl:apply-templates/>
+ </para>
+ <xsl:if test="not(following-sibling::text:p[@text:style-name='VarList Item'])">
+ <xsl:text disable-output-escaping="yes">&lt;/listitem&gt;</xsl:text>
+ </xsl:if>
+</xsl:template>-->
+
+
+ <xsl:template match="text:p[@text:style-name='Section1 Title']">
+ <xsl:element name="title">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="text:p[@text:style-name='Section2 Title']">
+ <xsl:element name="title">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+
+ <xsl:template match="text:p[@text:style-name='Section3 Title']">
+ <xsl:element name="title">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:footnote-citation"></xsl:template>
+
+ <xsl:template match="text:p[@text:style-name='Mediaobject']">
+ <mediaobject>
+ <xsl:apply-templates/>
+ </mediaobject>
+ </xsl:template>
+
+ <xsl:template match="office:annotation/text:p">
+ <note>
+ <remark>
+ <xsl:apply-templates/>
+ </remark>
+ </note>
+ </xsl:template>
+
+<!--<xsl:template match="meta:initial-creator">
+ <author>
+ <xsl:apply-templates />
+ </author>
+</xsl:template>-->
+
+ <xsl:template match="table:table">
+ <xsl:choose>
+ <xsl:when test="following-sibling::text:p[@text:style-name='Table']">
+ <table frame="all">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@table:name"/>
+ </xsl:attribute>
+ <title>
+ <xsl:value-of select="following-sibling::text:p[@text:style-name='Table']"/>
+ </title>
+ <xsl:call-template name="generictable"/>
+ </table>
+ </xsl:when>
+ <xsl:otherwise>
+ <informaltable frame="all">
+ <xsl:call-template name="generictable"/>
+ </informaltable>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="generictable">
+ <xsl:variable name="cells" select="count(descendant::table:table-cell)"></xsl:variable>
+ <xsl:variable name="rows">
+ <xsl:value-of select="count(descendant::table:table-row)"/>
+ </xsl:variable>
+ <xsl:variable name="cols">
+ <xsl:value-of select="$cells div $rows"/>
+ </xsl:variable>
+ <xsl:variable name="numcols">
+ <xsl:choose>
+ <xsl:when test="child::table:table-column/@table:number-columns-repeated">
+ <xsl:value-of select="number(table:table-column/@table:number-columns-repeated+1)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$cols"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="tgroup">
+ <xsl:attribute name="cols">
+ <xsl:value-of select="$numcols"/>
+ </xsl:attribute>
+ <xsl:call-template name="colspec">
+ <xsl:with-param name="left" select="1"/>
+ </xsl:call-template>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template name="colspec">
+ <xsl:param name="left"/>
+ <xsl:if test="number($left &lt; ( table:table-column/@table:number-columns-repeated +2) )">
+ <xsl:element name="colspec">
+ <xsl:attribute name="colnum">
+ <xsl:value-of select="$left"/>
+ </xsl:attribute>
+ <xsl:attribute name="colname">c<xsl:value-of select="$left"/>
+ </xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="colspec">
+ <xsl:with-param name="left" select="$left+1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="table:table-column">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="table:table-header-rows">
+ <thead>
+ <xsl:apply-templates/>
+ </thead>
+ </xsl:template>
+
+ <xsl:template match="table:table-header-rows/table:table-row">
+ <row>
+ <xsl:apply-templates/>
+ </row>
+ </xsl:template>
+
+ <xsl:template match="table:table/table:table-row">
+ <xsl:if test="not(preceding-sibling::table:table-row)">
+ <xsl:text disable-output-escaping="yes">&lt;tbody&gt;</xsl:text>
+ </xsl:if>
+ <row>
+ <xsl:apply-templates/>
+ </row>
+ <xsl:if test="not(following-sibling::table:table-row)">
+ <xsl:text disable-output-escaping="yes">&lt;/tbody&gt;</xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="table:table-cell">
+ <xsl:element name="entry">
+ <xsl:if test="@table:number-columns-spanned >'1'">
+ <xsl:attribute name="namest">
+ <xsl:value-of select="concat('c',count(preceding-sibling::table:table-cell[not(@table:number-columns-spanned)]) +sum(preceding-sibling::table:table-cell/@table:number-columns-spanned)+1)"/>
+ </xsl:attribute>
+ <xsl:attribute name="nameend">
+ <xsl:value-of select="concat('c',count(preceding-sibling::table:table-cell[not(@table:number-columns-spanned)]) +sum(preceding-sibling::table:table-cell/@table:number-columns-spanned)+ @table:number-columns-spanned)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:p">
+ <xsl:choose>
+ <xsl:when test="@text:style-name='Table'"></xsl:when>
+ <xsl:otherwise>
+ <para>
+ <xsl:apply-templates/>
+ </para>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:key match="text:list-style" name="getListStyle" use="@style:name"/>
+
+ <xsl:template match="text:ordered-list">
+ <xsl:param name="outlineLevel" select="1"/>
+
+ <xsl:variable name="listStyle" select="key('getListStyle', @text:style-name)/*[@text:level = $outlineLevel]"/>
+
+ <!-- if the list is not recognizable as a list (e.g. no indent, number/bullet, etc.) the list will be ignored -->
+ <xsl:if test="$listStyle/style:properties/@*">
+ <orderedlist>
+ <xsl:apply-templates>
+ <xsl:with-param name="itemType" select="'listitem'"/>
+ <xsl:with-param name="outlineLevel" select="$outlineLevel + 1"/>
+ </xsl:apply-templates>
+ </orderedlist>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="text:unordered-list">
+ <xsl:param name="outlineLevel" select="1"/>
+
+ <xsl:variable name="listStyle" select="key('getListStyle', @text:style-name)/*[@text:level = $outlineLevel]"/>
+ <!-- if the list is not recognizable as a list (e.g. no indent, number/bullet, etc.) the list will be ignored -->
+ <xsl:if test="$listStyle/style:properties/@*">
+ <xsl:choose>
+ <xsl:when test="@text:style-name='Var List'">
+ <variablelist>
+ <xsl:apply-templates>
+ <xsl:with-param name="itemType" select="'varlist'"/>
+ <xsl:with-param name="outlineLevel" select="$outlineLevel + 1"/>
+ </xsl:apply-templates>
+ </variablelist>
+ </xsl:when>
+ <xsl:otherwise>
+ <itemizedlist>
+ <xsl:apply-templates>
+ <xsl:with-param name="itemType" select="'listitem'"/>
+ <xsl:with-param name="outlineLevel" select="$outlineLevel + 1"/>
+ </xsl:apply-templates>
+ </itemizedlist>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="text:list-item | text:list-header">
+ <xsl:param name="listType"/>
+ <xsl:param name="outlineLevel"/>
+
+ <xsl:choose>
+ <xsl:when test="$listType='Var List'">
+ <xsl:element name="varlistentry">
+ <xsl:apply-templates>
+ <xsl:with-param name="outlineLevel" select="$outlineLevel"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="listitem">
+ <xsl:apply-templates>
+ <xsl:with-param name="outlineLevel" select="$outlineLevel"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="text:p[@text:style-name='VarList Term']">
+ <xsl:element name="term">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:p[@text:style-name='VarList Item']">
+ <xsl:element name="para">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- text headings should only be matched once, when creating a nested docbook section structure, but might be as well become as part of a list a title -->
+ <xsl:template match="text:h">
+ <title>
+ <xsl:apply-templates/>
+ </title>
+ </xsl:template>
+
+ <xsl:template match="dc:title"></xsl:template>
+
+ <xsl:template match="dc:description">
+ <abstract>
+ <para>
+ <xsl:apply-templates/>
+ </para>
+ </abstract>
+ </xsl:template>
+
+ <xsl:template match="dc:subject"></xsl:template>
+
+
+ <xsl:template match="meta:generator"></xsl:template>
+
+ <xsl:template match="draw:plugin">
+ <xsl:element name="audioobject">
+ <xsl:attribute name="fileref">
+ <xsl:value-of select="@xlink:href"/>
+ </xsl:attribute>
+ <xsl:attribute name="width"></xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:footnote">
+ <footnote>
+ <xsl:apply-templates/>
+ </footnote>
+ </xsl:template>
+
+ <xsl:template match="text:footnote-body">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+
+ <xsl:template match="draw:text-box"></xsl:template>
+
+
+
+ <xsl:template match="draw:image">
+ <xsl:choose>
+ <xsl:when test="parent::text:p[@text:style-name='Mediaobject']">
+ <xsl:element name="imageobject">
+ <xsl:element name="imagedata">
+ <xsl:attribute name="fileref">
+ <xsl:value-of select="@xlink:href"/>
+ </xsl:attribute>
+ </xsl:element>
+ <xsl:element name="caption">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="inlinegraphic">
+ <xsl:attribute name="fileref">
+ <xsl:choose>
+ <xsl:when test="@xlink:href != ''">
+ <xsl:value-of select="@xlink:href"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>embedded:</xsl:text>
+ <xsl:value-of select="@draw:name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="width">
+ <xsl:value-of select="@svg:width"/>
+ </xsl:attribute>
+ <xsl:attribute name="depth">
+ <xsl:value-of select="@svg:height"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template match="text:span">
+ <xsl:choose>
+ <xsl:when test="./@text:style-name='GuiMenu'">
+ <xsl:element name="guimenu">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="./@text:style-name='GuiSubMenu'">
+ <xsl:element name="guisubmenu">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='GuiMenuItem'">
+ <xsl:element name="guimenuitem">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='GuiButton'">
+ <xsl:element name="guibutton">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='GuiButton'">
+ <xsl:element name="guibutton">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='GuiLabel'">
+ <xsl:element name="guilabel">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='Emphasis'">
+ <xsl:element name="emphasis">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='FileName'">
+ <xsl:element name="filename">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='Application'">
+ <xsl:element name="application">
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='Command'">
+ <command>
+ <xsl:apply-templates/>
+ </command>
+ </xsl:when>
+ <xsl:when test="@text:style-name='SubScript'">
+ <subscript>
+ <xsl:apply-templates/>
+ </subscript>
+ </xsl:when>
+ <xsl:when test="@text:style-name='SuperScript'">
+ <superscript>
+ <xsl:apply-templates/>
+ </superscript>
+ </xsl:when>
+ <xsl:when test="@text:style-name='SystemItem'">
+ <systemitem>
+ <xsl:apply-templates/>
+ </systemitem>
+ </xsl:when>
+ <xsl:when test="@text:style-name='ComputerOutput'">
+ <computeroutput>
+ <xsl:apply-templates/>
+ </computeroutput>
+ </xsl:when>
+ <xsl:when test="@text:style-name='Highlight'">
+ <highlight>
+ <xsl:apply-templates/>
+ </highlight>
+ </xsl:when>
+ <xsl:when test="@text:style-name='KeyCap'">
+ <keycap>
+ <xsl:apply-templates/>
+ </keycap>
+ </xsl:when>
+ <xsl:when test="@text:style-name='KeySym'">
+ <xsl:element name="keysym">
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@text:style-name='KeyCombo'">
+ <keycombo>
+ <xsl:apply-templates/>
+ </keycombo>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+
+ <xsl:template match="text:a">
+ <xsl:choose>
+ <xsl:when test="contains(@xlink:href,'://')">
+ <xsl:element name="ulink">
+ <xsl:attribute name="url">
+ <xsl:value-of select="@xlink:href"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="contains(@xlink:href,'mailto:')">
+ <xsl:element name="ulink">
+ <xsl:attribute name="url">
+ <xsl:value-of select="@xlink:href"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="not(contains(@xlink:href,'#'))">
+ <xsl:element name="olink">
+ <xsl:attribute name="targetdocent">
+ <xsl:value-of select="@xlink:href"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="linkvar" select="substring-after(@xlink:href,'#')"/>
+ <xsl:element name="link">
+ <xsl:attribute name="linkend">
+ <xsl:value-of select="substring-before($linkvar,'%')"/>
+ </xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+<!--
+ Change Made By Kevin Fowlks (fowlks@msu.edu) July 2nd, 2003
+ This allows users to create example code in DocBook.
+
+ Note: This type of grouping could also be implemented for
+ <notes>,<literallayout>, <blockquote> or any other tag that requires text to be treated as blocked.
+-->
+ <xsl:template match="text:p[@text:style-name='Example']">
+ <xsl:if test="not(preceding-sibling::*[1][self::text:p[@text:style-name='Example']])">
+ <xsl:element name="example">
+ <xsl:element name="title"></xsl:element>
+ <xsl:element name="programlisting">
+ <xsl:value-of select="."/>
+ <xsl:text disable-output-escaping="no">&#xD;</xsl:text>
+ <xsl:apply-templates mode="in-list" select="following-sibling::*[1][self::text:p[@text:style-name='Example']]"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="text:p[@text:style-name='Example']" mode="in-list">
+ <xsl:value-of select="."/>
+ <xsl:text disable-output-escaping="no">&#xD;</xsl:text>
+ <xsl:apply-templates mode="in-list" select="following-sibling::*[1][self::text:p[@text:style-name='Example']]"/>
+ </xsl:template>
+
+ <!-- ****************** -->
+ <!-- *** Whitespace *** -->
+ <!-- ****************** -->
+
+ <xsl:template match="text:s">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="@text:c"/>
+ </xsl:call-template>
+ </xsl:template>
+
+
+ <!--write the number of 'whitespaces' -->
+ <xsl:template name="write-breakable-whitespace">
+ <xsl:param name="whitespaces"/>
+
+ <!--write two space chars as the normal white space character will be stripped
+ and the other is able to break -->
+ <xsl:text>&#160;</xsl:text>
+ <xsl:if test="$whitespaces >= 2">
+ <xsl:call-template name="write-breakable-whitespace-2">
+ <xsl:with-param name="whitespaces" select="$whitespaces - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+
+ <!--write the number of 'whitespaces' -->
+ <xsl:template name="write-breakable-whitespace-2">
+ <xsl:param name="whitespaces"/>
+ <!--write two space chars as the normal white space character will be stripped
+ and the other is able to break -->
+ <xsl:text> </xsl:text>
+ <xsl:if test="$whitespaces >= 2">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="$whitespaces - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="text:tab-stop">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="8"/>
+ </xsl:call-template>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/graphic/GraphicExportFilter.cxx b/filter/source/graphic/GraphicExportFilter.cxx
new file mode 100644
index 000000000..ee5843066
--- /dev/null
+++ b/filter/source/graphic/GraphicExportFilter.cxx
@@ -0,0 +1,235 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "GraphicExportFilter.hxx"
+
+#include <com/sun/star/drawing/GraphicExportFilter.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <cppuhelper/supportsservice.hxx>
+#include <utility>
+#include <vcl/graphicfilter.hxx>
+#include <svl/outstrm.hxx>
+#include <svtools/DocumentToGraphicRenderer.hxx>
+
+using namespace css;
+
+GraphicExportFilter::GraphicExportFilter( uno::Reference< uno::XComponentContext > xContext )
+ : mxContext(std::move(xContext))
+ , mnTargetWidth(0)
+ , mnTargetHeight(0)
+ , mbSelectionOnly(false)
+{}
+
+GraphicExportFilter::~GraphicExportFilter()
+{}
+
+// XServiceInfo
+sal_Bool GraphicExportFilter::supportsService(const OUString& sServiceName)
+{
+ return cppu::supportsService(this, sServiceName);
+}
+OUString GraphicExportFilter::getImplementationName()
+{
+ return "com.sun.star.comp.GraphicExportFilter";
+}
+css::uno::Sequence< OUString > GraphicExportFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ExportFilter" };
+}
+
+void GraphicExportFilter::gatherProperties( const uno::Sequence< beans::PropertyValue > & rProperties )
+{
+ OUString aInternalFilterName;
+
+ for ( const beans::PropertyValue& rProperty : rProperties )
+ {
+ if ( rProperty.Name == "FilterName" )
+ {
+ rProperty.Value >>= aInternalFilterName;
+ const sal_Int32 nLen = aInternalFilterName.getLength();
+ aInternalFilterName = aInternalFilterName.replaceFirst("calc_", "");
+ if (aInternalFilterName.getLength() == nLen)
+ aInternalFilterName = aInternalFilterName.replaceFirst("writer_", "");
+ if (aInternalFilterName.getLength() == nLen)
+ aInternalFilterName = aInternalFilterName.replaceFirst("web_", "");
+ if (aInternalFilterName.getLength() == nLen)
+ aInternalFilterName = aInternalFilterName.replaceFirst("draw_", "");
+ if (aInternalFilterName.getLength() == nLen)
+ aInternalFilterName = aInternalFilterName.replaceFirst("impress_", "");
+ }
+ else if ( rProperty.Name == "FilterData" )
+ {
+ rProperty.Value >>= maFilterDataSequence;
+ }
+ else if ( rProperty.Name == "OutputStream" )
+ {
+ rProperty.Value >>= mxOutputStream;
+ }
+ else if ( rProperty.Name == "SelectionOnly" )
+ {
+ rProperty.Value >>= mbSelectionOnly;
+ }
+ }
+
+ for ( const beans::PropertyValue& rProp : std::as_const(maFilterDataSequence) )
+ {
+ if ( rProp.Name == "PixelWidth" )
+ {
+ rProp.Value >>= mnTargetWidth;
+ }
+ else if ( rProp.Name == "PixelHeight" )
+ {
+ rProp.Value >>= mnTargetHeight;
+ }
+ }
+
+ if ( aInternalFilterName.isEmpty() )
+ return;
+
+ GraphicFilter aGraphicFilter( true );
+
+ sal_uInt16 nFilterCount = aGraphicFilter.GetExportFormatCount();
+ sal_uInt16 nFormat;
+
+ for ( nFormat = 0; nFormat < nFilterCount; nFormat++ )
+ {
+ if ( aGraphicFilter.GetExportInternalFilterName( nFormat ) == aInternalFilterName )
+ break;
+ }
+ if ( nFormat < nFilterCount )
+ {
+ maFilterExtension = aGraphicFilter.GetExportFormatShortName( nFormat );
+ }
+}
+
+sal_Bool SAL_CALL GraphicExportFilter::filter( const uno::Sequence< beans::PropertyValue > & rDescriptor )
+{
+ gatherProperties(rDescriptor);
+
+ if (mbSelectionOnly && mxDocument.is())
+ {
+ uno::Reference< frame::XModel > xModel( mxDocument, uno::UNO_QUERY);
+ if (xModel.is())
+ {
+ uno::Reference< frame::XController > xController( xModel->getCurrentController());
+ if (xController.is())
+ {
+ uno::Reference< drawing::XShapes > xShapes;
+ uno::Reference< drawing::XShape > xShape;
+ if (DocumentToGraphicRenderer::isShapeSelected( xShapes, xShape, xController))
+ return filterExportShape( rDescriptor, xShapes, xShape);
+ }
+ }
+ }
+
+ return filterRenderDocument();
+}
+
+bool GraphicExportFilter::filterRenderDocument() const
+{
+ DocumentToGraphicRenderer aRenderer( mxDocument, mbSelectionOnly );
+ sal_Int32 nCurrentPage = aRenderer.getCurrentPage();
+ Size aDocumentSizePixel = aRenderer.getDocumentSizeInPixels(nCurrentPage);
+
+ Size aTargetSizePixel(mnTargetWidth, mnTargetHeight);
+
+ if (mnTargetWidth == 0 || mnTargetHeight == 0)
+ aTargetSizePixel = aDocumentSizePixel;
+
+ Graphic aGraphic = aRenderer.renderToGraphic(nCurrentPage, aDocumentSizePixel, aTargetSizePixel, COL_WHITE, /*bExtOutDevData=*/false);
+
+ GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
+
+ sal_uInt16 nFilterFormat = rFilter.GetExportFormatNumberForShortName( maFilterExtension );
+
+ SvMemoryStream aMemStream;
+ const GraphicConversionParameters aParameters(aTargetSizePixel, true, true);
+
+ const ErrCode nResult = rFilter.ExportGraphic( aGraphic.GetBitmapEx(aParameters), u"", aMemStream,
+ nFilterFormat, &maFilterDataSequence );
+
+ if ( nResult == ERRCODE_NONE )
+ {
+ SvOutputStream aOutputStream( mxOutputStream );
+ aMemStream.Seek(0);
+ aOutputStream.WriteStream( aMemStream );
+
+ return true;
+ }
+
+ return false;
+}
+
+bool GraphicExportFilter::filterExportShape(
+ const css::uno::Sequence< css::beans::PropertyValue > & rDescriptor,
+ const css::uno::Reference< css::drawing::XShapes > & rxShapes,
+ const css::uno::Reference< css::drawing::XShape > & rxShape ) const
+{
+ uno::Reference< lang::XComponent > xSourceDoc;
+ if (rxShapes.is())
+ xSourceDoc.set( rxShapes, uno::UNO_QUERY_THROW );
+ else if (rxShape.is())
+ xSourceDoc.set( rxShape, uno::UNO_QUERY_THROW );
+ if (!xSourceDoc.is())
+ return false;
+
+ uno::Reference< drawing::XGraphicExportFilter > xGraphicExporter =
+ drawing::GraphicExportFilter::create( mxContext );
+ if (!xGraphicExporter.is())
+ return false;
+
+ // Need to replace the internal filter name with the short name
+ // (extension).
+ uno::Sequence< beans::PropertyValue > aDescriptor( rDescriptor);
+ for (sal_Int32 i = 0; i < aDescriptor.getLength(); ++i)
+ {
+ if (aDescriptor[i].Name == "FilterName")
+ {
+ aDescriptor.getArray()[i].Value <<= maFilterExtension;
+ break;
+ }
+ }
+
+ xGraphicExporter->setSourceDocument( xSourceDoc );
+ return xGraphicExporter->filter( aDescriptor );
+}
+
+void SAL_CALL GraphicExportFilter::cancel( )
+{
+}
+
+void SAL_CALL GraphicExportFilter::setSourceDocument( const uno::Reference< lang::XComponent > & xDocument )
+{
+ mxDocument = xDocument;
+}
+
+void SAL_CALL GraphicExportFilter::initialize( const uno::Sequence< uno::Any > & )
+{
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_GraphicExportFilter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new GraphicExportFilter(context));
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphic/GraphicExportFilter.hxx b/filter/source/graphic/GraphicExportFilter.hxx
new file mode 100644
index 000000000..c78b25d70
--- /dev/null
+++ b/filter/source/graphic/GraphicExportFilter.hxx
@@ -0,0 +1,79 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+namespace com::sun::star {
+ namespace drawing {
+ class XShapes;
+ class XShape;
+ }
+}
+
+class GraphicExportFilter :
+ public cppu::WeakImplHelper < css::document::XFilter, css::document::XExporter, css::lang::XInitialization, css::lang::XServiceInfo >
+{
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::lang::XComponent > mxDocument;
+ css::uno::Reference< css::io::XOutputStream > mxOutputStream;
+
+ css::uno::Sequence< css::beans::PropertyValue > maFilterDataSequence;
+
+ OUString maFilterExtension;
+ sal_Int32 mnTargetWidth;
+ sal_Int32 mnTargetHeight;
+ bool mbSelectionOnly;
+
+ void gatherProperties( const css::uno::Sequence< css::beans::PropertyValue > & rDescriptor );
+ bool filterRenderDocument() const;
+ bool filterExportShape(
+ const css::uno::Sequence< css::beans::PropertyValue > & rDescriptor,
+ const css::uno::Reference< css::drawing::XShapes > & rxShapes,
+ const css::uno::Reference< css::drawing::XShape > & rxShape ) const;
+
+public:
+ explicit GraphicExportFilter( css::uno::Reference< css::uno::XComponentContext > xContext );
+ virtual ~GraphicExportFilter() override;
+
+ // XServiceInfo
+ virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override;
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const css::uno::Sequence< css::beans::PropertyValue > & rDescriptor ) override;
+ virtual void SAL_CALL cancel( ) override;
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const css::uno::Reference< css::lang::XComponent > & xDocument ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any > & rArguments ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphic/graphicfilter.component b/filter/source/graphic/graphicfilter.component
new file mode 100644
index 000000000..1040d1440
--- /dev/null
+++ b/filter/source/graphic/graphicfilter.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.GraphicExportFilter"
+ constructor="filter_GraphicExportFilter_get_implementation">
+ <service name="com.sun.star.document.ExportFilter"/>
+ </implementation>
+</component>
diff --git a/filter/source/graphicfilter/icgm/actimpr.cxx b/filter/source/graphicfilter/icgm/actimpr.cxx
new file mode 100644
index 000000000..c77b55184
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/actimpr.cxx
@@ -0,0 +1,1041 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <o3tl/any.hxx>
+#include <o3tl/safeint.hxx>
+#include <vcl/bitmapex.hxx>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/Hatch.hpp>
+#include <com/sun/star/awt/FontDescriptor.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/awt/FontUnderline.hpp>
+#include <com/sun/star/drawing/XShapeGrouper.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
+#include <com/sun/star/drawing/PointSequenceSequence.hpp>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <com/sun/star/drawing/FlagSequence.hpp>
+#include <com/sun/star/drawing/ShapeCollection.hpp>
+#include <com/sun/star/drawing/TextAdjust.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/style/HorizontalAlignment.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <tools/helpers.hxx>
+#include <unotools/configmgr.hxx>
+
+#include "bitmap.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+#define MAX_PAGES_FOR_FUZZING 2048
+
+using namespace ::com::sun::star;
+
+CGMImpressOutAct::CGMImpressOutAct(CGM& rCGM, const uno::Reference< frame::XModel > & rModel)
+ : mnCurrentPage(0)
+ , mnGroupActCount(0)
+ , mnGroupLevel(0)
+ , maGroupLevel()
+ , mpCGM(&rCGM)
+ , nFinalTextCount(0)
+{
+ if ( !mpCGM->mbStatus )
+ return;
+
+ bool bStatRet = false;
+
+ uno::Reference< drawing::XDrawPagesSupplier > aDrawPageSup( rModel, uno::UNO_QUERY );
+ if( aDrawPageSup.is() )
+ {
+ maXDrawPages = aDrawPageSup->getDrawPages();
+ if ( maXDrawPages.is() )
+ {
+ maXMultiServiceFactory.set( rModel, uno::UNO_QUERY);
+ if( maXMultiServiceFactory.is() )
+ {
+ maXDrawPage = *o3tl::doAccess<uno::Reference<drawing::XDrawPage>>(maXDrawPages->getByIndex( 0 ));
+ if ( ImplInitPage() )
+ bStatRet = true;
+ }
+ }
+ }
+ mpCGM->mbStatus = bStatRet;
+}
+
+CGMImpressOutAct::~CGMImpressOutAct()
+{
+ for (auto &a : maLockedNewXShapes)
+ a->removeActionLock();
+}
+
+bool CGMImpressOutAct::ImplInitPage()
+{
+ bool bStatRet = false;
+ if( maXDrawPage.is() )
+ {
+ maXShapes = maXDrawPage;
+ if ( maXShapes.is() )
+ {
+ bStatRet = true;
+ }
+ }
+ return bStatRet;
+}
+
+bool CGMImpressOutAct::ImplCreateShape( const OUString& rType )
+{
+ if (utl::ConfigManager::IsFuzzing())
+ return false;
+ uno::Reference< uno::XInterface > xNewShape( maXMultiServiceFactory->createInstance( rType ) );
+ maXShape.set( xNewShape, uno::UNO_QUERY );
+ maXPropSet.set( xNewShape, uno::UNO_QUERY );
+ if ( maXShape.is() && maXPropSet.is() )
+ {
+ maXShapes->add( maXShape );
+ uno::Reference<document::XActionLockable> xLockable(maXShape, uno::UNO_QUERY);
+ if (xLockable)
+ {
+ xLockable->addActionLock();
+ maLockedNewXShapes.push_back(xLockable);
+ }
+ return true;
+ }
+ return false;
+}
+
+void CGMImpressOutAct::ImplSetOrientation( FloatPoint const & rRefPoint, double rOrientation )
+{
+ maXPropSet->setPropertyValue( "RotationPointX", uno::Any(static_cast<sal_Int32>(rRefPoint.X)) );
+ maXPropSet->setPropertyValue( "RotationPointY", uno::Any(static_cast<sal_Int32>(rRefPoint.Y)) );
+ maXPropSet->setPropertyValue( "RotateAngle", uno::Any(static_cast<sal_Int32>( rOrientation * 100.0 )) );
+}
+
+
+void CGMImpressOutAct::ImplSetLineBundle()
+{
+ drawing::LineStyle eLS;
+
+ sal_uInt32 nLineColor;
+ LineType eLineType;
+ double fLineWidth;
+
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINECOLOR )
+ nLineColor = mpCGM->pElement->pLineBundle->GetColor();
+ else
+ nLineColor = mpCGM->pElement->aLineBundle.GetColor();
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINETYPE )
+ eLineType = mpCGM->pElement->pLineBundle->eLineType;
+ else
+ eLineType = mpCGM->pElement->aLineBundle.eLineType;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_LINEWIDTH )
+ fLineWidth = mpCGM->pElement->pLineBundle->nLineWidth;
+ else
+ fLineWidth = mpCGM->pElement->aLineBundle.nLineWidth;
+
+ maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nLineColor)) );
+
+ maXPropSet->setPropertyValue( "LineWidth", uno::Any(static_cast<sal_Int32>(fLineWidth)) );
+
+ switch( eLineType )
+ {
+ case LT_NONE :
+ eLS = drawing::LineStyle_NONE;
+ break;
+ case LT_DASH :
+ case LT_DOT :
+ case LT_DASHDOT :
+ case LT_DOTDOTSPACE :
+ case LT_LONGDASH :
+ case LT_DASHDASHDOT :
+ eLS = drawing::LineStyle_DASH;
+ break;
+ case LT_SOLID :
+ default:
+ eLS = drawing::LineStyle_SOLID;
+ break;
+ }
+ maXPropSet->setPropertyValue( "LineStyle", uno::Any(eLS) );
+ if ( eLS == drawing::LineStyle_DASH )
+ {
+ drawing::LineDash aLineDash( drawing::DashStyle_RECTRELATIVE, 1, 50, 3, 33, 100 );
+ maXPropSet->setPropertyValue( "LineDash", uno::Any(aLineDash) );
+ }
+}
+
+void CGMImpressOutAct::ImplSetFillBundle()
+{
+ drawing::LineStyle eLS;
+ drawing::FillStyle eFS;
+
+ sal_uInt32 nEdgeColor = 0;
+ EdgeType eEdgeType;
+ double fEdgeWidth = 0;
+
+ sal_uInt32 nFillColor;
+ FillInteriorStyle eFillStyle;
+ sal_uInt32 nHatchIndex;
+
+ if ( mpCGM->pElement->eEdgeVisibility == EV_ON )
+ {
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGETYPE )
+ eEdgeType = mpCGM->pElement->pEdgeBundle->eEdgeType;
+ else
+ eEdgeType = mpCGM->pElement->aEdgeBundle.eEdgeType;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGEWIDTH )
+ fEdgeWidth = mpCGM->pElement->pEdgeBundle->nEdgeWidth;
+ else
+ fEdgeWidth = mpCGM->pElement->aEdgeBundle.nEdgeWidth;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_EDGECOLOR )
+ nEdgeColor = mpCGM->pElement->pEdgeBundle->GetColor();
+ else
+ nEdgeColor = mpCGM->pElement->aEdgeBundle.GetColor();
+ }
+ else
+ eEdgeType = ET_NONE;
+
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
+ eFillStyle = mpCGM->pElement->pFillBundle->eFillInteriorStyle;
+ else
+ eFillStyle = mpCGM->pElement->aFillBundle.eFillInteriorStyle;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLCOLOR )
+ nFillColor = mpCGM->pElement->pFillBundle->GetColor();
+ else
+ nFillColor = mpCGM->pElement->aFillBundle.GetColor();
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_HATCHINDEX )
+ nHatchIndex = static_cast<sal_uInt32>(mpCGM->pElement->pFillBundle->nFillHatchIndex);
+ else
+ nHatchIndex = static_cast<sal_uInt32>(mpCGM->pElement->aFillBundle.nFillHatchIndex);
+
+ maXPropSet->setPropertyValue( "FillColor", uno::Any(static_cast<sal_Int32>(nFillColor)) );
+
+ switch ( eFillStyle )
+ {
+ case FIS_HATCH :
+ {
+ if ( nHatchIndex == 0 )
+ eFS = drawing::FillStyle_NONE;
+ else
+ eFS = drawing::FillStyle_HATCH;
+ }
+ break;
+ case FIS_PATTERN :
+ case FIS_SOLID :
+ {
+ eFS = drawing::FillStyle_SOLID;
+ }
+ break;
+
+ case FIS_GEOPATTERN :
+ {
+ if ( mpCGM->pElement->eTransparency == T_ON )
+ nFillColor = mpCGM->pElement->nAuxiliaryColor;
+ eFS = drawing::FillStyle_NONE;
+ }
+ break;
+
+ case FIS_INTERPOLATED :
+ case FIS_GRADIENT :
+ {
+ eFS = drawing::FillStyle_GRADIENT;
+ }
+ break;
+
+ case FIS_HOLLOW :
+ case FIS_EMPTY :
+ default:
+ {
+ eFS = drawing::FillStyle_NONE;
+ }
+ }
+
+ if ( mpCGM->mnAct4PostReset & ACT4_GRADIENT_ACTION )
+ eFS = drawing::FillStyle_GRADIENT;
+
+ if ( eFS == drawing::FillStyle_GRADIENT )
+ {
+ maXPropSet->setPropertyValue( "FillGradient", uno::Any(*mpGradient) );
+ }
+ maXPropSet->setPropertyValue( "FillStyle", uno::Any(eFS) );
+
+ eLS = drawing::LineStyle_NONE;
+ if ( eFillStyle == FIS_HOLLOW )
+ {
+ eLS = drawing::LineStyle_SOLID;
+ maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nFillColor)) );
+ maXPropSet->setPropertyValue( "LineWidth", uno::Any(sal_Int32(0)) );
+ }
+ else if ( eEdgeType != ET_NONE )
+ {
+ maXPropSet->setPropertyValue( "LineColor", uno::Any(static_cast<sal_Int32>(nEdgeColor)) );
+
+ maXPropSet->setPropertyValue( "LineWidth", uno::Any(static_cast<sal_Int32>(fEdgeWidth)) );
+
+ switch( eEdgeType )
+ {
+ case ET_DASH :
+ case ET_DOT :
+ case ET_DASHDOT :
+ case ET_DASHDOTDOT :
+ case ET_DOTDOTSPACE :
+ case ET_LONGDASH :
+ case ET_DASHDASHDOT :
+ default: // case ET_SOLID :
+ {
+ eLS = drawing::LineStyle_SOLID;
+ }
+ break;
+ }
+ }
+
+ maXPropSet->setPropertyValue( "LineStyle", uno::Any(eLS) );
+
+ if ( eFS != drawing::FillStyle_HATCH )
+ return;
+
+ drawing::Hatch aHatch;
+
+ aHatch.Color = nFillColor;
+ if ( mpCGM->pElement->maHatchMap.find( nHatchIndex ) != mpCGM->pElement->maHatchMap.end() )
+ {
+ HatchEntry& rHatchEntry = mpCGM->pElement->maHatchMap[ nHatchIndex ];
+ switch ( rHatchEntry.HatchStyle )
+ {
+ case 0 : aHatch.Style = drawing::HatchStyle_SINGLE; break;
+ case 1 : aHatch.Style = drawing::HatchStyle_DOUBLE; break;
+ case 2 : aHatch.Style = drawing::HatchStyle_TRIPLE; break;
+ }
+ aHatch.Distance = rHatchEntry.HatchDistance;
+ aHatch.Angle = rHatchEntry.HatchAngle;
+ }
+ else
+ {
+ aHatch.Style = drawing::HatchStyle_TRIPLE;
+ aHatch.Distance = 10 * ( nHatchIndex & 0x1f ) | 100;
+ aHatch.Angle = 15 * ( ( nHatchIndex & 0x1f ) - 5 );
+ }
+ maXPropSet->setPropertyValue( "FillHatch", uno::Any(aHatch) );
+}
+
+void CGMImpressOutAct::ImplSetTextBundle( const uno::Reference< beans::XPropertySet > & rProperty )
+{
+ sal_uInt32 nTextFontIndex;
+ sal_uInt32 nTextColor;
+
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_TEXTFONTINDEX )
+ nTextFontIndex = mpCGM->pElement->pTextBundle->nTextFontIndex;
+ else
+ nTextFontIndex = mpCGM->pElement->aTextBundle.nTextFontIndex;
+ if ( mpCGM->pElement->nAspectSourceFlags & ASF_TEXTCOLOR )
+ nTextColor = mpCGM->pElement->pTextBundle->GetColor();
+ else
+ nTextColor = mpCGM->pElement->aTextBundle.GetColor();
+
+ rProperty->setPropertyValue( "CharColor", uno::Any(static_cast<sal_Int32>(nTextColor)) );
+
+ sal_uInt32 nFontType = 0;
+ awt::FontDescriptor aFontDescriptor;
+ FontEntry* pFontEntry = mpCGM->pElement->aFontList.GetFontEntry( nTextFontIndex );
+ if ( pFontEntry )
+ {
+ nFontType = pFontEntry->nFontType;
+ aFontDescriptor.Name = OUString(reinterpret_cast<char*>(pFontEntry->aFontName.data()),
+ pFontEntry->aFontName.size(),
+ RTL_TEXTENCODING_ASCII_US);
+ }
+ aFontDescriptor.Height = sal_Int16( mpCGM->pElement->nCharacterHeight * 1.50 );
+ if ( nFontType & 1 )
+ aFontDescriptor.Slant = awt::FontSlant_ITALIC;
+ if ( nFontType & 2 )
+ aFontDescriptor.Weight = awt::FontWeight::BOLD;
+ else
+ aFontDescriptor.Weight = awt::FontWeight::NORMAL;
+
+ if ( mpCGM->pElement->eUnderlineMode != UM_OFF )
+ {
+ aFontDescriptor.Underline = awt::FontUnderline::SINGLE;
+ }
+ rProperty->setPropertyValue( "FontDescriptor", uno::Any(aFontDescriptor) );
+}
+
+void CGMImpressOutAct::InsertPage()
+{
+ if ( mnCurrentPage ) // one side is always existing, therefore the first side will be left out
+ {
+ uno::Reference< drawing::XDrawPage > xPage = maXDrawPages->insertNewByIndex( 0xffff );
+ maXDrawPage = xPage;
+ if ( !ImplInitPage() )
+ mpCGM->mbStatus = false;
+ if (mnCurrentPage > MAX_PAGES_FOR_FUZZING && utl::ConfigManager::IsFuzzing())
+ {
+ // ofz#21753 that's enough pages for fuzzing, we're not doing anything productive now
+ mpCGM->mbStatus = false;
+ }
+ }
+ mnCurrentPage++;
+}
+
+void CGMImpressOutAct::BeginGroup()
+{
+ if ( mnGroupLevel < CGM_OUTACT_MAX_GROUP_LEVEL )
+ {
+ maGroupLevel[mnGroupLevel] = maXShapes->getCount();
+ }
+ ++mnGroupLevel;
+ mnGroupActCount = mpCGM->mnActCount;
+}
+
+void CGMImpressOutAct::EndGroup()
+{
+ if (!mnGroupLevel)
+ return;
+ --mnGroupLevel;
+ if ( mnGroupLevel >= CGM_OUTACT_MAX_GROUP_LEVEL )
+ return;
+
+ sal_uInt32 nFirstIndex = maGroupLevel[mnGroupLevel];
+ if ( nFirstIndex == 0xffffffff )
+ nFirstIndex = 0;
+ sal_uInt32 nCurrentCount = maXShapes->getCount();
+ if ( ( nCurrentCount - nFirstIndex ) <= 1 )
+ return;
+
+ uno::Reference< drawing::XShapeGrouper > aXShapeGrouper;
+ aXShapeGrouper.set( maXDrawPage, uno::UNO_QUERY );
+ if( !aXShapeGrouper.is() )
+ return;
+
+ uno::Reference< drawing::XShapes > aXShapes = drawing::ShapeCollection::create(comphelper::getProcessComponentContext());
+ for ( sal_uInt32 i = nFirstIndex; i < nCurrentCount; i++ )
+ {
+ uno::Reference< drawing::XShape > aXShape = *o3tl::doAccess<uno::Reference<drawing::XShape>>(maXShapes->getByIndex( i ));
+ if (aXShape.is() )
+ {
+ aXShapes->add( aXShape );
+ }
+ }
+ aXShapeGrouper->group( aXShapes );
+}
+
+void CGMImpressOutAct::EndGrouping()
+{
+ while ( mnGroupLevel )
+ {
+ EndGroup();
+ }
+}
+
+void CGMImpressOutAct::DrawRectangle( FloatRect const & rFloatRect )
+{
+ if (mnGroupActCount == (mpCGM->mnActCount - 1)) // POWERPOINT HACK !!!
+ return;
+ if (useless(rFloatRect.Left))
+ {
+ SAL_WARN("filter.icgm", "bad left: " << rFloatRect.Left);
+ return;
+ }
+ if (useless(rFloatRect.Top))
+ {
+ SAL_WARN("filter.icgm", "bad top: " << rFloatRect.Top);
+ return;
+ }
+ double fWidth = rFloatRect.Right - rFloatRect.Left;
+ if (useless(fWidth))
+ {
+ SAL_WARN("filter.icgm", "bad width: " << fWidth);
+ return;
+ }
+ double fHeight = rFloatRect.Bottom - rFloatRect.Top;
+ if (useless(fHeight))
+ {
+ SAL_WARN("filter.icgm", "bad height: " << fHeight);
+ return;
+ }
+ if (!ImplCreateShape( "com.sun.star.drawing.RectangleShape"))
+ return;
+ maXShape->setSize(awt::Size(fWidth, fHeight));
+ maXShape->setPosition(awt::Point(rFloatRect.Left, rFloatRect.Top));
+ ImplSetFillBundle();
+}
+
+void CGMImpressOutAct::DrawEllipse( FloatPoint const & rCenter, FloatPoint const & rSize, double& rOrientation )
+{
+ if ( !ImplCreateShape( "com.sun.star.drawing.EllipseShape" ) )
+ return;
+
+ drawing::CircleKind eCircleKind = drawing::CircleKind_FULL;
+ uno::Any aAny( &eCircleKind, ::cppu::UnoType<drawing::CircleKind>::get() );
+ maXPropSet->setPropertyValue( "CircleKind", aAny );
+
+ tools::Long nXSize = static_cast<tools::Long>( rSize.X * 2.0 ); // strange behaviour with an awt::Size of 0
+ tools::Long nYSize = static_cast<tools::Long>( rSize.Y * 2.0 );
+ if ( nXSize < 1 )
+ nXSize = 1;
+ if ( nYSize < 1 )
+ nYSize = 1;
+ maXShape->setSize( awt::Size( nXSize, nYSize ) );
+ maXShape->setPosition( awt::Point( static_cast<tools::Long>( rCenter.X - rSize.X ), static_cast<tools::Long>( rCenter.Y - rSize.Y ) ) );
+
+ if ( rOrientation != 0 )
+ {
+ ImplSetOrientation( rCenter, rOrientation );
+ }
+ ImplSetFillBundle();
+}
+
+void CGMImpressOutAct::DrawEllipticalArc( FloatPoint const & rCenter, FloatPoint const & rSize, double& rOrientation,
+ sal_uInt32 nType, double& fStartAngle, double& fEndAngle )
+{
+ if ( !ImplCreateShape( "com.sun.star.drawing.EllipseShape" ) )
+ return;
+
+ uno::Any aAny;
+ drawing::CircleKind eCircleKind;
+
+
+ tools::Long nXSize = static_cast<tools::Long>( rSize.X * 2.0 ); // strange behaviour with an awt::Size of 0
+ tools::Long nYSize = static_cast<tools::Long>( rSize.Y * 2.0 );
+ if ( nXSize < 1 )
+ nXSize = 1;
+ if ( nYSize < 1 )
+ nYSize = 1;
+
+ maXShape->setSize( awt::Size ( nXSize, nYSize ) );
+
+ if ( rOrientation != 0 )
+ {
+ fStartAngle = NormAngle360(fStartAngle + rOrientation);
+ fEndAngle = NormAngle360(fEndAngle + rOrientation);
+ }
+ switch( nType )
+ {
+ case 0 : eCircleKind = drawing::CircleKind_SECTION; break;
+ case 1 : eCircleKind = drawing::CircleKind_CUT; break;
+ case 2 : eCircleKind = drawing::CircleKind_ARC; break;
+ default : eCircleKind = drawing::CircleKind_FULL; break;
+ }
+ if ( static_cast<tools::Long>(fStartAngle) == static_cast<tools::Long>(fEndAngle) )
+ {
+ eCircleKind = drawing::CircleKind_FULL;
+ maXPropSet->setPropertyValue( "CircleKind", uno::Any(eCircleKind) );
+ }
+ else
+ {
+ maXPropSet->setPropertyValue( "CircleKind", uno::Any(eCircleKind) );
+ maXPropSet->setPropertyValue( "CircleStartAngle", uno::Any(static_cast<sal_Int32>( fStartAngle * 100 )) );
+ maXPropSet->setPropertyValue( "CircleEndAngle", uno::Any(static_cast<sal_Int32>( fEndAngle * 100 )) );
+ }
+ maXShape->setPosition( awt::Point( static_cast<tools::Long>( rCenter.X - rSize.X ), static_cast<tools::Long>( rCenter.Y - rSize.Y ) ) );
+ if ( rOrientation != 0 )
+ {
+ ImplSetOrientation( rCenter, rOrientation );
+ }
+ if ( eCircleKind == drawing::CircleKind_ARC )
+ {
+ ImplSetLineBundle();
+ }
+ else
+ {
+ ImplSetFillBundle();
+ if ( nType == 2 )
+ {
+ ImplSetLineBundle();
+ aAny <<= drawing::FillStyle_NONE;
+ maXPropSet->setPropertyValue( "FillStyle", aAny );
+ }
+ }
+}
+
+void CGMImpressOutAct::DrawBitmap( CGMBitmapDescriptor* pBmpDesc )
+{
+ if ( !pBmpDesc->mbStatus || pBmpDesc->mxBitmap.IsEmpty() )
+ return;
+
+ FloatPoint aOrigin = pBmpDesc->mnOrigin;
+ double fdx = pBmpDesc->mndx;
+ double fdy = pBmpDesc->mndy;
+
+ BmpMirrorFlags nMirr = BmpMirrorFlags::NONE;
+ if ( pBmpDesc->mbVMirror )
+ nMirr |= BmpMirrorFlags::Vertical;
+ if ( nMirr != BmpMirrorFlags::NONE )
+ pBmpDesc->mxBitmap.Mirror( nMirr );
+
+ mpCGM->ImplMapPoint( aOrigin );
+ mpCGM->ImplMapX( fdx );
+ mpCGM->ImplMapY( fdy );
+
+ if ( !ImplCreateShape( "com.sun.star.drawing.GraphicObjectShape" ) )
+ return;
+
+ maXShape->setSize( awt::Size( static_cast<tools::Long>(fdx), static_cast<tools::Long>(fdy) ) );
+ maXShape->setPosition( awt::Point( static_cast<tools::Long>(aOrigin.X), static_cast<tools::Long>(aOrigin.Y) ) );
+
+ if ( pBmpDesc->mnOrientation != 0 )
+ {
+ ImplSetOrientation( aOrigin, pBmpDesc->mnOrientation );
+ }
+
+ uno::Reference< awt::XBitmap > xBitmap( VCLUnoHelper::CreateBitmap( pBmpDesc->mxBitmap ) );
+ maXPropSet->setPropertyValue( "GraphicObjectFillBitmap", uno::Any(xBitmap) );
+}
+
+void CGMImpressOutAct::DrawPolygon( tools::Polygon& rPoly )
+{
+ sal_uInt16 nPoints = rPoly.GetSize();
+
+ if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.PolyPolygonShape" )) )
+ return;
+
+ drawing::PointSequenceSequence aRetval;
+
+ // prepare inside polygons
+ aRetval.realloc( 1 );
+
+ // get pointer to outside arrays
+ drawing::PointSequence* pOuterSequence = aRetval.getArray();
+
+ // make room in arrays
+ pOuterSequence->realloc(static_cast<sal_Int32>(nPoints));
+
+ // get pointer to arrays
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+
+ for( sal_uInt16 n = 0; n < nPoints; n++ )
+ *pInnerSequence++ = awt::Point( rPoly[ n ].X(), rPoly[n].Y() );
+
+ uno::Any aParam;
+ aParam <<= aRetval;
+ maXPropSet->setPropertyValue( "PolyPolygon", aParam );
+ ImplSetFillBundle();
+}
+
+void CGMImpressOutAct::DrawPolyLine( tools::Polygon& rPoly )
+{
+ sal_uInt16 nPoints = rPoly.GetSize();
+
+ if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.PolyLineShape" )) )
+ return;
+
+ drawing::PointSequenceSequence aRetval;
+
+ // prepare inside polygons
+ aRetval.realloc( 1 );
+
+ // get pointer to outside arrays
+ drawing::PointSequence* pOuterSequence = aRetval.getArray();
+
+ // make room in arrays
+ pOuterSequence->realloc(static_cast<sal_Int32>(nPoints));
+
+ // get pointer to arrays
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+
+ for( sal_uInt16 n = 0; n < nPoints; n++ )
+ *pInnerSequence++ = awt::Point( rPoly[ n ].X(), rPoly[n].Y() );
+
+ uno::Any aParam;
+ aParam <<= aRetval;
+ maXPropSet->setPropertyValue( "PolyPolygon", aParam );
+ ImplSetLineBundle();
+}
+
+void CGMImpressOutAct::DrawPolybezier( tools::Polygon& rPolygon )
+{
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ if ( !(( nPoints > 1 ) && ImplCreateShape( "com.sun.star.drawing.OpenBezierShape" )) )
+ return;
+
+ drawing::PolyPolygonBezierCoords aRetval;
+
+ aRetval.Coordinates.realloc( 1 );
+ aRetval.Flags.realloc( 1 );
+
+ // get pointer to outside arrays
+ drawing::PointSequence* pOuterSequence = aRetval.Coordinates.getArray();
+ drawing::FlagSequence* pOuterFlags = aRetval.Flags.getArray();
+
+ // make room in arrays
+ pOuterSequence->realloc( nPoints );
+ pOuterFlags->realloc( nPoints );
+
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+ drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray();
+
+ for( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ *pInnerSequence++ = awt::Point( rPolygon[ i ].X(), rPolygon[ i ].Y() );
+ *pInnerFlags++ = static_cast<drawing::PolygonFlags>(rPolygon.GetFlags( i ));
+ }
+ uno::Any aParam;
+ aParam <<= aRetval;
+ maXPropSet->setPropertyValue( "PolyPolygonBezier", aParam );
+ ImplSetLineBundle();
+}
+
+void CGMImpressOutAct::DrawPolyPolygon( tools::PolyPolygon const & rPolyPolygon )
+{
+ sal_uInt32 nNumPolys = rPolyPolygon.Count();
+ if ( !(nNumPolys && ImplCreateShape( "com.sun.star.drawing.ClosedBezierShape" )) )
+ return;
+
+ drawing::PolyPolygonBezierCoords aRetval;
+
+ // prepare inside polygons
+ aRetval.Coordinates.realloc(static_cast<sal_Int32>(nNumPolys));
+ aRetval.Flags.realloc(static_cast<sal_Int32>(nNumPolys));
+
+ // get pointer to outside arrays
+ drawing::PointSequence* pOuterSequence = aRetval.Coordinates.getArray();
+ drawing::FlagSequence* pOuterFlags = aRetval.Flags.getArray();
+
+ for( sal_uInt32 a = 0; a < nNumPolys; a++ )
+ {
+ const tools::Polygon& aPolygon( rPolyPolygon.GetObject( a ) );
+ sal_uInt32 nNumPoints = aPolygon.GetSize();
+
+ // make room in arrays
+ pOuterSequence->realloc(static_cast<sal_Int32>(nNumPoints));
+ pOuterFlags->realloc(static_cast<sal_Int32>(nNumPoints));
+
+ // get pointer to arrays
+ awt::Point* pInnerSequence = pOuterSequence->getArray();
+ drawing::PolygonFlags* pInnerFlags = pOuterFlags->getArray();
+
+ for( sal_uInt32 b = 0; b < nNumPoints; b++ )
+ {
+ *pInnerSequence++ = awt::Point( aPolygon.GetPoint( b ).X(), aPolygon.GetPoint( b ).Y() ) ;
+ *pInnerFlags++ = static_cast<drawing::PolygonFlags>(aPolygon.GetFlags( b ));
+ }
+ pOuterSequence++;
+ pOuterFlags++;
+ }
+ uno::Any aParam;
+ aParam <<= aRetval;
+ maXPropSet->setPropertyValue( "PolyPolygonBezier", aParam);
+ ImplSetFillBundle();
+}
+
+void CGMImpressOutAct::DrawText(awt::Point const & rTextPos, awt::Size const & rTextSize, const OUString& rString, FinalFlag eFlag)
+{
+ if ( !ImplCreateShape( "com.sun.star.drawing.TextShape" ) )
+ return;
+
+ uno::Any aAny;
+ tools::Long nWidth = rTextSize.Width;
+ tools::Long nHeight = rTextSize.Height;
+
+ awt::Point aTextPos( rTextPos );
+ switch ( mpCGM->pElement->eTextAlignmentV )
+ {
+ case TAV_HALF :
+ {
+ aTextPos.Y = o3tl::saturating_add(aTextPos.X, static_cast<sal_Int32>((mpCGM->pElement->nCharacterHeight * -1.5) / 2));
+ }
+ break;
+
+ case TAV_BASE :
+ case TAV_BOTTOM :
+ case TAV_NORMAL :
+ aTextPos.Y = o3tl::saturating_add(aTextPos.Y, static_cast<sal_Int32>(mpCGM->pElement->nCharacterHeight * -1.5));
+ break;
+ case TAV_TOP :
+ break;
+ case TAV_CAP:
+ case TAV_CONT:
+ break; // -Wall these two were not here.
+ }
+
+ if ( nWidth < 0 )
+ {
+ nWidth = -nWidth;
+ }
+ else if ( nWidth == 0 )
+ {
+ nWidth = -1;
+ }
+ if ( nHeight < 0 )
+ {
+ nHeight = -nHeight;
+ }
+ else if ( nHeight == 0 )
+ {
+ nHeight = -1;
+ }
+ maXShape->setPosition( aTextPos );
+ maXShape->setSize( awt::Size( nWidth, nHeight ) );
+ double nX = mpCGM->pElement->nCharacterOrientation[ 2 ];
+ double nY = mpCGM->pElement->nCharacterOrientation[ 3 ];
+ double fSqrt = std::hypot(nX, nY);
+ double nOrientation = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
+ if ( nY < 0 )
+ nOrientation = 360 - nOrientation;
+
+ if ( nOrientation )
+ {
+ maXPropSet->setPropertyValue( "RotationPointX", uno::Any(aTextPos.X) );
+ maXPropSet->setPropertyValue( "RotationPointY", uno::Any(static_cast<sal_Int32>( aTextPos.Y + nHeight )) );
+ maXPropSet->setPropertyValue( "RotateAngle", uno::Any(static_cast<sal_Int32>( nOrientation * 100 )) );
+ }
+ if ( nWidth == -1 )
+ {
+ aAny <<= true;
+ maXPropSet->setPropertyValue( "TextAutoGrowWidth", aAny );
+
+ drawing::TextAdjust eTextAdjust;
+ switch ( mpCGM->pElement->eTextAlignmentH )
+ {
+ case TAH_RIGHT :
+ eTextAdjust = drawing::TextAdjust_RIGHT;
+ break;
+ case TAH_LEFT :
+ case TAH_CONT :
+ case TAH_NORMAL :
+ eTextAdjust = drawing::TextAdjust_LEFT;
+ break;
+ case TAH_CENTER :
+ eTextAdjust = drawing::TextAdjust_CENTER;
+ break;
+ }
+ maXPropSet->setPropertyValue( "TextHorizontalAdjust", uno::Any(eTextAdjust) );
+ }
+ if ( nHeight == -1 )
+ {
+ maXPropSet->setPropertyValue( "TextAutoGrowHeight", uno::Any(true) );
+ }
+ uno::Reference< text::XText > xText;
+ uno::Any aFirstQuery( maXShape->queryInterface( cppu::UnoType<text::XText>::get()));
+ if( aFirstQuery >>= xText )
+ {
+ uno::Reference< text::XTextCursor > aXTextCursor( xText->createTextCursor() );
+ {
+ aXTextCursor->gotoEnd( false );
+ uno::Reference< text::XTextRange > aCursorText;
+ uno::Any aSecondQuery( aXTextCursor->queryInterface( cppu::UnoType<text::XTextRange>::get()));
+ if ( aSecondQuery >>= aCursorText )
+ {
+ uno::Reference< beans::XPropertySet > aCursorPropSet;
+
+ uno::Any aQuery( aCursorText->queryInterface( cppu::UnoType<beans::XPropertySet>::get()));
+ if( aQuery >>= aCursorPropSet )
+ {
+ if ( nWidth != -1 ) // paragraph adjusting in a valid textbox ?
+ {
+ switch ( mpCGM->pElement->eTextAlignmentH )
+ {
+ case TAH_RIGHT :
+ aAny <<= sal_Int16(style::HorizontalAlignment_RIGHT);
+ break;
+ case TAH_LEFT :
+ case TAH_CONT :
+ case TAH_NORMAL :
+ aAny <<= sal_Int16(style::HorizontalAlignment_LEFT);
+ break;
+ case TAH_CENTER :
+ aAny <<= sal_Int16(style::HorizontalAlignment_CENTER);
+ break;
+ }
+ aCursorPropSet->setPropertyValue( "ParaAdjust", aAny );
+ }
+ if ( nWidth > 0 && nHeight > 0 ) // restricted text
+ {
+ aAny <<= true;
+ maXPropSet->setPropertyValue( "TextFitToSize", aAny );
+ }
+ aCursorText->setString(rString);
+ aXTextCursor->gotoEnd( true );
+ ImplSetTextBundle( aCursorPropSet );
+ }
+ }
+ }
+ }
+ if ( eFlag == FF_NOT_FINAL )
+ {
+ nFinalTextCount = maXShapes->getCount();
+ }
+}
+
+void CGMImpressOutAct::AppendText( const char* pString )
+{
+ if ( !nFinalTextCount )
+ return;
+
+ uno::Reference< drawing::XShape > aShape = *o3tl::doAccess<uno::Reference<drawing::XShape>>(maXShapes->getByIndex( nFinalTextCount - 1 ));
+ if ( !aShape.is() )
+ return;
+
+ uno::Reference< text::XText > xText;
+ uno::Any aFirstQuery( aShape->queryInterface( cppu::UnoType<text::XText>::get()) );
+ if( !(aFirstQuery >>= xText) )
+ return;
+
+ OUString aStr(pString, strlen(pString), RTL_TEXTENCODING_ASCII_US);
+
+ uno::Reference< text::XTextCursor > aXTextCursor( xText->createTextCursor() );
+ if ( !aXTextCursor.is() )
+ return;
+
+ aXTextCursor->gotoEnd( false );
+ uno::Reference< text::XTextRange > aCursorText;
+ uno::Any aSecondQuery(aXTextCursor->queryInterface( cppu::UnoType<text::XTextRange>::get()));
+ if ( aSecondQuery >>= aCursorText )
+ {
+ uno::Reference< beans::XPropertySet > aPropSet;
+ uno::Any aQuery(aCursorText->queryInterface( cppu::UnoType<beans::XPropertySet>::get()));
+ if( aQuery >>= aPropSet )
+ {
+ aCursorText->setString( aStr );
+ aXTextCursor->gotoEnd( true );
+ ImplSetTextBundle( aPropSet );
+ }
+ }
+}
+
+
+void CGMImpressOutAct::BeginFigure()
+{
+ if (!maPoints.empty())
+ EndFigure();
+
+ BeginGroup();
+ maPoints.clear();
+ maFlags.clear();
+}
+
+void CGMImpressOutAct::CloseRegion()
+{
+ if (maPoints.size() > 2)
+ {
+ NewRegion();
+ DrawPolyPolygon( maPolyPolygon );
+ maPolyPolygon.Clear();
+ }
+}
+
+void CGMImpressOutAct::NewRegion()
+{
+ if (maPoints.size() > 2)
+ {
+ tools::Polygon aPolygon(maPoints.size(), maPoints.data(), maFlags.data());
+ maPolyPolygon.Insert( aPolygon );
+ }
+ maPoints.clear();
+ maFlags.clear();
+}
+
+void CGMImpressOutAct::EndFigure()
+{
+ NewRegion();
+ DrawPolyPolygon( maPolyPolygon );
+ maPolyPolygon.Clear();
+ EndGroup();
+ maPoints.clear();
+ maFlags.clear();
+}
+
+void CGMImpressOutAct::RegPolyLine( tools::Polygon const & rPolygon, bool bReverse )
+{
+ sal_uInt16 nPoints = rPolygon.GetSize();
+ if ( !nPoints )
+ return;
+
+ if ( bReverse )
+ {
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ maPoints.push_back(rPolygon.GetPoint(nPoints - i - 1));
+ maFlags.push_back(rPolygon.GetFlags(nPoints - i - 1));
+ }
+ }
+ else
+ {
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ maPoints.push_back(rPolygon.GetPoint(i));
+ maFlags.push_back(rPolygon.GetFlags(i));
+ }
+ }
+}
+
+void CGMImpressOutAct::SetGradientOffset( tools::Long nHorzOfs, tools::Long nVertOfs )
+{
+ if ( !mpGradient )
+ mpGradient.reset( new awt::Gradient );
+ mpGradient->XOffset = ( static_cast<sal_uInt16>(nHorzOfs) & 0x7f );
+ mpGradient->YOffset = ( static_cast<sal_uInt16>(nVertOfs) & 0x7f );
+}
+
+void CGMImpressOutAct::SetGradientAngle( tools::Long nAngle )
+{
+ if ( !mpGradient )
+ mpGradient.reset( new awt::Gradient );
+ mpGradient->Angle = sal::static_int_cast< sal_Int16 >(nAngle);
+}
+
+void CGMImpressOutAct::SetGradientDescriptor( sal_uInt32 nColorFrom, sal_uInt32 nColorTo )
+{
+ if ( !mpGradient )
+ mpGradient.reset( new awt::Gradient );
+ mpGradient->StartColor = nColorFrom;
+ mpGradient->EndColor = nColorTo;
+}
+
+void CGMImpressOutAct::SetGradientStyle( sal_uInt32 nStyle )
+{
+ if ( !mpGradient )
+ mpGradient.reset( new awt::Gradient );
+ switch ( nStyle )
+ {
+ case 0xff :
+ {
+ mpGradient->Style = awt::GradientStyle_AXIAL;
+ }
+ break;
+ case 4 :
+ {
+ mpGradient->Style = awt::GradientStyle_RADIAL; // CONICAL
+ }
+ break;
+ case 3 :
+ {
+ mpGradient->Style = awt::GradientStyle_RECT;
+ }
+ break;
+ case 2 :
+ {
+ mpGradient->Style = awt::GradientStyle_ELLIPTICAL;
+ }
+ break;
+ default :
+ {
+ mpGradient->Style = awt::GradientStyle_LINEAR;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/bitmap.cxx b/filter/source/graphicfilter/icgm/bitmap.cxx
new file mode 100644
index 000000000..67652d9ec
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/bitmap.cxx
@@ -0,0 +1,433 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <sal/log.hxx>
+#include <unotools/configmgr.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <memory>
+
+#include "bitmap.hxx"
+#include "elements.hxx"
+
+namespace {
+
+Color BMCOL(sal_uInt32 _col) {
+ return Color( static_cast<sal_Int8>(_col >> 16 ), static_cast<sal_Int8>( _col >> 8 ), static_cast<sal_Int8>(_col) );
+}
+
+}
+
+CGMBitmap::CGMBitmap( CGM& rCGM ) :
+ mpCGM ( &rCGM ),
+ pCGMBitmapDescriptor ( new CGMBitmapDescriptor )
+{
+ ImplGetBitmap( *pCGMBitmapDescriptor );
+};
+
+
+CGMBitmap::~CGMBitmap()
+{
+}
+
+namespace
+{
+ bool isLegalBitsPerPixel(sal_uInt32 nBitsPerPixel)
+ {
+ switch (nBitsPerPixel)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ case 24:
+ return true;
+ default:
+ break;
+ }
+ return false;
+ }
+}
+
+void CGMBitmap::ImplGetBitmap( CGMBitmapDescriptor& rDesc )
+{
+ rDesc.mbStatus = true;
+
+ if (!ImplGetDimensions(rDesc) || !rDesc.mpBuf)
+ return;
+
+ if (!isLegalBitsPerPixel(rDesc.mnDstBitsPerPixel))
+ {
+ rDesc.mbStatus = false;
+ return;
+ }
+
+ try
+ {
+ if (rDesc.mnScanSize)
+ {
+ vcl::bitmap::RawBitmap aBitmap( Size( rDesc.mnX, rDesc.mnY ), 24 );
+
+ // the picture may either be read from left to right or right to left, from top to bottom ...
+
+ tools::Long nxCount = rDesc.mnX + 1; // +1 because we are using prefix decreasing
+ tools::Long nyCount = rDesc.mnY + 1;
+ tools::Long nx, ny, nxC;
+
+ switch ( rDesc.mnDstBitsPerPixel ) {
+ case 1 : {
+ std::vector<Color> palette(2);
+ if ( rDesc.mnLocalColorPrecision == 1 )
+ palette = ImplGeneratePalette( rDesc );
+ else {
+ palette[0] = BMCOL( mpCGM->pElement->nBackGroundColor );
+ palette[1] = ( mpCGM->pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
+ ? BMCOL( mpCGM->pElement->pFillBundle->GetColor() )
+ : BMCOL( mpCGM->pElement->aFillBundle.GetColor() );
+ };
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ nxC = nxCount;
+ for ( nx = 0; --nxC; nx++ ) {
+ // this is not fast, but a one bit/pixel format is rarely used
+ const sal_uInt8* pPos = rDesc.mpBuf + (nx >> 3);
+ if (pPos >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+ sal_uInt8 colorIndex = static_cast<sal_uInt8>((*pPos >> ((nx & 7)^7))) & 1;
+ aBitmap.SetPixel(ny, nx, palette[colorIndex]);
+ }
+ }
+ }
+ break;
+
+ case 2 : {
+ auto palette = ImplGeneratePalette( rDesc );
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ nxC = nxCount;
+ for ( nx = 0; --nxC; nx++ ) {
+ // this is not fast, but a two bits/pixel format is rarely used
+ const sal_uInt8* pPos = rDesc.mpBuf + (nx >> 2);
+ if (pPos >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+ aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>( (*pPos >> (((nx & 3)^3) << 1))) & 3]);
+ }
+ }
+ }
+ break;
+
+ case 4 : {
+ auto palette = ImplGeneratePalette( rDesc );
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ nxC = nxCount;
+ sal_uInt8* pTemp = rDesc.mpBuf;
+ for ( nx = 0; --nxC; nx++ ) {
+
+ if (pTemp >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+
+ sal_uInt8 nDat = *pTemp++;
+
+ aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>(nDat >> 4)]);
+ if ( --nxC ) {
+ ++nx;
+ aBitmap.SetPixel(ny, nx, palette[static_cast<sal_uInt8>(nDat & 15)]);
+ } else
+ break;
+ }
+ }
+ }
+ break;
+
+ case 8 : {
+ auto palette = ImplGeneratePalette( rDesc );
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ sal_uInt8* pTemp = rDesc.mpBuf;
+ nxC = nxCount;
+ for ( nx = 0; --nxC; nx++ ) {
+
+ if (pTemp >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+
+ aBitmap.SetPixel(ny, nx, palette[*(pTemp++)]);
+ }
+ }
+ }
+ break;
+
+ case 24 : {
+ Color aBitmapColor;
+ for (ny = 0; rDesc.mbStatus && --nyCount; ny++, rDesc.mpBuf += rDesc.mnScanSize) {
+ sal_uInt8* pTemp = rDesc.mpBuf;
+ nxC = nxCount;
+ for ( nx = 0; --nxC; nx++ ) {
+
+ if (pTemp + 2 >= rDesc.mpEndBuf)
+ {
+ SAL_WARN("filter.icgm", "buffer is too small");
+ rDesc.mbStatus = false;
+ break;
+ }
+
+ aBitmapColor.SetRed( *pTemp++ );
+ aBitmapColor.SetGreen( *pTemp++ );
+ aBitmapColor.SetBlue( *pTemp++ );
+ aBitmap.SetPixel(ny, nx, aBitmapColor);
+ }
+ }
+ }
+ break;
+ }
+
+ if ( rDesc.mbStatus )
+ rDesc.mxBitmap = vcl::bitmap::CreateFromData(std::move(aBitmap));
+ }
+
+ double nX = rDesc.mnR.X - rDesc.mnQ.X;
+ double nY = rDesc.mnR.Y - rDesc.mnQ.Y;
+
+ rDesc.mndy = std::hypot(nX, nY);
+
+ nX = rDesc.mnR.X - rDesc.mnP.X;
+ nY = rDesc.mnR.Y - rDesc.mnP.Y;
+
+ rDesc.mndx = std::hypot(nX, nY);
+
+ nX = rDesc.mnR.X - rDesc.mnP.X;
+ nY = rDesc.mnR.Y - rDesc.mnP.Y;
+
+ double fSqrt = std::hypot(nX, nY);
+ rDesc.mnOrientation = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
+ if ( nY > 0 )
+ rDesc.mnOrientation = 360 - rDesc.mnOrientation;
+
+ nX = rDesc.mnQ.X - rDesc.mnR.X;
+ nY = rDesc.mnQ.Y - rDesc.mnR.Y;
+
+ double fAngle = basegfx::deg2rad( 360 - rDesc.mnOrientation );
+ double fSin = sin(fAngle);
+ double fCos = cos(fAngle);
+ nX = fCos * nX + fSin * nY;
+ nY = -( fSin * nX - fCos * nY );
+
+ fSqrt = std::hypot(nX, nY);
+ fAngle = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
+ if ( nY > 0 )
+ fAngle = 360 - fAngle;
+
+ if ( fAngle > 180 ) { // is the picture build upwards or downwards ?
+ rDesc.mnOrigin = rDesc.mnP;
+ } else {
+ rDesc.mbVMirror = true;
+ rDesc.mnOrigin = rDesc.mnP;
+ rDesc.mnOrigin.X += rDesc.mnQ.X - rDesc.mnR.X;
+ rDesc.mnOrigin.Y += rDesc.mnQ.Y - rDesc.mnR.Y;
+ }
+ }
+ catch (const std::bad_alloc&)
+ {
+ rDesc.mbStatus = false;
+ }
+}
+
+std::vector<Color> CGMBitmap::ImplGeneratePalette( CGMBitmapDescriptor const & rDesc )
+{
+ sal_uInt16 nColors = sal::static_int_cast< sal_uInt16 >(
+ 1 << rDesc.mnDstBitsPerPixel);
+ std::vector<Color> palette( nColors );
+ for ( sal_uInt16 i = 0; i < nColors; i++ )
+ {
+ palette[i] = BMCOL( mpCGM->pElement->aLatestColorTable[ i ] );
+ }
+ return palette;
+}
+
+
+bool CGMBitmap::ImplGetDimensions( CGMBitmapDescriptor& rDesc )
+{
+ mpCGM->ImplGetPoint( rDesc.mnP ); // parallelogram p < - > r
+ mpCGM->ImplGetPoint( rDesc.mnQ ); // |
+ mpCGM->ImplGetPoint( rDesc.mnR ); // q
+ sal_uInt32 nPrecision = mpCGM->pElement->nIntegerPrecision;
+ rDesc.mnX = mpCGM->ImplGetUI( nPrecision );
+ rDesc.mnY = mpCGM->ImplGetUI( nPrecision );
+ rDesc.mnLocalColorPrecision = mpCGM->ImplGetI( nPrecision );
+ rDesc.mnScanSize = 0;
+ switch( rDesc.mnLocalColorPrecision )
+ {
+ case tools::Long(0x80000001) : // monochrome ( bit = 0->backgroundcolor )
+ case 0 : // bit = 1->fillcolor
+ rDesc.mnDstBitsPerPixel = 1;
+ break;
+ case 1 : // 2 color indexed ( monochrome )
+ case -1 :
+ rDesc.mnDstBitsPerPixel = 1;
+ break;
+ case 2 : // 4 color indexed
+ case -2 :
+ rDesc.mnDstBitsPerPixel = 2;
+ break;
+ case 4 : // 16 color indexed
+ case -4 :
+ rDesc.mnDstBitsPerPixel = 4;
+ break;
+ case 8 : // 256 color indexed
+ case -8 :
+ rDesc.mnDstBitsPerPixel = 8;
+ rDesc.mnScanSize = rDesc.mnX;
+ break;
+ case 16 : // NS
+ case -16 :
+ rDesc.mbStatus = false;
+ break;
+ case 24 : // 24 bit directColor ( 8 bits each component )
+ case -24 :
+ rDesc.mnDstBitsPerPixel = 24;
+ break;
+ case 32 : // NS
+ case -32 :
+ rDesc.mbStatus = false;
+ break;
+
+ }
+ // mnCompressionMode == 0 : CCOMP_RUNLENGTH
+ // == 1 : CCOMP_PACKED ( no compression. each row starts on a 4 byte boundary )
+ if ( ( rDesc.mnCompressionMode = mpCGM->ImplGetUI16() ) != 1 )
+ rDesc.mbStatus = false;
+
+ if ( !( rDesc.mnX || rDesc.mnY ) )
+ rDesc.mbStatus = false;
+
+ sal_uInt32 nHeaderSize = 2 + 3 * nPrecision + 3 * mpCGM->ImplGetPointSize();
+
+ sal_uInt32 nWidthBits;
+ if (o3tl::checked_multiply(rDesc.mnX, rDesc.mnDstBitsPerPixel, nWidthBits))
+ {
+ rDesc.mbStatus = false;
+ return false;
+ }
+
+ rDesc.mnScanSize = (nWidthBits + 7) >> 3;
+
+ sal_uInt32 nScanSize;
+ nScanSize = rDesc.mnScanSize;
+ if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize ) // try a scansize without dw alignment
+ {
+ nScanSize = ( rDesc.mnScanSize + 1 ) & ~1;
+ if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize ) // then we'll try word alignment
+ {
+ nScanSize = ( rDesc.mnScanSize + 3 ) & ~3;
+ if ( ( nScanSize * rDesc.mnY + nHeaderSize ) != mpCGM->mnElementSize ) // and last we'll try dword alignment
+ {
+ nScanSize = ( rDesc.mnScanSize + 1 ) & ~1; // and LAST BUT NOT LEAST we'll try word alignment without aligning the last line
+ if ( ( nScanSize * ( rDesc.mnY - 1 ) + rDesc.mnScanSize + nHeaderSize ) != mpCGM->mnElementSize )
+ {
+ nScanSize = ( rDesc.mnScanSize + 3 ) & ~3;
+ if ( ( nScanSize * ( rDesc.mnY - 1 ) + rDesc.mnScanSize + nHeaderSize ) != mpCGM->mnElementSize )
+ {
+ mpCGM->mnParaSize = 0; // this format is corrupt
+ rDesc.mbStatus = false;
+ }
+ }
+ }
+ }
+ }
+ rDesc.mnScanSize = nScanSize;
+ if ( rDesc.mbStatus )
+ {
+ rDesc.mpBuf = mpCGM->mpSource + mpCGM->mnParaSize; // mpBuf now points to the first scanline
+ rDesc.mpEndBuf = mpCGM->mpEndValidSource;
+ mpCGM->mnParaSize += rDesc.mnScanSize * rDesc.mnY;
+ }
+ return rDesc.mbStatus;
+}
+
+
+void CGMBitmap::ImplInsert( CGMBitmapDescriptor const & rSource, CGMBitmapDescriptor& rDest )
+{
+ if (utl::ConfigManager::IsFuzzing() && rDest.mxBitmap.GetSizePixel().Height() + rSource.mnY > SAL_MAX_UINT16)
+ {
+ SAL_WARN("filter.icgm", "bitmap would expand too much");
+ rDest.mbStatus = false;
+ return;
+ }
+ rDest.mxBitmap.Expand( 0, rSource.mnY );
+ rDest.mxBitmap.CopyPixel( tools::Rectangle( Point( 0, rDest.mnY ), Size( rSource.mnX, rSource.mnY ) ),
+ tools::Rectangle( Point( 0, 0 ), Size( rSource.mnX, rSource.mnY ) ), &rSource.mxBitmap );
+
+ if ( ( rSource.mnR.Y == rDest.mnQ.Y ) && ( rSource.mnR.X == rDest.mnQ.X ) )
+ { // Insert on Bottom
+ if ( mpCGM->mnVDCYmul == -1 )
+ rDest.mnOrigin = rSource.mnOrigin; // new origin
+ FloatPoint aFloatPoint;
+ aFloatPoint.X = rSource.mnQ.X - rSource.mnR.X;
+ aFloatPoint.Y = rSource.mnQ.Y - rSource.mnR.Y;
+ rDest.mnQ.X += aFloatPoint.X;
+ rDest.mnQ.Y += aFloatPoint.Y;
+ rDest.mnP = rSource.mnP;
+ rDest.mnR = rSource.mnR;
+ }
+ else
+ { // Insert on Top
+ if ( mpCGM->mnVDCYmul == 1 )
+ rDest.mnOrigin = rSource.mnOrigin; // new origin
+ rDest.mnP = rSource.mnP;
+ rDest.mnR = rSource.mnR;
+ }
+ rDest.mnY += rSource.mnY;
+ rDest.mndy += rSource.mndy;
+};
+
+std::unique_ptr<CGMBitmap> CGMBitmap::GetNext()
+{
+ std::unique_ptr<CGMBitmap> xCGMTempBitmap;
+ if (!pCGMBitmapDescriptor->mxBitmap.IsEmpty() && pCGMBitmapDescriptor->mbStatus)
+ {
+ xCGMTempBitmap.reset(new CGMBitmap(*mpCGM));
+ if ( ( static_cast<tools::Long>(xCGMTempBitmap->pCGMBitmapDescriptor->mnOrientation) == static_cast<tools::Long>(pCGMBitmapDescriptor->mnOrientation) ) &&
+ ( ( ( xCGMTempBitmap->pCGMBitmapDescriptor->mnR.X == pCGMBitmapDescriptor->mnQ.X ) &&
+ ( xCGMTempBitmap->pCGMBitmapDescriptor->mnR.Y == pCGMBitmapDescriptor->mnQ.Y ) ) ||
+ ( ( xCGMTempBitmap->pCGMBitmapDescriptor->mnQ.X == pCGMBitmapDescriptor->mnR.X ) &&
+ ( xCGMTempBitmap->pCGMBitmapDescriptor->mnQ.Y == pCGMBitmapDescriptor->mnR.Y ) ) ) )
+ {
+ ImplInsert( *(xCGMTempBitmap->pCGMBitmapDescriptor), *pCGMBitmapDescriptor );
+ xCGMTempBitmap.reset();
+ return xCGMTempBitmap;
+ }
+
+ pCGMBitmapDescriptor.swap(xCGMTempBitmap->pCGMBitmapDescriptor);
+ }
+ return xCGMTempBitmap;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/bitmap.hxx b/filter/source/graphicfilter/icgm/bitmap.hxx
new file mode 100644
index 000000000..3e7b80f51
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/bitmap.hxx
@@ -0,0 +1,81 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "cgm.hxx"
+#include <vcl/bitmapex.hxx>
+#include <vector>
+
+class CGM;
+
+class CGMBitmapDescriptor
+{
+ public:
+ sal_uInt8* mpBuf;
+ sal_uInt8* mpEndBuf;
+ BitmapEx mxBitmap;
+ bool mbStatus;
+ bool mbVMirror;
+ sal_uInt32 mnDstBitsPerPixel;
+ sal_uInt32 mnScanSize; // bytes per line
+ FloatPoint mnP, mnQ, mnR;
+
+ FloatPoint mnOrigin;
+ double mndx, mndy;
+ double mnOrientation;
+
+ sal_uInt32 mnX, mnY;
+ tools::Long mnLocalColorPrecision;
+ sal_uInt32 mnCompressionMode;
+
+ CGMBitmapDescriptor()
+ : mpBuf(nullptr)
+ , mpEndBuf(nullptr)
+ , mbStatus(false)
+ , mbVMirror(false)
+ , mnDstBitsPerPixel(0)
+ , mnScanSize(0)
+ , mndx(0.0)
+ , mndy(0.0)
+ , mnOrientation(0.0)
+ , mnX(0)
+ , mnY(0)
+ , mnLocalColorPrecision(0)
+ , mnCompressionMode(0)
+ { };
+};
+
+class CGMBitmap
+{
+ CGM* mpCGM;
+ std::unique_ptr<CGMBitmapDescriptor>
+ pCGMBitmapDescriptor;
+ bool ImplGetDimensions( CGMBitmapDescriptor& );
+ std::vector<Color> ImplGeneratePalette( CGMBitmapDescriptor const & );
+ void ImplGetBitmap( CGMBitmapDescriptor& );
+ void ImplInsert( CGMBitmapDescriptor const & rSource, CGMBitmapDescriptor& rDest );
+public:
+ explicit CGMBitmap( CGM& rCGM );
+ ~CGMBitmap();
+ CGMBitmapDescriptor* GetBitmap() { return pCGMBitmapDescriptor.get();}
+ std::unique_ptr<CGMBitmap> GetNext();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/bundles.cxx b/filter/source/graphicfilter/icgm/bundles.cxx
new file mode 100644
index 000000000..64e63a750
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/bundles.cxx
@@ -0,0 +1,141 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "bundles.hxx"
+
+#include <string.h>
+
+void Bundle::SetColor( sal_uInt32 nColor )
+{
+ mnColor = nColor;
+}
+
+CGMFList::CGMFList()
+ : nFontNameCount(0)
+ , nCharSetCount(0)
+{
+}
+
+FontEntry* CGMFList::GetFontEntry( sal_uInt32 nIndex )
+{
+ sal_uInt32 nInd = nIndex;
+ if ( nInd )
+ nInd--;
+ return ( nInd < aFontEntryList.size() ) ? &aFontEntryList[nInd] : nullptr;
+}
+
+static sal_Int8* ImplSearchEntry( sal_Int8* pSource, sal_Int8 const * pDest, sal_uInt32 nComp, sal_uInt32 nSize )
+{
+ while ( nComp-- >= nSize )
+ {
+ sal_uInt32 i;
+ for ( i = 0; i < nSize; i++ )
+ {
+ if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
+ break;
+ }
+ if ( i == nSize )
+ return pSource;
+ pSource++;
+ }
+ return nullptr;
+}
+
+void CGMFList::InsertName( sal_uInt8 const * pSource, sal_uInt32 nSize )
+{
+ FontEntry* pFontEntry;
+ if (nFontNameCount == aFontEntryList.size())
+ {
+ aFontEntryList.push_back(FontEntry());
+ pFontEntry = &aFontEntryList.back();
+ }
+ else
+ {
+ pFontEntry = &aFontEntryList[nFontNameCount];
+ }
+ nFontNameCount++;
+
+ if (nSize == 0)
+ return;
+
+ std::vector<sal_Int8> aBuf(pSource, pSource + nSize);
+ sal_Int8* pFound = ImplSearchEntry(aBuf.data(), reinterpret_cast<sal_Int8 const *>("ITALIC"), nSize, 6);
+ if (pFound)
+ {
+ pFontEntry->nFontType |= 1;
+ sal_uInt32 nPrev = pFound - aBuf.data();
+ sal_uInt32 nToCopyOfs = 6;
+ if ( nPrev && ( pFound[ -1 ] == '-' || pFound[ -1 ] == ' ' ) )
+ {
+ nPrev--;
+ pFound--;
+ nToCopyOfs++;
+ }
+ sal_uInt32 nToCopy = nSize - nToCopyOfs - nPrev;
+ if ( nToCopy )
+ {
+ memmove( pFound, pFound + nToCopyOfs, nToCopy );
+ }
+ nSize -= nToCopyOfs;
+ }
+ pFound = ImplSearchEntry(aBuf.data(), reinterpret_cast<sal_Int8 const *>("BOLD"), nSize, 4);
+ if ( pFound )
+ {
+ pFontEntry->nFontType |= 2;
+
+ sal_uInt32 nPrev = pFound - aBuf.data();
+ sal_uInt32 nToCopyOfs = 4;
+ if ( nPrev && ( pFound[ -1 ] == '-' || pFound[ -1 ] == ' ' ) )
+ {
+ nPrev--;
+ pFound--;
+ nToCopyOfs++;
+ }
+ sal_uInt32 nToCopy = nSize - nToCopyOfs - nPrev;
+ if ( nToCopy )
+ {
+ memmove( pFound, pFound + nToCopyOfs, nToCopy );
+ }
+ nSize -= nToCopyOfs;
+ }
+ pFontEntry->aFontName.assign(aBuf.data(), aBuf.data() + nSize);
+}
+
+void CGMFList::InsertCharSet( sal_uInt8 const * pSource, sal_uInt32 nSize )
+{
+ FontEntry* pFontEntry;
+ if (nCharSetCount == aFontEntryList.size())
+ {
+ aFontEntryList.push_back(FontEntry());
+ pFontEntry = &aFontEntryList.back();
+ }
+ else
+ {
+ pFontEntry = &aFontEntryList[nCharSetCount];
+ }
+ nCharSetCount++;
+
+ if (nSize == 0)
+ return;
+
+ pFontEntry->aCharSetValue.assign(pSource, pSource + nSize);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/bundles.hxx b/filter/source/graphicfilter/icgm/bundles.hxx
new file mode 100644
index 000000000..209eae6dd
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/bundles.hxx
@@ -0,0 +1,166 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+#include "cgmtypes.hxx"
+#include <vector>
+#include <memory>
+
+
+class Bundle
+{
+
+ tools::Long mnBundleIndex;
+ sal_uInt32 mnColor;
+
+public:
+ void SetColor( sal_uInt32 nColor ) ;
+ sal_uInt32 GetColor() const { return mnColor;}
+ tools::Long GetIndex() const { return mnBundleIndex; } ;
+ void SetIndex( tools::Long nBundleIndex ) { mnBundleIndex = nBundleIndex; } ;
+
+ Bundle()
+ : mnBundleIndex( 0 )
+ , mnColor( 0 )
+ {};
+
+ virtual std::unique_ptr<Bundle> Clone() { return std::make_unique<Bundle>( *this ); };
+
+ virtual ~Bundle() {} ;
+
+ Bundle(Bundle const &) = default;
+ Bundle(Bundle &&) = default;
+ Bundle & operator =(Bundle const &) = default;
+ Bundle & operator =(Bundle &&) = default;
+};
+
+
+class LineBundle : public Bundle
+{
+public:
+
+ LineType eLineType;
+ double nLineWidth;
+
+ LineBundle()
+ : eLineType(LT_SOLID)
+ , nLineWidth(0)
+ {}
+
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<LineBundle>( *this ); }
+};
+
+
+class MarkerBundle : public Bundle
+{
+public:
+
+ MarkerType eMarkerType;
+ double nMarkerSize;
+
+ MarkerBundle()
+ : eMarkerType( MT_POINT )
+ , nMarkerSize( 0.0 )
+ {};
+
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<MarkerBundle>( *this ); } ;
+};
+
+
+class EdgeBundle : public Bundle
+{
+public:
+
+ EdgeType eEdgeType;
+ double nEdgeWidth;
+
+ EdgeBundle()
+ : eEdgeType(ET_NONE)
+ , nEdgeWidth(0)
+ {}
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<EdgeBundle>( *this ); }
+};
+
+
+class TextBundle : public Bundle
+{
+public:
+
+ sal_uInt32 nTextFontIndex;
+ TextPrecision eTextPrecision;
+ double nCharacterExpansion;
+ double nCharacterSpacing;
+
+ TextBundle()
+ : nTextFontIndex( 0 )
+ , eTextPrecision( TPR_UNDEFINED )
+ , nCharacterExpansion( 0.0 )
+ , nCharacterSpacing( 0.0 )
+ {};
+
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<TextBundle>( *this ); } ;
+};
+
+
+class FillBundle : public Bundle
+{
+public:
+
+ FillInteriorStyle eFillInteriorStyle;
+ tools::Long nFillPatternIndex;
+ tools::Long nFillHatchIndex;
+
+ FillBundle()
+ : eFillInteriorStyle(FIS_HOLLOW)
+ , nFillPatternIndex(0)
+ , nFillHatchIndex(0)
+ {}
+ virtual std::unique_ptr<Bundle> Clone() override { return std::make_unique<FillBundle>( *this ); }
+};
+
+
+struct FontEntry
+{
+ std::vector<sal_Int8> aFontName;
+ std::vector<sal_Int8> aCharSetValue;
+ sal_uInt32 nFontType; // bit 0 = 1 -> Italic,
+ // bit 1 = 1 -> Bold
+ FontEntry()
+ : nFontType(0)
+ {
+ }
+};
+
+class CGMFList
+{
+ sal_uInt32 nFontNameCount;
+ sal_uInt32 nCharSetCount;
+ std::vector<FontEntry> aFontEntryList;
+
+public:
+ CGMFList();
+
+ FontEntry* GetFontEntry( sal_uInt32 );
+ void InsertName( sal_uInt8 const * pSource, sal_uInt32 nSize );
+ void InsertCharSet( sal_uInt8 const * pSource, sal_uInt32 nSize );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/cgm.cxx b/filter/source/graphicfilter/icgm/cgm.cxx
new file mode 100644
index 000000000..1cf7c7ca0
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/cgm.cxx
@@ -0,0 +1,741 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <o3tl/safeint.hxx>
+#include <osl/endian.h>
+#include <tools/stream.hxx>
+#include "bitmap.hxx"
+#include "chart.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+#include <memory>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+using namespace ::com::sun::star;
+
+constexpr double gnOutdx = 28000; // Output size in 1/100TH mm
+constexpr double gnOutdy = 21000; // on which is mapped
+
+CGM::CGM(uno::Reference< frame::XModel > const & rModel)
+ : mnVDCXadd(0)
+ , mnVDCYadd(0)
+ , mnVDCXmul(0)
+ , mnVDCYmul(0)
+ , mnVDCdx(0)
+ , mnVDCdy(0)
+ , mnXFraction(0)
+ , mnYFraction(0)
+ , mbAngReverse(false)
+ , mbStatus(true)
+ , mbMetaFile(false)
+ , mbIsFinished(false)
+ , mbPicture(false)
+ , mbPictureBody(false)
+ , mbFigure(false)
+ , mbFirstOutPut(false)
+ , mbInDefaultReplacement(false)
+ , mnAct4PostReset(0)
+ , mpOutAct(new CGMImpressOutAct(*this, rModel))
+ , mpSource(nullptr)
+ , mpEndValidSource(nullptr)
+ , mnParaSize(0)
+ , mnActCount(0)
+ , mnEscape(0)
+ , mnElementClass(0)
+ , mnElementID(0)
+ , mnElementSize(0)
+{
+ pElement.reset( new CGMElements );
+ pCopyOfE.reset( new CGMElements );
+}
+
+CGM::~CGM()
+{
+ maDefRepList.clear();
+ maDefRepSizeList.clear();
+};
+
+sal_uInt32 CGM::GetBackGroundColor() const
+{
+ return pElement ? pElement->aColorTable[ 0 ] : 0;
+}
+
+sal_uInt32 CGM::ImplGetUI16()
+{
+ sal_uInt8* pSource = mpSource + mnParaSize;
+ if (mpEndValidSource - pSource < 2)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+ mnParaSize += 2;
+ return ( pSource[ 0 ] << 8 ) + pSource[ 1 ];
+};
+
+sal_uInt8 CGM::ImplGetByte( sal_uInt32 nSource, sal_uInt32 nPrecision )
+{
+ return static_cast<sal_uInt8>( nSource >> ( ( nPrecision - 1 ) << 3 ) );
+};
+
+sal_Int32 CGM::ImplGetI( sal_uInt32 nPrecision )
+{
+ sal_uInt8* pSource = mpSource + mnParaSize;
+ if (pSource > mpEndValidSource || o3tl::make_unsigned(mpEndValidSource - pSource) < nPrecision)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+ mnParaSize += nPrecision;
+ switch( nPrecision )
+ {
+ case 1 :
+ {
+ return static_cast<char>(*pSource);
+ }
+
+ case 2 :
+ {
+ return static_cast<sal_Int16>( ( pSource[ 0 ] << 8 ) | pSource[ 1 ] );
+ }
+
+ case 3 :
+ {
+ return ( ( pSource[ 0 ] << 24 ) | ( pSource[ 1 ] << 16 ) | pSource[ 2 ] << 8 ) >> 8;
+ }
+ case 4:
+ {
+ return static_cast<sal_Int32>( ( pSource[ 0 ] << 24 ) | ( pSource[ 1 ] << 16 ) | ( pSource[ 2 ] << 8 ) | ( pSource[ 3 ] ) );
+ }
+ default:
+ mbStatus = false;
+ return 0;
+ }
+}
+
+sal_uInt32 CGM::ImplGetUI( sal_uInt32 nPrecision )
+{
+ sal_uInt8* pSource = mpSource + mnParaSize;
+ if (pSource > mpEndValidSource || o3tl::make_unsigned(mpEndValidSource - pSource) < nPrecision)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+ mnParaSize += nPrecision;
+ switch( nPrecision )
+ {
+ case 1 :
+ return static_cast<sal_Int8>(*pSource);
+ case 2 :
+ {
+ return static_cast<sal_uInt16>( ( pSource[ 0 ] << 8 ) | pSource[ 1 ] );
+ }
+ case 3 :
+ {
+ return ( pSource[ 0 ] << 16 ) | ( pSource[ 1 ] << 8 ) | pSource[ 2 ];
+ }
+ case 4:
+ {
+ return static_cast<sal_uInt32>( ( pSource[ 0 ] << 24 ) | ( pSource[ 1 ] << 16 ) | ( pSource[ 2 ] << 8 ) | ( pSource[ 3 ] ) );
+ }
+ default:
+ mbStatus = false;
+ return 0;
+ }
+}
+
+void CGM::ImplGetSwitch4( const sal_uInt8* pSource, sal_uInt8* pDest )
+{
+ for ( int i = 0; i < 4; i++ )
+ {
+ pDest[ i ] = pSource[ i ^ 3 ]; // Little Endian <-> Big Endian switch
+ }
+}
+
+void CGM::ImplGetSwitch8( const sal_uInt8* pSource, sal_uInt8* pDest )
+{
+ for ( int i = 0; i < 8; i++ )
+ {
+ pDest[ i ] = pSource[ i ^ 7 ]; // Little Endian <-> Big Endian switch
+ }
+}
+
+double CGM::ImplGetFloat( RealPrecision eRealPrecision, sal_uInt32 nRealSize )
+{
+ void* pPtr;
+ sal_uInt8 aBuf[8];
+ double nRetValue;
+ double fDoubleBuf;
+ float fFloatBuf;
+
+#ifdef OSL_BIGENDIAN
+ const bool bCompatible = true;
+#else
+ const bool bCompatible = false;
+#endif
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nRealSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ if ( bCompatible )
+ {
+ pPtr = mpSource + mnParaSize;
+ }
+ else
+ {
+ if ( nRealSize == 4 )
+ ImplGetSwitch4( mpSource + mnParaSize, &aBuf[0] );
+ else
+ ImplGetSwitch8( mpSource + mnParaSize, &aBuf[0] );
+ pPtr = &aBuf;
+ }
+ if ( eRealPrecision == RP_FLOAT )
+ {
+ if ( nRealSize == 4 )
+ {
+ memcpy( static_cast<void*>(&fFloatBuf), pPtr, 4 );
+ nRetValue = static_cast<double>(fFloatBuf);
+ }
+ else
+ {
+ memcpy( static_cast<void*>(&fDoubleBuf), pPtr, 8 );
+ nRetValue = fDoubleBuf;
+ }
+ }
+ else // ->RP_FIXED
+ {
+ tools::Long nVal;
+ const int nSwitch = bCompatible ? 0 : 1 ;
+ if ( nRealSize == 4 )
+ {
+ sal_uInt16* pShort = static_cast<sal_uInt16*>(pPtr);
+ nVal = pShort[ nSwitch ];
+ nVal <<= 16;
+ nVal |= pShort[ nSwitch ^ 1 ];
+ nRetValue = static_cast<double>(nVal);
+ nRetValue /= 65536;
+ }
+ else
+ {
+ sal_Int32* pLong = static_cast<sal_Int32*>(pPtr);
+ nRetValue = static_cast<double>(abs( pLong[ nSwitch ] ));
+ nRetValue *= 65536;
+ nVal = static_cast<sal_uInt32>( pLong[ nSwitch ^ 1 ] );
+ nVal >>= 16;
+ nRetValue += static_cast<double>(nVal);
+ if ( pLong[ nSwitch ] < 0 )
+ {
+ nRetValue = -nRetValue;
+ }
+ nRetValue /= 65536;
+ }
+ }
+ mnParaSize += nRealSize;
+ return nRetValue;
+}
+
+sal_uInt32 CGM::ImplGetPointSize()
+{
+ if ( pElement->eVDCType == VDC_INTEGER )
+ return pElement->nVDCIntegerPrecision << 1;
+ else
+ return pElement->nVDCRealSize << 1;
+}
+
+inline double CGM::ImplGetIX()
+{
+ return ( ( ImplGetI( pElement->nVDCIntegerPrecision ) + mnVDCXadd ) * mnVDCXmul );
+}
+
+inline double CGM::ImplGetFX()
+{
+ return ( ( ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize ) + mnVDCXadd ) * mnVDCXmul );
+}
+
+inline double CGM::ImplGetIY()
+{
+ return ( ( ImplGetI( pElement->nVDCIntegerPrecision ) + mnVDCYadd ) * mnVDCYmul );
+}
+
+inline double CGM::ImplGetFY()
+{
+ return ( ( ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize ) + mnVDCYadd ) * mnVDCYmul );
+}
+
+void CGM::ImplGetPoint( FloatPoint& rFloatPoint, bool bMap )
+{
+ if ( pElement->eVDCType == VDC_INTEGER )
+ {
+ rFloatPoint.X = ImplGetIX();
+ rFloatPoint.Y = ImplGetIY();
+ }
+ else // ->floating points
+ {
+ rFloatPoint.X = ImplGetFX();
+ rFloatPoint.Y = ImplGetFY();
+ }
+ if ( bMap )
+ ImplMapPoint( rFloatPoint );
+}
+
+void CGM::ImplGetRectangle( FloatRect& rFloatRect, bool bMap )
+{
+ if ( pElement->eVDCType == VDC_INTEGER )
+ {
+ rFloatRect.Left = ImplGetIX();
+ rFloatRect.Bottom = ImplGetIY();
+ rFloatRect.Right = ImplGetIX();
+ rFloatRect.Top = ImplGetIY();
+ }
+ else // ->floating points
+ {
+ rFloatRect.Left = ImplGetFX();
+ rFloatRect.Bottom = ImplGetFY();
+ rFloatRect.Right = ImplGetFX();
+ rFloatRect.Top = ImplGetFY();
+ }
+ if ( bMap )
+ {
+ ImplMapX( rFloatRect.Left );
+ ImplMapX( rFloatRect.Right );
+ ImplMapY( rFloatRect.Top );
+ ImplMapY( rFloatRect.Bottom );
+ rFloatRect.Justify();
+ }
+}
+
+void CGM::ImplGetRectangleNS( FloatRect& rFloatRect )
+{
+ if ( pElement->eVDCType == VDC_INTEGER )
+ {
+ rFloatRect.Left = ImplGetI( pElement->nVDCIntegerPrecision );
+ rFloatRect.Bottom = ImplGetI( pElement->nVDCIntegerPrecision );
+ rFloatRect.Right = ImplGetI( pElement->nVDCIntegerPrecision );
+ rFloatRect.Top = ImplGetI( pElement->nVDCIntegerPrecision );
+ }
+ else // ->floating points
+ {
+ rFloatRect.Left = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ rFloatRect.Bottom = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ rFloatRect.Right = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ rFloatRect.Top = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+}
+
+sal_uInt32 CGM::ImplGetBitmapColor( bool bDirect )
+{
+ // the background color is always a direct color
+
+ sal_uInt32 nTmp;
+ if ( ( pElement->eColorSelectionMode == CSM_DIRECT ) || bDirect )
+ {
+ sal_uInt32 nColor = ImplGetByte( ImplGetUI( pElement->nColorPrecision ), 1 );
+ sal_uInt32 nDiff = pElement->nColorValueExtent[ 3 ] - pElement->nColorValueExtent[ 0 ] + 1;
+
+ if ( !nDiff )
+ nDiff++;
+ nColor = ( ( nColor - pElement->nColorValueExtent[ 0 ] ) << 8 ) / nDiff;
+ nTmp = nColor << 16 & 0xff0000;
+
+ nColor = ImplGetByte( ImplGetUI( pElement->nColorPrecision ), 1 );
+ nDiff = pElement->nColorValueExtent[ 4 ] - pElement->nColorValueExtent[ 1 ] + 1;
+ if ( !nDiff )
+ nDiff++;
+ nColor = ( ( nColor - pElement->nColorValueExtent[ 1 ] ) << 8 ) / nDiff;
+ nTmp |= nColor << 8 & 0xff00;
+
+ nColor = ImplGetByte( ImplGetUI( pElement->nColorPrecision ), 1 );
+ nDiff = pElement->nColorValueExtent[ 5 ] - pElement->nColorValueExtent[ 2 ] + 1;
+ if ( !nDiff )
+ nDiff++;
+ nColor = ( ( nColor - pElement->nColorValueExtent[ 2 ] ) << 8 ) / nDiff;
+ nTmp |= static_cast<sal_uInt8>(nColor);
+ }
+ else
+ {
+ sal_uInt32 nIndex = ImplGetUI( pElement->nColorIndexPrecision );
+ nTmp = pElement->aColorTable[ static_cast<sal_uInt8>(nIndex) ] ;
+ }
+ return nTmp;
+}
+
+// call this function each time after the mapmode settings has been changed
+void CGM::ImplSetMapMode()
+{
+ int nAngReverse = 1;
+ mnVDCdx = pElement->aVDCExtent.Right - pElement->aVDCExtent.Left;
+
+ mnVDCXadd = -pElement->aVDCExtent.Left;
+ mnVDCXmul = 1;
+ if ( mnVDCdx < 0 )
+ {
+ nAngReverse ^= 1;
+ mnVDCdx = -mnVDCdx;
+ mnVDCXmul = -1;
+ }
+
+ mnVDCdy = pElement->aVDCExtent.Bottom - pElement->aVDCExtent.Top;
+ mnVDCYadd = -pElement->aVDCExtent.Top;
+ mnVDCYmul = 1;
+ if ( mnVDCdy < 0 )
+ {
+ nAngReverse ^= 1;
+ mnVDCdy = -mnVDCdy;
+ mnVDCYmul = -1;
+ }
+ if ( nAngReverse )
+ mbAngReverse = true;
+ else
+ mbAngReverse = false;
+
+ if (mnVDCdy == 0.0 || mnVDCdx == 0.0 || gnOutdy == 0.0)
+ {
+ mbStatus = false;
+ return;
+ }
+
+ double fQuo1 = mnVDCdx / mnVDCdy;
+ double fQuo2 = gnOutdx / gnOutdy;
+ if ( fQuo2 < fQuo1 )
+ {
+ mnXFraction = gnOutdx / mnVDCdx;
+ mnYFraction = gnOutdy * ( fQuo2 / fQuo1 ) / mnVDCdy;
+ }
+ else
+ {
+ mnXFraction = gnOutdx * ( fQuo1 / fQuo2 ) / mnVDCdx;
+ mnYFraction = gnOutdy / mnVDCdy;
+ }
+}
+
+void CGM::ImplMapDouble( double& nNumb )
+{
+ if ( pElement->eDeviceViewPortMap != DVPM_FORCED )
+ return;
+
+ // point is 1mm * ScalingFactor
+ switch ( pElement->eDeviceViewPortMode )
+ {
+ case DVPM_FRACTION :
+ {
+ nNumb *= ( mnXFraction + mnYFraction ) / 2;
+ }
+ break;
+
+ case DVPM_METRIC :
+ {
+ // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
+ nNumb *= ( mnXFraction + mnYFraction ) / 2;
+ if ( pElement->nDeviceViewPortScale < 0 )
+ nNumb = -nNumb;
+ }
+ break;
+
+ case DVPM_DEVICE :
+ {
+
+ }
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+void CGM::ImplMapX( double& nNumb )
+{
+ if ( pElement->eDeviceViewPortMap != DVPM_FORCED )
+ return;
+
+ // point is 1mm * ScalingFactor
+ switch ( pElement->eDeviceViewPortMode )
+ {
+ case DVPM_FRACTION :
+ {
+ nNumb *= mnXFraction;
+ }
+ break;
+
+ case DVPM_METRIC :
+ {
+ // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
+ nNumb *= mnXFraction;
+ if ( pElement->nDeviceViewPortScale < 0 )
+ nNumb = -nNumb;
+ }
+ break;
+
+ case DVPM_DEVICE :
+ {
+
+ }
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+void CGM::ImplMapY( double& nNumb )
+{
+ if ( pElement->eDeviceViewPortMap != DVPM_FORCED )
+ return;
+
+ // point is 1mm * ScalingFactor
+ switch ( pElement->eDeviceViewPortMode )
+ {
+ case DVPM_FRACTION :
+ {
+ nNumb *= mnYFraction;
+ }
+ break;
+
+ case DVPM_METRIC :
+ {
+ // nNumb *= ( 100 * pElement->nDeviceViewPortScale );
+ nNumb *= mnYFraction;
+ if ( pElement->nDeviceViewPortScale < 0 )
+ nNumb = -nNumb;
+ }
+ break;
+
+ case DVPM_DEVICE :
+ {
+
+ }
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+// convert a point to the current VC mapmode (1/100TH mm)
+void CGM::ImplMapPoint( FloatPoint& rFloatPoint )
+{
+ if ( pElement->eDeviceViewPortMap != DVPM_FORCED )
+ return;
+
+ // point is 1mm * ScalingFactor
+ switch ( pElement->eDeviceViewPortMode )
+ {
+ case DVPM_FRACTION :
+ {
+ rFloatPoint.X *= mnXFraction;
+ rFloatPoint.Y *= mnYFraction;
+ }
+ break;
+
+ case DVPM_METRIC :
+ {
+ rFloatPoint.X *= mnXFraction;
+ rFloatPoint.Y *= mnYFraction;
+ if ( pElement->nDeviceViewPortScale < 0 )
+ {
+ rFloatPoint.X = -rFloatPoint.X;
+ rFloatPoint.Y = -rFloatPoint.Y;
+ }
+ }
+ break;
+
+ case DVPM_DEVICE :
+ {
+
+ }
+ break;
+
+ default:
+
+ break;
+ }
+}
+
+void CGM::ImplDoClass()
+{
+ switch ( mnElementClass )
+ {
+ case 0 : ImplDoClass0(); break;
+ case 1 : ImplDoClass1(); break;
+ case 2 : ImplDoClass2(); break;
+ case 3 : ImplDoClass3(); break;
+ case 4 :
+ {
+ ImplDoClass4();
+ mnAct4PostReset = 0;
+ }
+ break;
+ case 5 : ImplDoClass5(); break;
+ case 6 : ImplDoClass6(); break;
+ case 7 : ImplDoClass7(); break;
+ case 8 : ImplDoClass8(); break;
+ case 9 : ImplDoClass9(); break;
+ case 15 :ImplDoClass15(); break;
+ default: break;
+ }
+ mnActCount++;
+};
+
+void CGM::ImplDefaultReplacement()
+{
+ if (maDefRepList.empty())
+ return;
+
+ if (mbInDefaultReplacement)
+ {
+ SAL_WARN("filter.icgm", "recursion in ImplDefaultReplacement");
+ return;
+ }
+
+ mbInDefaultReplacement = true;
+
+ sal_uInt32 nOldEscape = mnEscape;
+ sal_uInt32 nOldElementClass = mnElementClass;
+ sal_uInt32 nOldElementID = mnElementID;
+ sal_uInt32 nOldElementSize = mnElementSize;
+ sal_uInt8* pOldBuf = mpSource;
+ sal_uInt8* pOldEndValidSource = mpEndValidSource;
+
+ for ( size_t i = 0, n = maDefRepList.size(); i < n; ++i )
+ {
+ sal_uInt8* pBuf = maDefRepList[ i ].get();
+ sal_uInt32 nElementSize = maDefRepSizeList[ i ];
+ mpEndValidSource = pBuf + nElementSize;
+ sal_uInt32 nCount = 0;
+ while ( mbStatus && ( nCount < nElementSize ) )
+ {
+ mpSource = pBuf + nCount;
+ mnParaSize = 0;
+ mnEscape = ImplGetUI16();
+ mnElementClass = mnEscape >> 12;
+ mnElementID = ( mnEscape & 0x0fe0 ) >> 5;
+ mnElementSize = mnEscape & 0x1f;
+ if ( mnElementSize == 31 )
+ {
+ mnElementSize = ImplGetUI16();
+ }
+ nCount += mnParaSize;
+ mnParaSize = 0;
+ mpSource = pBuf + nCount;
+ if ( mnElementSize & 1 )
+ nCount++;
+ nCount += mnElementSize;
+ if ( ( mnElementClass != 1 ) || ( mnElementID != 0xc ) ) // recursion is not possible here!!
+ ImplDoClass();
+ }
+ }
+ mnEscape = nOldEscape;
+ mnElementClass = nOldElementClass;
+ mnElementID = nOldElementID;
+ mnParaSize = mnElementSize = nOldElementSize;
+ mpSource = pOldBuf;
+ mpEndValidSource = pOldEndValidSource;
+
+ mbInDefaultReplacement = false;
+}
+
+bool CGM::Write( SvStream& rIStm )
+{
+ if ( !mpBuf )
+ mpBuf.reset( new sal_uInt8[ 0xffff ] );
+
+ mnParaSize = 0;
+ mpSource = mpBuf.get();
+ if (rIStm.ReadBytes(mpSource, 2) != 2)
+ return false;
+ mpEndValidSource = mpSource + 2;
+ mnEscape = ImplGetUI16();
+ mnElementClass = mnEscape >> 12;
+ mnElementID = ( mnEscape & 0x0fe0 ) >> 5;
+ mnElementSize = mnEscape & 0x1f;
+
+ if ( mnElementSize == 31 )
+ {
+ if (rIStm.ReadBytes(mpSource + mnParaSize, 2) != 2)
+ return false;
+ mpEndValidSource = mpSource + mnParaSize + 2;
+ mnElementSize = ImplGetUI16();
+ }
+ mnParaSize = 0;
+ if (mnElementSize)
+ {
+ if (rIStm.ReadBytes(mpSource, mnElementSize) != mnElementSize)
+ return false;
+ mpEndValidSource = mpSource + mnElementSize;
+ }
+
+ if ( mnElementSize & 1 )
+ rIStm.SeekRel( 1 );
+ ImplDoClass();
+
+ return mbStatus;
+};
+
+// GraphicImport - the exported function
+extern "C" SAL_DLLPUBLIC_EXPORT sal_uInt32
+ImportCGM(SvStream& rIn, uno::Reference< frame::XModel > const & rXModel, css::uno::Reference<css::task::XStatusIndicator> const & aXStatInd)
+{
+
+ sal_uInt32 nStatus = 0; // retvalue == 0 -> ERROR
+ // == 0xffrrggbb -> background color in the lower 24 bits
+
+ if( rXModel.is() )
+ {
+ try
+ {
+ CGM aCGM(rXModel);
+ if (aCGM.IsValid())
+ {
+ rIn.SetEndian(SvStreamEndian::BIG);
+ sal_uInt64 const nInSize = rIn.remainingSize();
+ rIn.Seek(0);
+
+ sal_uInt32 nNext = 0;
+ sal_uInt32 nAdd = nInSize / 20;
+ bool bProgressBar = aXStatInd.is();
+ if ( bProgressBar )
+ aXStatInd->start( "CGM Import" , nInSize );
+
+ while (aCGM.IsValid() && (rIn.Tell() < nInSize) && !aCGM.IsFinished())
+ {
+ if ( bProgressBar )
+ {
+ sal_uInt32 nCurrentPos = rIn.Tell();
+ if ( nCurrentPos >= nNext )
+ {
+ aXStatInd->setValue( nCurrentPos );
+ nNext = nCurrentPos + nAdd;
+ }
+ }
+
+ if (!aCGM.Write(rIn))
+ break;
+ }
+ if ( aCGM.IsValid() )
+ {
+ nStatus = aCGM.GetBackGroundColor() | 0xff000000;
+ }
+ if ( bProgressBar )
+ aXStatInd->end();
+ }
+ }
+ catch (const css::uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.icgm", "");
+ nStatus = 0;
+ }
+ }
+ return nStatus;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/cgm.hxx b/filter/source/graphicfilter/icgm/cgm.hxx
new file mode 100644
index 000000000..b344cb22e
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/cgm.hxx
@@ -0,0 +1,151 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <cmath>
+#include <memory>
+#include <vector>
+#include "cgmtypes.hxx"
+
+class Graphic;
+class SvStream;
+class CGMChart;
+class CGMBitmap;
+class CGMImpressOutAct;
+class CGMElements;
+class GDIMetaFile;
+class VirtualDevice;
+
+class CGM
+{
+ friend class CGMChart;
+ friend class CGMBitmap;
+ friend class CGMElements;
+ friend class CGMImpressOutAct;
+
+ double mnVDCXadd;
+ double mnVDCYadd;
+ double mnVDCXmul;
+ double mnVDCYmul;
+ double mnVDCdx;
+ double mnVDCdy;
+ double mnXFraction;
+ double mnYFraction;
+ bool mbAngReverse; // AngularDirection
+
+ bool mbStatus;
+ bool mbMetaFile;
+ bool mbIsFinished;
+ bool mbPicture;
+ bool mbPictureBody;
+ bool mbFigure;
+ bool mbFirstOutPut;
+ bool mbInDefaultReplacement;
+ sal_uInt32 mnAct4PostReset;
+ std::unique_ptr<CGMBitmap> mpBitmapInUse;
+ std::unique_ptr<CGMChart> mpChart; // if sal_True->"SHWSLIDEREC"
+ // otherwise "BEGINPIC" commands
+ // controls page inserting
+ std::unique_ptr<CGMElements> pElement;
+ std::unique_ptr<CGMElements> pCopyOfE;
+ std::unique_ptr<CGMImpressOutAct> mpOutAct;
+ ::std::vector< std::unique_ptr<sal_uInt8[]> > maDefRepList;
+ ::std::vector< sal_uInt32 > maDefRepSizeList;
+
+ sal_uInt8* mpSource; // start of source buffer that is not increased
+ // ( instead use mnParaCount to index )
+ sal_uInt8* mpEndValidSource; // end position in source buffer of last valid data
+ sal_uInt32 mnParaSize; // actual parameter size which has been done so far
+ sal_uInt32 mnActCount; // increased by each action
+ std::unique_ptr<sal_uInt8[]>
+ mpBuf; // source stream operation -> then this is allocated for
+ // the temp input buffer
+
+ sal_uInt32 mnEscape;
+ sal_uInt32 mnElementClass;
+ sal_uInt32 mnElementID;
+ sal_uInt32 mnElementSize; // full parameter size for the latest action
+
+ sal_uInt32 ImplGetUI16();
+ static sal_uInt8 ImplGetByte( sal_uInt32 nSource, sal_uInt32 nPrecision );
+ sal_Int32 ImplGetI( sal_uInt32 nPrecision );
+ sal_uInt32 ImplGetUI( sal_uInt32 nPrecision );
+ static void ImplGetSwitch4( const sal_uInt8* pSource, sal_uInt8* pDest );
+ static void ImplGetSwitch8( const sal_uInt8* pSource, sal_uInt8* pDest );
+ double ImplGetFloat( RealPrecision, sal_uInt32 nRealSize );
+ sal_uInt32 ImplGetBitmapColor( bool bDirectColor = false );
+ void ImplSetMapMode();
+ void ImplSetUnderlineMode();
+ void ImplMapDouble( double& );
+ void ImplMapX( double& );
+ void ImplMapY( double& );
+ void ImplMapPoint( FloatPoint& );
+ inline double ImplGetIY();
+ inline double ImplGetFY();
+ inline double ImplGetIX();
+ inline double ImplGetFX();
+ sal_uInt32 ImplGetPointSize();
+ void ImplGetPoint( FloatPoint& rFloatPoint, bool bMap = false );
+ void ImplGetRectangle( FloatRect&, bool bMap = false );
+ void ImplGetRectangleNS( FloatRect& );
+ void ImplGetVector( double* );
+ static double ImplGetOrientation( FloatPoint const & rCenter, FloatPoint const & rPoint );
+ static void ImplSwitchStartEndAngle( double& rStartAngle, double& rEndAngle );
+ bool ImplGetEllipse( FloatPoint& rCenter, FloatPoint& rRadius, double& rOrientation );
+
+ void ImplDefaultReplacement();
+ void ImplDoClass();
+ void ImplDoClass0();
+ void ImplDoClass1();
+ void ImplDoClass2();
+ void ImplDoClass3();
+ void ImplDoClass4();
+ void ImplDoClass5();
+ void ImplDoClass6();
+ void ImplDoClass7();
+ void ImplDoClass8();
+ void ImplDoClass9();
+ void ImplDoClass15();
+
+ public:
+
+ ~CGM();
+
+ CGM(css::uno::Reference< css::frame::XModel > const & rModel);
+ sal_uInt32 GetBackGroundColor() const;
+ bool IsValid() const { return mbStatus; };
+ bool IsFinished() const { return mbIsFinished; };
+ bool Write( SvStream& rIStm );
+
+};
+
+inline bool useless(double value)
+{
+ if (!std::isfinite(value))
+ return true;
+ int exp;
+ std::frexp(value, &exp);
+ const int maxbits = sizeof(tools::Long) * 8;
+ return exp > maxbits;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/cgmtypes.hxx b/filter/source/graphicfilter/icgm/cgmtypes.hxx
new file mode 100644
index 000000000..5b7def212
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/cgmtypes.hxx
@@ -0,0 +1,127 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <tools/long.hxx>
+
+struct FloatPoint
+{
+ double X;
+ double Y;
+ FloatPoint():X(0), Y(0){};
+};
+
+struct FloatRect
+{
+ double Left;
+ double Top;
+ double Right;
+ double Bottom;
+ FloatRect():Left(0), Top(0), Right(0), Bottom(0){};
+ void Justify()
+ {
+ double fTemp;
+ if ( Left > Right )
+ {
+ fTemp = Left;
+ Left = Right;
+ Right = fTemp;
+ }
+ if ( Top > Bottom )
+ {
+ fTemp = Top;
+ Top = Bottom;
+ Bottom = fTemp;
+ }
+ }
+};
+
+struct HatchEntry
+{
+ int HatchStyle;
+ tools::Long HatchDistance;
+ tools::Long HatchAngle;
+};
+
+#define ASF_LINETYPE 0x00000001UL
+#define ASF_LINEWIDTH 0x00000002UL
+#define ASF_LINECOLOR 0x00000004UL
+#define ASF_MARKERTYPE 0x00000008UL
+#define ASF_MARKERSIZE 0x00000010UL
+#define ASF_MARKERCOLOR 0x00000020UL // NS
+#define ASF_FILLINTERIORSTYLE 0x00000040UL
+#define ASF_HATCHINDEX 0x00000080UL
+#define ASF_PATTERNINDEX 0x00000100UL
+#define ASF_BITMAPINDEX 0x00000200UL // NS
+#define ASF_FILLCOLOR 0x00000400UL
+#define ASF_EDGETYPE 0x00000800UL
+#define ASF_EDGEWIDTH 0x00001000UL
+#define ASF_EDGECOLOR 0x00002000UL
+#define ASF_TEXTFONTINDEX 0x00004000UL
+#define ASF_TEXTPRECISION 0x00008000UL
+#define ASF_CHARACTEREXPANSION 0x00010000UL
+#define ASF_CHARACTERSPACING 0x00020000UL
+#define ASF_TEXTCOLOR 0x00040000UL
+
+#define ACT4_GRADIENT_ACTION 0x00000001UL
+
+enum RealPrecision { RP_FLOAT = 0, RP_FIXED = 1 };
+
+enum ScalingMode { SM_ABSTRACT = 0, SM_METRIC = 1 };
+
+enum VDCType { VDC_INTEGER = 0, VDC_REAL = 1 };
+enum DeviceViewPortMode { DVPM_FRACTION = 0, DVPM_METRIC = 1, DVPM_DEVICE = 2 };
+enum DeviceViewPortMap { DVPM_NOT_FORCED = 0, DVPM_FORCED = 1 };
+enum DeviceViewPortMapH { DVPMH_LEFT = 0, DVPMH_CENTER = 1, CVPMH_RIGHT = 2 };
+enum DeviceViewPortMapV { DVPMV_BOTTOM = 0, DVPMV_CENTER = 1, DVPMV_TOP = 2 };
+
+enum ClipIndicator { CI_OFF = 0, CI_ON = 1 };
+
+enum ColorSelectionMode { CSM_INDEXED = 0, CSM_DIRECT = 1 };
+enum ColorModel { CM_RGB = 0, CM_CMYK = 1 };
+
+enum CharacterCodingA { CCA_BASIC_7 = 0, CCA_BASIC_8 = 1, CCA_EXT_7 = 2, CCA_EXT_8 = 3 };
+enum TextPrecision { TPR_STRING = 0, TPR_CHARACTER = 1, TPR_STROKE = 2, TPR_UNDEFINED = 0xffff };
+enum TextPath { TPR_RIGHT = 0, TPR_LEFT = 1, TPR_UP = 2, TPR_DOWN = 3 };
+enum TextAlignmentH { TAH_NORMAL = 0, TAH_LEFT = 1, TAH_CENTER = 2, TAH_RIGHT = 3, TAH_CONT = 4 };
+enum TextAlignmentV { TAV_NORMAL = 0, TAV_TOP = 1, TAV_CAP = 2, TAV_HALF = 3, TAV_BASE = 4, TAV_BOTTOM = 5, TAV_CONT = 6 };
+enum UnderlineMode { UM_OFF = 0, UM_LOW = 1, UM_HIGH = 2, UM_STRIKEOUT = 4, UM_OVERSCORE = 8 };
+enum FinalFlag { FF_NOT_FINAL = 0, FF_FINAL = 1 };
+
+enum LineType { LT_SOLID = 1, LT_DASH = 2, LT_DOT = 3, LT_DASHDOT = 4, LT_DASHDOTDOT = 5, // Standard
+ LT_NONE = -4, LT_DOTDOTSPACE = -3, LT_LONGDASH = -2, LT_DASHDASHDOT = -1 }; // GDSF Styles
+enum SpecMode { SM_ABSOLUTE = 0, SM_SCALED = 1 };
+enum LineCapType { LCT_BUTT = 0, LCT_ROUND = 1, LCT_SQUARE = 2, LCT_TRIANGLE = 3, LCT_ARROW = 4, LCT_NONE = -1 };
+enum LineJoinType { LJT_MITER = 0, LJT_ROUND = 1, LJT_BEVEL = 2, LJT_NONE = -1 };
+
+
+enum EdgeType { ET_SOLID = 1, ET_DASH = 2, ET_DOT = 3, ET_DASHDOT = 4, ET_DASHDOTDOT = 5, // Standard
+ ET_NONE = -4, ET_DOTDOTSPACE = -3, ET_LONGDASH = -2, ET_DASHDASHDOT = -1 }; // GDSF Styles
+enum EdgeVisibility { EV_OFF = 0, EV_ON = 1 };
+
+enum MarkerType { MT_POINT = 1, MT_PLUS = 2, MT_STAR = 3, MT_CIRCLE = 4, MT_CROSS = 5 };
+
+enum Transparency { T_OFF = 0, T_ON = 1 };
+
+enum FillInteriorStyle { FIS_HOLLOW = 0, FIS_SOLID = 1, FIS_PATTERN = 2, FIS_HATCH = 3, FIS_EMPTY = 4, FIS_GEOPATTERN = 5,
+ FIS_INTERPOLATED = 6, FIS_GRADIENT = 7 };
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/chart.cxx b/filter/source/graphicfilter/icgm/chart.cxx
new file mode 100644
index 000000000..91818149a
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/chart.cxx
@@ -0,0 +1,57 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "chart.hxx"
+
+
+CGMChart::CGMChart()
+ : mnCurrentFileType(0)
+{
+ for ( sal_Int8 i = 0; i < 7; i++ )
+ {
+ mDataNode[ i ].nZoneEnum = i;
+ }
+}
+
+CGMChart::~CGMChart()
+{
+ // delete the whole textentry structure
+ for (const auto & pTextEntry : maTextEntryList)
+ {
+ if ( pTextEntry )
+ delete [] pTextEntry->pText;
+ }
+}
+
+void CGMChart::InsertTextEntry( std::unique_ptr<TextEntry> pTextEntry )
+{
+ maTextEntryList.push_back( std::move(pTextEntry) );
+}
+
+void CGMChart::ResetAnnotation()
+{
+ mDataNode[ 0 ].nZoneEnum = 0;
+}
+
+bool CGMChart::IsAnnotation() const
+{
+ return ( mDataNode[ 0 ].nZoneEnum == 0 );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/chart.hxx b/filter/source/graphicfilter/icgm/chart.hxx
new file mode 100644
index 000000000..ef77ace0e
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/chart.hxx
@@ -0,0 +1,84 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/types.h>
+
+#include <memory>
+#include <vector>
+
+/* FILE TYPE CONSTANTS: */
+#define BULCHART 32 /* Bullet chart file. */
+/* the following were added although SPC doesn't have a #define */
+/* for them... */
+#define AUTOTTLCHT 95 /* Autobuild TTL CHT */
+#define AUTOBULCHT 96 /* Autobuild BUL CHT */
+#define AUTOTABCHT 97 /* Autobuild TAB CHT */
+
+typedef struct TextEntry
+{
+ sal_uInt16 nTypeOfText;
+ sal_uInt16 nRowOrLineNum;
+ sal_uInt16 nColumnNum;
+ sal_uInt16 nZoneSize; // textzone attributes
+ sal_uInt16 nLineType;
+ sal_uInt16 nAttributes;
+ char* pText; // null terminated text
+} TextEntry;
+
+struct DataNode
+{
+ sal_Int16 nBoxX1;
+ sal_Int16 nBoxY1;
+ sal_Int16 nBoxX2;
+ sal_Int16 nBoxY2;
+ sal_Int8 nZoneEnum;
+ DataNode()
+ : nBoxX1(0)
+ , nBoxY1(0)
+ , nBoxX2(0)
+ , nBoxY2(0)
+ , nZoneEnum(0)
+ {
+ }
+};
+
+class CGM;
+class CGMImpressOutAct;
+class CGMChart final
+{
+ friend class CGM;
+ friend class CGMImpressOutAct;
+
+ sal_Int8 mnCurrentFileType;
+ ::std::vector< std::unique_ptr<TextEntry> > maTextEntryList;
+ DataNode mDataNode[ 7 ];
+
+ public:
+ CGMChart();
+ ~CGMChart();
+
+ void InsertTextEntry( std::unique_ptr<TextEntry> );
+
+ void ResetAnnotation();
+ bool IsAnnotation() const;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class0.cxx b/filter/source/graphicfilter/icgm/class0.cxx
new file mode 100644
index 000000000..a31bce5d2
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class0.cxx
@@ -0,0 +1,128 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "bitmap.hxx"
+#include "cgm.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+
+void CGM::ImplDoClass0()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Begin Metafile*/
+ {
+ ImplSetMapMode();
+ mbMetaFile = true;
+ }
+ break;
+ case 0x02 : /*End MetaFile*/
+ {
+ if ( mpBitmapInUse ) // process existing graphic
+ {
+ CGMBitmapDescriptor* pBmpDesc = mpBitmapInUse->GetBitmap();
+ // do anything with the bitmap
+ mpOutAct->DrawBitmap( pBmpDesc );
+ mpBitmapInUse.reset();
+ }
+ mbIsFinished = true;
+ mbPictureBody = false;
+ mbMetaFile = false;
+ }
+ break;
+ case 0x03 : /*Begin Picture*/
+ {
+ if (mbPicture || mbInDefaultReplacement)
+ mbStatus = false;
+ else
+ {
+ *pCopyOfE = *pElement;
+ ImplDefaultReplacement();
+ ImplSetMapMode();
+ mbPicture = mbFirstOutPut = true;
+ mbFigure = false;
+ mnAct4PostReset = 0;
+ if ( mpChart == nullptr ) // normal CGM Files determines "BeginPic"
+ mpOutAct->InsertPage(); // as the next slide
+ }
+ }
+ break;
+ case 0x04 : /*Begin Picture Body*/
+ mbPictureBody = true;
+ break;
+ case 0x05 : /* End Picture*/
+ {
+ if ( mbPicture )
+ {
+ if ( mpBitmapInUse ) // process existing graphic
+ {
+ CGMBitmapDescriptor* pBmpDesc = mpBitmapInUse->GetBitmap();
+ // do anything with the bitmap
+ mpOutAct->DrawBitmap( pBmpDesc );
+ mpBitmapInUse.reset();
+ }
+ mpOutAct->EndFigure(); // close potential figures
+ mpOutAct->EndGrouping(); // finish potential groups
+ *pElement = *pCopyOfE;
+ mbFigure = mbFirstOutPut = mbPicture = mbPictureBody = false;
+ }
+ else
+ mbStatus = false;
+ }
+ break;
+ case 0x06 : /*Begin Segment*/
+ pElement->bSegmentCount = true;
+ break;
+ case 0x07 : /*End Segment*/
+ pElement->bSegmentCount = true;
+ break;
+ case 0x08 : /*Begin Figure*/
+ mbFigure = true;
+ mpOutAct->BeginFigure();
+ break;
+ case 0x09 : /*End Figure*/
+ mpOutAct->EndFigure();
+ mbFigure = false;
+ break;
+ case 0x0d : /*Begin Protection vcl::Region */break;
+ case 0x0e : /*End Protection vcl::Region */break;
+ case 0x0f : /*Begin Compound Line */break;
+ case 0x10 : /*End Compound Line */break;
+ case 0x11 : /*Begin Compound Text Path */break;
+ case 0x12 : /*End Compound Text Path */break;
+ case 0x13 : /*Begin Tile Array */break; // NS
+ case 0x14 : /*End Tile Array */break; // NS
+ case 0xff : /*Filter Setup */break;
+ case 0xfe : /*Begin Block Text vcl::Region */break;
+ case 0xfd : /*End Block Text vcl::Region */break;
+ case 0xfc : /*Begin Group*/
+ mpOutAct->BeginGroup();
+ break;
+ case 0xfb : /*End Group*/
+ mpOutAct->EndGroup();
+ break;
+ case 0xfa : /*Begin Patch */break;
+ case 0xf9 : /*Begin Patch */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class1.cxx b/filter/source/graphicfilter/icgm/class1.cxx
new file mode 100644
index 000000000..07a6fe253
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class1.cxx
@@ -0,0 +1,225 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <sal/log.hxx>
+
+#include <o3tl/safeint.hxx>
+
+#include "bundles.hxx"
+#include "cgm.hxx"
+#include "elements.hxx"
+
+
+void CGM::ImplDoClass1()
+{
+ tools::Long nInteger, nI0, nI1;
+ sal_uInt32 nUInteger;
+
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Metafile Version*/
+ pElement->nMetaFileVersion = ImplGetI( pElement->nIntegerPrecision );
+ break;
+ case 0x02 : /*Metafile Description */break;
+ case 0x03 : /*VDC Type*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eVDCType = VDC_INTEGER; break;
+ case 1 : pElement->eVDCType = VDC_REAL; break;
+ default: mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x04 : /*Integer Precision*/
+ {
+ nInteger = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nInteger )
+ {
+ case 32 :
+ case 24 :
+ case 16 :
+ case 8 : pElement->nIntegerPrecision = nInteger >> 3; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x05 : /*Real Precision*/
+ {
+ nUInteger = ImplGetUI16();
+ nI0 = ImplGetI( pElement->nIntegerPrecision ); // exponent
+ nI1 = ImplGetI( pElement->nIntegerPrecision ); // mantissa
+ switch( nUInteger )
+ {
+ case 0 :
+ pElement->eRealPrecision = RP_FLOAT;
+ switch ( nI0 )
+ {
+ case 9 :
+ if ( nI1 != 23 )
+ mbStatus = false;
+ pElement->nRealSize = 4;
+ break;
+ case 12 :
+ if ( nI1 != 52 )
+ mbStatus =false;
+ pElement->nRealSize = 8;
+ break;
+ default:
+ mbStatus = false;
+ break;
+ }
+ break;
+ case 1 :
+ pElement->eRealPrecision = RP_FIXED;
+ if ( nI0 != nI1 )
+ mbStatus = false;
+ if ( nI0 == 16 )
+ pElement->nRealSize = 4;
+ else if ( nI0 == 32 )
+ pElement->nRealSize = 8;
+ else
+ mbStatus = false;
+ break;
+ default :
+ mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x06 : /*Index Precision*/
+ {
+ nInteger = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nInteger )
+ {
+ case 32 :
+ case 24 :
+ case 16 :
+ case 8 : pElement->nIndexPrecision = nInteger >> 3; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x07 : /*Color Precision*/
+ {
+ nInteger = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nInteger )
+ {
+ case 32 :
+ case 24 :
+ case 16 :
+ case 8 : pElement->nColorPrecision = nInteger >> 3; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x08 : /*Color Index Precision*/
+ {
+ nInteger = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nInteger )
+ {
+ case 32 :
+ case 24 :
+ case 16 :
+ case 8 : pElement->nColorIndexPrecision = nInteger >> 3; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x09 : /*Maximum Colour Index*/
+ {
+ pElement->nColorMaximumIndex = ImplGetUI( pElement->nColorIndexPrecision );
+ if ( ( pElement->nColorMaximumIndex > 256 /*255*/ ) || ( pElement->nColorMaximumIndex == 0 ) )
+ mbStatus = false;
+ }
+ break;
+ case 0x0a : /*Color Value Extent*/
+ {
+ nI1 = 6;
+ }
+ break;
+ case 0x0b : /*MetaFile Element List */break;
+ case 0x0c : /*MetaFile Default Replacement*/
+ {
+ if ( mnElementSize > 1 )
+ {
+ std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8[ mnElementSize ]);
+ memcpy( pBuf.get(), mpSource, mnElementSize );
+ maDefRepList.push_back( std::move(pBuf) );
+ maDefRepSizeList.push_back( mnElementSize );
+ }
+ mnParaSize = mnElementSize;
+ }
+ break;
+ case 0x0d : /*Font List*/
+ {
+ while ( mnParaSize < mnElementSize )
+ {
+ sal_uInt32 nSize = ImplGetUI(1);
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ pElement->aFontList.InsertName( mpSource + mnParaSize, nSize );
+ mnParaSize += nSize;
+ }
+ }
+ break;
+ case 0x0e : /*Character Set List*/
+ {
+ while ( mnParaSize < mnElementSize )
+ {
+ ImplGetUI16(); // skip CharSetType
+ sal_uInt32 nSize = ImplGetUI(1);
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ pElement->aFontList.InsertCharSet( mpSource + mnParaSize, nSize );
+ mnParaSize += nSize;
+ }
+ }
+ break;
+ case 0x0f : /*Character Coding Announcer*/
+ {
+ auto nCharacterCoding = ImplGetUI16();
+ if (nCharacterCoding <= CCA_EXT_8)
+ pElement->eCharacterCodingA = static_cast<CharacterCodingA>(nCharacterCoding);
+ else
+ SAL_WARN("filter.icgm", "CharacterCoding " << nCharacterCoding << " requested, but legal max is " << CCA_EXT_8);
+ }
+ break;
+ case 0x10 : /*Name Precision */break; // NS
+ case 0x11 : /*Maximum VDC Extent */break; // NS
+ case 0x12 : /*Segment Priority Extent */break; // NS
+ case 0x13 : /*Color Model */break; // NS
+ case 0x14 : /*Color Calibration */break; // NS
+ case 0x15 : /*Font Properties */break; // NS
+ case 0x16 : /*Glyph Mapping */break; // NS
+ case 0x17 : /*Symbol Library List */break; // NS
+ case 0xfc : /*Inquire Function Support */break;
+ case 0xfa : /*End Metafile Defaults Replacement */break;
+ case 0xf8 : /*Set Color Value Desc Extent */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class2.cxx b/filter/source/graphicfilter/icgm/class2.cxx
new file mode 100644
index 000000000..8d410e475
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class2.cxx
@@ -0,0 +1,233 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "cgm.hxx"
+#include "bundles.hxx"
+#include "elements.hxx"
+
+
+void CGM::ImplDoClass2()
+{
+ sal_uInt32 nUInteger;
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Scaling Mode*/
+ {
+ if ( mnElementSize ) // HACK (NASA.CGM)
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eScalingMode = SM_ABSTRACT; break;
+ case 1 : pElement->eScalingMode = SM_METRIC; break;
+ default : mbStatus = false; break;
+ }
+ pElement->nScalingFactor = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ ImplSetMapMode();
+ }
+ }
+ break;
+ case 0x02 : /*Color Selection Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eColorSelectionMode = CSM_INDEXED; break;
+ case 1 : pElement->eColorSelectionMode = CSM_DIRECT; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x03 : /*Line Width Specification Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eLineWidthSpecMode = SM_ABSOLUTE; break;
+ case 1 : pElement->eLineWidthSpecMode = SM_SCALED; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x04 : /*Marker Size Specification Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eMarkerSizeSpecMode = SM_ABSOLUTE; break;
+ case 1 : pElement->eMarkerSizeSpecMode = SM_SCALED; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x05 : /*Edge Width Specification Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eEdgeWidthSpecMode = SM_ABSOLUTE; break;
+ case 1 : pElement->eEdgeWidthSpecMode = SM_SCALED; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x06 : /*VDC Extent*/
+ {
+ ImplGetRectangleNS( pElement->aVDCExtent );
+ ImplSetMapMode();
+ }
+ break;
+ case 0x07 : /*Background Color*/
+ pElement->nBackGroundColor = ImplGetBitmapColor( true );
+ break;
+ case 0x08 : /*Device Viewport*/
+ {
+ if ( pElement->eVDCType == VDC_INTEGER )
+ ImplGetRectangle( pElement->aDeviceViewPort );
+ ImplSetMapMode();
+ }
+ break;
+ case 0x09 : /*Device Viewport Specification Mode*/
+ {
+ nUInteger = ImplGetUI16();
+ switch( nUInteger )
+ {
+ case 0 : pElement->eDeviceViewPortMode = DVPM_FRACTION; break;
+ case 1 : pElement->eDeviceViewPortMode = DVPM_METRIC; break;
+ case 2 : pElement->eDeviceViewPortMode = DVPM_DEVICE; break;
+ default : mbStatus = false; break;
+ }
+ pElement->nDeviceViewPortScale = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ ImplSetMapMode();
+ }
+ break;
+ case 0x0a : /*Device Viewport Mapping*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eDeviceViewPortMap = DVPM_NOT_FORCED; break;
+ case 1 : pElement->eDeviceViewPortMap = DVPM_FORCED; break;
+ default : mbStatus = false; break;
+ }
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eDeviceViewPortMapH = DVPMH_LEFT; break;
+ case 1 : pElement->eDeviceViewPortMapH = DVPMH_CENTER; break;
+ case 2 : pElement->eDeviceViewPortMapH = CVPMH_RIGHT; break;
+ default : mbStatus = false; break;
+ }
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eDeviceViewPortMapV = DVPMV_BOTTOM; break;
+ case 1 : pElement->eDeviceViewPortMapV = DVPMV_CENTER; break;
+ case 2 : pElement->eDeviceViewPortMapV = DVPMV_TOP; break;
+ default : mbStatus = false; break;
+ }
+ ImplSetMapMode();
+ }
+ break;
+ case 0x0b : /*Line Representation*/
+ {
+ LineBundle aTempLineBundle;
+ aTempLineBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempLineBundle.eLineType = static_cast<LineType>(ImplGetI( pElement->nIndexPrecision ));
+ aTempLineBundle.nLineWidth = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempLineBundle.SetColor( ImplGetBitmapColor() );
+ const bool bUpdateLineBundle = aTempLineBundle.GetIndex() == pElement->pLineBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aLineList, aTempLineBundle );
+ if (bUpdateLineBundle)
+ pElement->pLineBundle = static_cast<LineBundle*>(CGMElements::GetBundleIndex(aTempLineBundle.GetIndex(), pElement->aLineList, pElement->aLineBundle));
+ }
+ break;
+ case 0x0c : /*Marker Representation*/
+ {
+ MarkerBundle aTempMarkerBundle;
+ aTempMarkerBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempMarkerBundle.eMarkerType = static_cast<MarkerType>(ImplGetI( pElement->nIndexPrecision ));
+ aTempMarkerBundle.nMarkerSize = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempMarkerBundle.SetColor( ImplGetBitmapColor() );
+ const bool bUpdateMarkerBundle = aTempMarkerBundle.GetIndex() == pElement->pMarkerBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aMarkerList, aTempMarkerBundle );
+ if (bUpdateMarkerBundle)
+ pElement->pMarkerBundle = static_cast<MarkerBundle*>(CGMElements::GetBundleIndex(aTempMarkerBundle.GetIndex(), pElement->aMarkerList, pElement->aMarkerBundle));
+ }
+ break;
+ case 0x0d : /*Text Representation*/
+ {
+ TextBundle aTempTextBundle;
+ aTempTextBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempTextBundle.nTextFontIndex = ImplGetI( pElement->nIndexPrecision );
+ aTempTextBundle.eTextPrecision = static_cast<TextPrecision>(ImplGetI( pElement->nIndexPrecision ));
+ aTempTextBundle.nCharacterSpacing = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempTextBundle.nCharacterExpansion = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempTextBundle.SetColor( ImplGetBitmapColor() );
+ const bool bUpdateTextBundle = aTempTextBundle.GetIndex() == pElement->pTextBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aTextList, aTempTextBundle );
+ if (bUpdateTextBundle)
+ pElement->pTextBundle = static_cast<TextBundle*>(CGMElements::GetBundleIndex(aTempTextBundle.GetIndex(), pElement->aTextList, pElement->aTextBundle));
+ }
+ break;
+ case 0x0e : /*Fill Representation*/
+ {
+ FillBundle aTempFillBundle;
+ aTempFillBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempFillBundle.eFillInteriorStyle = static_cast<FillInteriorStyle>(ImplGetI( pElement->nIndexPrecision ));
+ aTempFillBundle.SetColor( ImplGetBitmapColor() );
+ aTempFillBundle.nFillPatternIndex = ImplGetI( pElement->nIndexPrecision );
+ aTempFillBundle.nFillHatchIndex = ImplGetI( pElement->nIndexPrecision );
+ const bool bUpdateFillBundle = aTempFillBundle.GetIndex() == pElement->pFillBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aFillList, aTempFillBundle );
+ if (bUpdateFillBundle)
+ pElement->pFillBundle = static_cast<FillBundle*>(CGMElements::GetBundleIndex(aTempFillBundle.GetIndex(), pElement->aFillList, pElement->aFillBundle));
+ }
+ break;
+ case 0x0f : /*Edge Representation*/
+ {
+ EdgeBundle aTempEdgeBundle;
+ aTempEdgeBundle.SetIndex( ImplGetI( pElement->nIndexPrecision ) );
+ aTempEdgeBundle.eEdgeType = static_cast<EdgeType>(ImplGetI( pElement->nIndexPrecision ));
+ aTempEdgeBundle.nEdgeWidth = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ aTempEdgeBundle.SetColor( ImplGetBitmapColor() );
+ const bool bUpdateEdgeBundle = aTempEdgeBundle.GetIndex() == pElement->pEdgeBundle->GetIndex();
+ CGMElements::InsertBundle( pElement->aEdgeList, aTempEdgeBundle );
+ if (bUpdateEdgeBundle)
+ pElement->pEdgeBundle = static_cast<EdgeBundle*>(CGMElements::GetBundleIndex(aTempEdgeBundle.GetIndex(), pElement->aEdgeList, pElement->aEdgeBundle));
+ }
+ break;
+ case 0x10 : /*Interior Style Specification Mode */break; // NS
+ case 0x11 : /*Line and Edge Type Definition */break;
+ case 0x12 : /*Hatch Style Definition */break; // NS
+ case 0x13 : /*Geometric Pattern Definition */break; // NS
+ case 0xff : /*inquire VDC EXTENT */break;
+ case 0xfe : /*inquire Background Color */break;
+ case 0xfd : /*inquire Device Viewport */break;
+ case 0xfc : /*set Font Selection Mode */break;
+ case 0xfb : /*inquire Color Selection Mode */break;
+ case 0xfa : /*inquire Font Selection Mode */break;
+ case 0xf9 : /*set Char Height Spec Mode*/
+ {
+ ImplGetUI16(); // -Wall is this really needed?
+ }
+ break;
+ case 0xf8 : /*set Background Style */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class3.cxx b/filter/source/graphicfilter/icgm/class3.cxx
new file mode 100644
index 000000000..3cc25730f
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class3.cxx
@@ -0,0 +1,134 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "cgm.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+
+void CGM::ImplDoClass3()
+{
+ sal_uInt32 nUInteger;
+ switch ( mnElementID )
+ {
+ case 0x01 : /*VDC Integer Precision*/
+ {
+ switch( ImplGetI( pElement->nIntegerPrecision ) )
+ {
+ case 16 : pElement->nVDCIntegerPrecision = 2; break;
+ case 32 : pElement->nVDCIntegerPrecision = 4; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x02 : /*VDC Real Precision*/
+ {
+ nUInteger = ImplGetUI16();
+ const tools::Long nI0 = ImplGetI( pElement->nIntegerPrecision ); // exponent
+ const tools::Long nI1 = ImplGetI( pElement->nIntegerPrecision ); // mantissa
+ switch( nUInteger )
+ {
+ case 0 :
+ pElement->eVDCRealPrecision = RP_FLOAT;
+ switch ( nI0 )
+ {
+ case 9 :
+ if ( nI1 != 23 )
+ mbStatus = false;
+ pElement->nVDCRealSize = 4;
+ break;
+ case 12 :
+ if ( nI1 != 52 )
+ mbStatus =false;
+ pElement->nVDCRealSize = 8;
+ break;
+ default:
+ mbStatus = false;
+ break;
+ }
+ break;
+ case 1 :
+ pElement->eVDCRealPrecision = RP_FIXED;
+ if ( nI0 != nI1 )
+ mbStatus = false;
+ if ( nI0 == 16 )
+ pElement->nVDCRealSize = 4;
+ else if ( nI0 == 32 )
+ pElement->nVDCRealSize = 8;
+ else
+ mbStatus = false;
+ break;
+ default :
+ mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x03 : /*Auxiliary Colour*/
+ {
+ pElement->nAuxiliaryColor = ImplGetBitmapColor();
+ }
+ break;
+ case 0x04 : /*Transparency*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eTransparency = T_OFF; break;
+ case 1 : pElement->eTransparency = T_ON; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x05 : /*Clip Rectangle*/
+ ImplGetRectangle( pElement->aClipRect );
+ break;
+ case 0x06 : /*Clip Indicator*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eClipIndicator = CI_OFF; break;
+ case 1 : pElement->eClipIndicator = CI_ON; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x07 : /*Line Clipping Mode */break; // NS
+ case 0x08 : /*Marker Clipping Mode */break; // NS
+ case 0x09 : /*Edge Clipping Mode */break; // NS
+ case 0x0a : /*New Region*/
+ mpOutAct->NewRegion();
+ break;
+ case 0x0b : /*Save Primitive Context */break; // NS
+ case 0x0c : /*Restore Primitive Context */break; // NS
+ case 0x11 : /*Protection vcl::Region Indicator */break;
+ case 0x12 : /*Generalized Text Path Mode */break; // NS
+ case 0x13 : /*Mitre Limit*/
+ pElement->nMitreLimit = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ break; // NS
+ case 0x14 : /*Transparent Cell Color */break; // NS
+ case 0xfc : /*Text Path Alignment Modes */break;
+ case 0xfd : /*Pop Transformation Stack */break;
+ case 0xfe : /*Push Transformation Stack */break;
+ case 0xff : /*Set Patch ID */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class4.cxx b/filter/source/graphicfilter/icgm/class4.cxx
new file mode 100644
index 000000000..af66ff26a
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class4.cxx
@@ -0,0 +1,911 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "bitmap.hxx"
+#include "cgm.hxx"
+#include "chart.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+#include <o3tl/float_int_conversion.hxx>
+#include <o3tl/safeint.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+double CGM::ImplGetOrientation( FloatPoint const & rCenter, FloatPoint const & rPoint )
+{
+ double nX = rPoint.X - rCenter.X;
+ double nY = rPoint.Y - rCenter.Y;
+
+ double fSqrt = std::hypot(nX, nY);
+ double fOrientation = fSqrt != 0.0 ? basegfx::rad2deg(acos(nX / fSqrt)) : 0.0;
+ if (nY > 0)
+ fOrientation = 360 - fOrientation;
+
+ return fOrientation;
+}
+
+
+void CGM::ImplSwitchStartEndAngle( double& rStartAngle, double& rEndAngle )
+{
+ double nTemp;
+ nTemp = rStartAngle;
+ rStartAngle = rEndAngle;
+ rEndAngle = nTemp;
+}
+
+
+void CGM::ImplGetVector( double* pVector )
+{
+ if ( pElement->eVDCType == VDC_REAL )
+ {
+ for ( sal_uInt32 i = 0; i < 4; i++ )
+ {
+ pVector[ i ] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ }
+ else
+ {
+ for ( sal_uInt32 i = 0; i < 4; i++ )
+ {
+ pVector[ i ] = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ }
+ }
+ pVector[ 0 ] *= mnVDCXmul;
+ pVector[ 2 ] *= mnVDCXmul;
+ pVector[ 1 ] *= mnVDCYmul;
+ pVector[ 3 ] *= mnVDCYmul;
+}
+
+
+bool CGM::ImplGetEllipse( FloatPoint& rCenter, FloatPoint& rRadius, double& rAngle )
+{
+ FloatPoint aPoint1, aPoint2;
+ double fRot1, fRot2;
+ ImplGetPoint( rCenter, true );
+ ImplGetPoint( aPoint1, true );
+ ImplGetPoint( aPoint2, true );
+ fRot1 = ImplGetOrientation( rCenter, aPoint1 );
+ fRot2 = ImplGetOrientation( rCenter, aPoint2 );
+ rAngle = ImplGetOrientation( rCenter, aPoint1 );
+ aPoint1.X -= rCenter.X;
+ aPoint1.Y -= rCenter.Y;
+ rRadius.X = std::hypot(aPoint1.X, aPoint1.Y);
+ aPoint2.X -= rCenter.X;
+ aPoint2.Y -= rCenter.Y;
+ rRadius.Y = std::hypot(aPoint2.X, aPoint2.Y);
+
+ if ( fRot1 > fRot2 )
+ {
+ if ( ( fRot1 - fRot2 ) < 180 )
+ return false;
+ }
+ else
+ {
+ if ( ( fRot2 - fRot1 ) > 180 )
+ return false;
+ }
+ return true;
+}
+
+void CGM::ImplDoClass4()
+{
+ if ( mbFirstOutPut )
+ mpOutAct->FirstOutPut();
+
+ if ( mpBitmapInUse && ( mnElementID != 9 ) ) // process existed graphic
+ { // because there are now no pending bitmap actions
+ CGMBitmapDescriptor* pBmpDesc = mpBitmapInUse->GetBitmap();
+ // do anything with the bitmap
+ mpOutAct->DrawBitmap( pBmpDesc );
+ mpBitmapInUse.reset();
+ }
+
+ if ( ( mpChart == nullptr ) || mpChart->IsAnnotation() )
+ {
+ switch ( mnElementID )
+ {
+ case 0x01 : /*PolyLine*/
+ {
+ sal_uInt32 nPoints = mnElementSize / ImplGetPointSize();
+ tools::Polygon aPolygon( static_cast<sal_uInt16>(nPoints) );
+ for ( sal_uInt32 i = 0; i < nPoints; i++)
+ {
+ FloatPoint aFloatPoint;
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), i );
+ }
+ if ( mbFigure )
+ mpOutAct->RegPolyLine( aPolygon );
+ else
+ mpOutAct->DrawPolyLine( aPolygon );
+ }
+ break;
+
+ case 0x02 : /*Disjoint PolyLine*/
+ {
+ sal_uInt16 nPoints = sal::static_int_cast< sal_uInt16 >(
+ mnElementSize / ImplGetPointSize());
+ if ( ! ( nPoints & 1 ) )
+ {
+ nPoints >>= 1;
+ FloatPoint aFloatPoint;
+ if ( mbFigure )
+ {
+ tools::Polygon aPolygon( nPoints );
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 0 );
+ }
+ mpOutAct->RegPolyLine( aPolygon );
+ }
+ else
+ {
+ mpOutAct->BeginGroup();
+ tools::Polygon aPolygon( sal_uInt16(2) );
+ for ( sal_uInt16 i = 0; i < nPoints; i++ )
+ {
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 0 );
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) ), 1);
+ mpOutAct->DrawPolyLine( aPolygon );
+ }
+ mpOutAct->EndGroup();
+ }
+ }
+ }
+ break;
+
+ case 0x03 : /*PolyMarker*/ break;
+ case 0x04 : /*Text*/
+ {
+ FloatPoint aFloatPoint;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ ImplGetPoint ( aFloatPoint, true );
+ sal_uInt32 nType = ImplGetUI16();
+ sal_uInt32 nSize = ImplGetUI( 1 );
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ OUString aStr(reinterpret_cast<char*>(mpSource) + mnParaSize, nSize, RTL_TEXTENCODING_ASCII_US);
+
+ awt::Size aSize;
+ awt::Point aPoint( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) );
+ mpOutAct->DrawText(aPoint, aSize, aStr, static_cast<FinalFlag>(nType));
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x05 : /*Restricted Text*/
+ {
+ double dx, dy;
+ FloatPoint aFloatPoint;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ if ( pElement->eVDCType == VDC_REAL )
+ {
+ dx = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ dy = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ else
+ {
+ dx = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ dy = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ }
+ ImplMapDouble( dx );
+ ImplMapDouble( dy );
+
+ ImplGetPoint ( aFloatPoint, true );
+ sal_uInt32 nType = ImplGetUI16();
+ sal_uInt32 nSize = ImplGetUI(1);
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) < nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ OUString aStr(reinterpret_cast<char*>(mpSource) + mnParaSize, nSize, RTL_TEXTENCODING_ASCII_US);
+
+ awt::Point aPoint( static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y) );
+ awt::Size aSize(static_cast<tools::Long>(dx), static_cast<tools::Long>(dy));
+ mpOutAct->DrawText(aPoint, aSize , aStr, static_cast<FinalFlag>(nType));
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x06 : /*Append Text*/
+ {
+ (void)ImplGetUI16(); // nType
+ sal_uInt32 nSize = ImplGetUI( 1 );
+
+ if (o3tl::make_unsigned(mpEndValidSource - (mpSource + mnParaSize)) <= nSize)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ mpSource[ mnParaSize + nSize ] = 0;
+
+ mpOutAct->AppendText( reinterpret_cast<char*>(mpSource) + mnParaSize );
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x07 : /*Polygon*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ sal_uInt16 nPoints = sal::static_int_cast< sal_uInt16 >(
+ mnElementSize / ImplGetPointSize());
+ tools::Polygon aPolygon( nPoints );
+ for ( sal_uInt16 i = 0; i < nPoints; i++)
+ {
+ FloatPoint aFloatPoint;
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point ( static_cast<tools::Long>( aFloatPoint.X ), static_cast<tools::Long>( aFloatPoint.Y ) ), i );
+ }
+ mpOutAct->DrawPolygon( aPolygon );
+ }
+ break;
+
+ case 0x08 : /*Polygon Set*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ std::vector<Point> aPoints;
+ tools::PolyPolygon aPolyPolygon;
+ FloatPoint aFloatPoint;
+
+ while ( mnParaSize < mnElementSize )
+ {
+ ImplGetPoint( aFloatPoint, true );
+ sal_uInt32 nEdgeFlag = ImplGetUI16();
+ aPoints.push_back(Point(static_cast<tools::Long>(aFloatPoint.X), static_cast<tools::Long>(aFloatPoint.Y)));
+ if ( ( nEdgeFlag & 2 ) || ( mnParaSize == mnElementSize ) )
+ {
+ aPolyPolygon.Insert(tools::Polygon(aPoints.size(), aPoints.data()));
+ aPoints.clear();
+ }
+ }
+ mpOutAct->DrawPolyPolygon( aPolyPolygon );
+ }
+ break;
+
+ case 0x09 : /*Cell Array*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ if ( mpBitmapInUse )
+ {
+ std::unique_ptr<CGMBitmap> xBmpDesc(mpBitmapInUse->GetNext());
+ if (xBmpDesc) // we possibly get a bitmap back which does not fit to
+ { // to the previous -> we need to delete this one too
+ mpOutAct->DrawBitmap(xBmpDesc->GetBitmap());
+ }
+ }
+ else
+ {
+ mpBitmapInUse.reset( new CGMBitmap( *this ) );
+ }
+ }
+ break;
+
+ case 0x0a : /*Generalized Drawing Primitive*/
+ {
+ ImplGetI( pElement->nIntegerPrecision ); //-Wall is this needed
+ ImplGetUI( pElement->nIntegerPrecision ); //-Wall is this needed
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x0b : /*Rectangle*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ FloatRect aFloatRect;
+ ImplGetRectangle( aFloatRect, true );
+ mpOutAct->DrawRectangle( aFloatRect );
+ }
+ break;
+
+ case 0x0c : /*Circle*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ double fRotation = 0;
+ FloatPoint aCenter, aRadius;
+ ImplGetPoint( aCenter, true );
+ if ( pElement->eVDCType == VDC_REAL )
+ aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ else
+ aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ ImplMapDouble( aRadius.X );
+ aRadius.Y = aRadius.X;
+ mpOutAct->DrawEllipse( aCenter, aRadius, fRotation );
+ }
+ break;
+
+ case 0x0d : /*Circular Arc 3 Point*/
+ {
+ FloatPoint aStartingPoint, aIntermediatePoint, aEndingPoint;
+ ImplGetPoint( aStartingPoint, true );
+ ImplGetPoint( aIntermediatePoint, true );
+ ImplGetPoint( aEndingPoint, true );
+
+ double fA = aIntermediatePoint.X - aStartingPoint.X;
+ double fB = aIntermediatePoint.Y - aStartingPoint.Y;
+ double fC = aEndingPoint.X - aStartingPoint.X;
+ double fD = aEndingPoint.Y - aStartingPoint.Y;
+
+ double fE = fA * ( aStartingPoint.X + aIntermediatePoint.X ) + fB * ( aStartingPoint.Y + aIntermediatePoint.Y );
+ double fF = fC * ( aStartingPoint.X + aEndingPoint.X ) + fD * ( aStartingPoint.Y + aEndingPoint.Y );
+
+ double fG = 2.0 * ( fA * ( aEndingPoint.Y - aIntermediatePoint.Y ) - fB * ( aEndingPoint.X - aIntermediatePoint.X ) );
+
+ bool bUseless = fG == 0;
+
+ FloatPoint aCenterPoint;
+ if (!bUseless)
+ {
+ aCenterPoint.X = ( fD * fE - fB * fF ) / fG;
+ aCenterPoint.Y = ( fA * fF - fC * fE ) / fG;
+ bUseless = useless(aCenterPoint.X) || useless(aCenterPoint.Y);
+ }
+
+ if (!bUseless)
+ bUseless = useless(aStartingPoint.X) || useless(aStartingPoint.Y);
+
+ if (!bUseless)
+ {
+ double fStartAngle = ImplGetOrientation( aCenterPoint, aStartingPoint );
+ double fInterAngle = ImplGetOrientation( aCenterPoint, aIntermediatePoint );
+ double fEndAngle = ImplGetOrientation( aCenterPoint, aEndingPoint );
+
+ int nSwitch = 0;
+
+ if ( fStartAngle > fEndAngle )
+ {
+ nSwitch ^=1;
+ aIntermediatePoint = aEndingPoint;
+ aEndingPoint = aStartingPoint;
+ aStartingPoint = aIntermediatePoint;
+ fG = fStartAngle;
+ fStartAngle = fEndAngle;
+ fEndAngle = fG;
+ }
+ if ( ! ( fInterAngle > fStartAngle ) && ( fInterAngle < fEndAngle ) )
+ {
+ nSwitch ^=1;
+ aIntermediatePoint = aEndingPoint;
+ aEndingPoint = aStartingPoint;
+ aStartingPoint = aIntermediatePoint;
+ fG = fStartAngle;
+ fStartAngle = fEndAngle;
+ fEndAngle = fG;
+ }
+ double fRadius = std::hypot(aStartingPoint.X - aCenterPoint.X, aStartingPoint.Y - aCenterPoint.Y);
+
+ if ( mbFigure )
+ {
+ double fLeft = aCenterPoint.X - fRadius;
+ double fTop = aCenterPoint.Y - fRadius;
+ double fRight = fLeft + (2 * fRadius);
+ double fBottom = fTop + (2 * fRadius);
+ bUseless = useless(fLeft) || useless(fTop) || useless(2 * fRadius) || useless(fRight) || useless(fBottom);
+ if (!bUseless)
+ {
+ double fCenterCalc = fLeft + fRight;
+ bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
+ !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
+ }
+ if (!bUseless)
+ {
+ double fCenterCalc = fTop + fBottom;
+ bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
+ !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
+ }
+ if (!bUseless)
+ {
+ tools::Rectangle aBoundingBox(Point(fLeft, fTop), Size(2 * fRadius, 2 * fRadius));
+ tools::Polygon aPolygon( aBoundingBox, Point( static_cast<tools::Long>(aStartingPoint.X), static_cast<tools::Long>(aStartingPoint.Y) ) ,Point( static_cast<tools::Long>(aEndingPoint.X), static_cast<tools::Long>(aEndingPoint.Y) ), PolyStyle::Arc );
+ if ( nSwitch )
+ mpOutAct->RegPolyLine( aPolygon, true );
+ else
+ mpOutAct->RegPolyLine( aPolygon );
+ }
+ }
+ else
+ {
+ fG = 0;
+ FloatPoint aRadius;
+ aRadius.X = aRadius.Y = fRadius;
+ mpOutAct->DrawEllipticalArc( aCenterPoint, aRadius, fG, 2, fStartAngle, fEndAngle );
+ }
+ }
+ }
+ break;
+
+ case 0x0e : /*Circular Arc 3 Point Close*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ FloatPoint aStartingPoint, aIntermediatePoint, aEndingPoint;
+ ImplGetPoint( aStartingPoint );
+ ImplGetPoint( aIntermediatePoint );
+ ImplGetPoint( aEndingPoint );
+
+ double fA = aIntermediatePoint.X - aStartingPoint.X;
+ double fB = aIntermediatePoint.Y - aStartingPoint.Y;
+ double fC = aEndingPoint.X - aStartingPoint.X;
+ double fD = aEndingPoint.Y - aStartingPoint.Y;
+
+ double fE = fA * ( aStartingPoint.X + aIntermediatePoint.X ) + fB * ( aStartingPoint.Y + aIntermediatePoint.Y );
+ double fF = fC * ( aStartingPoint.X + aEndingPoint.X ) + fD * ( aStartingPoint.Y + aEndingPoint.Y );
+
+ double fG = 2.0 * ( fA * ( aEndingPoint.Y - aIntermediatePoint.Y ) - fB * ( aEndingPoint.X - aIntermediatePoint.X ) );
+
+ if ( fG != 0 )
+ {
+ FloatPoint aCenterPoint;
+ aCenterPoint.X = ( fD * fE - fB * fF ) / fG;
+ aCenterPoint.Y = ( fA * fF - fC * fE ) / fG;
+ double fStartAngle = ImplGetOrientation( aCenterPoint, aStartingPoint );
+ double fInterAngle = ImplGetOrientation( aCenterPoint, aIntermediatePoint );
+ double fEndAngle = ImplGetOrientation( aCenterPoint, aEndingPoint );
+
+ if ( fStartAngle > fEndAngle )
+ {
+ aIntermediatePoint = aEndingPoint;
+ aEndingPoint = aStartingPoint;
+ aStartingPoint = aIntermediatePoint;
+ fG = fStartAngle;
+ fStartAngle = fEndAngle;
+ fEndAngle = fG;
+ }
+ if ( ! ( fInterAngle > fStartAngle ) && ( fInterAngle < fEndAngle ) )
+ {
+ aIntermediatePoint = aEndingPoint;
+ aEndingPoint = aStartingPoint;
+ aStartingPoint = aIntermediatePoint;
+ fG = fStartAngle;
+ fStartAngle = fEndAngle;
+ fEndAngle = fG;
+ }
+ FloatPoint fRadius;
+ fRadius.Y = fRadius.X = std::hypot(aStartingPoint.X - aCenterPoint.X, aStartingPoint.Y - aCenterPoint.Y);
+
+ sal_uInt32 nType = ImplGetUI16();
+ if ( nType == 0 )
+ nType = 0; // is PIE
+ else
+ nType = 1; // is CHORD
+
+ double fOrientation = 0;
+ mpOutAct->DrawEllipticalArc( aCenterPoint, fRadius, fOrientation, nType, fStartAngle, fEndAngle );
+ }
+ }
+ break;
+
+ case 0x0f : /*Circular Arc Centre*/
+ {
+ double fStartAngle, fEndAngle, vector[ 4 ];
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ ImplGetPoint( aCenter, true );
+ ImplGetVector( &vector[ 0 ] );
+
+ if ( pElement->eVDCType == VDC_REAL )
+ {
+ aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ else
+ {
+ aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ }
+
+ ImplMapDouble( aRadius.X );
+ aRadius.Y = aRadius.X;
+
+ bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
+ if (!bUseless)
+ {
+ const double fStartSqrt = std::hypot(vector[0], vector[1]);
+ fStartAngle = fStartSqrt != 0.0 ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
+ const double fEndSqrt = std::hypot(vector[2], vector[3]);
+ fEndAngle = fEndSqrt != 0.0 ? basegfx::rad2deg(acos(vector[ 2 ] / fEndSqrt)) : 0.0;
+
+ if ( vector[ 1 ] > 0 )
+ fStartAngle = 360 - fStartAngle;
+ if ( vector[ 3 ] > 0 )
+ fEndAngle = 360 - fEndAngle;
+
+ if ( mbAngReverse )
+ ImplSwitchStartEndAngle( fStartAngle, fEndAngle );
+
+ if ( mbFigure )
+ {
+ double fLeft = aCenter.X - aRadius.X;
+ double fTop = aCenter.Y - aRadius.X;
+ double fRight = fLeft + (2 * aRadius.X);
+ double fBottom = fTop + (2 * aRadius.X);
+ bUseless = useless(fLeft) || useless(fTop) || useless(2 * aRadius.X) || useless(fRight) || useless(fBottom);
+ if (!bUseless)
+ {
+ double fCenterCalc = fLeft + fRight;
+ bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
+ !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
+ }
+ if (!bUseless)
+ {
+ double fCenterCalc = fTop + fBottom;
+ bUseless = !o3tl::convertsToAtLeast(fCenterCalc, std::numeric_limits<tools::Long>::min()) ||
+ !o3tl::convertsToAtMost(fCenterCalc, std::numeric_limits<tools::Long>::max());
+ }
+ if (!bUseless)
+ {
+ tools::Rectangle aBoundingBox(Point(fLeft, fTop), Size(2 * aRadius.X, 2 * aRadius.X));
+ tools::Polygon aPolygon( aBoundingBox,
+ Point( static_cast<tools::Long>(vector[ 0 ]), static_cast<tools::Long>(vector[ 1 ]) ),
+ Point( static_cast<tools::Long>(vector[ 2 ]), static_cast<tools::Long>(vector[ 3 ]) ), PolyStyle::Arc );
+ mpOutAct->RegPolyLine( aPolygon );
+ }
+ }
+ else
+ {
+ double fOrientation = 0;
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation, 2, fStartAngle, fEndAngle );
+ }
+ }
+
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x10 : /*Circular Arc Centre Close*/
+ {
+ double fOrientation, vector[ 4 ];
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ ImplGetPoint( aCenter, true );
+ ImplGetVector( &vector[ 0 ] );
+ if ( pElement->eVDCType == VDC_REAL )
+ {
+ aRadius.X = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ else
+ {
+ aRadius.X = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ }
+ ImplMapDouble( aRadius.X );
+ aRadius.Y = aRadius.X;
+
+ sal_uInt32 nType = ImplGetUI16();
+
+ bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
+ if (!bUseless)
+ {
+ const double fStartSqrt = std::hypot(vector[0], vector[1]);
+ double fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
+ const double fEndSqrt = std::hypot(vector[2], vector[3]);
+ double fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
+
+ if ( vector[ 1 ] > 0 )
+ fStartAngle = 360 - fStartAngle;
+ if ( vector[ 3 ] > 0 )
+ fEndAngle = 360 - fEndAngle;
+
+ if ( mbAngReverse )
+ ImplSwitchStartEndAngle( fStartAngle, fEndAngle );
+
+ if ( nType == 0 )
+ nType = 0; // is PIE
+ else
+ nType = 1; // is CHORD
+ fOrientation = 0;
+
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ nType, fStartAngle, fEndAngle );
+ }
+
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x11 : /*Ellipse*/
+ {
+ double fOrientation;
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ ImplGetEllipse( aCenter, aRadius, fOrientation ) ;
+ mpOutAct->DrawEllipse( aCenter, aRadius, fOrientation ) ;
+ }
+ break;
+
+ case 0x12 : /*Elliptical Arc*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ double fOrientation, fStartAngle, fEndAngle, vector[ 4 ];
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ bool bDirection = ImplGetEllipse( aCenter, aRadius, fOrientation );
+ ImplGetVector( &vector[ 0 ] );
+
+ bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
+ if (!bUseless)
+ {
+ double fStartSqrt = std::hypot(vector[0], vector[1]);
+ fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
+ double fEndSqrt = std::hypot(vector[2], vector[3]);
+ fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
+
+ if ( vector[ 1 ] > 0 )
+ fStartAngle = 360 - fStartAngle;
+ if ( vector[ 3 ] > 0 )
+ fEndAngle = 360 - fEndAngle;
+
+ if ( bDirection )
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ 2, fStartAngle, fEndAngle );
+ else
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ 2, fEndAngle, fStartAngle);
+ }
+ }
+ break;
+
+ case 0x13 : /*Elliptical Arc Close*/
+ {
+ double fOrientation, fStartAngle, fEndAngle, vector[ 4 ];
+ FloatPoint aCenter, aRadius;
+
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+
+ bool bDirection = ImplGetEllipse( aCenter, aRadius, fOrientation );
+ ImplGetVector( &vector[ 0 ] );
+
+ sal_uInt32 nType = ImplGetUI16();
+
+ bool bUseless = useless(vector[0]) || useless(vector[1]) || useless(vector[2]) || useless(vector[3]);
+ if (!bUseless)
+ {
+ double fStartSqrt = std::hypot(vector[0], vector[1]);
+ fStartAngle = fStartSqrt ? basegfx::rad2deg(acos(vector[0] / fStartSqrt)) : 0.0;
+ double fEndSqrt = std::hypot(vector[2], vector[3]);
+ fEndAngle = fEndSqrt ? basegfx::rad2deg(acos(vector[2] / fEndSqrt)) : 0.0;
+
+ if ( vector[ 1 ] > 0 )
+ fStartAngle = 360 - fStartAngle;
+ if ( vector[ 3 ] > 0 )
+ fEndAngle = 360 - fEndAngle;
+
+ if ( nType == 0 )
+ nType = 0; // is PIE
+ else
+ nType = 1; // is CHORD
+
+ if ( bDirection )
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ nType, fStartAngle, fEndAngle );
+ else
+ mpOutAct->DrawEllipticalArc( aCenter, aRadius, fOrientation,
+ nType, fEndAngle, fStartAngle);
+ }
+ }
+ break;
+ case 0x14 : /*Circular Arc Centre Reversed*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x15 : /*Connection Edge */ // NS
+ {
+// if ( mbFigure )
+// mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x16 : /*Hyperbolic Arc */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x17 : /*Parabolic Arc */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x18 : /*Non Uniform B-Spline */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x19 : /*Non Uniform Rational B-Spline */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x1a : /*Polybezier*/
+ {
+ sal_uInt32 nOrder = ImplGetI( pElement->nIntegerPrecision );
+
+ sal_uInt16 nNumberOfPoints = sal::static_int_cast< sal_uInt16 >(( mnElementSize - pElement->nIntegerPrecision ) / ImplGetPointSize());
+
+ tools::Polygon aPolygon( nNumberOfPoints );
+
+ for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++)
+ {
+ FloatPoint aFloatPoint;
+ ImplGetPoint( aFloatPoint, true );
+ aPolygon.SetPoint( Point ( static_cast<tools::Long>( aFloatPoint.X ), static_cast<tools::Long>( aFloatPoint.Y ) ), i );
+ }
+ if ( nOrder & 4 )
+ {
+ for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++ )
+ {
+ if ( ( i % 3 ) == 0 )
+ aPolygon.SetFlags( i, PolyFlags::Normal );
+ else
+ aPolygon.SetFlags( i, PolyFlags::Control );
+ }
+ }
+ else
+ {
+ for ( sal_uInt16 i = 0; i < nNumberOfPoints; i++ )
+ {
+ switch ( i & 3 )
+ {
+ case 0 :
+ case 3 : aPolygon.SetFlags( i, PolyFlags::Normal ); break;
+ default : aPolygon.SetFlags( i, PolyFlags::Control ); break;
+ }
+ }
+ }
+ if ( mbFigure )
+ mpOutAct->RegPolyLine( aPolygon );
+ else
+ mpOutAct->DrawPolybezier( aPolygon );
+ mnParaSize = mnElementSize;
+ }
+ break;
+
+ case 0x1b : /*Polysymbol */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x1c : /*Bitonal Tile */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x1d : /*Tile */ // NS
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0x1e : /*Insert Object*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xff : /*Polybezier*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfe : /*Sharp Polybezier*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfd : /*Polyspline*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfc : /*Rounded Rectangle*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfb : /*Begin Cell Array*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xfa : /*End Cell Array*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf9 : /*Insert File*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf8 : /*Block Text*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf7 : /*Variable Width Polyline*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf6 : /*Elliptical Arc 3 Point*/
+ {
+ if ( mbFigure )
+ mpOutAct->CloseRegion();
+ }
+ break;
+ case 0xf1 : /*Hyperlink Definition */break;
+ default: break;
+ }
+ }
+ else
+ mnParaSize = mnElementSize;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class5.cxx b/filter/source/graphicfilter/icgm/class5.cxx
new file mode 100644
index 000000000..7cfd9911c
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class5.cxx
@@ -0,0 +1,532 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+//#define VCL_NEED_BASETSD
+
+#include <sal/log.hxx>
+#include "cgm.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+void CGM::ImplDoClass5()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Line Bundle Index*/
+ pElement->pLineBundle = static_cast<LineBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aLineList, pElement->aLineBundle ));
+ break;
+ case 0x02 : /*Line Type*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_LINETYPE )
+ pElement->pLineBundle->eLineType = static_cast<LineType>(ImplGetI( pElement->nIndexPrecision ));
+ else
+ pElement->aLineBundle.eLineType = static_cast<LineType>(ImplGetI( pElement->nIndexPrecision ));
+ }
+ break;
+ case 0x03 : /*Line Width*/
+ {
+ double nWidth;
+ if ( pElement->eLineWidthSpecMode == SM_ABSOLUTE )
+ {
+ if ( pElement->eVDCType == VDC_REAL )
+ nWidth = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ else
+ nWidth = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+
+ ImplMapDouble( nWidth );
+ }
+ else
+ nWidth = static_cast<sal_uInt32>(ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize )) * 25; // scaling in 1/4 mm
+
+ if ( pElement->nAspectSourceFlags & ASF_LINEWIDTH )
+ pElement->pLineBundle->nLineWidth = nWidth;
+ else
+ pElement->aLineBundle.nLineWidth = nWidth;
+ }
+ break;
+ case 0x04 : /*Line Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_LINECOLOR )
+ pElement->pLineBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aLineBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x05 : /*Marker Bundle Index*/
+ pElement->pMarkerBundle = static_cast<MarkerBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aMarkerList, pElement->aMarkerBundle ));
+ break;
+ case 0x06 : /*Marker Type*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_MARKERTYPE )
+ pElement->pMarkerBundle->eMarkerType = static_cast<MarkerType>(ImplGetI( pElement->nIndexPrecision ));
+ else
+ pElement->aMarkerBundle.eMarkerType = static_cast<MarkerType>(ImplGetI( pElement->nIndexPrecision ));
+ }
+ break;
+ case 0x07 : /*Marker Size*/
+ {
+ double nWidth;
+ if ( pElement->eMarkerSizeSpecMode == SM_ABSOLUTE )
+ {
+ if ( pElement->eVDCType == VDC_REAL )
+ nWidth = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ else
+ nWidth = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+ ImplMapDouble( nWidth );
+ }
+ else
+ nWidth = static_cast<sal_uInt32>(ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize )) * 25;
+ if ( pElement->nAspectSourceFlags & ASF_MARKERSIZE )
+ pElement->pMarkerBundle->nMarkerSize = nWidth;
+ else
+ pElement->aMarkerBundle.nMarkerSize = nWidth;
+ }
+ break;
+ case 0x08 : /*Marker Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_MARKERCOLOR )
+ pElement->pMarkerBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aMarkerBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x09 : /*Text Bundle Index*/
+ pElement->pTextBundle = static_cast<TextBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aTextList, pElement->aTextBundle ));
+ break;
+ case 0x0a : /*Text Font Index*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_TEXTFONTINDEX )
+ pElement->pTextBundle->nTextFontIndex = ImplGetI( pElement->nIndexPrecision );
+ else
+ pElement->aTextBundle.nTextFontIndex = ImplGetI( pElement->nIndexPrecision );
+ }
+ break;
+ case 0x0b : /*Text Precision*/
+ {
+ TextBundle* pBundle;
+ if ( pElement->nAspectSourceFlags & ASF_TEXTPRECISION )
+ pBundle = pElement->pTextBundle;
+ else
+ pBundle = &pElement->aTextBundle;
+ switch( ImplGetUI16() )
+ {
+ case 0 : pBundle->eTextPrecision = TPR_STRING; break;
+ case 1 : pBundle->eTextPrecision = TPR_CHARACTER; break;
+ case 2 : pBundle->eTextPrecision = TPR_STROKE; break;
+ default : pBundle->eTextPrecision = TPR_UNDEFINED; break;
+ }
+ }
+ break;
+ case 0x0c : /*Character Expansion Factor*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_CHARACTEREXPANSION )
+ pElement->pTextBundle->nCharacterExpansion = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ else
+ pElement->aTextBundle.nCharacterExpansion = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ }
+ break;
+ case 0x0d : /*Character Spacing*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_CHARACTERSPACING )
+ pElement->pTextBundle->nCharacterSpacing = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ else
+ pElement->aTextBundle.nCharacterSpacing = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ }
+ break;
+ case 0x0e : /*Text Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_TEXTCOLOR )
+ pElement->pTextBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aTextBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x0f : /*Character Height*/
+ {
+ if ( pElement->eVDCType == VDC_INTEGER )
+ pElement->nCharacterHeight = ImplGetI( pElement->nVDCIntegerPrecision );
+ else // ->floating points
+ pElement->nCharacterHeight = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ ImplMapDouble( pElement->nCharacterHeight );
+ pElement->nCharacterHeight /= 18.0;
+ }
+ break;
+ case 0x10 : /*Character Orientation*/
+ {
+ if ( pElement->eVDCType == VDC_INTEGER )
+ {
+ pElement->nCharacterOrientation[0] = ImplGetI( pElement->nVDCIntegerPrecision );
+ pElement->nCharacterOrientation[1] = ImplGetI( pElement->nVDCIntegerPrecision );
+ pElement->nCharacterOrientation[2] = ImplGetI( pElement->nVDCIntegerPrecision );
+ pElement->nCharacterOrientation[3] = ImplGetI( pElement->nVDCIntegerPrecision );
+ }
+ else // ->floating points
+ {
+ pElement->nCharacterOrientation[0] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ pElement->nCharacterOrientation[1] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ pElement->nCharacterOrientation[2] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ pElement->nCharacterOrientation[3] = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ }
+ }
+ break;
+ case 0x11 : /*Text Path*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eTextPath = TPR_RIGHT; break;
+ case 1 : pElement->eTextPath = TPR_LEFT; break;
+ case 2 : pElement->eTextPath = TPR_UP; break;
+ case 3 : pElement->eTextPath = TPR_DOWN; break;
+ default : mbStatus = false; break;
+ }
+ }
+ break;
+ case 0x12 : /*Text Alignment*/
+ {
+ auto nTextAlign = ImplGetUI16();
+ if (nTextAlign > TextAlignmentH::TAH_CONT)
+ SAL_WARN("filter.icgm", "TextAlign out of range");
+ else
+ pElement->eTextAlignmentH = static_cast<TextAlignmentH>(nTextAlign);
+ nTextAlign = ImplGetUI16();
+ if (nTextAlign > TextAlignmentV::TAV_CONT)
+ SAL_WARN("filter.icgm", "TextAlign out of range");
+ else
+ pElement->eTextAlignmentV = static_cast<TextAlignmentV>(nTextAlign);
+ pElement->nTextAlignmentHCont = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ pElement->nTextAlignmentVCont = ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize );
+ }
+ break;
+ case 0x13 : /*Character Set Index*/
+ pElement->nCharacterSetIndex = ImplGetI( pElement->nIndexPrecision );
+ break;
+ case 0x14 : /*Alternate Character Set Index*/
+ pElement->nAlternateCharacterSetIndex = ImplGetI( pElement->nIndexPrecision );
+ break;
+ case 0x15 : /*Fill Bundle Index*/
+ pElement->pFillBundle = static_cast<FillBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aFillList, pElement->aFillBundle ));
+ break;
+ case 0x16 : /*Fill Interior Style*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_FILLINTERIORSTYLE )
+ pElement->pFillBundle->eFillInteriorStyle = static_cast<FillInteriorStyle>(ImplGetUI16());
+ else
+ pElement->aFillBundle.eFillInteriorStyle = static_cast<FillInteriorStyle>(ImplGetUI16());
+ }
+ break;
+ case 0x17 : /*Fill Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_FILLCOLOR )
+ pElement->pFillBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aFillBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x18 : /*Fill Hatch Index*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_HATCHINDEX )
+ pElement->pFillBundle->nFillHatchIndex = ImplGetI( pElement->nIndexPrecision );
+ else
+ pElement->aFillBundle.nFillHatchIndex = ImplGetI( pElement->nIndexPrecision );
+ }
+ break;
+ case 0x19 : /*Fill Pattern Index*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_PATTERNINDEX )
+ pElement->pFillBundle->nFillPatternIndex = ImplGetI( pElement->nIndexPrecision );
+ else
+ pElement->aFillBundle.nFillPatternIndex = ImplGetI( pElement->nIndexPrecision );
+ }
+ break;
+ case 0x1a : /*Edge Bundle Index*/
+ pElement->pEdgeBundle = static_cast<EdgeBundle*>(CGMElements::GetBundleIndex( ImplGetI( pElement->nIndexPrecision ), pElement->aEdgeList, pElement->aEdgeBundle ));
+ break;
+ case 0x1b : /*Edge Type*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_EDGETYPE )
+ pElement->pEdgeBundle->eEdgeType = static_cast<EdgeType>(ImplGetI( pElement->nIndexPrecision ));
+ else
+ pElement->aEdgeBundle.eEdgeType = static_cast<EdgeType>(ImplGetI( pElement->nIndexPrecision ));
+ }
+ break;
+ case 0x1c : /*Edge Width*/
+ {
+ double nWidth;
+ if ( pElement->eEdgeWidthSpecMode == SM_ABSOLUTE )
+ {
+ if ( pElement->eVDCType == VDC_REAL )
+ nWidth = ImplGetFloat( pElement->eVDCRealPrecision, pElement->nVDCRealSize );
+ else
+ nWidth = static_cast<double>(ImplGetI( pElement->nVDCIntegerPrecision ));
+
+ ImplMapDouble( nWidth );
+ }
+ else
+ nWidth = static_cast<sal_uInt32>(ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize )) * 25;
+ if ( pElement->nAspectSourceFlags & ASF_EDGEWIDTH )
+ pElement->pEdgeBundle->nEdgeWidth = nWidth;
+ else
+ pElement->aEdgeBundle.nEdgeWidth = nWidth;
+ }
+ break;
+ case 0x1d : /*Edge Color*/
+ {
+ if ( pElement->nAspectSourceFlags & ASF_EDGECOLOR )
+ pElement->pEdgeBundle->SetColor( ImplGetBitmapColor() );
+ else
+ pElement->aEdgeBundle.SetColor( ImplGetBitmapColor() );
+ }
+ break;
+ case 0x1e : /*Edge Visibility*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eEdgeVisibility = EV_OFF; break;
+ case 1 : pElement->eEdgeVisibility = EV_ON; break;
+ default : mbStatus = false;
+ }
+ }
+ break;
+ case 0x1f : /*Fill Reference Point*/
+ ImplGetPoint( pElement->aFillRefPoint );
+ break;
+ case 0x20 : /*Pattern Table" )*/ break;
+ case 0x21 : /*Pattern Size" )*/ break;
+ case 0x22 : /*Color Table*/
+ {
+ sal_uInt32 nColorStartIndex = ImplGetUI( pElement->nColorIndexPrecision );
+ if ( ( nColorStartIndex > 255 ) ||
+ ( ( ( mnElementSize - pElement->nColorIndexPrecision ) % ( pElement->nColorPrecision * 3 ) ) != 0 ) )
+ {
+ mbStatus = false;
+ }
+ else
+ {
+ sal_uInt32 nColors = ( mnElementSize - pElement->nColorIndexPrecision ) / ( 3 * pElement->nColorPrecision );
+ if ( nColors )
+ {
+ sal_uInt32 nMaxColorIndex = nColorStartIndex + nColors - 1;
+ sal_uInt32 nIndex;
+ if ( nMaxColorIndex > 255 )
+ {
+ mbStatus = false;
+ break;
+ }
+ if ( pElement->nLatestColorMaximumIndex < nMaxColorIndex )
+ pElement->nLatestColorMaximumIndex = nMaxColorIndex;
+
+ for ( nIndex = nColorStartIndex; nIndex <= nMaxColorIndex; nIndex++ )
+ {
+ pElement->aLatestColorTable[ nIndex ] = ImplGetBitmapColor( true );
+ }
+
+ pElement->nColorMaximumIndex = pElement->nLatestColorMaximumIndex;
+ for ( nIndex = nColorStartIndex; nIndex <= nMaxColorIndex; nIndex++ )
+ {
+ if ( !pElement->aColorTableEntryIs[ nIndex ] )
+ {
+ pElement->aColorTableEntryIs[ nIndex ] = 1;
+ pElement->aColorTable[ nIndex ] = pElement->aLatestColorTable[ nIndex ];
+ }
+ }
+ }
+ }
+ }
+ break;
+ case 0x23 : /*Aspect Source Flags*/
+ {
+ int nFlags = mnElementSize >> 2;
+ while ( nFlags-- > 0 )
+ {
+ sal_uInt32 nFlag = 0;
+ switch( ImplGetUI16() )
+ {
+ case 0 : nFlag = ASF_LINETYPE; break;
+ case 1 : nFlag = ASF_LINEWIDTH; break;
+ case 2 : nFlag = ASF_LINECOLOR; break;
+ case 3 : nFlag = ASF_MARKERTYPE; break;
+ case 4 : nFlag = ASF_MARKERSIZE; break;
+ case 5 : nFlag = ASF_MARKERCOLOR; break;
+ case 6 : nFlag = ASF_FILLINTERIORSTYLE; break;
+ case 7 : nFlag = ASF_HATCHINDEX; break;
+ case 8 : nFlag = ASF_PATTERNINDEX; break;
+ case 9 : nFlag = ASF_BITMAPINDEX; break;
+ case 10 : nFlag = ASF_FILLCOLOR; break;
+ case 11 : nFlag = ASF_EDGETYPE; break;
+ case 12 : nFlag = ASF_EDGEWIDTH; break;
+ case 13 : nFlag = ASF_EDGECOLOR; break;
+ case 14 : nFlag = ASF_TEXTFONTINDEX; break;
+ case 15 : nFlag = ASF_TEXTPRECISION; break;
+ case 16 : nFlag = ASF_CHARACTEREXPANSION; break;
+ case 17 : nFlag = ASF_CHARACTERSPACING; break;
+ case 18 : nFlag = ASF_TEXTCOLOR; break;
+ default : mbStatus = false; break;
+ }
+ sal_uInt32 nASF = ImplGetUI16();
+ switch ( nASF )
+ {
+ case 0 : pElement->nAspectSourceFlags &= ~nFlag; break; // INDIVIDUAL
+ case 1 : pElement->nAspectSourceFlags |= nFlag; break; // BUNDLED
+ default : mbStatus = false; break;
+ }
+ }
+ }
+ break;
+ case 0x24 : /*Pick Identifier*/ break;
+ case 0x25 : /*Line Cap*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eLineCapType = LCT_BUTT; break;
+ case 1 : pElement->eLineCapType = LCT_ROUND; break;
+ case 2 : pElement->eLineCapType = LCT_SQUARE; break;
+ case 3 : pElement->eLineCapType = LCT_TRIANGLE; break;
+ case 4 : pElement->eLineCapType = LCT_ARROW; break;
+ default : pElement->eLineCapType = LCT_NONE; break;
+ }
+ }
+ break;
+ case 0x26 : /*Line Join*/
+ {
+ switch( ImplGetUI16() )
+ {
+ case 0 : pElement->eLineJoinType = LJT_MITER; break;
+ case 1 : pElement->eLineJoinType = LJT_ROUND; break;
+ case 2 : pElement->eLineJoinType = LJT_BEVEL; break;
+ default : pElement->eLineJoinType = LJT_NONE; break;
+ }
+ }
+ break;
+ case 0x27 : /*Line Type Continuation*/ break; // NS
+ case 0x28 : /*Line Type Initial Offset*/ break; // NS
+ case 0x29 : /*Text Score Type*/ break;
+ case 0x2a : /*Restricted Text Type*/ break;
+ case 0x2b : /*Interpolated interior*/ break;
+ case 0x2c : /*Edge Cap*/ break; // NS
+ case 0x2d : /*Edge Join*/ break;
+ case 0x2e : /*Edge Type Continuation*/ break; // NS
+ case 0x2f : /*Edge Type Initial Offset*/ break; // NS
+ case 0x30 : /*Symbol Library Index*/ break; // NS
+ case 0x31 : /*Symbol Color*/ break; // NS
+ case 0x32 : /*Symbol Size*/ break; // NS
+ case 0x33 : /*Symbol Orientation*/ break; // NS
+ case 0x50 : /*Block Text vcl::Region Margins*/ break;
+ case 0x51 : /*Block Text vcl::Region Expansion*/ break;
+ case 0x52 : /*Block Text vcl::Region Anchor*/ break;
+ case 0x53 : /*Block Text Paragraph Horizontal Alignment*/ break;
+ case 0x54 : /*Block Text Paragraph Vertical Alignment*/ break;
+ case 0x55 : /*Block Text Line Flow*/ break;
+ case 0x60 : /*Block Text Paragraph Spacing*/ break;
+ case 0x61 : /*Block Text Paragraph Indent*/ break;
+ case 0x62 : /*Block Text Paragraph Tabs*/ break;
+ case 0x63 : /*Block Text Paragraph Bullets*/ break;
+ case 0x64 : /*Block Text Paragraph Bullet Level*/ break;
+ case 0x65 : /*Block Text Paragraph Line Horizontal Alignment*/ break;
+ case 0x66 : /*Block Text Paragraph Line Vertical Alignment*/ break;
+ case 0x67 : /*Block Text Paragragh Line Spacing*/ break;
+ case 0x68 : /*Block Text Paragraph Word Wrap*/ break;
+ case 0x70 : /*Block Text Forward Advance Distance*/ break;
+ case 0x71 : /*Word Spacing*/ break;
+ case 0x72 : /*External Leading*/ break;
+ case 0x7a : /*set Gradient Offset*/
+ {
+ tools::Long nHorzOffset = ImplGetI( pElement->nIndexPrecision );
+ tools::Long nVertOffset = ImplGetI( pElement->nIndexPrecision );
+ (void)ImplGetUI16(); // nType
+ mpOutAct->SetGradientOffset( nHorzOffset, nVertOffset );
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0x7b : /*set Gradient Edge*/
+ {
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0x7c : /*set Gradient Angle*/
+ {
+ mpOutAct->SetGradientAngle( ImplGetI( pElement->nIndexPrecision ) );
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0x7d : /*set Gradient Description*/
+ {
+ ImplGetI( pElement->nIndexPrecision ); // -Wall is this needed?
+ sal_uInt32 nNumberOfStages = ImplGetI( pElement->nIndexPrecision );
+ sal_uInt32 i, nColorFrom = 0;
+ sal_uInt32 nColorTo = 0xffffff;
+
+ const size_t nRemainingSize = mpEndValidSource - (mpSource + mnParaSize);
+ const size_t nMaxPossibleRecords = nRemainingSize/pElement->nRealSize;
+
+ if (nNumberOfStages > nMaxPossibleRecords)
+ {
+ mbStatus = false;
+ break;
+ }
+
+ for ( i = 0; i < nNumberOfStages; i++ )
+ {
+ ImplGetFloat(pElement->eRealPrecision, pElement->nRealSize);
+ }
+
+ for ( i = 0; i <= nNumberOfStages; i++ )
+ {
+ sal_uInt32 nPara = mnParaSize + 24;
+ if ( i == 0 )
+ {
+ nColorTo = ImplGetBitmapColor();
+ nColorFrom = nColorTo ^ 0xffffff;
+ }
+ else if ( i == 1 )
+ nColorFrom = ImplGetBitmapColor();
+ mnParaSize = nPara;
+ }
+ if ( nNumberOfStages > 1 )
+ mpOutAct->SetGradientStyle( 0xff );
+
+ mpOutAct->SetGradientDescriptor( nColorFrom, nColorTo );
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0x7e : /*set Gradient Style*/
+ {
+ sal_uInt32 nStyle = ImplGetUI16();
+ (void)ImplGetFloat( pElement->eRealPrecision, pElement->nRealSize ); // fRatio
+ mpOutAct->SetGradientStyle( nStyle );
+ mnAct4PostReset |= ACT4_GRADIENT_ACTION;
+ }
+ break;
+ case 0xff : /*inquire Font metrics*/ break;
+ case 0xfe : /*inquire character widths*/ break;
+ case 0xfd : /*set Text Font*/ break;
+ case 0xfc : /*set current position*/ break;
+ case 0xfb : /*set current position mode*/ break;
+ case 0xfa : /*set character height mode*/ break;
+ case 0xf9 : /*set Transform matrix 2D*/ break;
+ case 0xf8 : /*set Transform matrix 3D*/ break;
+ case 0xf7 : /*pop transformation state*/ break;
+ case 0xf6 : /*clear transformation state*/ break;
+ case 0xf5 : /*set character widths*/ break;
+ case 0xf4 : /*set color name - for Pantone support*/ break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/class7.cxx b/filter/source/graphicfilter/icgm/class7.cxx
new file mode 100644
index 000000000..63bce3296
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/class7.cxx
@@ -0,0 +1,210 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <o3tl/safeint.hxx>
+
+#include "cgm.hxx"
+#include "chart.hxx"
+#include "outact.hxx"
+
+
+void CGM::ImplDoClass7()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Message */break;
+ case 0x02 :
+ {
+ if (mpEndValidSource - mpSource < 12)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ sal_uInt16* pTemp = reinterpret_cast<sal_uInt16*>(mpSource);
+ sal_uInt16 nOpcode = pTemp[ 4 ];
+
+ sal_uInt8* pAppData = mpSource + 12;
+
+ if ( mpChart || ( nOpcode == 0 ) )
+ {
+ switch ( nOpcode )
+ {
+ case 0x000 : /*AppData - Beginning of File Opcodes*/
+ {
+ if (mpEndValidSource - pAppData < 4)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ if ( mpChart == nullptr )
+ mpChart.reset( new CGMChart );
+ mpChart->mnCurrentFileType = pAppData[ 3 ];
+ }
+ break;
+ case 0x001 : /*AppData - End of File Opcodes */break;
+ case 0x190 : /*AppData - FDESC */break;
+ case 0x192 : /*AppData - FNOTES */break;
+ case 0x1F4 : /*AppData - BOGENFILE */break;
+ case 0x1F5 : /*AppData - EOGENFILE */break;
+ case 0x1F8 : /*AppData - BOCHTGROUP */break;
+ case 0x1F9 : /*AppData - EOCHTGROUP */break;
+ case 0x1FC : /*AppData - BOCHTDATA */break;
+ case 0x1FD : /*AppData - EOCHTDATA*/
+ {
+ // mpOutAct->DrawChart();
+ }
+ break;
+ case 0x200 : /*AppData - BOSYMGROUP */break;
+ case 0x201 : /*AppData - EOSYMGROUP */break;
+ case 0x204 : /*AppData - BEGSYMBOL */break;
+ case 0x205 : /*AppData - ENDSYMBOL */break;
+ case 0x208 : /*AppData - BOSHWGROUP */break;
+ case 0x209 : /*AppData - EOSHWGROUP */break;
+ case 0x260 : /*AppData - BEGGROUP */break;
+ case 0x262 : /*AppData - ENDGROUP */break;
+ case 0x264 : /*AppData - DATANODE*/
+ {
+ if (o3tl::make_unsigned(mpEndValidSource - pAppData) < sizeof(DataNode))
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ mpChart->mDataNode[ 0 ] = *reinterpret_cast<DataNode*>( pAppData );
+ sal_Int8 nZoneEnum = mpChart->mDataNode[ 0 ].nZoneEnum;
+ if (nZoneEnum > 0 && nZoneEnum <= 6)
+ mpChart->mDataNode[ nZoneEnum ] = *reinterpret_cast<DataNode*>( pAppData );
+ }
+ break;
+ case 0x2BE : /*AppData - SHWSLIDEREC*/
+ {
+ if (mpEndValidSource - pAppData < 17)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ if ( pAppData[ 16 ] == 0 ) // a blank template ?
+ {
+ if ( pAppData[ 2 ] == 46 )
+ {
+ // this starts the document -> maybe we could insert a new document
+ }
+ else if ( pAppData[ 2 ] & 0x80 )
+ {
+ // this is a template
+ }
+ else
+ {
+ mpOutAct->InsertPage();
+ }
+ }
+ mpChart->ResetAnnotation();
+ }
+ break;
+ case 0x2C0 : /*AppData - SHWKEYTABLE */break;
+ case 0x2C2 : /*AppData - SHWBUTTONTAB */break;
+ case 0x2C4 : /*AppData - SHWGLOBAL */break;
+ case 0x2C6 : /*AppData - SHWTITLE */break;
+ case 0x2CA : /*AppData - SHWAPP */break;
+ case 0x320 : /*AppData - TEXT*/
+ {
+ if (mpEndValidSource - pAppData < 9)
+ throw css::uno::Exception("attempt to read past end of input", nullptr);
+
+ std::unique_ptr<TextEntry> pTextEntry(new TextEntry);
+ pTextEntry->nTypeOfText = *reinterpret_cast<sal_uInt16*>( pAppData );
+ pTextEntry->nRowOrLineNum = *reinterpret_cast<sal_uInt16*>( pAppData + 2 );
+ pTextEntry->nColumnNum = *reinterpret_cast<sal_uInt16*>( pAppData + 4 );
+ sal_uInt16 nAttributes = *reinterpret_cast<sal_uInt16*>( pAppData + 6 );
+ pTextEntry->nZoneSize = nAttributes & 0xff;
+ pTextEntry->nLineType = ( nAttributes >> 8 ) & 0xf;
+ nAttributes >>= 12;
+ pTextEntry->nAttributes = nAttributes;
+ pAppData += 8;
+ auto nMaxLen = mpEndValidSource - pAppData;
+ sal_uInt32 nLen = strnlen(reinterpret_cast<char*>(pAppData), nMaxLen);
+ pTextEntry->pText = new char[nLen + 1];
+ memcpy( pTextEntry->pText, pAppData, nLen );
+ pTextEntry->pText[nLen] = 0;
+ pAppData += nLen;
+
+ mpChart->InsertTextEntry( std::move(pTextEntry) );
+ }
+ break;
+ case 0x321 : /*AppData - IOC_TABS */break;
+ case 0x322 : /*AppData - CHARTZONE*/
+ break;
+ case 0x324 : /*AppData - TITLEZONE */break;
+ case 0x328 : /*AppData - FOOTNOTEZONE */break;
+ case 0x32A : /*AppData - LEGENDZONE */break;
+ case 0x330 : /*AppData - PAGEORIENTDIM*/
+ break;
+ case 0x334 : /*AppData - CHTZONEOPTN*/
+ break;
+ case 0x336 : /*AppData - CHTINTL*/
+ break;
+ case 0x338 : /*AppData - CHTLINESPC */break;
+ case 0x384 : /*AppData - ORGGRIDSTATE */break;
+ case 0x386 : /*AppData - ORGSCRSTATE */break;
+ case 0x388 : /*AppData - ORGTREESTATE */break;
+ case 0x38A : /*AppData - ORGTEXTOPTN */break;
+ case 0x38E : /*AppData - ORGBOXOPTN */break;
+ case 0x390 : /*AppData - ORGBOXDIM */break;
+ case 0x392 : /*AppData - ORGBOX */break;
+ case 0x3EA : /*AppData - TTLTEXTOPTN */break;
+ case 0x3EE : /*AppData - TTLAUTOBUILD */break;
+ case 0x44E : /*AppData - BULTEXTOPTN */break;
+ case 0x452 : /*AppData - BULLETOPTN*/
+ break;
+ case 0x454 : /*AppData - BULLETLINES*/break;
+ case 0x456 : /*AppData - BULAUTOBUILD */break;
+ case 0x4B2 : /*AppData - TBLTEXTOPTN */break;
+ case 0x4B6 : /*AppData - TBLOPTN */break;
+ case 0x4B8 : /*AppData - TBLCOLOPTN */break;
+ case 0x4BA : /*AppData - TBLLEGENDOPTN */break;
+ case 0x4BC : /*AppData - TBLRANGEOPTN */break;
+ case 0x4BE : /*AppData - TBLROWOPTN */break;
+ case 0x4C0 : /*AppData - TBLAUTOBUILD */break;
+ case 0x518 : /*AppData - PIECHARTOPTN */break;
+ case 0x51A : /*AppData - PIELEGENDOPTN */break;
+ case 0x51C : /*AppData - PIETEXTOPTN */break;
+ case 0x51E : /*AppData - PIEOPTN */break;
+ case 0x520 : /*AppData - PIEPCTLABOPTN */break;
+ case 0x522 : /*AppData - PIEVALLABOPTN */break;
+ case 0x524 : /*AppData - PIESLICE */break;
+ case 0x57A : /*AppData - XYAXISOPTN */break;
+ case 0x57C : /*AppData - XYGRIDOPTN */break;
+ case 0x57D : /*AppData - XYGRIDSHOWFILL */break;
+ case 0x57E : /*AppData - XYSERIESOPTN */break;
+ case 0x580 : /*AppData - XYSTYLEOPTN */break;
+ case 0x582 : /*AppData - XYTABLEOPTN */break;
+ case 0x584 : /*AppData - XYTEXTOPTN */break;
+ case 0x586 : /*AppData - XYDATAOPTN */break;
+ case 0x58A : /*AppData - XYLEGENDOPN */break;
+ case 0x58C : /*AppData - XYCALCULATION */break;
+ case 0x58E : /*AppData - XYXVALUE */break;
+ case 0x590 : /*AppData - XYYVALUE */break;
+ case 0x592 : /*AppData - XYXEXTVALUE */break;
+ case 0x618 : /*AppData - IOC_CHTCOLRTAB */break;
+ case 0x619 : /*AppData - IOC_CHTFONTTAB */break;
+ case 0x1fff : /*AppData - 0x1fff */break;
+ default : /*UNKNOWN Application Data */break;
+ }
+ }
+ mnParaSize = mnElementSize;
+ break;
+ }
+ default: break;
+ }
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/classx.cxx b/filter/source/graphicfilter/icgm/classx.cxx
new file mode 100644
index 000000000..2b624f63b
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/classx.cxx
@@ -0,0 +1,249 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "cgm.hxx"
+#include "elements.hxx"
+#include "outact.hxx"
+
+
+void CGM::ImplSetUnderlineMode()
+{
+ sal_uInt32 nMode = ImplGetUI16();
+ switch ( nMode )
+ {
+ case 1 : pElement->eUnderlineMode = UM_LOW; break;
+ case 2 : pElement->eUnderlineMode = UM_HIGH; break;
+ case 4 : pElement->eUnderlineMode = UM_STRIKEOUT; break;
+ case 8 : pElement->eUnderlineMode = UM_OVERSCORE; break;
+ default: pElement->eUnderlineMode = UM_OFF; break;
+ }
+ pElement->nUnderlineColor = ImplGetBitmapColor();
+}
+
+void CGM::ImplDoClass6()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Escape*/
+ {
+ tools::Long nIdentifier = ImplGetI( pElement->nIntegerPrecision );
+ switch ( nIdentifier )
+ {
+ case 0 : /*inquire function support */break;
+ case -1 : /*set underline mode*/
+ {
+ ImplSetUnderlineMode();
+ }
+ break;
+ case -2 : /*set script mode */break;
+ case -3 : /*set shadow mode */break;
+ case -6 : /*inquire origin offset */break;
+ case -8 : /*set media size */break;
+ case -10 : /*set character mode */break;
+ case -14 : /*resolution mode */break;
+ case -17 : /*line cap */break;
+ case -18 : /*line join */break;
+ case -19 : /*edge join */break;
+ case -30 : /*media type */break;
+ case -31 : /*number of copies */break;
+ case -32 : /*orientation */break;
+ case -33 : /*device color representation */break;
+ case -34 : /*device font list */break;
+ case -35 : /*color reversal mode */break;
+ case -36 : /*line cap attributes */break;
+ case -37 : /*begin effect */break;
+ case -38 : /*end effect */break;
+ case -39 : /*begin effect definition */break;
+ case -40 : /*end effect definition */break;
+ case -41 : /*end style definition */break;
+ case -42 : /*begin eps data */break;
+ case -43 : /*eps data */break;
+ case -44 : /*end eps data */break;
+ case -45 : /*set background style */break;
+ case -46 : /*set eps mode */break;
+ case -47 : /*fill mode */break;
+ case -48 : /*begin symbol */break;
+ case -49 : /*end symbol */break;
+ case -50 : /*begin layer */break;
+ case -51 : /*end layer */break;
+ case -52 : /*layer visibility */break;
+ case -53 : /*inquire foreign data */break;
+ case -54 : /*set text offset */break;
+ case -55 : /*begin group */break;
+ case -56 : /*end group */break;
+ case -100 : /*begin patch */break;
+ case -101 : /*end patch */break;
+ case -102 : /*begin block text region */break;
+ case -103 : /*end block text region */break;
+ case -120 : /*region margins */break;
+ case -121 : /*region expansions */break;
+ case -122 : /*region anchor */break;
+ case -123 : /*paragraph horizontal align */break;
+ case -124 : /*paragraph vertical align */break;
+ case -125 : /*region line flow */break;
+ case -130 : /*paragraph spacing */break;
+ case -131 : /*paragraph indentation */break;
+ case -132 : /*paragraph tabs */break;
+ case -133 : /*paragraph bullet */break;
+ case -134 : /*paragraph bullet level */break;
+ case -135 : /*line horizontal align */break;
+ case -136 : /*line vertical align */break;
+ case -137 : /*line spacing */break;
+ case -138 : /*word wrap */break;
+ case -150 : /*forward advance distance */break;
+ case -151 : /*word spacing */break;
+ case -152 : /*external leading */break;
+ case -160 : /*set gradient offset */break;
+ case -161 : /*set gradient edge */break;
+ case -162 : /*set gradient angle */break;
+ case -163 : /*set gradient description */break;
+ case -164 : /*set gradient style */break;
+ case -165 : /*set background style */break;
+ case -170 : /*geometric pattern draw style */break;
+ case -190 : /*set character width */break;
+ case -191 : /*hyperlink definitions */break;
+ case -192 : /*set color name for pantone */break;
+ case -32746 : /*set text font */break;
+ case -32747 : /*font selection mode */break;
+ case -32752 : /*connecting edge */break;
+ case -32753 : /*set drawing mode */break;
+ case -32754 : /*inquire clip rectangle */break;
+ case -32755 : /*protection region indicator */break;
+ case -32756 : /*end protection region */break;
+ case -32757 : /*begin protection region */break;
+ case -32758 : /*geometric pattern definition */break;
+ case -32759 : /*hatch style definition */break;
+ case -32760 : /*close figure */break;
+ case -32761 : /*end figure*/
+ {
+ mpOutAct->EndFigure();
+ mbFigure = false;
+ }
+ break;
+ case -32762 : /*begin figure*/
+ {
+ mbFigure = true;
+ mpOutAct->BeginFigure();
+ }
+ break;
+ case -32763 : /*pop transformation */break;
+ case -32764 : /*push transformation */break;
+ case -32765 : /*copy segment */break;
+ case -32766 : /*endseg */break;
+ case -32767 : /*begin segment */break;
+ default : break;
+ }
+ mnParaSize = mnElementSize;
+ }
+ break;
+ case 0x02 : /*Get Escape */break;
+ case 0x11 : /*Set Underline Mode*/
+ {
+ ImplSetUnderlineMode();
+ }
+ break;
+ case 0x12 : /*Set Script Mode */break;
+ case 0x13 : /*Set Shadow Mode */break;
+ case 0x18 : /*Set Media Size */break;
+ case 0x20 : /*Set Character Mode */break;
+ case 0x24 : /*Resolution Mode */break;
+ case 0x27 : /*Line Cap */break;
+ case 0x28 : /*Line Join */break;
+ case 0x29 : /*Edge Join */break;
+ case 0x40 : /*Media Type */break;
+ case 0x41 : /*Number of Copies */break;
+ case 0x42 : /*Origin */break;
+ case 0x45 : /*Color Reversal Mode */break;
+ case 0x46 : /*Line Cap Attributes */break;
+ case 0x49 : /*Begin Effect Definition */break;
+ case 0x50 : /*End Effect Definition */break;
+ case 0x51 : /*Line End Style Attributes */break;
+ case 0x52 : /*Begin Data */break;
+ case 0x53 : /*Data */break;
+ case 0x54 : /*End Data */break;
+ case 0x55 : /*Set Background Style */break;
+ case 0x56 : /*Set EPS Mode */break;
+ case 0x57 : /*Fill Mode */break;
+ case 0x58 : /*Begin Symbol */break;
+ case 0x59 : /*End Symbol */break;
+ case 0x60 : /*Begin Layer */break;
+ case 0x61 : /*End Layer */break;
+ case 0x62 : /*Layer Visibility */break;
+ case 0x64 : /*Set Text Offset */break;
+ case 0xFF : /*Inquire Function Support */break;
+ case 0xFE : /*Inquire Origin */break;
+ case 0xFD : /*Inquire Foreign Data Mode */break;
+ case 0xFC : /*Inquire Text Extent */break;
+ case 0xFB : /*Inquire DPI */break;
+ default: break;
+ }
+};
+
+
+void CGM::ImplDoClass8()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Copy Segment */break; // NS
+ case 0x02 : /*Inheritance Filter */break; // NS
+ case 0x03 : /*Clip Inheritance */break; // NS
+ case 0x04 : /*Segment Transformation */break;
+ case 0x05 : /*Segment Highlighting */break; // NS
+ case 0x06 : /*Segment Display Priority */break; // NS
+ case 0x07 : /*Segment Pick Priority */break; // NS
+ case 0xfe : /*INQ Current Position */break;
+ case 0xff : /*INQ Inserted Object Extent */break;
+ default: break; // NS
+ }
+};
+
+
+void CGM::ImplDoClass9()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Pixel Array */break; // NS
+ case 0x02 : /*Create Bitmap */break; // NS
+ case 0x03 : /*Delete Bitmap */break; // NS
+ case 0x04 : /*Select Drawing Bitmap */break; // NS
+ case 0x05 : /*Display Bitmap */break; // NS
+ case 0x06 : /*Drawing Mode */break;
+ case 0x07 : /*Mapped Bitmap ForeGround Color */break; // NS
+ case 0x08 : /*Fill Bitmap */break; // NS
+ case 0x09 : /*Two Operand BitBlt */break; // NS
+ case 0x0a : /*Three Operand BitBlt */break; // NS
+ default: break;
+ }
+};
+
+
+void CGM::ImplDoClass15()
+{
+ switch ( mnElementID )
+ {
+ case 0x01 : /*Inquire Error Stack */break;
+ case 0x02 : /*Pop Error Stack */break;
+ case 0x03 : /*Empty Error Stack */break;
+ default: break;
+ }
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/elements.cxx b/filter/source/graphicfilter/icgm/elements.cxx
new file mode 100644
index 000000000..9a0221066
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/elements.cxx
@@ -0,0 +1,336 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "elements.hxx"
+
+#include <algorithm>
+
+CGMElements::CGMElements()
+{
+ Init();
+};
+
+
+CGMElements::~CGMElements()
+{
+}
+
+
+CGMElements& CGMElements::operator=( const CGMElements& rSource )
+{
+ if (this == &rSource)
+ return *this;
+
+ sal_uInt32 nIndex;
+
+ nVDCIntegerPrecision = rSource.nVDCIntegerPrecision;
+ nIntegerPrecision = rSource.nIntegerPrecision;
+ eRealPrecision = rSource.eRealPrecision;
+ nRealSize = rSource.nRealSize;
+ nIndexPrecision = rSource.nIndexPrecision;
+ nColorPrecision = rSource.nColorPrecision;
+ nColorIndexPrecision = rSource.nColorIndexPrecision;
+
+ nMetaFileVersion = rSource.nMetaFileVersion;
+ eScalingMode = rSource.eScalingMode;
+ nScalingFactor = rSource.nScalingFactor;
+ eVDCType = rSource.eVDCType;
+ eVDCRealPrecision = rSource.eVDCRealPrecision;
+ nVDCRealSize = rSource.nVDCRealSize;
+ aVDCExtent = rSource.aVDCExtent;
+ aVDCExtentMaximum = rSource.aVDCExtentMaximum;
+ eDeviceViewPortMode = rSource.eDeviceViewPortMode;
+ nDeviceViewPortScale = rSource.nDeviceViewPortScale;
+ eDeviceViewPortMap = rSource.eDeviceViewPortMap;
+ eDeviceViewPortMapH = rSource.eDeviceViewPortMapH;
+ eDeviceViewPortMapV = rSource.eDeviceViewPortMapV;
+ aDeviceViewPort = rSource.aDeviceViewPort;
+ nMitreLimit = rSource.nMitreLimit;
+ eClipIndicator = rSource.eClipIndicator;
+ aClipRect = rSource.aClipRect;
+ eColorSelectionMode = rSource.eColorSelectionMode;
+ nColorMaximumIndex = rSource.nColorMaximumIndex;
+ nLatestColorMaximumIndex = rSource.nLatestColorMaximumIndex;
+
+ for ( nIndex = 1; nIndex < 256; nIndex++ ) // do not overwrite the background color
+ {
+ aColorTableEntryIs[ nIndex ] = rSource.aColorTableEntryIs[ nIndex ];
+ aColorTable[ nIndex ] = rSource.aColorTable[ nIndex ];
+ aLatestColorTable[ nIndex ] = rSource.aColorTable[ nIndex ];
+ }
+
+ for ( nIndex = 0; nIndex < 8; nIndex++ )
+ {
+ nColorValueExtent[ nIndex ] = rSource.nColorValueExtent[ nIndex ];
+ }
+ nAspectSourceFlags = rSource.nAspectSourceFlags;
+
+ CopyAllBundles( rSource.aLineList, aLineList );
+ aLineBundle = rSource.aLineBundle;
+ pLineBundle = static_cast<LineBundle*>(GetBundle( aLineList, rSource.pLineBundle->GetIndex() ));
+ eLineWidthSpecMode = rSource.eLineWidthSpecMode;
+ eLineCapType = rSource.eLineCapType;
+ eLineJoinType = rSource.eLineJoinType;
+
+ CopyAllBundles( rSource.aMarkerList, aMarkerList );
+ aMarkerBundle = rSource.aMarkerBundle;
+ pMarkerBundle = static_cast<MarkerBundle*>(GetBundle( aMarkerList, rSource.pMarkerBundle->GetIndex() ));
+ eMarkerSizeSpecMode = rSource.eMarkerSizeSpecMode;
+
+ CopyAllBundles( rSource.aEdgeList, aEdgeList );
+ aEdgeBundle = rSource.aEdgeBundle;
+ pEdgeBundle = static_cast<EdgeBundle*>(GetBundle( aEdgeList, rSource.pEdgeBundle->GetIndex() ));
+ eEdgeVisibility = rSource.eEdgeVisibility;
+ eEdgeWidthSpecMode = rSource.eEdgeWidthSpecMode;
+
+ CopyAllBundles( rSource.aTextList, aTextList );
+ aTextBundle = rSource.aTextBundle;
+ pTextBundle = static_cast<TextBundle*>(GetBundle( aTextList, rSource.pTextBundle->GetIndex() ));
+ nCharacterHeight = rSource.nCharacterHeight;
+ nCharacterOrientation[ 0 ] = rSource.nCharacterOrientation[ 0 ];
+ nCharacterOrientation[ 1 ] = rSource.nCharacterOrientation[ 1 ];
+ nCharacterOrientation[ 2 ] = rSource.nCharacterOrientation[ 2 ];
+ nCharacterOrientation[ 3 ] = rSource.nCharacterOrientation[ 3 ];
+ eUnderlineMode = rSource.eUnderlineMode;
+ nUnderlineColor = rSource.nUnderlineColor;
+ eTextPath = rSource.eTextPath;
+ eTextAlignmentH = rSource.eTextAlignmentH;
+ eTextAlignmentV = rSource.eTextAlignmentV;
+ nTextAlignmentHCont = rSource.nTextAlignmentHCont;
+ nTextAlignmentVCont = rSource.nTextAlignmentVCont;
+ nCharacterSetIndex = rSource.nCharacterSetIndex;
+ nAlternateCharacterSetIndex = rSource.nAlternateCharacterSetIndex;
+ aFontList = rSource.aFontList;
+ eCharacterCodingA = rSource.eCharacterCodingA;
+
+ CopyAllBundles( rSource.aFillList, aFillList );
+ aFillBundle = rSource.aFillBundle;
+ pFillBundle = static_cast<FillBundle*>(GetBundle( aFillList, rSource.pFillBundle->GetIndex() ));
+ aFillRefPoint = rSource.aFillRefPoint;
+ eTransparency = rSource.eTransparency;
+ nAuxiliaryColor = rSource.nAuxiliaryColor;
+
+ maHatchMap = rSource.maHatchMap;
+ bSegmentCount = rSource.bSegmentCount;
+ return *this;
+}
+
+
+void CGMElements::Init()
+{
+
+ nIntegerPrecision = nIndexPrecision = 2;
+ nRealSize = nVDCRealSize = 4;
+ nColorIndexPrecision = 1;
+ nColorPrecision = 1;
+ nVDCIntegerPrecision = 2;
+ eRealPrecision = eVDCRealPrecision = RP_FIXED; //RP_FLOAT;
+
+ nMetaFileVersion = 1;
+ eScalingMode = SM_ABSTRACT;
+ eVDCType = VDC_INTEGER;
+ aVDCExtent.Left = aVDCExtent.Bottom = 0;
+// aVDCExtent.Right = aVDCExtent.Top = 32767;
+ aVDCExtent.Right = aVDCExtent.Top = 1.0;
+ aVDCExtentMaximum.Left = aVDCExtentMaximum.Bottom = 0;
+// aVDCExtentMaximum.Right = aVDCExtentMaximum.Top = 32767;
+ aVDCExtentMaximum.Right = aVDCExtentMaximum.Top = 1.0;
+
+ eDeviceViewPortMode = DVPM_FRACTION;
+ nDeviceViewPortScale = 1;
+ eDeviceViewPortMap = DVPM_FORCED;
+ eDeviceViewPortMapH = DVPMH_LEFT;
+ eDeviceViewPortMapV = DVPMV_BOTTOM;
+ aDeviceViewPort.Left = 0;
+ aDeviceViewPort.Top = 1;
+ aDeviceViewPort.Right = 0;
+ aDeviceViewPort.Bottom = 1;
+
+ nMitreLimit = 32767;
+ eClipIndicator = CI_ON;
+ aClipRect = aVDCExtent;
+
+ eColorSelectionMode = CSM_INDEXED;
+ nColorMaximumIndex = 63;
+ int i;
+ for ( i = 0; i < 256; aColorTableEntryIs[ i++ ] = 0 ) ;
+ aColorTable[ 0 ] = 0;
+ for ( i = 1; i < 256; aColorTable[ i++ ] = 0xffffff ) ;
+ nLatestColorMaximumIndex = 63;
+ aLatestColorTable[ 0 ] = 0;
+ for ( i = 1; i < 256; aLatestColorTable[ i++ ] = 0xffffff ) ;
+ nColorValueExtent[ 0 ] = nColorValueExtent[ 1 ] = nColorValueExtent[ 2 ] = 0;
+ nColorValueExtent[ 3 ] = nColorValueExtent[ 4 ] = nColorValueExtent[ 5 ] = 255;
+
+ nAspectSourceFlags = 0; // all flags are individual
+
+ eLineWidthSpecMode = SM_SCALED; // line parameter
+ eLineCapType = LCT_NONE;
+ eLineJoinType = LJT_NONE;
+ pLineBundle = &aLineBundle; // line bundle parameter
+ aLineBundle.SetIndex( 1 );
+ aLineBundle.eLineType = LT_SOLID;
+ aLineBundle.nLineWidth = 1;
+ aLineBundle.SetColor( 0xffffff );
+ InsertBundle( aLineList, aLineBundle );
+
+ eMarkerSizeSpecMode = SM_SCALED; // marker parameter
+ pMarkerBundle = &aMarkerBundle; // marker bundle parameter
+ aMarkerBundle.SetIndex( 1 );
+ aMarkerBundle.eMarkerType = MT_STAR;
+ aMarkerBundle.nMarkerSize = 1;
+ aMarkerBundle.SetColor( 0xffffff );
+ InsertBundle( aMarkerList, aMarkerBundle );
+
+ eEdgeVisibility = EV_OFF; // edge parameter
+ eEdgeWidthSpecMode = SM_SCALED;
+ pEdgeBundle = &aEdgeBundle; // edge bundle parameter
+ aEdgeBundle.SetIndex( 1 );
+ aEdgeBundle.eEdgeType = ET_SOLID;
+ aEdgeBundle.nEdgeWidth = 1;
+ aEdgeBundle.SetColor( 0xffffff );
+ InsertBundle( aEdgeList, aEdgeBundle );
+
+ nCharacterHeight = 327; // text parameter
+ nCharacterOrientation[0] = 0;
+ nCharacterOrientation[1] = 1;
+ nCharacterOrientation[2] = 1;
+ nCharacterOrientation[3] = 0;
+ eUnderlineMode = UM_OFF;
+ nUnderlineColor = 0xffffff;
+ eTextPath = TPR_RIGHT;
+ eTextAlignmentH = TAH_NORMAL;
+ eTextAlignmentV = TAV_NORMAL;
+ nCharacterSetIndex = nAlternateCharacterSetIndex = 1;
+ eCharacterCodingA = CCA_BASIC_7;
+ pTextBundle = &aTextBundle; // text bundle parameter
+ aTextBundle.SetIndex( 1 );
+ aTextBundle.nTextFontIndex = 1;
+ aTextBundle.eTextPrecision = TPR_STRING;
+ aTextBundle.nCharacterExpansion = 1;
+ aTextBundle.nCharacterSpacing = 0;
+ aTextBundle.SetColor( 0xffffff );
+ InsertBundle( aTextList, aTextBundle );
+
+ pFillBundle = &aFillBundle; // fill bundle parameter
+ aFillBundle.SetIndex( 1 );
+ aFillBundle.eFillInteriorStyle = FIS_HOLLOW;
+ aFillBundle.nFillHatchIndex = 1;
+ aFillBundle.nFillPatternIndex = 1;
+ aFillBundle.SetColor( 0xffffff );
+ InsertBundle( aFillList, aFillBundle );
+
+ ImplInsertHatch( 0, 0, 0, 0 );
+ ImplInsertHatch( 1, 0, 125, 0 );
+ ImplInsertHatch( 2, 0, 125, 900 );
+ ImplInsertHatch( 3, 0, 125, 450 );
+ ImplInsertHatch( 4, 0, 125, 1350 );
+ ImplInsertHatch( 5, 1, 125, 0 );
+ ImplInsertHatch( 6, 1, 125, 450 );
+ ImplInsertHatch( -1, 0, 75, 0 );
+ ImplInsertHatch( -2, 0, 75, 900 );
+ ImplInsertHatch( -3, 0, 75, 450 );
+ ImplInsertHatch( -4, 0, 75, 1350 );
+ ImplInsertHatch( -5, 1, 75, 0 );
+ ImplInsertHatch( -6, 1, 75, 450 );
+ ImplInsertHatch( -7, 2, 125, 0 );
+ ImplInsertHatch( -8, 2, 125, 900 );
+ ImplInsertHatch( -9, 2, 125, 450 );
+ ImplInsertHatch( -10, 2, 125, 1350 );
+ ImplInsertHatch( -11, 0, 40, 0 );
+ ImplInsertHatch( -12, 0, 40, 900 );
+ ImplInsertHatch( -13, 0, 40, 450 );
+ ImplInsertHatch( -14, 0, 40, 1350 );
+ ImplInsertHatch( -15, 1, 40, 0 );
+ ImplInsertHatch( -16, 1, 40, 900 );
+ ImplInsertHatch( -21, 0, 250, 0 );
+ ImplInsertHatch( -22, 0, 250, 900 );
+ ImplInsertHatch( -23, 0, 250, 450 );
+ ImplInsertHatch( -24, 0, 250, 1350 );
+ ImplInsertHatch( -25, 1, 250, 0 );
+ ImplInsertHatch( -26, 1, 250, 450 );
+
+ eTransparency = T_ON;
+
+ nBackGroundColor = nAuxiliaryColor = 0;
+
+ bSegmentCount = false;
+
+ nScalingFactor = 1.0;
+ nTextAlignmentVCont = nTextAlignmentHCont = 0.0;
+}
+
+
+void CGMElements::ImplInsertHatch( sal_Int32 nKey, int nStyle, tools::Long nDistance, tools::Long nAngle )
+{
+ HatchEntry& rEntry = maHatchMap[nKey];
+ rEntry.HatchStyle = nStyle;
+ rEntry.HatchDistance = nDistance;
+ rEntry.HatchAngle = nAngle;
+}
+
+
+void CGMElements::CopyAllBundles( const BundleList& rSource, BundleList& rDest )
+{
+ rDest.clear();
+
+ for (auto & pPtr : rSource)
+ {
+ rDest.push_back( pPtr->Clone() );
+ }
+};
+
+
+Bundle* CGMElements::GetBundleIndex( tools::Long nIndex, BundleList& rList, Bundle& rBundle )
+{
+ rBundle.SetIndex( nIndex );
+ Bundle* pBundle = GetBundle( rList, nIndex );
+ if ( !pBundle )
+ pBundle = InsertBundle( rList, rBundle );
+ return pBundle;
+}
+
+
+Bundle* CGMElements::GetBundle( BundleList& rList, tools::Long nIndex )
+{
+ for (auto const & i : rList) {
+ if ( i->GetIndex() == nIndex ) {
+ return i.get();
+ }
+ }
+ return nullptr;
+}
+
+
+Bundle* CGMElements::InsertBundle( BundleList& rList, Bundle& rBundle )
+{
+ Bundle* pBundle = GetBundle( rList, rBundle.GetIndex() );
+ if ( pBundle )
+ {
+ auto it = std::find_if(rList.begin(), rList.end(),
+ [&pBundle](const std::unique_ptr<Bundle>& rxBundle) { return rxBundle.get() == pBundle; });
+ if (it != rList.end())
+ rList.erase( it );
+ }
+ rList.push_back( rBundle.Clone() );
+ return rList.back().get();
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/elements.hxx b/filter/source/graphicfilter/icgm/elements.hxx
new file mode 100644
index 000000000..3f4bd710a
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/elements.hxx
@@ -0,0 +1,136 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include "bundles.hxx"
+#include "cgmtypes.hxx"
+#include <vector>
+#include <map>
+
+#define nBackGroundColor aColorTable[ 0 ]
+
+typedef ::std::vector< std::unique_ptr<Bundle> > BundleList;
+
+class CGMElements
+{
+ void ImplInsertHatch( sal_Int32 Key, int Style, tools::Long Distance, tools::Long Angle );
+ public:
+ tools::Long nMetaFileVersion;
+
+ sal_uInt32 nIntegerPrecision; // maybe 1, 2, 4 Bytes
+ sal_uInt32 nIndexPrecision; // " " "
+ RealPrecision eRealPrecision;
+ sal_uInt32 nRealSize; // maybe 4 or 8 bytes
+ sal_uInt32 nColorPrecision; // " " "
+ sal_uInt32 nColorIndexPrecision;// " " "
+
+ ScalingMode eScalingMode;
+ double nScalingFactor;
+
+ VDCType eVDCType; // Integer / Real
+ sal_uInt32 nVDCIntegerPrecision;
+ RealPrecision eVDCRealPrecision;
+ sal_uInt32 nVDCRealSize;
+ FloatRect aVDCExtent;
+ FloatRect aVDCExtentMaximum;
+
+ DeviceViewPortMode eDeviceViewPortMode;
+ double nDeviceViewPortScale;
+ DeviceViewPortMap eDeviceViewPortMap;
+ DeviceViewPortMapH eDeviceViewPortMapH;
+ DeviceViewPortMapV eDeviceViewPortMapV;
+ FloatRect aDeviceViewPort;
+
+ double nMitreLimit;
+
+ ClipIndicator eClipIndicator;
+ FloatRect aClipRect;
+
+ ColorSelectionMode eColorSelectionMode;
+ sal_uInt32 nColorMaximumIndex; // default 63
+ sal_uInt32 nLatestColorMaximumIndex; // default 63
+ sal_Int8 aColorTableEntryIs[ 256 ];
+ sal_uInt32 aColorTable[ 256 ];
+ sal_uInt32 aLatestColorTable[ 256 ];
+ sal_uInt32 nColorValueExtent[ 8 ]; // RGB, CMYK
+
+ // ASPECT SOURCE FLAGS
+ sal_uInt32 nAspectSourceFlags; // bit = 0 -> INDIVIDUAL
+ // 1 -> BUNDLED
+
+ LineBundle* pLineBundle; // Pointer to the current LineBundleIndex
+ LineBundle aLineBundle;
+ BundleList aLineList;
+ SpecMode eLineWidthSpecMode;
+ LineCapType eLineCapType;
+ LineJoinType eLineJoinType;
+
+ MarkerBundle* pMarkerBundle; // Pointer to the current MarkerBundleIndex
+ MarkerBundle aMarkerBundle;
+ BundleList aMarkerList;
+ SpecMode eMarkerSizeSpecMode;
+
+ EdgeBundle* pEdgeBundle; // Pointer to the current EdgeBundleIndex
+ EdgeBundle aEdgeBundle;
+ BundleList aEdgeList;
+ EdgeVisibility eEdgeVisibility;
+ SpecMode eEdgeWidthSpecMode;
+
+ TextBundle* pTextBundle; // Pointer to the current TextBundleIndex
+ TextBundle aTextBundle;
+ BundleList aTextList;
+ double nCharacterHeight;
+ double nCharacterOrientation[ 4 ];
+ UnderlineMode eUnderlineMode;
+ sal_uInt32 nUnderlineColor;
+ TextPath eTextPath;
+ TextAlignmentH eTextAlignmentH;
+ TextAlignmentV eTextAlignmentV;
+ double nTextAlignmentHCont;
+ double nTextAlignmentVCont;
+ tools::Long nCharacterSetIndex;
+ tools::Long nAlternateCharacterSetIndex;
+ CharacterCodingA eCharacterCodingA;
+ CGMFList aFontList;
+
+ FillBundle* pFillBundle; // Pointer to the current EdgeBundleIndex
+ FillBundle aFillBundle;
+ BundleList aFillList;
+ FloatPoint aFillRefPoint;
+ ::std::map<sal_uInt32, HatchEntry>
+ maHatchMap;
+
+ Transparency eTransparency;
+
+ sal_uInt32 nAuxiliaryColor;
+
+ // Delimiter Counts -> which will be increased by each 'begin' operation
+ // and decreased by each 'end' operation
+ bool bSegmentCount;
+ explicit CGMElements();
+ ~CGMElements();
+ CGMElements& operator=( const CGMElements& );
+ void Init();
+ static Bundle* GetBundleIndex( tools::Long nIndex, BundleList&, Bundle& );
+ static Bundle* GetBundle( BundleList& rList, tools::Long nIndex );
+ static Bundle* InsertBundle( BundleList&, Bundle& );
+ static void CopyAllBundles( const BundleList& Source, BundleList& Dest );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/graphicfilter/icgm/outact.hxx b/filter/source/graphicfilter/icgm/outact.hxx
new file mode 100644
index 000000000..b06fffda8
--- /dev/null
+++ b/filter/source/graphicfilter/icgm/outact.hxx
@@ -0,0 +1,108 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/document/XActionLockable.hpp>
+#include <com/sun/star/drawing/XDrawPages.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+
+
+#define CGM_OUTACT_MAX_GROUP_LEVEL 64
+
+#include "cgm.hxx"
+#include <tools/poly.hxx>
+#include <array>
+#include <memory>
+
+class CGM;
+class CGMBitmapDescriptor;
+
+class CGMImpressOutAct
+{
+ sal_uInt16 mnCurrentPage; // defaulted to zero
+
+ sal_uInt32 mnGroupActCount; // grouping
+ sal_uInt32 mnGroupLevel;
+ std::array<sal_uInt32, CGM_OUTACT_MAX_GROUP_LEVEL>
+ maGroupLevel;
+
+ std::vector<PolyFlags> maFlags;
+ std::vector<Point> maPoints;
+ tools::PolyPolygon maPolyPolygon;
+ std::unique_ptr<css::awt::Gradient>
+ mpGradient;
+
+ CGM* mpCGM;
+
+ css::uno::Reference< css::drawing::XDrawPages > maXDrawPages;
+ css::uno::Reference< css::drawing::XDrawPage > maXDrawPage;
+
+ css::uno::Reference< css::lang::XMultiServiceFactory > maXMultiServiceFactory;
+ css::uno::Reference< css::drawing::XShape > maXShape;
+
+ css::uno::Reference< css::beans::XPropertySet > maXPropSet;
+ css::uno::Reference< css::drawing::XShapes > maXShapes;
+ std::vector<css::uno::Reference<css::document::XActionLockable>> maLockedNewXShapes;
+
+ sal_uInt32 nFinalTextCount;
+
+ bool ImplCreateShape( const OUString& rType );
+ bool ImplInitPage();
+ void ImplSetOrientation( FloatPoint const & RefPoint, double Orientation );
+ void ImplSetLineBundle();
+ void ImplSetFillBundle();
+ void ImplSetTextBundle( const css::uno::Reference< css::beans::XPropertySet > & );
+public:
+ CGMImpressOutAct( CGM&, const css::uno::Reference< css::frame::XModel > & );
+ ~CGMImpressOutAct();
+ void InsertPage();
+ void BeginGroup();
+ void EndGroup();
+ void EndGrouping();
+ void DrawRectangle( FloatRect const & );
+ void DrawEllipse( FloatPoint const & center, FloatPoint const &, double& Orientation );
+ void DrawEllipticalArc( FloatPoint const & center, FloatPoint const & size, double& orientation,
+ sal_uInt32 etype, double& startangle, double& endangle );
+ void DrawBitmap( CGMBitmapDescriptor* );
+ void DrawPolygon( tools::Polygon& );
+ void DrawPolyLine( tools::Polygon& );
+ void DrawPolybezier( tools::Polygon& );
+ void DrawPolyPolygon( tools::PolyPolygon const & );
+ void DrawText(css::awt::Point const & TextRectPos, css::awt::Size const & TextRectSize, const OUString& rString, FinalFlag);
+ void AppendText( const char* String );
+
+ void FirstOutPut() { mpCGM->mbFirstOutPut = false; } ;
+ void BeginFigure();
+ void CloseRegion();
+ void NewRegion();
+ void EndFigure();
+ void RegPolyLine( tools::Polygon const &, bool bReverse = false );
+ void SetGradientOffset( tools::Long nHorzOfs, tools::Long nVertOfs );
+ void SetGradientAngle( tools::Long nAngle );
+ void SetGradientDescriptor( sal_uInt32 nColorFrom, sal_uInt32 nColorTo );
+ void SetGradientStyle( sal_uInt32 nStyle );
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/countryid.cxx b/filter/source/msfilter/countryid.cxx
new file mode 100644
index 000000000..9ad504ab3
--- /dev/null
+++ b/filter/source/msfilter/countryid.cxx
@@ -0,0 +1,319 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <filter/msfilter/countryid.hxx>
+
+#include <algorithm>
+#include <sal/macros.h>
+
+
+namespace msfilter {
+
+// Mapping table ==============================================================
+
+namespace {
+
+
+/** Table entry for Windows country ID <-> language type conversion.
+
+ The first member is the Windows country ID, as defined in the header.
+
+ The second member contains the corresponding language type for each country
+ ID. This must be a full language, not only the primary language type.
+
+ The last bool flag defines, if the sub language type should be evaluated to
+ find the country ID from a language. If not set, all languages map to the
+ country which contain the given primary language type.
+
+ Example: The language entry (COUNTRY_USA,LANGUAGE_ENGLISH_US,false) maps
+ the country ID for USA to the language LANGUAGE_ENGLISH_US. The clear sub
+ language flag causes all english languages LANGUAGE_ENGLISH_*** to map to
+ this country ID by default. To map the special case LANGUAGE_ENGLISH_EIRE
+ to the country ID COUNTRY_IRELAND, the sub language flag must be set in the
+ respective table entry, here (COUNTRY_IRELAND,LANGUAGE_ENGLISH_EIRE,true).
+ */
+struct CountryEntry
+{
+ CountryId meCountry; /// Windows country ID.
+ LanguageType meLanguage; /// Corresponding language type.
+ bool mbUseSubLang; /// false = Primary only, true = Primary and sub language.
+};
+
+
+/** Table for Windows country ID <-> language type conversion.
+
+ To map the same language to different country IDs, some of the entries
+ should contain a set sub language flag (see description of CountryEntry).
+ All table entries with a set flag take priority over the entry with the
+ same primary language, but cleared sub language flag, regardless of the
+ position in the table.
+
+ To map different languages to the same country ID, several entries with the
+ same country ID may be inserted. In this case the conversion to a language
+ is done with the first found entry (starting from top) containing the given
+ country ID.
+
+ For now all entries are sorted by country ID, but this is not required.
+ */
+const CountryEntry pTable[] =
+{
+ { COUNTRY_USA, LANGUAGE_ENGLISH_US, false },
+ { COUNTRY_DOMINICAN_REPUBLIC, LANGUAGE_SPANISH_DOMINICAN_REPUBLIC, true },
+ { COUNTRY_JAMAICA, LANGUAGE_ENGLISH_JAMAICA, true },
+ { COUNTRY_PUERTO_RICO, LANGUAGE_SPANISH_PUERTO_RICO, true },
+ { COUNTRY_TRINIDAD_Y_TOBAGO, LANGUAGE_ENGLISH_TRINIDAD, true },
+ { COUNTRY_CANADA, LANGUAGE_ENGLISH_CAN, true },
+ { COUNTRY_CANADA, LANGUAGE_FRENCH_CANADIAN, true },
+ { COUNTRY_RUSSIA, LANGUAGE_RUSSIAN, false },
+ { COUNTRY_KAZAKHSTAN, LANGUAGE_KAZAKH, false },
+ { COUNTRY_TATARSTAN, LANGUAGE_TATAR, false },
+ { COUNTRY_EGYPT, LANGUAGE_ARABIC_EGYPT, true },
+ { COUNTRY_SOUTH_AFRICA, LANGUAGE_AFRIKAANS, false },
+ { COUNTRY_SOUTH_AFRICA, LANGUAGE_ENGLISH_SAFRICA, true },
+ { COUNTRY_SOUTH_AFRICA, LANGUAGE_TSONGA, false },
+ { COUNTRY_SOUTH_AFRICA, LANGUAGE_VENDA, false },
+ { COUNTRY_SOUTH_AFRICA, LANGUAGE_XHOSA, false },
+ { COUNTRY_SOUTH_AFRICA, LANGUAGE_ZULU, false },
+ { COUNTRY_GREECE, LANGUAGE_GREEK, false },
+ { COUNTRY_NETHERLANDS, LANGUAGE_DUTCH, false },
+ { COUNTRY_NETHERLANDS, LANGUAGE_FRISIAN_NETHERLANDS, false },
+ { COUNTRY_BELGIUM, LANGUAGE_DUTCH_BELGIAN, true },
+ { COUNTRY_BELGIUM, LANGUAGE_FRENCH_BELGIAN, true },
+ { COUNTRY_FRANCE, LANGUAGE_FRENCH, false },
+ { COUNTRY_SPAIN, LANGUAGE_SPANISH_MODERN, false },
+ { COUNTRY_SPAIN, LANGUAGE_SPANISH_DATED, false },
+ { COUNTRY_SPAIN, LANGUAGE_CATALAN, false },
+ { COUNTRY_SPAIN, LANGUAGE_BASQUE, false },
+ { COUNTRY_SPAIN, LANGUAGE_GALICIAN, false },
+ { COUNTRY_HUNGARY, LANGUAGE_HUNGARIAN, false },
+ { COUNTRY_ITALY, LANGUAGE_ITALIAN, false },
+ { COUNTRY_ROMANIA, LANGUAGE_ROMANIAN, false },
+ { COUNTRY_SWITZERLAND, LANGUAGE_GERMAN_SWISS, true },
+ { COUNTRY_SWITZERLAND, LANGUAGE_FRENCH_SWISS, true },
+ { COUNTRY_SWITZERLAND, LANGUAGE_ITALIAN_SWISS, true },
+ { COUNTRY_SWITZERLAND, LANGUAGE_RHAETO_ROMAN, false },
+ { COUNTRY_AUSTRIA, LANGUAGE_GERMAN_AUSTRIAN, true },
+ { COUNTRY_UNITED_KINGDOM, LANGUAGE_ENGLISH_UK, true },
+ { COUNTRY_UNITED_KINGDOM, LANGUAGE_GAELIC_SCOTLAND, true },
+ { COUNTRY_UNITED_KINGDOM, LANGUAGE_WELSH, false },
+ { COUNTRY_DENMARK, LANGUAGE_DANISH, false },
+ { COUNTRY_SWEDEN, LANGUAGE_SWEDISH, false },
+ { COUNTRY_SWEDEN, LANGUAGE_SAMI_LAPPISH, false },
+ { COUNTRY_NORWAY, LANGUAGE_NORWEGIAN_BOKMAL, false },
+ { COUNTRY_POLAND, LANGUAGE_POLISH, false },
+ { COUNTRY_GERMANY, LANGUAGE_GERMAN, false },
+ { COUNTRY_GERMANY, LANGUAGE_SORBIAN, false },
+ { COUNTRY_PERU, LANGUAGE_SPANISH_PERU, true },
+ { COUNTRY_MEXICO, LANGUAGE_SPANISH_MEXICAN, true },
+ { COUNTRY_ARGENTINA, LANGUAGE_SPANISH_ARGENTINA, true },
+ { COUNTRY_BRAZIL, LANGUAGE_PORTUGUESE_BRAZILIAN, true },
+ { COUNTRY_CHILE, LANGUAGE_SPANISH_CHILE, true },
+ { COUNTRY_COLOMBIA, LANGUAGE_SPANISH_COLOMBIA, true },
+ { COUNTRY_VENEZUELA, LANGUAGE_SPANISH_VENEZUELA, true },
+ { COUNTRY_MALAYSIA, LANGUAGE_MALAY_MALAYSIA, false },
+ { COUNTRY_AUSTRALIA, LANGUAGE_ENGLISH_AUS, true },
+ { COUNTRY_INDONESIA, LANGUAGE_INDONESIAN, false },
+ { COUNTRY_PHILIPPINES, LANGUAGE_ENGLISH_PHILIPPINES, true },
+ { COUNTRY_NEW_ZEALAND, LANGUAGE_MAORI_NEW_ZEALAND, false },
+ { COUNTRY_NEW_ZEALAND, LANGUAGE_ENGLISH_NZ, true },
+ { COUNTRY_SINGAPORE, LANGUAGE_CHINESE_SINGAPORE, true },
+ { COUNTRY_THAILAND, LANGUAGE_THAI, false },
+ { COUNTRY_JAPAN, LANGUAGE_JAPANESE, false },
+ { COUNTRY_SOUTH_KOREA, LANGUAGE_KOREAN, false },
+ { COUNTRY_VIET_NAM, LANGUAGE_VIETNAMESE, false },
+ { COUNTRY_PR_CHINA, LANGUAGE_CHINESE_SIMPLIFIED, false },
+ { COUNTRY_TIBET, LANGUAGE_TIBETAN, false },
+ { COUNTRY_TURKEY, LANGUAGE_TURKISH, false },
+ { COUNTRY_INDIA, LANGUAGE_HINDI, false },
+ { COUNTRY_INDIA, LANGUAGE_URDU_INDIA, true },
+ { COUNTRY_INDIA, LANGUAGE_PUNJABI, false },
+ { COUNTRY_INDIA, LANGUAGE_GUJARATI, false },
+ { COUNTRY_INDIA, LANGUAGE_ODIA, false },
+ { COUNTRY_INDIA, LANGUAGE_TAMIL, false },
+ { COUNTRY_INDIA, LANGUAGE_TELUGU, false },
+ { COUNTRY_INDIA, LANGUAGE_KANNADA, false },
+ { COUNTRY_INDIA, LANGUAGE_MALAYALAM, false },
+ { COUNTRY_INDIA, LANGUAGE_ASSAMESE, false },
+ { COUNTRY_INDIA, LANGUAGE_MARATHI, false },
+ { COUNTRY_INDIA, LANGUAGE_SANSKRIT, false },
+ { COUNTRY_INDIA, LANGUAGE_KONKANI, false },
+ { COUNTRY_INDIA, LANGUAGE_MANIPURI, false },
+ { COUNTRY_INDIA, LANGUAGE_SINDHI, false },
+ { COUNTRY_INDIA, LANGUAGE_KASHMIRI, false },
+ { COUNTRY_PAKISTAN, LANGUAGE_URDU_PAKISTAN, false },
+ { COUNTRY_MYANMAR, LANGUAGE_BURMESE, false },
+ { COUNTRY_MOROCCO, LANGUAGE_ARABIC_MOROCCO, true },
+ { COUNTRY_ALGERIA, LANGUAGE_ARABIC_ALGERIA, true },
+ { COUNTRY_TUNISIA, LANGUAGE_ARABIC_TUNISIA, true },
+ { COUNTRY_LIBYA, LANGUAGE_ARABIC_LIBYA, true },
+ { COUNTRY_SENEGAL, LANGUAGE_FRENCH_SENEGAL, true },
+ { COUNTRY_MALI, LANGUAGE_FRENCH_MALI, true },
+ { COUNTRY_COTE_D_IVOIRE, LANGUAGE_FRENCH_COTE_D_IVOIRE, true },
+ { COUNTRY_CAMEROON, LANGUAGE_FRENCH_CAMEROON, true },
+ { COUNTRY_ZAIRE, LANGUAGE_FRENCH_ZAIRE, true },
+ { COUNTRY_RWANDA, LANGUAGE_KINYARWANDA_RWANDA, false },
+ { COUNTRY_KENYA, LANGUAGE_SWAHILI, false },
+ { COUNTRY_REUNION, LANGUAGE_FRENCH_REUNION, true },
+ { COUNTRY_ZIMBABWE, LANGUAGE_ENGLISH_ZIMBABWE, true },
+ { COUNTRY_LESOTHO, LANGUAGE_SESOTHO, false },
+ { COUNTRY_BOTSWANA, LANGUAGE_TSWANA, false },
+ { COUNTRY_FAEROE_ISLANDS, LANGUAGE_FAEROESE, false },
+ { COUNTRY_PORTUGAL, LANGUAGE_PORTUGUESE, false },
+ { COUNTRY_LUXEMBOURG, LANGUAGE_GERMAN_LUXEMBOURG, true },
+ { COUNTRY_LUXEMBOURG, LANGUAGE_FRENCH_LUXEMBOURG, true },
+ { COUNTRY_IRELAND, LANGUAGE_ENGLISH_EIRE, true },
+ { COUNTRY_IRELAND, LANGUAGE_GAELIC_IRELAND, true },
+ { COUNTRY_ICELAND, LANGUAGE_ICELANDIC, false },
+ { COUNTRY_ALBANIA, LANGUAGE_ALBANIAN, false },
+ { COUNTRY_MALTA, LANGUAGE_MALTESE, false },
+ { COUNTRY_FINLAND, LANGUAGE_FINNISH, false },
+ { COUNTRY_FINLAND, LANGUAGE_SWEDISH_FINLAND, true },
+ { COUNTRY_BULGARIA, LANGUAGE_BULGARIAN, false },
+ { COUNTRY_LITHUANIA, LANGUAGE_LITHUANIAN, false },
+ { COUNTRY_LATVIA, LANGUAGE_LATVIAN, false },
+ { COUNTRY_ESTONIA, LANGUAGE_ESTONIAN, false },
+ { COUNTRY_MOLDOVA, LANGUAGE_ROMANIAN_MOLDOVA, true },
+ { COUNTRY_MOLDOVA, LANGUAGE_RUSSIAN_MOLDOVA, true },
+ { COUNTRY_ARMENIA, LANGUAGE_ARMENIAN, false },
+ { COUNTRY_BELARUS, LANGUAGE_BELARUSIAN, false },
+ { COUNTRY_MONACO, LANGUAGE_FRENCH_MONACO, true },
+ { COUNTRY_UKRAINE, LANGUAGE_UKRAINIAN, false },
+ { COUNTRY_SERBIA, LANGUAGE_SERBIAN_LATIN_SAM, false },
+ { COUNTRY_CROATIA, LANGUAGE_CROATIAN, true }, // sub type of LANGUAGE_SERBIAN
+ { COUNTRY_SLOVENIA, LANGUAGE_SLOVENIAN, false },
+ { COUNTRY_MACEDONIA, LANGUAGE_MACEDONIAN, false },
+ { COUNTRY_CZECH, LANGUAGE_CZECH, false },
+ { COUNTRY_SLOVAK, LANGUAGE_SLOVAK, false },
+ { COUNTRY_LIECHTENSTEIN, LANGUAGE_GERMAN_LIECHTENSTEIN, true },
+ { COUNTRY_BELIZE, LANGUAGE_ENGLISH_BELIZE, true },
+ { COUNTRY_GUATEMALA, LANGUAGE_SPANISH_GUATEMALA, true },
+ { COUNTRY_EL_SALVADOR, LANGUAGE_SPANISH_EL_SALVADOR, true },
+ { COUNTRY_HONDURAS, LANGUAGE_SPANISH_HONDURAS, true },
+ { COUNTRY_NICARAGUA, LANGUAGE_SPANISH_NICARAGUA, true },
+ { COUNTRY_COSTA_RICA, LANGUAGE_SPANISH_COSTARICA, true },
+ { COUNTRY_PANAMA, LANGUAGE_SPANISH_PANAMA, true },
+ { COUNTRY_BOLIVIA, LANGUAGE_SPANISH_BOLIVIA, true },
+ { COUNTRY_ECUADOR, LANGUAGE_SPANISH_ECUADOR, true },
+ { COUNTRY_PARAGUAY, LANGUAGE_SPANISH_PARAGUAY, true },
+ { COUNTRY_URUGUAY, LANGUAGE_SPANISH_URUGUAY, true },
+ { COUNTRY_BRUNEI_DARUSSALAM, LANGUAGE_MALAY_BRUNEI_DARUSSALAM, true },
+ { COUNTRY_HONG_KONG, LANGUAGE_CHINESE_HONGKONG, true },
+ { COUNTRY_MACAU, LANGUAGE_CHINESE_MACAU, true },
+ { COUNTRY_CAMBODIA, LANGUAGE_KHMER, false },
+ { COUNTRY_LAOS, LANGUAGE_LAO, false },
+ { COUNTRY_BANGLADESH, LANGUAGE_BENGALI, false },
+ { COUNTRY_TAIWAN, LANGUAGE_CHINESE_TRADITIONAL, true },
+ { COUNTRY_MALDIVES, LANGUAGE_DHIVEHI, false },
+ { COUNTRY_LEBANON, LANGUAGE_ARABIC_LEBANON, true },
+ { COUNTRY_JORDAN, LANGUAGE_ARABIC_JORDAN, true },
+ { COUNTRY_SYRIA, LANGUAGE_ARABIC_SYRIA, true },
+ { COUNTRY_IRAQ, LANGUAGE_ARABIC_IRAQ, true },
+ { COUNTRY_KUWAIT, LANGUAGE_ARABIC_KUWAIT, true },
+ { COUNTRY_SAUDI_ARABIA, LANGUAGE_ARABIC_SAUDI_ARABIA, true },
+ { COUNTRY_YEMEN, LANGUAGE_ARABIC_YEMEN, true },
+ { COUNTRY_OMAN, LANGUAGE_ARABIC_OMAN, true },
+ { COUNTRY_UAE, LANGUAGE_ARABIC_UAE, true },
+ { COUNTRY_ISRAEL, LANGUAGE_HEBREW, false },
+ { COUNTRY_BAHRAIN, LANGUAGE_ARABIC_BAHRAIN, true },
+ { COUNTRY_QATAR, LANGUAGE_ARABIC_QATAR, true },
+ { COUNTRY_MONGOLIA, LANGUAGE_MONGOLIAN_CYRILLIC_MONGOLIA, false },
+ { COUNTRY_NEPAL, LANGUAGE_NEPALI, false },
+ { COUNTRY_IRAN, LANGUAGE_FARSI, false },
+ { COUNTRY_TAJIKISTAN, LANGUAGE_TAJIK, false },
+ { COUNTRY_TURKMENISTAN, LANGUAGE_TURKMEN, false },
+ { COUNTRY_AZERBAIJAN, LANGUAGE_AZERI_LATIN, false },
+ { COUNTRY_GEORGIA, LANGUAGE_GEORGIAN, false },
+ { COUNTRY_KYRGYZSTAN, LANGUAGE_KIRGHIZ, false },
+ { COUNTRY_UZBEKISTAN, LANGUAGE_UZBEK_LATIN, false }
+};
+
+const CountryEntry * const pEnd = pTable + SAL_N_ELEMENTS( pTable );
+
+/** Predicate comparing a country ID with the member of a CountryEntry. */
+struct CountryEntryPred_Country
+{
+ CountryId meCountry;
+
+ explicit CountryEntryPred_Country( CountryId eCountry ) :
+ meCountry( eCountry ) {}
+
+ bool operator()( const CountryEntry& rCmp ) const
+ { return rCmp.meCountry == meCountry; }
+};
+
+/** Predicate comparing a language type with the member of a CountryEntry.
+
+ Compares by primary language only, if the passed CountryEntry allows it
+ (the member mbUseSubLang is cleared), otherwise by full language type. */
+struct CountryEntryPred_Language
+{
+ LanguageType meLanguage;
+
+ explicit CountryEntryPred_Language( LanguageType eLanguage ) :
+ meLanguage( eLanguage ) {}
+
+ bool operator()( const CountryEntry& rCmp ) const;
+};
+
+bool CountryEntryPred_Language::operator()( const CountryEntry& rCmp ) const
+{
+ // rCmp.mbUseSubLang==true -> compare full language type
+ // rCmp.mbUseSubLang==false -> compare primary language only
+ return rCmp.mbUseSubLang ? (meLanguage == rCmp.meLanguage) :
+ (primary(meLanguage) == primary(rCmp.meLanguage));
+}
+
+} // namespace
+
+// Country ID <-> Language type conversion ====================================
+
+CountryId ConvertLanguageToCountry( LanguageType eLanguage )
+{
+ // country of a found primary language type
+ CountryId ePrimCountry = COUNTRY_DONTKNOW;
+
+ // find an exact match and a primary-language-only match, in one pass
+ const CountryEntry* pEntry = pTable;
+ do
+ {
+ pEntry = std::find_if( pEntry, pEnd, CountryEntryPred_Language( eLanguage ) );
+ if( pEntry != pEnd )
+ {
+ if( pEntry->mbUseSubLang )
+ return pEntry->meCountry; // exact match found -> return
+ if( ePrimCountry == COUNTRY_DONTKNOW )
+ ePrimCountry = pEntry->meCountry;
+ ++pEntry; // one entry forward for next find_if() call
+ }
+ }
+ while( pEntry != pEnd );
+
+ return ePrimCountry;
+}
+
+LanguageType ConvertCountryToLanguage( CountryId eCountry )
+{
+ // just find the first occurrence of eCountry and return the language type
+ const CountryEntry* pEntry = std::find_if( pTable, pEnd, CountryEntryPred_Country( eCountry ) );
+ return (pEntry != pEnd) ? pEntry->meLanguage : LANGUAGE_DONTKNOW;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/dffpropset.cxx b/filter/source/msfilter/dffpropset.cxx
new file mode 100644
index 000000000..e6ef672b0
--- /dev/null
+++ b/filter/source/msfilter/dffpropset.cxx
@@ -0,0 +1,1360 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <algorithm>
+#include <filter/msfilter/dffpropset.hxx>
+#include <filter/msfilter/dffrecordheader.hxx>
+#include <sal/log.hxx>
+#include <svx/msdffdef.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <tools/stream.hxx>
+
+const DffPropSetEntry mso_PropSetDefaults[] = {
+
+// 0
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+
+// 64
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0 }, // DFF_Prop_LockAgainstGrouping
+
+// 128
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0x0010 }, // DFF_Prop_FitTextToShape
+
+// 192
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0 }, // DFF_Prop_gtextFStrikethrough
+
+//256
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0 }, // DFF_Prop_pictureActive
+
+// 320
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0x0039 }, // DFF_Prop_fFillOK
+
+// 384
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0xffffff }, // DFF_Prop_fillColor
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0x001c }, // DFF_Prop_fNoFillHitTest
+
+// 448
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0x001e }, // DFF_Prop_fNoLineDrawDash
+
+// 512
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0 }, // DFF_Prop_fshadowObscured
+
+// 576
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0 }, // DFF_Prop_fPerspective
+
+// 640
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0x0001 }, // DFF_Prop_fc3DLightFace
+
+// 704
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0x0016 }, // DFF_Prop_fc3DFillHarsh
+
+// 768
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0 }, // DFF_Prop_fBackground
+
+// 832
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0x0010 }, // DFF_Prop_fCalloutLengthSpecified
+
+// 896
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { true, false, false, true }, 0, 0x0001 }, // DFF_Prop_fPrint
+
+// 960
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 },
+{ { false, false, false, false }, 0, 0 }
+
+};
+
+DffPropSet::DffPropSet()
+{
+ mpPropSetEntries = reinterpret_cast< DffPropSetEntry* >( new sal_uInt8[ 1024 * sizeof( DffPropSetEntry ) ] );
+}
+
+DffPropSet::~DffPropSet()
+{
+ delete[] reinterpret_cast< sal_uInt8* >( mpPropSetEntries );
+}
+
+void DffPropSet::ReadPropSet( SvStream& rIn, bool bSetUninitializedOnly )
+{
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rIn, aHd );
+
+ if ( !bSetUninitializedOnly )
+ {
+ InitializePropSet( aHd.nRecType );
+ maOffsets.clear();
+ }
+
+ sal_uInt32 nPropCount = aHd.nRecInstance;
+
+ sal_uInt32 nComplexDataFilePos = rIn.Tell() + ( nPropCount * 6 );
+
+ const size_t nMaxPossibleRecords = rIn.remainingSize() / (sizeof(sal_uInt16) + sizeof(sal_uInt32));
+ if (nPropCount > nMaxPossibleRecords)
+ {
+ SAL_WARN("filter.ms", "Parsing error: " << nMaxPossibleRecords <<
+ " max possible entries, but " << nPropCount << " claimed, truncating");
+ nPropCount = nMaxPossibleRecords;
+ }
+
+ for (sal_uInt32 nPropNum = 0; nPropNum < nPropCount; ++nPropNum)
+ {
+ sal_uInt16 nTmp(0);
+ sal_uInt32 nContent(0);
+ rIn.ReadUInt16( nTmp )
+ .ReadUInt32( nContent );
+
+ sal_uInt32 nRecType = nTmp & 0x3fff;
+
+ if ( nRecType > 0x3ff )
+ break;
+ if ( ( nRecType & 0x3f ) == 0x3f )
+ {
+ if ( bSetUninitializedOnly )
+ {
+ sal_uInt32 nCurrentFlags = mpPropSetEntries[ nRecType ].nContent;
+ sal_uInt32 nMergeFlags = nContent;
+
+ nMergeFlags &= ( nMergeFlags >> 16 ) | 0xffff0000; // clearing low word
+ nMergeFlags &= ( ( nCurrentFlags & 0xffff0000 ) // remove already hard set
+ | ( nCurrentFlags >> 16 ) ) ^ 0xffffffff; // attributes from mergeflags
+ nCurrentFlags &= ( ( nMergeFlags & 0xffff0000 ) // apply zero master bits
+ | ( nMergeFlags >> 16 ) ) ^ 0xffffffff;
+ nCurrentFlags |= static_cast<sal_uInt16>(nMergeFlags); // apply filled master bits
+ mpPropSetEntries[ nRecType ].nContent = nCurrentFlags;
+ mpPropSetEntries[ nRecType ].nComplexIndexOrFlagsHAttr |= static_cast< sal_uInt16 >( nContent >> 16 );
+ }
+ else
+ {
+ // clear flags that have to be cleared
+ mpPropSetEntries[ nRecType ].nContent &= ( ( nContent >> 16 ) ^ 0xffffffff );
+ // set flags that have to be set
+ mpPropSetEntries[ nRecType ].nContent |= nContent;
+ mpPropSetEntries[ nRecType ].nComplexIndexOrFlagsHAttr = static_cast< sal_uInt16 >( nContent >> 16 );
+ }
+ }
+ else
+ {
+ bool bSetProperty = !bSetUninitializedOnly || ( !IsProperty( nRecType ) || !IsHardAttribute( nRecType ) );
+
+ DffPropFlags aPropFlag = { true, false, false, false };
+ if ( nTmp & 0x4000 )
+ aPropFlag.bBlip = true;
+ if ( nTmp & 0x8000 )
+ aPropFlag.bComplex = true;
+ if ( aPropFlag.bComplex && nContent && ( nComplexDataFilePos < aHd.GetRecEndFilePos() ) )
+ {
+ // normally nContent is the complete size of the complex property,
+ // but this is not always true for IMsoArrays ( what the hell is a IMsoArray ? )
+
+ // I love special treatments :-(
+ if ( ( nRecType == DFF_Prop_pVertices ) || ( nRecType == DFF_Prop_pSegmentInfo )
+ || ( nRecType == DFF_Prop_fillShadeColors ) || ( nRecType == DFF_Prop_lineDashStyle )
+ || ( nRecType == DFF_Prop_pWrapPolygonVertices ) || ( nRecType == DFF_Prop_connectorPoints )
+ || ( nRecType == DFF_Prop_Handles ) || ( nRecType == DFF_Prop_pFormulas )
+ || ( nRecType == DFF_Prop_textRectangles ) )
+ {
+ // now check if the current content size is possible, or 6 bytes too small
+ sal_uInt32 nOldPos = rIn.Tell();
+
+ sal_Int16 nNumElem(0), nNumElemReserved(0), nSize(0);
+ if (checkSeek(rIn, nComplexDataFilePos))
+ rIn.ReadInt16(nNumElem).ReadInt16(nNumElemReserved).ReadInt16(nSize);
+ if (nNumElemReserved >= nNumElem)
+ {
+ // the size of these array elements is nowhere defined,
+ // what if the size is negative ?
+ // ok, we will make it positive and shift it.
+ // for -16 this works
+ if ( nSize < 0 )
+ nSize = ( -nSize ) >> 2;
+ sal_uInt32 nDataSize = static_cast<sal_uInt32>( nSize * nNumElem );
+
+ // sometimes the content size is 6 bytes too small (array header information is missing )
+ if ( nDataSize == nContent )
+ nContent += 6;
+
+ // check if array fits into the PropertyContainer
+ if ( ( nComplexDataFilePos + nContent ) > aHd.GetRecEndFilePos() )
+ nContent = 0;
+ }
+ else
+ nContent = 0;
+ rIn.Seek( nOldPos );
+ }
+ if ( nContent )
+ {
+ if ( bSetProperty )
+ {
+ mpPropSetEntries[ nRecType ].nComplexIndexOrFlagsHAttr = static_cast< sal_uInt16 >( maOffsets.size() );
+ maOffsets.push_back( nComplexDataFilePos ); // insert the filepos of this property;
+ }
+ nComplexDataFilePos += nContent; // store filepos, that is used for the next complex property
+ }
+ else // a complex property needs content
+ aPropFlag.bSet = false; // otherwise something is wrong
+ }
+ if ( bSetProperty )
+ {
+ // tdf#130262: ignore negative values for distances (maybe this list needs to be extended)
+ // LO does not allow negative values but [MS-ODRAW] does not forbid them
+ if ( nRecType == DFF_Prop_dxWrapDistLeft || nRecType == DFF_Prop_dxWrapDistRight
+ || nRecType == DFF_Prop_dyWrapDistTop || nRecType == DFF_Prop_dyWrapDistBottom )
+ {
+ if ( static_cast<sal_Int32>(nContent) < 0 )
+ {
+ break;
+ }
+ }
+
+ mpPropSetEntries[ nRecType ].nContent = nContent;
+ mpPropSetEntries[ nRecType ].aFlags = aPropFlag;
+ }
+ }
+ }
+ aHd.SeekToEndOfRecord( rIn );
+}
+
+SvStream& ReadDffPropSet( SvStream& rIn, DffPropSet& rRec )
+{
+ rRec.ReadPropSet( rIn, false );
+ return rIn;
+}
+
+SvStream& operator|=( SvStream& rIn, DffPropSet& rRec )
+{
+ rRec.ReadPropSet( rIn, true );
+ return rIn;
+}
+
+void DffPropSet::InitializePropSet( sal_uInt16 nPropSetType ) const
+{
+ /*
+ cmc:
+ " Boolean properties are grouped in bitfields by property set; note that
+ the Boolean properties in each property set are contiguous. They are saved
+ under the property ID of the last Boolean property in the set, and are
+ placed in the value field in reverse order starting with the last property
+ in the low bit. "
+
+ e.g.
+
+ fEditedWrap
+ fBehindDocument
+ fOnDblClickNotify
+ fIsButton
+ fOneD
+ fHidden
+ fPrint
+
+ are all part of a group and all are by default false except for fPrint,
+ which equates to a default bit sequence for the group of 0000001 -> 0x1
+
+ If at a later stage word sets fBehindDocument away from the default it
+ will be done by having a property named fPrint whose bitsequence will have
+ the fBehindDocument bit set. e.g. a DFF_Prop_fPrint with value 0x200020
+ has set bit 6 on so as to enable fBehindDocument (as well as disabling
+ everything else)
+ */
+ if ( nPropSetType == DFF_msofbtOPT )
+ {
+ memcpy( mpPropSetEntries, mso_PropSetDefaults, 0x400 * sizeof( DffPropSetEntry ) );
+ }
+ else
+ {
+ memset( mpPropSetEntries, 0, 0x400 * sizeof( DffPropSetEntry ) );
+ }
+}
+
+bool DffPropSet::IsHardAttribute( sal_uInt32 nId ) const
+{
+ bool bRetValue = true;
+ nId &= 0x3ff;
+ if ( ( nId & 0x3f ) >= 48 ) // is this a flag id
+ bRetValue = (mpPropSetEntries[nId | 0x3f].nComplexIndexOrFlagsHAttr
+ & (1 << (0xf - (nId & 0xf)))) != 0;
+ else
+ bRetValue = !mpPropSetEntries[ nId ].aFlags.bSoftAttr;
+ return bRetValue;
+};
+
+sal_uInt32 DffPropSet::GetPropertyValue( sal_uInt32 nId, sal_uInt32 nDefault ) const
+{
+ nId &= 0x3ff;
+ return ( mpPropSetEntries[ nId ].aFlags.bSet ) ? mpPropSetEntries[ nId ].nContent : nDefault;
+};
+
+bool DffPropSet::GetPropertyBool( sal_uInt32 nId ) const
+{
+ sal_uInt32 nBaseId = nId | 31; // base ID to get the sal_uInt32 property value
+ sal_uInt32 nMask = 1 << (nBaseId - nId); // bit mask of the boolean property
+
+ sal_uInt32 nPropValue = GetPropertyValue( nBaseId, 0 );
+ return (nPropValue & nMask) != 0;
+}
+
+OUString DffPropSet::GetPropertyString( sal_uInt32 nId, SvStream& rStrm ) const
+{
+ sal_uInt64 const nOldPos = rStrm.Tell();
+ OUStringBuffer aBuffer;
+ sal_uInt32 nBufferSize = GetPropertyValue( nId, 0 );
+ if( (nBufferSize > 0) && SeekToContent( nId, rStrm ) )
+ {
+ sal_Int32 nStrLen = static_cast< sal_Int32 >( nBufferSize / 2 );
+ //clip initial size of buffer to something sane in case of silly length
+ //strings. If there really is a silly amount of data available it still
+ //works out ok of course
+ aBuffer.ensureCapacity(std::min(nStrLen,static_cast<sal_Int32>(8192)));
+ for( sal_Int32 nCharIdx = 0; nCharIdx < nStrLen; ++nCharIdx )
+ {
+ sal_uInt16 nChar = 0;
+ rStrm.ReadUInt16( nChar );
+ if( nChar > 0 )
+ aBuffer.append( static_cast< sal_Unicode >( nChar ) );
+ else
+ break;
+ }
+ }
+ rStrm.Seek( nOldPos );
+ return aBuffer.makeStringAndClear();
+}
+
+bool DffPropSet::SeekToContent( sal_uInt32 nRecType, SvStream& rStrm ) const
+{
+ nRecType &= 0x3ff;
+ if ( mpPropSetEntries[ nRecType ].aFlags.bSet )
+ {
+ if ( mpPropSetEntries[ nRecType ].aFlags.bComplex )
+ {
+ sal_uInt16 nIndex = mpPropSetEntries[ nRecType ].nComplexIndexOrFlagsHAttr;
+ if ( nIndex < maOffsets.size() )
+ {
+ return checkSeek(rStrm, maOffsets[nIndex]);
+ }
+ }
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/dffrecordheader.cxx b/filter/source/msfilter/dffrecordheader.cxx
new file mode 100644
index 000000000..c94bec53b
--- /dev/null
+++ b/filter/source/msfilter/dffrecordheader.cxx
@@ -0,0 +1,43 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <filter/msfilter/dffrecordheader.hxx>
+
+bool ReadDffRecordHeader(SvStream& rIn, DffRecordHeader& rRec)
+{
+ rRec.nFilePos = rIn.Tell();
+ sal_uInt16 nTmp(0);
+ rIn.ReadUInt16(nTmp);
+ rRec.nImpVerInst = nTmp;
+ rRec.nRecVer = sal::static_int_cast<sal_uInt8>(nTmp & 0x000F);
+ rRec.nRecInstance = nTmp >> 4;
+ rRec.nRecType = 0;
+ rIn.ReadUInt16(rRec.nRecType);
+ rRec.nRecLen = 0;
+ rIn.ReadUInt32(rRec.nRecLen);
+
+ // preserving overflow, optimally we would check
+ // the record size against the parent header
+ if (rRec.nRecLen > (SAL_MAX_UINT32 - rRec.nFilePos))
+ rIn.SetError(SVSTREAM_FILEFORMAT_ERROR);
+
+ return rIn.good();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/escherex.cxx b/filter/source/msfilter/escherex.cxx
new file mode 100644
index 000000000..5f84a0df7
--- /dev/null
+++ b/filter/source/msfilter/escherex.cxx
@@ -0,0 +1,5295 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "eschesdo.hxx"
+#include <o3tl/any.hxx>
+#include <o3tl/string_view.hxx>
+#include <svx/svdxcgv.hxx>
+#include <svx/svdomedia.hxx>
+#include <svx/xflftrit.hxx>
+#include <filter/msfilter/escherex.hxx>
+#include <filter/msfilter/util.hxx>
+#include <svx/unoapi.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdoashp.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/sdtfsitm.hxx>
+#include <editeng/outlobj.hxx>
+#include <utility>
+#include <vcl/graph.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <vcl/svapp.hxx>
+#include <tools/debug.hxx>
+#include <tools/stream.hxx>
+#include <tools/zcodec.hxx>
+#include <tools/urlobj.hxx>
+#include <svx/svdopath.hxx>
+#include <stdlib.h>
+#include <vcl/graphicfilter.hxx>
+#include <svx/EnhancedCustomShapeTypeNames.hxx>
+#include <svx/EnhancedCustomShapeGeometry.hxx>
+#include <svx/EnhancedCustomShapeFunctionParser.hxx>
+#include <svx/EnhancedCustomShape2d.hxx>
+#include <com/sun/star/beans/PropertyValues.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/awt/GradientStyle.hpp>
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/drawing/LineStyle.hpp>
+#include <com/sun/star/drawing/LineJoint.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/LineDash.hpp>
+#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
+#include <com/sun/star/drawing/ConnectorType.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
+#include <com/sun/star/drawing/PointSequence.hpp>
+#include <com/sun/star/drawing/FlagSequence.hpp>
+#include <com/sun/star/drawing/PolygonFlags.hpp>
+#include <com/sun/star/text/WritingMode.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
+#include <com/sun/star/drawing/ProjectionMode.hpp>
+#include <com/sun/star/text/XSimpleText.hpp>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <com/sun/star/drawing/TextFitToSizeType.hpp>
+#include <vcl/hatch.hxx>
+#include <com/sun/star/awt/FontSlant.hpp>
+#include <com/sun/star/awt/FontWeight.hpp>
+#include <com/sun/star/drawing/ColorMode.hpp>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <com/sun/star/drawing/Hatch.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/text/GraphicCrop.hpp>
+#include <unotools/ucbstreamhelper.hxx>
+#include <comphelper/string.hxx>
+#include <vcl/virdev.hxx>
+#include <rtl/crc.h>
+#include <rtl/strbuf.hxx>
+#include <sal/log.hxx>
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <osl/diagnose.h>
+
+#include <algorithm>
+#include <memory>
+
+using namespace css;
+
+EscherExContainer::EscherExContainer( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance ) :
+ rStrm ( rSt )
+{
+ rStrm.WriteUInt32( ( 0xf | ( nInstance << 4 ) ) | ( nRecType << 16 ) ).WriteUInt32( 0 );
+ nContPos = rStrm.Tell();
+}
+EscherExContainer::~EscherExContainer()
+{
+ sal_uInt32 nPos = rStrm.Tell();
+ sal_uInt32 nSize= nPos - nContPos;
+ if ( nSize )
+ {
+ rStrm.Seek( nContPos - 4 );
+ rStrm.WriteUInt32( nSize );
+ rStrm.Seek( nPos );
+ }
+}
+
+EscherExAtom::EscherExAtom( SvStream& rSt, const sal_uInt16 nRecType, const sal_uInt16 nInstance, const sal_uInt8 nVersion ) :
+ rStrm ( rSt )
+{
+ rStrm.WriteUInt32( ( nVersion | ( nInstance << 4 ) ) | ( nRecType << 16 ) ).WriteUInt32( 0 );
+ nContPos = rStrm.Tell();
+}
+EscherExAtom::~EscherExAtom()
+{
+ sal_uInt32 nPos = rStrm.Tell();
+ sal_uInt32 nSize= nPos - nContPos;
+ if ( nSize )
+ {
+ rStrm.Seek( nContPos - 4 );
+ rStrm.WriteUInt32( nSize );
+ rStrm.Seek( nPos );
+ }
+}
+
+EscherExClientRecord_Base::~EscherExClientRecord_Base()
+{
+}
+
+EscherExClientAnchor_Base::~EscherExClientAnchor_Base()
+{
+}
+
+EscherPropertyContainer::EscherPropertyContainer(
+ EscherGraphicProvider * pGraphProv, SvStream * pPiOutStrm,
+ tools::Rectangle * pBoundRect):
+ pGraphicProvider(pGraphProv),
+ pPicOutStrm(pPiOutStrm),
+ pShapeBoundRect(pBoundRect),
+ nCountCount(0),
+ nCountSize(0),
+ bHasComplexData(false)
+{
+ pSortStruct.reserve(64);
+}
+
+EscherPropertyContainer::EscherPropertyContainer()
+ : EscherPropertyContainer(nullptr, nullptr, nullptr)
+{}
+
+EscherPropertyContainer::EscherPropertyContainer(
+ EscherGraphicProvider& rGraphProv,
+ SvStream* pPiOutStrm,
+ tools::Rectangle& rBoundRect ) :
+ EscherPropertyContainer(&rGraphProv, pPiOutStrm, &rBoundRect)
+{}
+
+EscherPropertyContainer::~EscherPropertyContainer()
+{
+};
+
+void EscherPropertyContainer::AddOpt(
+ sal_uInt16 nPropID,
+ bool bBlib,
+ sal_uInt32 nSizeReduction,
+ SvMemoryStream& rStream)
+{
+ sal_uInt8 const* pBuf(static_cast<sal_uInt8 const *>(rStream.GetData()));
+ const sal_uInt64 nSize(rStream.GetSize());
+ std::vector<sal_uInt8> aBuf;
+ aBuf.reserve(nSize);
+
+ for(sal_uInt64 a(0); a < nSize; a++)
+ {
+ aBuf.push_back(*pBuf++);
+ }
+
+ sal_uInt32 nPropValue(static_cast<sal_uInt32>(nSize));
+
+ if(0 != nSizeReduction && nPropValue > nSizeReduction)
+ {
+ nPropValue -= nSizeReduction;
+ }
+
+ AddOpt(nPropID, bBlib, nPropValue, aBuf);
+}
+
+void EscherPropertyContainer::AddOpt(
+ sal_uInt16 nPropID,
+ sal_uInt32 nPropValue,
+ bool bBlib)
+{
+ AddOpt(nPropID, bBlib, nPropValue, std::vector<sal_uInt8>());
+}
+
+void EscherPropertyContainer::AddOpt(
+ sal_uInt16 nPropID,
+ const OUString& rString)
+{
+ std::vector<sal_uInt8> aBuf;
+ aBuf.reserve(rString.getLength() * 2 + 2);
+
+ for(sal_Int32 i(0); i < rString.getLength(); i++)
+ {
+ const sal_Unicode nUnicode(rString[i]);
+ aBuf.push_back(static_cast<sal_uInt8>(nUnicode));
+ aBuf.push_back(static_cast<sal_uInt8>(nUnicode >> 8));
+ }
+
+ aBuf.push_back(0);
+ aBuf.push_back(0);
+
+ AddOpt(nPropID, true, aBuf.size(), aBuf);
+}
+
+void EscherPropertyContainer::AddOpt(
+ sal_uInt16 nPropID,
+ bool bBlib,
+ sal_uInt32 nPropValue,
+ const std::vector<sal_uInt8>& rProp)
+{
+ if ( bBlib ) // bBlib is only valid when fComplex = 0
+ nPropID |= 0x4000;
+ if ( !rProp.empty() )
+ nPropID |= 0x8000; // fComplex = sal_True;
+
+ for( size_t i = 0; i < pSortStruct.size(); i++ )
+ {
+ if ( ( pSortStruct[ i ].nPropId &~0xc000 ) == ( nPropID &~0xc000 ) ) // check, whether the Property only gets replaced
+ {
+ pSortStruct[ i ].nPropId = nPropID;
+ if ( !pSortStruct[ i ].nProp.empty() )
+ {
+ nCountSize -= pSortStruct[ i ].nProp.size();
+ }
+ pSortStruct[ i ].nProp = rProp;
+ pSortStruct[ i ].nPropValue = nPropValue;
+ if ( !rProp.empty() )
+ nCountSize += rProp.size();
+ return;
+ }
+ }
+ nCountCount++;
+ nCountSize += 6;
+ pSortStruct.emplace_back();
+ pSortStruct.back().nPropId = nPropID; // insert property
+ pSortStruct.back().nProp = rProp;
+ pSortStruct.back().nPropValue = nPropValue;
+
+ if ( !rProp.empty() )
+ {
+ nCountSize += rProp.size();
+ bHasComplexData = true;
+ }
+}
+
+bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, sal_uInt32& rPropValue ) const
+{
+ EscherPropSortStruct aPropStruct;
+
+ if ( GetOpt( nPropId, aPropStruct ) )
+ {
+ rPropValue = aPropStruct.nPropValue;
+ return true;
+ }
+ return false;
+}
+
+bool EscherPropertyContainer::GetOpt( sal_uInt16 nPropId, EscherPropSortStruct& rPropValue ) const
+{
+ for( size_t i = 0; i < pSortStruct.size(); i++ )
+ {
+ if ( ( pSortStruct[ i ].nPropId &~0xc000 ) == ( nPropId &~0xc000 ) )
+ {
+ rPropValue = pSortStruct[ i ];
+ return true;
+ }
+ }
+ return false;
+}
+
+const EscherProperties & EscherPropertyContainer::GetOpts() const
+{
+ return pSortStruct;
+}
+
+extern "C" {
+
+static int EscherPropSortFunc( const void* p1, const void* p2 )
+{
+ sal_Int16 nID1 = static_cast<EscherPropSortStruct const *>(p1)->nPropId &~0xc000;
+ sal_Int16 nID2 = static_cast<EscherPropSortStruct const *>(p2)->nPropId &~0xc000;
+
+ if( nID1 < nID2 )
+ return -1;
+ else if( nID1 > nID2 )
+ return 1;
+ else
+ return 0;
+}
+
+}
+
+void EscherPropertyContainer::Commit( SvStream& rSt, sal_uInt16 nVersion, sal_uInt16 nRecType )
+{
+ rSt.WriteUInt16( ( nCountCount << 4 ) | ( nVersion & 0xf ) ).WriteUInt16( nRecType ).WriteUInt32( nCountSize );
+ if ( pSortStruct.empty() )
+ return;
+
+ qsort( pSortStruct.data(), pSortStruct.size(), sizeof( EscherPropSortStruct ), EscherPropSortFunc );
+
+ for ( size_t i = 0; i < pSortStruct.size(); i++ )
+ {
+ sal_uInt32 nPropValue = pSortStruct[ i ].nPropValue;
+ sal_uInt16 nPropId = pSortStruct[ i ].nPropId;
+
+ rSt.WriteUInt16( nPropId )
+ .WriteUInt32( nPropValue );
+ }
+ if ( bHasComplexData )
+ {
+ for ( size_t i = 0; i < pSortStruct.size(); i++ )
+ {
+ if ( !pSortStruct[ i ].nProp.empty() )
+ rSt.WriteBytes(
+ pSortStruct[i].nProp.data(),
+ pSortStruct[i].nProp.size());
+ }
+ }
+}
+
+bool EscherPropertyContainer::IsFontWork() const
+{
+ sal_uInt32 nTextPathFlags = 0;
+ GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
+ return ( nTextPathFlags & 0x4000 ) != 0;
+}
+
+sal_uInt32 EscherPropertyContainer::ImplGetColor( const sal_uInt32 nSOColor, bool bSwap )
+{
+ if ( bSwap )
+ {
+ sal_uInt32 nColor = nSOColor & 0xff00; // green
+ nColor |= static_cast<sal_uInt8>(nSOColor) << 16; // red
+ nColor |= static_cast<sal_uInt8>( nSOColor >> 16 ); // blue
+ return nColor;
+ }
+ else
+ return nSOColor & 0xffffff;
+}
+
+sal_uInt32 EscherPropertyContainer::GetGradientColor(
+ const awt::Gradient* pGradient,
+ sal_uInt32 nStartColor )
+{
+ sal_uInt32 nIntensity = 100;
+ Color aColor;
+
+ if ( pGradient )
+ {
+ if ( nStartColor & 1 )
+ {
+ nIntensity = pGradient->StartIntensity;
+ aColor = Color(ColorTransparency, pGradient->StartColor);
+ }
+ else
+ {
+ nIntensity = pGradient->EndIntensity;
+ aColor = Color(ColorTransparency, pGradient->EndColor);
+ }
+ }
+ sal_uInt32 nRed = ( aColor.GetRed() * nIntensity ) / 100;
+ sal_uInt32 nGreen = ( ( aColor.GetGreen() * nIntensity ) / 100 ) << 8;
+ sal_uInt32 nBlue = ( ( aColor.GetBlue() * nIntensity ) / 100 ) << 16;
+ return nRed | nGreen | nBlue;
+}
+
+void EscherPropertyContainer::CreateGradientProperties(
+ const awt::Gradient & rGradient )
+{
+ sal_uInt32 nFillType = ESCHER_FillShadeScale;
+ sal_uInt32 nAngle = 0;
+ sal_uInt32 nFillFocus = 0;
+ sal_uInt32 nFillLR = 0;
+ sal_uInt32 nFillTB = 0;
+ sal_uInt32 nFirstColor = 0;
+ bool bWriteFillTo = false;
+
+ switch ( rGradient.Style )
+ {
+ case awt::GradientStyle_LINEAR :
+ case awt::GradientStyle_AXIAL :
+ {
+ nFillType = ESCHER_FillShadeScale;
+ nAngle = (rGradient.Angle * 0x10000) / 10;
+ nFillFocus = (sal::static_int_cast<int>(rGradient.Style) ==
+ sal::static_int_cast<int>(GradientStyle::Linear)) ? 0 : 50;
+ }
+ break;
+ case awt::GradientStyle_RADIAL :
+ case awt::GradientStyle_ELLIPTICAL :
+ case awt::GradientStyle_SQUARE :
+ case awt::GradientStyle_RECT :
+ {
+ nFillLR = (rGradient.XOffset * 0x10000) / 100;
+ nFillTB = (rGradient.YOffset * 0x10000) / 100;
+ if ( ((nFillLR > 0) && (nFillLR < 0x10000)) || ((nFillTB > 0) && (nFillTB < 0x10000)) )
+ nFillType = ESCHER_FillShadeShape;
+ else
+ nFillType = ESCHER_FillShadeCenter;
+ nFirstColor = 1;
+ bWriteFillTo = true;
+ }
+ break;
+ case awt::GradientStyle::GradientStyle_MAKE_FIXED_SIZE : break;
+ }
+ AddOpt( ESCHER_Prop_fillType, nFillType );
+ AddOpt( ESCHER_Prop_fillAngle, nAngle );
+ AddOpt( ESCHER_Prop_fillColor, GetGradientColor( &rGradient, nFirstColor ) );
+ AddOpt( ESCHER_Prop_fillBackColor, GetGradientColor( &rGradient, nFirstColor ^ 1 ) );
+ AddOpt( ESCHER_Prop_fillFocus, nFillFocus );
+ if ( bWriteFillTo )
+ {
+ AddOpt( ESCHER_Prop_fillToLeft, nFillLR );
+ AddOpt( ESCHER_Prop_fillToTop, nFillTB );
+ AddOpt( ESCHER_Prop_fillToRight, nFillLR );
+ AddOpt( ESCHER_Prop_fillToBottom, nFillTB );
+ }
+}
+
+void EscherPropertyContainer::CreateGradientProperties(
+ const uno::Reference<beans::XPropertySet> & rXPropSet , bool bTransparentGradient)
+{
+ uno::Any aAny;
+ awt::Gradient const * pGradient = nullptr;
+
+ sal_uInt32 nFillType = ESCHER_FillShadeScale;
+ sal_Int32 nAngle = 0;
+ sal_uInt32 nFillFocus = 0;
+ sal_uInt32 nFillLR = 0;
+ sal_uInt32 nFillTB = 0;
+ sal_uInt32 nFirstColor = 0;// like the control var nChgColors in import logic
+ bool bWriteFillTo = false;
+
+ // Transparency gradient: Means the third setting in transparency page is set
+ if (bTransparentGradient && EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, "FillTransparenceGradient" ) )
+ {
+ pGradient = o3tl::doAccess<awt::Gradient>(aAny);
+
+ uno::Any aAnyTemp;
+ if ( EscherPropertyValueHelper::GetPropertyValue(
+ aAnyTemp, rXPropSet, "FillStyle" ) )
+ {
+ drawing::FillStyle eFS;
+ if ( ! ( aAnyTemp >>= eFS ) )
+ eFS = drawing::FillStyle_SOLID;
+ // solid and transparency
+ if ( eFS == drawing::FillStyle_SOLID)
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue(
+ aAnyTemp, rXPropSet, "FillColor" ) )
+ {
+ const_cast<awt::Gradient *>(pGradient)->StartColor = ImplGetColor( *o3tl::doAccess<sal_uInt32>(aAnyTemp), false );
+ const_cast<awt::Gradient *>(pGradient)->EndColor = ImplGetColor( *o3tl::doAccess<sal_uInt32>(aAnyTemp), false );
+ }
+ }
+ // gradient and transparency.
+ else if( eFS == drawing::FillStyle_GRADIENT )
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, "FillGradient" ) )
+ pGradient = o3tl::doAccess<awt::Gradient>(aAny);
+ }
+ }
+
+ }
+ // Not transparency gradient
+ else if ( EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, "FillGradient" ) )
+ {
+ pGradient = o3tl::doAccess<awt::Gradient>(aAny);
+ }
+
+ if ( pGradient )
+ {
+ switch ( pGradient->Style )
+ {
+ case awt::GradientStyle_LINEAR :
+ case awt::GradientStyle_AXIAL :
+ {
+ nFillType = ESCHER_FillShadeScale;
+ nAngle = pGradient->Angle;
+ while ( nAngle > 0 ) nAngle -= 3600;
+ while ( nAngle <= -3600 ) nAngle += 3600;
+ // Value of the real number = Integral + (Fractional / 65536.0)
+ nAngle = ( nAngle * 0x10000) / 10;
+
+ nFillFocus = (pGradient->Style == awt::GradientStyle_LINEAR) ?
+ ( pGradient->XOffset + pGradient->YOffset )/2 : -50;
+ if( !nFillFocus )
+ nFirstColor=nFirstColor ^ 1;
+ if ( !nAngle )
+ nFirstColor=nFirstColor ^ 1;
+ }
+ break;
+ case awt::GradientStyle_RADIAL :
+ case awt::GradientStyle_ELLIPTICAL :
+ case awt::GradientStyle_SQUARE :
+ case awt::GradientStyle_RECT :
+ {
+ // according to the import logic and rect type fill** value
+ nFillLR = (pGradient->XOffset * 0x10000) / 100;
+ nFillTB = (pGradient->YOffset * 0x10000) / 100;
+ if ( ((nFillLR > 0) && (nFillLR < 0x10000)) || ((nFillTB > 0) && (nFillTB < 0x10000)) )
+ nFillType = ESCHER_FillShadeShape;
+ else
+ nFillType = ESCHER_FillShadeCenter;
+ nFirstColor = 1;
+ bWriteFillTo = true;
+ }
+ break;
+ default: break;
+ }
+ }
+
+ AddOpt( ESCHER_Prop_fillType, nFillType );
+ AddOpt( ESCHER_Prop_fillAngle, nAngle );
+ AddOpt( ESCHER_Prop_fillColor, GetGradientColor( pGradient, nFirstColor ) );
+ AddOpt( ESCHER_Prop_fillBackColor, GetGradientColor( pGradient, nFirstColor ^ 1 ) );
+ AddOpt( ESCHER_Prop_fillFocus, nFillFocus );
+ if ( bWriteFillTo )
+ {
+ // according to rect type fillTo** value
+ if(nFillLR)
+ {
+ AddOpt( ESCHER_Prop_fillToLeft, nFillLR );
+ AddOpt( ESCHER_Prop_fillToRight, nFillLR );
+ }
+ if(nFillTB)
+ {
+ AddOpt( ESCHER_Prop_fillToTop, nFillTB );
+ AddOpt( ESCHER_Prop_fillToBottom, nFillTB );
+ }
+ }
+
+ // Transparency gradient
+ if (bTransparentGradient && EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, "FillTransparenceGradient" ) )
+ {
+ pGradient = o3tl::doAccess<awt::Gradient>(aAny);
+ if ( pGradient )
+ {
+ sal_uInt32 nBlue = GetGradientColor( pGradient, nFirstColor ) >> 16;
+ AddOpt( ESCHER_Prop_fillOpacity,( ( 100 - ( nBlue * 100 / 255 ) ) << 16 ) / 100 );
+ nBlue = GetGradientColor( pGradient, nFirstColor ^ 1 ) >>16 ;
+ AddOpt( ESCHER_Prop_fillBackOpacity,( ( 100 - ( nBlue * 100 / 255 ) ) << 16 )/ 100 );
+ }
+ }
+}
+
+void EscherPropertyContainer::CreateFillProperties(
+ const uno::Reference<beans::XPropertySet> & rXPropSet,
+ bool bEdge , const uno::Reference<drawing::XShape> & rXShape )
+{
+ if ( rXShape.is() )
+ {
+ SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rXShape);
+ if ( pObj )
+ {
+ const SfxItemSet& aAttr( pObj->GetMergedItemSet() );
+ // transparency with gradient. Means the third setting in transparency page is set
+ bool bTransparentGradient = ( aAttr.GetItemState( XATTR_FILLFLOATTRANSPARENCE ) == SfxItemState::SET ) &&
+ aAttr.Get( XATTR_FILLFLOATTRANSPARENCE ).IsEnabled();
+ CreateFillProperties( rXPropSet, bEdge, bTransparentGradient );
+ }
+ }
+}
+
+void EscherPropertyContainer::CreateFillProperties(
+ const uno::Reference<beans::XPropertySet> & rXPropSet,
+ bool bEdge , bool bTransparentGradient)
+
+{
+ uno::Any aAny;
+ AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
+ AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
+ static const OUStringLiteral aPropName( u"FillStyle" );
+
+ if ( EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, aPropName ) )
+ {
+ drawing::FillStyle eFS;
+ if ( ! ( aAny >>= eFS ) )
+ eFS = drawing::FillStyle_SOLID;
+ sal_uInt32 nFillBackColor = 0;
+ switch( eFS )
+ {
+ case drawing::FillStyle_GRADIENT :
+ {
+ CreateGradientProperties( rXPropSet , bTransparentGradient );
+ AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
+ }
+ break;
+
+ case drawing::FillStyle_BITMAP :
+ {
+ CreateGraphicProperties(rXPropSet, "FillBitmap", true);
+ AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
+ AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
+ }
+ break;
+ case drawing::FillStyle_HATCH :
+ {
+ CreateGraphicProperties( rXPropSet, "FillHatch", true );
+ }
+ break;
+ case drawing::FillStyle_SOLID :
+ default:
+ {
+ if ( bTransparentGradient )
+ CreateGradientProperties( rXPropSet , bTransparentGradient );
+ else
+ {
+ beans::PropertyState ePropState = EscherPropertyValueHelper::GetPropertyState(
+ rXPropSet, aPropName );
+ if ( ePropState == beans::PropertyState_DIRECT_VALUE )
+ AddOpt( ESCHER_Prop_fillType, ESCHER_FillSolid );
+
+ if ( EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, "FillColor" ) )
+ {
+ sal_uInt32 nFillColor = ImplGetColor( *o3tl::doAccess<sal_uInt32>(aAny) );
+ nFillBackColor = nFillColor ^ 0xffffff;
+ AddOpt( ESCHER_Prop_fillColor, nFillColor );
+ }
+ AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
+ AddOpt( ESCHER_Prop_fillBackColor, nFillBackColor );
+ }
+ break;
+ }
+ case drawing::FillStyle_NONE :
+ AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
+ break;
+ }
+ if ( eFS != drawing::FillStyle_NONE )
+ {
+ sal_uInt16 nTransparency = ( EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, "FillTransparence", true ) )
+ ? *o3tl::doAccess<sal_Int16>(aAny) : 0;
+ if ( nTransparency )
+ AddOpt( ESCHER_Prop_fillOpacity, ( ( 100 - nTransparency ) << 16 ) / 100 );
+ }
+ }
+ CreateLineProperties( rXPropSet, bEdge );
+}
+
+void EscherPropertyContainer::CreateTextProperties(
+ const uno::Reference< beans::XPropertySet > & rXPropSet, sal_uInt32 nTextId,
+ const bool bIsCustomShape, const bool bIsTextFrame )
+{
+ uno::Any aAny;
+ text::WritingMode eWM( text::WritingMode_LR_TB );
+ drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP );
+ drawing::TextHorizontalAdjust eHA( drawing::TextHorizontalAdjust_LEFT );
+
+ sal_Int32 nLeft ( 0 );
+ sal_Int32 nTop ( 0 );
+ sal_Int32 nRight ( 0 );
+ sal_Int32 nBottom ( 0 );
+
+ // used with normal shapes:
+ bool bAutoGrowWidth ( false );
+ const bool bAutoGrowHeight ( false ); //#ii63936 not setting autogrowheight, because minframeheight would be ignored
+ // used with ashapes:
+ bool bWordWrap ( false );
+ bool bAutoGrowSize ( false );
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextWritingMode", true ) )
+ aAny >>= eWM;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextVerticalAdjust", true ) )
+ aAny >>= eVA;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextHorizontalAdjust", true ) )
+ aAny >>= eHA;
+ if ( bIsCustomShape )
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextWordWrap" ) )
+ aAny >>= bWordWrap;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextAutoGrowHeight", true ) )
+ aAny >>= bAutoGrowSize;
+ }
+ else if ( bIsTextFrame )
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextAutoGrowWidth", true ) )
+ aAny >>= bAutoGrowWidth;
+
+// i63936 not setting autogrowheight, because otherwise
+// the minframeheight of the text will be ignored
+//
+// if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextAutoGrowHeight", sal_True ) )
+// aAny >>= bAutoGrowHeight;
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextLeftDistance" ) )
+ aAny >>= nLeft;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextUpperDistance" ) )
+ aAny >>= nTop;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextRightDistance" ) )
+ aAny >>= nRight;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "TextLowerDistance" ) )
+ aAny >>= nBottom;
+
+ ESCHER_AnchorText eAnchor = ESCHER_AnchorTop;
+ ESCHER_WrapMode eWrapMode = ESCHER_WrapSquare;
+ sal_uInt32 nTextAttr = 0x40004; // rotate text with shape
+
+ if ( eWM == text::WritingMode_TB_RL )
+ { // vertical writing
+ switch ( eHA )
+ {
+ case drawing::TextHorizontalAdjust_LEFT :
+ eAnchor = ESCHER_AnchorBottom;
+ break;
+ case drawing::TextHorizontalAdjust_CENTER :
+ eAnchor = ESCHER_AnchorMiddle;
+ break;
+ default :
+ case drawing::TextHorizontalAdjust_BLOCK :
+ case drawing::TextHorizontalAdjust_RIGHT :
+ eAnchor = ESCHER_AnchorTop;
+ break;
+ }
+ if ( eVA == drawing::TextVerticalAdjust_CENTER )
+ {
+ switch ( eAnchor )
+ {
+ case ESCHER_AnchorMiddle :
+ eAnchor = ESCHER_AnchorMiddleCentered;
+ break;
+ case ESCHER_AnchorBottom :
+ eAnchor = ESCHER_AnchorBottomCentered;
+ break;
+ default :
+ case ESCHER_AnchorTop :
+ eAnchor = ESCHER_AnchorTopCentered;
+ break;
+ }
+ }
+ if ( bIsCustomShape )
+ {
+ if ( bWordWrap )
+ eWrapMode = ESCHER_WrapSquare;
+ else
+ eWrapMode = ESCHER_WrapNone;
+ if ( bAutoGrowSize )
+ nTextAttr |= 0x20002;
+ }
+ else
+ {
+ if ( bAutoGrowHeight )
+ eWrapMode = ESCHER_WrapNone;
+ if ( bAutoGrowWidth )
+ nTextAttr |= 0x20002;
+ }
+
+ AddOpt( ESCHER_Prop_txflTextFlow, ESCHER_txflTtoBA ); // rotate text within shape by 90
+ }
+ else
+ { // normal from left to right
+ switch ( eVA )
+ {
+ case drawing::TextVerticalAdjust_CENTER :
+ eAnchor = ESCHER_AnchorMiddle;
+ break;
+
+ case drawing::TextVerticalAdjust_BOTTOM :
+ eAnchor = ESCHER_AnchorBottom;
+ break;
+
+ default :
+ case drawing::TextVerticalAdjust_TOP :
+ eAnchor = ESCHER_AnchorTop;
+ break;
+ }
+ if ( eHA == drawing::TextHorizontalAdjust_CENTER )
+ {
+ switch( eAnchor )
+ {
+ case ESCHER_AnchorMiddle :
+ eAnchor = ESCHER_AnchorMiddleCentered;
+ break;
+ case ESCHER_AnchorBottom :
+ eAnchor = ESCHER_AnchorBottomCentered;
+ break;
+ case ESCHER_AnchorTop :
+ eAnchor = ESCHER_AnchorTopCentered;
+ break;
+ default: break;
+ }
+ }
+ if ( bIsCustomShape )
+ {
+ if ( bWordWrap )
+ eWrapMode = ESCHER_WrapSquare;
+ else
+ eWrapMode = ESCHER_WrapNone;
+ if ( bAutoGrowSize )
+ nTextAttr |= 0x20002;
+ }
+ else
+ {
+ if ( bAutoGrowWidth )
+ eWrapMode = ESCHER_WrapNone;
+ if ( bAutoGrowHeight )
+ nTextAttr |= 0x20002;
+ }
+ }
+ AddOpt( ESCHER_Prop_dxTextLeft, nLeft * 360 );
+ AddOpt( ESCHER_Prop_dxTextRight, nRight * 360 );
+ AddOpt( ESCHER_Prop_dyTextTop, nTop * 360 );
+ AddOpt( ESCHER_Prop_dyTextBottom, nBottom * 360 );
+
+ AddOpt( ESCHER_Prop_WrapText, eWrapMode );
+ AddOpt( ESCHER_Prop_AnchorText, eAnchor );
+ AddOpt( ESCHER_Prop_FitTextToShape, nTextAttr );
+
+ if ( nTextId )
+ AddOpt( ESCHER_Prop_lTxid, nTextId );
+
+ // n#404221: In case of rotation we need to write the txtflTextFlow
+ // attribute too.
+ // fdo#58204: not custom shapes (TODO: other cases when it doesn't work?)
+ if (!bIsTextFrame || bIsCustomShape)
+ return;
+
+ sal_uInt16 nAngle = EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, "RotateAngle", true ) ?
+ static_cast<sal_uInt16>( ( *o3tl::doAccess<sal_Int32>(aAny) ) + 5 ) / 10 : 0;
+ if (nAngle==900)
+ {
+ AddOpt( ESCHER_Prop_txflTextFlow, ESCHER_txflBtoT );
+ }
+ if (nAngle==2700)
+ {
+ AddOpt( ESCHER_Prop_txflTextFlow, ESCHER_txflTtoBA );
+ }
+}
+
+bool EscherPropertyContainer::GetLineArrow( const bool bLineStart,
+ const uno::Reference<beans::XPropertySet> & rXPropSet,
+ ESCHER_LineEnd& reLineEnd, sal_Int32& rnArrowLength, sal_Int32& rnArrowWidth )
+{
+ const OUString sLine ( bLineStart ? OUString("LineStart") : OUString("LineEnd") );
+ const OUString sLineName ( bLineStart ? OUString("LineStartName") : OUString("LineEndName") );
+
+ bool bIsArrow = false;
+
+ uno::Any aAny;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, sLine ) )
+ {
+ tools::PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aAny ) );
+ if ( aPolyPoly.Count() && aPolyPoly[ 0 ].GetSize() )
+ {
+ bIsArrow = true;
+
+ reLineEnd = ESCHER_LineArrowEnd;
+ rnArrowLength = 1;
+ rnArrowWidth = 1;
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, sLineName ) )
+ {
+ OUString aArrowStartName = *o3tl::doAccess<OUString>(aAny);
+ sal_uInt16 nWhich = bLineStart ? sal_uInt16(XATTR_LINESTART) : sal_uInt16(XATTR_LINEEND);
+
+ // remove extra space separated number
+ sal_Int32 nPos = aArrowStartName.lastIndexOf(' ');
+ if (nPos > -1 && aArrowStartName.lastIndexOf(' ', nPos) > -1)
+ aArrowStartName = aArrowStartName.copy(0, nPos);
+
+ OUString aApiName = SvxUnogetApiNameForItem(nWhich, aArrowStartName);
+ bool bIsMapped = true;
+ if ( !aApiName.isEmpty() )
+ {
+
+ // TODO: calculate the best option for ArrowLength and ArrowWidth
+ if ( aApiName == "Arrow concave" )
+ reLineEnd = ESCHER_LineArrowStealthEnd;
+ else if ( aApiName == "Square 45" )
+ reLineEnd = ESCHER_LineArrowDiamondEnd;
+ else if ( aApiName == "Small Arrow" )
+ reLineEnd = ESCHER_LineArrowEnd;
+ else if ( aApiName == "Dimension Lines" )
+ {
+ rnArrowLength = 0;
+ rnArrowWidth = 2;
+ reLineEnd = ESCHER_LineArrowOvalEnd;
+ }
+ else if ( aApiName == "Double Arrow" )
+ reLineEnd = ESCHER_LineArrowEnd;
+ else if ( aApiName == "Rounded short Arrow" )
+ reLineEnd = ESCHER_LineArrowEnd;
+ else if ( aApiName == "Symmetric Arrow" )
+ reLineEnd = ESCHER_LineArrowEnd;
+ else if ( aApiName == "Line Arrow" )
+ reLineEnd = ESCHER_LineArrowOpenEnd;
+ else if ( aApiName == "Rounded large Arrow" )
+ reLineEnd = ESCHER_LineArrowEnd;
+ else if ( aApiName == "Circle" )
+ reLineEnd = ESCHER_LineArrowOvalEnd;
+ else if ( aApiName == "Square" )
+ reLineEnd = ESCHER_LineArrowDiamondEnd;
+ else if ( aApiName == "Arrow" )
+ reLineEnd = ESCHER_LineArrowEnd;
+ else
+ bIsMapped = false;
+
+ }
+ if ( !bIsMapped && comphelper::string::getTokenCount(aArrowStartName, ' ') == 2 )
+ {
+ sal_Int32 nIdx{ 0 };
+ std::u16string_view aArrowName( o3tl::getToken(aArrowStartName, 0, ' ', nIdx ) );
+ if ( aArrowName == u"msArrowEnd" )
+ reLineEnd = ESCHER_LineArrowEnd;
+ else if ( aArrowName == u"msArrowOpenEnd" )
+ reLineEnd = ESCHER_LineArrowOpenEnd;
+ else if ( aArrowName == u"msArrowStealthEnd" )
+ reLineEnd = ESCHER_LineArrowStealthEnd;
+ else if ( aArrowName == u"msArrowDiamondEnd" )
+ reLineEnd = ESCHER_LineArrowDiamondEnd;
+ else if ( aArrowName == u"msArrowOvalEnd" )
+ reLineEnd = ESCHER_LineArrowOvalEnd;
+ else
+ nIdx = -1;
+
+ // now we have the arrow, and try to determine the arrow size;
+ if ( nIdx>0 )
+ {
+ std::u16string_view aArrowSize = o3tl::getToken(aArrowStartName, 0, ' ', nIdx );
+ sal_Int32 nArrowSize = o3tl::toInt32(aArrowSize);
+ rnArrowWidth = ( nArrowSize - 1 ) / 3;
+ rnArrowLength = nArrowSize - ( rnArrowWidth * 3 ) - 1;
+ }
+ }
+ }
+ }
+ }
+ return bIsArrow;
+}
+
+void EscherPropertyContainer::CreateLineProperties(
+ const uno::Reference<beans::XPropertySet> & rXPropSet, bool bEdge )
+{
+ uno::Any aAny;
+ sal_uInt32 nLineFlags = 0x80008;
+
+ ESCHER_LineEnd eLineEnd;
+ sal_Int32 nArrowLength;
+ sal_Int32 nArrowWidth;
+
+ bool bSwapLineEnds = false;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "CircleKind", true ) )
+ {
+ drawing::CircleKind eCircleKind;
+ if ( aAny >>= eCircleKind )
+ {
+ if ( eCircleKind == drawing::CircleKind_ARC )
+ bSwapLineEnds = true;
+ }
+ }
+ if ( GetLineArrow( !bSwapLineEnds, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
+ {
+ AddOpt( ESCHER_Prop_lineStartArrowLength, nArrowLength );
+ AddOpt( ESCHER_Prop_lineStartArrowWidth, nArrowWidth );
+ AddOpt( ESCHER_Prop_lineStartArrowhead, eLineEnd );
+ nLineFlags |= 0x100010;
+ }
+ if ( GetLineArrow( bSwapLineEnds, rXPropSet, eLineEnd, nArrowLength, nArrowWidth ) )
+ {
+ AddOpt( ESCHER_Prop_lineEndArrowLength, nArrowLength );
+ AddOpt( ESCHER_Prop_lineEndArrowWidth, nArrowWidth );
+ AddOpt( ESCHER_Prop_lineEndArrowhead, eLineEnd );
+ nLineFlags |= 0x100010;
+ }
+
+ // support LineCaps
+ if(EscherPropertyValueHelper::GetPropertyValue(aAny, rXPropSet, "LineCap"))
+ {
+ drawing::LineCap aLineCap(drawing::LineCap_BUTT);
+
+ if(aAny >>= aLineCap)
+ {
+ switch (aLineCap)
+ {
+ default: /* drawing::LineCap_BUTT */
+ {
+ AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapFlat);
+ break;
+ }
+ case drawing::LineCap_ROUND:
+ {
+ AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapRound);
+ break;
+ }
+ case drawing::LineCap_SQUARE:
+ {
+ AddOpt(ESCHER_Prop_lineEndCapStyle, ESCHER_LineEndCapSquare);
+ break;
+ }
+ }
+ }
+ }
+
+ sal_uInt32 nLineWidth = ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineWidth" ) )
+ ? *o3tl::doAccess<sal_uInt32>(aAny) : 0;
+ if ( nLineWidth > 1 )
+ AddOpt( ESCHER_Prop_lineWidth, nLineWidth * 360 ); // 100TH MM -> PT , 1PT = 12700 EMU
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineStyle" ) )
+ {
+ drawing::LineStyle eLS;
+ if ( aAny >>= eLS )
+ {
+ switch ( eLS )
+ {
+ case drawing::LineStyle_NONE :
+ AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); // 80000
+ break;
+
+ case drawing::LineStyle_DASH :
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineDash" ) )
+ {
+ ESCHER_LineDashing eDash = ESCHER_LineSolid;
+ auto pLineDash = o3tl::doAccess<drawing::LineDash>(aAny);
+ switch ( pLineDash->Style )
+ {
+ case drawing::DashStyle_ROUND :
+ case drawing::DashStyle_ROUNDRELATIVE :
+ AddOpt( ESCHER_Prop_lineEndCapStyle, 0 ); // set Style Round
+ break;
+ default : break;
+ }
+ // Try to detect exact prstDash styles. Use a similar method as in oox export.
+ // Map it to a roughly fitting prstDash in other cases.
+ bool bIsConverted = false;
+ bool bIsRelative = pLineDash->Style == drawing::DashStyle_RECTRELATIVE
+ || pLineDash->Style == drawing::DashStyle_ROUNDRELATIVE;
+ sal_Int16 nDashes = pLineDash->Dashes;
+ sal_Int16 nDots = pLineDash->Dots;
+ sal_Int32 nDashLen = pLineDash->DashLen;
+ sal_Int32 nDotLen = pLineDash->DotLen;
+ sal_Int32 nDistance = pLineDash->Distance;
+
+ // Caution! The names are misleading. "dot" is always the first dash and "dash"
+ // the second one, regardless of the actual length. All prstDash
+ // definitions start with the longer dash and have exact one longer dash.
+ // Preset line style definitions for binary format are the same as for OOXML.
+ if (bIsRelative && nDots == 1)
+ {
+ // I'm not sure that LO always uses 100%, because in case of absolute values, LO
+ // sets length to 0 but treats it as 100%, if the attribute is missing in ODF.
+ // So to be sure set 100% explicitly in case of relative too.
+ if (nDashes > 0 && nDashLen == 0)
+ nDashLen = 100;
+ if (nDotLen == 0)
+ nDotLen = 100;
+ bIsConverted = true;
+ if (nDotLen == 100 && nDashes == 0 && nDashLen == 0 && nDistance == 300)
+ eDash = ESCHER_LineDotGEL;
+ else if (nDotLen == 400 && nDashes == 0 && nDashLen == 0 && nDistance == 300)
+ eDash = ESCHER_LineDashGEL;
+ else if (nDotLen == 400 && nDashes == 1 && nDashLen == 100 && nDistance == 300)
+ eDash = ESCHER_LineDashDotGEL;
+ else if (nDotLen == 800 && nDashes == 0 && nDashLen == 0 && nDistance == 300)
+ eDash = ESCHER_LineLongDashGEL;
+ else if (nDotLen == 800 && nDashes == 1 && nDashLen == 100 && nDistance == 300)
+ eDash = ESCHER_LineLongDashDotGEL;
+ else if (nDotLen == 800 && nDashes == 2 && nDashLen == 100 && nDistance == 300)
+ eDash = ESCHER_LineLongDashDotDotGEL;
+ else if (nDotLen == 100 && nDashes == 0 && nDashLen == 0 && nDistance == 100)
+ eDash = ESCHER_LineDotSys;
+ else if (nDotLen == 300 && nDashes == 0 && nDashLen == 0 && nDistance == 100)
+ eDash = ESCHER_LineDashSys;
+ else if (nDotLen == 300 && nDashes == 1 && nDashLen == 100 && nDistance == 100)
+ eDash = ESCHER_LineDashDotSys;
+ else if (nDotLen == 300 && nDashes == 2 && nDashLen == 100 && nDistance == 100)
+ eDash = ESCHER_LineDashDotDotSys;
+ else
+ bIsConverted = false;
+ }
+
+ if (!bIsConverted)
+ { // Map the style roughly to preset line styles.
+ if (((!(pLineDash->Dots)) || (!(pLineDash->Dashes)))
+ || (pLineDash->DotLen == pLineDash->DashLen))
+ {
+ sal_Int32 nLen = pLineDash->DotLen;
+ if (pLineDash->Dashes)
+ nLen = pLineDash->DashLen;
+ if (nLen >= nDistance)
+ eDash = ESCHER_LineLongDashGEL;
+ else if (pLineDash->Dots)
+ eDash = ESCHER_LineDotSys;
+ else
+ eDash = ESCHER_LineDashGEL;
+ }
+ else // X Y
+ {
+ if (pLineDash->Dots != pLineDash->Dashes)
+ {
+ if ((pLineDash->DashLen > nDistance) || (pLineDash->DotLen > nDistance))
+ eDash = ESCHER_LineLongDashDotDotGEL;
+ else
+ eDash = ESCHER_LineDashDotDotSys;
+ }
+ else // X Y Y
+ {
+ if ((pLineDash->DashLen > nDistance) || (pLineDash->DotLen > nDistance))
+ eDash = ESCHER_LineLongDashDotGEL;
+ else
+ eDash = ESCHER_LineDashDotGEL;
+ }
+ }
+ }
+ AddOpt( ESCHER_Prop_lineDashing, eDash );
+ }
+ }
+ [[fallthrough]];
+ case drawing::LineStyle_SOLID :
+ default:
+ {
+ AddOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
+ }
+ break;
+ }
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineColor" ) )
+ {
+ sal_uInt32 nLineColor = ImplGetColor( *o3tl::doAccess<sal_uInt32>(aAny) );
+ AddOpt( ESCHER_Prop_lineColor, nLineColor );
+ AddOpt( ESCHER_Prop_lineBackColor, nLineColor ^ 0xffffff );
+ }
+ }
+
+ ESCHER_LineJoin eLineJoin = ESCHER_LineJoinMiter;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "LineJoint", true ) )
+ {
+ drawing::LineJoint eLJ;
+ if ( aAny >>= eLJ )
+ {
+ switch ( eLJ )
+ {
+ case drawing::LineJoint_NONE :
+ case drawing::LineJoint_BEVEL :
+ eLineJoin = ESCHER_LineJoinBevel;
+ break;
+ default:
+ case drawing::LineJoint_MIDDLE :
+ case drawing::LineJoint_MITER :
+ eLineJoin = ESCHER_LineJoinMiter;
+ break;
+ case drawing::LineJoint_ROUND :
+ eLineJoin = ESCHER_LineJoinRound;
+ break;
+ }
+ }
+ }
+ AddOpt( ESCHER_Prop_lineJoinStyle, eLineJoin );
+
+ if ( EscherPropertyValueHelper::GetPropertyValue(
+ aAny, rXPropSet, "LineTransparence", true ) )
+ {
+ sal_Int16 nTransparency = 0;
+ if ( aAny >>= nTransparency )
+ AddOpt( ESCHER_Prop_lineOpacity, ( ( 100 - nTransparency ) << 16 ) / 100 );
+ }
+
+
+ if ( !bEdge )
+ {
+ AddOpt( ESCHER_Prop_fFillOK, 0x1001 );
+ AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
+ }
+}
+
+static Size lcl_SizeToEmu(Size aPrefSize, const MapMode& aPrefMapMode)
+{
+ Size aRetSize;
+ if (aPrefMapMode.GetMapUnit() == MapUnit::MapPixel)
+ aRetSize = Application::GetDefaultDevice()->PixelToLogic(aPrefSize, MapMode(MapUnit::Map100thMM));
+ else
+ aRetSize = OutputDevice::LogicToLogic(aPrefSize, aPrefMapMode, MapMode(MapUnit::Map100thMM));
+ return aRetSize;
+}
+
+void EscherPropertyContainer::ImplCreateGraphicAttributes( const uno::Reference<beans::XPropertySet> & rXPropSet,
+ sal_uInt32 nBlibId, bool bCreateCroppingAttributes )
+{
+ uno::Any aAny;
+
+ sal_uInt32 nPicFlags = 0;
+ drawing::ColorMode eColorMode( drawing::ColorMode_STANDARD );
+ sal_Int16 nLuminance = 0;
+ sal_Int32 nContrast = 0;
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "GraphicColorMode" ) )
+ aAny >>= eColorMode;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "AdjustLuminance" ) )
+ aAny >>= nLuminance;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "AdjustContrast" ) )
+ {
+ sal_Int16 nC = sal_Int16();
+ aAny >>= nC;
+ nContrast = nC;
+ }
+
+ if ( eColorMode == drawing::ColorMode_WATERMARK )
+ {
+ eColorMode = drawing::ColorMode_STANDARD;
+ nLuminance += 70;
+ if ( nLuminance > 100 )
+ nLuminance = 100;
+ nContrast -= 70;
+ if ( nContrast < -100 )
+ nContrast = -100;
+ }
+ if ( eColorMode == drawing::ColorMode_GREYS )
+ nPicFlags |= 0x40004;
+ else if ( eColorMode == drawing::ColorMode_MONO )
+ nPicFlags |= 0x60006;
+
+ if ( nContrast )
+ {
+ nContrast += 100;
+ if ( nContrast == 100)
+ nContrast = 0x10000;
+ else if ( nContrast < 100 )
+ {
+ nContrast *= 0x10000;
+ nContrast /= 100;
+ }
+ else if ( nContrast < 200 )
+ nContrast = ( 100 * 0x10000 ) / ( 200 - nContrast );
+ else
+ nContrast = 0x7fffffff;
+ AddOpt( ESCHER_Prop_pictureContrast, nContrast );
+ }
+ if ( nLuminance )
+ AddOpt( ESCHER_Prop_pictureBrightness, nLuminance * 327 );
+ if ( nPicFlags )
+ AddOpt( ESCHER_Prop_pictureActive, nPicFlags );
+
+ if ( !(bCreateCroppingAttributes && pGraphicProvider) )
+ return;
+
+ Size aPrefSize;
+ MapMode aPrefMapMode;
+ if ( !pGraphicProvider->GetPrefSize( nBlibId, aPrefSize, aPrefMapMode ) )
+ return;
+
+ Size aCropSize(lcl_SizeToEmu(aPrefSize, aPrefMapMode));
+ if ( !(aCropSize.Width() && aCropSize.Height()) )
+ return;
+
+ if ( !EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "GraphicCrop" ) )
+ return;
+
+ text::GraphicCrop aGraphCrop;
+ if ( !(aAny >>= aGraphCrop) )
+ return;
+
+ if ( aGraphCrop.Left )
+ {
+ sal_uInt32 nLeft = ( aGraphCrop.Left * 65536 ) / aCropSize.Width();
+ AddOpt( ESCHER_Prop_cropFromLeft, nLeft );
+ }
+ if ( aGraphCrop.Top )
+ {
+ sal_uInt32 nTop = ( aGraphCrop.Top * 65536 ) / aCropSize.Height();
+ AddOpt( ESCHER_Prop_cropFromTop, nTop );
+ }
+ if ( aGraphCrop.Right )
+ {
+ sal_uInt32 nRight = ( aGraphCrop.Right * 65536 ) / aCropSize.Width();
+ AddOpt( ESCHER_Prop_cropFromRight, nRight );
+ }
+ if ( aGraphCrop.Bottom )
+ {
+ sal_uInt32 nBottom = ( aGraphCrop.Bottom * 65536 ) / aCropSize.Height();
+ AddOpt( ESCHER_Prop_cropFromBottom, nBottom );
+ }
+}
+
+void EscherPropertyContainer::CreateShapeProperties( const uno::Reference<drawing::XShape> & rXShape )
+{
+ uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
+ if ( !aXPropSet.is() )
+ return;
+
+ bool bVisible = false;
+ bool bPrintable = false;
+ uno::Any aAny;
+ sal_uInt32 nShapeAttr = 0;
+ if (EscherPropertyValueHelper::GetPropertyValue(aAny, aXPropSet, "Visible", true) && (aAny >>= bVisible))
+ {
+ if ( !bVisible )
+ nShapeAttr |= 0x20002; // set fHidden = true
+ }
+ // This property (fPrint) isn't used in Excel anymore, leaving it for legacy reasons
+ // one change, based on XLSX: hidden implies not printed, let's not export the fPrint property in that case
+ if (bVisible && EscherPropertyValueHelper::GetPropertyValue(aAny, aXPropSet, "Printable", true) && (aAny >>= bPrintable))
+ {
+ if ( !bPrintable )
+ nShapeAttr |= 0x10000; // set fPrint = false;
+ }
+ if ( nShapeAttr )
+ AddOpt( ESCHER_Prop_fPrint, nShapeAttr );
+}
+
+bool EscherPropertyContainer::CreateOLEGraphicProperties(const uno::Reference<drawing::XShape> & rXShape)
+{
+ bool bRetValue = false;
+
+ if ( rXShape.is() )
+ {
+ SdrObject* pObject = SdrObject::getSdrObjectFromXShape(rXShape); // SJ: leaving unoapi, because currently there is
+ if (auto pOle2Obj = dynamic_cast<const SdrOle2Obj*>(pObject)) // no access to the native graphic object
+ {
+ const Graphic* pGraphic = pOle2Obj->GetGraphic();
+ if (pGraphic)
+ {
+ Graphic aGraphic(*pGraphic);
+ GraphicObject aGraphicObject(aGraphic);
+ bRetValue = CreateGraphicProperties(rXShape, aGraphicObject);
+ }
+ }
+ }
+ return bRetValue;
+}
+
+bool EscherPropertyContainer::CreateGraphicProperties(const uno::Reference<drawing::XShape> & rXShape, const GraphicObject& rGraphicObj)
+{
+ bool bRetValue = false;
+ OString aUniqueId(rGraphicObj.GetUniqueID());
+ if ( !aUniqueId.isEmpty() )
+ {
+ AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
+ uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
+
+ if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect && aXPropSet.is() )
+ {
+ uno::Any aAny;
+ std::unique_ptr<awt::Rectangle> pVisArea;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "VisibleArea" ) )
+ {
+ pVisArea.reset(new awt::Rectangle);
+ aAny >>= *pVisArea;
+ }
+ sal_uInt32 nBlibId = pGraphicProvider->GetBlibID( *pPicOutStrm, rGraphicObj, pVisArea.get() );
+ if ( nBlibId )
+ {
+ AddOpt( ESCHER_Prop_pib, nBlibId, true );
+ ImplCreateGraphicAttributes( aXPropSet, nBlibId, false );
+ bRetValue = true;
+ }
+ }
+ }
+ return bRetValue;
+}
+
+bool EscherPropertyContainer::CreateMediaGraphicProperties(const uno::Reference<drawing::XShape> & rXShape)
+{
+ bool bRetValue = false;
+ if ( rXShape.is() )
+ {
+ SdrObject* pSdrObject(SdrObject::getSdrObjectFromXShape(rXShape)); // SJ: leaving unoapi, because currently there is
+ if (auto pSdrMediaObj = dynamic_cast<const SdrMediaObj*>(pSdrObject)) // no access to the native graphic object
+ {
+ GraphicObject aGraphicObject(pSdrMediaObj->getSnapshot());
+ bRetValue = CreateGraphicProperties(rXShape, aGraphicObject);
+ }
+ }
+ return bRetValue;
+}
+
+bool EscherPropertyContainer::ImplCreateEmbeddedBmp(GraphicObject const & rGraphicObject)
+{
+ if (rGraphicObject.GetType() != GraphicType::NONE)
+ {
+ EscherGraphicProvider aProvider;
+ SvMemoryStream aMemStrm;
+
+ if (aProvider.GetBlibID( aMemStrm, rGraphicObject))
+ {
+ AddOpt(ESCHER_Prop_fillBlip, true, 0, aMemStrm);
+ return true;
+ }
+ }
+ return false;
+}
+
+void EscherPropertyContainer::CreateEmbeddedBitmapProperties(
+ uno::Reference<awt::XBitmap> const & rxBitmap, drawing::BitmapMode eBitmapMode )
+{
+ uno::Reference<graphic::XGraphic> xGraphic(rxBitmap, uno::UNO_QUERY);
+ if (!xGraphic.is())
+ return;
+ const Graphic aGraphic(xGraphic);
+ if (aGraphic.IsNone())
+ return;
+ const GraphicObject aGraphicObject(aGraphic);
+ if (aGraphicObject.GetType() == GraphicType::NONE)
+ return;
+ if (ImplCreateEmbeddedBmp(aGraphicObject))
+ {
+ // bitmap mode property
+ bool bRepeat = eBitmapMode == drawing::BitmapMode_REPEAT;
+ AddOpt( ESCHER_Prop_fillType, bRepeat ? ESCHER_FillTexture : ESCHER_FillPicture );
+ }
+}
+
+namespace {
+
+Graphic lclDrawHatch( const drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground, const tools::Rectangle& rRect )
+{
+ // #i121183# For hatch, do no longer create a bitmap with the fixed size of 28x28 pixels. Also
+ // do not create a bitmap in page size, that would explode file sizes (and have no good quality).
+ // Better use a MetaFile graphic in page size; thus we have good quality due to vector format and
+ // no bit file sizes.
+ ScopedVclPtrInstance< VirtualDevice > pVDev;
+ GDIMetaFile aMtf;
+
+ pVDev->SetOutputSizePixel(Size(2, 2));
+ pVDev->EnableOutput(false);
+ pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));
+ aMtf.Clear();
+ aMtf.Record(pVDev);
+ pVDev->SetLineColor();
+ pVDev->SetFillColor(bFillBackground ? rBackColor : COL_TRANSPARENT);
+ pVDev->DrawRect(rRect);
+ pVDev->DrawHatch(tools::PolyPolygon(rRect), Hatch(static_cast<HatchStyle>(rHatch.Style), Color(ColorTransparency, rHatch.Color), rHatch.Distance,
+ Degree10(rHatch.Angle)));
+ aMtf.Stop();
+ aMtf.WindStart();
+ aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ aMtf.SetPrefSize(rRect.GetSize());
+
+ return Graphic(aMtf);
+}
+
+} // namespace
+
+void EscherPropertyContainer::CreateEmbeddedHatchProperties(const drawing::Hatch& rHatch, const Color& rBackColor, bool bFillBackground )
+{
+ const tools::Rectangle aRect(pShapeBoundRect ? *pShapeBoundRect : tools::Rectangle(Point(0,0), Size(28000, 21000)));
+ Graphic aGraphic(lclDrawHatch(rHatch, rBackColor, bFillBackground, aRect));
+ GraphicObject aGraphicObject(aGraphic);
+
+ if (ImplCreateEmbeddedBmp(aGraphicObject))
+ AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture );
+}
+
+bool EscherPropertyContainer::CreateGraphicProperties(const uno::Reference<beans::XPropertySet> & rXPropSet,
+ const OUString& rSource,
+ const bool bCreateFillBitmap,
+ const bool bCreateCroppingAttributes,
+ const bool bFillBitmapModeAllowed,
+ const bool bOOxmlExport )
+{
+ bool bRetValue = false;
+ bool bCreateFillStyles = false;
+
+ std::unique_ptr<GraphicAttr> pGraphicAttr;
+ uno::Reference<graphic::XGraphic> xGraphic;
+
+ uno::Any aAny;
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, rSource ) )
+ {
+ bool bMirrored = false;
+ bool bRotate = true;
+ bool bIsGraphicMtf = false;
+ sal_Int16 nTransparency(0);
+ sal_Int16 nRed(0);
+ sal_Int16 nGreen(0);
+ sal_Int16 nBlue(0);
+ double fGamma(1.0);
+ drawing::BitmapMode eBitmapMode(drawing::BitmapMode_NO_REPEAT);
+ OUString aGraphicUrl;
+
+ sal_uInt16 nAngle = 0;
+ if ( rSource == "MetaFile" )
+ {
+ auto & aSeq = *o3tl::doAccess<uno::Sequence<sal_Int8>>(aAny);
+ const sal_Int8* pArray = aSeq.getConstArray();
+ sal_uInt32 nArrayLength = aSeq.getLength();
+
+ // the metafile is already rotated
+ bRotate = false;
+
+ if (pArray && nArrayLength)
+ {
+ Graphic aGraphic;
+ SvMemoryStream aStream(const_cast<sal_Int8 *>(pArray), nArrayLength, StreamMode::READ);
+ ErrCode nErrCode = GraphicConverter::Import(aStream, aGraphic, ConvertDataFormat::WMF);
+ if ( nErrCode == ERRCODE_NONE )
+ {
+ xGraphic = aGraphic.GetXGraphic();
+ bIsGraphicMtf = aGraphic.GetType() == GraphicType::GdiMetafile;
+ }
+ }
+ }
+ else if (rSource == "Bitmap" || rSource == "FillBitmap")
+ {
+ auto xBitmap = aAny.get<uno::Reference<awt::XBitmap>>();
+ if (xBitmap.is())
+ {
+ xGraphic.set(xBitmap, uno::UNO_QUERY);
+ Graphic aGraphic(xGraphic);
+ bIsGraphicMtf = aGraphic.GetType() == GraphicType::GdiMetafile;
+ }
+ }
+ else if ( rSource == "Graphic" )
+ {
+ xGraphic = aAny.get<uno::Reference<graphic::XGraphic>>();
+ bCreateFillStyles = true;
+ }
+ else if ( rSource == "FillHatch" )
+ {
+ drawing::Hatch aHatch;
+ if ( aAny >>= aHatch )
+ {
+ Color aBackColor;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillColor" ) )
+ {
+ aBackColor = Color(ColorTransparency, ImplGetColor( *o3tl::doAccess<sal_uInt32>(aAny), false ));
+ }
+ bool bFillBackground = false;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillBackground", true ) )
+ {
+ aAny >>= bFillBackground;
+ }
+
+ const tools::Rectangle aRect(Point(0, 0), pShapeBoundRect ? pShapeBoundRect->GetSize() : Size(28000, 21000));
+ Graphic aGraphic(lclDrawHatch(aHatch, aBackColor, bFillBackground, aRect));
+ xGraphic = aGraphic.GetXGraphic();
+ eBitmapMode = drawing::BitmapMode_REPEAT;
+ bIsGraphicMtf = aGraphic.GetType() == GraphicType::GdiMetafile;
+ }
+ }
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "IsMirrored", true ) )
+ aAny >>= bMirrored;
+
+ // #121074# transparency of graphic is not supported in MS formats, get and apply it
+ // in the GetTransformedGraphic call in GetBlibID
+ if(EscherPropertyValueHelper::GetPropertyValue(aAny, rXPropSet, "Transparency"))
+ {
+ aAny >>= nTransparency;
+ }
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "AdjustRed" ) )
+ {
+ aAny >>= nRed;
+ }
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "AdjustGreen" ) )
+ {
+ aAny >>= nGreen;
+ }
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "AdjustBlue" ) )
+ {
+ aAny >>= nBlue;
+ }
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "Gamma" ) )
+ {
+ aAny >>= fGamma;
+ }
+
+ if ( bCreateFillBitmap && bFillBitmapModeAllowed )
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillBitmapMode", true ) )
+ aAny >>= eBitmapMode;
+ }
+ else
+ {
+ nAngle = bRotate && EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "RotateAngle", true )
+ ? static_cast<sal_uInt16>( ( *o3tl::doAccess<sal_Int32>(aAny) ) + 5 ) / 10
+ : 0;
+ }
+
+ if (xGraphic.is())
+ {
+ Graphic aGraphic(xGraphic);
+ aGraphicUrl = aGraphic.getOriginURL();
+ }
+
+ if (!aGraphicUrl.isEmpty())
+ {
+ bool bConverted = false;
+
+ // externally, linked graphic? convert to embedded
+ // one, if transformations are needed. this is because
+ // everything < msoxp cannot even handle rotated
+ // bitmaps.
+ // And check whether the graphic link target is
+ // actually supported by mso.
+ INetURLObject aTmp( aGraphicUrl );
+ GraphicDescriptor aDescriptor(aTmp);
+ (void)aDescriptor.Detect();
+ const GraphicFileFormat nFormat = aDescriptor.GetFileFormat();
+
+ // can MSO handle it?
+ if ( bMirrored || nAngle || nTransparency || nRed || nGreen || nBlue || (1.0 != fGamma) ||
+ (nFormat != GraphicFileFormat::BMP &&
+ nFormat != GraphicFileFormat::GIF &&
+ nFormat != GraphicFileFormat::JPG &&
+ nFormat != GraphicFileFormat::PNG &&
+ nFormat != GraphicFileFormat::TIF &&
+ nFormat != GraphicFileFormat::PCT &&
+ nFormat != GraphicFileFormat::WMF &&
+ nFormat != GraphicFileFormat::EMF) )
+ {
+ std::unique_ptr<SvStream> pIn(::utl::UcbStreamHelper::CreateStream(
+ aTmp.GetMainURL( INetURLObject::DecodeMechanism::NONE ), StreamMode::READ ));
+ if ( pIn )
+ {
+ Graphic aGraphic;
+ ErrCode nErrCode = GraphicConverter::Import( *pIn, aGraphic );
+
+ if ( nErrCode == ERRCODE_NONE )
+ {
+ xGraphic = aGraphic.GetXGraphic();
+ bConverted = true;
+ }
+ // else: simply keep the graphic link
+ }
+ }
+
+ if (!bConverted && pGraphicProvider )
+ {
+ const OUString& rBaseURI( pGraphicProvider->GetBaseURI() );
+ INetURLObject aBaseURI( rBaseURI );
+ if( aBaseURI.GetProtocol() == aTmp.GetProtocol() )
+ {
+ OUString aRelUrl( INetURLObject::GetRelURL( rBaseURI, aGraphicUrl ) );
+ if ( !aRelUrl.isEmpty() )
+ aGraphicUrl = aRelUrl;
+ }
+ }
+ }
+
+ if (!aGraphicUrl.isEmpty() || xGraphic.is())
+ {
+ if(bMirrored || nTransparency || nRed || nGreen || nBlue || (1.0 != fGamma))
+ {
+ pGraphicAttr.reset(new GraphicAttr);
+
+ if(bMirrored)
+ {
+ pGraphicAttr->SetMirrorFlags(BmpMirrorFlags::Horizontal);
+ }
+
+ if(nTransparency)
+ {
+ pGraphicAttr->SetAlpha(255 - (nTransparency * 255) / 100);
+ }
+
+ if(nRed)
+ {
+ pGraphicAttr->SetChannelR(nRed);
+ }
+
+ if(nGreen)
+ {
+ pGraphicAttr->SetChannelG(nGreen);
+ }
+
+ if(nBlue)
+ {
+ pGraphicAttr->SetChannelB(nBlue);
+ }
+
+ if(1.0 != fGamma)
+ {
+ pGraphicAttr->SetGamma(fGamma);
+ }
+ }
+
+ if(nAngle && bIsGraphicMtf)
+ {
+ AddOpt( ESCHER_Prop_Rotation, ( ( (static_cast<sal_Int32>(nAngle) << 16 ) / 10 ) + 0x8000 ) &~ 0xffff );
+ }
+
+ if ( eBitmapMode == drawing::BitmapMode_REPEAT )
+ {
+ sal_Int32 nSizeX = 0,nSizeY = 0,nOffsetX = 0,nOffsetY = 0,nPosOffsetX = 0,nPosOffsetY = 0;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillBitmapSizeX", true ) )
+ {
+ aAny >>= nSizeX;
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillBitmapSizeY", true ) )
+ {
+ aAny >>= nSizeY;
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillBitmapOffsetX", true ) )
+ {
+ aAny >>= nOffsetX;
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillBitmapOffsetY", true ) )
+ {
+ aAny >>= nOffsetY;
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillBitmapPositionOffsetX", true ) )
+ {
+ aAny >>= nPosOffsetX;
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "FillBitmapPositionOffsetY", true ) )
+ {
+ aAny >>= nPosOffsetY;
+ }
+ if(nSizeX == -100 && nSizeY == -100 && nOffsetX == 0 && nOffsetY == 0 && nPosOffsetX == 0 && nPosOffsetY == 0)
+ AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
+ else
+ AddOpt( ESCHER_Prop_fillType, ESCHER_FillTexture );
+ }
+ else
+ AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
+
+ if (xGraphic.is())
+ {
+ Graphic aGraphic(xGraphic);
+ if (!aGraphic.getOriginURL().isEmpty())
+ {
+ AddOpt(ESCHER_Prop_pibName, aGraphicUrl);
+ sal_uInt32 nPibFlags = 0;
+ GetOpt(ESCHER_Prop_pibFlags, nPibFlags);
+ AddOpt(ESCHER_Prop_pibFlags, ESCHER_BlipFlagLinkToFile | ESCHER_BlipFlagFile | ESCHER_BlipFlagDoNotSave | nPibFlags);
+ }
+ else if (pGraphicProvider && pPicOutStrm && pShapeBoundRect) // write out embedded graphic
+ {
+ GraphicObject aGraphicObject(aGraphic);
+ const sal_uInt32 nBlibId(pGraphicProvider->GetBlibID(*pPicOutStrm, aGraphicObject, nullptr, pGraphicAttr.get()));
+
+ if(nBlibId)
+ {
+ if(bCreateFillBitmap)
+ {
+ AddOpt(ESCHER_Prop_fillBlip, nBlibId, true);
+ }
+ else
+ {
+ AddOpt( ESCHER_Prop_pib, nBlibId, true );
+ ImplCreateGraphicAttributes( rXPropSet, nBlibId, bCreateCroppingAttributes );
+ }
+
+ bRetValue = true;
+ }
+ }
+ else
+ {
+ EscherGraphicProvider aProvider;
+ SvMemoryStream aMemStrm;
+ GraphicObject aGraphicObject(aGraphic);
+
+ if (aProvider.GetBlibID(aMemStrm, aGraphicObject, nullptr, pGraphicAttr.get(), bOOxmlExport))
+ {
+ AddOpt(ESCHER_Prop_fillBlip, true, 0, aMemStrm);
+ bRetValue = true;
+ }
+ }
+ }
+ }
+ }
+ pGraphicAttr.reset();
+ if ( bCreateFillStyles )
+ CreateFillProperties( rXPropSet, true );
+
+ return bRetValue;
+}
+
+tools::PolyPolygon EscherPropertyContainer::GetPolyPolygon( const uno::Reference< drawing::XShape > & rXShape )
+{
+ tools::PolyPolygon aRetPolyPoly;
+ uno::Reference< beans::XPropertySet > aXPropSet;
+ uno::Any aAny( rXShape->queryInterface(
+ cppu::UnoType<beans::XPropertySet>::get()));
+
+ if ( aAny >>= aXPropSet )
+ {
+ bool bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "PolyPolygonBezier", true );
+ if ( !bHasProperty )
+ bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "PolyPolygon", true );
+ if ( !bHasProperty )
+ bHasProperty = EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "Polygon", true );
+ if ( bHasProperty )
+ aRetPolyPoly = GetPolyPolygon( aAny );
+ }
+ return aRetPolyPoly;
+}
+
+// adapting to basegfx::B2DPolyPolygon now, has no sense to do corrections in the
+// old tools::PolyPolygon creation code. Convert to that at return time
+tools::PolyPolygon EscherPropertyContainer::GetPolyPolygon( const uno::Any& rAny )
+{
+ basegfx::B2DPolyPolygon aRetval;
+
+ if(auto pBCC = o3tl::tryAccess<drawing::PolyPolygonBezierCoords>(rAny))
+ {
+ aRetval = basegfx::utils::UnoPolyPolygonBezierCoordsToB2DPolyPolygon(*pBCC);
+ }
+ else if(auto pCC = o3tl::tryAccess<drawing::PointSequenceSequence>(rAny))
+ {
+ aRetval = basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(*pCC);
+ }
+ else if(auto pC = o3tl::tryAccess<drawing::PointSequence>(rAny))
+ {
+ aRetval.append(basegfx::utils::UnoPointSequenceToB2DPolygon(*pC));
+ }
+
+ basegfx::B2DPolyPolygon aRetval2;
+
+ for(sal_uInt32 a(0); a < aRetval.count(); a++)
+ {
+ if(0 != aRetval.getB2DPolygon(a).count())
+ {
+ aRetval2.append(aRetval.getB2DPolygon(a));
+ }
+ }
+
+ return tools::PolyPolygon(aRetval2);
+}
+
+bool EscherPropertyContainer::CreatePolygonProperties(
+ const uno::Reference<beans::XPropertySet> & rXPropSet,
+ sal_uInt32 nFlags,
+ bool bBezier,
+ awt::Rectangle& rGeoRect,
+ tools::Polygon const * pPolygon )
+{
+ tools::PolyPolygon aPolyPolygon;
+
+ if(nullptr != pPolygon)
+ {
+ aPolyPolygon.Insert(*pPolygon);
+ }
+ else
+ {
+ uno::Any aAny;
+
+ if(EscherPropertyValueHelper::GetPropertyValue(
+ aAny,
+ rXPropSet,
+ bBezier ? OUString("PolyPolygonBezier") : OUString("PolyPolygon"),
+ true))
+ {
+ aPolyPolygon = GetPolyPolygon(aAny);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ if(0 == aPolyPolygon.Count())
+ {
+ return false;
+ }
+
+ if(0 != (nFlags & ESCHER_CREATEPOLYGON_LINE))
+ {
+ if((1 == aPolyPolygon.Count()) && (2 == aPolyPolygon[0].GetSize()))
+ {
+ const tools::Polygon& rPoly(aPolyPolygon[0]);
+
+ rGeoRect = awt::Rectangle(
+ rPoly[0].X(),
+ rPoly[0].Y(),
+ rPoly[1].X() - rPoly[0].X(),
+ rPoly[1].Y() - rPoly[0].Y());
+
+ return true;
+ }
+
+ return false;
+ }
+
+ const tools::Rectangle aRect(aPolyPolygon.GetBoundRect());
+
+ rGeoRect = awt::Rectangle(
+ aRect.Left(),
+ aRect.Top(),
+ aRect.GetWidth(),
+ aRect.GetHeight());
+
+ const sal_uInt16 nPolyCount(aPolyPolygon.Count());
+ sal_uInt32 nTotalPoints(0);
+
+ std::vector< sal_uInt8 > aVertices
+ {
+ 0, 0, 0, 0,
+ static_cast<sal_uInt8>(0xf0),
+ static_cast<sal_uInt8>(0xff)
+ };
+
+ std::vector< sal_uInt8 > aSegments
+ {
+ 0, 0, 0, 0,
+ static_cast<sal_uInt8>(2),
+ static_cast<sal_uInt8>(0)
+ };
+
+ for(sal_uInt16 j(0); j < nPolyCount; ++j)
+ {
+ const tools::Polygon aPolygon(aPolyPolygon[j]);
+ const sal_uInt16 nPoints(aPolygon.GetSize());
+
+ if(0 == nPoints)
+ {
+ continue;
+ }
+
+ // Polygon start
+ aSegments.push_back(static_cast<sal_uInt8>(0x0));
+ aSegments.push_back(static_cast<sal_uInt8>(0x40));
+
+ sal_uInt16 nSegmentIgnoreCounter(0);
+
+ // write points from polygon to buffer
+ for(sal_uInt16 i(0); i < nPoints; ++i)
+ {
+ Point aPoint(aPolygon[i]);
+
+ aPoint.AdjustX(-(rGeoRect.X));
+ aPoint.AdjustY(-(rGeoRect.Y));
+
+ aVertices.push_back(static_cast<sal_uInt8>(aPoint.X()));
+ aVertices.push_back(static_cast<sal_uInt8>(aPoint.X() >> 8));
+ aVertices.push_back(static_cast<sal_uInt8>(aPoint.Y()));
+ aVertices.push_back(static_cast<sal_uInt8>(aPoint.Y() >> 8));
+
+ nTotalPoints++;
+
+ if(0 != nSegmentIgnoreCounter)
+ {
+ nSegmentIgnoreCounter--;
+ }
+ else
+ {
+ aSegments.push_back(static_cast<sal_uInt8>(0));
+
+ if(bBezier)
+ {
+ aSegments.push_back(static_cast<sal_uInt8>(0xb3));
+ }
+ else
+ {
+ aSegments.push_back(static_cast<sal_uInt8>(0xac));
+ }
+
+ if(i + 1 == nPoints)
+ {
+ if(nPolyCount > 1)
+ {
+ // end of polygon
+ aSegments.push_back(static_cast<sal_uInt8>(1));
+ aSegments.push_back(static_cast<sal_uInt8>(0x60));
+ }
+ }
+ else
+ {
+ aSegments.push_back(static_cast<sal_uInt8>(1));
+
+ if(PolyFlags::Control == aPolygon.GetFlags(i + 1))
+ {
+ aSegments.push_back(static_cast<sal_uInt8>(0x20));
+ nSegmentIgnoreCounter = 2;
+ }
+ else
+ {
+ aSegments.push_back(static_cast<sal_uInt8>(0));
+ }
+ }
+ }
+ }
+ }
+
+ if(0 == nTotalPoints || aSegments.size() < 6 || aVertices.size() < 6)
+ return false;
+
+ // Little endian
+ aVertices[0] = static_cast<sal_uInt8>(nTotalPoints);
+ aVertices[1] = static_cast<sal_uInt8>(nTotalPoints >> 8);
+ aVertices[2] = static_cast<sal_uInt8>(nTotalPoints);
+ aVertices[3] = static_cast<sal_uInt8>(nTotalPoints >> 8);
+
+ aSegments.push_back(static_cast<sal_uInt8>(0));
+ aSegments.push_back(static_cast<sal_uInt8>(0x80));
+
+ const sal_uInt32 nSegmentBufSize(aSegments.size() - 6);
+ aSegments[0] = static_cast<sal_uInt8>(nSegmentBufSize >> 1);
+ aSegments[1] = static_cast<sal_uInt8>(nSegmentBufSize >> 9);
+ aSegments[2] = static_cast<sal_uInt8>(nSegmentBufSize >> 1);
+ aSegments[3] = static_cast<sal_uInt8>(nSegmentBufSize >> 9);
+
+ AddOpt(
+ ESCHER_Prop_geoRight,
+ rGeoRect.Width);
+ AddOpt(
+ ESCHER_Prop_geoBottom,
+ rGeoRect.Height);
+ AddOpt(
+ ESCHER_Prop_shapePath,
+ ESCHER_ShapeComplex);
+ AddOpt(
+ ESCHER_Prop_pVertices,
+ true,
+ aVertices.size() - 6,
+ aVertices);
+ AddOpt(
+ ESCHER_Prop_pSegmentInfo,
+ true,
+ aSegments.size(),
+ aSegments);
+
+ return true;
+}
+
+
+/*
+in MS,the connector including 9 types :
+"straightConnector1",
+"bentConnector2","bentConnector3","bentConnector4","bentConnector5"
+"curvedConnector2","curvedConnector3","curvedConnector4","curvedConnector5"
+in AOO,including 4 types:"standard","lines","line","curve"
+when save as MS file, the connector must be convert to corresponding type.
+"line" and "lines" <-> "straightConnector1"
+"standard" <-> "bentConnector2-5"
+"curve" <-> "curvedConnector2-5"
+*/
+static sal_Int32 lcl_GetAdjustValueCount( const XPolygon& rPoly )
+{
+ int nRet = 0;
+ switch ( rPoly.GetSize() )
+ {
+ case 2 :
+ case 3:
+ nRet = 0;
+ break;
+ case 4:
+ nRet = 1;
+ break;
+ case 5:
+ nRet = 2;
+ break;
+ default:
+ if ( rPoly.GetSize()>=6 )
+ nRet = 3;
+ break;
+ }
+ return nRet;
+}
+
+// Adjust value decide the position which connector should turn a corner
+static sal_Int32 lcl_GetConnectorAdjustValue ( const XPolygon& rPoly, sal_uInt16 nIndex )
+{
+ sal_uInt16 k = rPoly.GetSize();
+ OSL_ASSERT ( k >= ( 3 + nIndex ) );
+
+ Point aPt;
+ Point aStart = rPoly[0];
+ Point aEnd = rPoly[k-1];
+ if ( aEnd.Y() == aStart.Y() )
+ aEnd.setY( aStart.Y() +4 );
+ if ( aEnd.X() == aStart.X() )
+ aEnd.setX( aStart.X() +4 );
+
+ bool bVertical = ( rPoly[1].X()-aStart.X() ) == 0 ;
+ // vertical and horizon alternate
+ if ( nIndex%2 == 1 ) bVertical = !bVertical;
+ aPt = rPoly[ nIndex + 1];
+
+ sal_Int32 nAdjustValue;
+ if ( bVertical )
+ nAdjustValue = ( aPt.Y()-aStart.Y())* 21600 /(aEnd.Y()-aStart.Y());
+ else
+ nAdjustValue = ( aPt.X()-aStart.X() )* 21600 /(aEnd.X()-aStart.X());
+
+ return nAdjustValue;
+}
+
+
+static void lcl_Rotate(Degree100 nAngle, Point center, Point& pt)
+{
+ nAngle = NormAngle36000(nAngle);
+
+ int cs, sn;
+ switch (nAngle.get())
+ {
+ case 0:
+ cs =1;
+ sn =0;
+ break;
+ case 9000:
+ cs =0;
+ sn =1;
+ break;
+ case 18000:
+ cs = -1;
+ sn = 0;
+ break;
+ case 27000:
+ cs = 0;
+ sn = -1;
+ break;
+ default:
+ return;
+ }
+ sal_Int32 x0 =pt.X()-center.X();
+ sal_Int32 y0 =pt.Y()-center.Y();
+ pt.setX(center.X()+ x0*cs-y0*sn );
+ pt.setY(center.Y()+ y0*cs+x0*sn );
+}
+/*
+ FlipV defines that the shape will be flipped vertically about the center of its bounding box.
+Generally, draw the connector from top to bottom, from left to right when meet the adjust value,
+but when (X1>X2 or Y1>Y2),the draw director must be reverse, FlipV or FlipH should be set to true.
+*/
+static bool lcl_GetAngle(tools::Polygon &rPoly, ShapeFlag& rShapeFlags,sal_Int32& nAngle )
+{
+ Point aStart = rPoly[0];
+ Point aEnd = rPoly[rPoly.GetSize()-1];
+ nAngle = ( rPoly[1].X() == aStart.X() ) ? 9000: 0 ;
+ Point p1(aStart.X(),aStart.Y());
+ Point p2(aEnd.X(),aEnd.Y());
+ if ( nAngle )
+ {
+ Point center((aEnd.X()+aStart.X())>>1,(aEnd.Y()+aStart.Y())>>1);
+ lcl_Rotate(Degree100(-nAngle), center,p1);
+ lcl_Rotate(Degree100(-nAngle), center,p2);
+ }
+ if ( p1.X() > p2.X() )
+ {
+ if ( nAngle )
+ rShapeFlags |= ShapeFlag::FlipV;
+ else
+ rShapeFlags |= ShapeFlag::FlipH;
+
+ }
+ if ( p1.Y() > p2.Y() )
+ {
+ if ( nAngle )
+ rShapeFlags |= ShapeFlag::FlipH;
+ else
+ rShapeFlags |= ShapeFlag::FlipV;
+ }
+
+ if ( (rShapeFlags&ShapeFlag::FlipH) && (rShapeFlags&ShapeFlag::FlipV) )
+ {
+ rShapeFlags &= ~ShapeFlag( ShapeFlag::FlipH | ShapeFlag::FlipV );
+ nAngle +=18000;
+ }
+
+ if ( nAngle )
+ {
+ // Set angle properties
+ nAngle *= 655;
+ nAngle += 0x8000;
+ nAngle &=~0xffff; // round nAngle to whole number of degrees
+ return true;
+ }
+ return false;
+}
+bool EscherPropertyContainer::CreateConnectorProperties(
+ const uno::Reference<drawing::XShape> & rXShape,
+ EscherSolverContainer& rSolverContainer, awt::Rectangle& rGeoRect,
+ sal_uInt16& rShapeType, ShapeFlag& rShapeFlags )
+{
+ bool bRetValue = false;
+ rShapeType = 0;
+ rShapeFlags = ShapeFlag::NONE;
+
+ if ( rXShape.is() )
+ {
+ uno::Reference<beans::XPropertySet> aXPropSet;
+ uno::Reference<drawing::XShape> aShapeA, aShapeB;
+ uno::Any aAny( rXShape->queryInterface( cppu::UnoType<beans::XPropertySet>::get()));
+ if ( aAny >>= aXPropSet )
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "EdgeKind", true ) )
+ {
+ drawing::ConnectorType eCt;
+ aAny >>= eCt;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "EdgeStartPoint" ) )
+ {
+ awt::Point aStartPoint = *o3tl::doAccess<awt::Point>(aAny);
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "EdgeEndPoint" ) )
+ {
+ awt::Point aEndPoint = *o3tl::doAccess<awt::Point>(aAny);
+
+ rShapeFlags = ShapeFlag::HaveAnchor | ShapeFlag::HaveShapeProperty | ShapeFlag::Connector;
+ rGeoRect = awt::Rectangle( aStartPoint.X, aStartPoint.Y,
+ ( aEndPoint.X - aStartPoint.X ) + 1, ( aEndPoint.Y - aStartPoint.Y ) + 1 );
+ // set standard's FLIP in below code
+ if ( eCt != drawing::ConnectorType_STANDARD)
+ {
+ if ( rGeoRect.Height < 0 ) // justify
+ {
+ rShapeFlags |= ShapeFlag::FlipV;
+ rGeoRect.Y = aEndPoint.Y;
+ rGeoRect.Height = -rGeoRect.Height;
+ }
+ if ( rGeoRect.Width < 0 )
+ {
+ rShapeFlags |= ShapeFlag::FlipH;
+ rGeoRect.X = aEndPoint.X;
+ rGeoRect.Width = -rGeoRect.Width;
+ }
+ }
+ sal_uInt32 nAdjustValue1, nAdjustValue2;
+ nAdjustValue1 = nAdjustValue2 = 0x2a30;
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "EdgeStartConnection" ) )
+ aAny >>= aShapeA;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "EdgeEndConnection" ) )
+ aAny >>= aShapeB;
+ rSolverContainer.AddConnector( rXShape, aStartPoint, aShapeA, aEndPoint, aShapeB );
+ switch ( eCt )
+ {
+ case drawing::ConnectorType_CURVE :
+ {
+ rShapeType = ESCHER_ShpInst_CurvedConnector3;
+ AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleCurved );
+ AddOpt( ESCHER_Prop_adjustValue, nAdjustValue1 );
+ AddOpt( ESCHER_Prop_adjust2Value, -static_cast<sal_Int32>(nAdjustValue2) );
+ }
+ break;
+
+ case drawing::ConnectorType_STANDARD :// Connector 2->5
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "PolyPolygonBezier" ) )
+ {
+ tools::PolyPolygon aPolyPolygon = GetPolyPolygon( aAny );
+ tools::Polygon aPoly;
+ if ( aPolyPolygon.Count() > 0 )
+ {
+ AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleBent );
+ aPoly = aPolyPolygon[ 0 ];
+ sal_Int32 nAdjCount = lcl_GetAdjustValueCount( aPoly );
+ rShapeType = static_cast<sal_uInt16>( ESCHER_ShpInst_BentConnector2 + nAdjCount);
+ for ( sal_Int32 i = 0 ; i < nAdjCount; ++ i)
+ AddOpt( static_cast<sal_uInt16>( ESCHER_Prop_adjustValue+i) , lcl_GetConnectorAdjustValue( aPoly, i ) );
+ }
+ sal_Int32 nAngle=0;
+ if (lcl_GetAngle(aPoly,rShapeFlags,nAngle ))
+ {
+ AddOpt( ESCHER_Prop_Rotation, nAngle );
+ }
+ }
+ else
+ {
+ rShapeType = ESCHER_ShpInst_BentConnector3;
+ AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleBent );
+ }
+ }
+ break;
+ default:
+ case drawing::ConnectorType_LINE :
+ case drawing::ConnectorType_LINES : // Connector 2->5
+ {
+ rShapeType = ESCHER_ShpInst_StraightConnector1;
+ AddOpt( ESCHER_Prop_cxstyle, ESCHER_cxstyleStraight );
+ }
+ break;
+ }
+ CreateLineProperties( aXPropSet, false );
+ bRetValue = true;
+ }
+ }
+ }
+ }
+ }
+ return bRetValue;
+}
+
+void EscherPropertyContainer::CreateShadowProperties(
+ const uno::Reference<beans::XPropertySet> & rXPropSet )
+{
+ uno::Any aAny;
+
+ sal_uInt32 nLineFlags = 0; // default : shape has no line
+ sal_uInt32 nFillFlags = 0x10; // shape is filled
+
+ GetOpt( ESCHER_Prop_fNoLineDrawDash, nLineFlags );
+ GetOpt( ESCHER_Prop_fNoFillHitTest, nFillFlags );
+
+ sal_uInt32 nDummy;
+ bool bGraphic = GetOpt( DFF_Prop_pib, nDummy ) || GetOpt( DFF_Prop_pibName, nDummy ) || GetOpt( DFF_Prop_pibFlags, nDummy );
+
+ sal_uInt32 nShadowFlags = 0x20000;
+ if ( ( nLineFlags & 8 ) || ( nFillFlags & 0x10 ) || bGraphic )
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "Shadow", true ) )
+ {
+ bool bHasShadow = false; // shadow is possible only if at least a fillcolor, linecolor or graphic is set
+ if ( (aAny >>= bHasShadow) && bHasShadow )
+ {
+ nShadowFlags |= 2;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "ShadowColor" ) )
+ AddOpt( ESCHER_Prop_shadowColor, ImplGetColor( *o3tl::doAccess<sal_uInt32>(aAny) ) );
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "ShadowXDistance" ) )
+ AddOpt( ESCHER_Prop_shadowOffsetX, *o3tl::doAccess<sal_Int32>(aAny) * 360 );
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "ShadowYDistance" ) )
+ AddOpt( ESCHER_Prop_shadowOffsetY, *o3tl::doAccess<sal_Int32>(aAny) * 360 );
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, rXPropSet, "ShadowTransparence" ) )
+ AddOpt( ESCHER_Prop_shadowOpacity, 0x10000 - (static_cast<sal_uInt32>(*o3tl::doAccess<sal_uInt16>(aAny)) * 655 ) );
+ }
+ }
+ }
+ AddOpt( ESCHER_Prop_fshadowObscured, nShadowFlags );
+}
+
+sal_Int32 EscherPropertyContainer::GetValueForEnhancedCustomShapeParameter( const drawing::EnhancedCustomShapeParameter& rParameter,
+ const std::vector< sal_Int32 >& rEquationOrder, bool bAdjustTrans )
+{
+ sal_Int32 nValue = 0;
+ if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
+ {
+ double fValue(0.0);
+ if ( rParameter.Value >>= fValue )
+ nValue = static_cast<sal_Int32>(fValue);
+ }
+ else
+ rParameter.Value >>= nValue;
+
+ switch( rParameter.Type )
+ {
+ case drawing::EnhancedCustomShapeParameterType::EQUATION :
+ {
+ size_t nIndex = static_cast<size_t>(nValue);
+ OSL_ASSERT(nIndex < rEquationOrder.size());
+ if ( nIndex < rEquationOrder.size() )
+ {
+ nValue = static_cast<sal_uInt16>(rEquationOrder[ nIndex ]);
+ nValue |= sal_uInt32(0x80000000);
+ }
+ }
+ break;
+ case drawing::EnhancedCustomShapeParameterType::ADJUSTMENT:
+ {
+ if(bAdjustTrans)
+ {
+ sal_uInt32 nAdjustValue = 0;
+ bool bGot = GetOpt(static_cast<sal_uInt16>( DFF_Prop_adjustValue + nValue ), nAdjustValue);
+ if(bGot) nValue = static_cast<sal_Int32>(nAdjustValue);
+ }
+ }
+ break;
+ case drawing::EnhancedCustomShapeParameterType::NORMAL :
+ default:
+ break;
+/* not sure if it is allowed to set following values
+(but they are not yet used)
+ case drawing::EnhancedCustomShapeParameterType::BOTTOM :
+ case drawing::EnhancedCustomShapeParameterType::RIGHT :
+ case drawing::EnhancedCustomShapeParameterType::TOP :
+ case drawing::EnhancedCustomShapeParameterType::LEFT :
+*/
+ }
+ return nValue;
+}
+
+static bool GetValueForEnhancedCustomShapeHandleParameter( sal_Int32& nRetValue, const drawing::EnhancedCustomShapeParameter& rParameter )
+{
+ bool bSpecial = false;
+ nRetValue = 0;
+ if ( rParameter.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
+ {
+ double fValue(0.0);
+ if ( rParameter.Value >>= fValue )
+ nRetValue = static_cast<sal_Int32>(fValue);
+ }
+ else
+ rParameter.Value >>= nRetValue;
+
+ switch( rParameter.Type )
+ {
+ case drawing::EnhancedCustomShapeParameterType::EQUATION :
+ {
+ nRetValue += 3;
+ bSpecial = true;
+ }
+ break;
+ case drawing::EnhancedCustomShapeParameterType::ADJUSTMENT :
+ {
+ nRetValue += 0x100;
+ bSpecial = true;
+ }
+ break;
+ case drawing::EnhancedCustomShapeParameterType::TOP :
+ case drawing::EnhancedCustomShapeParameterType::LEFT :
+ {
+ nRetValue = 0;
+ bSpecial = true;
+ }
+ break;
+ case drawing::EnhancedCustomShapeParameterType::RIGHT :
+ case drawing::EnhancedCustomShapeParameterType::BOTTOM :
+ {
+ nRetValue = 1;
+ bSpecial = true;
+ }
+ break;
+ case drawing::EnhancedCustomShapeParameterType::NORMAL :
+ {
+
+ }
+ break;
+ }
+ return bSpecial;
+}
+
+static void ConvertEnhancedCustomShapeEquation(
+ const SdrObjCustomShape& rSdrObjCustomShape,
+ std::vector< EnhancedCustomShapeEquation >& rEquations,
+ std::vector< sal_Int32 >& rEquationOrder )
+{
+ uno::Sequence< OUString > sEquationSource;
+ const SdrCustomShapeGeometryItem& rGeometryItem =
+ rSdrObjCustomShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
+ const uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "Equations" );
+ if ( pAny )
+ *pAny >>= sEquationSource;
+ sal_Int32 nEquationSourceCount = sEquationSource.getLength();
+ if ( !(nEquationSourceCount && (nEquationSourceCount <= 128)) )
+ return;
+
+ sal_Int32 i;
+ for ( i = 0; i < nEquationSourceCount; i++ )
+ {
+ EnhancedCustomShape2d aCustomShape2d(
+ const_cast< SdrObjCustomShape& >(rSdrObjCustomShape));
+ try
+ {
+ std::shared_ptr< EnhancedCustomShape::ExpressionNode > aExpressNode(
+ EnhancedCustomShape::FunctionParser::parseFunction(
+ sEquationSource[ i ], aCustomShape2d));
+ drawing::EnhancedCustomShapeParameter aPara( aExpressNode->fillNode( rEquations, nullptr, 0 ) );
+ if ( aPara.Type != drawing::EnhancedCustomShapeParameterType::EQUATION )
+ {
+ EnhancedCustomShapeEquation aEquation;
+ aEquation.nOperation = 0;
+ EnhancedCustomShape::FillEquationParameter( aPara, 0, aEquation );
+ rEquations.push_back( aEquation );
+ }
+ }
+ catch ( const EnhancedCustomShape::ParseError& )
+ {
+ EnhancedCustomShapeEquation aEquation; // ups, we should not be here,
+ aEquation.nOperation = 0; // creating a default equation with value 1
+ aEquation.nPara[ 0 ] = 1; // hoping that this will not break anything
+ rEquations.push_back( aEquation );
+ }
+ catch ( ... )
+ {
+ EnhancedCustomShapeEquation aEquation; // #i112309# EnhancedCustomShape::Parse error
+ aEquation.nOperation = 0; // not caught on linux platform
+ aEquation.nPara[ 0 ] = 1;
+ rEquations.push_back( aEquation );
+ }
+ rEquationOrder.push_back( rEquations.size() - 1 );
+ }
+ // now updating our old equation indices, they are marked with a bit in the hiword of nOperation
+ for (auto & equation : rEquations)
+ {
+ sal_uInt32 nMask = 0x20000000;
+ for( i = 0; i < 3; i++ )
+ {
+ if ( equation.nOperation & nMask )
+ {
+ equation.nOperation ^= nMask;
+ const size_t nIndex(equation.nPara[ i ] & 0x3ff);
+
+ // #i124661# check index access, there are cases where this is out of bound leading
+ // to errors up to crashes when executed
+ if(nIndex < rEquationOrder.size())
+ {
+ equation.nPara[ i ] = rEquationOrder[ nIndex ] | 0x400;
+ }
+ else
+ {
+ OSL_ENSURE(false, "Attempted out of bound access to rEquationOrder of CustomShape (!)");
+ }
+ }
+ nMask <<= 1;
+ }
+ }
+}
+
+bool EscherPropertyContainer::IsDefaultObject(
+ const SdrObjCustomShape& rSdrObjCustomShape,
+ const MSO_SPT eShapeType)
+{
+ switch(eShapeType)
+ {
+ // if the custom shape is not default shape of ppt, return false;
+ case mso_sptTearDrop:
+ return false;
+
+ default:
+ break;
+ }
+
+ return rSdrObjCustomShape.IsDefaultGeometry( SdrObjCustomShape::DefaultType::Equations )
+ && rSdrObjCustomShape.IsDefaultGeometry( SdrObjCustomShape::DefaultType::Viewbox )
+ && rSdrObjCustomShape.IsDefaultGeometry( SdrObjCustomShape::DefaultType::Path )
+ && rSdrObjCustomShape.IsDefaultGeometry( SdrObjCustomShape::DefaultType::Gluepoints )
+ && rSdrObjCustomShape.IsDefaultGeometry( SdrObjCustomShape::DefaultType::Segments )
+ && rSdrObjCustomShape.IsDefaultGeometry( SdrObjCustomShape::DefaultType::StretchX )
+ && rSdrObjCustomShape.IsDefaultGeometry( SdrObjCustomShape::DefaultType::StretchY )
+ && rSdrObjCustomShape.IsDefaultGeometry( SdrObjCustomShape::DefaultType::TextFrames );
+}
+
+void EscherPropertyContainer::LookForPolarHandles( const MSO_SPT eShapeType, sal_Int32& nAdjustmentsWhichNeedsToBeConverted )
+{
+ const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( eShapeType );
+ if ( !(pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles) )
+ return;
+
+ sal_Int32 k, nkCount = pDefCustomShape->nHandles;
+ const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
+ for ( k = 0; k < nkCount; k++, pData++ )
+ {
+ if ( pData->nFlags & SvxMSDffHandleFlags::POLAR )
+ {
+ if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) )
+ nAdjustmentsWhichNeedsToBeConverted |= ( 1 << k );
+ }
+ }
+}
+
+bool EscherPropertyContainer::GetAdjustmentValue( const drawing::EnhancedCustomShapeAdjustmentValue & rkProp, sal_Int32 nIndex, sal_Int32 nAdjustmentsWhichNeedsToBeConverted, sal_Int32& nValue )
+{
+ if ( rkProp.State != beans::PropertyState_DIRECT_VALUE )
+ return false;
+
+ bool bUseFixedFloat = ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << nIndex ) ) != 0;
+ if ( rkProp.Value.getValueTypeClass() == uno::TypeClass_DOUBLE )
+ {
+ double fValue(0.0);
+ rkProp.Value >>= fValue;
+ if ( bUseFixedFloat )
+ fValue *= 65536.0;
+ nValue = static_cast<sal_Int32>(fValue);
+ }
+ else
+ {
+ rkProp.Value >>= nValue;
+ if ( bUseFixedFloat )
+ nValue <<= 16;
+ }
+
+ return true;
+}
+
+void EscherPropertyContainer::CreateCustomShapeProperties( const MSO_SPT eShapeType, const uno::Reference< drawing::XShape > & rXShape )
+{
+ uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
+ if ( !aXPropSet.is() )
+ return;
+
+ SdrObjCustomShape* pSdrObjCustomShape = dynamic_cast< SdrObjCustomShape* >(SdrObject::getSdrObjectFromXShape(rXShape));
+ if(!pSdrObjCustomShape)
+ {
+ return;
+ }
+
+ SdrObjCustomShape& rSdrObjCustomShape = *pSdrObjCustomShape;
+ uno::Any aGeoPropSet = aXPropSet->getPropertyValue( "CustomShapeGeometry" );
+ uno::Sequence< beans::PropertyValue > aGeoPropSeq;
+ if ( !(aGeoPropSet >>= aGeoPropSeq) )
+ return;
+
+ static const OUStringLiteral sViewBox ( u"ViewBox" );
+ static const OUStringLiteral sTextRotateAngle ( u"TextRotateAngle" );
+ static const OUStringLiteral sExtrusion ( u"Extrusion" );
+ static const OUStringLiteral sEquations ( u"Equations" );
+ static const OUStringLiteral sPath ( u"Path" );
+ static const OUStringLiteral sTextPath ( u"TextPath" );
+ static const OUStringLiteral sHandles ( u"Handles" );
+ static const OUStringLiteral sAdjustmentValues ( u"AdjustmentValues" );
+
+ bool bAdjustmentValuesProp = false;
+ uno::Any aAdjustmentValuesProp;
+ bool bPathCoordinatesProp = false;
+ uno::Any aPathCoordinatesProp;
+
+ sal_Int32 nAdjustmentsWhichNeedsToBeConverted = 0;
+ uno::Sequence< beans::PropertyValues > aHandlesPropSeq;
+ bool bPredefinedHandlesUsed = true;
+ const bool bIsDefaultObject(
+ IsDefaultObject(
+ rSdrObjCustomShape,
+ eShapeType));
+
+ // convert property "Equations" into std::vector< EnhancedCustomShapeEquationEquation >
+ std::vector< EnhancedCustomShapeEquation > aEquations;
+ std::vector< sal_Int32 > aEquationOrder;
+ ConvertEnhancedCustomShapeEquation(
+ rSdrObjCustomShape,
+ aEquations,
+ aEquationOrder);
+
+ sal_Int32 i, nCount = aGeoPropSeq.getLength();
+ for ( i = 0; i < nCount; i++ )
+ {
+ const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
+ if ( rProp.Name == sViewBox )
+ {
+ if ( !bIsDefaultObject )
+ {
+ awt::Rectangle aViewBox;
+ if ( rProp.Value >>= aViewBox )
+ {
+ AddOpt( DFF_Prop_geoLeft, aViewBox.X );
+ AddOpt( DFF_Prop_geoTop, aViewBox.Y );
+ AddOpt( DFF_Prop_geoRight, aViewBox.X + aViewBox.Width );
+ AddOpt( DFF_Prop_geoBottom,aViewBox.Y + aViewBox.Height );
+ }
+ }
+ }
+ else if ( rProp.Name == sTextRotateAngle )
+ {
+ double f = 0;
+ if ( rProp.Value >>= f )
+ {
+ double fTextRotateAngle = fmod( f, 360.0 );
+ if ( fTextRotateAngle < 0 )
+ fTextRotateAngle = 360 + fTextRotateAngle;
+ if ( ( fTextRotateAngle < 271.0 ) && ( fTextRotateAngle > 269.0 ) )
+ AddOpt( DFF_Prop_cdirFont, mso_cdir90 );
+ else if ( ( fTextRotateAngle < 181.0 ) && ( fTextRotateAngle > 179.0 ) )
+ AddOpt( DFF_Prop_cdirFont, mso_cdir180 );
+ else if ( ( fTextRotateAngle < 91.0 ) && ( fTextRotateAngle > 79.0 ) )
+ AddOpt( DFF_Prop_cdirFont, mso_cdir270 );
+ }
+ }
+ else if ( rProp.Name == sExtrusion )
+ {
+ uno::Sequence< beans::PropertyValue > aExtrusionPropSeq;
+ if ( rProp.Value >>= aExtrusionPropSeq )
+ {
+ sal_uInt32 nLightFaceFlagsOrg, nLightFaceFlags;
+ sal_uInt32 nFillHarshFlagsOrg, nFillHarshFlags;
+ nLightFaceFlagsOrg = nLightFaceFlags = 0x000001;
+ nFillHarshFlagsOrg = nFillHarshFlags = 0x00001e;
+ if ( GetOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags ) )
+ nLightFaceFlagsOrg = nLightFaceFlags;
+ if ( GetOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags ) )
+ nFillHarshFlagsOrg = nFillHarshFlags;
+
+ sal_Int32 r, nrCount = aExtrusionPropSeq.getLength();
+ for ( r = 0; r < nrCount; r++ )
+ {
+ const beans::PropertyValue& rrProp = aExtrusionPropSeq[ r ];
+
+ if ( rrProp.Name == sExtrusion )
+ {
+ bool bExtrusionOn;
+ if ( rrProp.Value >>= bExtrusionOn )
+ {
+ nLightFaceFlags |= 0x80000;
+ if ( bExtrusionOn )
+ nLightFaceFlags |= 8;
+ else
+ nLightFaceFlags &=~8;
+ }
+ }
+ else if ( rrProp.Name == "Brightness" )
+ {
+ double fExtrusionBrightness = 0;
+ if ( rrProp.Value >>= fExtrusionBrightness )
+ AddOpt( DFF_Prop_c3DAmbientIntensity, static_cast<sal_Int32>( fExtrusionBrightness * 655.36 ) );
+ }
+ else if ( rrProp.Name == "Depth" )
+ {
+ double fDepth = 0;
+ double fFraction = 0;
+ drawing::EnhancedCustomShapeParameterPair aDepthParaPair;
+ if ( ( rrProp.Value >>= aDepthParaPair ) && ( aDepthParaPair.First.Value >>= fDepth ) && ( aDepthParaPair.Second.Value >>= fFraction ) )
+ {
+ double fForeDepth = fDepth * fFraction;
+ double fBackDepth = fDepth - fForeDepth;
+
+ fBackDepth *= 360.0;
+ AddOpt( DFF_Prop_c3DExtrudeBackward, static_cast<sal_Int32>(fBackDepth) );
+
+ if ( fForeDepth != 0.0 )
+ {
+ fForeDepth *= 360.0;
+ AddOpt( DFF_Prop_c3DExtrudeForward, static_cast<sal_Int32>(fForeDepth) );
+ }
+ }
+ }
+ else if ( rrProp.Name == "Diffusion" )
+ {
+ double fExtrusionDiffusion = 0;
+ if ( rrProp.Value >>= fExtrusionDiffusion )
+ AddOpt( DFF_Prop_c3DDiffuseAmt, static_cast<sal_Int32>( fExtrusionDiffusion * 655.36 ) );
+ }
+ else if ( rrProp.Name == "NumberOfLineSegments" )
+ {
+ sal_Int32 nExtrusionNumberOfLineSegments = 0;
+ if ( rrProp.Value >>= nExtrusionNumberOfLineSegments )
+ AddOpt( DFF_Prop_c3DTolerance, nExtrusionNumberOfLineSegments );
+ }
+ else if ( rrProp.Name == "LightFace" )
+ {
+ bool bExtrusionLightFace;
+ if ( rrProp.Value >>= bExtrusionLightFace )
+ {
+ nLightFaceFlags |= 0x10000;
+ if ( bExtrusionLightFace )
+ nLightFaceFlags |= 1;
+ else
+ nLightFaceFlags &=~1;
+ }
+ }
+ else if ( rrProp.Name == "FirstLightHarsh" )
+ {
+ bool bExtrusionFirstLightHarsh;
+ if ( rrProp.Value >>= bExtrusionFirstLightHarsh )
+ {
+ nFillHarshFlags |= 0x20000;
+ if ( bExtrusionFirstLightHarsh )
+ nFillHarshFlags |= 2;
+ else
+ nFillHarshFlags &=~2;
+ }
+ }
+ else if ( rrProp.Name == "SecondLightHarsh" )
+ {
+ bool bExtrusionSecondLightHarsh;
+ if ( rrProp.Value >>= bExtrusionSecondLightHarsh )
+ {
+ nFillHarshFlags |= 0x10000;
+ if ( bExtrusionSecondLightHarsh )
+ nFillHarshFlags |= 1;
+ else
+ nFillHarshFlags &=~1;
+ }
+ }
+ else if ( rrProp.Name == "FirstLightLevel" )
+ {
+ double fExtrusionFirstLightLevel = 0;
+ if ( rrProp.Value >>= fExtrusionFirstLightLevel )
+ AddOpt( DFF_Prop_c3DKeyIntensity, static_cast<sal_Int32>( fExtrusionFirstLightLevel * 655.36 ) );
+ }
+ else if ( rrProp.Name == "SecondLightLevel" )
+ {
+ double fExtrusionSecondLightLevel = 0;
+ if ( rrProp.Value >>= fExtrusionSecondLightLevel )
+ AddOpt( DFF_Prop_c3DFillIntensity, static_cast<sal_Int32>( fExtrusionSecondLightLevel * 655.36 ) );
+ }
+ else if ( rrProp.Name == "FirstLightDirection" )
+ {
+ drawing::Direction3D aExtrusionFirstLightDirection;
+ if ( rrProp.Value >>= aExtrusionFirstLightDirection )
+ {
+ AddOpt( DFF_Prop_c3DKeyX, static_cast<sal_Int32>(aExtrusionFirstLightDirection.DirectionX) );
+ AddOpt( DFF_Prop_c3DKeyY, static_cast<sal_Int32>(aExtrusionFirstLightDirection.DirectionY) );
+ AddOpt( DFF_Prop_c3DKeyZ, static_cast<sal_Int32>(aExtrusionFirstLightDirection.DirectionZ) );
+ }
+ }
+ else if ( rrProp.Name == "SecondLightDirection" )
+ {
+ drawing::Direction3D aExtrusionSecondLightPosition;
+ if ( rrProp.Value >>= aExtrusionSecondLightPosition )
+ {
+ AddOpt( DFF_Prop_c3DFillX, static_cast<sal_Int32>(aExtrusionSecondLightPosition.DirectionX) );
+ AddOpt( DFF_Prop_c3DFillY, static_cast<sal_Int32>(aExtrusionSecondLightPosition.DirectionY) );
+ AddOpt( DFF_Prop_c3DFillZ, static_cast<sal_Int32>(aExtrusionSecondLightPosition.DirectionZ) );
+ }
+ }
+ else if ( rrProp.Name == "Metal" )
+ {
+ bool bExtrusionMetal;
+ if ( rrProp.Value >>= bExtrusionMetal )
+ {
+ nLightFaceFlags |= 0x40000;
+ if ( bExtrusionMetal )
+ nLightFaceFlags |= 4;
+ else
+ nLightFaceFlags &=~4;
+ }
+ }
+ else if ( rrProp.Name == "ShadeMode" )
+ {
+ drawing::ShadeMode eExtrusionShadeMode;
+ if ( rrProp.Value >>= eExtrusionShadeMode )
+ {
+ sal_uInt32 nRenderMode;
+ switch( eExtrusionShadeMode )
+ {
+ default:
+ case drawing::ShadeMode_FLAT :
+ case drawing::ShadeMode_PHONG :
+ case drawing::ShadeMode_SMOOTH :
+ nRenderMode = mso_FullRender;
+ break;
+ case drawing::ShadeMode_DRAFT :
+ {
+ nRenderMode = mso_Wireframe;
+ }
+ break;
+ }
+ AddOpt( DFF_Prop_c3DRenderMode, nRenderMode );
+ }
+ }
+ else if ( rrProp.Name == "RotateAngle" )
+ {
+ double fExtrusionAngleX = 0;
+ double fExtrusionAngleY = 0;
+ drawing::EnhancedCustomShapeParameterPair aRotateAnglePair;
+ if ( ( rrProp.Value >>= aRotateAnglePair ) && ( aRotateAnglePair.First.Value >>= fExtrusionAngleX ) && ( aRotateAnglePair.Second.Value >>= fExtrusionAngleY ) )
+ {
+ fExtrusionAngleX *= 65536;
+ fExtrusionAngleY *= 65536;
+ AddOpt( DFF_Prop_c3DXRotationAngle, static_cast<sal_Int32>(fExtrusionAngleX) );
+ AddOpt( DFF_Prop_c3DYRotationAngle, static_cast<sal_Int32>(fExtrusionAngleY) );
+ }
+ }
+ else if ( rrProp.Name == "RotationCenter" )
+ {
+ drawing::Direction3D aExtrusionRotationCenter;
+ if ( rrProp.Value >>= aExtrusionRotationCenter )
+ {
+ // tdf#145904 X- and Y-component is fraction, Z-component in EMU
+ AddOpt( DFF_Prop_c3DRotationCenterX, static_cast<sal_Int32>( aExtrusionRotationCenter.DirectionX * 65536.0 ) );
+ AddOpt( DFF_Prop_c3DRotationCenterY, static_cast<sal_Int32>( aExtrusionRotationCenter.DirectionY * 65536.0 ) );
+ AddOpt( DFF_Prop_c3DRotationCenterZ, static_cast<sal_Int32>( aExtrusionRotationCenter.DirectionZ * 360.0 ) );
+ nFillHarshFlags &=~8; // don't use AutoRotationCenter;
+ }
+ }
+ else if ( rrProp.Name == "Shininess" )
+ {
+ double fExtrusionShininess = 0;
+ if ( rrProp.Value >>= fExtrusionShininess )
+ {
+ // ODF to MS Office conversion invers to msdffimp.cxx
+ fExtrusionShininess = basegfx::fround(fExtrusionShininess / 10.0);
+ AddOpt( DFF_Prop_c3DShininess, static_cast<sal_Int32>(fExtrusionShininess) );
+ }
+ }
+ else if ( rrProp.Name == "Skew" )
+ {
+ double fSkewAmount = 0;
+ double fSkewAngle = 0;
+ drawing::EnhancedCustomShapeParameterPair aSkewParaPair;
+ if ( ( rrProp.Value >>= aSkewParaPair ) && ( aSkewParaPair.First.Value >>= fSkewAmount ) && ( aSkewParaPair.Second.Value >>= fSkewAngle ) )
+ {
+ AddOpt( DFF_Prop_c3DSkewAmount, static_cast<sal_Int32>(fSkewAmount) );
+ AddOpt( DFF_Prop_c3DSkewAngle, static_cast<sal_Int32>( fSkewAngle * 65536 ) );
+ }
+ }
+ else if ( rrProp.Name == "Specularity" )
+ {
+ double fExtrusionSpecularity = 0;
+ if ( rrProp.Value >>= fExtrusionSpecularity )
+ AddOpt( DFF_Prop_c3DSpecularAmt, static_cast<sal_Int32>( fExtrusionSpecularity * 655.36 ) );
+ }
+ else if ( rrProp.Name == "ProjectionMode" )
+ {
+ drawing::ProjectionMode eExtrusionProjectionMode;
+ if ( rrProp.Value >>= eExtrusionProjectionMode )
+ {
+ nFillHarshFlags |= 0x40000;
+ if ( eExtrusionProjectionMode == drawing::ProjectionMode_PARALLEL )
+ nFillHarshFlags |= 4;
+ else
+ nFillHarshFlags &=~4;
+ }
+ }
+ else if ( rrProp.Name == "ViewPoint" )
+ {
+ drawing::Position3D aExtrusionViewPoint;
+ if ( rrProp.Value >>= aExtrusionViewPoint )
+ {
+ aExtrusionViewPoint.PositionX *= 360.0;
+ aExtrusionViewPoint.PositionY *= 360.0;
+ aExtrusionViewPoint.PositionZ *= 360.0;
+ AddOpt( DFF_Prop_c3DXViewpoint, static_cast<sal_Int32>(aExtrusionViewPoint.PositionX) );
+ AddOpt( DFF_Prop_c3DYViewpoint, static_cast<sal_Int32>(aExtrusionViewPoint.PositionY) );
+ AddOpt( DFF_Prop_c3DZViewpoint, static_cast<sal_Int32>(aExtrusionViewPoint.PositionZ) );
+ }
+ }
+ else if ( rrProp.Name == "Origin" )
+ {
+ double fExtrusionOriginX = 0;
+ double fExtrusionOriginY = 0;
+ drawing::EnhancedCustomShapeParameterPair aOriginPair;
+ if ( ( rrProp.Value >>= aOriginPair ) && ( aOriginPair.First.Value >>= fExtrusionOriginX ) && ( aOriginPair.Second.Value >>= fExtrusionOriginY ) )
+ {
+ AddOpt( DFF_Prop_c3DOriginX, static_cast<sal_Int32>( fExtrusionOriginX * 65536 ) );
+ AddOpt( DFF_Prop_c3DOriginY, static_cast<sal_Int32>( fExtrusionOriginY * 65536 ) );
+ }
+ }
+ else if ( rrProp.Name == "Color" )
+ {
+ bool bExtrusionColor;
+ if ( rrProp.Value >>= bExtrusionColor )
+ {
+ nLightFaceFlags |= 0x20000;
+ if ( bExtrusionColor )
+ {
+ nLightFaceFlags |= 2;
+ uno::Any aFillColor2;
+ if ( EscherPropertyValueHelper::GetPropertyValue( aFillColor2, aXPropSet, "FillColor2", true ) )
+ {
+ sal_uInt32 nFillColor = ImplGetColor( *o3tl::doAccess<sal_uInt32>(aFillColor2) );
+ AddOpt( DFF_Prop_c3DExtrusionColor, nFillColor );
+ }
+ }
+ else
+ nLightFaceFlags &=~2;
+ }
+ }
+ }
+ if ( nLightFaceFlags != nLightFaceFlagsOrg )
+ AddOpt( DFF_Prop_fc3DLightFace, nLightFaceFlags );
+ if ( nFillHarshFlags != nFillHarshFlagsOrg )
+ AddOpt( DFF_Prop_fc3DFillHarsh, nFillHarshFlags );
+ }
+ }
+ else if ( rProp.Name == sEquations )
+ {
+ if ( !bIsDefaultObject )
+ {
+ sal_uInt16 nElements = static_cast<sal_uInt16>(aEquations.size());
+ if ( nElements )
+ {
+ sal_uInt16 nElementSize = 8;
+ sal_uInt32 nStreamSize = nElementSize * nElements + 6;
+ SvMemoryStream aMemStrm( nStreamSize );
+ aMemStrm.WriteUInt16( nElements )
+ .WriteUInt16( nElements )
+ .WriteUInt16( nElementSize );
+
+ for (auto const& equation : aEquations)
+ {
+ aMemStrm.WriteUInt16( equation.nOperation )
+ .WriteInt16(
+ std::clamp(
+ equation.nPara[ 0 ], sal_Int32(SAL_MIN_INT16),
+ sal_Int32(SAL_MAX_INT16)) )
+ .WriteInt16(
+ std::clamp(
+ equation.nPara[ 1 ], sal_Int32(SAL_MIN_INT16),
+ sal_Int32(SAL_MAX_INT16)) )
+ .WriteInt16(
+ std::clamp(
+ equation.nPara[ 2 ], sal_Int32(SAL_MIN_INT16),
+ sal_Int32(SAL_MAX_INT16)) );
+ }
+
+ AddOpt(DFF_Prop_pFormulas, true, 6, aMemStrm);
+ }
+ else
+ {
+ AddOpt(DFF_Prop_pFormulas, 0, true);
+ }
+ }
+ }
+ else if ( rProp.Name == sPath )
+ {
+ uno::Sequence< beans::PropertyValue > aPathPropSeq;
+ if ( rProp.Value >>= aPathPropSeq )
+ {
+ sal_uInt32 nPathFlags, nPathFlagsOrg;
+ nPathFlagsOrg = nPathFlags = 0x39;
+ if ( GetOpt( DFF_Prop_fFillOK, nPathFlags ) )
+ nPathFlagsOrg = nPathFlags;
+
+ sal_Int32 r, nrCount = aPathPropSeq.getLength();
+ for ( r = 0; r < nrCount; r++ )
+ {
+ const beans::PropertyValue& rrProp = aPathPropSeq[ r ];
+
+ if ( rrProp.Name == "ExtrusionAllowed" )
+ {
+ bool bExtrusionAllowed;
+ if ( rrProp.Value >>= bExtrusionAllowed )
+ {
+ nPathFlags |= 0x100000;
+ if ( bExtrusionAllowed )
+ nPathFlags |= 16;
+ else
+ nPathFlags &=~16;
+ }
+ }
+ else if ( rrProp.Name == "ConcentricGradientFillAllowed" )
+ {
+ bool bConcentricGradientFillAllowed;
+ if ( rrProp.Value >>= bConcentricGradientFillAllowed )
+ {
+ nPathFlags |= 0x20000;
+ if ( bConcentricGradientFillAllowed )
+ nPathFlags |= 2;
+ else
+ nPathFlags &=~2;
+ }
+ }
+ else if ( rrProp.Name == "TextPathAllowed" )
+ {
+ bool bTextPathAllowed;
+ if ( rrProp.Value >>= bTextPathAllowed )
+ {
+ nPathFlags |= 0x40000;
+ if ( bTextPathAllowed )
+ nPathFlags |= 4;
+ else
+ nPathFlags &=~4;
+ }
+ }
+ else if ( rrProp.Name == "Coordinates" )
+ {
+ if ( !bIsDefaultObject )
+ {
+ aPathCoordinatesProp = rrProp.Value;
+ bPathCoordinatesProp = true;
+ }
+ }
+ else if ( rrProp.Name == "GluePoints" )
+ {
+ if ( !bIsDefaultObject )
+ {
+ uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aGluePoints;
+ if ( rrProp.Value >>= aGluePoints )
+ {
+ // creating the vertices
+ sal_uInt16 nElements = static_cast<sal_uInt16>(aGluePoints.getLength());
+ if ( nElements )
+ {
+ sal_uInt16 j, nElementSize = 8;
+ sal_uInt32 nStreamSize = nElementSize * nElements + 6;
+ SvMemoryStream aMemStrm( nStreamSize );
+ aMemStrm.WriteUInt16( nElements )
+ .WriteUInt16( nElements )
+ .WriteUInt16( nElementSize );
+ for( j = 0; j < nElements; j++ )
+ {
+ sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].First, aEquationOrder );
+ sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aGluePoints[ j ].Second, aEquationOrder );
+ aMemStrm.WriteInt32( X )
+ .WriteInt32( Y );
+ }
+
+ AddOpt(DFF_Prop_connectorPoints, true, 6, aMemStrm); // -6
+ }
+ else
+ {
+ AddOpt(DFF_Prop_connectorPoints, 0, true);
+ }
+ }
+ }
+ }
+ else if ( rrProp.Name == "GluePointType" )
+ {
+ sal_Int16 nGluePointType = sal_Int16();
+ if ( rrProp.Value >>= nGluePointType )
+ AddOpt( DFF_Prop_connectorType, static_cast<sal_uInt16>(nGluePointType) );
+ }
+ else if ( rrProp.Name == "Segments" )
+ {
+ if ( !bIsDefaultObject )
+ {
+ uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments;
+ if ( rrProp.Value >>= aSegments )
+ {
+ // creating seginfo
+ if ( aSegments.hasElements() )
+ {
+ sal_uInt16 j, nElements = static_cast<sal_uInt16>(aSegments.getLength());
+ sal_uInt16 nElementSize = 2;
+ sal_uInt32 nStreamSize = nElementSize * nElements + 6;
+ SvMemoryStream aMemStrm( nStreamSize );
+ aMemStrm.WriteUInt16( nElements )
+ .WriteUInt16( nElements )
+ .WriteUInt16( nElementSize );
+ for ( j = 0; j < nElements; j++ )
+ {
+ // The segment type is stored in the upper 3 bits
+ // and segment count is stored in the lower 13
+ // bits.
+ //
+ // If the segment type is msopathEscape, the lower 13 bits
+ // are divided in a 5 bit escape code and 8 bit
+ // vertex count (not segment count!)
+ sal_uInt16 nVal = static_cast<sal_uInt16>(aSegments[ j ].Count);
+ switch( aSegments[ j ].Command )
+ {
+ case drawing::EnhancedCustomShapeSegmentCommand::UNKNOWN :
+ case drawing::EnhancedCustomShapeSegmentCommand::LINETO :
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::MOVETO :
+ nVal = (msopathMoveTo << 13);
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::CURVETO :
+ {
+ nVal |= (msopathCurveTo << 13);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
+ {
+ nVal = 1;
+ nVal |= (msopathClose << 13);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
+ {
+ nVal = (msopathEnd << 13);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::NOFILL :
+ {
+ nVal = (msopathEscape << 13) | (10 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::NOSTROKE :
+ {
+ nVal = (msopathEscape << 13) | (11 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
+ {
+ nVal *= 3;
+ nVal |= (msopathEscape << 13) | (1 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
+ {
+ nVal *= 3;
+ nVal |= (msopathEscape << 13) | (2 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::ARCTO :
+ {
+ nVal <<= 2;
+ nVal |= (msopathEscape << 13) | (3 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::ARC :
+ {
+ nVal <<= 2;
+ nVal |= (msopathEscape << 13) | (4 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
+ {
+ nVal <<= 2;
+ nVal |= (msopathEscape << 13) | (5 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
+ {
+ nVal <<= 2;
+ nVal |= (msopathEscape << 13) | (6 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
+ {
+ nVal |= (msopathEscape << 13) | (7 << 8);
+ }
+ break;
+ case drawing::EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
+ {
+ nVal |= (msopathEscape << 13) | (8 << 8);
+ }
+ break;
+ }
+ aMemStrm.WriteUInt16( nVal );
+ }
+
+ AddOpt(DFF_Prop_pSegmentInfo, false, 6, aMemStrm);
+ }
+ else
+ {
+ AddOpt(DFF_Prop_pSegmentInfo, 0, true);
+ }
+ }
+ }
+ }
+ else if ( rrProp.Name == "StretchX" )
+ {
+ if ( !bIsDefaultObject )
+ {
+ sal_Int32 nStretchX = 0;
+ if ( rrProp.Value >>= nStretchX )
+ AddOpt( DFF_Prop_stretchPointX, nStretchX );
+ }
+ }
+ else if ( rrProp.Name == "StretchY" )
+ {
+ if ( !bIsDefaultObject )
+ {
+ sal_Int32 nStretchY = 0;
+ if ( rrProp.Value >>= nStretchY )
+ AddOpt( DFF_Prop_stretchPointY, nStretchY );
+ }
+ }
+ else if ( rrProp.Name == "TextFrames" )
+ {
+ if ( !bIsDefaultObject )
+ {
+ uno::Sequence<drawing::EnhancedCustomShapeTextFrame> aPathTextFrames;
+ if ( rrProp.Value >>= aPathTextFrames )
+ {
+ if ( aPathTextFrames.hasElements() )
+ {
+ sal_uInt16 j, nElements = static_cast<sal_uInt16>(aPathTextFrames.getLength());
+ sal_uInt16 nElementSize = 16;
+ sal_uInt32 nStreamSize = nElementSize * nElements + 6;
+ SvMemoryStream aMemStrm( nStreamSize );
+ aMemStrm.WriteUInt16( nElements )
+ .WriteUInt16( nElements )
+ .WriteUInt16( nElementSize );
+ for ( j = 0; j < nElements; j++ )
+ {
+ sal_Int32 nLeft = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.First, aEquationOrder );
+ sal_Int32 nTop = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].TopLeft.Second, aEquationOrder );
+ sal_Int32 nRight = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.First, aEquationOrder );
+ sal_Int32 nBottom = GetValueForEnhancedCustomShapeParameter( aPathTextFrames[ j ].BottomRight.Second, aEquationOrder );
+
+ aMemStrm.WriteInt32( nLeft )
+ .WriteInt32( nTop )
+ .WriteInt32( nRight )
+ .WriteInt32( nBottom );
+ }
+
+ AddOpt(DFF_Prop_textRectangles, true, 6, aMemStrm);
+ }
+ else
+ {
+ AddOpt(DFF_Prop_textRectangles, 0, true);
+ }
+ }
+ }
+ }
+ }
+ if ( nPathFlags != nPathFlagsOrg )
+ AddOpt( DFF_Prop_fFillOK, nPathFlags );
+ }
+ }
+ else if ( rProp.Name == sTextPath )
+ {
+ uno::Sequence< beans::PropertyValue > aTextPathPropSeq;
+ if ( rProp.Value >>= aTextPathPropSeq )
+ {
+ sal_uInt32 nTextPathFlagsOrg, nTextPathFlags;
+ nTextPathFlagsOrg = nTextPathFlags = 0xffff1000; // default
+ if ( GetOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags ) )
+ nTextPathFlagsOrg = nTextPathFlags;
+
+ sal_Int32 r, nrCount = aTextPathPropSeq.getLength();
+ for ( r = 0; r < nrCount; r++ )
+ {
+ const beans::PropertyValue& rrProp = aTextPathPropSeq[ r ];
+
+ if ( rrProp.Name == sTextPath )
+ {
+ bool bTextPathOn;
+ if ( rrProp.Value >>= bTextPathOn )
+ {
+ nTextPathFlags |= 0x40000000;
+ if ( bTextPathOn )
+ {
+ nTextPathFlags |= 0x4000;
+
+ sal_uInt32 nPathFlags = 0x39;
+ GetOpt( DFF_Prop_fFillOK, nPathFlags ); // SJ: can be removed if we are supporting the TextPathAllowed property in XML
+ nPathFlags |= 0x40004;
+ AddOpt( DFF_Prop_fFillOK, nPathFlags );
+ }
+ else
+ nTextPathFlags &=~0x4000;
+ }
+ }
+ else if ( rrProp.Name == "TextPathMode" )
+ {
+ drawing::EnhancedCustomShapeTextPathMode eTextPathMode;
+ if ( rrProp.Value >>= eTextPathMode )
+ {
+ nTextPathFlags |= 0x05000000;
+ nTextPathFlags &=~0x500; // TextPathMode_NORMAL
+ if ( eTextPathMode == drawing::EnhancedCustomShapeTextPathMode_PATH )
+ nTextPathFlags |= 0x100;
+ else if ( eTextPathMode == drawing::EnhancedCustomShapeTextPathMode_SHAPE )
+ nTextPathFlags |= 0x500;
+ }
+ }
+ else if ( rrProp.Name == "ScaleX" )
+ {
+ bool bTextPathScaleX;
+ if ( rrProp.Value >>= bTextPathScaleX )
+ {
+ nTextPathFlags |= 0x00400000;
+ if ( bTextPathScaleX )
+ nTextPathFlags |= 0x40;
+ else
+ nTextPathFlags &=~0x40;
+ }
+ }
+ else if ( rrProp.Name == "SameLetterHeights" )
+ {
+ bool bSameLetterHeights;
+ if ( rrProp.Value >>= bSameLetterHeights )
+ {
+ nTextPathFlags |= 0x00800000;
+ if ( bSameLetterHeights )
+ nTextPathFlags |= 0x80;
+ else
+ nTextPathFlags &=~0x80;
+ }
+ }
+ }
+ if ( nTextPathFlags & 0x4000 ) // Is FontWork ?
+ {
+ // FontWork Text
+ OUString aText;
+ uno::Reference< text::XSimpleText > xText( rXShape, uno::UNO_QUERY );
+ if ( xText.is() )
+ aText = xText->getString();
+ if ( aText.isEmpty() )
+ aText = "your text"; // TODO: moving into a resource
+ AddOpt( DFF_Prop_gtextUNICODE, aText );
+
+ // FontWork Font
+ OUString aFontName;
+ uno::Any aAny = aXPropSet->getPropertyValue( "CharFontName" );
+ aAny >>= aFontName;
+ if ( aFontName.isEmpty() )
+ aFontName = "Arial Black";
+ AddOpt( DFF_Prop_gtextFont, aFontName );
+
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "CharScaleWidth", true ) )
+ {
+ sal_Int16 nCharScaleWidth = 100;
+ if ( aAny >>= nCharScaleWidth )
+ {
+ if ( nCharScaleWidth != 100 )
+ {
+ sal_Int32 nVal = nCharScaleWidth * 655;
+ AddOpt( DFF_Prop_gtextSpacing, nVal );
+ }
+ }
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "CharHeight", true ) )
+ {
+ float fCharHeight = 0.0;
+ if ( aAny >>= fCharHeight )
+ {
+ sal_Int32 nTextSize = static_cast< sal_Int32 > ( fCharHeight * 65536 );
+ AddOpt(ESCHER_Prop_gtextSize, nTextSize);
+ }
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "CharKerning", true ) )
+ {
+ sal_Int16 nCharKerning = sal_Int16();
+ if ( aAny >>= nCharKerning )
+ {
+ nTextPathFlags |= 0x10000000;
+ if ( nCharKerning )
+ nTextPathFlags |= 0x1000;
+ else
+ nTextPathFlags &=~0x1000;
+ }
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "CharPosture", true ) )
+ {
+ awt::FontSlant eFontSlant;
+ if ( aAny >>= eFontSlant )
+ {
+ nTextPathFlags |= 0x100010;
+ if ( eFontSlant != awt::FontSlant_NONE )
+ nTextPathFlags |= 0x10;
+ else
+ nTextPathFlags &=~0x10;
+ }
+ }
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "CharWeight", true ) )
+ {
+ float fFontWidth = 0;
+ if ( aAny >>= fFontWidth )
+ {
+ nTextPathFlags |= 0x200020;
+ if ( fFontWidth > awt::FontWeight::NORMAL )
+ nTextPathFlags |= 0x20;
+ else
+ nTextPathFlags &=~0x20;
+ }
+ }
+ // export gTextAlign attr
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aXPropSet, "TextHorizontalAdjust", true ) )
+ {
+ MSO_GeoTextAlign gTextAlign = mso_alignTextCenter;
+ drawing::TextHorizontalAdjust eHA( drawing::TextHorizontalAdjust_LEFT );
+ aAny >>= eHA;
+ switch( eHA )
+ {
+ case drawing::TextHorizontalAdjust_LEFT :
+ gTextAlign = mso_alignTextLeft;
+ break;
+ case drawing::TextHorizontalAdjust_CENTER:
+ gTextAlign = mso_alignTextCenter;
+ break;
+ case drawing::TextHorizontalAdjust_RIGHT:
+ gTextAlign = mso_alignTextRight;
+ break;
+ case drawing::TextHorizontalAdjust_BLOCK:
+ {
+ drawing::TextFitToSizeType const eFTS(
+ rSdrObjCustomShape.GetMergedItem( SDRATTR_TEXT_FITTOSIZE ).GetValue() );
+ if (eFTS == drawing::TextFitToSizeType_ALLLINES ||
+ eFTS == drawing::TextFitToSizeType_PROPORTIONAL)
+ {
+ gTextAlign = mso_alignTextStretch;
+ }
+ else
+ {
+ gTextAlign = mso_alignTextWordJust;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ AddOpt(DFF_Prop_gtextAlign,gTextAlign);
+ }
+ }
+ if((nTextPathFlags & 0x4000) != 0) // Is Font work
+ {
+ OutlinerParaObject* pOutlinerParaObject(rSdrObjCustomShape.GetOutlinerParaObject());
+ if ( pOutlinerParaObject && pOutlinerParaObject->IsEffectivelyVertical() )
+ nTextPathFlags |= 0x2000;
+ }
+
+ // Use gtextFStretch for Watermark like MSO does
+ nTextPathFlags |= use_gtextFBestFit | gtextFBestFit
+ | use_gtextFStretch | gtextFStretch
+ | use_gtextFShrinkFit | gtextFShrinkFit;
+
+ if ( nTextPathFlags != nTextPathFlagsOrg )
+ AddOpt( DFF_Prop_gtextFStrikethrough, nTextPathFlags );
+ }
+ }
+ else if ( rProp.Name == sHandles )
+ {
+ if ( !bIsDefaultObject )
+ {
+ bPredefinedHandlesUsed = false;
+ if ( rProp.Value >>= aHandlesPropSeq )
+ {
+ sal_uInt16 nElements = static_cast<sal_uInt16>(aHandlesPropSeq.getLength());
+ if ( nElements )
+ {
+ sal_uInt16 k, nElementSize = 36;
+ sal_uInt32 nStreamSize = nElementSize * nElements + 6;
+ SvMemoryStream aMemStrm( nStreamSize );
+ aMemStrm.WriteUInt16( nElements )
+ .WriteUInt16( nElements )
+ .WriteUInt16( nElementSize );
+
+ for ( k = 0; k < nElements; k++ )
+ {
+ sal_uInt32 nFlags = 0;
+ sal_Int32 nXPosition = 0;
+ sal_Int32 nYPosition = 0;
+ sal_Int32 nXMap = 0;
+ sal_Int32 nYMap = 0;
+ sal_Int32 nXRangeMin = 0x80000000;
+ sal_Int32 nXRangeMax = 0x7fffffff;
+ sal_Int32 nYRangeMin = 0x80000000;
+ sal_Int32 nYRangeMax = 0x7fffffff;
+
+ const uno::Sequence< beans::PropertyValue >& rPropSeq = aHandlesPropSeq[ k ];
+ for ( const beans::PropertyValue& rPropVal: rPropSeq )
+ {
+ if ( rPropVal.Name == "Position" )
+ {
+ drawing::EnhancedCustomShapeParameterPair aPosition;
+ if ( rPropVal.Value >>= aPosition )
+ {
+ GetValueForEnhancedCustomShapeHandleParameter( nXPosition, aPosition.First );
+ GetValueForEnhancedCustomShapeHandleParameter( nYPosition, aPosition.Second );
+ }
+ }
+ else if ( rPropVal.Name == "MirroredX" )
+ {
+ bool bMirroredX;
+ if ( rPropVal.Value >>= bMirroredX )
+ {
+ if ( bMirroredX )
+ nFlags |= 1;
+ }
+ }
+ else if ( rPropVal.Name == "MirroredY" )
+ {
+ bool bMirroredY;
+ if ( rPropVal.Value >>= bMirroredY )
+ {
+ if ( bMirroredY )
+ nFlags |= 2;
+ }
+ }
+ else if ( rPropVal.Name == "Switched" )
+ {
+ bool bSwitched;
+ if ( rPropVal.Value >>= bSwitched )
+ {
+ if ( bSwitched )
+ nFlags |= 4;
+ }
+ }
+ else if ( rPropVal.Name == "Polar" )
+ {
+ drawing::EnhancedCustomShapeParameterPair aPolar;
+ if ( rPropVal.Value >>= aPolar )
+ {
+ if ( GetValueForEnhancedCustomShapeHandleParameter( nXMap, aPolar.First ) )
+ nFlags |= 0x800;
+ if ( GetValueForEnhancedCustomShapeHandleParameter( nYMap, aPolar.Second ) )
+ nFlags |= 0x1000;
+ nFlags |= 8;
+ }
+ }
+ else if ( rPropVal.Name == "RadiusRangeMinimum" )
+ {
+ nYRangeMin = sal_Int32(0xff4c0000); // the range of angles seems to be a not
+ nYRangeMax = sal_Int32(0x00b40000); // used feature, so we are defaulting this
+
+ drawing::EnhancedCustomShapeParameter aRadiusRangeMinimum;
+ if ( rPropVal.Value >>= aRadiusRangeMinimum )
+ {
+ if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aRadiusRangeMinimum ) )
+ nFlags |= 0x80;
+ nFlags |= 0x2000;
+ }
+ }
+ else if ( rPropVal.Name == "RadiusRangeMaximum" )
+ {
+ nYRangeMin = sal_Int32(0xff4c0000); // the range of angles seems to be a not
+ nYRangeMax = sal_Int32(0x00b40000); // used feature, so we are defaulting this
+
+ drawing::EnhancedCustomShapeParameter aRadiusRangeMaximum;
+ if ( rPropVal.Value >>= aRadiusRangeMaximum )
+ {
+ if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aRadiusRangeMaximum ) )
+ nFlags |= 0x100;
+ nFlags |= 0x2000;
+ }
+ }
+ else if ( rPropVal.Name == "RangeXMinimum" )
+ {
+ drawing::EnhancedCustomShapeParameter aXRangeMinimum;
+ if ( rPropVal.Value >>= aXRangeMinimum )
+ {
+ if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMin, aXRangeMinimum ) )
+ nFlags |= 0x80;
+ nFlags |= 0x20;
+ }
+ }
+ else if ( rPropVal.Name == "RangeXMaximum" )
+ {
+ drawing::EnhancedCustomShapeParameter aXRangeMaximum;
+ if ( rPropVal.Value >>= aXRangeMaximum )
+ {
+ if ( GetValueForEnhancedCustomShapeHandleParameter( nXRangeMax, aXRangeMaximum ) )
+ nFlags |= 0x100;
+ nFlags |= 0x20;
+ }
+ }
+ else if ( rPropVal.Name == "RangeYMinimum" )
+ {
+ drawing::EnhancedCustomShapeParameter aYRangeMinimum;
+ if ( rPropVal.Value >>= aYRangeMinimum )
+ {
+ if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMin, aYRangeMinimum ) )
+ nFlags |= 0x200;
+ nFlags |= 0x20;
+ }
+ }
+ else if ( rPropVal.Name == "RangeYMaximum" )
+ {
+ drawing::EnhancedCustomShapeParameter aYRangeMaximum;
+ if ( rPropVal.Value >>= aYRangeMaximum )
+ {
+ if ( GetValueForEnhancedCustomShapeHandleParameter( nYRangeMax, aYRangeMaximum ) )
+ nFlags |= 0x400;
+ nFlags |= 0x20;
+ }
+ }
+ }
+ aMemStrm.WriteUInt32( nFlags )
+ .WriteInt32( nXPosition )
+ .WriteInt32( nYPosition )
+ .WriteInt32( nXMap )
+ .WriteInt32( nYMap )
+ .WriteInt32( nXRangeMin )
+ .WriteInt32( nXRangeMax )
+ .WriteInt32( nYRangeMin )
+ .WriteInt32( nYRangeMax );
+
+ if ( nFlags & 8 )
+ nAdjustmentsWhichNeedsToBeConverted |= ( 1 << ( nYPosition - 0x100 ) );
+ }
+
+ AddOpt(DFF_Prop_Handles, true, 6, aMemStrm);
+ }
+ else
+ {
+ AddOpt(DFF_Prop_Handles, 0, true);
+ }
+ }
+ }
+ }
+ else if ( rProp.Name == sAdjustmentValues )
+ {
+ // it is required, that the information which handle is polar has already be read,
+ // so we are able to change the polar value to a fixed float
+ aAdjustmentValuesProp = rProp.Value;
+ bAdjustmentValuesProp = true;
+ }
+ }
+ if ( bAdjustmentValuesProp )
+ {
+ uno::Sequence<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentSeq;
+ if ( aAdjustmentValuesProp >>= aAdjustmentSeq )
+ {
+ if ( bPredefinedHandlesUsed )
+ LookForPolarHandles( eShapeType, nAdjustmentsWhichNeedsToBeConverted );
+
+ sal_Int32 k, nValue = 0, nAdjustmentValues = aAdjustmentSeq.getLength();
+ for ( k = 0; k < nAdjustmentValues; k++ )
+ if( GetAdjustmentValue( aAdjustmentSeq[ k ], k, nAdjustmentsWhichNeedsToBeConverted, nValue ) )
+ AddOpt( static_cast<sal_uInt16>( DFF_Prop_adjustValue + k ), static_cast<sal_uInt32>(nValue) );
+ }
+ }
+ if( !bPathCoordinatesProp )
+ return;
+
+ uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aCoordinates;
+ if ( !(aPathCoordinatesProp >>= aCoordinates) )
+ return;
+
+ // creating the vertices
+ if (aCoordinates.hasElements())
+ {
+ sal_uInt16 j, nElements = static_cast<sal_uInt16>(aCoordinates.getLength());
+ sal_uInt16 nElementSize = 8;
+ sal_uInt32 nStreamSize = nElementSize * nElements + 6;
+ SvMemoryStream aMemStrm( nStreamSize );
+ aMemStrm.WriteUInt16( nElements )
+ .WriteUInt16( nElements )
+ .WriteUInt16( nElementSize );
+ for( j = 0; j < nElements; j++ )
+ {
+ sal_Int32 X = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].First, aEquationOrder, true );
+ sal_Int32 Y = GetValueForEnhancedCustomShapeParameter( aCoordinates[ j ].Second, aEquationOrder, true );
+ aMemStrm.WriteInt32( X )
+ .WriteInt32( Y );
+ }
+
+ AddOpt(DFF_Prop_pVertices, true, 6, aMemStrm); // -6
+ }
+ else
+ {
+ AddOpt(DFF_Prop_pVertices, 0, true);
+ }
+}
+
+MSO_SPT EscherPropertyContainer::GetCustomShapeType( const uno::Reference< drawing::XShape > & rXShape, ShapeFlag& nMirrorFlags, OUString& rShapeType, bool bOOXML )
+{
+ MSO_SPT eShapeType = mso_sptNil;
+ nMirrorFlags = ShapeFlag::NONE;
+ uno::Reference< beans::XPropertySet > aXPropSet( rXShape, uno::UNO_QUERY );
+ if ( aXPropSet.is() )
+ {
+ try
+ {
+ uno::Any aGeoPropSet = aXPropSet->getPropertyValue( "CustomShapeGeometry" );
+ uno::Sequence< beans::PropertyValue > aGeoPropSeq;
+ if ( aGeoPropSet >>= aGeoPropSeq )
+ {
+ sal_Int32 i, nCount = aGeoPropSeq.getLength();
+ for ( i = 0; i < nCount; i++ )
+ {
+ const beans::PropertyValue& rProp = aGeoPropSeq[ i ];
+ if ( rProp.Name == "Type" )
+ {
+ if ( rProp.Value >>= rShapeType )
+ {
+ if (bOOXML)
+ {
+ // In case of VML export, try to handle the
+ // ooxml- prefix in rShapeType. If that fails,
+ // just do the same as the binary export.
+ eShapeType = msfilter::util::GETVMLShapeType(rShapeType);
+ if (eShapeType == mso_sptNil)
+ eShapeType = EnhancedCustomShapeTypeNames::Get(rShapeType);
+ }
+ else
+ eShapeType = EnhancedCustomShapeTypeNames::Get( rShapeType );
+ }
+ }
+ else if ( rProp.Name == "MirroredX" )
+ {
+ bool bMirroredX;
+ if ( ( rProp.Value >>= bMirroredX ) && bMirroredX )
+ nMirrorFlags |= ShapeFlag::FlipH;
+ }
+ else if ( rProp.Name == "MirroredY" )
+ {
+ bool bMirroredY;
+ if ( ( rProp.Value >>= bMirroredY ) && bMirroredY )
+ nMirrorFlags |= ShapeFlag::FlipV;
+ }
+ }
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ return eShapeType;
+}
+
+
+// Implement for form control export
+bool EscherPropertyContainer::CreateBlipPropertiesforOLEControl(const uno::Reference<beans::XPropertySet> & rXPropSet,
+ const uno::Reference<drawing::XShape> & rXShape)
+{
+ SdrObject* pShape = SdrObject::getSdrObjectFromXShape(rXShape);
+ if ( !pShape )
+ return false;
+
+ const Graphic aGraphic(SdrExchangeView::GetObjGraphic(*pShape));
+ const GraphicObject aGraphicObject(aGraphic);
+
+ if (!aGraphicObject.GetUniqueID().isEmpty())
+ {
+ if ( pGraphicProvider && pPicOutStrm && pShapeBoundRect )
+ {
+ sal_uInt32 nBlibId = pGraphicProvider->GetBlibID(*pPicOutStrm, aGraphicObject);
+ if ( nBlibId )
+ {
+ AddOpt( ESCHER_Prop_pib, nBlibId, true );
+ ImplCreateGraphicAttributes( rXPropSet, nBlibId, false );
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+EscherPersistTable::EscherPersistTable()
+{
+}
+
+EscherPersistTable::~EscherPersistTable()
+{
+}
+
+bool EscherPersistTable::PtIsID( sal_uInt32 nID )
+{
+ for(auto const & pPtr : maPersistTable) {
+ if ( pPtr->mnID == nID ) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void EscherPersistTable::PtInsert( sal_uInt32 nID, sal_uInt32 nOfs )
+{
+ maPersistTable.push_back( std::make_unique<EscherPersistEntry>( nID, nOfs ) );
+}
+
+void EscherPersistTable::PtDelete( sal_uInt32 nID )
+{
+ auto it = std::find_if(maPersistTable.begin(), maPersistTable.end(),
+ [&nID](const std::unique_ptr<EscherPersistEntry>& rxEntry) { return rxEntry->mnID == nID; });
+ if (it != maPersistTable.end())
+ maPersistTable.erase( it );
+}
+
+sal_uInt32 EscherPersistTable::PtGetOffsetByID( sal_uInt32 nID )
+{
+ for(auto const & pPtr : maPersistTable) {
+ if ( pPtr->mnID == nID ) {
+ return pPtr->mnOffset;
+ }
+ }
+ return 0;
+};
+
+void EscherPersistTable::PtReplace( sal_uInt32 nID, sal_uInt32 nOfs )
+{
+ for(auto const & pPtr : maPersistTable) {
+ if ( pPtr->mnID == nID ) {
+ pPtr->mnOffset = nOfs;
+ return;
+ }
+ }
+}
+
+void EscherPersistTable::PtReplaceOrInsert( sal_uInt32 nID, sal_uInt32 nOfs )
+{
+ for(auto const & pPtr : maPersistTable) {
+ if ( pPtr->mnID == nID ) {
+ pPtr->mnOffset = nOfs;
+ return;
+ }
+ }
+ PtInsert( nID, nOfs );
+}
+
+bool EscherPropertyValueHelper::GetPropertyValue(
+ uno::Any& rAny,
+ const uno::Reference<beans::XPropertySet> & rXPropSet,
+ const OUString& rString,
+ bool bTestPropertyAvailability)
+{
+ bool bRetValue = true;
+ if ( bTestPropertyAvailability )
+ {
+ bRetValue = false;
+ try
+ {
+ uno::Reference<beans::XPropertySetInfo>
+ aXPropSetInfo( rXPropSet->getPropertySetInfo() );
+ if ( aXPropSetInfo.is() )
+ bRetValue = aXPropSetInfo->hasPropertyByName( rString );
+ }
+ catch( const uno::Exception& )
+ {
+ bRetValue = false;
+ }
+ }
+ if ( bRetValue )
+ {
+ try
+ {
+ rAny = rXPropSet->getPropertyValue( rString );
+ if ( !rAny.hasValue() )
+ bRetValue = false;
+ }
+ catch( const uno::Exception& )
+ {
+ bRetValue = false;
+ }
+ }
+ return bRetValue;
+}
+
+beans::PropertyState EscherPropertyValueHelper::GetPropertyState(
+ const uno::Reference<beans::XPropertySet> & rXPropSet,
+ const OUString& rPropertyName )
+{
+ beans::PropertyState eRetValue = beans::PropertyState_AMBIGUOUS_VALUE;
+ try
+ {
+ uno::Reference<beans::XPropertyState> aXPropState
+ ( rXPropSet, uno::UNO_QUERY );
+ if ( aXPropState.is() )
+ eRetValue = aXPropState->getPropertyState( rPropertyName );
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ return eRetValue;
+}
+
+EscherBlibEntry::EscherBlibEntry( sal_uInt32 nPictureOffset, const GraphicObject& rObject, const OString& rId,
+ const GraphicAttr* pGraphicAttr ) :
+ maPrefMapMode ( rObject.GetPrefMapMode() ),
+ maPrefSize ( rObject.GetPrefSize() ),
+ mnPictureOffset ( nPictureOffset ),
+ mnRefCount ( 1 ),
+ mnSizeExtra ( 0 ),
+ mbIsEmpty ( true )
+{
+ mbIsNativeGraphicPossible = ( pGraphicAttr == nullptr );
+ meBlibType = UNKNOWN;
+ mnSize = 0;
+
+ sal_uInt32 nLen = static_cast<sal_uInt32>(rId.getLength());
+ const char* pData = rId.getStr();
+ GraphicType eType( rObject.GetType() );
+ if (!(nLen && (eType != GraphicType::NONE)))
+ return;
+
+ mnIdentifier[ 0 ] = rtl_crc32( 0,pData, nLen );
+ mnIdentifier[ 1 ] = 0;
+
+ if ( pGraphicAttr )
+ {
+ if ( pGraphicAttr->IsSpecialDrawMode()
+ || pGraphicAttr->IsMirrored()
+ || pGraphicAttr->IsCropped()
+ || pGraphicAttr->IsRotated()
+ || pGraphicAttr->IsTransparent()
+ || pGraphicAttr->IsAdjusted() )
+ {
+ SvMemoryStream aSt( sizeof( GraphicAttr ) );
+ aSt.WriteUInt16( static_cast<sal_uInt16>(pGraphicAttr->GetDrawMode()) )
+ .WriteUInt32( static_cast<sal_uInt32>(pGraphicAttr->GetMirrorFlags()) )
+ .WriteInt32( pGraphicAttr->GetLeftCrop() )
+ .WriteInt32( pGraphicAttr->GetTopCrop() )
+ .WriteInt32( pGraphicAttr->GetRightCrop() )
+ .WriteInt32( pGraphicAttr->GetBottomCrop() )
+ .WriteUInt16( pGraphicAttr->GetRotation().get() )
+ .WriteInt16( pGraphicAttr->GetLuminance() )
+ .WriteInt16( pGraphicAttr->GetContrast() )
+ .WriteInt16( pGraphicAttr->GetChannelR() )
+ .WriteInt16( pGraphicAttr->GetChannelG() )
+ .WriteInt16( pGraphicAttr->GetChannelB() )
+ .WriteDouble( pGraphicAttr->GetGamma() );
+ aSt.WriteBool( pGraphicAttr->IsInvert() )
+ .WriteUChar( 255 - pGraphicAttr->GetAlpha() ); // transparency
+ mnIdentifier[ 1 ] = rtl_crc32( 0, aSt.GetData(), aSt.Tell() );
+ }
+ else
+ mbIsNativeGraphicPossible = true;
+ }
+ sal_uInt32 i, nTmp, n1, n2;
+ n1 = n2 = 0;
+ for ( i = 0; i < nLen; i++ )
+ {
+ nTmp = n2 >> 28; // rotating 4 bit
+ n2 <<= 4;
+ n2 |= n1 >> 28;
+ n1 <<= 4;
+ n1 |= nTmp;
+ n1 ^= *pData++ - '0';
+ }
+ mnIdentifier[ 2 ] = n1;
+ mnIdentifier[ 3 ] = n2;
+ mbIsEmpty = false;
+};
+
+void EscherBlibEntry::WriteBlibEntry( SvStream& rSt, bool bWritePictureOffset, sal_uInt32 nResize )
+{
+ sal_uInt32 nPictureOffset = bWritePictureOffset ? mnPictureOffset : 0;
+
+ rSt.WriteUInt32( ( ESCHER_BSE << 16 ) | ( ( static_cast<sal_uInt16>(meBlibType) << 4 ) | 2 ) )
+ .WriteUInt32( 36 + nResize )
+ .WriteUChar( meBlibType );
+
+ switch ( meBlibType )
+ {
+ case EMF :
+ case WMF : // converting EMF/WMF on OS2 to Pict
+ rSt.WriteUChar( PICT );
+ break;
+ default:
+ rSt.WriteUChar( meBlibType );
+ }
+
+ rSt.WriteBytes(&mnIdentifier[0], 16);
+ rSt.WriteUInt16( 0 )
+ .WriteUInt32( mnSize + mnSizeExtra )
+ .WriteUInt32( mnRefCount )
+ .WriteUInt32( nPictureOffset )
+ .WriteUInt32( 0 );
+}
+
+EscherBlibEntry::~EscherBlibEntry()
+{
+};
+
+bool EscherBlibEntry::operator==( const EscherBlibEntry& rEscherBlibEntry ) const
+{
+ for ( int i = 0; i < 3; i++ )
+ {
+ if ( mnIdentifier[ i ] != rEscherBlibEntry.mnIdentifier[ i ] )
+ return false;
+ }
+ return true;
+}
+
+EscherGraphicProvider::EscherGraphicProvider( EscherGraphicProviderFlags nFlags ) :
+ mnFlags ( nFlags )
+{
+}
+
+EscherGraphicProvider::~EscherGraphicProvider()
+{
+}
+
+void EscherGraphicProvider::SetNewBlipStreamOffset( sal_Int32 nOffset )
+{
+ for( size_t i = 0; i < mvBlibEntrys.size(); i++ )
+ {
+ mvBlibEntrys[ i ]->mnPictureOffset += nOffset;
+ }
+}
+
+sal_uInt32 EscherGraphicProvider::ImplInsertBlib( EscherBlibEntry* p_EscherBlibEntry )
+{
+ mvBlibEntrys.push_back( std::unique_ptr<EscherBlibEntry>(p_EscherBlibEntry) );
+ return mvBlibEntrys.size();
+}
+
+sal_uInt32 EscherGraphicProvider::GetBlibStoreContainerSize( SvStream const * pMergePicStreamBSE ) const
+{
+ sal_uInt32 nSize = 44 * mvBlibEntrys.size() + 8;
+ if ( pMergePicStreamBSE )
+ {
+ for ( size_t i = 0; i < mvBlibEntrys.size(); i++ )
+ nSize += mvBlibEntrys[ i ]->mnSize + mvBlibEntrys[ i ]->mnSizeExtra;
+ }
+ return nSize;
+}
+
+void EscherGraphicProvider::WriteBlibStoreEntry(SvStream& rSt,
+ sal_uInt32 nBlipId, sal_uInt32 nResize)
+{
+ if (nBlipId > mvBlibEntrys.size() || nBlipId == 0)
+ return;
+ mvBlibEntrys[nBlipId-1]->WriteBlibEntry(rSt, true/*bWritePictureOffSet*/, nResize);
+}
+
+void EscherGraphicProvider::WriteBlibStoreContainer( SvStream& rSt, SvStream* pMergePicStreamBSE )
+{
+ sal_uInt32 nSize = GetBlibStoreContainerSize( pMergePicStreamBSE );
+ if ( !nSize )
+ return;
+
+ rSt.WriteUInt32( ( ESCHER_BstoreContainer << 16 ) | 0x1f )
+ .WriteUInt32( nSize - 8 );
+
+ if ( pMergePicStreamBSE )
+ {
+ sal_uInt32 nBlipSize, nOldPos = pMergePicStreamBSE->Tell();
+ const sal_uInt32 nBuf = 0x40000; // 256KB buffer
+ std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8[ nBuf ]);
+
+ for ( size_t i = 0; i < mvBlibEntrys.size(); i++ )
+ {
+ EscherBlibEntry* pBlibEntry = mvBlibEntrys[ i ].get();
+
+ ESCHER_BlibType nBlibType = pBlibEntry->meBlibType;
+ nBlipSize = pBlibEntry->mnSize + pBlibEntry->mnSizeExtra;
+ pBlibEntry->WriteBlibEntry( rSt, false, nBlipSize );
+
+ // BLIP
+ pMergePicStreamBSE->Seek( pBlibEntry->mnPictureOffset );
+ sal_uInt16 n16;
+ // record version and instance
+ pMergePicStreamBSE->ReadUInt16( n16 );
+ rSt.WriteUInt16( n16 );
+ // record type
+ pMergePicStreamBSE->ReadUInt16( n16 );
+ rSt.WriteUInt16( ESCHER_BlipFirst + nBlibType );
+ DBG_ASSERT( n16 == ESCHER_BlipFirst + nBlibType , "EscherGraphicProvider::WriteBlibStoreContainer: BLIP record types differ" );
+ sal_uInt32 n32;
+ // record size
+ pMergePicStreamBSE->ReadUInt32( n32 );
+ nBlipSize -= 8;
+ rSt.WriteUInt32( nBlipSize );
+ DBG_ASSERT( nBlipSize == n32, "EscherGraphicProvider::WriteBlibStoreContainer: BLIP sizes differ" );
+ // record
+ while ( nBlipSize )
+ {
+ sal_uInt32 nBytes = std::min( nBlipSize, nBuf );
+ pMergePicStreamBSE->ReadBytes(pBuf.get(), nBytes);
+ rSt.WriteBytes(pBuf.get(), nBytes);
+ nBlipSize -= nBytes;
+ }
+ }
+ pMergePicStreamBSE->Seek( nOldPos );
+ }
+ else
+ {
+ for ( size_t i = 0; i < mvBlibEntrys.size(); i++ )
+ mvBlibEntrys[ i ]->WriteBlibEntry( rSt, true );
+ }
+}
+
+bool EscherGraphicProvider::GetPrefSize( const sal_uInt32 nBlibId, Size& rPrefSize, MapMode& rPrefMapMode )
+{
+ bool bInRange = nBlibId && ( ( nBlibId - 1 ) < mvBlibEntrys.size() );
+ if ( bInRange )
+ {
+ EscherBlibEntry* pEntry = mvBlibEntrys[ nBlibId - 1 ].get();
+ rPrefSize = pEntry->maPrefSize;
+ rPrefMapMode = pEntry->maPrefMapMode;
+ }
+ return bInRange;
+}
+
+sal_uInt32 EscherGraphicProvider::GetBlibID( SvStream& rPicOutStrm, GraphicObject const & rGraphicObject,
+ const awt::Rectangle* pVisArea,
+ const GraphicAttr* pGraphicAttr, const bool bOOxmlExport )
+{
+ sal_uInt32 nBlibId = 0;
+
+ std::unique_ptr<EscherBlibEntry> p_EscherBlibEntry( new EscherBlibEntry( rPicOutStrm.Tell(), rGraphicObject, rGraphicObject.GetUniqueID(), pGraphicAttr ) );
+ if ( !p_EscherBlibEntry->IsEmpty() )
+ {
+ for ( size_t i = 0; i < mvBlibEntrys.size(); i++ )
+ {
+ if ( *( mvBlibEntrys[ i ] ) == *p_EscherBlibEntry )
+ {
+ mvBlibEntrys[ i ]->mnRefCount++;
+ return i + 1;
+ }
+ }
+
+ bool bUseNativeGraphic( false );
+
+ Graphic aGraphic(rGraphicObject.GetTransformedGraphic(pGraphicAttr));
+ GfxLink aGraphicLink;
+ SvMemoryStream aStream;
+
+ const sal_uInt8* pGraphicAry = nullptr;
+
+ if ( p_EscherBlibEntry->mbIsNativeGraphicPossible && aGraphic.IsGfxLink() )
+ {
+ aGraphicLink = aGraphic.GetGfxLink();
+
+ p_EscherBlibEntry->mnSize = aGraphicLink.GetDataSize();
+ pGraphicAry = aGraphicLink.GetData();
+
+ if ( p_EscherBlibEntry->mnSize && pGraphicAry )
+ {
+ switch ( aGraphicLink.GetType() )
+ {
+ case GfxLinkType::NativeJpg : p_EscherBlibEntry->meBlibType = PEG; break;
+ case GfxLinkType::NativePng : p_EscherBlibEntry->meBlibType = PNG; break;
+
+ // #i15508# added BMP type for better exports; need to check this
+ // checked - does not work that way, so keep out for now. It may
+ // work somehow with direct DIB data, but that would need to be checked
+ // carefully
+ // for more comments please check RtfAttributeOutput::FlyFrameGraphic
+ //
+ // case GfxLinkType::NativeBmp : p_EscherBlibEntry->meBlibType = DIB; break;
+
+ case GfxLinkType::NativeWmf :
+ {
+ if ( aGraphicLink.IsEMF() )
+ {
+ p_EscherBlibEntry->meBlibType = EMF;
+ }
+ else if ( pGraphicAry && ( p_EscherBlibEntry->mnSize > 0x2c ) )
+ {
+ p_EscherBlibEntry->meBlibType = WMF;
+ if ( ( pGraphicAry[ 0 ] == 0xd7 ) && ( pGraphicAry[ 1 ] == 0xcd )
+ && ( pGraphicAry[ 2 ] == 0xc6 ) && ( pGraphicAry[ 3 ] == 0x9a ) )
+ { // we have to get rid of the metafileheader
+ pGraphicAry += 22;
+ p_EscherBlibEntry->mnSize -= 22;
+ }
+ }
+ }
+ break;
+ default: break;
+ }
+ if ( p_EscherBlibEntry->meBlibType != UNKNOWN )
+ bUseNativeGraphic = true;
+ }
+ }
+ if ( !bUseNativeGraphic )
+ {
+ GraphicType eGraphicType = aGraphic.GetType();
+ if ( ( eGraphicType == GraphicType::Bitmap ) || ( eGraphicType == GraphicType::GdiMetafile ) )
+ {
+ ErrCode nErrCode;
+ if ( !aGraphic.IsAnimated() )
+ nErrCode = GraphicConverter::Export( aStream, aGraphic, ( eGraphicType == GraphicType::Bitmap ) ? ConvertDataFormat::PNG : ConvertDataFormat::EMF );
+ else
+ { // to store an animation, a gif has to be included into the msOG chunk of a png #I5583#
+ GraphicFilter &rFilter = GraphicFilter::GetGraphicFilter();
+ SvMemoryStream aGIFStream;
+ const char* const pString = "MSOFFICE9.0";
+ aGIFStream.WriteBytes(pString, strlen(pString));
+ nErrCode = rFilter.ExportGraphic( aGraphic, u"", aGIFStream,
+ rFilter.GetExportFormatNumberForShortName( u"GIF" ) );
+ SAL_WARN_IF(
+ nErrCode != ERRCODE_NONE, "filter.ms",
+ "ExportGraphic to GIF failed with " << nErrCode);
+ if (nErrCode == ERRCODE_NONE)
+ {
+ sal_uInt32 nGIFSreamLen = aGIFStream.Tell();
+ uno::Sequence<sal_Int8> aGIFSeq( nGIFSreamLen );
+ sal_Int8* pSeq = aGIFSeq.getArray();
+ aGIFStream.Seek( STREAM_SEEK_TO_BEGIN );
+ aGIFStream.ReadBytes(pSeq, nGIFSreamLen);
+ beans::PropertyValue aChunkProp, aFilterProp;
+ aChunkProp.Name = "msOG";
+ aChunkProp.Value <<= aGIFSeq;
+ uno::Sequence<beans::PropertyValue> aAdditionalChunkSequence{ aChunkProp };
+ aFilterProp.Name = "AdditionalChunks";
+ aFilterProp.Value <<= aAdditionalChunkSequence;
+ uno::Sequence<beans::PropertyValue> aFilterData{ aFilterProp };
+ nErrCode = rFilter.ExportGraphic( aGraphic, u"", aStream,
+ rFilter.GetExportFormatNumberForShortName( u"PNG" ), &aFilterData );
+ }
+ }
+ if ( nErrCode == ERRCODE_NONE )
+ {
+ p_EscherBlibEntry->meBlibType = ( eGraphicType == GraphicType::Bitmap ) ? PNG : EMF;
+ p_EscherBlibEntry->mnSize = aStream.TellEnd();
+ pGraphicAry = static_cast<sal_uInt8 const *>(aStream.GetData());
+ }
+ }
+ }
+
+ ESCHER_BlibType eBlibType = p_EscherBlibEntry->meBlibType;
+ if ( p_EscherBlibEntry->mnSize && pGraphicAry && ( eBlibType != UNKNOWN ) )
+ {
+ sal_uInt32 nExtra, nAtomSize = 0;
+ sal_uInt32 nInstance, nUncompressedSize = p_EscherBlibEntry->mnSize;
+
+ if ( mnFlags & EscherGraphicProviderFlags::UseInstances )
+ {
+ rPicOutStrm.WriteUInt32( 0x7f90000 | static_cast<sal_uInt16>( mvBlibEntrys.size() << 4 ) )
+ .WriteUInt32( 0 );
+ nAtomSize = rPicOutStrm.Tell();
+ if ( eBlibType == PNG )
+ rPicOutStrm.WriteUInt16( 0x0606 );
+ else if ( eBlibType == WMF )
+ rPicOutStrm.WriteUInt16( 0x0403 );
+ else if ( eBlibType == EMF )
+ rPicOutStrm.WriteUInt16( 0x0402 );
+ else if ( eBlibType == PEG )
+ rPicOutStrm.WriteUInt16( 0x0505 );
+ }
+
+ // fdo#69607 do not compress WMF files if we are in OOXML export
+ if ( ( eBlibType == PEG ) || ( eBlibType == PNG ) // || ( eBlibType == DIB )) // #i15508#
+ || ( ( ( eBlibType == WMF ) || ( eBlibType == EMF ) ) && bOOxmlExport ) )
+ {
+ nExtra = 17;
+ p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
+
+ // #i15508# type see SvxMSDffManager::GetBLIPDirect (checked, does not work this way)
+ // see RtfAttributeOutput::FlyFrameGraphic for more comments
+ // maybe it would work with direct DIB data, but that would need thorough testing
+ if( eBlibType == PNG )
+ {
+ nInstance = 0xf01e6e00;
+ }
+ else // if( eBlibType == PEG )
+ {
+ nInstance = 0xf01d46a0;
+ }
+ //else // eBlibType == DIB
+ //{
+ // nInstance = 0xf01d7A80;
+ //}
+
+ // #i15508#
+ //nInstance = ( eBlibType == PNG ) ? 0xf01e6e00 : 0xf01d46a0;
+
+
+ rPicOutStrm.WriteUInt32( nInstance ).WriteUInt32( p_EscherBlibEntry->mnSize + nExtra );
+ rPicOutStrm.WriteBytes(p_EscherBlibEntry->mnIdentifier, 16);
+ rPicOutStrm.WriteUChar( 0xff );
+ rPicOutStrm.WriteBytes(pGraphicAry, p_EscherBlibEntry->mnSize);
+ }
+ else
+ {
+ ZCodec aZCodec( 0x8000, 0x8000 );
+ aZCodec.BeginCompression();
+ SvMemoryStream aDestStrm;
+ aZCodec.Write( aDestStrm, pGraphicAry, p_EscherBlibEntry->mnSize );
+ aZCodec.EndCompression();
+ p_EscherBlibEntry->mnSize = aDestStrm.TellEnd();
+ pGraphicAry = static_cast<sal_uInt8 const *>(aDestStrm.GetData());
+ if ( p_EscherBlibEntry->mnSize && pGraphicAry )
+ {
+ nExtra = eBlibType == WMF ? 0x42 : 0x32; // !EMF -> no change
+ p_EscherBlibEntry->mnSizeExtra = nExtra + 8;
+ nInstance = ( eBlibType == WMF ) ? 0xf01b2170 : 0xf01a3d40; // !EMF -> no change
+ rPicOutStrm.WriteUInt32( nInstance ).WriteUInt32( p_EscherBlibEntry->mnSize + nExtra );
+ if ( eBlibType == WMF ) // !EMF -> no change
+ rPicOutStrm.WriteBytes(p_EscherBlibEntry->mnIdentifier, 16);
+ rPicOutStrm.WriteBytes(p_EscherBlibEntry->mnIdentifier, 16);
+
+ /*
+ ##913##
+ For Word the stored size of the graphic is critical the
+ metafile boundaries must match the actual graphics
+ boundaries, and the width and height must be in EMU's
+
+ If you don't do it this way then objects edited in the
+ msoffice app may show strange behaviour as the size jumps
+ around, and the original size and scaling factor in word
+ will be a very strange figure
+ */
+ sal_uInt32 nPrefWidth = p_EscherBlibEntry->maPrefSize.Width();
+ sal_uInt32 nPrefHeight = p_EscherBlibEntry->maPrefSize.Height();
+ sal_uInt32 nWidth, nHeight;
+ if ( pVisArea )
+ {
+ nWidth = pVisArea->Width * 360;
+ nHeight = pVisArea->Height * 360;
+ }
+ else
+ {
+ Size aPrefSize(lcl_SizeToEmu(p_EscherBlibEntry->maPrefSize, p_EscherBlibEntry->maPrefMapMode));
+ nWidth = aPrefSize.Width() * 360;
+ nHeight = aPrefSize.Height() * 360;
+ }
+ rPicOutStrm.WriteUInt32( nUncompressedSize ) // WMFSize without FileHeader
+ .WriteInt32( 0 ) // since we can't find out anymore what the original size of
+ .WriteInt32( 0 ) // the WMF (without Fileheader) was we write 10cm / x
+ .WriteUInt32( nPrefWidth )
+ .WriteUInt32( nPrefHeight )
+ .WriteUInt32( nWidth )
+ .WriteUInt32( nHeight )
+ .WriteUInt32( p_EscherBlibEntry->mnSize )
+ .WriteUInt16( 0xfe00 ); // compression Flags
+ rPicOutStrm.WriteBytes(pGraphicAry, p_EscherBlibEntry->mnSize);
+ }
+ }
+ if ( nAtomSize )
+ {
+ sal_uInt32 nPos = rPicOutStrm.Tell();
+ rPicOutStrm.Seek( nAtomSize - 4 );
+ rPicOutStrm.WriteUInt32( nPos - nAtomSize );
+ rPicOutStrm.Seek( nPos );
+ }
+ nBlibId = ImplInsertBlib( p_EscherBlibEntry.release() );
+ }
+ }
+ return nBlibId;
+}
+
+namespace {
+
+struct EscherConnectorRule
+{
+ sal_uInt32 nRuleId;
+ sal_uInt32 nShapeA; // SPID of shape A
+ sal_uInt32 nShapeB; // SPID of shape B
+ sal_uInt32 nShapeC; // SPID of connector shape
+ sal_uInt32 ncptiA; // Connection site Index of shape A
+ sal_uInt32 ncptiB; // Connection site Index of shape B
+};
+
+}
+
+struct EscherShapeListEntry
+{
+ uno::Reference<drawing::XShape>aXShape;
+ sal_uInt32 n_EscherId;
+
+ EscherShapeListEntry(uno::Reference<drawing::XShape> xShape, sal_uInt32 nId)
+ : aXShape(std::move(xShape))
+ , n_EscherId(nId)
+ {}
+};
+
+sal_uInt32 EscherConnectorListEntry::GetClosestPoint( const tools::Polygon& rPoly, const awt::Point& rPoint )
+{
+ sal_uInt16 nCount = rPoly.GetSize();
+ sal_uInt16 nClosest = nCount;
+ double fDist = sal_uInt32(0xffffffff);
+ while( nCount-- )
+ {
+ double fDistance = hypot( rPoint.X - rPoly[ nCount ].X(), rPoint.Y - rPoly[ nCount ].Y() );
+ if ( fDistance < fDist )
+ {
+ nClosest = nCount;
+ fDist = fDistance;
+ }
+ }
+ return nClosest;
+};
+
+
+// for rectangles for ellipses for polygons
+//
+// nRule = 0 ->Top 0 ->Top nRule = index to a (Poly)Polygon point
+// 1 ->Left 2 ->Left
+// 2 ->Bottom 4 ->Bottom
+// 3 ->Right 6 ->Right
+
+sal_uInt32 EscherConnectorListEntry::GetConnectorRule( bool bFirst )
+{
+ sal_uInt32 nRule = 0;
+
+ uno::Any aAny;
+ awt::Point aRefPoint( bFirst ? maPointA : maPointB );
+ uno::Reference<drawing::XShape>
+ aXShape( bFirst ? mXConnectToA : mXConnectToB );
+
+ OUString aString(aXShape->getShapeType());
+ OStringBuffer aBuf(OUStringToOString(aString, RTL_TEXTENCODING_UTF8));
+ aBuf.remove( 0, 13 ); // removing "com.sun.star."
+ sal_Int16 nPos = aBuf.toString().indexOf("Shape");
+ aBuf.remove(nPos, 5);
+ OString aType = aBuf.makeStringAndClear();
+
+ uno::Reference<beans::XPropertySet>
+ aPropertySet( aXShape, uno::UNO_QUERY );
+
+ if ((aType == "drawing.PolyPolygon") || (aType == "drawing.PolyLine"))
+ {
+ if ( aPropertySet.is() )
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aPropertySet, "PolyPolygon" ) )
+ {
+ auto pSourcePolyPolygon =
+ o3tl::doAccess<drawing::PointSequenceSequence>(aAny);
+ sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->getLength();
+ drawing::PointSequence const * pOuterSequence = pSourcePolyPolygon->getConstArray();
+
+ if ( pOuterSequence )
+ {
+ sal_Int32 a, b, nIndex = 0;
+ sal_uInt32 nDistance = 0xffffffff;
+ for( a = 0; a < nOuterSequenceCount; a++ )
+ {
+ drawing::PointSequence const * pInnerSequence = pOuterSequence++;
+ if ( pInnerSequence )
+ {
+ awt::Point const * pArray = pInnerSequence->getConstArray();
+ if ( pArray )
+ {
+ for ( b = 0; b < pInnerSequence->getLength(); b++, nIndex++, pArray++ )
+ {
+ sal_uInt32 nDist = static_cast<sal_uInt32>(hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y ));
+ if ( nDist < nDistance )
+ {
+ nRule = nIndex;
+ nDistance = nDist;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else if ((aType == "drawing.OpenBezier") || (aType == "drawing.OpenFreeHand") || (aType == "drawing.PolyLinePath")
+ || (aType == "drawing.ClosedBezier") || ( aType == "drawing.ClosedFreeHand") || (aType == "drawing.PolyPolygonPath") )
+ {
+ uno::Reference<beans::XPropertySet>
+ aPropertySet2( aXShape, uno::UNO_QUERY );
+ if ( aPropertySet2.is() )
+ {
+ if ( EscherPropertyValueHelper::GetPropertyValue( aAny, aPropertySet2, "PolyPolygonBezier" ) )
+ {
+ auto pSourcePolyPolygon =
+ o3tl::doAccess<drawing::PolyPolygonBezierCoords>(aAny);
+ sal_Int32 nOuterSequenceCount = pSourcePolyPolygon->Coordinates.getLength();
+
+ // get pointer of inner sequences
+ drawing::PointSequence const * pOuterSequence =
+ pSourcePolyPolygon->Coordinates.getConstArray();
+ drawing::FlagSequence const * pOuterFlags =
+ pSourcePolyPolygon->Flags.getConstArray();
+
+ if ( pOuterSequence && pOuterFlags )
+ {
+ sal_Int32 a, b, nIndex = 0;
+ sal_uInt32 nDistance = 0xffffffff;
+
+ for ( a = 0; a < nOuterSequenceCount; a++ )
+ {
+ drawing::PointSequence const * pInnerSequence = pOuterSequence++;
+ drawing::FlagSequence const * pInnerFlags = pOuterFlags++;
+ if ( pInnerSequence && pInnerFlags )
+ {
+ awt::Point const * pArray = pInnerSequence->getConstArray();
+ drawing::PolygonFlags const * pFlags = pInnerFlags->getConstArray();
+ if ( pArray && pFlags )
+ {
+ for ( b = 0; b < pInnerSequence->getLength(); b++, pArray++ )
+ {
+ drawing::PolygonFlags ePolyFlags = *pFlags++;
+ if ( ePolyFlags == drawing::PolygonFlags_CONTROL )
+ continue;
+ sal_uInt32 nDist = static_cast<sal_uInt32>(hypot( aRefPoint.X - pArray->X, aRefPoint.Y - pArray->Y ));
+ if ( nDist < nDistance )
+ {
+ nRule = nIndex;
+ nDistance = nDist;
+ }
+ nIndex++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ bool bRectangularConnection = true;
+
+ if (aType == "drawing.Custom")
+ {
+ if (auto pSdrObjCustomShape = dynamic_cast< SdrObjCustomShape* >(SdrObject::getSdrObjectFromXShape(aXShape)))
+ {
+ const SdrCustomShapeGeometryItem& rGeometryItem =
+ pSdrObjCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
+
+ OUString sShapeType;
+ const uno::Any* pType = rGeometryItem.GetPropertyValueByName( "Type" );
+ if ( pType )
+ *pType >>= sShapeType;
+ MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
+
+ uno::Any* pGluePointType = const_cast<SdrCustomShapeGeometryItem&>(rGeometryItem).GetPropertyValueByName( "Path", "GluePointType" );
+
+ sal_Int16 nGluePointType = sal_Int16();
+ if ( !( pGluePointType &&
+ ( *pGluePointType >>= nGluePointType ) ) )
+ nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType );
+
+ if ( nGluePointType == drawing::EnhancedCustomShapeGluePointType::CUSTOM )
+ {
+ const SdrGluePointList* pList = pSdrObjCustomShape->GetGluePointList();
+ if ( pList )
+ {
+ tools::Polygon aPoly;
+ sal_uInt16 nNum, nCnt = pList->GetCount();
+ if ( nCnt )
+ {
+ for ( nNum = 0; nNum < nCnt; nNum++ )
+ {
+ const SdrGluePoint& rGP = (*pList)[ nNum ];
+ Point aPt(rGP.GetAbsolutePos(*pSdrObjCustomShape));
+ aPoly.Insert( POLY_APPEND, aPt );
+ }
+ nRule = GetClosestPoint( aPoly, aRefPoint );
+ bRectangularConnection = false;
+ }
+ }
+ }
+ else if ( nGluePointType == drawing::EnhancedCustomShapeGluePointType::SEGMENTS )
+ {
+ tools::PolyPolygon aPolyPoly;
+ SdrObjectUniquePtr pTemporaryConvertResultObject(pSdrObjCustomShape->DoConvertToPolyObj(true, true));
+ SdrPathObj* pSdrPathObj(dynamic_cast< SdrPathObj* >(pTemporaryConvertResultObject.get()));
+
+ if(pSdrPathObj)
+ {
+ // #i74631# use explicit constructor here. Also XPolyPolygon is not necessary,
+ // reducing to PolyPolygon
+ aPolyPoly = tools::PolyPolygon(pSdrPathObj->GetPathPoly());
+ }
+
+ // do *not* forget to delete the temporary used SdrObject - possible memory leak (!)
+ pTemporaryConvertResultObject.reset();
+ pSdrPathObj = nullptr;
+
+ if(0 != aPolyPoly.Count())
+ {
+ sal_Int16 nIndex = 0;
+ sal_uInt16 a, b;
+ sal_uInt32 nDistance = 0xffffffff;
+
+ for ( a = 0; a < aPolyPoly.Count(); a++ )
+ {
+ const tools::Polygon& rPoly = aPolyPoly.GetObject( a );
+ for ( b = 0; b < rPoly.GetSize(); b++ )
+ {
+ if ( rPoly.GetFlags( b ) != PolyFlags::Normal )
+ continue;
+ const Point& rPt = rPoly[ b ];
+ sal_uInt32 nDist = static_cast<sal_uInt32>(hypot( aRefPoint.X - rPt.X(), aRefPoint.Y - rPt.Y() ));
+ if ( nDist < nDistance )
+ {
+ nRule = nIndex;
+ nDistance = nDist;
+ }
+ nIndex++;
+ }
+ }
+
+ if ( nDistance != 0xffffffff )
+ bRectangularConnection = false;
+ }
+ }
+ }
+ }
+ if ( bRectangularConnection )
+ {
+ awt::Point aPoint( aXShape->getPosition() );
+ awt::Size aSize( aXShape->getSize() );
+
+ tools::Rectangle aRect( Point( aPoint.X, aPoint.Y ), Size( aSize.Width, aSize.Height ) );
+ Point aCenter( aRect.Center() );
+ tools::Polygon aPoly( 4 );
+
+ aPoly[ 0 ] = Point( aCenter.X(), aRect.Top() );
+ aPoly[ 1 ] = Point( aRect.Left(), aCenter.Y() );
+ aPoly[ 2 ] = Point( aCenter.X(), aRect.Bottom() );
+ aPoly[ 3 ] = Point( aRect.Right(), aCenter.Y() );
+
+ sal_Int32 nAngle = ( EscherPropertyValueHelper::GetPropertyValue( aAny, aPropertySet, "RotateAngle", true ) )
+ ? *o3tl::doAccess<sal_Int32>(aAny) : 0;
+ if ( nAngle )
+ aPoly.Rotate( aRect.TopLeft(), Degree10(static_cast<sal_Int16>( ( nAngle + 5 ) / 10 )) );
+ nRule = GetClosestPoint( aPoly, aRefPoint );
+
+ if (aType == "drawing.Ellipse")
+ nRule <<= 1; // In PPT an ellipse has 8 ways to connect
+ }
+ }
+ return nRule;
+}
+
+EscherSolverContainer::EscherSolverContainer()
+{
+}
+
+EscherSolverContainer::~EscherSolverContainer()
+{
+}
+
+void EscherSolverContainer::AddShape( const uno::Reference<drawing::XShape> & rXShape, sal_uInt32 nId )
+{
+ maShapeList.push_back( std::make_unique<EscherShapeListEntry>( rXShape, nId ) );
+}
+
+void EscherSolverContainer::AddConnector(
+ const uno::Reference<drawing::XShape> & rConnector,
+ const awt::Point& rPA,
+ uno::Reference<drawing::XShape> const & rConA,
+ const awt::Point& rPB,
+ uno::Reference<drawing::XShape> const & rConB
+)
+{
+ maConnectorList.push_back( std::make_unique<EscherConnectorListEntry>( rConnector, rPA, rConA, rPB, rConB ) );
+}
+
+sal_uInt32 EscherSolverContainer::GetShapeId( const uno::Reference<drawing::XShape> & rXShape ) const
+{
+ for (auto const & pPtr : maShapeList)
+ {
+ if ( rXShape == pPtr->aXShape )
+ return pPtr->n_EscherId;
+ }
+ return 0;
+}
+
+void EscherSolverContainer::WriteSolver( SvStream& rStrm )
+{
+ sal_uInt32 nCount = maConnectorList.size();
+ if ( !nCount )
+ return;
+
+ sal_uInt32 nRecHdPos, nCurrentPos, nSize;
+ rStrm .WriteUInt16( ( nCount << 4 ) | 0xf ) // open an ESCHER_SolverContainer
+ .WriteUInt16( ESCHER_SolverContainer )
+ .WriteUInt32( 0 );
+
+ nRecHdPos = rStrm.Tell() - 4;
+
+ EscherConnectorRule aConnectorRule;
+ aConnectorRule.nRuleId = 2;
+ for (auto const & pPtr : maConnectorList)
+ {
+ aConnectorRule.ncptiA = aConnectorRule.ncptiB = 0xffffffff;
+ aConnectorRule.nShapeC = GetShapeId( pPtr->mXConnector );
+ aConnectorRule.nShapeA = GetShapeId( pPtr->mXConnectToA );
+ aConnectorRule.nShapeB = GetShapeId( pPtr->mXConnectToB );
+
+ if ( aConnectorRule.nShapeC )
+ {
+ if ( aConnectorRule.nShapeA )
+ aConnectorRule.ncptiA = pPtr->GetConnectorRule( true );
+ if ( aConnectorRule.nShapeB )
+ aConnectorRule.ncptiB = pPtr->GetConnectorRule( false );
+ }
+ rStrm .WriteUInt32( ( ESCHER_ConnectorRule << 16 ) | 1 ) // atom hd
+ .WriteUInt32( 24 )
+ .WriteUInt32( aConnectorRule.nRuleId )
+ .WriteUInt32( aConnectorRule.nShapeA )
+ .WriteUInt32( aConnectorRule.nShapeB )
+ .WriteUInt32( aConnectorRule.nShapeC )
+ .WriteUInt32( aConnectorRule.ncptiA )
+ .WriteUInt32( aConnectorRule.ncptiB );
+
+ aConnectorRule.nRuleId += 2;
+ }
+
+ nCurrentPos = rStrm.Tell(); // close the ESCHER_SolverContainer
+ nSize = ( nCurrentPos - nRecHdPos ) - 4;
+ rStrm.Seek( nRecHdPos );
+ rStrm.WriteUInt32( nSize );
+ rStrm.Seek( nCurrentPos );
+}
+
+EscherExGlobal::EscherExGlobal() :
+ EscherGraphicProvider( EscherGraphicProviderFlags::NONE ),
+ mpPicStrm( nullptr ),
+ mbHasDggCont( false ),
+ mbPicStrmQueried( false )
+{
+}
+
+EscherExGlobal::~EscherExGlobal()
+{
+}
+
+sal_uInt32 EscherExGlobal::GenerateDrawingId()
+{
+ // new drawing starts a new cluster in the cluster table (cluster identifiers are one-based)
+ sal_uInt32 nClusterId = static_cast< sal_uInt32 >( maClusterTable.size() + 1 );
+ // drawing identifiers are one-based
+ sal_uInt32 nDrawingId = static_cast< sal_uInt32 >( maDrawingInfos.size() + 1 );
+ // prepare new entries in the tables
+ maClusterTable.emplace_back( nDrawingId );
+ maDrawingInfos.emplace_back( nClusterId );
+ // return the new drawing identifier
+ return nDrawingId;
+}
+
+sal_uInt32 EscherExGlobal::GenerateShapeId( sal_uInt32 nDrawingId, bool bIsInSpgr )
+{
+ // drawing identifier is one-based
+ // make sure the drawing is valid (bnc#656503)
+ if ( nDrawingId == 0 )
+ return 0;
+ // create index from the identifier
+ size_t nDrawingIdx = nDrawingId - 1;
+ OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GenerateShapeId - invalid drawing ID" );
+ if( nDrawingIdx >= maDrawingInfos.size() )
+ return 0;
+ DrawingInfo& rDrawingInfo = maDrawingInfos[ nDrawingIdx ];
+
+ // cluster identifier in drawing info struct is one-based
+ ClusterEntry* pClusterEntry = &maClusterTable[ rDrawingInfo.mnClusterId - 1 ];
+
+ // check cluster overflow, create new cluster entry
+ if( pClusterEntry->mnNextShapeId == DFF_DGG_CLUSTER_SIZE )
+ {
+ // start a new cluster in the cluster table
+ maClusterTable.emplace_back( nDrawingId );
+ pClusterEntry = &maClusterTable.back();
+ // new size of maClusterTable is equal to one-based identifier of the new cluster
+ rDrawingInfo.mnClusterId = static_cast< sal_uInt32 >( maClusterTable.size() );
+ }
+
+ // build shape identifier from cluster identifier and next free cluster shape identifier
+ rDrawingInfo.mnLastShapeId = static_cast< sal_uInt32 >( rDrawingInfo.mnClusterId * DFF_DGG_CLUSTER_SIZE + pClusterEntry->mnNextShapeId );
+ // update free shape identifier in cluster entry
+ ++pClusterEntry->mnNextShapeId;
+ /* Old code has counted the shapes only, if we are in a SPGRCONTAINER. Is
+ this really intended? Maybe it's always true... */
+ if( bIsInSpgr )
+ ++rDrawingInfo.mnShapeCount;
+
+ // return the new shape identifier
+ return rDrawingInfo.mnLastShapeId;
+}
+
+sal_uInt32 EscherExGlobal::GetDrawingShapeCount( sal_uInt32 nDrawingId ) const
+{
+ size_t nDrawingIdx = nDrawingId - 1;
+ OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetDrawingShapeCount - invalid drawing ID" );
+ return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnShapeCount : 0;
+}
+
+sal_uInt32 EscherExGlobal::GetLastShapeId( sal_uInt32 nDrawingId ) const
+{
+ size_t nDrawingIdx = nDrawingId - 1;
+ OSL_ENSURE( nDrawingIdx < maDrawingInfos.size(), "EscherExGlobal::GetLastShapeId - invalid drawing ID" );
+ return (nDrawingIdx < maDrawingInfos.size()) ? maDrawingInfos[ nDrawingIdx ].mnLastShapeId : 0;
+}
+
+sal_uInt32 EscherExGlobal::GetDggAtomSize() const
+{
+ // 8 bytes header, 16 bytes fixed DGG data, 8 bytes for each cluster
+ return static_cast< sal_uInt32 >( 24 + 8 * maClusterTable.size() );
+}
+
+void EscherExGlobal::WriteDggAtom( SvStream& rStrm ) const
+{
+ sal_uInt32 nDggSize = GetDggAtomSize();
+
+ // write the DGG record header (do not include the 8 bytes of the header in the data size)
+ rStrm.WriteUInt32( ESCHER_Dgg << 16 ).WriteUInt32( nDggSize - 8 );
+
+ // calculate and write the fixed DGG data
+ sal_uInt32 nShapeCount = 0;
+ sal_uInt32 nLastShapeId = 0;
+ for (auto const& drawingInfo : maDrawingInfos)
+ {
+ nShapeCount += drawingInfo.mnShapeCount;
+ nLastShapeId = ::std::max( nLastShapeId, drawingInfo.mnLastShapeId );
+ }
+ // the non-existing cluster with index #0 is counted too
+ sal_uInt32 nClusterCount = static_cast< sal_uInt32 >( maClusterTable.size() + 1 );
+ sal_uInt32 nDrawingCount = static_cast< sal_uInt32 >( maDrawingInfos.size() );
+ rStrm.WriteUInt32( nLastShapeId ).WriteUInt32( nClusterCount ).WriteUInt32( nShapeCount ).WriteUInt32( nDrawingCount );
+
+ // write the cluster table
+ for (auto const& elem : maClusterTable)
+ rStrm.WriteUInt32( elem.mnDrawingId ).WriteUInt32( elem.mnNextShapeId );
+}
+
+SvStream* EscherExGlobal::QueryPictureStream()
+{
+ if( !mbPicStrmQueried )
+ {
+ mpPicStrm = ImplQueryPictureStream();
+ mbPicStrmQueried = true;
+ }
+ return mpPicStrm;
+}
+
+SvStream* EscherExGlobal::ImplQueryPictureStream()
+{
+ return nullptr;
+}
+
+namespace {
+
+// Implementation of an empty stream that silently succeeds, but does nothing.
+//
+// In fact, this is a hack. The right solution is to abstract EscherEx to be
+// able to work without SvStream; but at the moment it is better to live with
+// this I guess.
+class SvNullStream : public SvStream
+{
+protected:
+ virtual std::size_t GetData( void* pData, std::size_t nSize ) override { memset( pData, 0, nSize ); return nSize; }
+ virtual std::size_t PutData( const void*, std::size_t nSize ) override { return nSize; }
+ virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) override { return nPos; }
+ virtual void SetSize( sal_uInt64 ) override {}
+ virtual void FlushData() override {}
+
+public:
+ SvNullStream() {}
+};
+
+}
+
+EscherEx::EscherEx(std::shared_ptr<EscherExGlobal> xGlobal, SvStream* pOutStrm, bool bOOXML)
+ : mxGlobal(std::move(xGlobal))
+ , mpOutStrm(pOutStrm)
+ , mbOwnsStrm(false)
+ , mnCurrentDg(0)
+ , mnCountOfs(0)
+ , mnGroupLevel(0)
+ , mnHellLayerId(SDRLAYER_NOTFOUND)
+ , mbEscherSpgr(false)
+ , mbEscherDg(false)
+ , mbOOXML(bOOXML)
+{
+ if (!mpOutStrm)
+ {
+ mpOutStrm = new SvNullStream();
+ mbOwnsStrm = true;
+ }
+ mnStrmStartOfs = mpOutStrm->Tell();
+ mpImplEESdrWriter.reset( new ImplEESdrWriter( *this ) );
+}
+
+EscherEx::~EscherEx()
+{
+ if (mbOwnsStrm)
+ delete mpOutStrm;
+}
+
+void EscherEx::Flush( SvStream* pPicStreamMergeBSE /* = NULL */ )
+{
+ if ( !mxGlobal->HasDggContainer() )
+ return;
+
+ // store the current stream position at ESCHER_Persist_CurrentPosition key
+ PtReplaceOrInsert( ESCHER_Persist_CurrentPosition, mpOutStrm->Tell() );
+ if ( DoSeek( ESCHER_Persist_Dgg ) )
+ {
+ /* The DGG record is still not written. ESCHER_Persist_Dgg seeks
+ to the place where the complete record has to be inserted. */
+ InsertAtCurrentPos( mxGlobal->GetDggAtomSize() );
+ mxGlobal->WriteDggAtom( *mpOutStrm );
+
+ if ( mxGlobal->HasGraphics() )
+ {
+ /* Calculate the total size of the BSTORECONTAINER including
+ all BSE records containing the picture data contained in
+ the passed in pPicStreamMergeBSE. */
+ sal_uInt32 nBSCSize = mxGlobal->GetBlibStoreContainerSize( pPicStreamMergeBSE );
+ if ( nBSCSize > 0 )
+ {
+ InsertAtCurrentPos( nBSCSize );
+ mxGlobal->WriteBlibStoreContainer( *mpOutStrm, pPicStreamMergeBSE );
+ }
+ }
+
+ /* Forget the stream position stored for the DGG which is invalid
+ after the call to InsertAtCurrentPos() anyway. */
+ PtDelete( ESCHER_Persist_Dgg );
+ }
+ // seek to initial position (may be different due to inserted DGG and BLIPs)
+ mpOutStrm->Seek( PtGetOffsetByID( ESCHER_Persist_CurrentPosition ) );
+}
+
+void EscherEx::InsertAtCurrentPos( sal_uInt32 nBytes )
+{
+ sal_uInt32 nSize, nType, nSource, nBufSize, nToCopy, nCurPos = mpOutStrm->Tell();
+
+ // adjust persist table
+ for(auto const & pPtr : maPersistTable) {
+ sal_uInt32 nOfs = pPtr->mnOffset;
+ if ( nOfs >= nCurPos ) {
+ pPtr->mnOffset += nBytes;
+ }
+ }
+
+ // adapt container and atom sizes
+ mpOutStrm->Seek( mnStrmStartOfs );
+ while ( mpOutStrm->Tell() < nCurPos )
+ {
+ mpOutStrm->ReadUInt32( nType ).ReadUInt32( nSize );
+ sal_uInt32 nEndOfRecord = mpOutStrm->Tell() + nSize;
+ bool bContainer = (nType & 0x0F) == 0x0F;
+ /* Expand the record, if the insertion position is inside, or if the
+ position is at the end of a container (expands always), or at the
+ end of an atom and bExpandEndOfAtom is set. */
+ if ( (nCurPos < nEndOfRecord) || ((nCurPos == nEndOfRecord) && bContainer) )
+ {
+ mpOutStrm->SeekRel( -4 );
+ mpOutStrm->WriteUInt32( nSize + nBytes );
+ if ( !bContainer )
+ mpOutStrm->SeekRel( nSize );
+ }
+ else
+ mpOutStrm->SeekRel( nSize );
+ }
+ for (auto & offset : mOffsets)
+ {
+ if ( offset > nCurPos )
+ offset += nBytes;
+ }
+ nSource = mpOutStrm->TellEnd();
+ nToCopy = nSource - nCurPos; // increase the size of the stream by nBytes
+ std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8[ 0x40000 ]); // 256KB Buffer
+ while ( nToCopy )
+ {
+ nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy;
+ nToCopy -= nBufSize;
+ nSource -= nBufSize;
+ mpOutStrm->Seek( nSource );
+ mpOutStrm->ReadBytes(pBuf.get(), nBufSize);
+ mpOutStrm->Seek( nSource + nBytes );
+ mpOutStrm->WriteBytes(pBuf.get(), nBufSize);
+ }
+ mpOutStrm->Seek( nCurPos );
+}
+
+void EscherEx::InsertPersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset )
+{
+ PtInsert( ESCHER_Persist_PrivateEntry | nKey, nOffset );
+}
+
+void EscherEx::ReplacePersistOffset( sal_uInt32 nKey, sal_uInt32 nOffset )
+{
+ PtReplace( ESCHER_Persist_PrivateEntry | nKey, nOffset );
+}
+
+void EscherEx::SetEditAs( const OUString& rEditAs )
+{
+ mEditAs = rEditAs;
+}
+
+sal_uInt32 EscherEx::GetPersistOffset( sal_uInt32 nKey )
+{
+ return PtGetOffsetByID( ESCHER_Persist_PrivateEntry | nKey );
+}
+
+bool EscherEx::DoSeek( sal_uInt32 nKey )
+{
+ sal_uInt32 nPos = PtGetOffsetByID( nKey );
+ if ( nPos )
+ mpOutStrm->Seek( nPos );
+ else
+ {
+ if (! PtIsID( nKey ) )
+ return false;
+ mpOutStrm->Seek( 0 );
+ }
+ return true;
+}
+
+bool EscherEx::SeekToPersistOffset( sal_uInt32 nKey )
+{
+ return DoSeek( ESCHER_Persist_PrivateEntry | nKey );
+}
+
+void EscherEx::InsertAtPersistOffset( sal_uInt32 nKey, sal_uInt32 nValue )
+{
+ sal_uInt32 nOldPos = mpOutStrm->Tell();
+ bool bRetValue = SeekToPersistOffset( nKey );
+ if ( bRetValue )
+ {
+ mpOutStrm->WriteUInt32( nValue );
+ mpOutStrm->Seek( nOldPos );
+ }
+}
+
+void EscherEx::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
+{
+ mpOutStrm->WriteUInt16( ( nRecInstance << 4 ) | 0xf ).WriteUInt16( nEscherContainer ).WriteUInt32( 0 );
+ mOffsets.push_back( mpOutStrm->Tell() - 4 );
+ mRecTypes.push_back( nEscherContainer );
+ switch( nEscherContainer )
+ {
+ case ESCHER_DggContainer :
+ {
+ mxGlobal->SetDggContainer();
+ mnCurrentDg = 0;
+ /* Remember the current position as start position of the DGG
+ record and BSTORECONTAINER, but do not write them actually.
+ This will be done later in Flush() when the number of drawings,
+ the size and contents of the FIDCL cluster table, and the size
+ of the BLIP container are known. */
+ PtReplaceOrInsert( ESCHER_Persist_Dgg, mpOutStrm->Tell() );
+ }
+ break;
+
+ case ESCHER_DgContainer :
+ {
+ if ( mxGlobal->HasDggContainer() )
+ {
+ if ( !mbEscherDg )
+ {
+ mbEscherDg = true;
+ mnCurrentDg = mxGlobal->GenerateDrawingId();
+ AddAtom( 8, ESCHER_Dg, 0, mnCurrentDg );
+ PtReplaceOrInsert( ESCHER_Persist_Dg | mnCurrentDg, mpOutStrm->Tell() );
+ mpOutStrm->WriteUInt32( 0 ) // The number of shapes in this drawing
+ .WriteUInt32( 0 ); // The last MSOSPID given to an SP in this DG
+ }
+ }
+ }
+ break;
+
+ case ESCHER_SpgrContainer :
+ {
+ if ( mbEscherDg )
+ {
+ mbEscherSpgr = true;
+ }
+ }
+ break;
+
+ case ESCHER_SpContainer :
+ {
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+void EscherEx::CloseContainer()
+{
+ sal_uInt32 nSize, nPos = mpOutStrm->Tell();
+ nSize = ( nPos - mOffsets.back() ) - 4;
+ mpOutStrm->Seek( mOffsets.back() );
+ mpOutStrm->WriteUInt32( nSize );
+
+ switch( mRecTypes.back() )
+ {
+ case ESCHER_DgContainer :
+ {
+ if ( mbEscherDg )
+ {
+ mbEscherDg = false;
+ if ( DoSeek( ESCHER_Persist_Dg | mnCurrentDg ) )
+ mpOutStrm->WriteUInt32( mxGlobal->GetDrawingShapeCount( mnCurrentDg ) ).WriteUInt32( mxGlobal->GetLastShapeId( mnCurrentDg ) );
+ }
+ }
+ break;
+
+ case ESCHER_SpgrContainer :
+ {
+ if ( mbEscherSpgr )
+ {
+ mbEscherSpgr = false;
+
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ mOffsets.pop_back();
+ mRecTypes.pop_back();
+ mpOutStrm->Seek( nPos );
+}
+
+void EscherEx::BeginAtom()
+{
+ mnCountOfs = mpOutStrm->Tell();
+ mpOutStrm->WriteUInt32( 0 ).WriteUInt32( 0 ); // record header will be written later
+}
+
+void EscherEx::EndAtom( sal_uInt16 nRecType, int nRecVersion, int nRecInstance )
+{
+ sal_uInt32 nOldPos = mpOutStrm->Tell();
+ mpOutStrm->Seek( mnCountOfs );
+ sal_uInt32 nSize = nOldPos - mnCountOfs;
+ mpOutStrm->WriteUInt16( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ).WriteUInt16( nRecType ).WriteUInt32( nSize - 8 );
+ mpOutStrm->Seek( nOldPos );
+}
+
+void EscherEx::AddAtom( sal_uInt32 nAtomSize, sal_uInt16 nRecType, int nRecVersion, int nRecInstance )
+{
+ mpOutStrm->WriteUInt16( ( nRecInstance << 4 ) | ( nRecVersion & 0xf ) ).WriteUInt16( nRecType ).WriteUInt32( nAtomSize );
+}
+
+void EscherEx::AddChildAnchor( const tools::Rectangle& rRect )
+{
+ AddAtom( 16, ESCHER_ChildAnchor );
+ mpOutStrm ->WriteInt32( rRect.Left() )
+ .WriteInt32( rRect.Top() )
+ .WriteInt32( rRect.Right() )
+ .WriteInt32( rRect.Bottom() );
+}
+
+void EscherEx::AddClientAnchor( const tools::Rectangle& rRect )
+{
+ AddAtom( 8, ESCHER_ClientAnchor );
+ mpOutStrm->WriteInt16( rRect.Top() )
+ .WriteInt16( rRect.Left() )
+ .WriteInt16( rRect.GetWidth() + rRect.Left() )
+ .WriteInt16( rRect.GetHeight() + rRect.Top() );
+}
+
+EscherExHostAppData* EscherEx::EnterAdditionalTextGroup()
+{
+ return nullptr;
+}
+
+sal_uInt32 EscherEx::EnterGroup( const OUString& rShapeName, const tools::Rectangle* pBoundRect )
+{
+ tools::Rectangle aRect;
+ if( pBoundRect )
+ aRect = *pBoundRect;
+
+ OpenContainer( ESCHER_SpgrContainer );
+ OpenContainer( ESCHER_SpContainer );
+ AddAtom( 16, ESCHER_Spgr, 1 );
+ PtReplaceOrInsert( ESCHER_Persist_Grouping_Snap | mnGroupLevel,
+ mpOutStrm->Tell() );
+ mpOutStrm ->WriteInt32( aRect.Left() ) // Bounding box for the grouped shapes to which they will be attached
+ .WriteInt32( aRect.Top() )
+ .WriteInt32( aRect.IsWidthEmpty() ? aRect.Left() : aRect.Right() )
+ .WriteInt32( aRect.IsHeightEmpty() ? aRect.Top() : aRect.Bottom() );
+
+ sal_uInt32 nShapeId = GenerateShapeId();
+ if ( !mnGroupLevel )
+ AddShape( ESCHER_ShpInst_Min, ShapeFlag::Group | ShapeFlag::Patriarch, nShapeId );
+ else
+ {
+ AddShape( ESCHER_ShpInst_Min, ShapeFlag::Group | ShapeFlag::HaveAnchor, nShapeId );
+ EscherPropertyContainer aPropOpt;
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x00040004 );
+ aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
+ aPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
+
+ // #i51348# shape name
+ if( rShapeName.getLength() > 0 )
+ aPropOpt.AddOpt( ESCHER_Prop_wzName, rShapeName );
+
+ Commit( aPropOpt, aRect );
+ if ( mnGroupLevel > 1 )
+ AddChildAnchor( aRect );
+
+ EscherExHostAppData* pAppData = mpImplEESdrWriter->ImplGetHostData();
+ if( pAppData )
+ {
+ if ( mnGroupLevel <= 1 )
+ pAppData->WriteClientAnchor( *this, aRect );
+ pAppData->WriteClientData( *this );
+ }
+ }
+ CloseContainer(); // ESCHER_SpContainer
+ mnGroupLevel++;
+ return nShapeId;
+}
+
+sal_uInt32 EscherEx::EnterGroup( const tools::Rectangle* pBoundRect )
+{
+ return EnterGroup( OUString(), pBoundRect );
+}
+
+void EscherEx::SetGroupSnapRect( sal_uInt32 nGroupLevel, const tools::Rectangle& rRect )
+{
+ if ( nGroupLevel )
+ {
+ sal_uInt32 nCurrentPos = mpOutStrm->Tell();
+ if ( DoSeek( ESCHER_Persist_Grouping_Snap | ( nGroupLevel - 1 ) ) )
+ {
+ mpOutStrm ->WriteInt32( rRect.Left() ) // Bounding box for the grouped shapes to which they will be attached
+ .WriteInt32( rRect.Top() )
+ .WriteInt32( rRect.Right() )
+ .WriteInt32( rRect.Bottom() );
+ mpOutStrm->Seek( nCurrentPos );
+ }
+ }
+}
+
+void EscherEx::SetGroupLogicRect( sal_uInt32 nGroupLevel, const tools::Rectangle& rRect )
+{
+ if ( nGroupLevel )
+ {
+ sal_uInt32 nCurrentPos = mpOutStrm->Tell();
+ if ( DoSeek( ESCHER_Persist_Grouping_Logic | ( nGroupLevel - 1 ) ) )
+ {
+ mpOutStrm->WriteInt16( rRect.Top() ).WriteInt16( rRect.Left() ).WriteInt16( rRect.Right() ).WriteInt16( rRect.Bottom() );
+ mpOutStrm->Seek( nCurrentPos );
+ }
+ }
+}
+
+void EscherEx::LeaveGroup()
+{
+ --mnGroupLevel;
+ PtDelete( ESCHER_Persist_Grouping_Snap | mnGroupLevel );
+ PtDelete( ESCHER_Persist_Grouping_Logic | mnGroupLevel );
+ CloseContainer();
+}
+
+void EscherEx::AddShape( sal_uInt32 nShpInstance, ShapeFlag nFlags, sal_uInt32 nShapeID )
+{
+ AddAtom( 8, ESCHER_Sp, 2, nShpInstance );
+
+ if ( !nShapeID )
+ nShapeID = GenerateShapeId();
+
+ if (nFlags ^ ShapeFlag::Group) // no pure group shape
+ {
+ if ( mnGroupLevel > 1 )
+ nFlags |= ShapeFlag::Child; // this not a topmost shape
+ }
+ mpOutStrm->WriteUInt32( nShapeID ).WriteUInt32( static_cast<sal_uInt32>(nFlags) );
+}
+
+void EscherEx::Commit( EscherPropertyContainer& rProps, const tools::Rectangle& )
+{
+ rProps.Commit( GetStream() );
+}
+
+sal_uInt32 EscherEx::GetColor( const sal_uInt32 nSOColor )
+{
+ sal_uInt32 nColor = nSOColor & 0xff00; // Green
+ nColor |= static_cast<sal_uInt8>(nSOColor) << 16; // Red
+ nColor |= static_cast<sal_uInt8>( nSOColor >> 16 ); // Blue
+ return nColor;
+}
+
+sal_uInt32 EscherEx::GetColor( const Color& rSOColor )
+{
+ sal_uInt32 nColor = ( rSOColor.GetRed() << 16 );
+ nColor |= ( rSOColor.GetGreen() << 8 );
+ nColor |= rSOColor.GetBlue();
+ nColor = GetColor( nColor );
+ return nColor;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/eschesdo.cxx b/filter/source/msfilter/eschesdo.cxx
new file mode 100644
index 000000000..d052b5968
--- /dev/null
+++ b/filter/source/msfilter/eschesdo.cxx
@@ -0,0 +1,1237 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <memory>
+#include "eschesdo.hxx"
+#include <o3tl/any.hxx>
+#include <svx/svdobj.hxx>
+#include <tools/poly.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <svx/fmdpage.hxx>
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/drawing/CircleKind.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <comphelper/extract.hxx>
+#include <com/sun/star/drawing/HomogenMatrix3.hpp>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::drawing;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::task;
+
+constexpr o3tl::Length geUnitsSrc(o3tl::Length::mm100);
+// PowerPoint: 576 dpi, WinWord: 1440 dpi, Excel: 1440 dpi
+constexpr o3tl::Length geUnitsDest(o3tl::Length::twip);
+
+ImplEESdrWriter::ImplEESdrWriter( EscherEx& rEx )
+ : mpEscherEx(&rEx)
+ , mpPicStrm(nullptr)
+ , mpHostAppData(nullptr)
+ , mbIsTitlePossible(false)
+ , mpSdrPage( nullptr )
+{
+}
+
+
+
+Point ImplEESdrWriter::ImplMapPoint( const Point& rPoint )
+{
+ return o3tl::convert( rPoint, geUnitsSrc, geUnitsDest );
+}
+
+Size ImplEESdrWriter::ImplMapSize( const Size& rSize )
+{
+ Size aRetSize( o3tl::convert( rSize, geUnitsSrc, geUnitsDest ) );
+
+ if ( !aRetSize.Width() )
+ aRetSize.AdjustWidth( 1 );
+ if ( !aRetSize.Height() )
+ aRetSize.AdjustHeight( 1 );
+ return aRetSize;
+}
+
+void ImplEESdrWriter::ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt )
+{
+ sal_Int32 nAngle = rObj.GetAngle();
+ tools::Rectangle aRect( rObj.GetRect() );
+
+ // for position calculations, we normalize the angle between 0 and 90 degrees
+ if ( nAngle < 0 )
+ nAngle = ( 36000 + nAngle ) % 36000;
+ if ( nAngle % 18000 == 0 )
+ nAngle = 0;
+ while ( nAngle > 9000 )
+ nAngle = ( 18000 - ( nAngle % 18000 ) );
+
+ double fVal = basegfx::deg2rad<100>(nAngle);
+ double fCos = cos( fVal );
+ double fSin = sin( fVal );
+
+ double nWidthHalf = static_cast<double>(aRect.GetWidth()) / 2;
+ double nHeightHalf = static_cast<double>(aRect.GetHeight()) / 2;
+
+ // fdo#70838:
+ // when you rotate an object, the top-left corner of its bounding box is moved
+ // nXDiff and nYDiff pixels. To get their values we use these equations:
+ //
+ // fSin * nHeightHalf + fCos * nWidthHalf == nXDiff + nWidthHalf
+ // fSin * nWidthHalf + fCos * nHeightHalf == nYDiff + nHeightHalf
+
+ double nXDiff = fSin * nHeightHalf + fCos * nWidthHalf - nWidthHalf;
+ double nYDiff = fSin * nWidthHalf + fCos * nHeightHalf - nHeightHalf;
+
+ aRect.Move( static_cast<sal_Int32>(nXDiff), static_cast<sal_Int32>(nYDiff) );
+
+ // calculate the proper angle value to be saved
+ nAngle = rObj.GetAngle();
+ if ( nAngle < 0 )
+ nAngle = ( 36000 + nAngle ) % 36000;
+ else
+ nAngle = ( 36000 - ( nAngle % 36000 ) );
+
+ nAngle *= 655;
+ nAngle += 0x8000;
+ nAngle &=~0xffff; // nAngle round to full degrees
+ rPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
+
+ rObj.SetAngle( nAngle );
+ rObj.SetRect( aRect );
+}
+
+
+sal_uInt32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj,
+ EscherSolverContainer& rSolverContainer,
+ const bool bOOxmlExport )
+{
+ sal_uInt32 nShapeID = 0;
+ sal_uInt16 nShapeType = 0;
+ bool bDontWriteText = false; // if a metafile is written as shape replacement, then the text is already part of the metafile
+ bool bAdditionalText = false;
+ sal_uInt32 nGrpShapeID = 0;
+ auto addShape = [this, &rObj, &rSolverContainer, &nShapeID, &nShapeType](sal_uInt16 nType, ShapeFlag nFlags)
+ {
+ nShapeType = nType;
+ nShapeID = mpEscherEx->GenerateShapeId();
+ rObj.SetShapeId( nShapeID );
+ mpEscherEx->AddShape( nType, nFlags, nShapeID );
+ rSolverContainer.AddShape( rObj.GetShapeRef(), nShapeID );
+ };
+
+ do {
+ mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : nullptr );
+ if ( mpHostAppData && mpHostAppData->DontWriteShape() )
+ break;
+
+ // #i51348# get shape name
+ OUString aShapeName;
+ if( const SdrObject* pSdrObj = rObj.GetSdrObject() )
+ if (!pSdrObj->GetName().isEmpty())
+ aShapeName = pSdrObj->GetName();
+ uno::Reference< drawing::XShape> xShape = rObj.GetShapeRef();
+ if (xShape.is())
+ {
+ uno::Reference<beans::XPropertySet> xPropertySet(xShape, uno::UNO_QUERY);
+ if (xPropertySet.is())
+ {
+ uno::Sequence<beans::PropertyValue> aGrabBag;
+ uno::Reference< XPropertySetInfo > xPropInfo = xPropertySet->getPropertySetInfo();
+ if ( xPropInfo.is() && xPropInfo->hasPropertyByName( "InteropGrabBag" ) )
+ {
+ xPropertySet->getPropertyValue( "InteropGrabBag" ) >>= aGrabBag;
+ for (const beans::PropertyValue& rProp : std::as_const(aGrabBag))
+ {
+ if (rProp.Name == "mso-edit-as")
+ {
+ OUString rEditAs;
+ rProp.Value >>= rEditAs;
+ mpEscherEx->SetEditAs(rEditAs);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if( rObj.GetType() == "drawing.Group" )
+ {
+ Reference< XIndexAccess > xXIndexAccess( rObj.GetShapeRef(), UNO_QUERY );
+
+ if( xXIndexAccess.is() && 0 != xXIndexAccess->getCount() )
+ {
+ nShapeID = mpEscherEx->EnterGroup( aShapeName, &rObj.GetRect() );
+ nShapeType = ESCHER_ShpInst_Min;
+
+ for( sal_uInt32 n = 0, nCnt = xXIndexAccess->getCount();
+ n < nCnt; ++n )
+ {
+ ImplEESdrObject aObj( *o3tl::doAccess<Reference<XShape>>(
+ xXIndexAccess->getByIndex( n )) );
+ if( aObj.IsValid() )
+ {
+ aObj.SetOOXML(bOOxmlExport);
+ ImplWriteShape( aObj, rSolverContainer, bOOxmlExport );
+ }
+ }
+ mpEscherEx->LeaveGroup();
+ }
+ break;
+ }
+ rObj.SetAngle( rObj.ImplGetInt32PropertyValue( "RotateAngle" ));
+
+ if( ( rObj.ImplGetPropertyValue( "IsFontwork" ) &&
+ ::cppu::any2bool( rObj.GetUsrAny() ) ) ||
+ rObj.GetType() == "drawing.Measure" )
+ {
+ rObj.SetType("drawing.dontknow");
+ }
+
+ const css::awt::Size aSize100thmm( rObj.GetShapeRef()->getSize() );
+ const css::awt::Point aPoint100thmm( rObj.GetShapeRef()->getPosition() );
+ tools::Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
+ if ( !mpPicStrm )
+ mpPicStrm = mpEscherEx->QueryPictureStream();
+ EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
+
+ // #i51348# shape name
+ if (!aShapeName.isEmpty())
+ aPropOpt.AddOpt( ESCHER_Prop_wzName, aShapeName );
+ if ( InteractionInfo* pInteraction = mpHostAppData ? mpHostAppData->GetInteractionInfo():nullptr )
+ {
+ const std::unique_ptr< SvMemoryStream >& pMemStrm = pInteraction->getHyperlinkRecord();
+ if (pMemStrm)
+ {
+ aPropOpt.AddOpt(ESCHER_Prop_pihlShape, false, 0, *pMemStrm);
+ }
+ aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080008 );
+ }
+
+ if ( rObj.GetType() == "drawing.Custom" )
+ {
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ ShapeFlag nMirrorFlags;
+
+ OUString sCustomShapeType;
+ MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( rObj.GetShapeRef(), nMirrorFlags, sCustomShapeType, rObj.GetOOXML() );
+ if ( sCustomShapeType == "col-502ad400" || sCustomShapeType == "col-60da8460" )
+ {
+ addShape( ESCHER_ShpInst_PictureFrame, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+
+ if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", false ) )
+ {
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 ); // no fill
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); // no linestyle
+ SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rObj.GetShapeRef());
+ if ( pObj )
+ {
+ tools::Rectangle aBound = pObj->GetCurrentBoundRect();
+ Point aPosition( ImplMapPoint( aBound.TopLeft() ) );
+ Size aSize( ImplMapSize( aBound.GetSize() ) );
+ rObj.SetRect( tools::Rectangle( aPosition, aSize ) );
+ rObj.SetAngle( 0 );
+ bDontWriteText = true;
+ }
+ }
+ }
+ else
+ {
+ const Reference< XPropertySet > xPropSet = rObj.mXPropSet;
+ drawing::FillStyle eFS = drawing::FillStyle_NONE;
+ if(xPropSet.is())
+ {
+ uno::Reference< XPropertySetInfo > xPropInfo = xPropSet->getPropertySetInfo();
+ if ( xPropInfo.is() && xPropInfo->hasPropertyByName("FillStyle"))
+ xPropSet->getPropertyValue("FillStyle") >>= eFS;
+ }
+
+ if (eFS == drawing::FillStyle_BITMAP && eShapeType == mso_sptMax)
+ {
+ // We can't map this custom shape to a DOC preset and it has a bitmap fill.
+ // Make sure that at least the bitmap fill is not lost.
+ addShape( ESCHER_ShpInst_PictureFrame, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "Bitmap", false, true, true, bOOxmlExport ) )
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
+ }
+ else
+ {
+ addShape(sal::static_int_cast< sal_uInt16 >(eShapeType),
+ nMirrorFlags | ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor);
+ aPropOpt.CreateCustomShapeProperties( eShapeType, rObj.GetShapeRef() );
+ aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
+ if ( rObj.ImplGetText() )
+ {
+ if ( !aPropOpt.IsFontWork() )
+ aPropOpt.CreateTextProperties( rObj.mXPropSet, mpEscherEx->QueryTextID(
+ rObj.GetShapeRef(), rObj.GetShapeId() ), true, false );
+ }
+ }
+ }
+ }
+ else if ( rObj.GetType() == "drawing.Rectangle" )
+ {
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ sal_Int32 nRadius = rObj.ImplGetInt32PropertyValue("CornerRadius");
+ if( nRadius )
+ {
+ nRadius = ImplMapSize( Size( nRadius, 0 )).Width();
+ addShape( ESCHER_ShpInst_RoundRectangle, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ sal_Int32 nLength = rObj.GetRect().GetWidth();
+ if ( nLength > rObj.GetRect().GetHeight() )
+ nLength = rObj.GetRect().GetHeight();
+ nLength >>= 1;
+ if ( nRadius >= nLength || nLength == 0 )
+ nRadius = 0x2a30; // 0x2a30 is PPTs maximum radius
+ else
+ nRadius = ( 0x2a30 * nRadius ) / nLength;
+ aPropOpt.AddOpt( ESCHER_Prop_adjustValue, nRadius );
+ }
+ else
+ {
+ addShape( ESCHER_ShpInst_Rectangle, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ }
+ aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
+ if( rObj.ImplGetText() )
+ aPropOpt.CreateTextProperties( rObj.mXPropSet,
+ mpEscherEx->QueryTextID( rObj.GetShapeRef(),
+ rObj.GetShapeId() ), false, false );
+ }
+ else if ( rObj.GetType() == "drawing.Ellipse" )
+ {
+ CircleKind eCircleKind = CircleKind_FULL;
+ PolyStyle ePolyKind = PolyStyle();
+ if ( rObj.ImplGetPropertyValue( "CircleKind" ) )
+ {
+ eCircleKind = *o3tl::doAccess<CircleKind>(rObj.GetUsrAny());
+ switch ( eCircleKind )
+ {
+ case CircleKind_SECTION :
+ {
+ ePolyKind = PolyStyle::Pie;
+ }
+ break;
+ case CircleKind_ARC :
+ {
+ ePolyKind = PolyStyle::Arc;
+ }
+ break;
+
+ case CircleKind_CUT :
+ {
+ ePolyKind = PolyStyle::Chord;
+ }
+ break;
+
+ default:
+ eCircleKind = CircleKind_FULL;
+ }
+ }
+ if ( eCircleKind == CircleKind_FULL )
+ {
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_Ellipse, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
+ }
+ else
+ {
+ sal_Int32 nStartAngle, nEndAngle;
+ if ( !rObj.ImplGetPropertyValue( "CircleStartAngle" ) )
+ break;
+ nStartAngle = *o3tl::doAccess<sal_Int32>(rObj.GetUsrAny());
+ if( !rObj.ImplGetPropertyValue( "CircleEndAngle" ) )
+ break;
+ nEndAngle = *o3tl::doAccess<sal_Int32>(rObj.GetUsrAny());
+
+ Point aStart, aEnd, aCenter;
+ aStart.setX( static_cast<sal_Int32>( cos( basegfx::deg2rad<100>(nStartAngle) ) * 100.0 ) );
+ aStart.setY( - static_cast<sal_Int32>( sin( basegfx::deg2rad<100>(nStartAngle) ) * 100.0 ) );
+ aEnd.setX( static_cast<sal_Int32>( cos( basegfx::deg2rad<100>(nEndAngle) ) * 100.0 ) );
+ aEnd.setY( - static_cast<sal_Int32>( sin( basegfx::deg2rad<100>(nEndAngle) ) * 100.0 ) );
+ const tools::Rectangle& rRect = aRect100thmm;
+ aCenter.setX( rRect.Left() + ( rRect.GetWidth() / 2 ) );
+ aCenter.setY( rRect.Top() + ( rRect.GetHeight() / 2 ) );
+ aStart.AdjustX(aCenter.X() );
+ aStart.AdjustY(aCenter.Y() );
+ aEnd.AdjustX(aCenter.X() );
+ aEnd.AdjustY(aCenter.Y() );
+ tools::Polygon aPolygon( rRect, aStart, aEnd, ePolyKind );
+ if( rObj.GetAngle() )
+ {
+ aPolygon.Rotate( rRect.TopLeft(), Degree10(static_cast<sal_Int16>( rObj.GetAngle() / 10 )) );
+ rObj.SetAngle( 0 );
+ }
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_NotPrimitive, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ css::awt::Rectangle aNewRect;
+ switch ( ePolyKind )
+ {
+ case PolyStyle::Pie :
+ case PolyStyle::Chord :
+ {
+ aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, false, aNewRect, &aPolygon );
+ aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
+ }
+ break;
+
+ case PolyStyle::Arc :
+ {
+ aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, false, aNewRect, &aPolygon );
+ aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
+ }
+ break;
+ }
+ rObj.SetRect( tools::Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
+ ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
+ }
+ if ( rObj.ImplGetText() )
+ aPropOpt.CreateTextProperties( rObj.mXPropSet,
+ mpEscherEx->QueryTextID( rObj.GetShapeRef(),
+ rObj.GetShapeId() ), false, false );
+
+ }
+ else if ( rObj.GetType() == "drawing.Control" )
+ {
+ const Reference< XPropertySet > xPropSet = rObj.mXPropSet;
+ const Reference<XPropertySetInfo> xPropInfo = xPropSet.is() ? xPropSet->getPropertySetInfo() : Reference<XPropertySetInfo>();
+ // This code is expected to be called only for DOCX/XLSX formats.
+ if (xPropInfo.is() && bOOxmlExport)
+ {
+ bool bInline = false;
+ if (xPropInfo->hasPropertyByName("AnchorType"))
+ {
+ text::TextContentAnchorType eAnchorType;
+ xPropSet->getPropertyValue("AnchorType") >>= eAnchorType;
+ bInline = eAnchorType == text::TextContentAnchorType_AS_CHARACTER;
+ }
+
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ if(bInline)
+ {
+ addShape( ESCHER_ShpInst_PictureFrame, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ }
+ else
+ {
+ addShape( ESCHER_ShpInst_HostControl, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ }
+ }
+ else
+ break;
+ }
+ else if ( rObj.GetType() == "drawing.Connector" )
+ {
+ sal_uInt16 nSpType;
+ ShapeFlag nSpFlags;
+ css::awt::Rectangle aNewRect;
+ if ( ! aPropOpt.CreateConnectorProperties( rObj.GetShapeRef(),
+ rSolverContainer, aNewRect, nSpType, nSpFlags ) )
+ break;
+ rObj.SetRect( tools::Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
+ ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
+
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( nSpType, nSpFlags );
+ }
+ else if ( rObj.GetType() == "drawing.Measure" )
+ {
+ break;
+ }
+ else if ( rObj.GetType() == "drawing.Line" )
+ {
+ css::awt::Rectangle aNewRect;
+ aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_LINE, false, aNewRect );
+ //i27942: Poly/Lines/Bezier do not support text.
+
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ ShapeFlag nFlags = ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor;
+ if( aNewRect.Height < 0 )
+ nFlags |= ShapeFlag::FlipV;
+ if( aNewRect.Width < 0 )
+ nFlags |= ShapeFlag::FlipH;
+
+ addShape( ESCHER_ShpInst_Line, nFlags );
+ aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
+ aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
+ rObj.SetAngle( 0 );
+ }
+ else if ( rObj.GetType() == "drawing.PolyPolygon" )
+ {
+ if( rObj.ImplHasText() )
+ {
+ nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
+ bAdditionalText = true;
+ }
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_NotPrimitive, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ css::awt::Rectangle aNewRect;
+ aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, false, aNewRect );
+ aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
+ rObj.SetAngle( 0 );
+ }
+ else if ( rObj.GetType() == "drawing.PolyLine" )
+ {
+ //i27942: Poly/Lines/Bezier do not support text.
+
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_NotPrimitive, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ css::awt::Rectangle aNewRect;
+ aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, false, aNewRect );
+ aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
+ rObj.SetAngle( 0 );
+ }
+ else if ( rObj.GetType() == "drawing.OpenBezier" )
+ {
+ //i27942: Poly/Lines/Bezier do not support text.
+
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_NotPrimitive, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ css::awt::Rectangle aNewRect;
+ aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, true, aNewRect );
+ aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
+ rObj.SetAngle( 0 );
+ }
+ else if ( rObj.GetType() == "drawing.ClosedBezier" )
+ {
+ if ( rObj.ImplHasText() )
+ {
+ nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
+ bAdditionalText = true;
+ }
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_NotPrimitive, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ css::awt::Rectangle aNewRect;
+ aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, true, aNewRect );
+ aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
+ rObj.SetAngle( 0 );
+ }
+ else if ( rObj.GetType() == "drawing.GraphicObject" )
+ {
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+
+ // a GraphicObject can also be a ClickMe element
+ if( rObj.IsEmptyPresObj() )
+ {
+ addShape( ESCHER_ShpInst_Rectangle, ShapeFlag::HaveMaster | ShapeFlag::HaveAnchor );
+ sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
+ rObj.GetShapeId() );
+ aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
+ aPropOpt.AddOpt( ESCHER_Prop_hspMaster, 0 );
+ }
+ else
+ {
+ if( rObj.ImplGetText() )
+ {
+ /* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we
+ have to create a simple Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat).
+ */
+ addShape( ESCHER_ShpInst_Rectangle, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "Graphic", true, true, false ) )
+ {
+ aPropOpt.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
+ aPropOpt.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
+ aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x8000000 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
+ if ( rObj.ImplGetText() )
+ aPropOpt.CreateTextProperties( rObj.mXPropSet,
+ mpEscherEx->QueryTextID( rObj.GetShapeRef(),
+ rObj.GetShapeId() ), false, false );
+ }
+ }
+ else
+ {
+ addShape( ESCHER_ShpInst_PictureFrame, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "Graphic", false, true, true, bOOxmlExport ) )
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
+ }
+ }
+ }
+ else if ( rObj.GetType() == "drawing.Text" )
+ {
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_TextBox, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
+ if( rObj.ImplGetText() )
+ aPropOpt.CreateTextProperties( rObj.mXPropSet,
+ mpEscherEx->QueryTextID( rObj.GetShapeRef(),
+ rObj.GetShapeId() ) );
+ }
+ else if ( rObj.GetType() == "drawing.Page" )
+ {
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_Rectangle, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x40004 );
+ aPropOpt.AddOpt( ESCHER_Prop_fFillOK, 0x100001 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x110011 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90008 );
+ aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x10001 );
+ }
+ else if ( rObj.GetType() == "drawing.Frame" )
+ {
+ break;
+ }
+ else if ( rObj.GetType() == "drawing.OLE2" )
+ {
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ if( rObj.IsEmptyPresObj() )
+ {
+ addShape( ESCHER_ShpInst_Rectangle, ShapeFlag::HaveMaster | ShapeFlag::HaveAnchor );
+ sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
+ rObj.GetShapeId() );
+ aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
+ aPropOpt.AddOpt( ESCHER_Prop_hspMaster, 0 );
+ }
+ else
+ {
+ //2do: could be made an option in HostAppData whether OLE object should be written or not
+ const bool bAppOLE = true;
+ addShape( ESCHER_ShpInst_PictureFrame,
+ ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor | (bAppOLE ? ShapeFlag::OLEShape : ShapeFlag::NONE) );
+ if ( aPropOpt.CreateOLEGraphicProperties( rObj.GetShapeRef() ) )
+ {
+ if ( bAppOLE )
+ { // snooped from Xcl hex dump, nobody knows the trouble I have seen
+ aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );
+ aPropOpt.AddOpt( ESCHER_Prop_pictureId, 0x00000001 );
+ aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x08000041 );
+ aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000041 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 );
+ aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash,0x00080008 );
+ aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 );
+ }
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
+ }
+ }
+ }
+ else if( '3' == rObj.GetType()[8] &&
+ 'D' == rObj.GetType()[9] ) // drawing.3D
+ {
+ // SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject
+ if ( !rObj.ImplGetPropertyValue( "Bitmap" ) )
+ break;
+
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_PictureFrame, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+
+ if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "Bitmap", false ) )
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
+ }
+ else if ( rObj.GetType() == "drawing.Caption" )
+ {
+ rObj.SetAngle( 0 );
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_TextBox, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", false ) )
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
+ }
+ else if ( rObj.GetType() == "drawing.dontknow" )
+ {
+ rObj.SetAngle( 0 );
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ addShape( ESCHER_ShpInst_PictureFrame, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", false ) )
+ aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
+ }
+ else
+ {
+ break;
+ }
+ aPropOpt.CreateShadowProperties( rObj.mXPropSet );
+
+ if( SDRLAYER_NOTFOUND != mpEscherEx->GetHellLayerId() &&
+ rObj.ImplGetPropertyValue( "LayerID" ) &&
+ *o3tl::doAccess<sal_Int16>(rObj.GetUsrAny()) == mpEscherEx->GetHellLayerId().get() )
+ {
+ aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
+ }
+
+ {
+ tools::Rectangle aRect( rObj.GetRect() );
+ aRect.Justify();
+ rObj.SetRect( aRect );
+ }
+
+ if( rObj.GetAngle() )
+ ImplFlipBoundingBox( rObj, aPropOpt );
+
+ aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
+ const SdrObject* sdrObj = rObj.GetSdrObject();
+ mpEscherEx->AddSdrObjectVMLObject(*sdrObj );
+ mpEscherEx->Commit( aPropOpt, rObj.GetRect());
+ if( mpEscherEx->GetGroupLevel() > 1 )
+ mpEscherEx->AddChildAnchor( rObj.GetRect() );
+
+ if ( mpHostAppData )
+ { //! with AdditionalText the App has to control whether these are written or not
+ mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
+ mpHostAppData->WriteClientData( *mpEscherEx );
+ if ( !bDontWriteText )
+ mpHostAppData->WriteClientTextbox( *mpEscherEx );
+ }
+ mpEscherEx->CloseContainer(); // ESCHER_SpContainer
+
+ if( bAdditionalText )
+ {
+ mpEscherEx->EndShape( nShapeType, nShapeID );
+ ImplWriteAdditionalText( rObj );
+ }
+
+ } while ( false );
+
+ if ( bAdditionalText )
+ mpEscherEx->EndShape( ESCHER_ShpInst_Min, nGrpShapeID );
+ else
+ mpEscherEx->EndShape( nShapeType, nShapeID );
+ return nShapeID;
+}
+
+void ImplEESdrWriter::ImplWriteAdditionalText( ImplEESdrObject& rObj )
+{
+ sal_uInt32 nShapeID = 0;
+ sal_uInt16 nShapeType = 0;
+ do
+ {
+ mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : nullptr );
+ if ( mpHostAppData && mpHostAppData->DontWriteShape() )
+ break;
+
+ const css::awt::Size aSize100thmm( rObj.GetShapeRef()->getSize() );
+ const css::awt::Point aPoint100thmm( rObj.GetShapeRef()->getPosition() );
+ tools::Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
+ if ( !mpPicStrm )
+ mpPicStrm = mpEscherEx->QueryPictureStream();
+ EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
+ rObj.SetAngle( rObj.ImplGetInt32PropertyValue( "RotateAngle" ));
+ sal_Int32 nAngle = rObj.GetAngle();
+ if( rObj.GetType() == "drawing.Line" )
+ {
+//2do: this does not work right
+ double fDist = hypot( rObj.GetRect().GetWidth(),
+ rObj.GetRect().GetHeight() );
+ rObj.SetRect( tools::Rectangle( Point(),
+ Point( static_cast<sal_Int32>( fDist ), -1 ) ) );
+
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ mpEscherEx->AddShape( ESCHER_ShpInst_TextBox, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor );
+ if ( rObj.ImplGetText() )
+ aPropOpt.CreateTextProperties( rObj.mXPropSet,
+ mpEscherEx->QueryTextID( rObj.GetShapeRef(),
+ rObj.GetShapeId() ) );
+
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
+ aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x60006 ); // Size Shape To Fit Text
+ if ( nAngle < 0 )
+ nAngle = ( 36000 + nAngle ) % 36000;
+ if ( nAngle )
+ ImplFlipBoundingBox( rObj, aPropOpt );
+ }
+ else
+ {
+ mpEscherEx->OpenContainer( ESCHER_SpContainer );
+ nShapeID = mpEscherEx->GenerateShapeId();
+ nShapeType = ESCHER_ShpInst_TextBox;
+ mpEscherEx->AddShape( nShapeType, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor, nShapeID );
+ if ( rObj.ImplGetText() )
+ aPropOpt.CreateTextProperties( rObj.mXPropSet,
+ mpEscherEx->QueryTextID( rObj.GetShapeRef(),
+ rObj.GetShapeId() ) );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
+
+ if( nAngle < 0 )
+ nAngle = ( 36000 + nAngle ) % 36000;
+ else
+ nAngle = ( 36000 - ( nAngle % 36000 ) );
+
+ nAngle *= 655;
+ nAngle += 0x8000;
+ nAngle &=~0xffff; // nAngle round to full degrees
+ aPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
+ mpEscherEx->SetGroupSnapRect( mpEscherEx->GetGroupLevel(),
+ rObj.GetRect() );
+ mpEscherEx->SetGroupLogicRect( mpEscherEx->GetGroupLevel(),
+ rObj.GetRect() );
+ }
+ rObj.SetAngle( nAngle );
+ aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
+ const SdrObject* sdrObj = rObj.GetSdrObject();
+ mpEscherEx->AddSdrObjectVMLObject(*sdrObj );
+ mpEscherEx->Commit( aPropOpt, rObj.GetRect());
+
+ // write the childanchor
+ mpEscherEx->AddChildAnchor( rObj.GetRect() );
+
+#if defined EES_WRITE_EPP
+ // ClientAnchor
+ mpEscherEx->AddClientAnchor( maRect );
+ // ClientTextbox
+ mpEscherEx->OpenContainer( ESCHER_ClientTextbox );
+ mpEscherEx->AddAtom( 4, EPP_TextHeaderAtom );
+ *mpStrm << (sal_uInt32)EPP_TEXTTYPE_Other; // Text in a Shape
+ ImplWriteTextStyleAtom();
+ mpEscherEx->CloseContainer(); // ESCHER_ClientTextBox
+#else // !EES_WRITE_EPP
+ if ( mpHostAppData )
+ { //! the App has to control whether these are written or not
+ mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
+ mpHostAppData->WriteClientData( *mpEscherEx );
+ mpHostAppData->WriteClientTextbox( *mpEscherEx );
+ }
+#endif // EES_WRITE_EPP
+ mpEscherEx->CloseContainer(); // ESCHER_SpContainer
+ } while ( false );
+ mpEscherEx->LeaveGroup();
+ mpEscherEx->EndShape( nShapeType, nShapeID );
+}
+
+
+sal_uInt32 ImplEESdrWriter::ImplEnterAdditionalTextGroup( const Reference< XShape >& rShape,
+ const tools::Rectangle* pBoundRect )
+{
+ mpHostAppData = mpEscherEx->EnterAdditionalTextGroup();
+ sal_uInt32 nGrpId = mpEscherEx->EnterGroup( pBoundRect );
+ mpHostAppData = mpEscherEx->StartShape( rShape, pBoundRect );
+ return nGrpId;
+}
+
+
+void ImplEESdrWriter::ImplInitPageValues()
+{
+ mbIsTitlePossible = true; // With more than one title PowerPoint will fail.
+}
+
+void ImplEESdrWriter::ImplWritePage(
+ EscherSolverContainer& rSolverContainer, bool ooxmlExport )
+{
+ ImplInitPageValues();
+
+ const sal_uInt32 nShapes = mXShapes->getCount();
+ for( sal_uInt32 n = 0; n < nShapes; ++n )
+ {
+ ImplEESdrObject aObj( *o3tl::doAccess<Reference<XShape>>(
+ mXShapes->getByIndex( n )) );
+ if( aObj.IsValid() )
+ {
+ ImplWriteShape( aObj, rSolverContainer, ooxmlExport );
+ }
+ }
+}
+
+ImplEESdrWriter::~ImplEESdrWriter()
+{
+ DBG_ASSERT( !mpSolverContainer, "ImplEESdrWriter::~ImplEESdrWriter: unwritten SolverContainer" );
+ Reference<css::lang::XComponent> xComp(mXDrawPage, UNO_QUERY);
+ if (xComp.is())
+ xComp->dispose();
+}
+
+
+bool ImplEESdrWriter::ImplInitPage( const SdrPage& rPage )
+{
+ rtl::Reference<SvxDrawPage> pSvxDrawPage;
+ if ( mpSdrPage != &rPage || !mXDrawPage.is() )
+ {
+ // eventually write SolverContainer of current page, deletes the Solver
+ ImplFlushSolverContainer();
+
+ mpSdrPage = nullptr;
+ Reference<css::lang::XComponent> xOldDrawPage(mXDrawPage, UNO_QUERY);
+ if (xOldDrawPage.is())
+ xOldDrawPage->dispose();
+ mXDrawPage = pSvxDrawPage = new SvxFmDrawPage( const_cast<SdrPage*>(&rPage) );
+ mXShapes = mXDrawPage;
+ if ( !mXShapes.is() )
+ return false;
+ ImplInitPageValues();
+ mpSdrPage = &rPage;
+
+ mpSolverContainer.reset( new EscherSolverContainer );
+ }
+ else
+ pSvxDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>(mXDrawPage);
+
+ return pSvxDrawPage != nullptr;
+}
+
+bool ImplEESdrWriter::ImplInitUnoShapes( const Reference< XShapes >& rxShapes )
+{
+ // eventually write SolverContainer of current page, deletes the Solver
+ ImplFlushSolverContainer();
+
+ if( !rxShapes.is() )
+ return false;
+
+ mpSdrPage = nullptr;
+ mXDrawPage.clear();
+ mXShapes = rxShapes;
+
+ ImplInitPageValues();
+
+ mpSolverContainer.reset( new EscherSolverContainer );
+ return true;
+}
+
+void ImplEESdrWriter::ImplExitPage()
+{
+ // close all groups before the solver container is written
+ while( mpEscherEx->GetGroupLevel() )
+ mpEscherEx->LeaveGroup();
+
+ ImplFlushSolverContainer();
+ mpSdrPage = nullptr; // reset page for next init
+}
+
+
+void ImplEESdrWriter::ImplFlushSolverContainer()
+{
+ if ( mpSolverContainer )
+ {
+ mpSolverContainer->WriteSolver( mpEscherEx->GetStream() );
+ mpSolverContainer.reset();
+ }
+}
+
+void ImplEESdrWriter::ImplWriteCurrentPage(bool ooxmlExport)
+{
+ assert(mpSolverContainer && "ImplEESdrWriter::ImplWriteCurrentPage: no SolverContainer");
+ ImplWritePage( *mpSolverContainer, ooxmlExport );
+ ImplExitPage();
+}
+
+sal_uInt32 ImplEESdrWriter::ImplWriteTheShape( ImplEESdrObject& rObj , bool ooxmlExport )
+{
+ assert(mpSolverContainer && "ImplEESdrWriter::ImplWriteShape: no SolverContainer");
+ return ImplWriteShape( rObj, *mpSolverContainer, ooxmlExport );
+}
+
+void EscherEx::AddSdrPage( const SdrPage& rPage, bool ooxmlExport )
+{
+ if ( mpImplEESdrWriter->ImplInitPage( rPage ) )
+ mpImplEESdrWriter->ImplWriteCurrentPage(ooxmlExport);
+}
+
+void EscherEx::AddUnoShapes( const Reference< XShapes >& rxShapes, bool ooxmlExport )
+{
+ if ( mpImplEESdrWriter->ImplInitUnoShapes( rxShapes ) )
+ mpImplEESdrWriter->ImplWriteCurrentPage(ooxmlExport);
+}
+
+sal_uInt32 EscherEx::AddSdrObject( const SdrObject& rObj, bool ooxmlExport )
+{
+ ImplEESdrObject aObj( *mpImplEESdrWriter, rObj, mbOOXML );
+ if( aObj.IsValid() )
+ return mpImplEESdrWriter->ImplWriteTheShape( aObj, ooxmlExport );
+ return 0;
+}
+
+
+void EscherEx::EndSdrObjectPage()
+{
+ mpImplEESdrWriter->ImplExitPage();
+}
+
+EscherExHostAppData* EscherEx::StartShape( const Reference< XShape >& /* rShape */, const tools::Rectangle* /*pChildAnchor*/ )
+{
+ return nullptr;
+}
+
+void EscherEx::EndShape( sal_uInt16 /* nShapeType */, sal_uInt32 /* nShapeID */ )
+{
+}
+
+sal_uInt32 EscherEx::QueryTextID( const Reference< XShape >&, sal_uInt32 )
+{
+ return 0;
+}
+
+// add a dummy rectangle shape into the escher stream
+sal_uInt32 EscherEx::AddDummyShape()
+{
+ OpenContainer( ESCHER_SpContainer );
+ sal_uInt32 nShapeID = GenerateShapeId();
+ AddShape( ESCHER_ShpInst_Rectangle, ShapeFlag::HaveShapeProperty | ShapeFlag::HaveAnchor, nShapeID );
+ CloseContainer();
+
+ return nShapeID;
+}
+
+// static
+const SdrObject* EscherEx::GetSdrObject( const Reference< XShape >& rShape )
+{
+ const SdrObject* pRet = SdrObject::getSdrObjectFromXShape( rShape );
+ DBG_ASSERT( pRet, "EscherEx::GetSdrObject: no SdrObj" );
+ return pRet;
+}
+
+
+ImplEESdrObject::ImplEESdrObject( ImplEESdrWriter& rEx,
+ const SdrObject& rObj, bool bOOXML ) :
+ mnShapeId( 0 ),
+ mnTextSize( 0 ),
+ mnAngle( 0 ),
+ mbValid( false ),
+ mbPresObj( false ),
+ mbEmptyPresObj( false ),
+ mbOOXML(bOOXML)
+{
+ SdrPage* pPage = rObj.getSdrPageFromSdrObject();
+ DBG_ASSERT( pPage, "ImplEESdrObject::ImplEESdrObject: no SdrPage" );
+ if( pPage && rEx.ImplInitPage( *pPage ) )
+ {
+ // why not declare a const parameter if the object will
+ // not be modified?
+ mXShape.set( const_cast<SdrObject*>(&rObj)->getUnoShape(), UNO_QUERY );
+ Init();
+ }
+}
+
+ImplEESdrObject::ImplEESdrObject( const Reference< XShape >& rShape ) :
+ mXShape( rShape ),
+ mnShapeId( 0 ),
+ mnTextSize( 0 ),
+ mnAngle( 0 ),
+ mbValid( false ),
+ mbPresObj( false ),
+ mbEmptyPresObj( false ),
+ mbOOXML(false)
+{
+ Init();
+}
+
+
+ImplEESdrObject::~ImplEESdrObject()
+{
+}
+
+static basegfx::B2DRange getUnrotatedGroupBoundRange(const Reference< XShape >& rxShape)
+{
+ basegfx::B2DRange aRetval;
+
+ try
+ {
+ if(rxShape.is())
+ {
+ if(rxShape->getShapeType() == "com.sun.star.drawing.GroupShape")
+ {
+ // it's a group shape, iterate over children
+ const Reference< XIndexAccess > xXIndexAccess(rxShape, UNO_QUERY);
+
+ if(xXIndexAccess.is())
+ {
+ for(sal_uInt32 n(0), nCnt = xXIndexAccess->getCount(); n < nCnt; ++n)
+ {
+ const Reference< XShape > axShape(xXIndexAccess->getByIndex(n), UNO_QUERY);
+
+ if(axShape.is())
+ {
+ // we are calculating the bound for a group, correct rotation for sub-objects
+ // to get the unrotated bounds for the group
+ const basegfx::B2DRange aExtend(getUnrotatedGroupBoundRange(axShape));
+
+ aRetval.expand(aExtend);
+ }
+ }
+ }
+ }
+ else
+ {
+ // iT#s a xShape, get its transformation
+ const Reference< XPropertySet > xPropSet(rxShape, UNO_QUERY);
+
+ if(xPropSet.is())
+ {
+ const Any aAny = xPropSet->getPropertyValue("Transformation");
+
+ if(aAny.hasValue())
+ {
+ HomogenMatrix3 aMatrix;
+
+ if(aAny >>= aMatrix)
+ {
+ basegfx::B2DHomMatrix aHomogenMatrix;
+
+ aHomogenMatrix.set(0, 0, aMatrix.Line1.Column1);
+ aHomogenMatrix.set(0, 1, aMatrix.Line1.Column2);
+ aHomogenMatrix.set(0, 2, aMatrix.Line1.Column3);
+ aHomogenMatrix.set(1, 0, aMatrix.Line2.Column1);
+ aHomogenMatrix.set(1, 1, aMatrix.Line2.Column2);
+ aHomogenMatrix.set(1, 2, aMatrix.Line2.Column3);
+ aHomogenMatrix.set(2, 0, aMatrix.Line3.Column1);
+ aHomogenMatrix.set(2, 1, aMatrix.Line3.Column2);
+ aHomogenMatrix.set(2, 2, aMatrix.Line3.Column3);
+
+ basegfx::B2DVector aScale, aTranslate;
+ double fRotate, fShearX;
+
+ // decompose transformation
+ aHomogenMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
+
+ // check if rotation needs to be corrected
+ if(!basegfx::fTools::equalZero(fRotate))
+ {
+ // to correct, keep in mind that ppt graphics are rotated around their center
+ const basegfx::B2DPoint aCenter(aHomogenMatrix * basegfx::B2DPoint(0.5, 0.5));
+
+ aHomogenMatrix.translate(-aCenter.getX(), -aCenter.getY());
+ aHomogenMatrix.rotate(-fRotate);
+ aHomogenMatrix.translate(aCenter.getX(), aCenter.getY());
+ }
+
+
+ // check if shear needs to be corrected (always correct shear,
+ // ppt does not know about it)
+ if(!basegfx::fTools::equalZero(fShearX))
+ {
+ const basegfx::B2DPoint aMinimum(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
+
+ aHomogenMatrix.translate(-aMinimum.getX(), -aMinimum.getY());
+ aHomogenMatrix.shearX(-fShearX);
+ aHomogenMatrix.translate(aMinimum.getX(), aMinimum.getY());
+ }
+
+ // create range. It's no longer rotated (or sheared), so use
+ // minimum and maximum values
+ aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
+ aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(1.0, 1.0));
+ }
+ }
+ }
+ }
+ }
+ }
+ catch(css::uno::Exception&)
+ {
+ }
+
+ return aRetval;
+}
+
+void ImplEESdrObject::Init()
+{
+ mXPropSet.set( mXShape, UNO_QUERY );
+ if( !mXPropSet.is() )
+ return;
+
+ // detect name first to make below test (is group) work
+ mType = mXShape->getShapeType();
+ (void)mType.startsWith( "com.sun.star.", &mType ); // strip "com.sun.star."
+ (void)mType.endsWith( "Shape", &mType ); // strip "Shape"
+
+ if(GetType() == "drawing.Group")
+ {
+ // if it's a group, the unrotated range is needed for that group
+ const basegfx::B2DRange aUnrotatedRange(getUnrotatedGroupBoundRange(mXShape));
+ const Point aNewP(basegfx::fround(aUnrotatedRange.getMinX()), basegfx::fround(aUnrotatedRange.getMinY()));
+ const Size aNewS(basegfx::fround(aUnrotatedRange.getWidth()), basegfx::fround(aUnrotatedRange.getHeight()));
+
+ SetRect(ImplEESdrWriter::ImplMapPoint(aNewP), ImplEESdrWriter::ImplMapSize(aNewS));
+ }
+ else
+ {
+ // if it's no group, use position and size directly, rotated/sheared or not
+ const Point aOldP(mXShape->getPosition().X, mXShape->getPosition().Y);
+ const Size aOldS(mXShape->getSize().Width, mXShape->getSize().Height);
+
+ SetRect(ImplEESdrWriter::ImplMapPoint(aOldP), ImplEESdrWriter::ImplMapSize(aOldS));
+ }
+
+ if( ImplGetPropertyValue( "IsPresentationObject" ) )
+ mbPresObj = ::cppu::any2bool( mAny );
+
+ if( mbPresObj && ImplGetPropertyValue( "IsEmptyPresentationObject" ) )
+ mbEmptyPresObj = ::cppu::any2bool( mAny );
+
+ mbValid = true;
+}
+
+bool ImplEESdrObject::ImplGetPropertyValue( const OUString& rString )
+{
+ bool bRetValue = false;
+ if( mbValid )
+ {
+ try
+ {
+ mAny = mXPropSet->getPropertyValue( rString );
+ if( mAny.hasValue() )
+ bRetValue = true;
+ }
+ catch( const css::uno::Exception& )
+ {
+ bRetValue = false;
+ }
+ }
+ return bRetValue;
+}
+
+void ImplEESdrObject::SetRect( const Point& rPos, const Size& rSz )
+{
+ maRect = tools::Rectangle( rPos, rSz );
+}
+
+const SdrObject* ImplEESdrObject::GetSdrObject() const
+{
+ return EscherEx::GetSdrObject( mXShape );
+}
+
+// loads and converts text from shape, result is saved in mnTextSize
+sal_uInt32 ImplEESdrObject::ImplGetText()
+{
+ Reference< XText > xXText( mXShape, UNO_QUERY );
+ mnTextSize = 0;
+ if (xXText.is())
+ {
+ try
+ {
+ mnTextSize = xXText->getString().getLength();
+ }
+ catch (const uno::RuntimeException&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.ms", "ImplGetText");
+ }
+ }
+ return mnTextSize;
+}
+
+bool ImplEESdrObject::ImplHasText() const
+{
+ Reference< XText > xXText( mXShape, UNO_QUERY );
+ return xXText.is() && !xXText->getString().isEmpty();
+}
+
+
+void ImplEESdrObject::SetOOXML(bool bOOXML)
+{
+ mbOOXML = bOOXML;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/eschesdo.hxx b/filter/source/msfilter/eschesdo.hxx
new file mode 100644
index 000000000..cf46f49b6
--- /dev/null
+++ b/filter/source/msfilter/eschesdo.hxx
@@ -0,0 +1,138 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+#include <filter/msfilter/escherex.hxx>
+#include <o3tl/any.hxx>
+
+
+// fractions of Draw PPTWriter etc.
+
+class ImplEESdrWriter;
+class SdrObject;
+class SdrPage;
+
+class ImplEESdrObject
+{
+ css::uno::Reference< css::drawing::XShape > mXShape;
+ css::uno::Any mAny;
+ tools::Rectangle maRect;
+ OUString mType;
+ sal_uInt32 mnShapeId;
+ sal_uInt32 mnTextSize;
+ sal_Int32 mnAngle;
+ bool mbValid : 1;
+ bool mbPresObj : 1;
+ bool mbEmptyPresObj : 1;
+ bool mbOOXML;
+
+ void Init();
+public:
+ css::uno::Reference< css::beans::XPropertySet > mXPropSet;
+
+ ImplEESdrObject( ImplEESdrWriter& rEx, const SdrObject& rObj, bool bOOXML );
+ ImplEESdrObject( const css::uno::Reference< css::drawing::XShape >& rShape );
+ ~ImplEESdrObject();
+
+ bool ImplGetPropertyValue( const OUString& rString );
+
+ sal_Int32 ImplGetInt32PropertyValue( const OUString& rStr )
+ { return ImplGetPropertyValue( rStr ) ? *o3tl::doAccess<sal_Int32>(mAny) : 0; }
+
+ const css::uno::Reference< css::drawing::XShape >& GetShapeRef() const { return mXShape; }
+ const css::uno::Any& GetUsrAny() const { return mAny; }
+ const OUString& GetType() const { return mType; }
+ void SetType( const OUString& rS ) { mType = rS; }
+
+ const tools::Rectangle& GetRect() const { return maRect; }
+ void SetRect( const Point& rPos, const Size& rSz );
+ void SetRect( const tools::Rectangle& rRect )
+ { maRect = rRect; }
+
+ sal_Int32 GetAngle() const { return mnAngle; }
+ void SetAngle( sal_Int32 nVal ) { mnAngle = nVal; }
+
+ bool IsValid() const { return mbValid; }
+
+ bool IsEmptyPresObj() const { return mbEmptyPresObj; }
+ sal_uInt32 GetShapeId() const { return mnShapeId; }
+ void SetShapeId( sal_uInt32 nVal ) { mnShapeId = nVal; }
+
+ const SdrObject* GetSdrObject() const;
+
+ sal_uInt32 ImplGetText();
+ bool ImplHasText() const;
+ bool GetOOXML() const { return mbOOXML;}
+ void SetOOXML(bool bOOXML);
+};
+
+
+// fractions of the Draw PPTWriter
+
+class EscherEx;
+namespace com::sun::star {
+ namespace drawing {
+ class XDrawPage;
+ class XShape;
+ }
+ namespace task {
+ class XStatusIndicator;
+ }
+}
+class EscherExHostAppData;
+
+class ImplEESdrWriter
+{
+ EscherEx* mpEscherEx;
+ css::uno::Reference< css::drawing::XDrawPage > mXDrawPage;
+ css::uno::Reference< css::drawing::XShapes > mXShapes;
+ SvStream* mpPicStrm;
+ // own extensions
+ EscherExHostAppData* mpHostAppData;
+ bool mbIsTitlePossible;
+ const SdrPage* mpSdrPage;
+ std::unique_ptr<EscherSolverContainer> mpSolverContainer;
+
+ void ImplInitPageValues();
+ void ImplWritePage( EscherSolverContainer& rSolver, bool ooxmlExport );
+ sal_uInt32 ImplWriteShape( ImplEESdrObject& rObj,
+ EscherSolverContainer& rSolver,
+ const bool bOOxmlExport = false ); // returns ShapeID
+ static void ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt );
+ void ImplWriteAdditionalText(
+ ImplEESdrObject& rObj );
+ sal_uInt32 ImplEnterAdditionalTextGroup(
+ const css::uno::Reference< css::drawing::XShape >& rShape,
+ const tools::Rectangle* pBoundRect );
+ void ImplFlushSolverContainer();
+
+public:
+ explicit ImplEESdrWriter( EscherEx& rEx );
+ ~ImplEESdrWriter();
+ static Point ImplMapPoint( const Point& rPoint );
+ static Size ImplMapSize( const Size& rSize );
+ EscherExHostAppData* ImplGetHostData() { return mpHostAppData; }
+ bool ImplInitPage( const SdrPage& rPage );
+ bool ImplInitUnoShapes( const css::uno::Reference< css::drawing::XShapes >& rxShapes );
+ void ImplWriteCurrentPage( bool ooxmlExport );
+ sal_uInt32 ImplWriteTheShape( ImplEESdrObject& rObj, bool ooxmlExport );
+ void ImplExitPage();
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/mscodec.cxx b/filter/source/msfilter/mscodec.cxx
new file mode 100644
index 000000000..376a45320
--- /dev/null
+++ b/filter/source/msfilter/mscodec.cxx
@@ -0,0 +1,642 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <filter/msfilter/mscodec.hxx>
+
+#include <osl/diagnose.h>
+#include <algorithm>
+#include <string.h>
+#include <tools/solar.h>
+
+#include <comphelper/hash.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <comphelper/docpasswordhelper.hxx>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <utility>
+
+#define DEBUG_MSO_ENCRYPTION_STD97 0
+
+#if DEBUG_MSO_ENCRYPTION_STD97
+#include <stdio.h>
+#endif
+
+using namespace ::com::sun::star;
+
+namespace msfilter {
+
+
+namespace {
+
+/** Rotates rnValue left by nBits bits. */
+template< typename Type >
+void lclRotateLeft( Type& rnValue, int nBits )
+{
+ OSL_ASSERT(
+ nBits >= 0 &&
+ sal::static_int_cast< unsigned int >(nBits) < sizeof( Type ) * 8 );
+ rnValue = static_cast< Type >( (rnValue << nBits) | (rnValue >> (sizeof( Type ) * 8 - nBits)) );
+}
+
+/** Rotates the lower nWidth bits of rnValue left by nBits bits. */
+template< typename Type >
+void lclRotateLeft( Type& rnValue, sal_uInt8 nBits, sal_uInt8 nWidth )
+{
+ OSL_ASSERT( (nBits < nWidth) && (nWidth < sizeof( Type ) * 8) );
+ Type nMask = static_cast< Type >( (1UL << nWidth) - 1 );
+ rnValue = static_cast< Type >(
+ ((rnValue << nBits) | ((rnValue & nMask) >> (nWidth - nBits))) & nMask );
+}
+
+std::size_t lclGetLen( const sal_uInt8* pnPassData, std::size_t nBufferSize )
+{
+ std::size_t nLen = 0;
+ while( (nLen < nBufferSize) && pnPassData[ nLen ] ) ++nLen;
+ return nLen;
+}
+
+sal_uInt16 lclGetKey( const sal_uInt8* pnPassData, std::size_t nBufferSize )
+{
+ std::size_t nLen = lclGetLen( pnPassData, nBufferSize );
+ if( !nLen ) return 0;
+
+ sal_uInt16 nKey = 0;
+ sal_uInt16 nKeyBase = 0x8000;
+ sal_uInt16 nKeyEnd = 0xFFFF;
+ const sal_uInt8* pnChar = pnPassData + nLen - 1;
+ for( std::size_t nIndex = 0; nIndex < nLen; ++nIndex, --pnChar )
+ {
+ sal_uInt8 cChar = *pnChar & 0x7F;
+ for( sal_uInt8 nBit = 0; nBit < 8; ++nBit )
+ {
+ lclRotateLeft( nKeyBase, 1 );
+ if( nKeyBase & 1 ) nKeyBase ^= 0x1020;
+ if( cChar & 1 ) nKey ^= nKeyBase;
+ cChar >>= 1;
+ lclRotateLeft( nKeyEnd, 1 );
+ if( nKeyEnd & 1 ) nKeyEnd ^= 0x1020;
+ }
+ }
+ return nKey ^ nKeyEnd;
+}
+
+sal_uInt16 lclGetHash( const sal_uInt8* pnPassData, std::size_t nBufferSize )
+{
+ std::size_t nLen = lclGetLen( pnPassData, nBufferSize );
+
+ sal_uInt16 nHash = static_cast< sal_uInt16 >( nLen );
+ if( nLen )
+ nHash ^= 0xCE4B;
+
+ const sal_uInt8* pnChar = pnPassData;
+ for( std::size_t nIndex = 0; nIndex < nLen; ++nIndex, ++pnChar )
+ {
+ sal_uInt16 cChar = *pnChar;
+ sal_uInt8 nRot = static_cast< sal_uInt8 >( (nIndex + 1) % 15 );
+ lclRotateLeft( cChar, nRot, 15 );
+ nHash ^= cChar;
+ }
+ return nHash;
+}
+
+
+} // namespace
+
+
+MSCodec_Xor95::MSCodec_Xor95(int nRotateDistance) :
+ mnOffset( 0 ),
+ mnKey( 0 ),
+ mnHash( 0 ),
+ mnRotateDistance( nRotateDistance )
+{
+}
+
+MSCodec_Xor95::~MSCodec_Xor95()
+{
+ memset( mpnKey, 0, sizeof( mpnKey ) );
+ mnKey = mnHash = 0;
+}
+
+void MSCodec_Xor95::InitKey( const sal_uInt8 pnPassData[ 16 ] )
+{
+ mnKey = lclGetKey( pnPassData, 16 );
+ mnHash = lclGetHash( pnPassData, 16 );
+
+ memcpy( mpnKey, pnPassData, 16 );
+
+ static const sal_uInt8 spnFillChars[] =
+ {
+ 0xBB, 0xFF, 0xFF, 0xBA,
+ 0xFF, 0xFF, 0xB9, 0x80,
+ 0x00, 0xBE, 0x0F, 0x00,
+ 0xBF, 0x0F, 0x00, 0x00
+ };
+
+ std::size_t nLen = lclGetLen( pnPassData, 16 );
+ const sal_uInt8* pnFillChar = spnFillChars;
+ for (std::size_t nIndex = nLen; nIndex < sizeof(mpnKey); ++nIndex, ++pnFillChar)
+ mpnKey[ nIndex ] = *pnFillChar;
+
+ SVBT16 pnOrigKey;
+ ShortToSVBT16( mnKey, pnOrigKey );
+ sal_uInt8* pnKeyChar = mpnKey;
+ for (std::size_t nIndex = 0; nIndex < sizeof(mpnKey); ++nIndex, ++pnKeyChar)
+ {
+ *pnKeyChar ^= pnOrigKey[ nIndex & 0x01 ];
+ lclRotateLeft( *pnKeyChar, mnRotateDistance );
+ }
+}
+
+bool MSCodec_Xor95::InitCodec( const uno::Sequence< beans::NamedValue >& aData )
+{
+ bool bResult = false;
+
+ ::comphelper::SequenceAsHashMap aHashData( aData );
+ uno::Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault("XOR95EncryptionKey", uno::Sequence< sal_Int8 >() );
+
+ if ( aKey.getLength() == 16 )
+ {
+ memcpy( mpnKey, aKey.getConstArray(), 16 );
+ bResult = true;
+
+ mnKey = static_cast<sal_uInt16>(aHashData.getUnpackedValueOrDefault("XOR95BaseKey", sal_Int16(0) ));
+ mnHash = static_cast<sal_uInt16>(aHashData.getUnpackedValueOrDefault("XOR95PasswordHash", sal_Int16(0) ));
+ }
+ else
+ OSL_FAIL( "Unexpected key size!" );
+
+ return bResult;
+}
+
+uno::Sequence< beans::NamedValue > MSCodec_Xor95::GetEncryptionData()
+{
+ ::comphelper::SequenceAsHashMap aHashData;
+ // coverity[overrun-buffer-arg : FALSE] - coverity has difficulty with css::uno::Sequence
+ aHashData[ OUString( "XOR95EncryptionKey" ) ] <<= uno::Sequence<sal_Int8>( reinterpret_cast<sal_Int8*>(mpnKey), 16 );
+ aHashData[ OUString( "XOR95BaseKey" ) ] <<= static_cast<sal_Int16>(mnKey);
+ aHashData[ OUString( "XOR95PasswordHash" ) ] <<= static_cast<sal_Int16>(mnHash);
+
+ return aHashData.getAsConstNamedValueList();
+}
+
+bool MSCodec_Xor95::VerifyKey( sal_uInt16 nKey, sal_uInt16 nHash ) const
+{
+ return (nKey == mnKey) && (nHash == mnHash);
+}
+
+void MSCodec_Xor95::InitCipher()
+{
+ mnOffset = 0;
+}
+
+void MSCodec_XorXLS95::Decode( sal_uInt8* pnData, std::size_t nBytes )
+{
+ const sal_uInt8* pnCurrKey = mpnKey + mnOffset;
+ const sal_uInt8* pnKeyLast = mpnKey + 0x0F;
+
+ for( const sal_uInt8* pnDataEnd = pnData + nBytes; pnData < pnDataEnd; ++pnData )
+ {
+ lclRotateLeft( *pnData, 3 );
+ *pnData ^= *pnCurrKey;
+ if( pnCurrKey < pnKeyLast ) ++pnCurrKey; else pnCurrKey = mpnKey;
+ }
+
+ // update mnOffset
+ Skip( nBytes );
+}
+
+void MSCodec_XorWord95::Decode( sal_uInt8* pnData, std::size_t nBytes )
+{
+ const sal_uInt8* pnCurrKey = mpnKey + mnOffset;
+ const sal_uInt8* pnKeyLast = mpnKey + 0x0F;
+
+ for( const sal_uInt8* pnDataEnd = pnData + nBytes; pnData < pnDataEnd; ++pnData )
+ {
+ const sal_uInt8 cChar = *pnData ^ *pnCurrKey;
+ if (*pnData && cChar)
+ *pnData = cChar;
+
+ if( pnCurrKey < pnKeyLast )
+ ++pnCurrKey;
+ else
+ pnCurrKey = mpnKey;
+ }
+
+ // update mnOffset
+ Skip( nBytes );
+}
+
+
+void MSCodec_Xor95::Skip( std::size_t nBytes )
+{
+ mnOffset = (mnOffset + nBytes) & 0x0F;
+}
+
+MSCodec97::MSCodec97(size_t nHashLen, OUString aEncKeyName)
+ : m_sEncKeyName(std::move(aEncKeyName))
+ , m_nHashLen(nHashLen)
+ , m_hCipher(rtl_cipher_create(rtl_Cipher_AlgorithmARCFOUR, rtl_Cipher_ModeStream))
+ , m_aDocId(16, 0)
+ , m_aDigestValue(nHashLen, 0)
+{
+ assert(m_hCipher != nullptr);
+}
+
+MSCodec_Std97::MSCodec_Std97()
+ : MSCodec97(RTL_DIGEST_LENGTH_MD5, "STD97EncryptionKey")
+{
+ m_hDigest = rtl_digest_create(rtl_Digest_AlgorithmMD5);
+ assert(m_hDigest != nullptr);
+}
+
+MSCodec_CryptoAPI::MSCodec_CryptoAPI()
+ : MSCodec97(RTL_DIGEST_LENGTH_SHA1, "CryptoAPIEncryptionKey")
+{
+}
+
+MSCodec97::~MSCodec97()
+{
+ memset(m_aDigestValue.data(), 0, m_aDigestValue.size());
+ memset(m_aDocId.data(), 0, m_aDocId.size());
+ rtl_cipher_destroy(m_hCipher);
+}
+
+MSCodec_Std97::~MSCodec_Std97()
+{
+ rtl_digest_destroy(m_hDigest);
+}
+
+#if DEBUG_MSO_ENCRYPTION_STD97
+static void lcl_PrintDigest(const sal_uInt8* pDigest, const char* msg)
+{
+ printf("digest: (%s)\n", msg);
+ for (int i = 0; i < 16; ++i)
+ printf("%2.2x ", pDigest[i]);
+ printf("\n");
+}
+#else
+static void lcl_PrintDigest(const sal_uInt8* /*pDigest*/, const char* /*msg*/)
+{
+}
+#endif
+
+bool MSCodec97::InitCodec( const uno::Sequence< beans::NamedValue >& aData )
+{
+#if DEBUG_MSO_ENCRYPTION_STD97
+ fprintf(stdout, "MSCodec_Std97::InitCodec: --begin\n");fflush(stdout);
+#endif
+ bool bResult = false;
+
+ ::comphelper::SequenceAsHashMap aHashData( aData );
+ uno::Sequence<sal_Int8> aKey = aHashData.getUnpackedValueOrDefault(m_sEncKeyName, uno::Sequence<sal_Int8>());
+ const size_t nKeyLen = aKey.getLength();
+ if (nKeyLen == m_nHashLen)
+ {
+ assert(m_aDigestValue.size() == m_nHashLen);
+ memcpy(m_aDigestValue.data(), aKey.getConstArray(), m_nHashLen);
+ uno::Sequence< sal_Int8 > aUniqueID = aHashData.getUnpackedValueOrDefault("STD97UniqueID", uno::Sequence< sal_Int8 >() );
+ if ( aUniqueID.getLength() == 16 )
+ {
+ assert(m_aDocId.size() == static_cast<size_t>(aUniqueID.getLength()));
+ memcpy(m_aDocId.data(), aUniqueID.getConstArray(), m_aDocId.size());
+ bResult = true;
+ lcl_PrintDigest(m_aDigestValue.data(), "digest value");
+ lcl_PrintDigest(m_aDocId.data(), "DocId value");
+ }
+ else
+ OSL_FAIL( "Unexpected document ID!" );
+ }
+ else
+ OSL_FAIL( "Unexpected key size!" );
+
+ return bResult;
+}
+
+uno::Sequence< beans::NamedValue > MSCodec97::GetEncryptionData()
+{
+ ::comphelper::SequenceAsHashMap aHashData;
+ assert(m_aDigestValue.size() == m_nHashLen);
+ aHashData[m_sEncKeyName] <<= uno::Sequence<sal_Int8>(reinterpret_cast<sal_Int8*>(m_aDigestValue.data()), m_nHashLen);
+ aHashData[ OUString( "STD97UniqueID" ) ] <<= uno::Sequence< sal_Int8 >( reinterpret_cast<sal_Int8*>(m_aDocId.data()), m_aDocId.size() );
+
+ return aHashData.getAsConstNamedValueList();
+}
+
+void MSCodec_Std97::InitKey (
+ const sal_uInt16 pPassData[16],
+ const sal_uInt8 pDocId[16])
+{
+#if DEBUG_MSO_ENCRYPTION_STD97
+ fprintf(stdout, "MSCodec_Std97::InitKey: --begin\n");fflush(stdout);
+#endif
+ uno::Sequence< sal_Int8 > aKey = ::comphelper::DocPasswordHelper::GenerateStd97Key(pPassData, pDocId);
+ // Fill raw digest of above updates into DigestValue.
+
+ const size_t nKeyLen = aKey.getLength();
+ if (m_aDigestValue.size() == nKeyLen)
+ memcpy(m_aDigestValue.data(), aKey.getConstArray(), m_aDigestValue.size());
+ else
+ memset(m_aDigestValue.data(), 0, m_aDigestValue.size());
+
+ lcl_PrintDigest(m_aDigestValue.data(), "digest value");
+
+ memcpy (m_aDocId.data(), pDocId, 16);
+
+ lcl_PrintDigest(m_aDocId.data(), "DocId value");
+}
+
+void MSCodec_CryptoAPI::InitKey (
+ const sal_uInt16 pPassData[16],
+ const sal_uInt8 pDocId[16])
+{
+ sal_uInt32 const saltSize = 16;
+
+ // Prepare initial data -> salt + password (in 16-bit chars)
+ std::vector<sal_uInt8> initialData(pDocId, pDocId + saltSize);
+
+ // Fill PassData into KeyData.
+ for (sal_Int32 nInd = 0; nInd < 16 && pPassData[nInd]; ++nInd)
+ {
+ initialData.push_back(sal::static_int_cast<sal_uInt8>((pPassData[nInd] >> 0) & 0xff));
+ initialData.push_back(sal::static_int_cast<sal_uInt8>((pPassData[nInd] >> 8) & 0xff));
+ }
+
+ // calculate SHA1 hash of initialData
+ std::vector<unsigned char> const sha1(::comphelper::Hash::calculateHash(
+ initialData.data(), initialData.size(),
+ ::comphelper::HashType::SHA1));
+ m_aDigestValue = sha1;
+
+ lcl_PrintDigest(m_aDigestValue.data(), "digest value");
+
+ memcpy(m_aDocId.data(), pDocId, 16);
+
+ lcl_PrintDigest(m_aDocId.data(), "DocId value");
+
+ //generate the old format key while we have the required data
+ m_aStd97Key = ::comphelper::DocPasswordHelper::GenerateStd97Key(pPassData, pDocId);
+}
+
+bool MSCodec97::VerifyKey(const sal_uInt8* pSaltData, const sal_uInt8* pSaltDigest)
+{
+ // both the salt data and salt digest (hash) come from the document being imported.
+
+#if DEBUG_MSO_ENCRYPTION_STD97
+ fprintf(stdout, "MSCodec97::VerifyKey: \n");
+ lcl_PrintDigest(pSaltData, "salt data");
+ lcl_PrintDigest(pSaltDigest, "salt hash");
+#endif
+ bool result = false;
+
+ if (InitCipher(0))
+ {
+ std::vector<sal_uInt8> aDigest(m_nHashLen);
+ GetDigestFromSalt(pSaltData, aDigest.data());
+
+ std::vector<sal_uInt8> aBuffer(m_nHashLen);
+ // Decode original SaltDigest into Buffer.
+ rtl_cipher_decode(m_hCipher, pSaltDigest, m_nHashLen, aBuffer.data(), m_nHashLen);
+
+ // Compare Buffer with computed Digest.
+ result = (memcmp(aBuffer.data(), aDigest.data(), m_nHashLen) == 0);
+
+ // Erase Buffer and Digest arrays.
+ rtl_secureZeroMemory(aBuffer.data(), m_nHashLen);
+ rtl_secureZeroMemory(aDigest.data(), m_nHashLen);
+ }
+
+ return result;
+}
+
+void MSCodec_CryptoAPI::GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest)
+{
+ std::vector<sal_uInt8> verifier(16);
+ rtl_cipher_decode(m_hCipher,
+ pSaltData, 16, verifier.data(), verifier.size());
+
+ std::vector<unsigned char> const sha1(::comphelper::Hash::calculateHash(
+ verifier.data(), verifier.size(), ::comphelper::HashType::SHA1));
+ ::std::copy(sha1.begin(), sha1.end(), pDigest);
+}
+
+bool MSCodec_Std97::InitCipher(sal_uInt32 nCounter)
+{
+ sal_uInt8 pKeyData[64] = {}; // 512-bit message block
+
+ // Fill 40 bit of DigestValue into [0..4].
+ memcpy (pKeyData, m_aDigestValue.data(), 5);
+
+ // Fill counter into [5..8].
+ pKeyData[ 5] = sal_uInt8((nCounter >> 0) & 0xff);
+ pKeyData[ 6] = sal_uInt8((nCounter >> 8) & 0xff);
+ pKeyData[ 7] = sal_uInt8((nCounter >> 16) & 0xff);
+ pKeyData[ 8] = sal_uInt8((nCounter >> 24) & 0xff);
+
+ pKeyData[ 9] = 0x80;
+ pKeyData[56] = 0x48;
+
+ // Fill raw digest of KeyData into KeyData.
+ (void)rtl_digest_updateMD5 (
+ m_hDigest, pKeyData, sizeof(pKeyData));
+ (void)rtl_digest_rawMD5 (
+ m_hDigest, pKeyData, RTL_DIGEST_LENGTH_MD5);
+
+ // Initialize Cipher with KeyData (for decoding).
+ rtlCipherError result = rtl_cipher_init (
+ m_hCipher, rtl_Cipher_DirectionBoth,
+ pKeyData, RTL_DIGEST_LENGTH_MD5, nullptr, 0);
+
+ // Erase KeyData array and leave.
+ rtl_secureZeroMemory (pKeyData, sizeof(pKeyData));
+
+ return (result == rtl_Cipher_E_None);
+}
+
+bool MSCodec_CryptoAPI::InitCipher(sal_uInt32 nCounter)
+{
+ // data = hash + iterator (4bytes)
+ std::vector<sal_uInt8> aKeyData(m_aDigestValue);
+ aKeyData.push_back(sal_uInt8((nCounter >> 0) & 0xff));
+ aKeyData.push_back(sal_uInt8((nCounter >> 8) & 0xff));
+ aKeyData.push_back(sal_uInt8((nCounter >> 16) & 0xff));
+ aKeyData.push_back(sal_uInt8((nCounter >> 24) & 0xff));
+
+ std::vector<unsigned char> const hash(::comphelper::Hash::calculateHash(
+ aKeyData.data(), aKeyData.size(), ::comphelper::HashType::SHA1));
+
+ rtlCipherError result =
+ rtl_cipher_init(m_hCipher, rtl_Cipher_DirectionDecode,
+ hash.data(), ENCRYPT_KEY_SIZE_AES_128/8, nullptr, 0);
+
+ return (result == rtl_Cipher_E_None);
+}
+
+uno::Sequence<beans::NamedValue> MSCodec_CryptoAPI::GetEncryptionData()
+{
+ ::comphelper::SequenceAsHashMap aHashData(MSCodec97::GetEncryptionData());
+ //add in the old encryption key as well as our new key so saving using the
+ //old crypto scheme can be done without reprompt for the password
+ aHashData[OUString("STD97EncryptionKey")] <<= m_aStd97Key;
+ return aHashData.getAsConstNamedValueList();
+}
+
+void MSCodec_Std97::CreateSaltDigest( const sal_uInt8 nSaltData[16], sal_uInt8 nSaltDigest[16] )
+{
+#if DEBUG_MSO_ENCRYPTION_STD97
+ lcl_PrintDigest(nSaltData, "salt data");
+#endif
+ if (InitCipher(0))
+ {
+ sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5];
+ GetDigestFromSalt(nSaltData, pDigest);
+
+ rtl_cipher_decode (
+ m_hCipher, pDigest, 16, pDigest, sizeof(pDigest));
+
+ memcpy(nSaltDigest, pDigest, 16);
+ }
+}
+
+bool MSCodec97::Encode (
+ const void *pData, std::size_t nDatLen,
+ sal_uInt8 *pBuffer, std::size_t nBufLen)
+{
+ rtlCipherError result = rtl_cipher_encode(
+ m_hCipher, pData, nDatLen, pBuffer, nBufLen);
+
+ return (result == rtl_Cipher_E_None);
+}
+
+bool MSCodec97::Decode (
+ const void *pData, std::size_t nDatLen,
+ sal_uInt8 *pBuffer, std::size_t nBufLen)
+{
+ rtlCipherError result = rtl_cipher_decode(
+ m_hCipher, pData, nDatLen, pBuffer, nBufLen);
+
+ return (result == rtl_Cipher_E_None);
+}
+
+bool MSCodec97::Skip(std::size_t nDatLen)
+{
+ sal_uInt8 pnDummy[ 1024 ];
+ std::size_t nDatLeft = nDatLen;
+ bool bResult = true;
+
+ while (bResult && nDatLeft)
+ {
+ std::size_t nBlockLen = ::std::min< std::size_t >( nDatLeft, sizeof(pnDummy) );
+ bResult = Decode( pnDummy, nBlockLen, pnDummy, nBlockLen );
+ nDatLeft -= nBlockLen;
+ }
+
+ return bResult;
+}
+
+void MSCodec_Std97::GetDigestFromSalt(const sal_uInt8* pSaltData, sal_uInt8* pDigest)
+{
+ sal_uInt8 pBuffer[64];
+ sal_uInt8 pDigestLocal[16];
+
+ // Decode SaltData into Buffer.
+ rtl_cipher_decode (
+ m_hCipher, pSaltData, 16, pBuffer, sizeof(pBuffer));
+
+ // set the 129th bit to make the buffer 128-bit in length.
+ pBuffer[16] = 0x80;
+
+ // erase the rest of the buffer with zeros.
+ memset (pBuffer + 17, 0, sizeof(pBuffer) - 17);
+
+ // set the 441st bit.
+ pBuffer[56] = 0x80;
+
+ // Fill raw digest of Buffer into Digest.
+ rtl_digest_updateMD5 (
+ m_hDigest, pBuffer, sizeof(pBuffer));
+ rtl_digest_rawMD5 (
+ m_hDigest, pDigestLocal, sizeof(pDigestLocal));
+
+ memcpy(pDigest, pDigestLocal, 16);
+}
+
+void MSCodec_Std97::GetEncryptKey (
+ const sal_uInt8 pSalt[16],
+ sal_uInt8 pSaltData[16],
+ sal_uInt8 pSaltDigest[16])
+{
+ if (!InitCipher(0))
+ return;
+
+ sal_uInt8 pDigest[RTL_DIGEST_LENGTH_MD5];
+ sal_uInt8 pBuffer[64];
+
+ rtl_cipher_encode (
+ m_hCipher, pSalt, 16, pSaltData, sizeof(pBuffer));
+
+ memcpy( pBuffer, pSalt, 16 );
+
+ pBuffer[16] = 0x80;
+ memset (pBuffer + 17, 0, sizeof(pBuffer) - 17);
+ pBuffer[56] = 0x80;
+
+ rtl_digest_updateMD5 (
+ m_hDigest, pBuffer, sizeof(pBuffer));
+ rtl_digest_rawMD5 (
+ m_hDigest, pDigest, sizeof(pDigest));
+
+ rtl_cipher_encode (
+ m_hCipher, pDigest, 16, pSaltDigest, 16);
+
+ rtl_secureZeroMemory (pBuffer, sizeof(pBuffer));
+ rtl_secureZeroMemory (pDigest, sizeof(pDigest));
+}
+
+void MSCodec97::GetDocId( sal_uInt8 pDocId[16] )
+{
+ assert(m_aDocId.size() == 16);
+ memcpy(pDocId, m_aDocId.data(), 16);
+}
+
+EncryptionStandardHeader::EncryptionStandardHeader()
+{
+ flags = 0;
+ sizeExtra = 0;
+ algId = 0;
+ algIdHash = 0;
+ keyBits = 0;
+ providedType = 0;
+ reserved1 = 0;
+ reserved2 = 0;
+}
+
+EncryptionVerifierAES::EncryptionVerifierAES()
+ : saltSize(SALT_LENGTH)
+ , encryptedVerifierHashSize(comphelper::SHA1_HASH_LENGTH)
+{
+}
+
+EncryptionVerifierRC4::EncryptionVerifierRC4()
+ : saltSize(SALT_LENGTH)
+ , encryptedVerifierHashSize(comphelper::SHA1_HASH_LENGTH)
+{
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/msdffimp.cxx b/filter/source/msfilter/msdffimp.cxx
new file mode 100644
index 000000000..66bac102a
--- /dev/null
+++ b/filter/source/msfilter/msdffimp.cxx
@@ -0,0 +1,7610 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+
+#include <math.h>
+#include <limits>
+#include <limits.h>
+#include <utility>
+#include <vector>
+
+#include <o3tl/any.hxx>
+#include <o3tl/safeint.hxx>
+#include <osl/file.hxx>
+#include <tools/solar.h>
+#include <sal/log.hxx>
+#include <rtl/math.hxx>
+
+#include <comphelper/classids.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <unotools/configmgr.hxx>
+#include <unotools/streamwrap.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/seqstream.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <comphelper/sequence.hxx>
+#include <sot/exchange.hxx>
+#include <sot/storinfo.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <vcl/wmf.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/vclptr.hxx>
+#include <vcl/BitmapTools.hxx>
+#include "viscache.hxx"
+
+// SvxItem-Mapping. Is needed to successfully include the SvxItem-Header
+#include <editeng/eeitem.hxx>
+#include <editeng/editdata.hxx>
+#include <tools/stream.hxx>
+#include <tools/debug.hxx>
+#include <tools/zcodec.hxx>
+#include <filter/msfilter/escherex.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <com/sun/star/drawing/Position3D.hpp>
+#include <com/sun/star/drawing/Direction3D.hpp>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <tools/urlobj.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <sot/storage.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/xsflclit.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xflftrit.hxx>
+#include <svx/sdgcpitm.hxx>
+#include <svx/sdgmoitm.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/svdorect.hxx>
+#include <svx/svdoedge.hxx>
+#include <svx/svdoutl.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/xlntrit.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflbmtit.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xfltrit.hxx>
+#include <svx/xflbmsxy.hxx>
+#include <svx/xflbmsli.hxx>
+#include <editeng/frmdir.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svx/svdtrans.hxx>
+#include <svx/sxenditm.hxx>
+#include <svx/sdgluitm.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/fontitem.hxx>
+#include <svx/sxekitm.hxx>
+#include <svx/xpoly.hxx>
+#include <svx/xlineit0.hxx>
+#include <svx/xlncapit.hxx>
+#include <svx/xlinjoit.hxx>
+#include <svx/xlndsit.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xlnwtit.hxx>
+#include <svx/xlnstwit.hxx>
+#include <svx/xlnedwit.hxx>
+#include <svx/xlnstit.hxx>
+#include <svx/xlnedit.hxx>
+#include <svx/xlnstcit.hxx>
+#include <svx/xlnedcit.hxx>
+#include <svx/sdasitm.hxx>
+#include <svx/sdggaitm.hxx>
+#include <svx/sdshcitm.hxx>
+#include <svx/sdshitm.hxx>
+#include <svx/sdshtitm.hxx>
+#include <svx/sdsxyitm.hxx>
+#include <svx/sdtagitm.hxx>
+#include <svx/sdtcfitm.hxx>
+#include <svx/sdtditm.hxx>
+#include <svx/sdtfsitm.hxx>
+#include <svx/sdtmfitm.hxx>
+#include <filter/msfilter/classids.hxx>
+#include <filter/msfilter/msdffimp.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/outlobj.hxx>
+#include <com/sun/star/drawing/ShadeMode.hpp>
+#include <vcl/dibtools.hxx>
+#include <vcl/svapp.hxx>
+#include <svx/svdoashp.hxx>
+#include <svx/EnhancedCustomShapeTypeNames.hxx>
+#include <svx/EnhancedCustomShapeGeometry.hxx>
+#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
+#include <com/sun/star/drawing/EnhancedCustomShapeMetalType.hpp>
+#include <com/sun/star/beans/PropertyValues.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/ProjectionMode.hpp>
+#include <svx/EnhancedCustomShape2d.hxx>
+#include <rtl/ustring.hxx>
+#include <svtools/embedhlp.hxx>
+#include <memory>
+
+using namespace ::com::sun::star ;
+using namespace ::com::sun::star::drawing;
+using namespace uno ;
+using namespace beans ;
+using namespace drawing ;
+using namespace container ;
+
+// static counter for OLE-Objects
+static sal_uInt32 nMSOleObjCntr = 0;
+constexpr OUStringLiteral MSO_OLE_Obj = u"MSO_OLE_Obj";
+
+namespace {
+/* Office File Formats - 2.2.23 */
+enum class OfficeArtBlipRecInstance : sal_uInt32
+{
+ EMF = 0x3D4, // defined in section 2.2.24.
+ WMF = 0x216, // defined in section 2.2.25.
+ PICT = 0x542, // as defined in section 2.2.26.
+ JPEG_RGB = 0x46A, // defined in section 2.2.27.
+ JPEG_CMYK = 0x6E2, // defined in section 2.2.27.
+ PNG = 0x6E0, // defined in section 2.2.28.
+ DIB = 0x7A8, // defined in section 2.2.29.
+ TIFF = 0x6E4 // defined in section 2.2.30.
+};
+
+struct SvxMSDffBLIPInfo
+{
+ sal_uLong nFilePos; ///< offset of the BLIP in data stream
+ explicit SvxMSDffBLIPInfo(sal_uLong nFPos)
+ : nFilePos(nFPos)
+ {
+ }
+};
+
+}
+
+/// the following will be sorted by the order of their appearance:
+struct SvxMSDffBLIPInfos : public std::vector<SvxMSDffBLIPInfo> {};
+
+/************************************************************************/
+void Impl_OlePres::Write( SvStream & rStm )
+{
+ WriteClipboardFormat( rStm, SotClipboardFormatId::GDIMETAFILE );
+ rStm.WriteInt32( 4 ); // a TargetDevice that's always empty
+ rStm.WriteUInt32( nAspect );
+ rStm.WriteInt32( -1 ); //L-Index always -1
+ rStm.WriteInt32( nAdvFlags );
+ rStm.WriteInt32( 0 ); //Compression
+ rStm.WriteInt32( aSize.Width() );
+ rStm.WriteInt32( aSize.Height() );
+ sal_uInt64 nPos = rStm.Tell();
+ rStm.WriteInt32( 0 );
+
+ if( nFormat == SotClipboardFormatId::GDIMETAFILE && pMtf )
+ {
+ // Always to 1/100 mm, until Mtf-Solution found
+ // Assumption (no scaling, no origin translation)
+ DBG_ASSERT( pMtf->GetPrefMapMode().GetScaleX() == Fraction( 1, 1 ),
+ "x-scale in the Mtf is wrong" );
+ DBG_ASSERT( pMtf->GetPrefMapMode().GetScaleY() == Fraction( 1, 1 ),
+ "y-scale in the Mtf is wrong" );
+ DBG_ASSERT( pMtf->GetPrefMapMode().GetOrigin() == Point(),
+ "origin-shift in the Mtf is wrong" );
+ MapUnit nMU = pMtf->GetPrefMapMode().GetMapUnit();
+ if( MapUnit::Map100thMM != nMU )
+ {
+ Size aPrefS( pMtf->GetPrefSize() );
+ Size aS = OutputDevice::LogicToLogic(aPrefS, MapMode(nMU), MapMode(MapUnit::Map100thMM));
+
+ pMtf->Scale( Fraction( aS.Width(), aPrefS.Width() ),
+ Fraction( aS.Height(), aPrefS.Height() ) );
+ pMtf->SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ pMtf->SetPrefSize( aS );
+ }
+ WriteWindowMetafileBits( rStm, *pMtf );
+ }
+ else
+ {
+ OSL_FAIL( "unknown format" );
+ }
+ sal_uInt64 nEndPos = rStm.Tell();
+ rStm.Seek( nPos );
+ rStm.WriteUInt32( nEndPos - nPos - 4 );
+ rStm.Seek( nEndPos );
+}
+
+DffPropertyReader::DffPropertyReader( const SvxMSDffManager& rMan )
+ : rManager(rMan)
+ , mnFix16Angle(0)
+ , mbRotateGranientFillWithAngle(false)
+{
+ InitializePropSet( DFF_msofbtOPT );
+}
+
+void DffPropertyReader::SetDefaultPropSet( SvStream& rStCtrl, sal_uInt32 nOffsDgg ) const
+{
+ const_cast<DffPropertyReader*>(this)->pDefaultPropSet.reset();
+ sal_uInt64 nOldPos = rStCtrl.Tell();
+ bool bOk = checkSeek(rStCtrl, nOffsDgg);
+ DffRecordHeader aRecHd;
+ if (bOk)
+ bOk = ReadDffRecordHeader( rStCtrl, aRecHd );
+ if (bOk && aRecHd.nRecType == DFF_msofbtDggContainer)
+ {
+ if ( SvxMSDffManager::SeekToRec( rStCtrl, DFF_msofbtOPT, aRecHd.GetRecEndFilePos() ) )
+ {
+ const_cast<DffPropertyReader*>(this)->pDefaultPropSet.reset( new DffPropSet );
+ ReadDffPropSet( rStCtrl, *pDefaultPropSet );
+ }
+ }
+ rStCtrl.Seek( nOldPos );
+}
+
+#ifdef DBG_CUSTOMSHAPE
+void DffPropertyReader::ReadPropSet( SvStream& rIn, SvxMSDffClientData* pClientData, sal_uInt32 nShapeId ) const
+#else
+void DffPropertyReader::ReadPropSet( SvStream& rIn, SvxMSDffClientData* pClientData ) const
+#endif
+{
+ sal_uInt64 nFilePos = rIn.Tell();
+ ReadDffPropSet( rIn, const_cast<DffPropertyReader&>(*this) );
+
+ if ( IsProperty( DFF_Prop_hspMaster ) )
+ {
+ if ( rManager.SeekToShape( rIn, pClientData, GetPropertyValue( DFF_Prop_hspMaster, 0 ) ) )
+ {
+ DffRecordHeader aRecHd;
+ bool bOk = ReadDffRecordHeader(rIn, aRecHd);
+ if (bOk && SvxMSDffManager::SeekToRec(rIn, DFF_msofbtOPT, aRecHd.GetRecEndFilePos()))
+ {
+ rIn |= const_cast<DffPropertyReader&>(*this);
+ }
+ }
+ }
+
+ const_cast<DffPropertyReader*>(this)->mnFix16Angle = Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation, 0 ) );
+
+#ifdef DBG_CUSTOMSHAPE
+
+ OUString aURLStr;
+
+ if( osl::FileBase::getFileURLFromSystemPath( OUString("d:\\ashape.dbg"), aURLStr ) == osl::FileBase::E_None )
+ {
+ std::unique_ptr<SvStream> xOut(::utl::UcbStreamHelper::CreateStream( aURLStr, StreamMode::WRITE ));
+
+ if( xOut )
+ {
+ xOut->Seek( STREAM_SEEK_TO_END );
+
+ if ( IsProperty( DFF_Prop_adjustValue ) || IsProperty( DFF_Prop_pVertices ) )
+ {
+ xOut->WriteLine( "" );
+ OString aString("ShapeId: " + OString::number(nShapeId));
+ xOut->WriteLine(aString);
+ }
+ for ( sal_uInt32 i = DFF_Prop_adjustValue; i <= DFF_Prop_adjust10Value; i++ )
+ {
+ if ( IsProperty( i ) )
+ {
+ OString aString("Prop_adjustValue" + OString::number( ( i - DFF_Prop_adjustValue ) + 1 ) +
+ ":" + OString::number(GetPropertyValue(i)) );
+ xOut->WriteLine(aString);
+ }
+ }
+ sal_Int32 i;
+ for ( i = 320; i < 383; i++ )
+ {
+ if ( ( i >= DFF_Prop_adjustValue ) && ( i <= DFF_Prop_adjust10Value ) )
+ continue;
+ if ( IsProperty( i ) )
+ {
+ if ( SeekToContent( i, rIn ) )
+ {
+ sal_Int32 nLen = (sal_Int32)GetPropertyValue( i );
+ if ( nLen )
+ {
+ xOut->WriteLine( "" );
+ OStringBuffer aDesc("Property:" + OString::number(i) +
+ " Size:" + OString::number(nLen));
+ xOut->WriteLine(aDesc.makeStringAndClear());
+ sal_Int16 nNumElem, nNumElemMem, nNumSize;
+ rIn >> nNumElem >> nNumElemMem >> nNumSize;
+ aDesc.append("Entries: " + OString::number(nNumElem) +
+ " Size:" + OString::number(nNumSize));
+ xOut->WriteLine(aDesc.makeStringAndClear());
+ if ( nNumSize < 0 )
+ nNumSize = ( ( -nNumSize ) >> 2 );
+ if ( !nNumSize )
+ nNumSize = 16;
+ nLen -= 6;
+ while ( nLen > 0 )
+ {
+ for ( sal_uInt32 j = 0; nLen && ( j < ( nNumSize >> 1 ) ); j++ )
+ {
+ for ( sal_uInt32 k = 0; k < 2; k++ )
+ {
+ if ( nLen )
+ {
+ sal_uInt8 nVal;
+ rIn >> nVal;
+ if ( ( nVal >> 4 ) > 9 )
+ *xOut << (sal_uInt8)( ( nVal >> 4 ) + 'A' - 10 );
+ else
+ *xOut << (sal_uInt8)( ( nVal >> 4 ) + '0' );
+
+ if ( ( nVal & 0xf ) > 9 )
+ *xOut << (sal_uInt8)( ( nVal & 0xf ) + 'A' - 10 );
+ else
+ *xOut << (sal_uInt8)( ( nVal & 0xf ) + '0' );
+
+ nLen--;
+ }
+ }
+ *xOut << (char)( ' ' );
+ }
+ xOut->WriteLine( OString() );
+ }
+ }
+ }
+ else
+ {
+ OString aString("Property" + OString::number(i) +
+ ":" + OString::number(GetPropertyValue(i)));
+ xOut->WriteLine(aString);
+ }
+ }
+ }
+ }
+ }
+
+#endif
+
+ rIn.Seek( nFilePos );
+}
+
+
+Degree100 DffPropertyReader::Fix16ToAngle( sal_Int32 nContent )
+{
+ Degree100 nAngle(0);
+ if ( nContent )
+ {
+ nAngle = Degree100(( static_cast<sal_Int16>( nContent >> 16) * 100L ) + ( ( ( nContent & 0x0000ffff) * 100L ) >> 16 ));
+ nAngle = NormAngle36000( -nAngle );
+ }
+ return nAngle;
+}
+
+DffPropertyReader::~DffPropertyReader()
+{
+}
+
+static SvStream& operator>>( SvStream& rIn, SvxMSDffConnectorRule& rRule )
+{
+ sal_uInt32 nRuleId;
+ rIn.ReadUInt32( nRuleId )
+ .ReadUInt32( rRule.nShapeA )
+ .ReadUInt32( rRule.nShapeB )
+ .ReadUInt32( rRule.nShapeC )
+ .ReadUInt32( rRule.ncptiA )
+ .ReadUInt32( rRule.ncptiB );
+
+ return rIn;
+}
+
+SvxMSDffSolverContainer::SvxMSDffSolverContainer()
+{
+}
+
+SvxMSDffSolverContainer::~SvxMSDffSolverContainer()
+{
+}
+
+SvStream& ReadSvxMSDffSolverContainer( SvStream& rIn, SvxMSDffSolverContainer& rContainer )
+{
+ DffRecordHeader aHd;
+ bool bOk = ReadDffRecordHeader( rIn, aHd );
+ if (!bOk || aHd.nRecType != DFF_msofbtSolverContainer)
+ return rIn;
+
+ DffRecordHeader aCRule;
+ auto nEndPos = DffPropSet::SanitizeEndPos(rIn, aHd.GetRecEndFilePos());
+ while ( rIn.good() && ( rIn.Tell() < nEndPos ) )
+ {
+ if (!ReadDffRecordHeader(rIn, aCRule))
+ break;
+ if ( aCRule.nRecType == DFF_msofbtConnectorRule )
+ {
+ std::unique_ptr<SvxMSDffConnectorRule> pRule(new SvxMSDffConnectorRule);
+ rIn >> *pRule;
+ rContainer.aCList.push_back( std::move(pRule) );
+ }
+ if (!aCRule.SeekToEndOfRecord(rIn))
+ break;
+ }
+ return rIn;
+}
+
+void SvxMSDffManager::SolveSolver( const SvxMSDffSolverContainer& rSolver )
+{
+ size_t i, nCnt;
+ for ( i = 0, nCnt = rSolver.aCList.size(); i < nCnt; i++ )
+ {
+ SvxMSDffConnectorRule* pPtr = rSolver.aCList[ i ].get();
+ if ( pPtr->pCObj )
+ {
+ for ( int nN = 0; nN < 2; nN++ )
+ {
+ SdrObject* pO;
+ sal_uInt32 nC;
+ ShapeFlag nSpFlags;
+ if ( !nN )
+ {
+ pO = pPtr->pAObj;
+ nC = pPtr->ncptiA;
+ nSpFlags = pPtr->nSpFlagsA;
+ }
+ else
+ {
+ pO = pPtr->pBObj;
+ nC = pPtr->ncptiB;
+ nSpFlags = pPtr->nSpFlagsB;
+ }
+ if ( pO )
+ {
+ SdrGluePoint aGluePoint;
+ Reference< XShape > aXShape( pO->getUnoShape(), UNO_QUERY );
+ Reference< XShape > aXConnector( pPtr->pCObj->getUnoShape(), UNO_QUERY );
+ SdrGluePointList* pList = pO->ForceGluePointList();
+
+ sal_Int32 nId = nC;
+ SdrInventor nInventor = pO->GetObjInventor();
+
+ if( nInventor == SdrInventor::Default )
+ {
+ bool bValidGluePoint = false;
+ SdrObjKind nObjId = pO->GetObjIdentifier();
+ switch( nObjId )
+ {
+ case SdrObjKind::Group :
+ case SdrObjKind::Graphic :
+ case SdrObjKind::Rectangle :
+ case SdrObjKind::Text :
+ case SdrObjKind::Page :
+ case SdrObjKind::TitleText :
+ case SdrObjKind::OutlineText :
+ {
+ if ( nC & 1 )
+ {
+ if ( nSpFlags & ShapeFlag::FlipH )
+ nC ^= 2; // 1 <-> 3
+ }
+ else
+ {
+ if ( nSpFlags & ShapeFlag::FlipV )
+ nC ^= 1; // 0 <-> 2
+ }
+ switch( nC )
+ {
+ case 0 :
+ nId = 0; // SdrAlign::VERT_TOP;
+ break;
+ case 1 :
+ nId = 3; // SdrAlign::HORZ_RIGHT;
+ break;
+ case 2 :
+ nId = 2; // SdrAlign::VERT_BOTTOM;
+ break;
+ case 3 :
+ nId = 1; // SdrAlign::HORZ_LEFT;
+ break;
+ }
+ if ( nId <= 3 )
+ bValidGluePoint = true;
+ }
+ break;
+ case SdrObjKind::Polygon :
+ case SdrObjKind::PolyLine :
+ case SdrObjKind::Line :
+ case SdrObjKind::PathLine :
+ case SdrObjKind::PathFill :
+ case SdrObjKind::FreehandLine :
+ case SdrObjKind::FreehandFill :
+ case SdrObjKind::SplineLine :
+ case SdrObjKind::SplineFill :
+ case SdrObjKind::PathPoly :
+ case SdrObjKind::PathPolyLine :
+ {
+ if (pList)
+ {
+ if (pList->GetCount() > nC )
+ {
+ bValidGluePoint = true;
+ nId = static_cast<sal_Int32>((*pList)[ static_cast<sal_uInt16>(nC)].GetId() + 3 );
+ }
+ else
+ {
+ bool bNotFound = true;
+
+ tools::PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aXShape ) );
+ sal_uInt16 k, j, nPolySize = aPolyPoly.Count();
+ if ( nPolySize )
+ {
+ tools::Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
+ if ( aBoundRect.GetWidth() && aBoundRect.GetHeight() )
+ {
+ sal_uInt32 nPointCount = 0;
+ for ( k = 0; bNotFound && ( k < nPolySize ); k++ )
+ {
+ const tools::Polygon& rPolygon = aPolyPoly.GetObject( k );
+ for ( j = 0; bNotFound && ( j < rPolygon.GetSize() ); j++ )
+ {
+ PolyFlags eFlags = rPolygon.GetFlags( j );
+ if ( eFlags == PolyFlags::Normal )
+ {
+ if ( nC == nPointCount )
+ {
+ const Point& rPoint = rPolygon.GetPoint( j );
+ double fXRel = rPoint.X() - aBoundRect.Left();
+ double fYRel = rPoint.Y() - aBoundRect.Top();
+ sal_Int32 nWidth = aBoundRect.GetWidth();
+ if ( !nWidth )
+ nWidth = 1;
+ sal_Int32 nHeight= aBoundRect.GetHeight();
+ if ( !nHeight )
+ nHeight = 1;
+ fXRel /= static_cast<double>(nWidth);
+ fXRel *= 10000;
+ fYRel /= static_cast<double>(nHeight);
+ fYRel *= 10000;
+ aGluePoint.SetPos( Point( static_cast<sal_Int32>(fXRel), static_cast<sal_Int32>(fYRel) ) );
+ aGluePoint.SetPercent( true );
+ aGluePoint.SetAlign( SdrAlign::VERT_TOP | SdrAlign::HORZ_LEFT );
+ aGluePoint.SetEscDir( SdrEscapeDirection::SMART );
+ nId = static_cast<sal_Int32>((*pList)[ pList->Insert( aGluePoint ) ].GetId() + 3 );
+ bNotFound = false;
+ }
+ nPointCount++;
+ }
+ }
+ }
+ }
+ }
+ if ( !bNotFound )
+ {
+ bValidGluePoint = true;
+ }
+ }
+ }
+ }
+ break;
+
+ case SdrObjKind::CustomShape :
+ {
+ const SfxPoolItem& aCustomShape = static_cast<SdrObjCustomShape*>(pO)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
+ SdrCustomShapeGeometryItem aGeometryItem( static_cast<const SdrCustomShapeGeometryItem&>(aCustomShape) );
+ static const OUStringLiteral sPath( u"Path" );
+ sal_Int16 nGluePointType = EnhancedCustomShapeGluePointType::SEGMENTS;
+ css::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sPath, "GluePointType" );
+ if ( pAny )
+ *pAny >>= nGluePointType;
+ else
+ {
+ OUString sShapeType;
+ pAny = aGeometryItem.GetPropertyValueByName( "Type" );
+ if ( pAny )
+ *pAny >>= sShapeType;
+ MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
+ nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType );
+ }
+ if ( nGluePointType == EnhancedCustomShapeGluePointType::CUSTOM )
+ {
+ if ( pList && ( pList->GetCount() > nC ) )
+ {
+ bValidGluePoint = true;
+ nId = static_cast<sal_Int32>((*pList)[ static_cast<sal_uInt16>(nC)].GetId() + 3 );
+ }
+ }
+ else if ( nGluePointType == EnhancedCustomShapeGluePointType::RECT )
+ {
+ if ( nC & 1 )
+ {
+ if ( nSpFlags & ShapeFlag::FlipH )
+ nC ^= 2; // 1 <-> 3
+ }
+ else
+ {
+ if ( nSpFlags & ShapeFlag::FlipV )
+ nC ^= 1; // 0 <-> 2
+ }
+ switch( nC )
+ {
+ case 0 :
+ nId = 0; // SdrAlign::VERT_TOP;
+ break;
+ case 1 :
+ nId = 3; // SdrAlign::HORZ_RIGHT;
+ break;
+ case 2 :
+ nId = 2; // SdrAlign::VERT_BOTTOM;
+ break;
+ case 3 :
+ nId = 1; // SdrAlign::HORZ_LEFT;
+ break;
+ }
+ if ( nId <= 3 )
+ bValidGluePoint = true;
+ }
+ else if ( nGluePointType == EnhancedCustomShapeGluePointType::SEGMENTS )
+ {
+ sal_uInt32 nPt = nC;
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > aSegments;
+ pAny = aGeometryItem.GetPropertyValueByName( sPath, "Segments" );
+ if ( pAny && (*pAny >>= aSegments) )
+ {
+ nPt = 0;
+ for ( sal_Int32 k = 1; nC && ( k < aSegments.getLength() ); k++ )
+ {
+ sal_Int16 j, nCnt2 = aSegments[ k ].Count;
+ if ( aSegments[ k ].Command != EnhancedCustomShapeSegmentCommand::UNKNOWN )
+ {
+ for ( j = 0; nC && ( j < nCnt2 ); j++ )
+ {
+ switch( aSegments[ k ].Command )
+ {
+ case EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
+ case EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
+ case EnhancedCustomShapeSegmentCommand::LINETO :
+ case EnhancedCustomShapeSegmentCommand::MOVETO :
+ {
+ nC--;
+ nPt++;
+ }
+ break;
+ case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
+ case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
+ break;
+
+ case EnhancedCustomShapeSegmentCommand::CURVETO :
+ {
+ nC--;
+ nPt += 3;
+ }
+ break;
+
+ case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
+ case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
+ {
+ nC--;
+ nPt += 3;
+ }
+ break;
+ case EnhancedCustomShapeSegmentCommand::ARCTO :
+ case EnhancedCustomShapeSegmentCommand::ARC :
+ case EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
+ case EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
+ {
+ nC--;
+ nPt += 4;
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ pAny = aGeometryItem.GetPropertyValueByName( sPath, "Coordinates" );
+ if ( pAny )
+ {
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
+ *pAny >>= aCoordinates;
+ if ( nPt < o3tl::make_unsigned(aCoordinates.getLength()) )
+ {
+ nId = 4;
+ css::drawing::EnhancedCustomShapeParameterPair& rPara = aCoordinates.getArray()[ nPt ];
+ sal_Int32 nX = 0, nY = 0;
+ if ( ( rPara.First.Value >>= nX ) && ( rPara.Second.Value >>= nY ) )
+ {
+ static const OUStringLiteral sGluePoints( u"GluePoints" );
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aGluePoints;
+ pAny = aGeometryItem.GetPropertyValueByName( sPath, sGluePoints );
+ if ( pAny )
+ *pAny >>= aGluePoints;
+ sal_Int32 nGluePoints = aGluePoints.getLength();
+ aGluePoints.realloc( nGluePoints + 1 );
+ auto pGluePoints = aGluePoints.getArray();
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pGluePoints[ nGluePoints ].First, nX );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pGluePoints[ nGluePoints ].Second, nY );
+ PropertyValue aProp;
+ aProp.Name = sGluePoints;
+ aProp.Value <<= aGluePoints;
+ aGeometryItem.SetPropertyValue( sPath, aProp );
+ bValidGluePoint = true;
+ static_cast<SdrObjCustomShape*>(pO)->SetMergedItem( aGeometryItem );
+ SdrGluePointList* pLst = pO->ForceGluePointList();
+ if ( pLst->GetCount() > nGluePoints )
+ nId = static_cast<sal_Int32>((*pLst)[ static_cast<sal_uInt16>(nGluePoints) ].GetId() + 3 );
+ }
+ }
+ }
+ }
+ }
+ break;
+ default: ;
+ }
+ if ( bValidGluePoint )
+ {
+ Reference< XPropertySet > xPropSet( aXConnector, UNO_QUERY );
+ if ( xPropSet.is() )
+ {
+ if ( nN )
+ {
+ OUString aPropName( "EndShape" );
+ SetPropValue( Any(aXShape), xPropSet, aPropName );
+ aPropName = "EndGluePointIndex";
+ SetPropValue( Any(nId), xPropSet, aPropName );
+ }
+ else
+ {
+ OUString aPropName( "StartShape" );
+ SetPropValue( Any(aXShape), xPropSet, aPropName );
+ aPropName = "StartGluePointIndex";
+ SetPropValue( Any(nId), xPropSet, aPropName );
+ }
+
+ // Not sure what this is good for, repaint or broadcast of object change.
+ //( Thus I am adding repaint here
+ pO->SetChanged();
+ pO->BroadcastObjectChange();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static basegfx::B2DPolyPolygon GetLineArrow( const sal_Int32 nLineWidth, const sal_uInt32 eLineEnd,
+ const sal_uInt32 eLineWidth, const sal_uInt32 eLineLength,
+ sal_Int32& rnArrowWidth, bool& rbArrowCenter,
+ OUString& rsArrowName, bool bScaleArrow )
+{
+ basegfx::B2DPolyPolygon aRetPolyPoly;
+ // 70 100mm = 2pt = 40 twip. In MS, line width less than 2pt has the same size arrow as 2pt
+ //If the unit is twip. Make all use this unit especially the critical value 70/40.
+ sal_Int32 nLineWidthCritical = bScaleArrow ? 40 : 70;
+ double fLineWidth = nLineWidth < nLineWidthCritical ? nLineWidthCritical : nLineWidth;
+
+ double fLengthMul, fWidthMul;
+ sal_Int32 nLineNumber;
+ switch( eLineLength )
+ {
+ default :
+ case mso_lineMediumLenArrow : fLengthMul = 3.0; nLineNumber = 2; break;
+ case mso_lineShortArrow : fLengthMul = 2.0; nLineNumber = 1; break;
+ case mso_lineLongArrow : fLengthMul = 5.0; nLineNumber = 3; break;
+ }
+ switch( eLineWidth )
+ {
+ default :
+ case mso_lineMediumWidthArrow : fWidthMul = 3.0; nLineNumber += 3; break;
+ case mso_lineNarrowArrow : fWidthMul = 2.0; break;
+ case mso_lineWideArrow : fWidthMul = 5.0; nLineNumber += 6; break;
+ }
+
+ rbArrowCenter = false;
+ OUStringBuffer aArrowName;
+ switch ( eLineEnd )
+ {
+ case mso_lineArrowEnd :
+ {
+ basegfx::B2DPolygon aTriangle;
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50, 0.0 ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth, fLengthMul * fLineWidth ));
+ aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth ));
+ aTriangle.setClosed(true);
+ aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
+ aArrowName.append("msArrowEnd ");
+ }
+ break;
+
+ case mso_lineArrowOpenEnd :
+ {
+ switch( eLineLength )
+ {
+ default :
+ case mso_lineMediumLenArrow : fLengthMul = 4.5; break;
+ case mso_lineShortArrow : fLengthMul = 3.5; break;
+ case mso_lineLongArrow : fLengthMul = 6.0; break;
+ }
+ switch( eLineWidth )
+ {
+ default :
+ case mso_lineMediumWidthArrow : fWidthMul = 4.5; break;
+ case mso_lineNarrowArrow : fWidthMul = 3.5; break;
+ case mso_lineWideArrow : fWidthMul = 6.0; break;
+ }
+ basegfx::B2DPolygon aTriangle;
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth, fLengthMul * fLineWidth * 0.91 ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.85, fLengthMul * fLineWidth ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50, fLengthMul * fLineWidth * 0.36 ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.15, fLengthMul * fLineWidth ));
+ aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth * 0.91 ));
+ aTriangle.setClosed(true);
+ aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
+ aArrowName.append("msArrowOpenEnd ");
+ }
+ break;
+ case mso_lineArrowStealthEnd :
+ {
+ basegfx::B2DPolygon aTriangle;
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth , fLengthMul * fLineWidth ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , fLengthMul * fLineWidth * 0.60 ));
+ aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth ));
+ aTriangle.setClosed(true);
+ aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
+ aArrowName.append("msArrowStealthEnd ");
+ }
+ break;
+ case mso_lineArrowDiamondEnd :
+ {
+ basegfx::B2DPolygon aTriangle;
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth , fLengthMul * fLineWidth * 0.50 ));
+ aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , fLengthMul * fLineWidth ));
+ aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth * 0.50 ));
+ aTriangle.setClosed(true);
+ aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
+ rbArrowCenter = true;
+ aArrowName.append("msArrowDiamondEnd ");
+ }
+ break;
+ case mso_lineArrowOvalEnd :
+ {
+ aRetPolyPoly = basegfx::B2DPolyPolygon(
+ XPolygon(
+ Point( static_cast<sal_Int32>( fWidthMul * fLineWidth * 0.50 ), 0 ),
+ static_cast<sal_Int32>( fWidthMul * fLineWidth * 0.50 ),
+ static_cast<sal_Int32>( fLengthMul * fLineWidth * 0.50 ),
+ 0_deg100, 36000_deg100 ).getB2DPolygon() );
+ rbArrowCenter = true;
+ aArrowName.append("msArrowOvalEnd ");
+ }
+ break;
+ default: break;
+ }
+ aArrowName.append(nLineNumber);
+ rsArrowName = aArrowName.makeStringAndClear();
+ rnArrowWidth = static_cast<sal_Int32>( fLineWidth * fWidthMul );
+
+ return aRetPolyPoly;
+}
+
+void DffPropertyReader::ApplyLineAttributes( SfxItemSet& rSet, const MSO_SPT eShapeType ) const // #i28269#
+{
+ sal_uInt32 nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash, 0 ));
+
+ if(!IsHardAttribute( DFF_Prop_fLine ) && !IsCustomShapeStrokedByDefault( eShapeType ))
+ {
+ nLineFlags &= ~0x08;
+ }
+
+ if ( nLineFlags & 8 )
+ {
+ // Line Attributes
+ sal_Int32 nLineWidth = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_lineWidth, 9525 ));
+
+ // support LineCap
+ auto eLineCap = GetPropertyValue(DFF_Prop_lineEndCapStyle, mso_lineEndCapFlat);
+
+ switch(eLineCap)
+ {
+ default: /* case mso_lineEndCapFlat */
+ {
+ // no need to set, it is the default. If this changes, this needs to be activated
+ // rSet.Put(XLineCapItem(css::drawing::LineCap_BUTT));
+ break;
+ }
+ case mso_lineEndCapRound:
+ {
+ rSet.Put(XLineCapItem(css::drawing::LineCap_ROUND));
+ break;
+ }
+ case mso_lineEndCapSquare:
+ {
+ rSet.Put(XLineCapItem(css::drawing::LineCap_SQUARE));
+ break;
+ }
+ }
+
+ auto eLineDashing = GetPropertyValue( DFF_Prop_lineDashing, mso_lineSolid);
+ if (eLineDashing == mso_lineSolid || nLineWidth < 0)
+ rSet.Put(XLineStyleItem( drawing::LineStyle_SOLID ) );
+ else
+ {
+ // Despite of naming "dot" and "dash", that are all dashes and a "dot" can be longer
+ // than a "dash". The naming indicates the order, "dot" is always the first dash and
+ // "dash" is always the second dash. MS Office always starts with the longer dash, so
+ // set it here accordingly.
+ // The preset from binary is essentially the same as from OOXML. So here the same
+ // setting is used as in oox import. The comment corresponds to
+ // "dots, dotLen, dashes, dashLen, distance" there.
+ // MS Office uses always relative length, so no need to consider nLineWidth
+ // here. Values are of kind 300 for 300% in css::drawing::DashStyle, for example.
+
+ sal_uInt16 nDots = 1; // in all cases, "solid" is treated above
+ // initialize, will be changed if necessary
+ sal_uInt32 nDotLen = 300;
+ sal_uInt16 nDashes = 0;
+ sal_uInt32 nDashLen = 0;
+ sal_uInt32 nDistance = 300;
+ switch ( eLineDashing )
+ {
+ default:
+ case mso_lineDotSys : // 1 1 0 0 1
+ {
+ nDotLen =100;
+ nDistance = 100;
+ }
+ break;
+
+ case mso_lineDashGEL : // 1 4 0 0 3
+ {
+ nDotLen = 400;
+ }
+ break;
+
+ case mso_lineDashDotGEL : // 1 4 1 1 3
+ {
+ nDotLen = 400;
+ nDashes = 1;
+ nDashLen = 100;
+ }
+ break;
+
+ case mso_lineLongDashGEL : // 1 8 0 0 3
+ {
+ nDotLen = 800;
+ }
+ break;
+
+ case mso_lineLongDashDotGEL : // 1 8 1 1 3
+ {
+ nDotLen = 800;
+ nDashes = 1;
+ nDashLen = 100;
+ }
+ break;
+
+ case mso_lineLongDashDotDotGEL: // 1 8 2 1 3
+ {
+ nDotLen = 800;
+ nDashes = 2;
+ nDashLen = 100;
+ }
+ break;
+
+ case mso_lineDotGEL: // 1 1 0 0 3
+ {
+ nDotLen = 100;
+ }
+ break;
+
+ case mso_lineDashSys: // 1 3 0 0 1
+ {
+ nDistance = 100;
+ }
+ break;
+
+ case mso_lineDashDotSys: // 1 3 1 1 1
+ {
+ nDashes = 1;
+ nDashLen = 100;
+ nDistance = 100;
+ }
+ break;
+
+ case mso_lineDashDotDotSys: // 1 3 2 1 1
+ {
+ nDashes = 2;
+ nDashLen = 100;
+ nDistance = 100;
+ }
+ break;
+ }
+ rSet.Put( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECTRELATIVE, nDots, nDotLen, nDashes, nDashLen, nDistance ) ) );
+ rSet.Put( XLineStyleItem( drawing::LineStyle_DASH ) );
+ }
+ rSet.Put( XLineColorItem( OUString(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_lineColor, 0 ) ) ) );
+ if ( IsProperty( DFF_Prop_lineOpacity ) )
+ {
+ double nTrans = GetPropertyValue(DFF_Prop_lineOpacity, 0x10000);
+ nTrans = (nTrans * 100) / 65536;
+ rSet.Put(XLineTransparenceItem(
+ sal_uInt16(100 - ::rtl::math::round(nTrans))));
+ }
+
+ rManager.ScaleEmu( nLineWidth );
+ rSet.Put( XLineWidthItem( nLineWidth ) );
+
+ // SJ: LineJoint (setting each time a line is set, because our internal joint type has another default)
+ MSO_LineJoin eLineJointDefault = mso_lineJoinMiter;
+ if ( eShapeType == mso_sptMin )
+ eLineJointDefault = mso_lineJoinRound;
+ auto eLineJoint = GetPropertyValue(DFF_Prop_lineJoinStyle, eLineJointDefault);
+ css::drawing::LineJoint eXLineJoint( css::drawing::LineJoint_MITER );
+ if ( eLineJoint == mso_lineJoinBevel )
+ eXLineJoint = css::drawing::LineJoint_BEVEL;
+ else if ( eLineJoint == mso_lineJoinRound )
+ eXLineJoint = css::drawing::LineJoint_ROUND;
+ rSet.Put( XLineJointItem( eXLineJoint ) );
+
+ if ( nLineFlags & 0x10 )
+ {
+ bool bScaleArrows = rManager.pSdrModel->GetScaleUnit() == MapUnit::MapTwip;
+
+ // LineStart
+
+ if ( IsProperty( DFF_Prop_lineStartArrowhead ) )
+ {
+ auto eLineEnd = GetPropertyValue(DFF_Prop_lineStartArrowhead, 0);
+ auto eWidth = GetPropertyValue(DFF_Prop_lineStartArrowWidth, mso_lineMediumWidthArrow);
+ auto eLength = GetPropertyValue(DFF_Prop_lineStartArrowLength, mso_lineMediumLenArrow);
+
+ sal_Int32 nArrowWidth;
+ bool bArrowCenter;
+ OUString aArrowName;
+ basegfx::B2DPolyPolygon aPolyPoly(GetLineArrow( nLineWidth, eLineEnd, eWidth, eLength, nArrowWidth, bArrowCenter, aArrowName, bScaleArrows ));
+
+ rSet.Put( XLineStartWidthItem( nArrowWidth ) );
+ rSet.Put( XLineStartItem( aArrowName, aPolyPoly) );
+ rSet.Put( XLineStartCenterItem( bArrowCenter ) );
+ }
+
+ // LineEnd
+
+ if ( IsProperty( DFF_Prop_lineEndArrowhead ) )
+ {
+ auto eLineEnd = GetPropertyValue(DFF_Prop_lineEndArrowhead, 0);
+ auto eWidth = GetPropertyValue(DFF_Prop_lineEndArrowWidth, mso_lineMediumWidthArrow);
+ auto eLength = GetPropertyValue(DFF_Prop_lineEndArrowLength, mso_lineMediumLenArrow);
+
+ sal_Int32 nArrowWidth;
+ bool bArrowCenter;
+ OUString aArrowName;
+ basegfx::B2DPolyPolygon aPolyPoly(GetLineArrow( nLineWidth, eLineEnd, eWidth, eLength, nArrowWidth, bArrowCenter, aArrowName, bScaleArrows ));
+
+ rSet.Put( XLineEndWidthItem( nArrowWidth ) );
+ rSet.Put( XLineEndItem( aArrowName, aPolyPoly ) );
+ rSet.Put( XLineEndCenterItem( bArrowCenter ) );
+ }
+ }
+ }
+ else
+ rSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
+}
+
+namespace {
+
+struct ShadeColor
+{
+ Color aColor;
+ double fDist;
+
+ ShadeColor( const Color& rC, double fR ) : aColor( rC ), fDist( fR ) {};
+};
+
+}
+
+static void GetShadeColors( const SvxMSDffManager& rManager, const DffPropertyReader& rProperties, SvStream& rIn, std::vector< ShadeColor >& rShadeColors )
+{
+ sal_uInt64 nPos = rIn.Tell();
+ if ( rProperties.IsProperty( DFF_Prop_fillShadeColors ) )
+ {
+ sal_uInt16 i = 0, nNumElem = 0;
+ bool bOk = false;
+ if (rProperties.SeekToContent(DFF_Prop_fillShadeColors, rIn))
+ {
+ sal_uInt16 nNumElemReserved = 0, nSize = 0;
+ rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemReserved ).ReadUInt16( nSize );
+ //sanity check that the stream is long enough to fulfill nNumElem * 2 sal_Int32s
+ bOk = rIn.remainingSize() / (2*sizeof(sal_Int32)) >= nNumElem;
+ }
+ if (bOk)
+ {
+ for ( ; i < nNumElem; i++ )
+ {
+ sal_Int32 nColor(0);
+ sal_Int32 nDist(0);
+
+ rIn.ReadInt32( nColor ).ReadInt32( nDist );
+ rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( nColor, DFF_Prop_fillColor ), 1.0 - ( nDist / 65536.0 ) );
+ }
+ }
+ }
+ if ( rShadeColors.empty() )
+ {
+ rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( rProperties.GetPropertyValue( DFF_Prop_fillBackColor, sal_uInt32(COL_WHITE) ), DFF_Prop_fillBackColor ), 0 );
+ rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( rProperties.GetPropertyValue( DFF_Prop_fillColor, sal_uInt32(COL_WHITE) ), DFF_Prop_fillColor ), 1 );
+ }
+ rIn.Seek( nPos );
+}
+
+static void ApplyRectangularGradientAsBitmap( const SvxMSDffManager& rManager, SvStream& rIn, SfxItemSet& rSet, const std::vector< ShadeColor >& rShadeColors, const DffObjData& rObjData, Degree100 nFix16Angle )
+{
+ Size aBitmapSizePixel( static_cast< sal_Int32 >( ( rObjData.aBoundRect.GetWidth() / 2540.0 ) * 90.0 ), // we will create a bitmap with 90 dpi
+ static_cast< sal_Int32 >( ( rObjData.aBoundRect.GetHeight() / 2540.0 ) * 90.0 ) );
+ if (aBitmapSizePixel.IsEmpty() || aBitmapSizePixel.Width() > 1024 || aBitmapSizePixel.Height() > 1024)
+ return;
+
+ double fFocusX = rManager.GetPropertyValue( DFF_Prop_fillToRight, 0 ) / 65536.0;
+ double fFocusY = rManager.GetPropertyValue( DFF_Prop_fillToBottom, 0 ) / 65536.0;
+
+ vcl::bitmap::RawBitmap aBitmap(aBitmapSizePixel, 24);
+
+ for ( tools::Long nY = 0; nY < aBitmapSizePixel.Height(); nY++ )
+ {
+ for ( tools::Long nX = 0; nX < aBitmapSizePixel.Width(); nX++ )
+ {
+ double fX = static_cast< double >( nX ) / aBitmapSizePixel.Width();
+ double fY = static_cast< double >( nY ) / aBitmapSizePixel.Height();
+
+ double fD, fDist;
+ if ( fX < fFocusX )
+ {
+ if ( fY < fFocusY )
+ {
+ if ( fX > fY )
+ {
+ fDist = fY;
+ fD = fFocusY;
+ }
+ else
+ {
+ fDist = fX;
+ fD = fFocusX;
+ }
+ }
+ else
+ {
+ if ( fX > ( 1 - fY ) )
+ {
+ fDist = 1 - fY;
+ fD = 1 - fFocusY;
+ }
+ else
+ {
+ fDist = fX;
+ fD = fFocusX;
+ }
+ }
+ }
+ else
+ {
+ if ( fY < fFocusY )
+ {
+ if ( ( 1 - fX ) > fY )
+ {
+ fDist = fY;
+ fD = fFocusY;
+ }
+ else
+ {
+ fDist = 1 - fX;
+ fD = 1 - fFocusX;
+ }
+ }
+ else
+ {
+ if ( ( 1 - fX ) > ( 1 - fY ) )
+ {
+ fDist = 1 - fY;
+ fD = 1 - fFocusY;
+ }
+ else
+ {
+ fDist = 1 - fX;
+ fD = 1 - fFocusX;
+ }
+ }
+ }
+ if ( fD != 0.0 )
+ fDist /= fD;
+
+ double fA = 0.0;
+ Color aColorA = rShadeColors.front().aColor;
+ double fB = 1.0;
+ Color aColorB( aColorA );
+ for ( const auto& rShadeColor : rShadeColors )
+ {
+ if ( fA <= rShadeColor.fDist && rShadeColor.fDist <= fDist )
+ {
+ fA = rShadeColor.fDist;
+ aColorA = rShadeColor.aColor;
+ }
+ if ( fDist < rShadeColor.fDist && rShadeColor.fDist <= fB )
+ {
+ fB = rShadeColor.fDist;
+ aColorB = rShadeColor.aColor;
+ }
+ }
+ double fRed = aColorA.GetRed(), fGreen = aColorA.GetGreen(), fBlue = aColorA.GetBlue();
+ double fD1 = fB - fA;
+ if ( fD1 != 0.0 )
+ {
+ fRed += ( ( ( fDist - fA ) * ( aColorB.GetRed() - aColorA.GetRed() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fRed;
+ fGreen += ( ( ( fDist - fA ) * ( aColorB.GetGreen() - aColorA.GetGreen() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fGreen;
+ fBlue += ( ( ( fDist - fA ) * ( aColorB.GetBlue() - aColorA.GetBlue() ) ) / fD1 ); // + aQuantErrCurrScan[ nX ].fBlue;
+ }
+ sal_Int16 nRed = static_cast< sal_Int16 >( fRed + 0.5 );
+ sal_Int16 nGreen = static_cast< sal_Int16 >( fGreen + 0.5 );
+ sal_Int16 nBlue = static_cast< sal_Int16 >( fBlue + 0.5 );
+ if ( nRed < 0 )
+ nRed = 0;
+ if ( nRed > 255 )
+ nRed = 255;
+ if ( nGreen < 0 )
+ nGreen = 0;
+ if ( nGreen > 255 )
+ nGreen = 255;
+ if ( nBlue < 0 )
+ nBlue = 0;
+ if ( nBlue > 255 )
+ nBlue = 255;
+
+ aBitmap.SetPixel(nY, nX, Color(static_cast<sal_Int8>(nRed), static_cast<sal_Int8>(nGreen), static_cast<sal_Int8>(nBlue)));
+ }
+ }
+ BitmapEx aBitmapEx = vcl::bitmap::CreateFromData( std::move(aBitmap) );
+
+ if ( nFix16Angle )
+ {
+ bool bRotateWithShape = true; // sal_True seems to be default
+ sal_uInt64 nPos = rIn.Tell();
+ if ( const_cast< SvxMSDffManager& >( rManager ).maShapeRecords.SeekToContent( rIn, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART ) )
+ {
+ const_cast< SvxMSDffManager& >( rManager ).maShapeRecords.Current()->SeekToBegOfRecord( rIn );
+ DffPropertyReader aSecPropSet( rManager );
+ aSecPropSet.ReadPropSet( rIn, nullptr );
+ sal_Int32 nSecFillProperties = aSecPropSet.GetPropertyValue( DFF_Prop_fNoFillHitTest, 0x200020 );
+ bRotateWithShape = ( nSecFillProperties & 0x0020 );
+ }
+ rIn.Seek( nPos );
+ if ( bRotateWithShape )
+ {
+ // convert from 100th to 10th degrees
+ aBitmapEx.Rotate( to<Degree10>(nFix16Angle), rShadeColors[ 0 ].aColor );
+
+ BmpMirrorFlags nMirrorFlags = BmpMirrorFlags::NONE;
+ if ( rObjData.nSpFlags & ShapeFlag::FlipV )
+ nMirrorFlags |= BmpMirrorFlags::Vertical;
+ if ( rObjData.nSpFlags & ShapeFlag::FlipH )
+ nMirrorFlags |= BmpMirrorFlags::Horizontal;
+ if ( nMirrorFlags != BmpMirrorFlags::NONE )
+ aBitmapEx.Mirror( nMirrorFlags );
+ }
+ }
+
+ rSet.Put(XFillBmpTileItem(false));
+ rSet.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx)));
+}
+
+void DffPropertyReader::ApplyFillAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const
+{
+ sal_uInt32 nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ));
+
+ std::vector< ShadeColor > aShadeColors;
+ GetShadeColors( rManager, *this, rIn, aShadeColors );
+
+ if(!IsHardAttribute( DFF_Prop_fFilled ) && !IsCustomShapeFilledByDefault( rObjData.eShapeType ))
+ {
+ nFillFlags &= ~0x10;
+ }
+
+ if ( nFillFlags & 0x10 )
+ {
+ auto eMSO_FillType = GetPropertyValue(DFF_Prop_fillType, mso_fillSolid);
+ drawing::FillStyle eXFill = drawing::FillStyle_NONE;
+ switch( eMSO_FillType )
+ {
+ case mso_fillSolid : // Fill with a solid color
+ eXFill = drawing::FillStyle_SOLID;
+ break;
+ case mso_fillPattern : // Fill with a pattern (bitmap)
+ case mso_fillTexture : // A texture (pattern with its own color map)
+ case mso_fillPicture : // Center a picture in the shape
+ eXFill = drawing::FillStyle_BITMAP;
+ break;
+ case mso_fillShadeCenter : // Shade from bounding rectangle to end point
+ {
+ //If it is imported as a bitmap, it will not work well with transparency especially 100
+ //But the gradient look well comparing with imported as gradient. And rotate with shape
+ //also works better. So here just keep it.
+ if ( rObjData.aBoundRect.IsEmpty() )// size of object needed to be able
+ eXFill = drawing::FillStyle_GRADIENT; // to create a bitmap substitution
+ else
+ eXFill = drawing::FillStyle_BITMAP;
+ }
+ break;
+ case mso_fillShade : // Shade from start to end points
+ case mso_fillShadeShape : // Shade from shape outline to end point
+ case mso_fillShadeScale : // Similar to mso_fillShade, but the fillAngle
+ case mso_fillShadeTitle : // special type - shade to title --- for PP
+ eXFill = drawing::FillStyle_GRADIENT;
+ break;
+// case mso_fillBackground : // Use the background fill color/pattern
+ default: break;
+ }
+ rSet.Put( XFillStyleItem( eXFill ) );
+
+ double dTrans = 1.0;
+ double dBackTrans = 1.0;
+ if (IsProperty(DFF_Prop_fillOpacity))
+ {
+ dTrans = GetPropertyValue(DFF_Prop_fillOpacity, 0) / 65536.0;
+ if ( eXFill != drawing::FillStyle_GRADIENT )
+ {
+ dTrans = dTrans * 100;
+ rSet.Put(XFillTransparenceItem(
+ sal_uInt16(100 - ::rtl::math::round(dTrans))));
+ }
+ }
+
+ if ( IsProperty(DFF_Prop_fillBackOpacity) )
+ dBackTrans = GetPropertyValue(DFF_Prop_fillBackOpacity, 0) / 65536.0;
+
+ if ( ( eMSO_FillType == mso_fillShadeCenter ) && ( eXFill == drawing::FillStyle_BITMAP ) )
+ {
+ ApplyRectangularGradientAsBitmap( rManager, rIn, rSet, aShadeColors, rObjData, mnFix16Angle );
+ }
+ else if ( eXFill == drawing::FillStyle_GRADIENT )
+ {
+ ImportGradientColor ( rSet, eMSO_FillType, dTrans , dBackTrans );
+ }
+ else if ( eXFill == drawing::FillStyle_BITMAP )
+ {
+ if( IsProperty( DFF_Prop_fillBlip ) )
+ {
+ Graphic aGraf;
+ // first try to get BLIP from cache
+ bool bOK = const_cast<SvxMSDffManager&>(rManager).GetBLIP( GetPropertyValue( DFF_Prop_fillBlip, 0 ), aGraf );
+ // then try directly from stream (i.e. Excel chart hatches/bitmaps)
+ if ( !bOK )
+ bOK = SeekToContent( DFF_Prop_fillBlip, rIn ) && SvxMSDffManager::GetBLIPDirect( rIn, aGraf );
+ if ( bOK )
+ {
+ if ( eMSO_FillType == mso_fillPattern )
+ {
+ Bitmap aBmp( aGraf.GetBitmapEx().GetBitmap() );
+ if (aBmp.GetSizePixel().Width() == 8 &&
+ aBmp.GetSizePixel().Height() == 8 &&
+ aBmp.getPixelFormat() == vcl::PixelFormat::N1_BPP)
+ {
+ Color aCol1( COL_WHITE ), aCol2( COL_WHITE );
+
+ if ( IsProperty( DFF_Prop_fillColor ) )
+ aCol1 = rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor, 0 ), DFF_Prop_fillColor );
+
+ if ( IsProperty( DFF_Prop_fillBackColor ) )
+ aCol2 = rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor, 0 ), DFF_Prop_fillBackColor );
+
+ // Create a bitmap for the pattern with expected colors
+ vcl::bitmap::RawBitmap aResult(Size(8, 8), 24);
+ {
+ Bitmap::ScopedReadAccess pRead(aBmp);
+
+ for (tools::Long y = 0; y < aResult.Height(); ++y)
+ {
+ Scanline pScanlineRead = pRead->GetScanline( y );
+ for (tools::Long x = 0; x < aResult.Width(); ++x)
+ {
+ Color aReadColor;
+ if (pRead->HasPalette())
+ aReadColor = pRead->GetPaletteColor(pRead->GetIndexFromData(pScanlineRead, x));
+ else
+ aReadColor = pRead->GetPixelFromData(pScanlineRead, x);
+
+ if (aReadColor == Color(0))
+ aResult.SetPixel(y, x, aCol2);
+ else
+ aResult.SetPixel(y, x, aCol1);
+ }
+ }
+ }
+ aGraf = Graphic(vcl::bitmap::CreateFromData(std::move(aResult)));
+ }
+
+ rSet.Put(XFillBitmapItem(OUString(), aGraf));
+ }
+ else if ( eMSO_FillType == mso_fillTexture )
+ {
+ rSet.Put(XFillBmpTileItem(true));
+ rSet.Put(XFillBitmapItem(OUString(), aGraf));
+ rSet.Put(XFillBmpSizeXItem(GetPropertyValue(DFF_Prop_fillWidth, 0) / 360));
+ rSet.Put(XFillBmpSizeYItem(GetPropertyValue(DFF_Prop_fillHeight, 0) / 360));
+ rSet.Put(XFillBmpSizeLogItem(true));
+ }
+ else
+ {
+ rSet.Put(XFillBitmapItem(OUString(), aGraf));
+ rSet.Put(XFillBmpTileItem(false));
+ }
+ }
+ }
+ }
+ }
+ else
+ rSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
+}
+
+void DffPropertyReader::ApplyCustomShapeTextAttributes( SfxItemSet& rSet ) const
+{
+ bool bVerticalText = false;
+ sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 25 * 3600 ) / 360; // 0.25 cm (emu)
+ sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 25 * 3600 ) / 360; // 0.25 cm (emu)
+ sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 13 * 3600 ) / 360; // 0.13 cm (emu)
+ sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 13 * 3600 ) /360; // 0.13 cm (emu)
+
+ SdrTextVertAdjust eTVA;
+ SdrTextHorzAdjust eTHA;
+
+ if ( IsProperty( DFF_Prop_txflTextFlow ) )
+ {
+ auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
+ switch( eTextFlow )
+ {
+ case mso_txflTtoBA : /* #68110# */ // Top to Bottom @-font, oben -> unten
+ case mso_txflTtoBN : // Top to Bottom non-@, oben -> unten
+ case mso_txflVertN : // Vertical, non-@, oben -> unten
+ bVerticalText = true; // nTextRotationAngle += 27000;
+ break;
+ default: break;
+ }
+ }
+ sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 );
+ if ( ( nFontDirection == 1 ) || ( nFontDirection == 3 ) )
+ bVerticalText = !bVerticalText;
+
+ if ( bVerticalText )
+ {
+ eTHA = SDRTEXTHORZADJUST_CENTER;
+
+ // read text anchor
+ sal_uInt32 eTextAnchor = GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
+
+ switch( eTextAnchor )
+ {
+ case mso_anchorTop:
+ case mso_anchorTopCentered:
+ case mso_anchorTopBaseline:
+ case mso_anchorTopCenteredBaseline:
+ eTHA = SDRTEXTHORZADJUST_RIGHT;
+ break;
+
+ case mso_anchorMiddle :
+ case mso_anchorMiddleCentered:
+ eTHA = SDRTEXTHORZADJUST_CENTER;
+ break;
+
+ case mso_anchorBottom:
+ case mso_anchorBottomCentered:
+ case mso_anchorBottomBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ eTHA = SDRTEXTHORZADJUST_LEFT;
+ break;
+ }
+ // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction
+ switch ( eTextAnchor )
+ {
+ case mso_anchorTopCentered :
+ case mso_anchorMiddleCentered :
+ case mso_anchorBottomCentered :
+ case mso_anchorTopCenteredBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+ break;
+
+ default :
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ break;
+ }
+ }
+ else
+ {
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+
+ // read text anchor
+ sal_uInt32 eTextAnchor = GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
+
+ switch( eTextAnchor )
+ {
+ case mso_anchorTop:
+ case mso_anchorTopCentered:
+ case mso_anchorTopBaseline:
+ case mso_anchorTopCenteredBaseline:
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ break;
+
+ case mso_anchorMiddle :
+ case mso_anchorMiddleCentered:
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+ break;
+
+ case mso_anchorBottom:
+ case mso_anchorBottomCentered:
+ case mso_anchorBottomBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ break;
+ }
+ // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction
+ switch ( eTextAnchor )
+ {
+ case mso_anchorTopCentered :
+ case mso_anchorMiddleCentered :
+ case mso_anchorBottomCentered :
+ case mso_anchorTopCenteredBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ eTHA = SDRTEXTHORZADJUST_CENTER; // the text has to be displayed using the full width;
+ break;
+
+ default :
+ eTHA = SDRTEXTHORZADJUST_LEFT;
+ break;
+ }
+ }
+ rSet.Put( SvxFrameDirectionItem( bVerticalText ? SvxFrameDirection::Vertical_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
+
+ rSet.Put( SdrTextVertAdjustItem( eTVA ) );
+ rSet.Put( SdrTextHorzAdjustItem( eTHA ) );
+
+ rSet.Put( makeSdrTextLeftDistItem( nTextLeft ) );
+ rSet.Put( makeSdrTextRightDistItem( nTextRight ) );
+ rSet.Put( makeSdrTextUpperDistItem( nTextTop ) );
+ rSet.Put( makeSdrTextLowerDistItem( nTextBottom ) );
+
+ rSet.Put( makeSdrTextWordWrapItem( GetPropertyValue(DFF_Prop_WrapText, mso_wrapSquare) != mso_wrapNone ) );
+ rSet.Put( makeSdrTextAutoGrowHeightItem( ( GetPropertyValue( DFF_Prop_FitTextToShape, 0 ) & 2 ) != 0 ) );
+}
+
+void DffPropertyReader::ApplyCustomShapeGeometryAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const
+{
+
+ sal_uInt32 nAdjustmentsWhichNeedsToBeConverted = 0;
+
+
+ // creating SdrCustomShapeGeometryItem
+
+ typedef std::vector< beans::PropertyValue > PropVec;
+
+ // aPropVec will be filled with all PropertyValues
+ PropVec aPropVec;
+ PropertyValue aProp;
+
+
+ // "Type" property, including the predefined CustomShape type name
+
+ aProp.Name = "Type";
+ aProp.Value <<= EnhancedCustomShapeTypeNames::Get( rObjData.eShapeType );
+ aPropVec.push_back( aProp );
+
+
+ // "ViewBox"
+
+
+ sal_Int32 nCoordWidth = 21600; // needed to replace handle type center with absolute value
+ sal_Int32 nCoordHeight= 21600;
+ if ( IsProperty( DFF_Prop_geoLeft ) || IsProperty( DFF_Prop_geoTop ) || IsProperty( DFF_Prop_geoRight ) || IsProperty( DFF_Prop_geoBottom ) )
+ {
+ css::awt::Rectangle aViewBox;
+ aViewBox.X = GetPropertyValue( DFF_Prop_geoLeft, 0 );
+ aViewBox.Y = GetPropertyValue( DFF_Prop_geoTop, 0 );
+ aViewBox.Width = nCoordWidth = o3tl::saturating_sub<sal_Int32>(GetPropertyValue(DFF_Prop_geoRight, 21600), aViewBox.X);
+ aViewBox.Height = nCoordHeight = o3tl::saturating_sub<sal_Int32>(GetPropertyValue(DFF_Prop_geoBottom, 21600), aViewBox.Y);
+ aProp.Name = "ViewBox";
+ aProp.Value <<= aViewBox;
+ aPropVec.push_back( aProp );
+ }
+
+ // TextRotateAngle
+
+ if ( IsProperty( DFF_Prop_txflTextFlow ) || IsProperty( DFF_Prop_cdirFont ) )
+ {
+ sal_Int32 nTextRotateAngle = 0;
+ auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
+
+ if ( eTextFlow == mso_txflBtoT ) // Bottom to Top non-@
+ nTextRotateAngle += 90;
+ switch( GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 ) ) // SJ: mso_cdir90 and mso_cdir270 will be simulated by
+ { // activating vertical writing for the text objects
+ case mso_cdir90 :
+ {
+ if ( eTextFlow == mso_txflTtoBA )
+ nTextRotateAngle -= 180;
+ }
+ break;
+ case mso_cdir180: nTextRotateAngle -= 180; break;
+ case mso_cdir270:
+ {
+ if ( eTextFlow != mso_txflTtoBA )
+ nTextRotateAngle -= 180;
+ }
+ break;
+ default: break;
+ }
+ if ( nTextRotateAngle )
+ {
+ double fTextRotateAngle = nTextRotateAngle;
+ aProp.Name = "TextRotateAngle";
+ aProp.Value <<= fTextRotateAngle;
+ aPropVec.push_back( aProp );
+ }
+ }
+
+ // "Extrusion" PropertySequence element
+
+ bool bExtrusionOn = ( GetPropertyValue( DFF_Prop_fc3DLightFace, 0 ) & 8 ) != 0;
+ if ( bExtrusionOn )
+ {
+ PropVec aExtrusionPropVec;
+
+ // "Extrusion"
+ aProp.Name = "Extrusion";
+ aProp.Value <<= bExtrusionOn;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "Brightness"
+ // MS Office default 0x00004E20 16.16 FixedPoint, 20000/65536=0.30517, ODF default 33%.
+ // Thus must set value even if default.
+ double fBrightness = 20000.0;
+ if ( IsProperty( DFF_Prop_c3DAmbientIntensity ) )
+ {
+ // Value must be in range 0.0 to 1.0 in MS Office binary specification, but larger
+ // values are in fact interpreted.
+ fBrightness = GetPropertyValue( DFF_Prop_c3DAmbientIntensity, 0 );
+ }
+ fBrightness /= 655.36;
+ aProp.Name = "Brightness";
+ aProp.Value <<= fBrightness;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "Depth" in 1/100mm
+ if ( IsProperty( DFF_Prop_c3DExtrudeBackward ) || IsProperty( DFF_Prop_c3DExtrudeForward ) )
+ {
+ double fBackDepth = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DExtrudeBackward, 1270 * 360 ))) / 360.0;
+ double fForeDepth = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DExtrudeForward, 0 ))) / 360.0;
+ double fDepth = fBackDepth + fForeDepth;
+ double fFraction = fDepth != 0.0 ? fForeDepth / fDepth : 0;
+ EnhancedCustomShapeParameterPair aDepthParaPair;
+ aDepthParaPair.First.Value <<= fDepth;
+ aDepthParaPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
+ aDepthParaPair.Second.Value <<= fFraction;
+ aDepthParaPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
+ aProp.Name = "Depth";
+ aProp.Value <<= aDepthParaPair;
+ aExtrusionPropVec.push_back( aProp );
+ }
+ // "Diffusion"
+ // ODF default is 0%, MS Office default is 100%. Thus must set value even if default.
+ double fDiffusion = 100;
+ if ( IsProperty( DFF_Prop_c3DDiffuseAmt ) )
+ {
+ fDiffusion = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DDiffuseAmt, 0 ));
+ fDiffusion /= 655.36;
+ }
+ aProp.Name = "Diffusion";
+ aProp.Value <<= fDiffusion;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "NumberOfLineSegments"
+ if ( IsProperty( DFF_Prop_c3DTolerance ) )
+ {
+ aProp.Name = "NumberOfLineSegments";
+ aProp.Value <<= static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DTolerance, 0 ));
+ aExtrusionPropVec.push_back( aProp );
+ }
+ // "LightFace"
+ bool bExtrusionLightFace = ( GetPropertyValue( DFF_Prop_fc3DLightFace, 0 ) & 1 ) != 0;
+ aProp.Name = "LightFace";
+ aProp.Value <<= bExtrusionLightFace;
+ aExtrusionPropVec.push_back( aProp );
+ // "FirstLightHarsh"
+ bool bExtrusionFirstLightHarsh = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh, 0 ) & 2 ) != 0;
+ aProp.Name = "FirstLightHarsh";
+ aProp.Value <<= bExtrusionFirstLightHarsh;
+ aExtrusionPropVec.push_back( aProp );
+ // "SecondLightHarsh"
+ bool bExtrusionSecondLightHarsh = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh, 0 ) & 1 ) != 0;
+ aProp.Name = "SecondLightHarsh";
+ aProp.Value <<= bExtrusionSecondLightHarsh;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "FirstLightLevel"
+ // MS Office default 0x00009470 16.16 FixedPoint, 38000/65536 = 0.5798, ODF default 66%.
+ // Thus must set value even if default.
+ double fFirstLightLevel = 38000.0;
+ if ( IsProperty( DFF_Prop_c3DKeyIntensity ) )
+ {
+ // value<0 and value>1 are allowed in MS Office. Clamp such in ODF export, not here.
+ fFirstLightLevel = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyIntensity, 0 ));
+ }
+ fFirstLightLevel /= 655.36;
+ aProp.Name = "FirstLightLevel";
+ aProp.Value <<= fFirstLightLevel;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "SecondLightLevel"
+ // MS Office default 0x00009470 16.16 FixedPoint, 38000/65536 = 0.5798, ODF default 66%.
+ // Thus must set value even if default.
+ double fSecondLightLevel = 38000.0;
+ if ( IsProperty( DFF_Prop_c3DFillIntensity ) )
+ {
+ // value<0 and value>1 are allowed in MS Office. Clamp such in ODF export, not here.
+ fSecondLightLevel = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillIntensity, 0 ));
+ }
+ fSecondLightLevel /= 655.36;
+ aProp.Name = "SecondLightLevel";
+ aProp.Value <<= fSecondLightLevel;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "FirstLightDirection"
+ if ( IsProperty( DFF_Prop_c3DKeyX ) || IsProperty( DFF_Prop_c3DKeyY ) || IsProperty( DFF_Prop_c3DKeyZ ) )
+ {
+ double fLightX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyX, 50000 )));
+ double fLightY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyY, 0 )));
+ double fLightZ = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyZ, 10000 )));
+ css::drawing::Direction3D aExtrusionFirstLightDirection( fLightX, fLightY, fLightZ );
+ aProp.Name = "FirstLightDirection";
+ aProp.Value <<= aExtrusionFirstLightDirection;
+ aExtrusionPropVec.push_back( aProp );
+ }
+ // "SecondLightDirection"
+ if ( IsProperty( DFF_Prop_c3DFillX ) || IsProperty( DFF_Prop_c3DFillY ) || IsProperty( DFF_Prop_c3DFillZ ) )
+ {
+ double fLight2X = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillX, sal_uInt32(-50000) )));
+ double fLight2Y = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillY, 0 )));
+ double fLight2Z = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillZ, 10000 )));
+ css::drawing::Direction3D aExtrusionSecondLightDirection( fLight2X, fLight2Y, fLight2Z );
+ aProp.Name = "SecondLightDirection";
+ aProp.Value <<= aExtrusionSecondLightDirection;
+ aExtrusionPropVec.push_back( aProp );
+ }
+
+ // "Metal"
+ bool bExtrusionMetal = ( GetPropertyValue( DFF_Prop_fc3DLightFace, 0 ) & 4 ) != 0;
+ aProp.Name = "Metal";
+ aProp.Value <<= bExtrusionMetal;
+ aExtrusionPropVec.push_back( aProp );
+ aProp.Name = "MetalType";
+ aProp.Value <<= css::drawing::EnhancedCustomShapeMetalType::MetalMSCompatible;
+ aExtrusionPropVec.push_back(aProp);
+
+ // "ShadeMode"
+ if ( IsProperty( DFF_Prop_c3DRenderMode ) )
+ {
+ sal_uInt32 nExtrusionRenderMode = GetPropertyValue( DFF_Prop_c3DRenderMode, 0 );
+ css::drawing::ShadeMode eExtrusionShadeMode( css::drawing::ShadeMode_FLAT );
+ if ( nExtrusionRenderMode == mso_Wireframe )
+ eExtrusionShadeMode = css::drawing::ShadeMode_DRAFT;
+
+ aProp.Name = "ShadeMode";
+ aProp.Value <<= eExtrusionShadeMode;
+ aExtrusionPropVec.push_back( aProp );
+ }
+ // "RotateAngle" in Degree
+ if ( IsProperty( DFF_Prop_c3DXRotationAngle ) || IsProperty( DFF_Prop_c3DYRotationAngle ) )
+ {
+ double fAngleX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DXRotationAngle, 0 ))) / 65536.0;
+ double fAngleY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DYRotationAngle, 0 ))) / 65536.0;
+ EnhancedCustomShapeParameterPair aRotateAnglePair;
+ aRotateAnglePair.First.Value <<= fAngleX;
+ aRotateAnglePair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
+ aRotateAnglePair.Second.Value <<= fAngleY;
+ aRotateAnglePair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
+ aProp.Name = "RotateAngle";
+ aProp.Value <<= aRotateAnglePair;
+ aExtrusionPropVec.push_back( aProp );
+ }
+
+ // "AutoRotationCenter"
+ if ( ( GetPropertyValue( DFF_Prop_fc3DFillHarsh, 0 ) & 8 ) == 0 )
+ {
+ // "RotationCenter"
+ if ( IsProperty( DFF_Prop_c3DRotationCenterX ) || IsProperty( DFF_Prop_c3DRotationCenterY ) || IsProperty( DFF_Prop_c3DRotationCenterZ ) )
+ {
+ // tdf#145904 X- and Y-component is fraction, Z-component in EMU
+ css::drawing::Direction3D aRotationCenter(
+ static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterX, 0 ))) / 65536.0,
+ static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterY, 0 ))) / 65536.0,
+ static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterZ, 0 ))) / 360.0 );
+
+ aProp.Name = "RotationCenter";
+ aProp.Value <<= aRotationCenter;
+ aExtrusionPropVec.push_back( aProp );
+ }
+ }
+ // "Shininess"
+ // MS Office default 5, ODF default 50%.
+ if ( IsProperty( DFF_Prop_c3DShininess ) )
+ {
+ double fShininess = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DShininess, 0 ));
+ fShininess *= 10.0; // error in [MS ODRAW] (2021), type is not FixedPoint but long.
+ aProp.Name = "Shininess";
+ aProp.Value <<= fShininess;
+ aExtrusionPropVec.push_back( aProp );
+ }
+
+ // "Skew"
+ // MS Office angle file value is 16.16 FixedPoint, default 0xFF790000,
+ // -8847360/65536=-135, ODF default 45. Thus must set value even if default.
+ double fSkewAngle = -135.0;
+ // MS Office amount file value is signed integer in range 0xFFFFFF9C to 0x00000064,
+ // default 0x00000032, ODF default 50.0
+ double fSkewAmount = 50.0;
+ if ( IsProperty( DFF_Prop_c3DSkewAmount ) || IsProperty( DFF_Prop_c3DSkewAngle ) )
+ {
+ fSkewAmount = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSkewAmount, 50 ));
+ fSkewAngle = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSkewAngle, sal::static_int_cast< sal_uInt32 >(-135 * 65536) ));
+ fSkewAngle /= 65536.0;
+ }
+ EnhancedCustomShapeParameterPair aSkewPair;
+ aSkewPair.First.Value <<= fSkewAmount;
+ aSkewPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
+ aSkewPair.Second.Value <<= fSkewAngle;
+ aSkewPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
+ aProp.Name = "Skew";
+ aProp.Value <<= aSkewPair;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "Specularity"
+ // Type Fixed point 16.16, percent in API
+ if ( IsProperty( DFF_Prop_c3DSpecularAmt ) )
+ {
+ double fSpecularity = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSpecularAmt, 0 ));
+ fSpecularity /= 655.36;
+ aProp.Name = "Specularity";
+ aProp.Value <<= fSpecularity;
+ aExtrusionPropVec.push_back( aProp );
+ }
+ // "ProjectionMode"
+ ProjectionMode eProjectionMode = (GetPropertyValue( DFF_Prop_fc3DFillHarsh, 0 ) & 4) ? ProjectionMode_PARALLEL : ProjectionMode_PERSPECTIVE;
+ aProp.Name = "ProjectionMode";
+ aProp.Value <<= eProjectionMode;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "ViewPoint" in 1/100mm
+ // MS Office default 1250000 EMU=3472.222 Hmm, ODF default 3.5cm
+ // Thus must set value even if default.
+ double fViewX = 1250000.0 / 360.0;
+ double fViewY = -1250000.0 / 360.0;;
+ double fViewZ = 9000000.0 / 360.0;
+ if ( IsProperty( DFF_Prop_c3DXViewpoint ) || IsProperty( DFF_Prop_c3DYViewpoint ) || IsProperty( DFF_Prop_c3DZViewpoint ) )
+ {
+ fViewX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DXViewpoint, 1250000 ))) / 360.0;
+ fViewY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DYViewpoint, sal_uInt32(-1250000) )))/ 360.0;
+ fViewZ = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DZViewpoint, 9000000 ))) / 360.0;
+ }
+ css::drawing::Position3D aExtrusionViewPoint( fViewX, fViewY, fViewZ );
+ aProp.Name = "ViewPoint";
+ aProp.Value <<= aExtrusionViewPoint;
+ aExtrusionPropVec.push_back( aProp );
+
+ // "Origin"
+ if ( IsProperty( DFF_Prop_c3DOriginX ) || IsProperty( DFF_Prop_c3DOriginY ) )
+ {
+ double fOriginX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DOriginX, 32768 )));
+ double fOriginY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DOriginY, sal_uInt32(-32768) )));
+ fOriginX /= 65536;
+ fOriginY /= 65536;
+ EnhancedCustomShapeParameterPair aOriginPair;
+ aOriginPair.First.Value <<= fOriginX;
+ aOriginPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
+ aOriginPair.Second.Value <<= fOriginY;
+ aOriginPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
+ aProp.Name = "Origin";
+ aProp.Value <<= aOriginPair;
+ aExtrusionPropVec.push_back( aProp );
+ }
+ // "ExtrusionColor"
+ bool bExtrusionColor = IsProperty( DFF_Prop_c3DExtrusionColor ); // ( GetPropertyValue( DFF_Prop_fc3DLightFace ) & 2 ) != 0;
+ aProp.Name = "Color";
+ aProp.Value <<= bExtrusionColor;
+ aExtrusionPropVec.push_back( aProp );
+ if ( IsProperty( DFF_Prop_c3DExtrusionColor ) )
+ rSet.Put( XSecondaryFillColorItem( OUString(), rManager.MSO_CLR_ToColor(
+ GetPropertyValue( DFF_Prop_c3DExtrusionColor, 0 ), DFF_Prop_c3DExtrusionColor ) ) );
+ // pushing the whole Extrusion element
+ aProp.Name = "Extrusion";
+ aProp.Value <<= comphelper::containerToSequence(aExtrusionPropVec);
+ aPropVec.push_back( aProp );
+ }
+
+
+ // "Equations" PropertySequence element
+
+ if ( IsProperty( DFF_Prop_pFormulas ) )
+ {
+ sal_uInt16 nNumElem = 0;
+
+ if ( SeekToContent( DFF_Prop_pFormulas, rIn ) )
+ {
+ sal_uInt16 nNumElemMem = 0;
+ sal_uInt16 nElemSize = 8;
+ rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
+ }
+ if ( nNumElem <= 128 )
+ {
+ uno::Sequence< OUString > aEquations( nNumElem );
+ for ( auto& rEquation : asNonConstRange(aEquations) )
+ {
+ sal_Int16 nP1(0), nP2(0), nP3(0);
+ sal_uInt16 nFlags(0);
+ rIn.ReadUInt16( nFlags ).ReadInt16( nP1 ).ReadInt16( nP2 ).ReadInt16( nP3 );
+ rEquation = EnhancedCustomShape2d::GetEquation( nFlags, nP1, nP2, nP3 );
+ }
+ // pushing the whole Equations element
+ aProp.Name = "Equations";
+ aProp.Value <<= aEquations;
+ aPropVec.push_back( aProp );
+ }
+ }
+
+
+ // "Handles" PropertySequence element
+
+ if ( IsProperty( DFF_Prop_Handles ) )
+ {
+ sal_uInt16 nNumElem = 0;
+ sal_uInt16 nElemSize = 36;
+
+ if ( SeekToContent( DFF_Prop_Handles, rIn ) )
+ {
+ sal_uInt16 nNumElemMem = 0;
+ rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
+ }
+ bool bImport = false;
+ if (nElemSize == 36)
+ {
+ //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
+ bImport = rIn.remainingSize() / nElemSize >= nNumElem;
+ }
+ if (bImport)
+ {
+ uno::Sequence< beans::PropertyValues > aHandles( nNumElem );
+ auto aHandlesRange = asNonConstRange(aHandles);
+ for (sal_uInt32 i = 0; i < nNumElem; ++i)
+ {
+ PropVec aHandlePropVec;
+ sal_uInt32 nFlagsTmp(0);
+ sal_Int32 nPositionX(0), nPositionY(0), nCenterX(0), nCenterY(0), nRangeXMin(0), nRangeXMax(0), nRangeYMin(0), nRangeYMax(0);
+ rIn.ReadUInt32( nFlagsTmp )
+ .ReadInt32( nPositionX )
+ .ReadInt32( nPositionY )
+ .ReadInt32( nCenterX )
+ .ReadInt32( nCenterY )
+ .ReadInt32( nRangeXMin )
+ .ReadInt32( nRangeXMax )
+ .ReadInt32( nRangeYMin )
+ .ReadInt32( nRangeYMax );
+ SvxMSDffHandleFlags nFlags = static_cast<SvxMSDffHandleFlags>(nFlagsTmp);
+ if ( nPositionX == 2 ) // replacing center position with absolute value
+ nPositionX = nCoordWidth / 2;
+ if ( nPositionY == 2 )
+ nPositionY = nCoordHeight / 2;
+ EnhancedCustomShapeParameterPair aPosition;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First, nPositionX, true, true );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, nPositionY, true, false );
+ aProp.Name = "Position";
+ aProp.Value <<= aPosition;
+ aHandlePropVec.push_back( aProp );
+
+ if ( nFlags & SvxMSDffHandleFlags::MIRRORED_X )
+ {
+ aProp.Name = "MirroredX";
+ aProp.Value <<= true;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( nFlags & SvxMSDffHandleFlags::MIRRORED_Y )
+ {
+ aProp.Name = "MirroredY";
+ aProp.Value <<= true;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( nFlags & SvxMSDffHandleFlags::SWITCHED )
+ {
+ aProp.Name = "Switched";
+ aProp.Value <<= true;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( nFlags & SvxMSDffHandleFlags::POLAR )
+ {
+ if ( nCenterX == 2 )
+ nCenterX = nCoordWidth / 2;
+ if ( nCenterY == 2 )
+ nCenterY = nCoordHeight / 2;
+ if ((nPositionY >= 0x256 || nPositionY <= 0x107) && i < sizeof(sal_uInt32) * 8) // position y
+ nAdjustmentsWhichNeedsToBeConverted |= ( 1U << i );
+ EnhancedCustomShapeParameterPair aPolar;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar.First, nCenterX, bool( nFlags & SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL ), true );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar.Second, nCenterY, bool( nFlags & SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL ), false );
+ aProp.Name = "Polar";
+ aProp.Value <<= aPolar;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( nFlags & SvxMSDffHandleFlags::MAP )
+ {
+ if ( nCenterX == 2 )
+ nCenterX = nCoordWidth / 2;
+ if ( nCenterY == 2 )
+ nCenterY = nCoordHeight / 2;
+ EnhancedCustomShapeParameterPair aMap;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap.First, nCenterX, bool( nFlags & SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL ), true );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap.Second, nCenterY, bool( nFlags & SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL ), false );
+ aProp.Name = "Map";
+ aProp.Value <<= aMap;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( nFlags & SvxMSDffHandleFlags::RANGE )
+ {
+ if ( static_cast<sal_uInt32>(nRangeXMin) != 0x80000000 )
+ {
+ if ( nRangeXMin == 2 )
+ nRangeXMin = nCoordWidth / 2;
+ EnhancedCustomShapeParameter aRangeXMinimum;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum, nRangeXMin,
+ bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true );
+ aProp.Name = "RangeXMinimum";
+ aProp.Value <<= aRangeXMinimum;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( static_cast<sal_uInt32>(nRangeXMax) != 0x7fffffff )
+ {
+ if ( nRangeXMax == 2 )
+ nRangeXMax = nCoordWidth / 2;
+ EnhancedCustomShapeParameter aRangeXMaximum;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, nRangeXMax,
+ bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false );
+ aProp.Name = "RangeXMaximum";
+ aProp.Value <<= aRangeXMaximum;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( static_cast<sal_uInt32>(nRangeYMin) != 0x80000000 )
+ {
+ if ( nRangeYMin == 2 )
+ nRangeYMin = nCoordHeight / 2;
+ EnhancedCustomShapeParameter aRangeYMinimum;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, nRangeYMin,
+ bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MIN_IS_SPECIAL ), true );
+ aProp.Name = "RangeYMinimum";
+ aProp.Value <<= aRangeYMinimum;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( static_cast<sal_uInt32>(nRangeYMax) != 0x7fffffff )
+ {
+ if ( nRangeYMax == 2 )
+ nRangeYMax = nCoordHeight / 2;
+ EnhancedCustomShapeParameter aRangeYMaximum;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, nRangeYMax,
+ bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MAX_IS_SPECIAL ), false );
+ aProp.Name = "RangeYMaximum";
+ aProp.Value <<= aRangeYMaximum;
+ aHandlePropVec.push_back( aProp );
+ }
+ }
+ if ( nFlags & SvxMSDffHandleFlags::RADIUS_RANGE )
+ {
+ if ( static_cast<sal_uInt32>(nRangeXMin) != 0x7fffffff )
+ {
+ if ( nRangeXMin == 2 )
+ nRangeXMin = nCoordWidth / 2;
+ EnhancedCustomShapeParameter aRadiusRangeMinimum;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, nRangeXMin,
+ bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true );
+ aProp.Name = "RadiusRangeMinimum";
+ aProp.Value <<= aRadiusRangeMinimum;
+ aHandlePropVec.push_back( aProp );
+ }
+ if ( static_cast<sal_uInt32>(nRangeXMax) != 0x80000000 )
+ {
+ if ( nRangeXMax == 2 )
+ nRangeXMax = nCoordWidth / 2;
+ EnhancedCustomShapeParameter aRadiusRangeMaximum;
+ EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, nRangeXMax,
+ bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false );
+ aProp.Name = "RadiusRangeMaximum";
+ aProp.Value <<= aRadiusRangeMaximum;
+ aHandlePropVec.push_back( aProp );
+ }
+ }
+ if ( !aHandlePropVec.empty() )
+ {
+ aHandlesRange[ i ] = comphelper::containerToSequence(aHandlePropVec);
+ }
+ }
+ // pushing the whole Handles element
+ aProp.Name = "Handles";
+ aProp.Value <<= aHandles;
+ aPropVec.push_back( aProp );
+ }
+ }
+ else
+ {
+ const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( rObjData.eShapeType );
+ if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
+ {
+ sal_uInt32 i, nCnt = pDefCustomShape->nHandles;
+ const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
+ for ( i = 0; i < nCnt; i++, pData++ )
+ {
+ if ( pData->nFlags & SvxMSDffHandleFlags::POLAR )
+ {
+ if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) )
+ nAdjustmentsWhichNeedsToBeConverted |= ( 1U << i );
+ }
+ }
+ }
+ }
+
+ // "Path" PropertySequence element
+
+ {
+ PropVec aPathPropVec;
+
+ // "Path/ExtrusionAllowed"
+ if ( IsHardAttribute( DFF_Prop_f3DOK ) )
+ {
+ bool bExtrusionAllowed = ( GetPropertyValue( DFF_Prop_fFillOK, 0 ) & 16 ) != 0;
+ aProp.Name = "ExtrusionAllowed";
+ aProp.Value <<= bExtrusionAllowed;
+ aPathPropVec.push_back( aProp );
+ }
+ // "Path/ConcentricGradientFillAllowed"
+ if ( IsHardAttribute( DFF_Prop_fFillShadeShapeOK ) )
+ {
+ bool bConcentricGradientFillAllowed = ( GetPropertyValue( DFF_Prop_fFillOK, 0 ) & 2 ) != 0;
+ aProp.Name = "ConcentricGradientFillAllowed";
+ aProp.Value <<= bConcentricGradientFillAllowed;
+ aPathPropVec.push_back( aProp );
+ }
+ // "Path/TextPathAllowed"
+ if ( IsHardAttribute( DFF_Prop_fGtextOK ) || ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x4000 ) )
+ {
+ bool bTextPathAllowed = ( GetPropertyValue( DFF_Prop_fFillOK, 0 ) & 4 ) != 0;
+ aProp.Name = "TextPathAllowed";
+ aProp.Value <<= bTextPathAllowed;
+ aPathPropVec.push_back( aProp );
+ }
+ // Path/Coordinates
+ if ( IsProperty( DFF_Prop_pVertices ) )
+ {
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
+ sal_uInt16 nNumElemVert = 0;
+ sal_uInt16 nElemSizeVert = 8;
+
+ if ( SeekToContent( DFF_Prop_pVertices, rIn ) )
+ {
+ sal_uInt16 nNumElemMemVert = 0;
+ rIn.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
+ // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
+ // low-order bytes are recorded
+ if (nElemSizeVert == 0xFFF0)
+ nElemSizeVert = 4;
+ }
+ //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
+ bool bImport = nElemSizeVert && (rIn.remainingSize() / nElemSizeVert >= nNumElemVert);
+ if (bImport)
+ {
+ aCoordinates.realloc( nNumElemVert );
+ for (auto& rCoordinate : asNonConstRange(aCoordinates))
+ {
+ sal_Int32 nX(0), nY(0);
+
+ if ( nElemSizeVert == 8 )
+ {
+ rIn.ReadInt32( nX )
+ .ReadInt32( nY );
+ }
+ else
+ {
+ // The mso-spt19 (arc) uses this. But it needs unsigned integer. I don't
+ // know if other shape types also need it. They can be added as necessary.
+ bool bNeedsUnsigned = rObjData.eShapeType == mso_sptArc;
+ if (bNeedsUnsigned)
+ {
+ sal_uInt16 nTmpA(0), nTmpB(0);
+ rIn.ReadUInt16(nTmpA)
+ .ReadUInt16(nTmpB);
+ nX = nTmpA;
+ nY = nTmpB;
+ }
+ else
+ {
+ sal_Int16 nTmpA(0), nTmpB(0);
+ rIn.ReadInt16( nTmpA )
+ .ReadInt16( nTmpB );
+ nX = nTmpA;
+ nY = nTmpB;
+ }
+ }
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rCoordinate.First, nX );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rCoordinate.Second, nY );
+ }
+ }
+ aProp.Name = "Coordinates";
+ aProp.Value <<= aCoordinates;
+ aPathPropVec.push_back( aProp );
+ }
+ // Path/Segments
+ if ( IsProperty( DFF_Prop_pSegmentInfo ) )
+ {
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > aSegments;
+
+ sal_uInt16 nNumElemSeg = 0;
+
+ if ( SeekToContent( DFF_Prop_pSegmentInfo, rIn ) )
+ {
+ sal_uInt16 nNumElemMemSeg = 0;
+ sal_uInt16 nElemSizeSeg = 2;
+ rIn.ReadUInt16( nNumElemSeg ).ReadUInt16( nNumElemMemSeg ).ReadUInt16( nElemSizeSeg );
+ }
+ sal_uInt64 nMaxEntriesPossible = rIn.remainingSize() / sizeof(sal_uInt16);
+ if (nNumElemSeg > nMaxEntriesPossible)
+ {
+ SAL_WARN("filter.ms", "NumElem list is longer than remaining bytes, ppt or parser is wrong");
+ nNumElemSeg = nMaxEntriesPossible;
+ }
+ if ( nNumElemSeg )
+ {
+ aSegments.realloc( nNumElemSeg );
+ for (auto& rSegment : asNonConstRange(aSegments))
+ {
+ sal_uInt16 nTmp(0);
+ rIn.ReadUInt16( nTmp );
+ sal_Int16 nCommand = EnhancedCustomShapeSegmentCommand::UNKNOWN;
+ sal_Int16 nCnt = static_cast<sal_Int16>( nTmp & 0x1fff );//Last 13 bits for segment points number
+ switch( nTmp >> 13 )//First 3 bits for command type
+ {
+ case 0x0:
+ nCommand = EnhancedCustomShapeSegmentCommand::LINETO;
+ if ( !nCnt ) nCnt = 1;
+ break;
+ case 0x1:
+ nCommand = EnhancedCustomShapeSegmentCommand::CURVETO;
+ if ( !nCnt ) nCnt = 1;
+ break;
+ case 0x2:
+ nCommand = EnhancedCustomShapeSegmentCommand::MOVETO;
+ if ( !nCnt ) nCnt = 1;
+ break;
+ case 0x3:
+ nCommand = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
+ nCnt = 0;
+ break;
+ case 0x4:
+ nCommand = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
+ nCnt = 0;
+ break;
+ case 0x5:
+ case 0x6:
+ {
+ switch ( ( nTmp >> 8 ) & 0x1f )//5 bits next to command type is for path escape type
+ {
+ case 0x0:
+ {
+ //It is msopathEscapeExtension which is transformed into LINETO.
+ //If issue happens, I think this part can be comment so that it will be taken as unknown command.
+ //When export, origin data will be export without any change.
+ nCommand = EnhancedCustomShapeSegmentCommand::LINETO;
+ if ( !nCnt )
+ nCnt = 1;
+ }
+ break;
+ case 0x1:
+ {
+ nCommand = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
+ nCnt = ( nTmp & 0xff ) / 3;
+ }
+ break;
+ case 0x2:
+ {
+ nCommand = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
+ nCnt = ( nTmp & 0xff ) / 3;
+ }
+ break;
+ case 0x3:
+ {
+ nCommand = EnhancedCustomShapeSegmentCommand::ARCTO;
+ nCnt = ( nTmp & 0xff ) >> 2;
+ };
+ break;
+ case 0x4:
+ {
+ nCommand = EnhancedCustomShapeSegmentCommand::ARC;
+ nCnt = ( nTmp & 0xff ) >> 2;
+ }
+ break;
+ case 0x5:
+ {
+ nCommand = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
+ nCnt = ( nTmp & 0xff ) >> 2;
+ }
+ break;
+ case 0x6:
+ {
+ nCommand = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
+ nCnt = ( nTmp & 0xff ) >> 2;
+ }
+ break;
+ case 0x7:
+ {
+ nCommand = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
+ nCnt = nTmp & 0xff;
+ }
+ break;
+ case 0x8:
+ {
+ nCommand = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
+ nCnt = nTmp & 0xff;
+ }
+ break;
+ case 0xa: nCommand = EnhancedCustomShapeSegmentCommand::NOFILL; nCnt = 0; break;
+ case 0xb: nCommand = EnhancedCustomShapeSegmentCommand::NOSTROKE; nCnt = 0; break;
+ }
+ }
+ break;
+ }
+ // if the command is unknown, we will store all the data in nCnt, so it will be possible to export without loss
+ if ( nCommand == EnhancedCustomShapeSegmentCommand::UNKNOWN )
+ nCnt = static_cast<sal_Int16>(nTmp);
+ rSegment.Command = nCommand;
+ rSegment.Count = nCnt;
+ }
+ }
+ aProp.Name = "Segments";
+ aProp.Value <<= aSegments;
+ aPathPropVec.push_back( aProp );
+ }
+ // Path/StretchX
+ if ( IsProperty( DFF_Prop_stretchPointX ) )
+ {
+ sal_Int32 nStretchX = GetPropertyValue( DFF_Prop_stretchPointX, 0 );
+ aProp.Name = "StretchX";
+ aProp.Value <<= nStretchX;
+ aPathPropVec.push_back( aProp );
+ }
+ // Path/StretchX
+ if ( IsProperty( DFF_Prop_stretchPointY ) )
+ {
+ sal_Int32 nStretchY = GetPropertyValue( DFF_Prop_stretchPointY, 0 );
+ aProp.Name = "StretchY";
+ aProp.Value <<= nStretchY;
+ aPathPropVec.push_back( aProp );
+ }
+ // Path/TextFrames
+ if ( IsProperty( DFF_Prop_textRectangles ) )
+ {
+ sal_uInt16 nNumElem = 0;
+ sal_uInt16 nElemSize = 16;
+
+ if ( SeekToContent( DFF_Prop_textRectangles, rIn ) )
+ {
+ sal_uInt16 nNumElemMem = 0;
+ rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
+ }
+ bool bImport = false;
+ if (nElemSize == 16)
+ {
+ //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
+ bImport = rIn.remainingSize() / nElemSize >= nNumElem;
+ }
+ if (bImport)
+ {
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > aTextFrames( nNumElem );
+ for (auto& rTextFrame : asNonConstRange(aTextFrames))
+ {
+ sal_Int32 nLeft(0), nTop(0), nRight(0), nBottom(0);
+
+ rIn.ReadInt32( nLeft )
+ .ReadInt32( nTop )
+ .ReadInt32( nRight )
+ .ReadInt32( nBottom );
+
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rTextFrame.TopLeft.First, nLeft );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rTextFrame.TopLeft.Second, nTop );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rTextFrame.BottomRight.First, nRight );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rTextFrame.BottomRight.Second, nBottom);
+ }
+ aProp.Name = "TextFrames";
+ aProp.Value <<= aTextFrames;
+ aPathPropVec.push_back( aProp );
+ }
+ }
+ //Path/GluePoints
+ if ( IsProperty( DFF_Prop_connectorPoints ) )
+ {
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aGluePoints;
+ sal_uInt16 nNumElemVert = 0;
+ sal_uInt16 nElemSizeVert = 8;
+
+ if ( SeekToContent( DFF_Prop_connectorPoints, rIn ) )
+ {
+ sal_uInt16 nNumElemMemVert = 0;
+ rIn.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
+ // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
+ // low-order bytes are recorded
+ if (nElemSizeVert == 0xFFF0)
+ nElemSizeVert = 4;
+ }
+
+ // sanity check that the stream is long enough to fulfill nNumElemVert * nElemSizeVert;
+ bool bImport = nElemSizeVert && (rIn.remainingSize() / nElemSizeVert >= nNumElemVert);
+ if (bImport)
+ {
+ aGluePoints.realloc( nNumElemVert );
+ for (auto& rGluePoint : asNonConstRange(aGluePoints))
+ {
+ sal_Int32 nX(0), nY(0);
+ if ( nElemSizeVert == 8 )
+ {
+ rIn.ReadInt32( nX )
+ .ReadInt32( nY );
+ }
+ else
+ {
+ sal_Int16 nTmpA(0), nTmpB(0);
+
+ rIn.ReadInt16( nTmpA )
+ .ReadInt16( nTmpB );
+
+ nX = nTmpA;
+ nY = nTmpB;
+ }
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rGluePoint.First, nX );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( rGluePoint.Second, nY );
+ }
+ }
+ aProp.Name = "GluePoints";
+ aProp.Value <<= aGluePoints;
+ aPathPropVec.push_back( aProp );
+ }
+ if ( IsProperty( DFF_Prop_connectorType ) )
+ {
+ sal_Int16 nGluePointType = static_cast<sal_uInt16>(GetPropertyValue( DFF_Prop_connectorType, 0 ));
+ aProp.Name = "GluePointType";
+ aProp.Value <<= nGluePointType;
+ aPathPropVec.push_back( aProp );
+ }
+ // pushing the whole Path element
+ if ( !aPathPropVec.empty() )
+ {
+ aProp.Name = "Path";
+ aProp.Value <<= comphelper::containerToSequence(aPathPropVec);
+ aPropVec.push_back( aProp );
+ }
+ }
+
+ // "TextPath" PropertySequence element
+
+ bool bTextPathOn = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x4000 ) != 0;
+ if ( bTextPathOn )
+ {
+ PropVec aTextPathPropVec;
+
+ // TextPath
+ aProp.Name = "TextPath";
+ aProp.Value <<= bTextPathOn;
+ aTextPathPropVec.push_back( aProp );
+
+ // TextPathMode
+ bool bTextPathFitPath = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x100 ) != 0;
+
+ bool bTextPathFitShape;
+ if ( IsHardAttribute( DFF_Prop_gtextFStretch ) )
+ bTextPathFitShape = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x400 ) != 0;
+ else
+ {
+ bTextPathFitShape = true;
+ switch( rObjData.eShapeType )
+ {
+ case mso_sptTextArchUpCurve :
+ case mso_sptTextArchDownCurve :
+ case mso_sptTextCircleCurve :
+ case mso_sptTextButtonCurve :
+ bTextPathFitShape = false;
+ break;
+ default : break;
+ }
+ }
+ EnhancedCustomShapeTextPathMode eTextPathMode( EnhancedCustomShapeTextPathMode_NORMAL );
+ if ( bTextPathFitShape )
+ eTextPathMode = EnhancedCustomShapeTextPathMode_SHAPE;
+ else if ( bTextPathFitPath )
+ eTextPathMode = EnhancedCustomShapeTextPathMode_PATH;
+ aProp.Name = "TextPathMode";
+ aProp.Value <<= eTextPathMode;
+ aTextPathPropVec.push_back( aProp );
+
+ // ScaleX
+ bool bTextPathScaleX = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x40 ) != 0;
+ aProp.Name = "ScaleX";
+ aProp.Value <<= bTextPathScaleX;
+ aTextPathPropVec.push_back( aProp );
+ // SameLetterHeights
+ bool bSameLetterHeight = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x80 ) != 0;
+ aProp.Name = "SameLetterHeights";
+ aProp.Value <<= bSameLetterHeight;
+ aTextPathPropVec.push_back( aProp );
+
+ // pushing the whole TextPath element
+ aProp.Name = "TextPath";
+ aProp.Value <<= comphelper::containerToSequence(aTextPathPropVec);
+ aPropVec.push_back( aProp );
+ }
+
+ // "AdjustmentValues" // The AdjustmentValues are imported at last, because depending to the type of the
+ //////////////////////// handle (POLAR) we will convert the adjustment value from a fixed float to double
+
+ // checking the last used adjustment handle, so we can determine how many handles are to allocate
+ sal_uInt32 i = DFF_Prop_adjust10Value;
+ while ( ( i >= DFF_Prop_adjustValue ) && !IsProperty( i ) )
+ i--;
+ sal_Int32 nAdjustmentValues = ( i - DFF_Prop_adjustValue ) + 1;
+ if ( nAdjustmentValues )
+ {
+ uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq( nAdjustmentValues );
+ auto pAdjustmentSeq = aAdjustmentSeq.getArray();
+ while( --nAdjustmentValues >= 0 )
+ {
+ sal_Int32 nValue = 0;
+ beans::PropertyState ePropertyState = beans::PropertyState_DEFAULT_VALUE;
+ if ( IsProperty( i ) )
+ {
+ nValue = GetPropertyValue( i, 0 );
+ ePropertyState = beans::PropertyState_DIRECT_VALUE;
+ }
+ if ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << ( i - DFF_Prop_adjustValue ) ) )
+ {
+ double fValue = nValue;
+ fValue /= 65536;
+ pAdjustmentSeq[ nAdjustmentValues ].Value <<= fValue;
+ }
+ else
+ pAdjustmentSeq[ nAdjustmentValues ].Value <<= nValue;
+ pAdjustmentSeq[ nAdjustmentValues ].State = ePropertyState;
+ i--;
+ }
+ aProp.Name = "AdjustmentValues";
+ aProp.Value <<= aAdjustmentSeq;
+ aPropVec.push_back( aProp );
+ }
+
+ // creating the whole property set
+ rSet.Put( SdrCustomShapeGeometryItem( comphelper::containerToSequence(aPropVec) ) );
+}
+
+void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet ) const
+{
+ DffRecordHeader aHdTemp;
+ DffObjData aDffObjTemp( aHdTemp, tools::Rectangle(), 0 );
+ ApplyAttributes( rIn, rSet, aDffObjTemp );
+}
+
+void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet, DffObjData const & rObjData ) const
+{
+ bool bHasShadow = false;
+ bool bNonZeroShadowOffset = false;
+
+ if ( IsProperty( DFF_Prop_gtextSize ) )
+ rSet.Put( SvxFontHeightItem( rManager.ScalePt( GetPropertyValue( DFF_Prop_gtextSize, 0 ) ), 100, EE_CHAR_FONTHEIGHT ) );
+ sal_uInt32 nFontAttributes = GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 );
+ if ( nFontAttributes & 0x20 )
+ rSet.Put( SvxWeightItem( (nFontAttributes & 0x20) ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
+ if ( nFontAttributes & 0x10 )
+ rSet.Put( SvxPostureItem( (nFontAttributes & 0x10) ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
+ if ( nFontAttributes & 0x08 )
+ rSet.Put( SvxUnderlineItem( (nFontAttributes & 0x08) ? LINESTYLE_SINGLE : LINESTYLE_NONE, EE_CHAR_UNDERLINE ) );
+ if ( nFontAttributes & 0x40 )
+ rSet.Put( SvxShadowedItem( (nFontAttributes & 0x40) != 0, EE_CHAR_SHADOW ) );
+// if ( nFontAttributes & 0x02 )
+// rSet.Put( SvxCaseMapItem( nFontAttributes & 0x02 ? SvxCaseMap::SmallCaps : SvxCaseMap::NotMapped ) );
+ if ( nFontAttributes & 0x01 )
+ rSet.Put( SvxCrossedOutItem( (nFontAttributes & 0x01) ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) );
+ if ( IsProperty( DFF_Prop_fillColor ) )
+ rSet.Put( XFillColorItem( OUString(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor, 0 ), DFF_Prop_fillColor ) ) );
+ if ( IsProperty( DFF_Prop_shadowColor ) )
+ rSet.Put( makeSdrShadowColorItem( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_shadowColor, 0 ), DFF_Prop_shadowColor ) ) );
+ else
+ {
+ //The default value for this property is 0x00808080
+ rSet.Put( makeSdrShadowColorItem( rManager.MSO_CLR_ToColor( 0x00808080, DFF_Prop_shadowColor ) ) );
+ }
+ if ( IsProperty( DFF_Prop_shadowOpacity ) )
+ rSet.Put( makeSdrShadowTransparenceItem( static_cast<sal_uInt16>( ( 0x10000 - GetPropertyValue( DFF_Prop_shadowOpacity, 0 ) ) / 655 ) ) );
+ if ( IsProperty( DFF_Prop_shadowOffsetX ) )
+ {
+ sal_Int32 nVal = static_cast< sal_Int32 >( GetPropertyValue( DFF_Prop_shadowOffsetX, 0 ) );
+ rManager.ScaleEmu( nVal );
+ rSet.Put( makeSdrShadowXDistItem( nVal ) );
+ bNonZeroShadowOffset = ( nVal > 0 );
+ }
+ if ( IsProperty( DFF_Prop_shadowOffsetY ) )
+ {
+ sal_Int32 nVal = static_cast< sal_Int32 >( GetPropertyValue( DFF_Prop_shadowOffsetY, 0 ) );
+ rManager.ScaleEmu( nVal );
+ rSet.Put( makeSdrShadowYDistItem( nVal ) );
+ bNonZeroShadowOffset = ( nVal > 0 );
+ }
+ if ( IsProperty( DFF_Prop_fshadowObscured ) )
+ {
+ bHasShadow = ( GetPropertyValue( DFF_Prop_fshadowObscured, 0 ) & 2 ) != 0;
+ if ( bHasShadow )
+ {
+ if ( !IsProperty( DFF_Prop_shadowOffsetX ) )
+ rSet.Put( makeSdrShadowXDistItem( 35 ) );
+ if ( !IsProperty( DFF_Prop_shadowOffsetY ) )
+ rSet.Put( makeSdrShadowYDistItem( 35 ) );
+ }
+ }
+ if ( IsProperty( DFF_Prop_shadowType ) )
+ {
+ auto eShadowType = GetPropertyValue(DFF_Prop_shadowType, 0);
+ if( eShadowType != mso_shadowOffset && !bNonZeroShadowOffset )
+ {
+ //0.12" == 173 twip == 302 100mm
+ sal_uInt32 nDist = rManager.pSdrModel->GetScaleUnit() == MapUnit::MapTwip ? 173: 302;
+ rSet.Put( makeSdrShadowXDistItem( nDist ) );
+ rSet.Put( makeSdrShadowYDistItem( nDist ) );
+ }
+ }
+ if ( bHasShadow )
+ {
+ static bool bCheckShadow(false); // loplugin:constvars:ignore
+
+ // #i124477# Found no reason not to set shadow, esp. since it is applied to evtl. existing text
+ // and will lead to an error if in PPT someone used text and added the object shadow to the
+ // object carrying that text. I found no cases where this leads to problems (the old bugtracker
+ // task #160376# from sj is unfortunately no longer available). Keeping the code for now
+ // to allow easy fallback when this shows problems in the future
+ if(bCheckShadow)
+ {
+ // #160376# sj: activating shadow only if fill and or linestyle is used
+ // this is required because of the latest drawing layer core changes.
+ // #i104085# is related to this.
+ sal_uInt32 nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash, 0 ));
+ if(!IsHardAttribute( DFF_Prop_fLine ) && !IsCustomShapeStrokedByDefault( rObjData.eShapeType ))
+ nLineFlags &= ~0x08;
+ sal_uInt32 nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ));
+ if(!IsHardAttribute( DFF_Prop_fFilled ) && !IsCustomShapeFilledByDefault( rObjData.eShapeType ))
+ nFillFlags &= ~0x10;
+ if ( nFillFlags & 0x10 )
+ {
+ auto eMSO_FillType = GetPropertyValue(DFF_Prop_fillType, mso_fillSolid);
+ switch( eMSO_FillType )
+ {
+ case mso_fillSolid :
+ case mso_fillPattern :
+ case mso_fillTexture :
+ case mso_fillPicture :
+ case mso_fillShade :
+ case mso_fillShadeCenter :
+ case mso_fillShadeShape :
+ case mso_fillShadeScale :
+ case mso_fillShadeTitle :
+ break;
+ default:
+ nFillFlags &=~0x10; // no fillstyle used
+ break;
+ }
+ }
+ if ( ( ( nLineFlags & 0x08 ) == 0 ) && ( ( nFillFlags & 0x10 ) == 0 ) && ( rObjData.eShapeType != mso_sptPictureFrame )) // if there is no fillstyle and linestyle
+ bHasShadow = false; // we are turning shadow off.
+ }
+
+ if ( bHasShadow )
+ rSet.Put( makeSdrShadowItem( bHasShadow ) );
+ }
+ ApplyLineAttributes( rSet, rObjData.eShapeType ); // #i28269#
+ ApplyFillAttributes( rIn, rSet, rObjData );
+ if ( rObjData.eShapeType != mso_sptNil || IsProperty( DFF_Prop_pVertices ) )
+ {
+ ApplyCustomShapeGeometryAttributes( rIn, rSet, rObjData );
+ ApplyCustomShapeTextAttributes( rSet );
+ if ( rManager.GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL )
+ {
+ if ( mnFix16Angle || ( rObjData.nSpFlags & ShapeFlag::FlipV ) )
+ CheckAndCorrectExcelTextRotation( rIn, rSet, rObjData );
+ }
+ }
+}
+
+void DffPropertyReader::CheckAndCorrectExcelTextRotation( SvStream& rIn, SfxItemSet& rSet, DffObjData const & rObjData ) const
+{
+ bool bRotateTextWithShape = rObjData.bRotateTextWithShape;
+ if ( rObjData.bOpt2 ) // sj: #158494# is the second property set available ? if then we have to check the xml data of
+ { // the shape, because the textrotation of Excel 2003 and greater versions is stored there
+ // (upright property of the textbox)
+ if ( rManager.pSecPropSet->SeekToContent( DFF_Prop_metroBlob, rIn ) )
+ {
+ sal_uInt32 nLen = rManager.pSecPropSet->GetPropertyValue( DFF_Prop_metroBlob, 0 );
+ if ( nLen )
+ {
+ css::uno::Sequence< sal_Int8 > aXMLDataSeq( nLen );
+ rIn.ReadBytes(aXMLDataSeq.getArray(), nLen);
+ css::uno::Reference< css::io::XInputStream > xInputStream
+ ( new ::comphelper::SequenceInputStream( aXMLDataSeq ) );
+ try
+ {
+ css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
+ css::uno::Reference< css::embed::XStorage > xStorage
+ ( ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(
+ OFOPXML_STORAGE_FORMAT_STRING, xInputStream, xContext, true ) );
+ if ( xStorage.is() )
+ {
+ css::uno::Reference< css::embed::XStorage >
+ xStorageDRS( xStorage->openStorageElement( "drs", css::embed::ElementModes::SEEKABLEREAD ) );
+ if ( xStorageDRS.is() )
+ {
+ css::uno::Reference< css::io::XStream > xShapeXMLStream( xStorageDRS->openStreamElement( "shapexml.xml", css::embed::ElementModes::SEEKABLEREAD ) );
+ if ( xShapeXMLStream.is() )
+ {
+ css::uno::Reference< css::io::XInputStream > xShapeXMLInputStream( xShapeXMLStream->getInputStream() );
+ if ( xShapeXMLInputStream.is() )
+ {
+ css::uno::Sequence< sal_Int8 > aSeq;
+ sal_Int32 nBytesRead = xShapeXMLInputStream->readBytes( aSeq, 0x7fffffff );
+ if ( nBytesRead )
+ { // for only one property I spare to use a XML parser at this point, this
+ // should be enhanced if needed
+
+ bRotateTextWithShape = true; // using the correct xml default
+ const char* pArry = reinterpret_cast< char* >( aSeq.getArray() );
+ const char* const pUpright = "upright=";
+ const char* pEnd = pArry + nBytesRead;
+ const char* pPtr = pArry;
+ while( ( pPtr + 12 ) < pEnd )
+ {
+ if ( !memcmp( pUpright, pPtr, 8 ) )
+ {
+ bRotateTextWithShape = ( pPtr[ 9 ] != '1' ) && ( pPtr[ 9 ] != 't' );
+ break;
+ }
+ else
+ pPtr++;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( css::uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+ if ( bRotateTextWithShape )
+ return;
+
+ const css::uno::Any* pAny;
+ SdrCustomShapeGeometryItem aGeometryItem(rSet.Get( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
+ static const OUStringLiteral sTextRotateAngle( u"TextRotateAngle" );
+ pAny = aGeometryItem.GetPropertyValueByName( sTextRotateAngle );
+ double fExtraTextRotateAngle = 0.0;
+ if ( pAny )
+ *pAny >>= fExtraTextRotateAngle;
+
+ if ( rManager.mnFix16Angle )
+ fExtraTextRotateAngle += toDegrees(mnFix16Angle);
+ if ( rObjData.nSpFlags & ShapeFlag::FlipV )
+ fExtraTextRotateAngle -= 180.0;
+
+ css::beans::PropertyValue aTextRotateAngle;
+ aTextRotateAngle.Name = sTextRotateAngle;
+ aTextRotateAngle.Value <<= fExtraTextRotateAngle;
+ aGeometryItem.SetPropertyValue( aTextRotateAngle );
+ rSet.Put( aGeometryItem );
+}
+
+
+void DffPropertyReader::ImportGradientColor( SfxItemSet& aSet, sal_uInt32 eMSO_FillType, double dTrans , double dBackTrans) const
+{
+ //MS Focus prop will impact the start and end color position. And AOO does not
+ //support this prop. So need some swap for the two color to keep fidelity with AOO and MS shape.
+ //So below var is defined.
+ sal_Int32 nChgColors = 0;
+ sal_Int32 nAngleFix16 = GetPropertyValue( DFF_Prop_fillAngle, 0 );
+ if(nAngleFix16 >= 0)
+ nChgColors ^= 1;
+
+ //Translate a MS clockwise(+) or count clockwise angle(-) into an AOO count clock wise angle
+ Degree10 nAngle( 3600_deg10 - to<Degree10>( Fix16ToAngle(nAngleFix16) ) );
+ //Make sure this angle belongs to 0~3600
+ while ( nAngle >= 3600_deg10 ) nAngle -= 3600_deg10;
+ while ( nAngle < 0_deg10 ) nAngle += 3600_deg10;
+
+ //Rotate angle
+ if ( mbRotateGranientFillWithAngle )
+ {
+ sal_Int32 nRotateAngle = GetPropertyValue( DFF_Prop_Rotation, 0 );
+ //nAngle is a clockwise angle. If nRotateAngle is a clockwise angle, then gradient needs to be rotated a little less
+ //or it needs to be rotated a little more
+ nAngle -= to<Degree10>(Fix16ToAngle(nRotateAngle));
+ }
+ while ( nAngle >= 3600_deg10 ) nAngle -= 3600_deg10;
+ while ( nAngle < 0_deg10 ) nAngle += 3600_deg10;
+
+ css::awt::GradientStyle eGrad = css::awt::GradientStyle_LINEAR;
+
+ sal_Int32 nFocus = GetPropertyValue( DFF_Prop_fillFocus, 0 );
+ if ( !nFocus )
+ nChgColors ^= 1;
+ else if ( nFocus < 0 )//If it is a negative focus, the color will be swapped
+ {
+ nFocus = o3tl::saturating_toggle_sign(nFocus);
+ nChgColors ^= 1;
+ }
+
+ if( nFocus > 40 && nFocus < 60 )
+ {
+ eGrad = css::awt::GradientStyle_AXIAL;//A axial gradient other than linear
+ nChgColors ^= 1;
+ }
+ //if the type is linear or axial, just save focus to nFocusX and nFocusY for export
+ //Core function does no need them. They serve for rect gradient(CenterXY).
+ sal_uInt16 nFocusX = static_cast<sal_uInt16>(nFocus);
+ sal_uInt16 nFocusY = static_cast<sal_uInt16>(nFocus);
+
+ switch( eMSO_FillType )
+ {
+ case mso_fillShadeShape :
+ {
+ eGrad = css::awt::GradientStyle_RECT;
+ nFocusY = nFocusX = 50;
+ nChgColors ^= 1;
+ }
+ break;
+ case mso_fillShadeCenter :
+ {
+ eGrad = css::awt::GradientStyle_RECT;
+ //A MS fillTo prop specifies the relative position of the left boundary
+ //of the center rectangle in a concentric shaded fill. Use 100 or 0 to keep fidelity
+ nFocusX=(GetPropertyValue( DFF_Prop_fillToRight, 0 )==0x10000) ? 100 : 0;
+ nFocusY=(GetPropertyValue( DFF_Prop_fillToBottom,0 )==0x10000) ? 100 : 0;
+ nChgColors ^= 1;
+ }
+ break;
+ default: break;
+ }
+
+ Color aCol1( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor, sal_uInt32(COL_WHITE) ), DFF_Prop_fillColor ) );
+ Color aCol2( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor, sal_uInt32(COL_WHITE) ), DFF_Prop_fillBackColor ) );
+ if ( nChgColors )
+ {
+ //Swap start and end color
+ Color aZwi( aCol1 );
+ aCol1 = aCol2;
+ aCol2 = aZwi;
+ //Swap two colors' transparency
+ double dTemp = dTrans;
+ dTrans = dBackTrans;
+ dBackTrans = dTemp;
+ }
+
+ //Construct gradient item
+ XGradient aGrad( aCol2, aCol1, eGrad, nAngle, nFocusX, nFocusY );
+ //Intensity has been merged into color. So here just set is as 100
+ aGrad.SetStartIntens( 100 );
+ aGrad.SetEndIntens( 100 );
+ aSet.Put( XFillGradientItem( OUString(), aGrad ) );
+ //Construct transparency item. This item can coordinate with both solid and gradient.
+ if ( dTrans < 1.0 || dBackTrans < 1.0 )
+ {
+ sal_uInt8 nStartCol = static_cast<sal_uInt8>( (1 - dTrans )* 255 );
+ sal_uInt8 nEndCol = static_cast<sal_uInt8>( ( 1- dBackTrans ) * 255 );
+ aCol1 = Color(nStartCol, nStartCol, nStartCol);
+ aCol2 = Color(nEndCol, nEndCol, nEndCol);
+
+ XGradient aGrad2( aCol2 , aCol1 , eGrad, nAngle, nFocusX, nFocusY );
+ aSet.Put( XFillFloatTransparenceItem( OUString(), aGrad2 ) );
+ }
+}
+
+
+//- Record Manager ----------------------------------------------------------
+
+
+DffRecordList::DffRecordList( DffRecordList* pList ) :
+ nCount ( 0 ),
+ nCurrent ( 0 ),
+ pPrev ( pList )
+{
+ if ( pList )
+ pList->pNext.reset( this );
+}
+
+DffRecordList::~DffRecordList()
+{
+}
+
+DffRecordManager::DffRecordManager() :
+ DffRecordList ( nullptr ),
+ pCList ( static_cast<DffRecordList*>(this) )
+{
+}
+
+DffRecordManager::DffRecordManager( SvStream& rIn ) :
+ DffRecordList ( nullptr ),
+ pCList ( static_cast<DffRecordList*>(this) )
+{
+ Consume( rIn );
+}
+
+void DffRecordManager::Consume( SvStream& rIn, sal_uInt32 nStOfs )
+{
+ Clear();
+ sal_uInt64 nOldPos = rIn.Tell();
+ if ( !nStOfs )
+ {
+ DffRecordHeader aHd;
+ bool bOk = ReadDffRecordHeader( rIn, aHd );
+ if (bOk && aHd.nRecVer == DFF_PSFLAG_CONTAINER)
+ nStOfs = aHd.GetRecEndFilePos();
+ }
+ if ( !nStOfs )
+ return;
+
+ pCList = this;
+ while ( pCList->pNext )
+ pCList = pCList->pNext.get();
+ while (rIn.good() && ( ( rIn.Tell() + 8 ) <= nStOfs ))
+ {
+ if ( pCList->nCount == DFF_RECORD_MANAGER_BUF_SIZE )
+ pCList = new DffRecordList( pCList );
+ if (!ReadDffRecordHeader(rIn, pCList->mHd[ pCList->nCount ]))
+ break;
+ bool bSeekSucceeded = pCList->mHd[ pCList->nCount++ ].SeekToEndOfRecord(rIn);
+ if (!bSeekSucceeded)
+ break;
+ }
+ rIn.Seek( nOldPos );
+}
+
+void DffRecordManager::Clear()
+{
+ pCList = this;
+ pNext.reset();
+ nCurrent = 0;
+ nCount = 0;
+}
+
+DffRecordHeader* DffRecordManager::Current()
+{
+ DffRecordHeader* pRet = nullptr;
+ if ( pCList->nCurrent < pCList->nCount )
+ pRet = &pCList->mHd[ pCList->nCurrent ];
+ return pRet;
+}
+
+DffRecordHeader* DffRecordManager::First()
+{
+ DffRecordHeader* pRet = nullptr;
+ pCList = this;
+ if ( pCList->nCount )
+ {
+ pCList->nCurrent = 0;
+ pRet = &pCList->mHd[ 0 ];
+ }
+ return pRet;
+}
+
+DffRecordHeader* DffRecordManager::Next()
+{
+ DffRecordHeader* pRet = nullptr;
+ sal_uInt32 nC = pCList->nCurrent + 1;
+ if ( nC < pCList->nCount )
+ {
+ pCList->nCurrent++;
+ pRet = &pCList->mHd[ nC ];
+ }
+ else if ( pCList->pNext )
+ {
+ pCList = pCList->pNext.get();
+ pCList->nCurrent = 0;
+ pRet = &pCList->mHd[ 0 ];
+ }
+ return pRet;
+}
+
+DffRecordHeader* DffRecordManager::Prev()
+{
+ DffRecordHeader* pRet = nullptr;
+ sal_uInt32 nCur = pCList->nCurrent;
+ if ( !nCur && pCList->pPrev )
+ {
+ pCList = pCList->pPrev;
+ nCur = pCList->nCount;
+ }
+ if ( nCur-- )
+ {
+ pCList->nCurrent = nCur;
+ pRet = &pCList->mHd[ nCur ];
+ }
+ return pRet;
+}
+
+DffRecordHeader* DffRecordManager::Last()
+{
+ DffRecordHeader* pRet = nullptr;
+ while ( pCList->pNext )
+ pCList = pCList->pNext.get();
+ sal_uInt32 nCnt = pCList->nCount;
+ if ( nCnt-- )
+ {
+ pCList->nCurrent = nCnt;
+ pRet = &pCList->mHd[ nCnt ];
+ }
+ return pRet;
+}
+
+bool DffRecordManager::SeekToContent( SvStream& rIn, sal_uInt16 nRecId, DffSeekToContentMode eMode )
+{
+ DffRecordHeader* pHd = GetRecordHeader( nRecId, eMode );
+ if ( pHd )
+ {
+ pHd->SeekToContent( rIn );
+ return true;
+ }
+ else
+ return false;
+}
+
+DffRecordHeader* DffRecordManager::GetRecordHeader( sal_uInt16 nRecId, DffSeekToContentMode eMode )
+{
+ sal_uInt32 nOldCurrent = pCList->nCurrent;
+ DffRecordList* pOldList = pCList;
+ DffRecordHeader* pHd;
+
+ if ( eMode == SEEK_FROM_BEGINNING )
+ pHd = First();
+ else
+ pHd = Next();
+
+ while ( pHd )
+ {
+ if ( pHd->nRecType == nRecId )
+ break;
+ pHd = Next();
+ }
+ if ( !pHd && eMode == SEEK_FROM_CURRENT_AND_RESTART )
+ {
+ DffRecordHeader* pBreak = &pOldList->mHd[ nOldCurrent ];
+ pHd = First();
+ if ( pHd )
+ {
+ while ( pHd != pBreak )
+ {
+ if ( pHd->nRecType == nRecId )
+ break;
+ pHd = Next();
+ }
+ if ( pHd->nRecType != nRecId )
+ pHd = nullptr;
+ }
+ }
+ if ( !pHd )
+ {
+ pCList = pOldList;
+ pOldList->nCurrent = nOldCurrent;
+ }
+ return pHd;
+}
+
+
+// private methods
+
+
+bool CompareSvxMSDffShapeInfoById::operator() (
+ std::shared_ptr<SvxMSDffShapeInfo> const& lhs,
+ std::shared_ptr<SvxMSDffShapeInfo> const& rhs) const
+{
+ return lhs->nShapeId < rhs->nShapeId;
+}
+
+bool CompareSvxMSDffShapeInfoByTxBxComp::operator() (
+ std::shared_ptr<SvxMSDffShapeInfo> const& lhs,
+ std::shared_ptr<SvxMSDffShapeInfo> const& rhs) const
+{
+ return lhs->nTxBxComp < rhs->nTxBxComp;
+}
+
+void SvxMSDffManager::Scale( sal_Int32& rVal ) const
+{
+ if ( bNeedMap )
+ rVal = BigMulDiv( rVal, nMapMul, nMapDiv );
+}
+
+void SvxMSDffManager::Scale( Point& rPos ) const
+{
+ rPos.AdjustX(nMapXOfs );
+ rPos.AdjustY(nMapYOfs );
+ if ( bNeedMap )
+ {
+ rPos.setX( BigMulDiv( rPos.X(), nMapMul, nMapDiv ) );
+ rPos.setY( BigMulDiv( rPos.Y(), nMapMul, nMapDiv ) );
+ }
+}
+
+void SvxMSDffManager::Scale( Size& rSiz ) const
+{
+ if ( bNeedMap )
+ {
+ rSiz.setWidth( BigMulDiv( rSiz.Width(), nMapMul, nMapDiv ) );
+ rSiz.setHeight( BigMulDiv( rSiz.Height(), nMapMul, nMapDiv ) );
+ }
+}
+
+void SvxMSDffManager::ScaleEmu( sal_Int32& rVal ) const
+{
+ rVal = BigMulDiv( rVal, nEmuMul, nEmuDiv );
+}
+
+sal_uInt32 SvxMSDffManager::ScalePt( sal_uInt32 nVal ) const
+{
+ MapUnit eMap = pSdrModel->GetScaleUnit();
+ Fraction aFact( GetMapFactor( MapUnit::MapPoint, eMap ).X() );
+ tools::Long aMul = aFact.GetNumerator();
+ tools::Long aDiv = aFact.GetDenominator() * 65536;
+ aFact = Fraction( aMul, aDiv ); // try again to shorten it
+ return BigMulDiv( nVal, aFact.GetNumerator(), aFact.GetDenominator() );
+}
+
+sal_Int32 SvxMSDffManager::ScalePoint( sal_Int32 nVal ) const
+{
+ return BigMulDiv( nVal, nPntMul, nPntDiv );
+};
+
+void SvxMSDffManager::SetModel(SdrModel* pModel, tools::Long nApplicationScale)
+{
+ pSdrModel = pModel;
+ if( pModel && (0 < nApplicationScale) )
+ {
+ // PPT works in units of 576DPI
+ // WW on the other side uses twips, i.e. 1440DPI.
+ MapUnit eMap = pSdrModel->GetScaleUnit();
+ Fraction aFact( GetMapFactor(MapUnit::MapInch, eMap).X() );
+ tools::Long nMul=aFact.GetNumerator();
+ tools::Long nDiv=aFact.GetDenominator()*nApplicationScale;
+ aFact=Fraction(nMul,nDiv); // try again to shorten it
+ // For 100TH_MM -> 2540/576=635/144
+ // For Twip -> 1440/576=5/2
+ nMapMul = aFact.GetNumerator();
+ nMapDiv = aFact.GetDenominator();
+ bNeedMap = nMapMul!=nMapDiv;
+
+ // MS-DFF-Properties are mostly given in EMU (English Metric Units)
+ // 1mm=36000emu, 1twip=635emu
+ aFact=GetMapFactor(MapUnit::Map100thMM,eMap).X();
+ nMul=aFact.GetNumerator();
+ nDiv=aFact.GetDenominator()*360;
+ aFact=Fraction(nMul,nDiv); // try again to shorten it
+ // For 100TH_MM -> 1/360
+ // For Twip -> 14,40/(25,4*360)=144/91440=1/635
+ nEmuMul=aFact.GetNumerator();
+ nEmuDiv=aFact.GetDenominator();
+
+ // And something for typographic Points
+ aFact=GetMapFactor(MapUnit::MapPoint,eMap).X();
+ nPntMul=aFact.GetNumerator();
+ nPntDiv=aFact.GetDenominator();
+ }
+ else
+ {
+ pModel = nullptr;
+ nMapMul = nMapDiv = nMapXOfs = nMapYOfs = nEmuMul = nEmuDiv = nPntMul = nPntDiv = 0;
+ bNeedMap = false;
+ }
+}
+
+bool SvxMSDffManager::SeekToShape( SvStream& rSt, SvxMSDffClientData* /* pClientData */, sal_uInt32 nId ) const
+{
+ bool bRet = false;
+ if ( !maFidcls.empty() )
+ {
+ sal_uInt64 nOldPos = rSt.Tell();
+ sal_uInt32 nSec = ( nId >> 10 ) - 1;
+ if ( nSec < mnIdClusters )
+ {
+ OffsetMap::const_iterator it = maDgOffsetTable.find( maFidcls[ nSec ].dgid );
+ if ( it != maDgOffsetTable.end() )
+ {
+ sal_uInt64 nOfs = it->second;
+ rSt.Seek( nOfs );
+ DffRecordHeader aEscherF002Hd;
+ bool bOk = ReadDffRecordHeader( rSt, aEscherF002Hd );
+ sal_uLong nEscherF002End = bOk ? aEscherF002Hd.GetRecEndFilePos() : 0;
+ while (rSt.good() && rSt.Tell() < nEscherF002End)
+ {
+ DffRecordHeader aEscherObjListHd;
+ if (!ReadDffRecordHeader(rSt, aEscherObjListHd))
+ break;
+ if ( aEscherObjListHd.nRecVer != 0xf )
+ {
+ bool bSeekSuccess = aEscherObjListHd.SeekToEndOfRecord(rSt);
+ if (!bSeekSuccess)
+ break;
+ }
+ else if ( aEscherObjListHd.nRecType == DFF_msofbtSpContainer )
+ {
+ DffRecordHeader aShapeHd;
+ if ( SeekToRec( rSt, DFF_msofbtSp, aEscherObjListHd.GetRecEndFilePos(), &aShapeHd ) )
+ {
+ sal_uInt32 nShapeId(0);
+ rSt.ReadUInt32( nShapeId );
+ if ( nId == nShapeId )
+ {
+ aEscherObjListHd.SeekToBegOfRecord( rSt );
+ bRet = true;
+ break;
+ }
+ }
+ bool bSeekSuccess = aEscherObjListHd.SeekToEndOfRecord(rSt);
+ if (!bSeekSuccess)
+ break;
+ }
+ }
+ }
+ }
+ if ( !bRet )
+ rSt.Seek( nOldPos );
+ }
+ return bRet;
+}
+
+bool SvxMSDffManager::SeekToRec( SvStream& rSt, sal_uInt16 nRecId, sal_uLong nMaxFilePos, DffRecordHeader* pRecHd, sal_uLong nSkipCount )
+{
+ bool bRet = false;
+ sal_uInt64 nOldFPos = rSt.Tell(); // store FilePos to restore it later if necessary
+ do
+ {
+ DffRecordHeader aHd;
+ if (!ReadDffRecordHeader(rSt, aHd))
+ break;
+ if (aHd.nRecLen > nMaxLegalDffRecordLength)
+ break;
+ if ( aHd.nRecType == nRecId )
+ {
+ if ( nSkipCount )
+ nSkipCount--;
+ else
+ {
+ bRet = true;
+ if ( pRecHd != nullptr )
+ *pRecHd = aHd;
+ else
+ {
+ bool bSeekSuccess = aHd.SeekToBegOfRecord(rSt);
+ if (!bSeekSuccess)
+ {
+ bRet = false;
+ break;
+ }
+ }
+ }
+ }
+ if ( !bRet )
+ {
+ bool bSeekSuccess = aHd.SeekToEndOfRecord(rSt);
+ if (!bSeekSuccess)
+ break;
+ }
+ }
+ while ( rSt.good() && rSt.Tell() < nMaxFilePos && !bRet );
+ if ( !bRet )
+ rSt.Seek( nOldFPos ); // restore original FilePos
+ return bRet;
+}
+
+bool SvxMSDffManager::SeekToRec2( sal_uInt16 nRecId1, sal_uInt16 nRecId2, sal_uLong nMaxFilePos ) const
+{
+ bool bRet = false;
+ sal_uInt64 nOldFPos = rStCtrl.Tell(); // remember FilePos for conditionally later restoration
+ do
+ {
+ DffRecordHeader aHd;
+ if (!ReadDffRecordHeader(rStCtrl, aHd))
+ break;
+ if ( aHd.nRecType == nRecId1 || aHd.nRecType == nRecId2 )
+ {
+ bRet = true;
+ bool bSeekSuccess = aHd.SeekToBegOfRecord(rStCtrl);
+ if (!bSeekSuccess)
+ {
+ bRet = false;
+ break;
+ }
+ }
+ if ( !bRet )
+ {
+ bool bSeekSuccess = aHd.SeekToEndOfRecord(rStCtrl);
+ if (!bSeekSuccess)
+ break;
+ }
+ }
+ while ( rStCtrl.good() && rStCtrl.Tell() < nMaxFilePos && !bRet );
+ if ( !bRet )
+ rStCtrl.Seek( nOldFPos ); // restore FilePos
+ return bRet;
+}
+
+
+bool SvxMSDffManager::GetColorFromPalette( sal_uInt16 /* nNum */, Color& rColor ) const
+{
+ // This method has to be overwritten in the class
+ // derived for the excel export
+ rColor = COL_WHITE;
+ return true;
+}
+
+// sj: the documentation is not complete, especially in ppt the normal rgb for text
+// color is written as 0xfeRRGGBB, this can't be explained by the documentation, nearly
+// every bit in the upper code is set -> so there seems to be a special handling for
+// ppt text colors, i decided not to fix this in MSO_CLR_ToColor because of possible
+// side effects, instead MSO_TEXT_CLR_ToColor is called for PPT text colors, to map
+// the color code to something that behaves like the other standard color codes used by
+// fill and line color
+Color SvxMSDffManager::MSO_TEXT_CLR_ToColor( sal_uInt32 nColorCode ) const
+{
+ // for text colors: Header is 0xfeRRGGBB
+ if ( ( nColorCode & 0xfe000000 ) == 0xfe000000 )
+ nColorCode &= 0x00ffffff;
+ else
+ {
+ // for colorscheme colors the color index are the lower three bits of the upper byte
+ if ( ( nColorCode & 0xf8000000 ) == 0 ) // this must be a colorscheme index
+ {
+ nColorCode >>= 24;
+ nColorCode |= 0x8000000;
+ }
+ }
+ return MSO_CLR_ToColor( nColorCode );
+}
+
+Color SvxMSDffManager::MSO_CLR_ToColor( sal_uInt32 nColorCode, sal_uInt16 nContentProperty ) const
+{
+ Color aColor( mnDefaultColor );
+
+ // for text colors: Header is 0xfeRRGGBB
+ if ( ( nColorCode & 0xfe000000 ) == 0xfe000000 ) // sj: it needs to be checked if 0xfe is used in
+ nColorCode &= 0x00ffffff; // other cases than ppt text -> if not this code can be removed
+
+ sal_uInt8 nUpper = static_cast<sal_uInt8>( nColorCode >> 24 );
+
+ // sj: below change from 0x1b to 0x19 was done because of i84812 (0x02 -> rgb color),
+ // now I have some problems to fix i104685 (there the color value is 0x02000000 which requires
+ // a 0x2 scheme color to be displayed properly), the color docu seems to be incomplete
+ if( nUpper & 0x19 ) // if( nUpper & 0x1f )
+ {
+ if( ( nUpper & 0x08 ) || ( ( nUpper & 0x10 ) == 0 ) )
+ {
+ // SCHEMECOLOR
+ if ( !GetColorFromPalette( ( nUpper & 8 ) ? static_cast<sal_uInt16>(nColorCode) : nUpper, aColor ) )
+ {
+ switch( nContentProperty )
+ {
+ case DFF_Prop_pictureTransparent :
+ case DFF_Prop_shadowColor :
+ case DFF_Prop_fillBackColor :
+ case DFF_Prop_fillColor :
+ aColor = COL_WHITE;
+ break;
+ case DFF_Prop_lineColor :
+ {
+ aColor = COL_BLACK;
+ }
+ break;
+ }
+ }
+ }
+ else // SYSCOLOR
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+
+ sal_uInt16 nParameter = sal_uInt16(( nColorCode >> 16 ) & 0x00ff); // the HiByte of nParameter is not zero, an exclusive AND is helping :o
+ sal_uInt16 nFunctionBits = static_cast<sal_uInt16>( ( nColorCode & 0x00000f00 ) >> 8 );
+ sal_uInt16 nAdditionalFlags = static_cast<sal_uInt16>( ( nColorCode & 0x0000f000) >> 8 );
+ sal_uInt16 nColorIndex = sal_uInt16(nColorCode & 0x00ff);
+ sal_uInt32 nPropColor = 0;
+
+ sal_uInt16 nCProp = 0;
+
+ switch ( nColorIndex )
+ {
+ case mso_syscolorButtonFace : aColor = rStyleSettings.GetFaceColor(); break;
+ case mso_syscolorWindowText : aColor = rStyleSettings.GetWindowTextColor(); break;
+ case mso_syscolorMenu : aColor = rStyleSettings.GetMenuColor(); break;
+ case mso_syscolor3DLight :
+ case mso_syscolorButtonHighlight :
+ case mso_syscolorHighlight : aColor = rStyleSettings.GetHighlightColor(); break;
+ case mso_syscolorHighlightText : aColor = rStyleSettings.GetHighlightTextColor(); break;
+ case mso_syscolorCaptionText : aColor = rStyleSettings.GetMenuTextColor(); break;
+ case mso_syscolorActiveCaption : aColor = rStyleSettings.GetHighlightColor(); break;
+ case mso_syscolorButtonShadow : aColor = rStyleSettings.GetShadowColor(); break;
+ case mso_syscolorButtonText : aColor = rStyleSettings.GetButtonTextColor(); break;
+ case mso_syscolorGrayText : aColor = rStyleSettings.GetDeactiveColor(); break;
+ case mso_syscolorInactiveCaption : aColor = rStyleSettings.GetDeactiveColor(); break;
+ case mso_syscolorInactiveCaptionText : aColor = rStyleSettings.GetDeactiveColor(); break;
+ case mso_syscolorInfoBackground : aColor = rStyleSettings.GetFaceColor(); break;
+ case mso_syscolorInfoText : aColor = rStyleSettings.GetLabelTextColor(); break;
+ case mso_syscolorMenuText : aColor = rStyleSettings.GetMenuTextColor(); break;
+ case mso_syscolorScrollbar : aColor = rStyleSettings.GetFaceColor(); break;
+ case mso_syscolorWindow : aColor = rStyleSettings.GetWindowColor(); break;
+ case mso_syscolorWindowFrame : aColor = rStyleSettings.GetWindowColor(); break;
+
+ case mso_colorFillColor :
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );
+ nCProp = DFF_Prop_fillColor;
+ }
+ break;
+ case mso_colorLineOrFillColor : // ( use the line color only if there is a line )
+ {
+ if ( GetPropertyValue( DFF_Prop_fNoLineDrawDash, 0 ) & 8 )
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_lineColor, 0 );
+ nCProp = DFF_Prop_lineColor;
+ }
+ else
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );
+ nCProp = DFF_Prop_fillColor;
+ }
+ }
+ break;
+ case mso_colorLineColor :
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_lineColor, 0 );
+ nCProp = DFF_Prop_lineColor;
+ }
+ break;
+ case mso_colorShadowColor :
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_shadowColor, 0x808080 );
+ nCProp = DFF_Prop_shadowColor;
+ }
+ break;
+ case mso_colorThis : // ( use this color ... )
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); //?????????????
+ nCProp = DFF_Prop_fillColor;
+ }
+ break;
+ case mso_colorFillBackColor :
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_fillBackColor, 0xffffff );
+ nCProp = DFF_Prop_fillBackColor;
+ }
+ break;
+ case mso_colorLineBackColor :
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_lineBackColor, 0xffffff );
+ nCProp = DFF_Prop_lineBackColor;
+ }
+ break;
+ case mso_colorFillThenLine : // ( use the fillcolor unless no fill and line )
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); //?????????????
+ nCProp = DFF_Prop_fillColor;
+ }
+ break;
+ case mso_colorIndexMask : // ( extract the color index ) ?
+ {
+ nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff ); //?????????????
+ nCProp = DFF_Prop_fillColor;
+ }
+ break;
+ }
+ if ( nCProp && ( nPropColor & 0x10000000 ) == 0 ) // beware of looping recursive
+ aColor = MSO_CLR_ToColor( nPropColor, nCProp );
+
+ if( nAdditionalFlags & 0x80 ) // make color gray
+ {
+ sal_uInt8 nZwi = aColor.GetLuminance();
+ aColor = Color( nZwi, nZwi, nZwi );
+ }
+ switch( nFunctionBits )
+ {
+ case 0x01 : // darken color by parameter
+ {
+ aColor.SetRed( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetRed() ) >> 8 ) );
+ aColor.SetGreen( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetGreen() ) >> 8 ) );
+ aColor.SetBlue( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetBlue() ) >> 8 ) );
+ }
+ break;
+ case 0x02 : // lighten color by parameter
+ {
+ sal_uInt16 nInvParameter = ( 0x00ff - nParameter ) * 0xff;
+ aColor.SetRed( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetRed() ) ) >> 8 ) );
+ aColor.SetGreen( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetGreen() ) ) >> 8 ) );
+ aColor.SetBlue( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetBlue() ) ) >> 8 ) );
+ }
+ break;
+ case 0x03 : // add grey level RGB(p,p,p)
+ {
+ sal_Int16 nR = static_cast<sal_Int16>(aColor.GetRed()) + static_cast<sal_Int16>(nParameter);
+ sal_Int16 nG = static_cast<sal_Int16>(aColor.GetGreen()) + static_cast<sal_Int16>(nParameter);
+ sal_Int16 nB = static_cast<sal_Int16>(aColor.GetBlue()) + static_cast<sal_Int16>(nParameter);
+ if ( nR > 0x00ff )
+ nR = 0x00ff;
+ if ( nG > 0x00ff )
+ nG = 0x00ff;
+ if ( nB > 0x00ff )
+ nB = 0x00ff;
+ aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
+ }
+ break;
+ case 0x04 : // subtract grey level RGB(p,p,p)
+ {
+ sal_Int16 nR = static_cast<sal_Int16>(aColor.GetRed()) - static_cast<sal_Int16>(nParameter);
+ sal_Int16 nG = static_cast<sal_Int16>(aColor.GetGreen()) - static_cast<sal_Int16>(nParameter);
+ sal_Int16 nB = static_cast<sal_Int16>(aColor.GetBlue()) - static_cast<sal_Int16>(nParameter);
+ if ( nR < 0 )
+ nR = 0;
+ if ( nG < 0 )
+ nG = 0;
+ if ( nB < 0 )
+ nB = 0;
+ aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
+ }
+ break;
+ case 0x05 : // subtract from gray level RGB(p,p,p)
+ {
+ sal_Int16 nR = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetRed());
+ sal_Int16 nG = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetGreen());
+ sal_Int16 nB = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetBlue());
+ if ( nR < 0 )
+ nR = 0;
+ if ( nG < 0 )
+ nG = 0;
+ if ( nB < 0 )
+ nB = 0;
+ aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
+ }
+ break;
+ case 0x06 : // per component: black if < p, white if >= p
+ {
+ aColor.SetRed( aColor.GetRed() < nParameter ? 0x00 : 0xff );
+ aColor.SetGreen( aColor.GetGreen() < nParameter ? 0x00 : 0xff );
+ aColor.SetBlue( aColor.GetBlue() < nParameter ? 0x00 : 0xff );
+ }
+ break;
+ }
+ if ( nAdditionalFlags & 0x40 ) // top-bit invert
+ aColor = Color( aColor.GetRed() ^ 0x80, aColor.GetGreen() ^ 0x80, aColor.GetBlue() ^ 0x80 );
+
+ if ( nAdditionalFlags & 0x20 ) // invert color
+ aColor = Color(0xff - aColor.GetRed(), 0xff - aColor.GetGreen(), 0xff - aColor.GetBlue());
+ }
+ }
+ else if ( ( nUpper & 4 ) && ( ( nColorCode & 0xfffff8 ) == 0 ) )
+ { // case of nUpper == 4 powerpoint takes this as argument for a colorschemecolor
+ GetColorFromPalette( nUpper, aColor );
+ }
+ else // attributed hard, maybe with hint to SYSTEMRGB
+ aColor = Color( static_cast<sal_uInt8>(nColorCode), static_cast<sal_uInt8>( nColorCode >> 8 ), static_cast<sal_uInt8>( nColorCode >> 16 ) );
+ return aColor;
+}
+
+void SvxMSDffManager::ReadObjText( SvStream& rStream, SdrObject* pObj )
+{
+ DffRecordHeader aRecHd;
+ if (!ReadDffRecordHeader(rStream, aRecHd))
+ return;
+ if( aRecHd.nRecType != DFF_msofbtClientTextbox && aRecHd.nRecType != 0x1022 )
+ return;
+
+ while (rStream.good() && rStream.Tell() < aRecHd.GetRecEndFilePos())
+ {
+ DffRecordHeader aHd;
+ if (!ReadDffRecordHeader(rStream, aHd))
+ break;
+ switch( aHd.nRecType )
+ {
+ case DFF_PST_TextBytesAtom:
+ case DFF_PST_TextCharsAtom:
+ {
+ bool bUniCode = ( aHd.nRecType == DFF_PST_TextCharsAtom );
+ sal_uInt32 nBytes = aHd.nRecLen;
+ OUString aStr = MSDFFReadZString( rStream, nBytes, bUniCode );
+ ReadObjText( aStr, pObj );
+ }
+ break;
+ default:
+ break;
+ }
+ bool bSeekSuccess = aHd.SeekToEndOfRecord(rStream);
+ if (!bSeekSuccess)
+ break;
+ }
+}
+
+// sj: I just want to set a string for a text object that may contain multiple
+// paragraphs. If I now take a look at the following code I get the impression that
+// our outliner is too complicate to be used properly,
+void SvxMSDffManager::ReadObjText( const OUString& rText, SdrObject* pObj )
+{
+ SdrTextObj* pText = dynamic_cast<SdrTextObj*>( pObj );
+ if ( !pText )
+ return;
+
+ SdrOutliner& rOutliner = pText->ImpGetDrawOutliner();
+ rOutliner.Init( OutlinerMode::TextObject );
+
+ bool bOldUpdateMode = rOutliner.SetUpdateLayout( false );
+ rOutliner.SetVertical( pText->IsVerticalWriting() );
+
+ sal_Int32 nParaIndex = 0;
+ sal_Int32 nParaSize;
+ const sal_Unicode* pBuf = rText.getStr();
+ const sal_Unicode* pEnd = rText.getStr() + rText.getLength();
+
+ while( pBuf < pEnd )
+ {
+ const sal_Unicode* pCurrent = pBuf;
+
+ for ( nParaSize = 0; pBuf < pEnd; )
+ {
+ sal_Unicode nChar = *pBuf++;
+ if ( nChar == 0xa )
+ {
+ if ( ( pBuf < pEnd ) && ( *pBuf == 0xd ) )
+ pBuf++;
+ break;
+ }
+ else if ( nChar == 0xd )
+ {
+ if ( ( pBuf < pEnd ) && ( *pBuf == 0xa ) )
+ pBuf++;
+ break;
+ }
+ else
+ ++nParaSize;
+ }
+ ESelection aSelection( nParaIndex, 0, nParaIndex, 0 );
+ OUString aParagraph( pCurrent, nParaSize );
+ if ( !nParaIndex && aParagraph.isEmpty() ) // SJ: we are crashing if the first paragraph is empty ?
+ aParagraph += " "; // otherwise these two lines can be removed.
+ rOutliner.Insert( aParagraph, nParaIndex );
+ rOutliner.SetParaAttribs( nParaIndex, rOutliner.GetEmptyItemSet() );
+
+ SfxItemSet aParagraphAttribs( rOutliner.GetEmptyItemSet() );
+ if ( !aSelection.nStartPos )
+ aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
+ aSelection.nStartPos = 0;
+ rOutliner.QuickSetAttribs( aParagraphAttribs, aSelection );
+ nParaIndex++;
+ }
+ std::optional<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
+ rOutliner.Clear();
+ rOutliner.SetUpdateLayout( bOldUpdateMode );
+ pText->SetOutlinerParaObject( std::move(pNewText) );
+ // tdf#143315: restore stylesheet applied to Outliner's nodes when SdrTextObj initializes
+ // its attributes, but removed by Outliner::Init, which calls Outliner::Clear.
+ pText->SetStyleSheet(pText->GetStyleSheet(), true);
+}
+
+//static
+OUString SvxMSDffManager::MSDFFReadZString(SvStream& rIn,
+ sal_uInt32 nLen, bool bUniCode)
+{
+ if (!nLen)
+ return OUString();
+
+ OUString sBuf;
+
+ if( bUniCode )
+ sBuf = read_uInt16s_ToOUString(rIn, nLen/2);
+ else
+ sBuf = read_uInt8s_ToOUString(rIn, nLen, RTL_TEXTENCODING_MS_1252);
+
+ return comphelper::string::stripEnd(sBuf, 0);
+}
+
+static Size lcl_GetPrefSize(const Graphic& rGraf, const MapMode& aWanted)
+{
+ MapMode aPrefMapMode(rGraf.GetPrefMapMode());
+ if (aPrefMapMode == aWanted)
+ return rGraf.GetPrefSize();
+ Size aRetSize;
+ if (aPrefMapMode.GetMapUnit() == MapUnit::MapPixel)
+ {
+ aRetSize = Application::GetDefaultDevice()->PixelToLogic(
+ rGraf.GetPrefSize(), aWanted);
+ }
+ else
+ {
+ aRetSize = OutputDevice::LogicToLogic(
+ rGraf.GetPrefSize(), rGraf.GetPrefMapMode(), aWanted);
+ }
+ return aRetSize;
+}
+
+// sj: if the parameter pSet is null, then the resulting crop bitmap will be stored in rGraf,
+// otherwise rGraf is untouched and pSet is used to store the corresponding SdrGrafCropItem
+static void lcl_ApplyCropping( const DffPropSet& rPropSet, SfxItemSet* pSet, Graphic& rGraf )
+{
+ sal_Int32 nCropTop = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromTop, 0 ));
+ sal_Int32 nCropBottom = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromBottom, 0 ));
+ sal_Int32 nCropLeft = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromLeft, 0 ));
+ sal_Int32 nCropRight = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromRight, 0 ));
+
+ if( !(nCropTop || nCropBottom || nCropLeft || nCropRight) )
+ return;
+
+ double fFactor;
+ Size aCropSize;
+ BitmapEx aCropBitmap;
+ sal_uInt32 nTop( 0 ), nBottom( 0 ), nLeft( 0 ), nRight( 0 );
+
+ // Cropping has to be applied on a loaded graphic.
+ rGraf.makeAvailable();
+
+ if ( pSet ) // use crop attributes ?
+ aCropSize = lcl_GetPrefSize(rGraf, MapMode(MapUnit::Map100thMM));
+ else
+ {
+ aCropBitmap = rGraf.GetBitmapEx();
+ aCropSize = aCropBitmap.GetSizePixel();
+ }
+ if ( nCropTop )
+ {
+ fFactor = static_cast<double>(nCropTop) / 65536.0;
+ nTop = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Height() + 1 ) * fFactor ) + 0.5 );
+ }
+ if ( nCropBottom )
+ {
+ fFactor = static_cast<double>(nCropBottom) / 65536.0;
+ nBottom = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Height() + 1 ) * fFactor ) + 0.5 );
+ }
+ if ( nCropLeft )
+ {
+ fFactor = static_cast<double>(nCropLeft) / 65536.0;
+ nLeft = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Width() + 1 ) * fFactor ) + 0.5 );
+ }
+ if ( nCropRight )
+ {
+ fFactor = static_cast<double>(nCropRight) / 65536.0;
+ nRight = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Width() + 1 ) * fFactor ) + 0.5 );
+ }
+ if ( pSet ) // use crop attributes ?
+ pSet->Put( SdrGrafCropItem( nLeft, nTop, nRight, nBottom ) );
+ else
+ {
+ tools::Rectangle aCropRect( nLeft, nTop, aCropSize.Width() - nRight, aCropSize.Height() - nBottom );
+ aCropBitmap.Crop( aCropRect );
+ rGraf = aCropBitmap;
+ }
+}
+
+SdrObject* SvxMSDffManager::ImportGraphic( SvStream& rSt, SfxItemSet& rSet, const DffObjData& rObjData )
+{
+ SdrObject* pRet = nullptr;
+ OUString aLinkFileName;
+ tools::Rectangle aVisArea;
+
+ auto eFlags = GetPropertyValue(DFF_Prop_pibFlags, mso_blipflagDefault);
+ sal_uInt32 nBlipId = GetPropertyValue( DFF_Prop_pib, 0 );
+ bool bGrfRead = false,
+
+ // Graphic linked
+ bLinkGrf = 0 != ( eFlags & mso_blipflagLinkToFile );
+ {
+ OUString aFileName;
+ Graphic aGraf; // be sure this graphic is deleted before swapping out
+ if( SeekToContent( DFF_Prop_pibName, rSt ) )
+ aFileName = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_pibName, 0 ), true );
+
+ // AND, OR the following:
+ if( !( eFlags & mso_blipflagDoNotSave ) ) // Graphic embedded
+ {
+ bGrfRead = GetBLIP( nBlipId, aGraf, &aVisArea );
+ if ( !bGrfRead )
+ {
+ /*
+ Still no luck, lets look at the end of this record for a FBSE pool,
+ this fallback is a specific case for how word does it sometimes
+ */
+ bool bOk = rObjData.rSpHd.SeekToEndOfRecord( rSt );
+ DffRecordHeader aHd;
+ if (bOk)
+ {
+ bOk = ReadDffRecordHeader(rSt, aHd);
+ }
+ if (bOk && DFF_msofbtBSE == aHd.nRecType)
+ {
+ const sal_uLong nSkipBLIPLen = 20;
+ const sal_uLong nSkipShapePos = 4;
+ const sal_uLong nSkipBLIP = 4;
+ const sal_uLong nSkip =
+ nSkipBLIPLen + 4 + nSkipShapePos + 4 + nSkipBLIP;
+
+ if (nSkip <= aHd.nRecLen)
+ {
+ rSt.SeekRel(nSkip);
+ if (ERRCODE_NONE == rSt.GetError())
+ bGrfRead = GetBLIPDirect( rSt, aGraf, &aVisArea );
+ }
+ }
+ }
+ }
+ if ( bGrfRead )
+ {
+ // the writer is doing its own cropping, so this part affects only impress and calc,
+ // unless we're inside a group, in which case writer doesn't crop either
+ if (( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_CROP_BITMAPS ) || rObjData.nCalledByGroup != 0 )
+ lcl_ApplyCropping( *this, !bool( rObjData.nSpFlags & ShapeFlag::OLEShape ) ? &rSet : nullptr, aGraf );
+
+ if ( IsProperty( DFF_Prop_pictureTransparent ) )
+ {
+ sal_uInt32 nTransColor = GetPropertyValue( DFF_Prop_pictureTransparent, 0 );
+
+ if ( aGraf.GetType() == GraphicType::Bitmap )
+ {
+ BitmapEx aBitmapEx( aGraf.GetBitmapEx() );
+ aBitmapEx.CombineMaskOr( MSO_CLR_ToColor( nTransColor, DFF_Prop_pictureTransparent ), 9 );
+ aGraf = aBitmapEx;
+ }
+ }
+
+ sal_Int32 nContrast = GetPropertyValue( DFF_Prop_pictureContrast, 0x10000 );
+ /*
+ 0x10000 is msoffice 50%
+ < 0x10000 is in units of 1/50th of 0x10000 per 1%
+ > 0x10000 is in units where
+ a msoffice x% is stored as 50/(100-x) * 0x10000
+
+ plus, a (ui) microsoft % ranges from 0 to 100, OOO
+ from -100 to 100, so also normalize into that range
+ */
+ if ( nContrast > 0x10000 )
+ {
+ double fX = nContrast;
+ fX /= 0x10000;
+ fX /= 51; // 50 + 1 to round
+ fX = 1/fX;
+ nContrast = static_cast<sal_Int32>(fX);
+ nContrast -= 100;
+ nContrast = -nContrast;
+ nContrast = (nContrast-50)*2;
+ }
+ else if ( nContrast == 0x10000 )
+ nContrast = 0;
+ else
+ {
+ if (o3tl::checked_multiply<sal_Int32>(nContrast, 101, nContrast)) //100 + 1 to round
+ {
+ SAL_WARN("filter.ms", "bad Contrast value:" << nContrast);
+ nContrast = 0;
+ }
+ else
+ {
+ nContrast /= 0x10000;
+ nContrast -= 100;
+ }
+ }
+ sal_Int16 nBrightness = static_cast<sal_Int16>( static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_pictureBrightness, 0 )) / 327 );
+ sal_Int32 nGamma = GetPropertyValue( DFF_Prop_pictureGamma, 0x10000 );
+ GraphicDrawMode eDrawMode = GraphicDrawMode::Standard;
+ switch ( GetPropertyValue( DFF_Prop_pictureActive, 0 ) & 6 )
+ {
+ case 4 : eDrawMode = GraphicDrawMode::Greys; break;
+ case 6 : eDrawMode = GraphicDrawMode::Mono; break;
+ case 0 :
+ {
+ //office considers the converted values of (in OOo) 70 to be the
+ //"watermark" values, which can vary slightly due to rounding from the
+ //above values
+ if (( nContrast == -70 ) && ( nBrightness == 70 ))
+ {
+ nContrast = 0;
+ nBrightness = 0;
+ eDrawMode = GraphicDrawMode::Watermark;
+ };
+ }
+ break;
+ }
+
+ if ( nContrast || nBrightness || ( nGamma != 0x10000 ) || ( eDrawMode != GraphicDrawMode::Standard ) )
+ {
+ // MSO uses a different algorithm for contrast+brightness, LO applies contrast before brightness,
+ // while MSO apparently applies half of brightness before contrast and half after. So if only
+ // contrast or brightness need to be altered, the result is the same, but if both are involved,
+ // there's no way to map that, so just force a conversion of the image.
+ bool needsConversion = nContrast != 0 && nBrightness != 0;
+ if ( !bool(rObjData.nSpFlags & ShapeFlag::OLEShape) && !needsConversion )
+ {
+ if ( nBrightness )
+ rSet.Put( SdrGrafLuminanceItem( nBrightness ) );
+ if ( nContrast )
+ rSet.Put( SdrGrafContrastItem( static_cast<sal_Int16>(nContrast) ) );
+ if ( nGamma != 0x10000 )
+ rSet.Put( SdrGrafGamma100Item( nGamma / 655 ) );
+ if ( eDrawMode != GraphicDrawMode::Standard )
+ rSet.Put( SdrGrafModeItem( eDrawMode ) );
+ }
+ else
+ {
+ if ( eDrawMode == GraphicDrawMode::Watermark )
+ {
+ nContrast = 60;
+ nBrightness = 70;
+ eDrawMode = GraphicDrawMode::Standard;
+ }
+ switch ( aGraf.GetType() )
+ {
+ case GraphicType::Bitmap :
+ {
+ BitmapEx aBitmapEx( aGraf.GetBitmapEx() );
+ if ( nBrightness || nContrast || ( nGamma != 0x10000 ) )
+ aBitmapEx.Adjust( nBrightness, static_cast<sal_Int16>(nContrast), 0, 0, 0, static_cast<double>(nGamma) / 0x10000, false, true );
+ if ( eDrawMode == GraphicDrawMode::Greys )
+ aBitmapEx.Convert( BmpConversion::N8BitGreys );
+ else if ( eDrawMode == GraphicDrawMode::Mono )
+ aBitmapEx.Convert( BmpConversion::N1BitThreshold );
+ aGraf = aBitmapEx;
+
+ }
+ break;
+
+ case GraphicType::GdiMetafile :
+ {
+ GDIMetaFile aGdiMetaFile( aGraf.GetGDIMetaFile() );
+ if ( nBrightness || nContrast || ( nGamma != 0x10000 ) )
+ aGdiMetaFile.Adjust( nBrightness, static_cast<sal_Int16>(nContrast), 0, 0, 0, static_cast<double>(nGamma) / 0x10000, false, true );
+ if ( eDrawMode == GraphicDrawMode::Greys )
+ aGdiMetaFile.Convert( MtfConversion::N8BitGreys );
+ else if ( eDrawMode == GraphicDrawMode::Mono )
+ aGdiMetaFile.Convert( MtfConversion::N1BitThreshold );
+ aGraf = aGdiMetaFile;
+ }
+ break;
+ default: break;
+ }
+ }
+ }
+ }
+
+ // should it be an OLE object?
+ if( bGrfRead && !bLinkGrf && IsProperty( DFF_Prop_pictureId ) )
+ {
+ // TODO/LATER: in future probably the correct aspect should be provided here
+ // #i32596# - pass <nCalledByGroup> to method
+ pRet = ImportOLE( GetPropertyValue( DFF_Prop_pictureId, 0 ), aGraf, rObjData.aBoundRect, aVisArea, rObjData.nCalledByGroup );
+ }
+ if( !pRet )
+ {
+ pRet = new SdrGrafObj(*pSdrModel);
+ if( bGrfRead )
+ static_cast<SdrGrafObj*>(pRet)->SetGraphic( aGraf );
+
+ if( bLinkGrf && !bGrfRead ) // sj: #i55484# if the graphic was embedded ( bGrfRead == true ) then
+ { // we do not need to set a link. TODO: not to lose the information where the graphic is linked from
+ INetURLObject aAbsURL;
+ if ( !INetURLObject( maBaseURL ).GetNewAbsURL( aFileName, &aAbsURL ) )
+ {
+ OUString aValidURL;
+ if( osl::FileBase::getFileURLFromSystemPath( aFileName, aValidURL ) == osl::FileBase::E_None )
+ aAbsURL = INetURLObject( aValidURL );
+ }
+ if( aAbsURL.GetProtocol() != INetProtocol::NotValid )
+ {
+ aLinkFileName = aAbsURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
+ }
+ else
+ aLinkFileName = aFileName;
+ }
+ }
+
+ // set the size from BLIP if there is one
+ if ( bGrfRead && !aVisArea.IsEmpty() )
+ pRet->SetBLIPSizeRectangle( aVisArea );
+
+ if (pRet->GetName().isEmpty()) // SJ 22.02.00 : PPT OLE IMPORT:
+ { // name is already set in ImportOLE !!
+ // JP 01.12.99: SetName before SetModel - because in the other order the Bug 70098 is active
+ if ( ( eFlags & mso_blipflagType ) != mso_blipflagComment )
+ {
+ INetURLObject aURL;
+ aURL.SetSmartURL( aFileName );
+ pRet->SetName( aURL.getBase() );
+ }
+ else
+ pRet->SetName( aFileName );
+ }
+ }
+ pRet->NbcSetLogicRect( rObjData.aBoundRect );
+
+ if (SdrGrafObj* pGrafObj = dynamic_cast<SdrGrafObj*>(pRet))
+ {
+ if( aLinkFileName.getLength() )
+ {
+ pGrafObj->SetGraphicLink( aLinkFileName );
+ Graphic aGraphic(pGrafObj->GetGraphic());
+ aGraphic.setOriginURL(aLinkFileName);
+ }
+
+ if ( bLinkGrf && !bGrfRead )
+ {
+ Graphic aGraf(pGrafObj->GetGraphic());
+ lcl_ApplyCropping( *this, &rSet, aGraf );
+ }
+ }
+
+ return pRet;
+}
+
+// PptSlidePersistEntry& rPersistEntry, SdPage* pPage
+SdrObject* SvxMSDffManager::ImportObj( SvStream& rSt, SvxMSDffClientData& rClientData,
+ tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect, int nCalledByGroup, sal_Int32* pShapeId )
+{
+ SdrObject* pRet = nullptr;
+ DffRecordHeader aObjHd;
+ bool bOk = ReadDffRecordHeader(rSt, aObjHd);
+ if (bOk && aObjHd.nRecType == DFF_msofbtSpgrContainer)
+ {
+ pRet = ImportGroup( aObjHd, rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup, pShapeId );
+ }
+ else if (bOk && aObjHd.nRecType == DFF_msofbtSpContainer)
+ {
+ pRet = ImportShape( aObjHd, rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup, pShapeId );
+ }
+ aObjHd.SeekToBegOfRecord( rSt ); // restore FilePos
+ return pRet;
+}
+
+SdrObject* SvxMSDffManager::ImportGroup( const DffRecordHeader& rHd, SvStream& rSt, SvxMSDffClientData& rClientData,
+ tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect,
+ int nCalledByGroup, sal_Int32* pShapeId )
+{
+ SdrObject* pRet = nullptr;
+
+ if( pShapeId )
+ *pShapeId = 0;
+
+ if (!rHd.SeekToContent(rSt))
+ return pRet;
+
+ DffRecordHeader aRecHd; // the first atom has to be the SpContainer for the GroupObject
+ bool bOk = ReadDffRecordHeader(rSt, aRecHd);
+ if (bOk && aRecHd.nRecType == DFF_msofbtSpContainer)
+ {
+ mnFix16Angle = 0_deg100;
+ if (!aRecHd.SeekToBegOfRecord(rSt))
+ return pRet;
+ pRet = ImportObj( rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup + 1, pShapeId );
+ if ( pRet )
+ {
+ Degree100 nGroupRotateAngle(0);
+ ShapeFlag nSpFlags = nGroupShapeFlags;
+ nGroupRotateAngle = mnFix16Angle;
+
+ tools::Rectangle aClientRect( rClientRect );
+
+ tools::Rectangle aGlobalChildRect;
+ if ( !nCalledByGroup || rGlobalChildRect.IsEmpty() )
+ aGlobalChildRect = GetGlobalChildAnchor( rHd, rSt, aClientRect );
+ else
+ aGlobalChildRect = rGlobalChildRect;
+
+ if ( ( nGroupRotateAngle > 4500_deg100 && nGroupRotateAngle <= 13500_deg100 )
+ || ( nGroupRotateAngle > 22500_deg100 && nGroupRotateAngle <= 31500_deg100 ) )
+ {
+ sal_Int32 nHalfWidth = ( aClientRect.GetWidth() + 1 ) >> 1;
+ sal_Int32 nHalfHeight = ( aClientRect.GetHeight() + 1 ) >> 1;
+ Point aTopLeft( aClientRect.Left() + nHalfWidth - nHalfHeight,
+ aClientRect.Top() + nHalfHeight - nHalfWidth );
+ const tools::Long nRotatedWidth = aClientRect.GetHeight();
+ const tools::Long nRotatedHeight = aClientRect.GetWidth();
+ Size aNewSize(nRotatedWidth, nRotatedHeight);
+ tools::Rectangle aNewRect( aTopLeft, aNewSize );
+ aClientRect = aNewRect;
+ }
+
+ // now importing the inner objects of the group
+ if (!aRecHd.SeekToEndOfRecord(rSt))
+ return pRet;
+
+ while (rSt.good() && ( rSt.Tell() < rHd.GetRecEndFilePos()))
+ {
+ DffRecordHeader aRecHd2;
+ if (!ReadDffRecordHeader(rSt, aRecHd2))
+ break;
+ if ( aRecHd2.nRecType == DFF_msofbtSpgrContainer )
+ {
+ tools::Rectangle aGroupClientAnchor, aGroupChildAnchor;
+ GetGroupAnchors( aRecHd2, rSt, aGroupClientAnchor, aGroupChildAnchor, aClientRect, aGlobalChildRect );
+ if (!aRecHd2.SeekToBegOfRecord(rSt))
+ return pRet;
+ sal_Int32 nShapeId;
+ SdrObject* pTmp = ImportGroup( aRecHd2, rSt, rClientData, aGroupClientAnchor, aGroupChildAnchor, nCalledByGroup + 1, &nShapeId );
+ if (pTmp)
+ {
+ SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pRet);
+ if (pGroup && pGroup->GetSubList())
+ {
+ pGroup->GetSubList()->NbcInsertObject(pTmp);
+ if (nShapeId)
+ insertShapeId(nShapeId, pTmp);
+ }
+ else
+ FreeObj(rClientData, pTmp);
+ }
+ }
+ else if ( aRecHd2.nRecType == DFF_msofbtSpContainer )
+ {
+ if (!aRecHd2.SeekToBegOfRecord(rSt))
+ return pRet;
+ sal_Int32 nShapeId;
+ SdrObject* pTmp = ImportShape( aRecHd2, rSt, rClientData, aClientRect, aGlobalChildRect, nCalledByGroup + 1, &nShapeId );
+ if (pTmp)
+ {
+ SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pRet);
+ if (pGroup && pGroup->GetSubList())
+ {
+ pGroup->GetSubList()->NbcInsertObject(pTmp);
+ if (nShapeId)
+ insertShapeId(nShapeId, pTmp);
+ }
+ else
+ FreeObj(rClientData, pTmp);
+ }
+ }
+ if (!aRecHd2.SeekToEndOfRecord(rSt))
+ return pRet;
+ }
+
+ if ( nGroupRotateAngle )
+ pRet->NbcRotate( aClientRect.Center(), nGroupRotateAngle );
+ if ( nSpFlags & ShapeFlag::FlipV )
+ { // BoundRect in aBoundRect
+ Point aLeft( aClientRect.Left(), ( aClientRect.Top() + aClientRect.Bottom() ) >> 1 );
+ Point aRight( aLeft.X() + 1000, aLeft.Y() );
+ pRet->NbcMirror( aLeft, aRight );
+ }
+ if ( nSpFlags & ShapeFlag::FlipH )
+ { // BoundRect in aBoundRect
+ Point aTop( ( aClientRect.Left() + aClientRect.Right() ) >> 1, aClientRect.Top() );
+ Point aBottom( aTop.X(), aTop.Y() + 1000 );
+ pRet->NbcMirror( aTop, aBottom );
+ }
+ }
+ }
+ if (o3tl::make_unsigned(nCalledByGroup) < maPendingGroupData.size())
+ {
+ // finalization for this group is pending, do it now
+ pRet = FinalizeObj(maPendingGroupData.back().first, pRet);
+ maPendingGroupData.pop_back();
+ }
+ return pRet;
+}
+
+SdrObject* SvxMSDffManager::ImportShape( const DffRecordHeader& rHd, SvStream& rSt, SvxMSDffClientData& rClientData,
+ tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect,
+ int nCalledByGroup, sal_Int32* pShapeId )
+{
+ if( pShapeId )
+ *pShapeId = 0;
+
+ if (!rHd.SeekToBegOfRecord(rSt))
+ return nullptr;
+
+ DffObjData aObjData( rHd, rClientRect, nCalledByGroup );
+
+ aObjData.bRotateTextWithShape = ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL ) == 0;
+ maShapeRecords.Consume( rSt );
+ if( maShapeRecords.SeekToContent( rSt,
+ DFF_msofbtUDefProp ) )
+ {
+ sal_uInt32 nBytesLeft = maShapeRecords.Current()->nRecLen;
+ while( 5 < nBytesLeft )
+ {
+ sal_uInt16 nPID(0);
+ rSt.ReadUInt16(nPID);
+ if (!rSt.good())
+ break;
+ sal_uInt32 nUDData(0);
+ rSt.ReadUInt32(nUDData);
+ if (!rSt.good())
+ break;
+ if (nPID == 447)
+ {
+ mbRotateGranientFillWithAngle = nUDData & 0x20;
+ break;
+ }
+ nBytesLeft -= 6;
+ }
+ }
+ aObjData.bShapeType = maShapeRecords.SeekToContent( rSt, DFF_msofbtSp );
+ if ( aObjData.bShapeType )
+ {
+ sal_uInt32 temp(0);
+ rSt.ReadUInt32( aObjData.nShapeId )
+ .ReadUInt32( temp );
+ aObjData.nSpFlags = ShapeFlag(temp);
+ aObjData.eShapeType = static_cast<MSO_SPT>(maShapeRecords.Current()->nRecInstance);
+ }
+ else
+ {
+ aObjData.nShapeId = 0;
+ aObjData.nSpFlags = ShapeFlag::NONE;
+ aObjData.eShapeType = mso_sptNil;
+ }
+
+ if( pShapeId )
+ *pShapeId = aObjData.nShapeId;
+
+ aObjData.bOpt = maShapeRecords.SeekToContent( rSt, DFF_msofbtOPT, SEEK_FROM_CURRENT_AND_RESTART );
+ if ( aObjData.bOpt )
+ {
+ if (!maShapeRecords.Current()->SeekToBegOfRecord(rSt))
+ return nullptr;
+#ifdef DBG_AUTOSHAPE
+ ReadPropSet( rSt, &rClientData, (sal_uInt32)aObjData.eShapeType );
+#else
+ ReadPropSet( rSt, &rClientData );
+#endif
+ }
+ else
+ {
+ InitializePropSet( DFF_msofbtOPT ); // get the default PropSet
+ static_cast<DffPropertyReader*>(this)->mnFix16Angle = 0_deg100;
+ }
+
+ aObjData.bOpt2 = maShapeRecords.SeekToContent( rSt, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART );
+ if ( aObjData.bOpt2 )
+ {
+ maShapeRecords.Current()->SeekToBegOfRecord( rSt );
+ pSecPropSet.reset( new DffPropertyReader( *this ) );
+ pSecPropSet->ReadPropSet( rSt, nullptr );
+ }
+
+ aObjData.bChildAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtChildAnchor, SEEK_FROM_CURRENT_AND_RESTART );
+ if ( aObjData.bChildAnchor )
+ {
+ sal_Int32 l(0), o(0), r(0), u(0);
+ rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
+ Scale( l );
+ Scale( o );
+ Scale( r );
+ Scale( u );
+ aObjData.aChildAnchor = tools::Rectangle( l, o, r, u );
+ sal_Int32 nWidth, nHeight;
+ if (!rGlobalChildRect.IsEmpty() && !rClientRect.IsEmpty() && rGlobalChildRect.GetWidth() && rGlobalChildRect.GetHeight() &&
+ !o3tl::checked_sub(r, l, nWidth) && !o3tl::checked_sub(u, o, nHeight))
+ {
+ double fXScale = static_cast<double>(rClientRect.GetWidth()) / static_cast<double>(rGlobalChildRect.GetWidth());
+ double fYScale = static_cast<double>(rClientRect.GetHeight()) / static_cast<double>(rGlobalChildRect.GetHeight());
+ double fl = ( ( l - rGlobalChildRect.Left() ) * fXScale ) + rClientRect.Left();
+ double fo = ( ( o - rGlobalChildRect.Top() ) * fYScale ) + rClientRect.Top();
+ double fWidth = nWidth * fXScale;
+ double fHeight = nHeight * fYScale;
+ aObjData.aChildAnchor = tools::Rectangle( Point( fl, fo ), Size( fWidth + 1, fHeight + 1 ) );
+ }
+ }
+
+ aObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtClientAnchor, SEEK_FROM_CURRENT_AND_RESTART );
+ if ( aObjData.bClientAnchor )
+ ProcessClientAnchor2( rSt, *maShapeRecords.Current(), aObjData );
+
+ if ( aObjData.bChildAnchor )
+ aObjData.aBoundRect = aObjData.aChildAnchor;
+
+ if ( aObjData.nSpFlags & ShapeFlag::Background )
+ aObjData.aBoundRect = tools::Rectangle( Point(), Size( 1, 1 ) );
+
+ SdrObjectUniquePtr xRet;
+
+ tools::Rectangle aTextRect;
+ if ( !aObjData.aBoundRect.IsEmpty() )
+ { // apply rotation to the BoundingBox BEFORE an object has been generated
+ if( mnFix16Angle )
+ {
+ Degree100 nAngle = mnFix16Angle;
+ if ( ( nAngle > 4500_deg100 && nAngle <= 13500_deg100 ) || ( nAngle > 22500_deg100 && nAngle <= 31500_deg100 ) )
+ {
+ sal_Int32 nHalfWidth = ( aObjData.aBoundRect.GetWidth() + 1 ) >> 1;
+ sal_Int32 nHalfHeight = ( aObjData.aBoundRect.GetHeight() + 1 ) >> 1;
+ Point aTopLeft( aObjData.aBoundRect.Left() + nHalfWidth - nHalfHeight,
+ aObjData.aBoundRect.Top() + nHalfHeight - nHalfWidth );
+ Size aNewSize( aObjData.aBoundRect.GetHeight(), aObjData.aBoundRect.GetWidth() );
+ tools::Rectangle aNewRect( aTopLeft, aNewSize );
+ aObjData.aBoundRect = aNewRect;
+ }
+ }
+ aTextRect = aObjData.aBoundRect;
+ bool bGraphic = IsProperty( DFF_Prop_pib ) ||
+ IsProperty( DFF_Prop_pibName ) ||
+ IsProperty( DFF_Prop_pibFlags );
+
+ if ( aObjData.nSpFlags & ShapeFlag::Group )
+ {
+ xRet.reset(new SdrObjGroup(*pSdrModel));
+ /* After CWS aw033 has been integrated, an empty group object
+ cannot store its resulting bounding rectangle anymore. We have
+ to return this rectangle via rClientRect now, but only, if
+ caller has not passed an own bounding ractangle. */
+ if ( rClientRect.IsEmpty() )
+ rClientRect = aObjData.aBoundRect;
+ nGroupShapeFlags = aObjData.nSpFlags;
+ }
+ else if ( ( aObjData.eShapeType != mso_sptNil ) || IsProperty( DFF_Prop_pVertices ) || bGraphic )
+ {
+ SfxItemSet aSet( pSdrModel->GetItemPool() );
+
+ bool bIsConnector = ( ( aObjData.eShapeType >= mso_sptStraightConnector1 ) && ( aObjData.eShapeType <= mso_sptCurvedConnector5 ) );
+ Degree100 nObjectRotation = mnFix16Angle;
+ ShapeFlag nSpFlags = aObjData.nSpFlags;
+
+ if ( bGraphic )
+ {
+ if (!mbSkipImages) {
+ xRet.reset(ImportGraphic(rSt, aSet, aObjData)); // SJ: #68396# is no longer true (fixed in ppt2000)
+ ApplyAttributes( rSt, aSet, aObjData );
+ xRet->SetMergedItemSet(aSet);
+ }
+ }
+ else if ( aObjData.eShapeType == mso_sptLine && !( GetPropertyValue( DFF_Prop_fc3DLightFace, 0 ) & 8 ) )
+ {
+ basegfx::B2DPolygon aPoly;
+ aPoly.append(basegfx::B2DPoint(aObjData.aBoundRect.Left(), aObjData.aBoundRect.Top()));
+ aPoly.append(basegfx::B2DPoint(aObjData.aBoundRect.Right(), aObjData.aBoundRect.Bottom()));
+ xRet.reset(new SdrPathObj(
+ *pSdrModel,
+ SdrObjKind::Line,
+ basegfx::B2DPolyPolygon(aPoly)));
+ ApplyAttributes( rSt, aSet, aObjData );
+ xRet->SetMergedItemSet(aSet);
+ }
+ else
+ {
+ if ( GetCustomShapeContent( aObjData.eShapeType ) || IsProperty( DFF_Prop_pVertices ) )
+ {
+
+ ApplyAttributes( rSt, aSet, aObjData );
+
+ xRet.reset(new SdrObjCustomShape(*pSdrModel));
+
+ sal_uInt32 ngtextFStrikethrough = GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 );
+ bool bIsFontwork = ( ngtextFStrikethrough & 0x4000 ) != 0;
+
+ // in case of a FontWork, the text is set by the escher import
+ if ( bIsFontwork )
+ {
+ OUString aObjectText;
+ OUString aFontName;
+
+ if ( SeekToContent( DFF_Prop_gtextFont, rSt ) )
+ {
+ SvxFontItem aLatin(EE_CHAR_FONTINFO), aAsian(EE_CHAR_FONTINFO_CJK), aComplex(EE_CHAR_FONTINFO_CTL);
+ GetDefaultFonts( aLatin, aAsian, aComplex );
+
+ aFontName = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_gtextFont, 0 ), true );
+ aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
+ PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO ));
+ aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
+ PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO_CJK ) );
+ aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
+ PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO_CTL ) );
+ }
+
+ // SJ: applying fontattributes for Fontwork :
+ if ( IsHardAttribute( DFF_Prop_gtextFItalic ) )
+ aSet.Put( SvxPostureItem( ( ngtextFStrikethrough & 0x0010 ) != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
+
+ if ( IsHardAttribute( DFF_Prop_gtextFBold ) )
+ aSet.Put( SvxWeightItem( ( ngtextFStrikethrough & 0x0020 ) != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
+
+ // SJ TODO: Vertical Writing is not correct, instead
+ // this should be replaced through "CharacterRotation"
+ // by 90 degrees, therefore a new Item has to be
+ // supported by svx core, api and xml file format
+ static_cast<SdrObjCustomShape*>(xRet.get())->SetVerticalWriting( ( ngtextFStrikethrough & 0x2000 ) != 0 );
+
+ if ( SeekToContent( DFF_Prop_gtextUNICODE, rSt ) )
+ {
+ aObjectText = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_gtextUNICODE, 0 ), true );
+ ReadObjText(aObjectText, xRet.get());
+ }
+
+ auto eGeoTextAlign = GetPropertyValue(DFF_Prop_gtextAlign, mso_alignTextCenter);
+ {
+ SdrTextHorzAdjust eHorzAdjust;
+ switch( eGeoTextAlign )
+ {
+ case mso_alignTextLetterJust :
+ case mso_alignTextWordJust :
+ case mso_alignTextStretch : eHorzAdjust = SDRTEXTHORZADJUST_BLOCK; break;
+ default:
+ case mso_alignTextInvalid :
+ case mso_alignTextCenter : eHorzAdjust = SDRTEXTHORZADJUST_CENTER; break;
+ case mso_alignTextLeft : eHorzAdjust = SDRTEXTHORZADJUST_LEFT; break;
+ case mso_alignTextRight : eHorzAdjust = SDRTEXTHORZADJUST_RIGHT; break;
+ }
+ aSet.Put( SdrTextHorzAdjustItem( eHorzAdjust ) );
+
+ drawing::TextFitToSizeType eFTS = drawing::TextFitToSizeType_NONE;
+ if ( eGeoTextAlign == mso_alignTextStretch )
+ eFTS = drawing::TextFitToSizeType_ALLLINES;
+ aSet.Put( SdrTextFitToSizeTypeItem( eFTS ) );
+ }
+ if ( IsProperty( DFF_Prop_gtextSpacing ) )
+ {
+ sal_Int32 nTextWidth = GetPropertyValue( DFF_Prop_gtextSpacing, 1 << 16 ) / 655;
+ if ( nTextWidth != 100 )
+ aSet.Put( SvxCharScaleWidthItem( static_cast<sal_uInt16>(nTextWidth), EE_CHAR_FONTWIDTH ) );
+ }
+ if ( ngtextFStrikethrough & 0x1000 ) // SJ: Font Kerning On ?
+ aSet.Put( SvxKerningItem( 1, EE_CHAR_KERNING ) );
+
+ // #i119496# the resize autoshape to fit text attr of word art in MS PPT is always false
+ aSet.Put(makeSdrTextAutoGrowHeightItem(false));
+ aSet.Put(makeSdrTextAutoGrowWidthItem(false));
+
+ bool bWithPadding = !( ngtextFStrikethrough & use_gtextFBestFit
+ && ngtextFStrikethrough & use_gtextFShrinkFit
+ && ngtextFStrikethrough & use_gtextFStretch
+ && ngtextFStrikethrough & gtextFBestFit
+ && ngtextFStrikethrough & gtextFShrinkFit
+ && ngtextFStrikethrough & gtextFStretch );
+
+ if ( bWithPadding )
+ {
+ // trim, remove additional space
+ VclPtr<VirtualDevice> pDevice = VclPtr<VirtualDevice>::Create();
+ vcl::Font aFont = pDevice->GetFont();
+ aFont.SetFamilyName( aFontName );
+ aFont.SetFontSize( Size( 0, 96 ) );
+ pDevice->SetFont( aFont );
+
+ auto nTextWidth = pDevice->GetTextWidth( aObjectText );
+ OUString aObjName = GetPropertyString( DFF_Prop_wzName, rSt );
+ if ( nTextWidth && aObjData.eShapeType == mso_sptTextPlainText
+ && aObjName.match( "PowerPlusWaterMarkObject" ) )
+ {
+ double fRatio = static_cast<double>(pDevice->GetTextHeight()) / nTextWidth;
+ sal_Int32 nNewHeight = fRatio * aObjData.aBoundRect.getWidth();
+ sal_Int32 nPaddingY = aObjData.aBoundRect.getHeight() - nNewHeight;
+
+ if ( nPaddingY > 0 )
+ aObjData.aBoundRect.setHeight( nNewHeight );
+ }
+ }
+ }
+ xRet->SetMergedItemSet( aSet );
+
+ // sj: taking care of rtl, ltr. In case of fontwork mso. seems not to be able to set
+ // proper text directions, instead the text default is depending to the string.
+ // so we have to calculate the a text direction from string:
+ if ( bIsFontwork )
+ {
+ OutlinerParaObject* pParaObj = static_cast<SdrObjCustomShape*>(xRet.get())->GetOutlinerParaObject();
+ if ( pParaObj )
+ {
+ SdrOutliner& rOutliner = static_cast<SdrObjCustomShape*>(xRet.get())->ImpGetDrawOutliner();
+ rOutliner.SetStyleSheetPool(static_cast< SfxStyleSheetPool* >(xRet->getSdrModelFromSdrObject().GetStyleSheetPool()));
+ bool bOldUpdateMode = rOutliner.SetUpdateLayout( false );
+ rOutliner.SetText( *pParaObj );
+ ScopedVclPtrInstance< VirtualDevice > pVirDev(DeviceFormat::DEFAULT);
+ pVirDev->SetMapMode(MapMode(MapUnit::Map100thMM));
+ sal_Int32 i, nParagraphs = rOutliner.GetParagraphCount();
+ if ( nParagraphs )
+ {
+ bool bCreateNewParaObject = false;
+ for ( i = 0; i < nParagraphs; i++ )
+ {
+ OUString aString(rOutliner.GetText(rOutliner.GetParagraph(i)));
+ bool bIsRTL = pVirDev->GetTextIsRTL(aString, 0, aString.getLength());
+ if ( bIsRTL )
+ {
+ SfxItemSet aSet2( rOutliner.GetParaAttribs( i ) );
+ aSet2.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB, EE_PARA_WRITINGDIR ) );
+ rOutliner.SetParaAttribs( i, aSet2 );
+ bCreateNewParaObject = true;
+ }
+ }
+ if ( bCreateNewParaObject )
+ {
+ std::optional<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
+ rOutliner.Init( OutlinerMode::TextObject );
+ static_cast<SdrObjCustomShape*>(xRet.get())->NbcSetOutlinerParaObject( std::move(pNewText) );
+ }
+ }
+ rOutliner.Clear();
+ rOutliner.SetUpdateLayout( bOldUpdateMode );
+ }
+ }
+
+ // mso_sptArc special treating
+ // tdf#124029: A new custom shape is generated from prototype 'msoArc'. Values, which are
+ // read here, are adapted and merged. The shape type is changed, so this code
+ // applies only if importing arcs from MS Office.
+ if ( aObjData.eShapeType == mso_sptArc )
+ {
+ static const OUStringLiteral sAdjustmentValues( u"AdjustmentValues" );
+ static const OUStringLiteral sViewBox( u"ViewBox" );
+ static const OUStringLiteral sPath( u"Path" );
+ SdrCustomShapeGeometryItem aGeometryItem( static_cast<SdrObjCustomShape*>(xRet.get())->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
+ PropertyValue aPropVal;
+
+ // The default arc goes form -90deg to 0deg. Replace general defaults used
+ // when read from stream with this specific values.
+ double fStartAngle(-90.0);
+ double fEndAngle(0.0);
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues;
+ const uno::Any* pAny = aGeometryItem.GetPropertyValueByName(sAdjustmentValues);
+ if (pAny && (*pAny >>= seqAdjustmentValues) && seqAdjustmentValues.getLength() > 1)
+ {
+ auto pseqAdjustmentValues = seqAdjustmentValues.getArray();
+ if (seqAdjustmentValues[0].State == css::beans::PropertyState_DEFAULT_VALUE)
+ {
+ pseqAdjustmentValues[0].Value <<= -90.0;
+ pseqAdjustmentValues[0].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
+ }
+ if (seqAdjustmentValues[1].State == css::beans::PropertyState_DEFAULT_VALUE)
+ {
+ pseqAdjustmentValues[1].Value <<= 0.0;
+ pseqAdjustmentValues[1].State = com::sun::star::beans::PropertyState_DIRECT_VALUE;
+ }
+ seqAdjustmentValues[0].Value >>= fStartAngle;
+ seqAdjustmentValues[1].Value >>= fEndAngle;
+ aPropVal.Name = sAdjustmentValues;
+ aPropVal.Value <<= seqAdjustmentValues;
+ aGeometryItem.SetPropertyValue(aPropVal);
+ }
+
+ // arc first command is always wr -- clockwise arc
+ // the parameters are : (left,top),(right,bottom),start(x,y),end(x,y)
+ // The left/top vertex of the frame rectangle of the sector is the origin
+ // of the shape internal coordinate system in MS Office. The default arc
+ // has an ellipse frame rectangle with LT(-21600,0) and
+ // RB(21600,43200) in this coordinate system.
+ basegfx::B2DRectangle aEllipseRect_MS(-21600.0, 0.0, 21600.0, 43200.0);
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
+ pAny = aGeometryItem.GetPropertyValueByName( sPath, "Coordinates" );
+ if (pAny && (*pAny >>= seqCoordinates) && (seqCoordinates.getLength() >= 2))
+ {
+ auto const nL
+ = *o3tl::doAccess<sal_Int32>(seqCoordinates[0].First.Value);
+ auto const nT
+ = *o3tl::doAccess<sal_Int32>(seqCoordinates[0].Second.Value);
+ auto const nR
+ = *o3tl::doAccess<sal_Int32>(seqCoordinates[1].First.Value);
+ auto const nB
+ = *o3tl::doAccess<sal_Int32>(seqCoordinates[1].Second.Value);
+ aEllipseRect_MS = basegfx::B2DRectangle(nL, nT, nR, nB);
+ }
+
+ // MS Office uses the pie frame rectangle as reference for outer position
+ // and size of the shape and for text in the shape. We can get this rectangle
+ // from imported viewBox or from the arc geometry.
+ basegfx::B2DRectangle aPieRect_MS(0.0 , 0.0, 21600.0, 21600.0);
+ pAny = aGeometryItem.GetPropertyValueByName(sPath,sViewBox);
+ css::awt::Rectangle aImportedViewBox;
+ if (pAny && (*pAny >>= aImportedViewBox))
+ {
+ aPieRect_MS = basegfx::B2DRectangle( aImportedViewBox.X,
+ aImportedViewBox.Y,
+ aImportedViewBox.X + aImportedViewBox.Width,
+ aImportedViewBox.Y + aImportedViewBox.Height);
+ }
+ else
+ {
+ double fRadStartAngle(basegfx::deg2rad(NormAngle360(fStartAngle)));
+ double fRadEndAngle(basegfx::deg2rad(NormAngle360(fEndAngle)));
+ basegfx::B2DPoint aCenter(aEllipseRect_MS.getCenter());
+ basegfx::B2DPolygon aTempPie(
+ basegfx::utils::createPolygonFromEllipseSegment(
+ aCenter,
+ aEllipseRect_MS.getWidth() * 0.5,
+ aEllipseRect_MS.getHeight() * 0.5,
+ fRadStartAngle,
+ fRadEndAngle));
+ aTempPie.append(aCenter);
+ aPieRect_MS = aTempPie.getB2DRange();
+ }
+
+ // MS Office uses for mso_sptArc a frame rectangle (=resize handles)
+ // which encloses only the sector, LibreOffice uses for custom shapes as
+ // default a frame rectangle, which encloses the entire ellipse. That would
+ // result in wrong positions in Writer and Calc, see tdf#124029.
+ // We workaround this problem, by setting a suitable viewBox.
+ bool bIsImportPPT(GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_PPT);
+ if (bIsImportPPT || aPieRect_MS.getWidth() == 0 || aPieRect_MS.getHeight() == 0)
+ { // clear item, so that default from EnhancedCustomShapeGeometry is used
+ aGeometryItem.ClearPropertyValue(sViewBox);
+ }
+ else
+ {
+ double fX((aPieRect_MS.getMinX() - aEllipseRect_MS.getMinX()) / 2.0);
+ double fY((aPieRect_MS.getMinY() - aEllipseRect_MS.getMinY()) / 2.0);
+ css::awt::Rectangle aViewBox_LO; // in LO coordinate system
+ aViewBox_LO.X = static_cast<sal_Int32>(fX);
+ aViewBox_LO.Y = static_cast<sal_Int32>(fY);
+ aViewBox_LO.Width = static_cast<sal_Int32>(aPieRect_MS.getWidth() / 2.0);
+ aViewBox_LO.Height = static_cast<sal_Int32>(aPieRect_MS.getHeight() / 2.0);
+ aPropVal.Name = sViewBox;
+ aPropVal.Value <<= aViewBox_LO;
+ aGeometryItem.SetPropertyValue(aPropVal);
+ }
+
+ // aObjData.aBoundRect contains position and size of the sector in (outer)
+ // logic coordinates, e.g. for PPT in 1/100 mm, for Word in twips.
+ // For Impress the default viewBox is used, so adapt aObjData.aBoundRect.
+ tools::Rectangle aOldBoundRect(aObjData.aBoundRect); // backup, needed later on
+ if (bIsImportPPT)
+ {
+ double fLogicXOfs(0.0); // LogicLeft_LO = LogicLeft_MS + fXLogicOfs
+ double fLogicYOfs(0.0);
+ double fLogicPieWidth(aObjData.aBoundRect.getWidth());
+ double fLogicPieHeight(aObjData.aBoundRect.getHeight());
+ double fLogicEllipseWidth(0.0); // to be LogicWidth_LO
+ double fLogicEllipseHeight(0.0);
+ if (aPieRect_MS.getWidth())
+ {
+ // fXScale = ratio 'logic length' : 'shape internal length'
+ double fXScale = fLogicPieWidth / aPieRect_MS.getWidth();
+ if (nSpFlags & ShapeFlag::FlipH)
+ fLogicXOfs = (aPieRect_MS.getMaxX() - aEllipseRect_MS.getMaxX()) * fXScale;
+ else
+ fLogicXOfs = (aEllipseRect_MS.getMinX() - aPieRect_MS.getMinX()) * fXScale;
+ fLogicEllipseWidth = aEllipseRect_MS.getWidth() * fXScale;
+ }
+ if (aPieRect_MS.getHeight())
+ {
+ double fYScale = fLogicPieHeight / aPieRect_MS.getHeight();
+ if (nSpFlags & ShapeFlag::FlipV)
+ fLogicYOfs = (aPieRect_MS.getMaxY() - aEllipseRect_MS.getMaxY()) * fYScale;
+ else
+ fLogicYOfs = (aEllipseRect_MS.getMinY() - aPieRect_MS.getMinY()) * fYScale;
+ fLogicEllipseHeight = aEllipseRect_MS.getHeight() * fYScale;
+ }
+ aObjData.aBoundRect = tools::Rectangle(
+ Point(aOldBoundRect.Left() + static_cast<sal_Int32>(fLogicXOfs),
+ aOldBoundRect.Top() + static_cast<sal_Int32>(fLogicYOfs)),
+ Size(static_cast<sal_Int32>(fLogicEllipseWidth),
+ static_cast<sal_Int32>(fLogicEllipseHeight)));
+ }
+ // else nothing to do. aObjData.aBoundRect corresponds to changed viewBox.
+
+ // creating the text frame -> scaling into (0,0),(21600,21600) destination coordinate system
+ double fTextFrameScaleX = 0.0;
+ double fTextFrameScaleY = 0.0;
+ if (aEllipseRect_MS.getWidth())
+ fTextFrameScaleX = 21600.0 / aEllipseRect_MS.getWidth();
+ if (aEllipseRect_MS.getHeight())
+ fTextFrameScaleY = 21600.0 / aEllipseRect_MS.getHeight();
+
+ sal_Int32 nLeft = static_cast<sal_Int32>((aPieRect_MS.getMinX() - aEllipseRect_MS.getMinX()) * fTextFrameScaleX );
+ sal_Int32 nTop = static_cast<sal_Int32>((aPieRect_MS.getMinY() - aEllipseRect_MS.getMinY()) * fTextFrameScaleY );
+ sal_Int32 nRight = static_cast<sal_Int32>((aPieRect_MS.getMaxX() - aEllipseRect_MS.getMinX()) * fTextFrameScaleX );
+ sal_Int32 nBottom= static_cast<sal_Int32>((aPieRect_MS.getMaxY() - aEllipseRect_MS.getMinY()) * fTextFrameScaleY );
+ css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > aTextFrame( 1 );
+ auto pTextFrame = aTextFrame.getArray();
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pTextFrame[ 0 ].TopLeft.First, nLeft );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pTextFrame[ 0 ].TopLeft.Second, nTop );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pTextFrame[ 0 ].BottomRight.First, nRight );
+ EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( pTextFrame[ 0 ].BottomRight.Second,nBottom );
+ PropertyValue aProp;
+ aProp.Name = "TextFrames";
+ aProp.Value <<= aTextFrame;
+ aGeometryItem.SetPropertyValue( sPath, aProp );
+
+ // sj: taking care of the different rotation points, since the new arc is having a bigger snaprect
+ if ( mnFix16Angle )
+ {
+ Degree100 nAngle = mnFix16Angle;
+ if ( nSpFlags & ShapeFlag::FlipH )
+ nAngle = 36000_deg100 - nAngle;
+ if ( nSpFlags & ShapeFlag::FlipV )
+ nAngle = -nAngle;
+ double a = toRadians(nAngle);
+ double ss = sin( a );
+ double cc = cos( a );
+ Point aP1( aOldBoundRect.TopLeft() );
+ Point aC1( aObjData.aBoundRect.Center() );
+ Point aP2( aOldBoundRect.TopLeft() );
+ Point aC2( aOldBoundRect.Center() );
+ RotatePoint( aP1, aC1, ss, cc );
+ RotatePoint( aP2, aC2, ss, cc );
+ aObjData.aBoundRect.Move( aP2.X() - aP1.X(), aP2.Y() - aP1.Y() );
+ }
+
+ // clearing items, so MergeDefaultAttributes will set the corresponding
+ // defaults from EnhancedCustomShapeGeometry
+ aGeometryItem.ClearPropertyValue( "Handles" );
+ aGeometryItem.ClearPropertyValue( "Equations" );
+ aGeometryItem.ClearPropertyValue( sPath );
+
+ static_cast<SdrObjCustomShape*>(xRet.get())->SetMergedItem( aGeometryItem );
+ static_cast<SdrObjCustomShape*>(xRet.get())->MergeDefaultAttributes();
+
+ // now setting a new name, so the above correction is only done once when importing from ms
+ SdrCustomShapeGeometryItem aGeoName( static_cast<SdrObjCustomShape*>(xRet.get())->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
+ aPropVal.Name = "Type";
+ aPropVal.Value <<= OUString( "mso-spt100" );
+ aGeoName.SetPropertyValue( aPropVal );
+ static_cast<SdrObjCustomShape*>(xRet.get())->SetMergedItem( aGeoName );
+ }
+ else
+ static_cast<SdrObjCustomShape*>(xRet.get())->MergeDefaultAttributes();
+
+ xRet->SetSnapRect( aObjData.aBoundRect );
+ EnhancedCustomShape2d aCustomShape2d(static_cast<SdrObjCustomShape&>(*xRet));
+ aTextRect = aCustomShape2d.GetTextRect();
+
+ if( bIsConnector )
+ {
+ if( nObjectRotation )
+ xRet->NbcRotate( aObjData.aBoundRect.Center(), nObjectRotation );
+ // mirrored horizontally?
+ if ( nSpFlags & ShapeFlag::FlipH )
+ {
+ tools::Rectangle aBndRect(xRet->GetSnapRect());
+ Point aTop( ( aBndRect.Left() + aBndRect.Right() ) >> 1, aBndRect.Top() );
+ Point aBottom( aTop.X(), aTop.Y() + 1000 );
+ xRet->NbcMirror( aTop, aBottom );
+ }
+ // mirrored vertically?
+ if ( nSpFlags & ShapeFlag::FlipV )
+ {
+ tools::Rectangle aBndRect(xRet->GetSnapRect());
+ Point aLeft( aBndRect.Left(), ( aBndRect.Top() + aBndRect.Bottom() ) >> 1 );
+ Point aRight( aLeft.X() + 1000, aLeft.Y() );
+ xRet->NbcMirror( aLeft, aRight );
+ }
+ basegfx::B2DPolyPolygon aPoly( static_cast<SdrObjCustomShape*>(xRet.get())->GetLineGeometry( true ) );
+
+ xRet.reset(new SdrEdgeObj(*pSdrModel));
+ ApplyAttributes( rSt, aSet, aObjData );
+ xRet->SetLogicRect( aObjData.aBoundRect );
+ xRet->SetMergedItemSet(aSet);
+
+ // connectors
+ auto eConnectorStyle = GetPropertyValue(DFF_Prop_cxstyle, mso_cxstyleStraight);
+
+ static_cast<SdrEdgeObj*>(xRet.get())->ConnectToNode(true, nullptr);
+ static_cast<SdrEdgeObj*>(xRet.get())->ConnectToNode(false, nullptr);
+
+ Point aPoint1( aObjData.aBoundRect.TopLeft() );
+ Point aPoint2( aObjData.aBoundRect.BottomRight() );
+
+ // pay attention to the rotations
+ if ( nObjectRotation )
+ {
+ double a = toRadians(nObjectRotation);
+ Point aCenter( aObjData.aBoundRect.Center() );
+ double ss = sin(a);
+ double cc = cos(a);
+
+ RotatePoint(aPoint1, aCenter, ss, cc);
+ RotatePoint(aPoint2, aCenter, ss, cc);
+
+ // #i120437# reset rotation, it is part of the path and shall not be applied again
+ nObjectRotation = 0_deg100;
+ }
+
+ // rotate/mirror line within the area as we need it
+ if ( nSpFlags & ShapeFlag::FlipH )
+ {
+ sal_Int32 n = aPoint1.X();
+ aPoint1.setX( aPoint2.X() );
+ aPoint2.setX( n );
+
+ // #i120437# reset hor flip
+ nSpFlags &= ~ShapeFlag::FlipH;
+ }
+ if ( nSpFlags & ShapeFlag::FlipV )
+ {
+ sal_Int32 n = aPoint1.Y();
+ aPoint1.setY( aPoint2.Y() );
+ aPoint2.setY( n );
+
+ // #i120437# reset ver flip
+ nSpFlags &= ~ShapeFlag::FlipV;
+ }
+
+ xRet->NbcSetPoint(aPoint1, 0); // start point
+ xRet->NbcSetPoint(aPoint2, 1); // endpoint
+
+ sal_Int32 n1HorzDist, n1VertDist, n2HorzDist, n2VertDist;
+ n1HorzDist = n1VertDist = n2HorzDist = n2VertDist = 0;
+ switch( eConnectorStyle )
+ {
+ case mso_cxstyleBent:
+ {
+ aSet.Put( SdrEdgeKindItem( SdrEdgeKind::OrthoLines ) );
+ n1HorzDist = n1VertDist = n2HorzDist = n2VertDist = 630;
+ }
+ break;
+ case mso_cxstyleCurved:
+ aSet.Put( SdrEdgeKindItem( SdrEdgeKind::Bezier ) );
+ break;
+ default: // mso_cxstyleStraight || mso_cxstyleNone
+ aSet.Put( SdrEdgeKindItem( SdrEdgeKind::OneLine ) );
+ break;
+ }
+ aSet.Put( SdrEdgeNode1HorzDistItem( n1HorzDist ) );
+ aSet.Put( SdrEdgeNode1VertDistItem( n1VertDist ) );
+ aSet.Put( SdrEdgeNode2HorzDistItem( n2HorzDist ) );
+ aSet.Put( SdrEdgeNode2VertDistItem( n2VertDist ) );
+
+ static_cast<SdrEdgeObj*>(xRet.get())->SetEdgeTrackPath( aPoly );
+ xRet->SetMergedItemSet(aSet);
+ }
+ if ( aObjData.eShapeType == mso_sptLine )
+ {
+ xRet->SetMergedItemSet(aSet);
+ static_cast<SdrObjCustomShape*>(xRet.get())->MergeDefaultAttributes();
+ }
+ }
+ }
+
+ if (xRet)
+ {
+ if( nObjectRotation )
+ xRet->NbcRotate( aObjData.aBoundRect.Center(), nObjectRotation );
+ // mirrored horizontally?
+ if ( nSpFlags & ShapeFlag::FlipH )
+ {
+ tools::Rectangle aBndRect(xRet->GetSnapRect());
+ Point aTop( ( aBndRect.Left() + aBndRect.Right() ) >> 1, aBndRect.Top() );
+ Point aBottom( aTop.X(), aTop.Y() + 1000 );
+ xRet->NbcMirror(aTop, aBottom);
+ }
+ // mirrored vertically?
+ if ( nSpFlags & ShapeFlag::FlipV )
+ {
+ tools::Rectangle aBndRect(xRet->GetSnapRect());
+ Point aLeft( aBndRect.Left(), ( aBndRect.Top() + aBndRect.Bottom() ) >> 1 );
+ Point aRight( aLeft.X() + 1000, aLeft.Y() );
+ xRet->NbcMirror(aLeft, aRight);
+ }
+ }
+ }
+ }
+
+ // #i51348# #118052# name of the shape
+ if (xRet)
+ {
+ OUString aObjName = GetPropertyString( DFF_Prop_wzName, rSt );
+ if( !aObjName.isEmpty() )
+ xRet->SetName(aObjName);
+ }
+
+ xRet.reset(ProcessObj(rSt, aObjData, rClientData, aTextRect, xRet.release()));
+
+ if (xRet)
+ {
+ sal_Int32 nGroupProperties( GetPropertyValue( DFF_Prop_fPrint, 0 ) );
+ const bool bVisible = ( ( nGroupProperties & 2 ) == 0 );
+ xRet->SetVisible( bVisible );
+ // In Excel hidden means not printed
+ if ( !bVisible )
+ {
+ xRet->SetPrintable(false);
+ }
+ else
+ {
+ // This property isn't used in Excel anymore, leaving it for legacy reasons
+ xRet->SetPrintable( ( nGroupProperties & 1 ) != 0 );
+ }
+ }
+
+ //Import alt text as description
+ if (xRet && SeekToContent(DFF_Prop_wzDescription, rSt))
+ {
+ OUString aAltText = MSDFFReadZString(rSt, GetPropertyValue(DFF_Prop_wzDescription, 0), true);
+ xRet->SetDescription(aAltText);
+ }
+
+ // If this shape opens a new group, push back its object data because
+ // finalization will be called when nested objects have been imported;
+ // otherwise, just finalize here
+ if (o3tl::make_unsigned(nCalledByGroup) > maPendingGroupData.size())
+ {
+ auto xHdClone = std::make_shared<DffRecordHeader>(aObjData.rSpHd);
+ maPendingGroupData.emplace_back(DffObjData(xHdClone, aObjData), xHdClone );
+ }
+ else
+ {
+ xRet.reset(FinalizeObj(aObjData, xRet.release()));
+ }
+ return xRet.release();
+}
+
+tools::Rectangle SvxMSDffManager::GetGlobalChildAnchor( const DffRecordHeader& rHd, SvStream& rSt, tools::Rectangle& aClientRect )
+{
+ tools::Rectangle aChildAnchor;
+ if (!rHd.SeekToContent(rSt))
+ return aChildAnchor;
+
+ bool bIsClientRectRead = false;
+ while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < rHd.GetRecEndFilePos() ) )
+ {
+ DffRecordHeader aShapeHd;
+ if (!ReadDffRecordHeader(rSt, aShapeHd))
+ break;
+ if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) ||
+ ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) )
+ {
+ DffRecordHeader aShapeHd2( aShapeHd );
+ if ( aShapeHd.nRecType == DFF_msofbtSpgrContainer )
+ ReadDffRecordHeader( rSt, aShapeHd2 );
+ while (rSt.good() && rSt.Tell() < aShapeHd2.GetRecEndFilePos())
+ {
+ DffRecordHeader aShapeAtom;
+ if (!ReadDffRecordHeader(rSt, aShapeAtom))
+ break;
+
+ if ( aShapeAtom.nRecType == DFF_msofbtClientAnchor )
+ {
+ if ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_PPT )
+ {
+ sal_Int32 l(0), t(0), r(0), b(0);
+ if ( aShapeAtom.nRecLen == 16 )
+ {
+ rSt.ReadInt32( l ).ReadInt32( t ).ReadInt32( r ).ReadInt32( b );
+ }
+ else
+ {
+ sal_Int16 ls(0), ts(0), rs(0), bs(0);
+ rSt.ReadInt16( ts ).ReadInt16( ls ).ReadInt16( rs ).ReadInt16( bs ); // the order of coordinates is a bit strange...
+ l = ls;
+ t = ts;
+ r = rs;
+ b = bs;
+ }
+ Scale( l );
+ Scale( t );
+ Scale( r );
+ Scale( b );
+ if ( bIsClientRectRead )
+ {
+ tools::Rectangle aChild( l, t, r, b );
+ aChildAnchor.Union( aChild );
+ }
+ else
+ {
+ aClientRect = tools::Rectangle( l, t, r, b );
+ bIsClientRectRead = true;
+ }
+ }
+ break;
+ }
+ else if ( aShapeAtom.nRecType == DFF_msofbtChildAnchor )
+ {
+ sal_Int32 l(0), o(0), r(0), u(0);
+ rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
+ Scale( l );
+ Scale( o );
+ Scale( r );
+ Scale( u );
+ tools::Rectangle aChild( l, o, r, u );
+ aChildAnchor.Union( aChild );
+ break;
+ }
+ if (!aShapeAtom.SeekToEndOfRecord(rSt))
+ break;
+ }
+ }
+ if (!aShapeHd.SeekToEndOfRecord(rSt))
+ break;
+ }
+ return aChildAnchor;
+}
+
+void SvxMSDffManager::GetGroupAnchors( const DffRecordHeader& rHd, SvStream& rSt,
+ tools::Rectangle& rGroupClientAnchor, tools::Rectangle& rGroupChildAnchor,
+ const tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect )
+{
+ if (!rHd.SeekToContent(rSt))
+ return;
+
+ bool bFirst = true;
+ DffRecordHeader aShapeHd;
+ while (rSt.good() && rSt.Tell() < rHd.GetRecEndFilePos())
+ {
+ if (!ReadDffRecordHeader(rSt, aShapeHd))
+ break;
+ if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) ||
+ ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) )
+ {
+ DffRecordHeader aShapeHd2( aShapeHd );
+ if ( aShapeHd.nRecType == DFF_msofbtSpgrContainer )
+ ReadDffRecordHeader( rSt, aShapeHd2 );
+ while (rSt.good() && rSt.Tell() < aShapeHd2.GetRecEndFilePos())
+ {
+ DffRecordHeader aShapeAtom;
+ if (!ReadDffRecordHeader(rSt, aShapeAtom))
+ break;
+ if ( aShapeAtom.nRecType == DFF_msofbtChildAnchor )
+ {
+ sal_Int32 l(0), o(0), r(0), u(0);
+ rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
+ Scale( l );
+ Scale( o );
+ Scale( r );
+ Scale( u );
+ tools::Rectangle aChild( l, o, r, u );
+
+ if ( bFirst )
+ {
+ if ( !rGlobalChildRect.IsEmpty() && !rClientRect.IsEmpty() && rGlobalChildRect.GetWidth() && rGlobalChildRect.GetHeight() )
+ {
+ double fWidth = o3tl::saturating_sub(r, l);
+ double fHeight= o3tl::saturating_sub(u, o);
+ double fXScale = static_cast<double>(rClientRect.GetWidth()) / static_cast<double>(rGlobalChildRect.GetWidth());
+ double fYScale = static_cast<double>(rClientRect.GetHeight()) / static_cast<double>(rGlobalChildRect.GetHeight());
+ double fl = ( ( l - rGlobalChildRect.Left() ) * fXScale ) + rClientRect.Left();
+ double fo = ( ( o - rGlobalChildRect.Top() ) * fYScale ) + rClientRect.Top();
+ fWidth *= fXScale;
+ fHeight *= fYScale;
+ rGroupClientAnchor = tools::Rectangle( Point( static_cast<sal_Int32>(fl), static_cast<sal_Int32>(fo) ), Size( static_cast<sal_Int32>( fWidth + 1 ), static_cast<sal_Int32>( fHeight + 1 ) ) );
+ }
+ bFirst = false;
+ }
+ else
+ rGroupChildAnchor.Union( aChild );
+ break;
+ }
+ if (!aShapeAtom.SeekToEndOfRecord(rSt))
+ break;
+ }
+ }
+ if (!aShapeHd.SeekToEndOfRecord(rSt))
+ break;
+ }
+}
+
+SvxMSDffImportRec* SvxMSDffImportData::find(const SdrObject* pObj)
+{
+ auto it = m_ObjToRecMap.find(pObj);
+ if (it != m_ObjToRecMap.end())
+ return it->second;
+ return nullptr;
+}
+
+void SvxMSDffImportData::insert(std::unique_ptr<SvxMSDffImportRec> pImpRec)
+{
+ auto aRet = m_Records.insert(std::move(pImpRec));
+ bool bSuccess = aRet.second;
+ if (bSuccess)
+ {
+ SvxMSDffImportRec* pRec = aRet.first->get();
+ m_ObjToRecMap[pRec->pObj] = pRec;
+ }
+}
+
+void SvxMSDffImportData::NotifyFreeObj(SdrObject* pObj)
+{
+ if (SvxMSDffImportRec* pRecord = find(pObj))
+ {
+ m_ObjToRecMap.erase(pObj);
+ pRecord->pObj = nullptr;
+ }
+}
+
+void SvxMSDffManager::NotifyFreeObj(SvxMSDffClientData& rData, SdrObject* pObj)
+{
+ if (SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pObj))
+ {
+ SdrObjList* pSubList = pGroup->GetSubList();
+ size_t nObjCount = pSubList->GetObjCount();
+ for (size_t i = 0; i < nObjCount; ++i)
+ NotifyFreeObj(rData, pSubList->GetObj(i));
+ }
+
+ rData.NotifyFreeObj(pObj);
+}
+
+void SvxMSDffManager::FreeObj(SvxMSDffClientData& rData, SdrObject* pObj)
+{
+ NotifyFreeObj(rData, pObj);
+ SdrObject::Free(pObj);
+}
+
+SdrObject* SvxMSDffManager::ProcessObj(SvStream& rSt,
+ DffObjData& rObjData,
+ SvxMSDffClientData& rData,
+ tools::Rectangle& rTextRect,
+ SdrObject* pObj
+ )
+{
+ if( !rTextRect.IsEmpty() )
+ {
+ SvxMSDffImportData& rImportData = static_cast<SvxMSDffImportData&>(rData);
+ SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec;
+ bool bDeleteImpRec = true;
+ SvxMSDffImportRec* pTextImpRec = pImpRec;
+ bool bDeleteTextImpRec = false;
+
+ // fill Import Record with data
+ pImpRec->nShapeId = rObjData.nShapeId;
+ pImpRec->eShapeType = rObjData.eShapeType;
+
+ auto eWrapMode = GetPropertyValue(DFF_Prop_WrapText, mso_wrapSquare);
+ rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt,
+ DFF_msofbtClientAnchor,
+ SEEK_FROM_CURRENT_AND_RESTART );
+ if( rObjData.bClientAnchor )
+ ProcessClientAnchor( rSt,
+ maShapeRecords.Current()->nRecLen,
+ pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen );
+
+ rObjData.bClientData = maShapeRecords.SeekToContent( rSt,
+ DFF_msofbtClientData,
+ SEEK_FROM_CURRENT_AND_RESTART );
+ if( rObjData.bClientData )
+ ProcessClientData( rSt,
+ maShapeRecords.Current()->nRecLen,
+ pImpRec->pClientDataBuffer, pImpRec->nClientDataLen );
+
+
+ // process user (== Winword) defined parameters in 0xF122 record
+ if( maShapeRecords.SeekToContent( rSt,
+ DFF_msofbtUDefProp,
+ SEEK_FROM_CURRENT_AND_RESTART )
+ && maShapeRecords.Current()->nRecLen )
+ {
+ sal_uInt32 nBytesLeft = maShapeRecords.Current()->nRecLen;
+ while( 5 < nBytesLeft )
+ {
+ sal_uInt16 nPID(0);
+ rSt.ReadUInt16(nPID);
+ if (!rSt.good())
+ break;
+ sal_uInt32 nUDData(0);
+ rSt.ReadUInt32(nUDData);
+ switch (nPID)
+ {
+ case 0x038F: pImpRec->nXAlign = nUDData; break;
+ case 0x0390:
+ pImpRec->nXRelTo = nUDData;
+ break;
+ case 0x0391: pImpRec->nYAlign = nUDData; break;
+ case 0x0392:
+ pImpRec->nYRelTo = nUDData;
+ break;
+ case 0x03BF: pImpRec->nGroupShapeBooleanProperties = nUDData; break;
+ case 0x0393:
+ // This seems to correspond to o:hrpct from .docx (even including
+ // the difference that it's in 0.1% even though the .docx spec
+ // says it's in 1%).
+ pImpRec->relativeHorizontalWidth = nUDData;
+ break;
+ case 0x0394:
+ // And this is really just a guess, but a mere presence of this
+ // flag makes a horizontal rule be as wide as the page (unless
+ // overridden by something), so it probably matches o:hr from .docx.
+ pImpRec->isHorizontalRule = true;
+ break;
+ }
+ if (!rSt.good())
+ break;
+ nBytesLeft -= 6;
+ }
+ }
+
+ // text frame, also Title or Outline
+ SdrObject* pOrgObj = pObj;
+ SdrRectObj* pTextObj = nullptr;
+ sal_uInt32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 );
+ if( nTextId )
+ {
+ SfxItemSet aSet( pSdrModel->GetItemPool() );
+
+ //Originally anything that as a mso_sptTextBox was created as a
+ //textbox, this was changed for #88277# to be created as a simple
+ //rect to keep impress happy. For the rest of us we'd like to turn
+ //it back into a textbox again.
+ bool bTextFrame = (pImpRec->eShapeType == mso_sptTextBox);
+ if (!bTextFrame)
+ {
+ //Either
+ //a) it's a simple text object or
+ //b) it's a rectangle with text and square wrapping.
+ bTextFrame =
+ (
+ (pImpRec->eShapeType == mso_sptTextSimple) ||
+ (
+ (pImpRec->eShapeType == mso_sptRectangle)
+ && (eWrapMode == mso_wrapSquare)
+ && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
+ )
+ );
+ }
+
+ if (bTextFrame)
+ {
+ SdrObject::Free( pObj );
+ pObj = pOrgObj = nullptr;
+ }
+
+ // Distance of Textbox to its surrounding Customshape
+ sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L);
+ sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L );
+ sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L );
+ sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L );
+
+ ScaleEmu( nTextLeft );
+ ScaleEmu( nTextRight );
+ ScaleEmu( nTextTop );
+ ScaleEmu( nTextBottom );
+
+ Degree100 nTextRotationAngle(0);
+ bool bVerticalText = false;
+ if ( IsProperty( DFF_Prop_txflTextFlow ) )
+ {
+ auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
+ switch( eTextFlow )
+ {
+ case mso_txflBtoT:
+ nTextRotationAngle = 9000_deg100;
+ break;
+ case mso_txflVertN:
+ case mso_txflTtoBN:
+ nTextRotationAngle = 27000_deg100;
+ break;
+ case mso_txflTtoBA:
+ bVerticalText = true;
+ break;
+ case mso_txflHorzA:
+ bVerticalText = true;
+ nTextRotationAngle = 9000_deg100;
+ break;
+ case mso_txflHorzN:
+ default :
+ break;
+ }
+ }
+
+ if (nTextRotationAngle)
+ {
+ switch (nTextRotationAngle.get())
+ {
+ case 9000:
+ {
+ tools::Long nWidth = rTextRect.GetWidth();
+ rTextRect.SetRight( rTextRect.Left() + rTextRect.GetHeight() );
+ rTextRect.SetBottom( rTextRect.Top() + nWidth );
+
+ sal_Int32 nOldTextLeft = nTextLeft;
+ sal_Int32 nOldTextRight = nTextRight;
+ sal_Int32 nOldTextTop = nTextTop;
+ sal_Int32 nOldTextBottom = nTextBottom;
+
+ nTextLeft = nOldTextBottom;
+ nTextRight = nOldTextTop;
+ nTextTop = nOldTextLeft;
+ nTextBottom = nOldTextRight;
+ }
+ break;
+ case 27000:
+ {
+ tools::Long nWidth = rTextRect.GetWidth();
+ rTextRect.SetRight( rTextRect.Left() + rTextRect.GetHeight() );
+ rTextRect.SetBottom( rTextRect.Top() + nWidth );
+
+ sal_Int32 nOldTextLeft = nTextLeft;
+ sal_Int32 nOldTextRight = nTextRight;
+ sal_Int32 nOldTextTop = nTextTop;
+ sal_Int32 nOldTextBottom = nTextBottom;
+
+ nTextLeft = nOldTextTop;
+ nTextRight = nOldTextBottom;
+ nTextTop = nOldTextRight;
+ nTextBottom = nOldTextLeft;
+ }
+ break;
+ }
+ }
+
+ pTextObj = new SdrRectObj(
+ *pSdrModel,
+ SdrObjKind::Text,
+ rTextRect);
+ pTextImpRec = new SvxMSDffImportRec(*pImpRec);
+ bDeleteTextImpRec = true;
+
+ // the vertical paragraph indents are part of the BoundRect,
+ // here we 'remove' them by calculating
+ tools::Rectangle aNewRect(rTextRect);
+ aNewRect.AdjustBottom( -(nTextTop + nTextBottom) );
+ aNewRect.AdjustRight( -(nTextLeft + nTextRight) );
+
+ // Only if it's a simple textbox may Writer replace
+ // the object with a frame, otherwise
+ if( bTextFrame )
+ {
+ auto const pTmpRec = std::make_shared<SvxMSDffShapeInfo>(0, pImpRec->nShapeId);
+
+ SvxMSDffShapeInfos_ById::const_iterator const it =
+ m_xShapeInfosById->find(pTmpRec);
+ if (it != m_xShapeInfosById->end())
+ {
+ SvxMSDffShapeInfo& rInfo = **it;
+ pTextImpRec->bReplaceByFly = rInfo.bReplaceByFly;
+ }
+ }
+
+ if( !pObj )
+ ApplyAttributes( rSt, aSet, rObjData );
+
+ bool bFitText = false;
+ if (GetPropertyValue(DFF_Prop_FitTextToShape, 0) & 2)
+ {
+ aSet.Put( makeSdrTextAutoGrowHeightItem( true ) );
+ aSet.Put( makeSdrTextMinFrameHeightItem(
+ aNewRect.Bottom() - aNewRect.Top() ) );
+ aSet.Put( makeSdrTextMinFrameWidthItem(
+ aNewRect.Right() - aNewRect.Left() ) );
+ bFitText = true;
+ }
+ else
+ {
+ aSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
+ aSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
+ }
+
+ switch (GetPropertyValue(DFF_Prop_WrapText, mso_wrapSquare))
+ {
+ case mso_wrapNone :
+ aSet.Put( makeSdrTextAutoGrowWidthItem( true ) );
+ if (bFitText)
+ {
+ //can't do autowidth in flys #i107184#
+ pTextImpRec->bReplaceByFly = false;
+ }
+ break;
+ case mso_wrapByPoints :
+ aSet.Put( makeSdrTextContourFrameItem( true ) );
+ break;
+ default: break;
+ }
+
+ // set margins at the border of the textbox
+ aSet.Put( makeSdrTextLeftDistItem( nTextLeft ) );
+ aSet.Put( makeSdrTextRightDistItem( nTextRight ) );
+ aSet.Put( makeSdrTextUpperDistItem( nTextTop ) );
+ aSet.Put( makeSdrTextLowerDistItem( nTextBottom ) );
+ pTextImpRec->nDxTextLeft = nTextLeft;
+ pTextImpRec->nDyTextTop = nTextTop;
+ pTextImpRec->nDxTextRight = nTextRight;
+ pTextImpRec->nDyTextBottom = nTextBottom;
+
+ // read text anchor
+ if ( IsProperty( DFF_Prop_anchorText ) )
+ {
+ auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, 0);
+
+ SdrTextVertAdjust eTVA = SDRTEXTVERTADJUST_CENTER;
+ bool bTVASet(false);
+ bool bTHASet(false);
+
+ switch( eTextAnchor )
+ {
+ case mso_anchorTop:
+ {
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ bTVASet = true;
+ }
+ break;
+ case mso_anchorTopCentered:
+ {
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ bTVASet = true;
+ bTHASet = true;
+ }
+ break;
+
+ case mso_anchorMiddle:
+ bTVASet = true;
+ break;
+ case mso_anchorMiddleCentered:
+ {
+ bTVASet = true;
+ bTHASet = true;
+ }
+ break;
+ case mso_anchorBottom:
+ {
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ bTVASet = true;
+ }
+ break;
+ case mso_anchorBottomCentered:
+ {
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ bTVASet = true;
+ bTHASet = true;
+ }
+ break;
+ default : break;
+ }
+ // insert
+ if ( bTVASet )
+ aSet.Put( SdrTextVertAdjustItem( eTVA ) );
+ if ( bTHASet )
+ aSet.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER ) );
+ }
+
+ pTextObj->SetMergedItemSet(aSet);
+
+ if (bVerticalText)
+ pTextObj->SetVerticalWriting(true);
+
+ if (nTextRotationAngle)
+ {
+ tools::Long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ?
+ rTextRect.GetWidth() : rTextRect.GetHeight();
+ nMinWH /= 2;
+ Point aPivot(rTextRect.TopLeft());
+ aPivot.AdjustX(nMinWH );
+ aPivot.AdjustY(nMinWH );
+ pTextObj->SdrAttrObj::NbcRotate(aPivot, nTextRotationAngle);
+ }
+
+ // rotate text with shape?
+ if ( mnFix16Angle )
+ {
+ double a = toRadians(mnFix16Angle);
+ pTextObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle,
+ sin( a ), cos( a ) );
+ }
+
+ if( !pObj )
+ {
+ pObj = pTextObj;
+ }
+ else
+ {
+ if( pTextObj != pObj )
+ {
+ SdrObject* pGroup = new SdrObjGroup(*pSdrModel);
+ pGroup->GetSubList()->NbcInsertObject( pObj );
+ pGroup->GetSubList()->NbcInsertObject( pTextObj );
+ if (pOrgObj == pObj)
+ pOrgObj = pGroup;
+ else
+ pOrgObj = pObj;
+ pObj = pGroup;
+ }
+ }
+ }
+ else if( !pObj )
+ {
+ // simple rectangular objects are ignored by ImportObj() :-(
+ // this is OK for Draw but not for Calc and Writer
+ // cause here these objects have a default border
+ pObj = new SdrRectObj(
+ *pSdrModel,
+ rTextRect);
+
+ pOrgObj = pObj;
+ SfxItemSet aSet( pSdrModel->GetItemPool() );
+ ApplyAttributes( rSt, aSet, rObjData );
+
+ SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR );
+ if( SfxItemState::DEFAULT == eState )
+ aSet.Put( XFillColorItem( OUString(), mnDefaultColor ) );
+ pObj->SetMergedItemSet(aSet);
+ }
+
+ //Means that fBehindDocument is set
+ if (GetPropertyValue(DFF_Prop_fPrint, 0) & 0x20)
+ pImpRec->bDrawHell = true;
+ else
+ pImpRec->bDrawHell = false;
+ if (GetPropertyValue(DFF_Prop_fPrint, 0) & 0x02)
+ pImpRec->bHidden = true;
+ pTextImpRec->bDrawHell = pImpRec->bDrawHell;
+ pTextImpRec->bHidden = pImpRec->bHidden;
+ pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext, 0 );
+ pTextImpRec->nNextShapeId=pImpRec->nNextShapeId;
+
+ if ( nTextId )
+ {
+ pTextImpRec->aTextId.nTxBxS = static_cast<sal_uInt16>( nTextId >> 16 );
+ pTextImpRec->aTextId.nSequence = static_cast<sal_uInt16>(nTextId);
+ }
+
+ pTextImpRec->nDxWrapDistLeft = GetPropertyValue(
+ DFF_Prop_dxWrapDistLeft, 114935L ) / 635L;
+ pTextImpRec->nDyWrapDistTop = GetPropertyValue(
+ DFF_Prop_dyWrapDistTop, 0 ) / 635L;
+ pTextImpRec->nDxWrapDistRight = GetPropertyValue(
+ DFF_Prop_dxWrapDistRight, 114935L ) / 635L;
+ pTextImpRec->nDyWrapDistBottom = GetPropertyValue(
+ DFF_Prop_dyWrapDistBottom, 0 ) / 635L;
+ // 16.16 fraction times total image width or height, as appropriate.
+
+ if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt))
+ {
+ pTextImpRec->pWrapPolygon.reset();
+ sal_uInt16 nNumElemVert(0), nNumElemMemVert(0), nElemSizeVert(8);
+ rSt.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
+ // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
+ // low-order bytes are recorded
+ if (nElemSizeVert == 0xFFF0)
+ nElemSizeVert = 4;
+
+ // sanity check that the stream is long enough to fulfill nNumElemVert * nElemSizeVert;
+ bool bOk = nElemSizeVert && (rSt.remainingSize() / nElemSizeVert >= nNumElemVert);
+ if (bOk)
+ {
+ pTextImpRec->pWrapPolygon = tools::Polygon(nNumElemVert);
+ for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
+ {
+ sal_Int32 nX(0), nY(0);
+ if (nElemSizeVert == 8)
+ rSt.ReadInt32( nX ).ReadInt32( nY );
+ else
+ {
+ sal_Int16 nSmallX(0), nSmallY(0);
+ rSt.ReadInt16( nSmallX ).ReadInt16( nSmallY );
+ nX = nSmallX;
+ nY = nSmallY;
+ }
+ (*(pTextImpRec->pWrapPolygon))[i].setX( nX );
+ (*(pTextImpRec->pWrapPolygon))[i].setY( nY );
+ }
+ }
+ }
+
+ pImpRec->nCropFromTop = GetPropertyValue(
+ DFF_Prop_cropFromTop, 0 );
+ pImpRec->nCropFromBottom = GetPropertyValue(
+ DFF_Prop_cropFromBottom, 0 );
+ pImpRec->nCropFromLeft = GetPropertyValue(
+ DFF_Prop_cropFromLeft, 0 );
+ pImpRec->nCropFromRight = GetPropertyValue(
+ DFF_Prop_cropFromRight, 0 );
+
+ pImpRec->bVFlip = bool(rObjData.nSpFlags & ShapeFlag::FlipV);
+ pImpRec->bHFlip = bool(rObjData.nSpFlags & ShapeFlag::FlipH);
+
+ sal_uInt32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash, 0 );
+ pImpRec->eLineStyle = (nLineFlags & 8)
+ ? static_cast<MSO_LineStyle>(GetPropertyValue(
+ DFF_Prop_lineStyle,
+ mso_lineSimple ))
+ : MSO_LineStyle_NONE;
+ pTextImpRec->eLineStyle = pImpRec->eLineStyle;
+
+ pImpRec->eLineDashing = static_cast<MSO_LineDashing>(GetPropertyValue(
+ DFF_Prop_lineDashing, mso_lineSolid ));
+ pTextImpRec->eLineDashing = pImpRec->eLineDashing;
+
+ if( pImpRec->nShapeId )
+ {
+ // amend the import record list
+ if( pOrgObj )
+ {
+ pImpRec->pObj = pOrgObj;
+ rImportData.insert(std::unique_ptr<SvxMSDffImportRec>(pImpRec));
+ bDeleteImpRec = false;
+ if (pImpRec == pTextImpRec)
+ bDeleteTextImpRec = false;
+ }
+
+ if( pTextObj && (pOrgObj != pTextObj) )
+ {
+ // Modify ShapeId (must be unique)
+ pImpRec->nShapeId |= 0x8000000;
+ pTextImpRec->pObj = pTextObj;
+ rImportData.insert(std::unique_ptr<SvxMSDffImportRec>(pTextImpRec));
+ bDeleteTextImpRec = false;
+ if (pTextImpRec == pImpRec)
+ bDeleteImpRec = false;
+ }
+
+ // entry in the z-order-list in order to complement the pointer to this object
+ /*Only store objects which are not deep inside the tree*/
+ if( ( rObjData.nCalledByGroup == 0 )
+ ||
+ ( (rObjData.nSpFlags & ShapeFlag::Group)
+ && (rObjData.nCalledByGroup < 2) )
+ )
+ StoreShapeOrder( pImpRec->nShapeId,
+ ( static_cast<sal_uLong>(pImpRec->aTextId.nTxBxS) << 16 )
+ + pImpRec->aTextId.nSequence, pObj );
+ }
+
+ if (bDeleteImpRec)
+ delete pImpRec;
+
+ if (bDeleteTextImpRec)
+ delete pTextImpRec;
+ }
+
+ return pObj;
+};
+
+SdrObject* SvxMSDffManager::FinalizeObj(DffObjData& /* rObjData */, SdrObject* pObj)
+{
+ return pObj;
+}
+
+
+void SvxMSDffManager::StoreShapeOrder(sal_uLong nId,
+ sal_uLong nTxBx,
+ SdrObject* pObject,
+ SwFlyFrameFormat* pFly) const
+{
+ for (const auto& pOrder : m_aShapeOrders)
+ {
+ if (pOrder->nShapeId == nId)
+ {
+ pOrder->nTxBxComp = nTxBx;
+ pOrder->pObj = pObject;
+ pOrder->pFly = pFly;
+ }
+ }
+}
+
+
+void SvxMSDffManager::ExchangeInShapeOrder( SdrObject const * pOldObject,
+ sal_uLong nTxBx,
+ SdrObject* pObject) const
+{
+ for (const auto& pOrder : m_aShapeOrders)
+ {
+ if (pOrder->pObj == pOldObject)
+ {
+ pOrder->pFly = nullptr;
+ pOrder->pObj = pObject;
+ pOrder->nTxBxComp = nTxBx;
+ }
+ }
+}
+
+
+void SvxMSDffManager::RemoveFromShapeOrder( SdrObject const * pObject ) const
+{
+ for (const auto& pOrder : m_aShapeOrders)
+ {
+ if (pOrder->pObj == pObject)
+ {
+ pOrder->pObj = nullptr;
+ pOrder->pFly = nullptr;
+ pOrder->nTxBxComp = 0;
+ }
+ }
+}
+
+
+// exported class: Public Methods
+
+SvxMSDffManager::SvxMSDffManager(SvStream& rStCtrl_,
+ OUString aBaseURL,
+ sal_uInt32 nOffsDgg_,
+ SvStream* pStData_,
+ SdrModel* pSdrModel_,// see SetModel() below
+ tools::Long nApplicationScale,
+ Color mnDefaultColor_,
+ SvStream* pStData2_,
+ bool bSkipImages )
+ :DffPropertyReader( *this ),
+ m_pBLIPInfos( new SvxMSDffBLIPInfos ),
+ m_xShapeInfosByTxBxComp( new SvxMSDffShapeInfos_ByTxBxComp ),
+ nOffsDgg( nOffsDgg_ ),
+ nBLIPCount( USHRT_MAX ), // initialize with error, since we first check if the
+ nGroupShapeFlags(ShapeFlag::NONE), // ensure initialization here, as some corrupted
+ // files may yield to this being uninitialized
+ maBaseURL(std::move( aBaseURL )),
+ mnIdClusters(0),
+ rStCtrl( rStCtrl_ ),
+ pStData( pStData_ ),
+ pStData2( pStData2_ ),
+ nSvxMSDffSettings( 0 ),
+ nSvxMSDffOLEConvFlags( 0 ),
+ mnDefaultColor( mnDefaultColor_),
+ mbSkipImages (bSkipImages)
+{
+ SetModel( pSdrModel_, nApplicationScale );
+
+ // remember FilePos of the stream(s)
+ sal_uInt64 nOldPosCtrl = rStCtrl.Tell();
+ sal_uInt64 nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl;
+
+ // if no data stream is given we assume that the BLIPs
+ // are in the control stream
+ if( !pStData )
+ pStData = &rStCtrl;
+
+ SetDefaultPropSet( rStCtrl, nOffsDgg );
+
+ // read control stream, if successful set nBLIPCount
+ GetCtrlData( nOffsDgg );
+
+ // check Text-Box-Story-Chain-Infos
+ CheckTxBxStoryChain();
+
+ // restore old FilePos of the stream(s)
+ rStCtrl.Seek( nOldPosCtrl );
+ if( &rStCtrl != pStData )
+ pStData->Seek( nOldPosData );
+}
+
+SvxMSDffManager::SvxMSDffManager( SvStream& rStCtrl_, OUString aBaseURL )
+ :DffPropertyReader( *this ),
+ m_pBLIPInfos( new SvxMSDffBLIPInfos ),
+ m_xShapeInfosByTxBxComp( new SvxMSDffShapeInfos_ByTxBxComp ),
+ nOffsDgg( 0 ),
+ nBLIPCount( USHRT_MAX ), // initialize with error, since we first have to check
+ nGroupShapeFlags(ShapeFlag::NONE),
+ maBaseURL(std::move( aBaseURL )),
+ mnIdClusters(0),
+ rStCtrl( rStCtrl_ ),
+ pStData( nullptr ),
+ pStData2( nullptr ),
+ nSvxMSDffSettings( 0 ),
+ nSvxMSDffOLEConvFlags( 0 ),
+ mnDefaultColor( COL_DEFAULT ),
+ mbSkipImages(false)
+{
+ SetModel( nullptr, 0 );
+}
+
+SvxMSDffManager::~SvxMSDffManager()
+{
+}
+
+void SvxMSDffManager::InitSvxMSDffManager( sal_uInt32 nOffsDgg_, SvStream* pStData_, sal_uInt32 nOleConvFlags )
+{
+ nOffsDgg = nOffsDgg_;
+ pStData = pStData_;
+ nSvxMSDffOLEConvFlags = nOleConvFlags;
+
+ // remember FilePos of the stream(s)
+ sal_uInt64 nOldPosCtrl = rStCtrl.Tell();
+
+ SetDefaultPropSet( rStCtrl, nOffsDgg );
+
+ // insert fidcl cluster table
+ GetFidclData( nOffsDgg );
+
+ // read control stream, if successful, set nBLIPCount
+ GetCtrlData( nOffsDgg );
+
+ // check Text-Box-Story-Chain-Infos
+ CheckTxBxStoryChain();
+
+ // restore old FilePos of the stream(s)
+ rStCtrl.Seek( nOldPosCtrl );
+}
+
+void SvxMSDffManager::SetDgContainer( SvStream& rSt )
+{
+ sal_uInt64 nFilePos = rSt.Tell();
+ DffRecordHeader aDgContHd;
+ bool bOk = ReadDffRecordHeader(rSt, aDgContHd);
+ // insert this container only if there is also a DggAtom
+ if (bOk && SeekToRec(rSt, DFF_msofbtDg, aDgContHd.GetRecEndFilePos()))
+ {
+ DffRecordHeader aRecHd;
+ if (ReadDffRecordHeader(rSt, aRecHd))
+ {
+ sal_uInt32 nDrawingId = aRecHd.nRecInstance;
+ maDgOffsetTable[nDrawingId] = nFilePos;
+ }
+ }
+ rSt.Seek(nFilePos);
+}
+
+void SvxMSDffManager::GetFidclData( sal_uInt32 nOffsDggL )
+{
+ if (!nOffsDggL)
+ return;
+
+ sal_uInt64 nOldPos = rStCtrl.Tell();
+
+ if (nOffsDggL == rStCtrl.Seek(nOffsDggL))
+ {
+ DffRecordHeader aRecHd;
+ bool bOk = ReadDffRecordHeader(rStCtrl, aRecHd);
+
+ DffRecordHeader aDggAtomHd;
+ if (bOk && SeekToRec(rStCtrl, DFF_msofbtDgg, aRecHd.GetRecEndFilePos(), &aDggAtomHd))
+ {
+ aDggAtomHd.SeekToContent( rStCtrl );
+ sal_uInt32 nCurMaxShapeId;
+ sal_uInt32 nDummy;
+ rStCtrl.ReadUInt32( nCurMaxShapeId )
+ .ReadUInt32( mnIdClusters )
+ .ReadUInt32( nDummy )
+ .ReadUInt32( nDummy ); // nDrawingsSaved
+
+ if ( mnIdClusters-- > 2 )
+ {
+ const std::size_t nFIDCLsize = sizeof(sal_uInt32) * 2;
+ if ( aDggAtomHd.nRecLen == ( mnIdClusters * nFIDCLsize + 16 ) )
+ {
+ sal_uInt64 nMaxEntriesPossible = rStCtrl.remainingSize() / nFIDCLsize;
+ SAL_WARN_IF(nMaxEntriesPossible < mnIdClusters,
+ "filter.ms", "FIDCL list longer than remaining bytes, ppt or parser is wrong");
+ mnIdClusters = std::min(nMaxEntriesPossible, static_cast<sal_uInt64>(mnIdClusters));
+
+ maFidcls.resize(mnIdClusters);
+ for (sal_uInt32 i = 0; i < mnIdClusters; ++i)
+ {
+ sal_uInt32 cspidCur; ///< number of SPIDs used so far
+ rStCtrl.ReadUInt32( maFidcls[ i ].dgid )
+ .ReadUInt32( cspidCur );
+ }
+ }
+ }
+ }
+ }
+ rStCtrl.Seek( nOldPos );
+}
+
+void SvxMSDffManager::CheckTxBxStoryChain()
+{
+ m_xShapeInfosById.reset(new SvxMSDffShapeInfos_ById);
+ // mangle old Info array, sorted by nTxBxComp
+ sal_uInt32 nChain = std::numeric_limits<sal_uInt32>::max();
+ bool bSetReplaceFALSE = false;
+ for (SvxMSDffShapeInfos_ByTxBxComp::iterator iter =
+ m_xShapeInfosByTxBxComp->begin(),
+ mark = m_xShapeInfosByTxBxComp->begin();
+ iter != m_xShapeInfosByTxBxComp->end(); ++iter)
+ {
+ std::shared_ptr<SvxMSDffShapeInfo> const pObj = *iter;
+ if( pObj->nTxBxComp )
+ {
+ // group change?
+ // the text id also contains an internal drawing container id
+ // to distinguish between text id of drawing objects in different
+ // drawing containers.
+ if( nChain != pObj->nTxBxComp )
+ {
+ // reset mark and helper flag
+ mark = iter;
+ nChain = pObj->nTxBxComp;
+ bSetReplaceFALSE = !pObj->bReplaceByFly;
+ }
+ else if( !pObj->bReplaceByFly )
+ {
+ // object that must NOT be replaced by frame?
+ bSetReplaceFALSE = true;
+ // maybe reset flags in start of group
+ for (SvxMSDffShapeInfos_ByTxBxComp::iterator itemp = mark;
+ itemp != iter; ++itemp)
+ {
+ (*itemp)->bReplaceByFly = false;
+ }
+ }
+
+ if( bSetReplaceFALSE )
+ {
+ pObj->bReplaceByFly = false;
+ }
+ }
+ // copy all Shape Info objects to m_xShapeInfosById, sorted by nShapeId
+ pObj->nTxBxComp = pObj->nTxBxComp & 0xFFFF0000;
+ m_xShapeInfosById->insert( pObj );
+ }
+ // free original array but don't free its elements
+ m_xShapeInfosByTxBxComp.reset();
+}
+
+
+/*****************************************************************************
+
+ Reading the Shape-Infos in the Ctor:
+ ---------------------------------
+ remembering the Shape-Ids and the associated Blip-Numbers and TextBox-Infos
+ ========= ============ =============
+ and remembering the File-Offsets for each Blip
+ ============
+******************************************************************************/
+void SvxMSDffManager::GetCtrlData(sal_uInt32 nOffsDggL)
+{
+ // position control stream
+ if (!checkSeek(rStCtrl, nOffsDggL))
+ return;
+
+ sal_uInt8 nVer;
+ sal_uInt16 nInst;
+ sal_uInt16 nFbt;
+ sal_uInt32 nLength;
+ if( !ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) ) return;
+
+ sal_uInt64 nPos = nOffsDggL + DFF_COMMON_RECORD_HEADER_SIZE;
+
+ // case A: first Drawing Group Container, then n times Drawing Container
+ if( DFF_msofbtDggContainer != nFbt )
+ return;
+
+ bool bOk;
+ GetDrawingGroupContainerData( rStCtrl, nLength );
+
+ sal_uInt64 nMaxStrPos = rStCtrl.TellEnd();
+
+ nPos += nLength;
+ sal_uInt16 nDrawingContainerId = 1;
+ do
+ {
+ if (!checkSeek(rStCtrl, nPos))
+ break;
+
+ bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) && ( DFF_msofbtDgContainer == nFbt );
+
+ if( !bOk )
+ {
+ nPos++; // ????????? TODO: trying to get a one-hit wonder, this code should be rewritten...
+ if (nPos != rStCtrl.Seek(nPos))
+ break;
+ bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength )
+ && ( DFF_msofbtDgContainer == nFbt );
+ }
+ if( bOk )
+ {
+ GetDrawingContainerData( rStCtrl, nLength, nDrawingContainerId );
+ }
+ nPos += DFF_COMMON_RECORD_HEADER_SIZE + nLength;
+ ++nDrawingContainerId;
+ }
+ while( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( nPos < nMaxStrPos ) && bOk );
+}
+
+
+// from here on: Drawing Group Container i.e. document-wide valid data
+
+void SvxMSDffManager::GetDrawingGroupContainerData( SvStream& rSt, sal_uInt32 nLenDgg )
+{
+ sal_uInt8 nVer;
+ sal_uInt16 nInst;
+ sal_uInt16 nFbt;
+ sal_uInt32 nLength;
+
+ sal_uInt32 nLenBStoreCont = 0, nLenFBSE = 0;
+ sal_uLong nRead = 0;
+
+ // search for a BStore Container
+ bool bOk = true;
+ do
+ {
+ if (!ReadCommonRecordHeader(rSt, nVer, nInst, nFbt, nLength))
+ return;
+ nRead += DFF_COMMON_RECORD_HEADER_SIZE + nLength;
+ if (DFF_msofbtBstoreContainer == nFbt)
+ {
+ nLenBStoreCont = nLength;
+ break;
+ }
+ bOk = checkSeek(rSt, rSt.Tell() + nLength);
+ }
+ while (bOk && nRead < nLenDgg);
+
+ if (!bOk || !nLenBStoreCont)
+ return;
+
+ // Read all atoms of the containers from the BStore container and store all
+ // relevant data of all contained FBSEs in out pointer array.
+ // We also count all found FBSEs in member nBLIPCount.
+
+ const sal_uLong nSkipBLIPLen = 20; // skip to get to the nBLIPLen
+ const sal_uLong nSkipBLIPPos = 4; // thereafter skip up to nBLIPPos
+
+ sal_uInt32 nBLIPLen = 0, nBLIPPos = 0;
+
+ nRead = 0;
+ do
+ {
+ if(!ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return;
+ nRead += DFF_COMMON_RECORD_HEADER_SIZE + nLength;
+ if( DFF_msofbtBSE == nFbt && /* magic value from spec */ 0x2 == nVer )
+ {
+ nLenFBSE = nLength;
+ // is FBSE big enough for our data
+ bOk = ( nSkipBLIPLen + 4 + nSkipBLIPPos + 4 <= nLenFBSE );
+
+ if (bOk)
+ {
+ rSt.SeekRel( nSkipBLIPLen );
+ rSt.ReadUInt32( nBLIPLen );
+ rSt.SeekRel( nSkipBLIPPos );
+ rSt.ReadUInt32( nBLIPPos );
+ bOk = rSt.GetError() == ERRCODE_NONE;
+
+ nLength -= nSkipBLIPLen+ 4 + nSkipBLIPPos + 4;
+ }
+
+ if (bOk)
+ {
+ // specialty:
+ // If nBLIPLen is less than nLenFBSE AND nBLIPPos is NULL,
+ // then we assume, that the image is in FBSE!
+ if( (!nBLIPPos) && (nBLIPLen < nLenFBSE) )
+ nBLIPPos = rSt.Tell() + 4;
+
+ if( USHRT_MAX == nBLIPCount )
+ nBLIPCount = 1;
+ else
+ nBLIPCount++;
+
+ // now save the info for later access
+ m_pBLIPInfos->push_back(SvxMSDffBLIPInfo(nBLIPPos));
+ }
+ if (!checkSeek(rSt, rSt.Tell() + nLength))
+ return; // invalid offset
+ }
+ else return; // invalid input
+ }
+ while( nRead < nLenBStoreCont );
+}
+
+
+// from now on: Drawing Container which means Pages (Sheet, Slide) - wide valid data
+// ================= ======
+
+void SvxMSDffManager::GetDrawingContainerData( SvStream& rSt, sal_uInt32 nLenDg,
+ sal_uInt16 nDrawingContainerId )
+{
+ sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
+
+ sal_uLong nReadDg = 0;
+
+ // We are now in a drawing container (one per each page) and
+ // we now have to iterate through all contained shape group containers
+ do
+ {
+ if (!ReadCommonRecordHeader(rSt, nVer, nInst, nFbt, nLength))
+ return;
+ nReadDg += DFF_COMMON_RECORD_HEADER_SIZE;
+ // Patriarch found (the upmost shape group container) ?
+ if (DFF_msofbtSpgrContainer == nFbt)
+ {
+ if (!GetShapeGroupContainerData(rSt, nLength, true, nDrawingContainerId))
+ return;
+ }
+ // empty Shape Container ? (outside of shape group container)
+ else if (DFF_msofbtSpContainer == nFbt)
+ {
+ if (!GetShapeContainerData(
+ rSt, nLength, std::numeric_limits<sal_uInt64>::max(), nDrawingContainerId))
+ return;
+ }
+ else
+ {
+ if (!checkSeek(rSt, rSt.Tell() + nLength))
+ return;
+ }
+ nReadDg += nLength;
+ }
+ while( nReadDg < nLenDg );
+}
+
+bool SvxMSDffManager::GetShapeGroupContainerData( SvStream& rSt,
+ sal_uInt32 nLenShapeGroupCont,
+ bool bPatriarch,
+ sal_uInt16 nDrawingContainerId )
+{
+ sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
+ sal_uInt64 nStartShapeGroupCont = rSt.Tell();
+ // We are now in a shape group container (conditionally multiple per page)
+ // and we now have to iterate through all contained shape containers
+ bool bFirst = !bPatriarch;
+ sal_uLong nReadSpGrCont = 0;
+ do
+ {
+ if( !ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength ) )
+ return false;
+ nReadSpGrCont += DFF_COMMON_RECORD_HEADER_SIZE;
+ // Shape Container?
+ if( DFF_msofbtSpContainer == nFbt )
+ {
+ sal_uInt64 nGroupOffs = bFirst ? nStartShapeGroupCont - DFF_COMMON_RECORD_HEADER_SIZE : std::numeric_limits<sal_uInt64>::max();
+ if ( !GetShapeContainerData( rSt, nLength, nGroupOffs, nDrawingContainerId ) )
+ return false;
+ bFirst = false;
+ }
+ // nested shape group container ?
+ else if( DFF_msofbtSpgrContainer == nFbt )
+ {
+ if ( !GetShapeGroupContainerData( rSt, nLength, false, nDrawingContainerId ) )
+ return false;
+ }
+ else
+ {
+ if (!checkSeek(rSt, rSt.Tell() + nLength))
+ return false;
+ }
+ nReadSpGrCont += nLength;
+ }
+ while( nReadSpGrCont < nLenShapeGroupCont );
+ // position the stream correctly
+ rSt.Seek( nStartShapeGroupCont + nLenShapeGroupCont );
+ return true;
+}
+
+bool SvxMSDffManager::GetShapeContainerData( SvStream& rSt,
+ sal_uInt32 nLenShapeCont,
+ sal_uInt64 nPosGroup,
+ sal_uInt16 nDrawingContainerId )
+{
+ sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
+ sal_uInt64 nStartShapeCont = rSt.Tell();
+
+ // We are in a shape container (possibly more than one per shape group) and we now
+ // have to fetch the shape id and file position (to be able to access them again later)
+ // and the first BStore reference (if present).
+ sal_uInt32 nLenShapePropTbl = 0;
+ sal_uLong nReadSpCont = 0;
+
+ // Store file offset of the shape containers or respectively the group(!).
+ sal_uInt64 nStartOffs = (std::numeric_limits<sal_uInt64>::max() > nPosGroup) ?
+ nPosGroup : nStartShapeCont - DFF_COMMON_RECORD_HEADER_SIZE;
+ SvxMSDffShapeInfo aInfo( nStartOffs );
+
+ // Can the shape be replaced with a frame?
+ // (provided that it is a TextBox and the text is not rotated)
+ bool bCanBeReplaced = nPosGroup >= std::numeric_limits<sal_uInt64>::max();
+
+ // we don't know yet whether it's a TextBox
+ MSO_SPT eShapeType = mso_sptNil;
+
+ // analyze Shape
+
+ do
+ {
+ if(!ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return false;
+ nReadSpCont += DFF_COMMON_RECORD_HEADER_SIZE;
+ // FSP ?
+ if( ( DFF_msofbtSp == nFbt ) && ( 4 <= nLength ) )
+ {
+ // we've found the FSP: note Shape Type and Id!
+ eShapeType = static_cast<MSO_SPT>(nInst);
+ rSt.ReadUInt32( aInfo.nShapeId );
+ rSt.SeekRel( nLength - 4 );
+ nReadSpCont += nLength;
+ }
+ else if( DFF_msofbtOPT == nFbt ) // Shape Property Table ?
+ {
+ // We've found the Property Table:
+ // search for the Blip Property!
+ sal_uLong nPropRead = 0;
+ nLenShapePropTbl = nLength;
+ auto nStartShapePropTbl = rSt.Tell();
+ do
+ {
+ sal_uInt16 nPropId(0);
+ sal_uInt32 nPropVal(0);
+
+ rSt.ReadUInt16( nPropId )
+ .ReadUInt32( nPropVal );
+ nPropRead += 6;
+
+ switch( nPropId )
+ {
+ case DFF_Prop_txflTextFlow :
+ //Writer can now handle vertical textflows in its
+ //native frames, to only need to do this for the
+ //other two formats
+
+ //Writer will handle all textflow except BtoT
+ if (GetSvxMSDffSettings() &
+ (SVXMSDFF_SETTINGS_IMPORT_PPT |
+ SVXMSDFF_SETTINGS_IMPORT_EXCEL))
+ {
+ if( 0 != nPropVal )
+ bCanBeReplaced = false;
+ }
+ else if (
+ (nPropVal != mso_txflHorzN) &&
+ (nPropVal != mso_txflTtoBA)
+ )
+ {
+ bCanBeReplaced = false;
+ }
+ break;
+ case DFF_Prop_cdirFont :
+ //Writer can now handle right to left and left
+ //to right in its native frames, so only do
+ //this for the other two formats.
+ if (GetSvxMSDffSettings() &
+ (SVXMSDFF_SETTINGS_IMPORT_PPT |
+ SVXMSDFF_SETTINGS_IMPORT_EXCEL))
+ {
+ if( 0 != nPropVal )
+ bCanBeReplaced = false;
+ }
+ break;
+ case DFF_Prop_Rotation :
+ if( 0 != nPropVal )
+ bCanBeReplaced = false;
+ break;
+
+ case DFF_Prop_gtextFStrikethrough :
+ if( ( 0x20002000 & nPropVal ) == 0x20002000 )
+ bCanBeReplaced = false;
+ break;
+
+ case DFF_Prop_fc3DLightFace :
+ if( ( 0x00080008 & nPropVal ) == 0x00080008 )
+ bCanBeReplaced = false;
+ break;
+
+ case DFF_Prop_WrapText :
+ //TODO: eWrapMode = (MSO_WrapMode)nPropVal;
+ break;
+
+ default:
+ {
+ // is the Bit set and valid?
+ if( 0x4000 == ( nPropId & 0xC000 ) )
+ {
+ // Blip Property found: remember BStore Idx!
+ nPropRead = nLenShapePropTbl;
+ }
+ else if( 0x8000 & nPropId )
+ {
+ // complex Prop found:
+ // Length is always 6. The length of the appended extra data
+ // after the actual prop table is of different size.
+ nPropVal = 6;
+ }
+ }
+ break;
+ }
+ }
+ while (rSt.good() && nPropRead < nLenShapePropTbl);
+ rSt.Seek( nStartShapePropTbl + nLenShapePropTbl );
+ nReadSpCont += nLenShapePropTbl;
+ }
+ else if( ( DFF_msofbtClientTextbox == nFbt ) && ( 4 == nLength ) ) // Text-Box-Story-Entry found
+ {
+ rSt.ReadUInt32( aInfo.nTxBxComp );
+ // Add internal drawing container id to text id.
+ // Note: The text id uses the first two bytes, while the internal
+ // drawing container id used the second two bytes.
+ aInfo.nTxBxComp = ( aInfo.nTxBxComp & 0xFFFF0000 ) +
+ nDrawingContainerId;
+ DBG_ASSERT( (aInfo.nTxBxComp & 0x0000FFFF) == nDrawingContainerId,
+ "<SvxMSDffManager::GetShapeContainerData(..)> - internal drawing container Id could not be correctly merged into DFF_msofbtClientTextbox value." );
+ }
+ else
+ {
+ if (!checkSeek(rSt, rSt.Tell() + nLength))
+ {
+ SAL_WARN("filter.ms", "remaining record longer than available data, ppt or parser is wrong");
+ break;
+ }
+ nReadSpCont += nLength;
+ }
+ }
+ while( nReadSpCont < nLenShapeCont );
+
+
+ // Now possibly store the information for subsequent accesses to the shape
+
+ if( aInfo.nShapeId )
+ {
+ // Possibly allow replacement of textboxes with frames
+ if( bCanBeReplaced
+ && aInfo.nTxBxComp
+ && (
+ ( eShapeType == mso_sptTextSimple )
+ || ( eShapeType == mso_sptTextBox )
+ || ( eShapeType == mso_sptRectangle )
+ || ( eShapeType == mso_sptRoundRectangle )
+ ) )
+ {
+ aInfo.bReplaceByFly = true;
+ }
+ m_xShapeInfosByTxBxComp->insert(std::make_shared<SvxMSDffShapeInfo>(
+ aInfo));
+ m_aShapeOrders.push_back(std::make_unique<SvxMSDffShapeOrder>(
+ aInfo.nShapeId ));
+ }
+
+ // and position the Stream correctly again
+ rSt.Seek( nStartShapeCont + nLenShapeCont );
+ return true;
+}
+
+
+/*****************************************************************************
+
+ Access to a shape at runtime (via the Shape-Id)
+ ----------------------------
+******************************************************************************/
+bool SvxMSDffManager::GetShape(sal_uLong nId, SdrObject*& rpShape,
+ SvxMSDffImportData& rData)
+{
+ auto const pTmpRec = std::make_shared<SvxMSDffShapeInfo>(0, nId);
+
+ SvxMSDffShapeInfos_ById::const_iterator const it =
+ m_xShapeInfosById->find(pTmpRec);
+ if (it == m_xShapeInfosById->end())
+ return false;
+
+ // Possibly delete old error flag.
+ if( rStCtrl.GetError() )
+ rStCtrl.ResetError();
+ // store FilePos of the stream(s)
+ sal_uInt64 nOldPosCtrl = rStCtrl.Tell();
+ sal_uInt64 nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl;
+ // jump to the shape in the control stream
+ sal_uInt64 const nFilePos((*it)->nFilePos);
+ bool bSeeked = (nFilePos == rStCtrl.Seek(nFilePos));
+
+ // if it failed, reset error statusF
+ if (!bSeeked || rStCtrl.GetError())
+ rStCtrl.ResetError();
+ else
+ rpShape = ImportObj( rStCtrl, rData, rData.aParentRect, rData.aParentRect, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
+
+ // restore old FilePos of the stream(s)
+ rStCtrl.Seek( nOldPosCtrl );
+ if( &rStCtrl != pStData && pStData )
+ pStData->Seek( nOldPosData );
+ return ( nullptr != rpShape );
+}
+
+
+/** Access to a BLIP at runtime (if the Blip-Number is already known)
+ */
+bool SvxMSDffManager::GetBLIP( sal_uLong nIdx_, Graphic& rGraphic, tools::Rectangle* pVisArea )
+{
+ if (!pStData)
+ return false;
+
+ bool bOk = false; // initialize result variable
+
+ // check if a graphic for this blipId is already imported
+ if (nIdx_)
+ {
+ auto iter = aEscherBlipCache.find(nIdx_);
+
+ if (iter != aEscherBlipCache.end())
+ {
+ /* if this entry is available */
+ rGraphic = iter->second;
+ if (rGraphic.GetType() != GraphicType::NONE)
+ bOk = true;
+ else
+ aEscherBlipCache.erase(iter);
+ }
+ }
+
+ if (!bOk)
+ {
+ sal_uInt16 nIdx = sal_uInt16( nIdx_ );
+ if (!nIdx || (m_pBLIPInfos->size() < nIdx))
+ return false;
+
+ // possibly delete old error flag(s)
+ if( rStCtrl.GetError() )
+ rStCtrl.ResetError();
+ if( ( &rStCtrl != pStData )
+ && pStData->GetError() )
+ pStData->ResetError();
+
+ // remember FilePos of the stream(s)
+ sal_uInt64 nOldPosCtrl = rStCtrl.Tell();
+ sal_uInt64 nOldPosData = pStData->Tell();
+
+ // fetch matching info struct out of the pointer array
+ SvxMSDffBLIPInfo& rInfo = (*m_pBLIPInfos)[ nIdx-1 ];
+ // jump to the BLIP atom in the data stream
+ bOk = checkSeek(*pStData, rInfo.nFilePos);
+ // possibly reset error status
+ if (!bOk || pStData->GetError())
+ pStData->ResetError();
+ else
+ bOk = GetBLIPDirect( *pStData, rGraphic, pVisArea );
+ if( pStData2 && !bOk )
+ {
+ // Error, but the is a second chance: There is a second
+ // data stream in which the graphic could be stored!
+ if( pStData2->GetError() )
+ pStData2->ResetError();
+ sal_uInt64 nOldPosData2 = pStData2->Tell();
+ // jump to the BLIP atom in the second data stream
+ bOk = checkSeek(*pStData2, rInfo.nFilePos);
+ // reset error status if necessary
+ if (!bOk || pStData2->GetError())
+ pStData2->ResetError();
+ else
+ bOk = GetBLIPDirect( *pStData2, rGraphic, pVisArea );
+ // restore of FilePos of the second data stream
+ pStData2->Seek( nOldPosData2 );
+ }
+ // restore old FilePos of the stream(s)
+ rStCtrl.Seek( nOldPosCtrl );
+ if( &rStCtrl != pStData )
+ pStData->Seek( nOldPosData );
+
+ if (bOk)
+ {
+ // create new BlipCacheEntry for this graphic
+ aEscherBlipCache.insert(std::make_pair(nIdx_, rGraphic));
+ }
+ }
+
+ return bOk;
+}
+
+/* access to a BLIP at runtime (with correctly positioned stream)
+ ---------------------------------
+******************************************************************************/
+bool SvxMSDffManager::GetBLIPDirect( SvStream& rBLIPStream, Graphic& rData, tools::Rectangle* pVisArea )
+{
+ sal_uInt64 nOldPos = rBLIPStream.Tell();
+
+ ErrCode nRes = ERRCODE_GRFILTER_OPENERROR; // initialize error variable
+
+ // check whether it's really a BLIP
+ sal_uInt32 nLength;
+ sal_uInt16 nInst, nFbt( 0 );
+ sal_uInt8 nVer;
+ if( ReadCommonRecordHeader( rBLIPStream, nVer, nInst, nFbt, nLength) && ( 0xF018 <= nFbt ) && ( 0xF117 >= nFbt ) )
+ {
+ Size aMtfSize100;
+ bool bMtfBLIP = false;
+ bool bZCodecCompression = false;
+ // now position it exactly at the beginning of the embedded graphic
+ sal_uLong nSkip = (nInst & 0x0001) ? 32 : 16;
+ const OfficeArtBlipRecInstance aRecInstanse = OfficeArtBlipRecInstance(nInst & 0xFFFE);
+ switch (aRecInstanse)
+ {
+ case OfficeArtBlipRecInstance::EMF:
+ case OfficeArtBlipRecInstance::WMF:
+ case OfficeArtBlipRecInstance::PICT:
+ {
+ rBLIPStream.SeekRel(nSkip + 20);
+
+ // read in size of metafile in English Metric Units (EMUs)
+ sal_Int32 width(0), height(0);
+ rBLIPStream.ReadInt32(width).ReadInt32(height);
+ aMtfSize100.setWidth(width);
+ aMtfSize100.setHeight(height);
+
+ // 1 EMU = 1/360,000 of a centimeter
+ // scale to 1/100mm
+ aMtfSize100.setWidth(aMtfSize100.Width() / 360);
+ aMtfSize100.setHeight(aMtfSize100.Height() / 360);
+
+ if (pVisArea) // seem that we currently are skipping the visarea position
+ *pVisArea = tools::Rectangle(Point(), aMtfSize100);
+
+ // skip rest of header
+ nSkip = 6;
+ bMtfBLIP = bZCodecCompression = true;
+ }
+ break;
+ case OfficeArtBlipRecInstance::JPEG_RGB:
+ case OfficeArtBlipRecInstance::JPEG_CMYK:
+ case OfficeArtBlipRecInstance::PNG:
+ case OfficeArtBlipRecInstance::DIB:
+ case OfficeArtBlipRecInstance::TIFF:
+ nSkip += 1; // Skip one byte tag
+ break;
+ }
+ rBLIPStream.SeekRel( nSkip );
+
+ SvStream* pGrStream = &rBLIPStream;
+ std::unique_ptr<SvMemoryStream> xOut;
+ if( bZCodecCompression )
+ {
+ xOut.reset(new SvMemoryStream( 0x8000, 0x4000 ));
+ ZCodec aZCodec( 0x8000, 0x8000 );
+ aZCodec.BeginCompression();
+ aZCodec.Decompress( rBLIPStream, *xOut );
+ aZCodec.EndCompression();
+ xOut->Seek( STREAM_SEEK_TO_BEGIN );
+ xOut->SetResizeOffset( 0 ); // sj: #i102257# setting ResizeOffset of 0 prevents from seeking
+ // behind the stream end (allocating too much memory)
+ pGrStream = xOut.get();
+ }
+
+#ifdef DEBUG_FILTER_MSDFFIMP
+ // extract graphics from ole storage into "dbggfxNNN.*"
+ static sal_Int32 nGrfCount;
+
+ OUString aFileName = "dbggfx" + OUString::number(nGrfCount++);
+ switch (aRecInstanse)
+ {
+ case OfficeArtBlipRecInstance::WMF:
+ aFileName += ".wmf";
+ break;
+ case OfficeArtBlipRecInstance::EMF:
+ aFileName += ".emf";
+ break;
+ case OfficeArtBlipRecInstance::PICT:
+ aFileName += ".pct";
+ break;
+ case OfficeArtBlipRecInstance::JPEG_RGB:
+ case OfficeArtBlipRecInstance::JPEG_CMYK:
+ aFileName += ".jpg";
+ break;
+ case OfficeArtBlipRecInstance::PNG:
+ aFileName += ".png";
+ break;
+ case OfficeArtBlipRecInstance::DIB:
+ aFileName += ".bmp";
+ break;
+ case OfficeArtBlipRecInstance::TIFF:
+ aFileName += ".tif";
+ break;
+ }
+
+
+ OUString aURLStr;
+ if( osl::FileBase::getFileURLFromSystemPath( Application::GetAppFileName(), aURLStr ) == osl::FileBase::E_None )
+ {
+ INetURLObject aURL( aURLStr );
+
+ aURL.removeSegment();
+ aURL.removeFinalSlash();
+ aURL.Append( aFileName );
+
+ aURLStr = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
+
+ SAL_INFO("filter.ms", "dumping " << aURLStr);
+
+ std::unique_ptr<SvStream> pDbgOut(::utl::UcbStreamHelper::CreateStream(aURLStr, StreamMode::TRUNC | StreamMode::WRITE));
+
+ if( pDbgOut )
+ {
+ if ( bZCodecCompression )
+ {
+ pDbgOut->WriteBytes(xOut->GetData(), xOut->TellEnd());
+ xOut->Seek(STREAM_SEEK_TO_BEGIN);
+ }
+ else
+ {
+ sal_Int32 nDbgLen = nLength - nSkip;
+ if ( nDbgLen )
+ {
+ std::vector<char> aData(nDbgLen);
+ pGrStream->ReadBytes(aData.data(), nDbgLen);
+ pDbgOut->WriteBytes(aData.data(), nDbgLen);
+ pGrStream->SeekRel(-nDbgLen);
+ }
+ }
+ }
+ }
+#endif
+ if (aRecInstanse == OfficeArtBlipRecInstance::DIB)
+ { // getting the DIBs immediately
+ Bitmap aNew;
+ if( ReadDIB(aNew, *pGrStream, false) )
+ {
+ rData = Graphic(BitmapEx(aNew));
+ nRes = ERRCODE_NONE;
+ }
+ }
+ else
+ { // and unleash our filter
+ GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
+ // ImportUnloadedGraphic() may simply read the entire rest of the stream,
+ // which may be very large if the whole document is large. Limit the read
+ // size to the size of this record.
+ sal_uInt64 maxSize = pGrStream == &rBLIPStream ? nLength : 0;
+ Graphic aGraphic;
+
+ // Size available in metafile header.
+ if (aMtfSize100.getWidth() && aMtfSize100.getHeight())
+ aGraphic = rGF.ImportUnloadedGraphic(*pGrStream, maxSize, &aMtfSize100);
+ else
+ aGraphic = rGF.ImportUnloadedGraphic(*pGrStream, maxSize);
+
+ if (!aGraphic.IsNone())
+ {
+ rData = aGraphic;
+ nRes = ERRCODE_NONE;
+ }
+ else
+ nRes = rGF.ImportGraphic( rData, u"", *pGrStream );
+
+ // SJ: I40472, sometimes the aspect ratio (aMtfSize100) does not match and we get scaling problems,
+ // then it is better to use the prefsize that is stored within the metafile. Bug #72846# for what the
+ // scaling has been implemented does not happen anymore.
+ //
+ // For pict graphics we will furthermore scale the metafile, because font scaling leads to error if the
+ // dxarray is empty (this has been solved in wmf/emf but not for pict)
+ if (bMtfBLIP && (ERRCODE_NONE == nRes) && (rData.GetType() == GraphicType::GdiMetafile)
+ && (aRecInstanse == OfficeArtBlipRecInstance::PICT))
+ {
+ if ( ( aMtfSize100.Width() >= 1000 ) && ( aMtfSize100.Height() >= 1000 ) )
+ { // #75956#, scaling does not work properly, if the graphic is less than 1cm
+ GDIMetaFile aMtf( rData.GetGDIMetaFile() );
+ const Size aOldSize( aMtf.GetPrefSize() );
+
+ if( aOldSize.Width() && ( aOldSize.Width() != aMtfSize100.Width() ) &&
+ aOldSize.Height() && ( aOldSize.Height() != aMtfSize100.Height() ) )
+ {
+ aMtf.Scale( static_cast<double>(aMtfSize100.Width()) / aOldSize.Width(),
+ static_cast<double>(aMtfSize100.Height()) / aOldSize.Height() );
+ aMtf.SetPrefSize( aMtfSize100 );
+ aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ rData = aMtf;
+ }
+ }
+ }
+ }
+ // reset error status if necessary
+ if ( ERRCODE_IO_PENDING == pGrStream->GetError() )
+ pGrStream->ResetError();
+ }
+ rBLIPStream.Seek( nOldPos ); // restore old FilePos of the stream
+
+ return ( ERRCODE_NONE == nRes ); // return result
+}
+
+/* also static */
+bool SvxMSDffManager::ReadCommonRecordHeader(SvStream& rSt,
+ sal_uInt8& rVer, sal_uInt16& rInst, sal_uInt16& rFbt, sal_uInt32& rLength)
+{
+ sal_uInt16 nTmp(0);
+ rSt.ReadUInt16( nTmp ).ReadUInt16( rFbt ).ReadUInt32( rLength );
+ rVer = sal::static_int_cast< sal_uInt8 >(nTmp & 15);
+ rInst = nTmp >> 4;
+ if (!rSt.good())
+ return false;
+ if (rLength > nMaxLegalDffRecordLength)
+ return false;
+ return true;
+}
+
+void SvxMSDffManager::ProcessClientAnchor(SvStream& rStData, sal_uInt32 nDatLen,
+ std::unique_ptr<char[]>& rpBuff, sal_uInt32& rBuffLen )
+{
+ if( nDatLen )
+ {
+ rBuffLen = std::min(rStData.remainingSize(), static_cast<sal_uInt64>(nDatLen));
+ rpBuff.reset( new char[rBuffLen] );
+ rBuffLen = rStData.ReadBytes(rpBuff.get(), rBuffLen);
+ }
+}
+
+void SvxMSDffManager::ProcessClientData(SvStream& rStData, sal_uInt32 nDatLen,
+ std::unique_ptr<char[]>& rpBuff, sal_uInt32& rBuffLen )
+{
+ if( nDatLen )
+ {
+ rBuffLen = std::min(rStData.remainingSize(), static_cast<sal_uInt64>(nDatLen));
+ rpBuff.reset( new char[rBuffLen] );
+ rBuffLen = rStData.ReadBytes(rpBuff.get(), rBuffLen);
+ }
+}
+
+
+void SvxMSDffManager::ProcessClientAnchor2( SvStream& /* rSt */, DffRecordHeader& /* rHd */ , DffObjData& /* rObj */ )
+{
+ // will be overridden by SJ in Draw
+}
+
+bool SvxMSDffManager::GetOLEStorageName( sal_uInt32, OUString&, tools::SvRef<SotStorage>&, uno::Reference < embed::XStorage >& ) const
+{
+ return false;
+}
+
+bool SvxMSDffManager::ShapeHasText( sal_uLong /* nShapeId */, sal_uLong /* nFilePos */ ) const
+{
+ return true;
+}
+
+// #i32596# - add new parameter <_nCalledByGroup>
+SdrObject* SvxMSDffManager::ImportOLE( sal_uInt32 nOLEId,
+ const Graphic& rGrf,
+ const tools::Rectangle& rBoundRect,
+ const tools::Rectangle& rVisArea,
+ const int /* _nCalledByGroup */ ) const
+{
+ SdrObject* pRet = nullptr;
+ OUString sStorageName;
+ tools::SvRef<SotStorage> xSrcStg;
+ ErrCode nError = ERRCODE_NONE;
+ uno::Reference < embed::XStorage > xDstStg;
+ if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg ))
+ pRet = CreateSdrOLEFromStorage(
+ *GetModel(),
+ sStorageName,
+ xSrcStg,
+ xDstStg,
+ rGrf,
+ rBoundRect,
+ rVisArea,
+ pStData,
+ nError,
+ nSvxMSDffOLEConvFlags,
+ embed::Aspects::MSOLE_CONTENT,
+ maBaseURL);
+ return pRet;
+}
+
+bool SvxMSDffManager::MakeContentStream( SotStorage * pStor, const GDIMetaFile & rMtf )
+{
+ tools::SvRef<SotStorageStream> xStm = pStor->OpenSotStream(SVEXT_PERSIST_STREAM);
+ xStm->SetVersion( pStor->GetVersion() );
+ xStm->SetBufferSize( 8192 );
+
+ Impl_OlePres aEle;
+ // Convert the size in 1/100 mm
+ // If a not applicable MapUnit (device dependent) is used,
+ // SV tries to guess a best match for the right value
+ Size aSize = rMtf.GetPrefSize();
+ const MapMode& aMMSrc = rMtf.GetPrefMapMode();
+ MapMode aMMDst( MapUnit::Map100thMM );
+ aSize = OutputDevice::LogicToLogic( aSize, aMMSrc, aMMDst );
+ aEle.SetSize( aSize );
+ aEle.SetAspect( ASPECT_CONTENT );
+ aEle.SetAdviseFlags( 2 );
+ aEle.SetMtf( rMtf );
+ aEle.Write( *xStm );
+
+ xStm->SetBufferSize( 0 );
+ return xStm->GetError() == ERRCODE_NONE;
+}
+
+namespace {
+
+struct ClsIDs {
+ sal_uInt32 nId;
+ const char* pSvrName;
+ const char* pDspName;
+};
+
+}
+
+const ClsIDs aClsIDs[] = {
+
+ { 0x000212F0, "MSWordArt", "Microsoft Word Art" },
+ { 0x000212F0, "MSWordArt.2", "Microsoft Word Art 2.0" },
+
+ // MS Apps
+ { 0x00030000, "ExcelWorksheet", "Microsoft Excel Worksheet" },
+ { 0x00030001, "ExcelChart", "Microsoft Excel Chart" },
+ { 0x00030002, "ExcelMacrosheet", "Microsoft Excel Macro" },
+ { 0x00030003, "WordDocument", "Microsoft Word Document" },
+ { 0x00030004, "MSPowerPoint", "Microsoft PowerPoint" },
+ { 0x00030005, "MSPowerPointSho", "Microsoft PowerPoint Slide Show"},
+ { 0x00030006, "MSGraph", "Microsoft Graph" },
+ { 0x00030007, "MSDraw", "Microsoft Draw" },
+ { 0x00030008, "Note-It", "Microsoft Note-It" },
+ { 0x00030009, "WordArt", "Microsoft Word Art" },
+ { 0x0003000a, "PBrush", "Microsoft PaintBrush Picture" },
+ { 0x0003000b, "Equation", "Microsoft Equation Editor" },
+ { 0x0003000c, "Package", "Package" },
+ { 0x0003000d, "SoundRec", "Sound" },
+ { 0x0003000e, "MPlayer", "Media Player" },
+ // MS Demos
+ { 0x0003000f, "ServerDemo", "OLE 1.0 Server Demo" },
+ { 0x00030010, "Srtest", "OLE 1.0 Test Demo" },
+ { 0x00030011, "SrtInv", "OLE 1.0 Inv Demo" },
+ { 0x00030012, "OleDemo", "OLE 1.0 Demo" },
+
+ // Coromandel / Dorai Swamy / 718-793-7963
+ { 0x00030013, "CoromandelIntegra", "Coromandel Integra" },
+ { 0x00030014, "CoromandelObjServer","Coromandel Object Server" },
+
+ // 3-d Visions Corp / Peter Hirsch / 310-325-1339
+ { 0x00030015, "StanfordGraphics", "Stanford Graphics" },
+
+ // Deltapoint / Nigel Hearne / 408-648-4000
+ { 0x00030016, "DGraphCHART", "DeltaPoint Graph Chart" },
+ { 0x00030017, "DGraphDATA", "DeltaPoint Graph Data" },
+
+ // Corel / Richard V. Woodend / 613-728-8200 x1153
+ { 0x00030018, "PhotoPaint", "Corel PhotoPaint" },
+ { 0x00030019, "CShow", "Corel Show" },
+ { 0x0003001a, "CorelChart", "Corel Chart" },
+ { 0x0003001b, "CDraw", "Corel Draw" },
+
+ // Inset Systems / Mark Skiba / 203-740-2400
+ { 0x0003001c, "HJWIN1.0", "Inset Systems" },
+
+ // Mark V Systems / Mark McGraw / 818-995-7671
+ { 0x0003001d, "ObjMakerOLE", "MarkV Systems Object Maker" },
+
+ // IdentiTech / Mike Gilger / 407-951-9503
+ { 0x0003001e, "FYI", "IdentiTech FYI" },
+ { 0x0003001f, "FYIView", "IdentiTech FYI Viewer" },
+
+ // Inventa Corporation / Balaji Varadarajan / 408-987-0220
+ { 0x00030020, "Stickynote", "Inventa Sticky Note" },
+
+ // ShapeWare Corp. / Lori Pearce / 206-467-6723
+ { 0x00030021, "ShapewareVISIO10", "Shapeware Visio 1.0" },
+ { 0x00030022, "ImportServer", "Spaheware Import Server" },
+
+ // test app SrTest
+ { 0x00030023, "SrvrTest", "OLE 1.0 Server Test" },
+
+ // test app ClTest. Doesn't really work as a server but is in reg db
+ { 0x00030025, "Cltest", "OLE 1.0 Client Test" },
+
+ // Microsoft ClipArt Gallery Sherry Larsen-Holmes
+ { 0x00030026, "MS_ClipArt_Gallery", "Microsoft ClipArt Gallery" },
+ // Microsoft Project Cory Reina
+ { 0x00030027, "MSProject", "Microsoft Project" },
+
+ // Microsoft Works Chart
+ { 0x00030028, "MSWorksChart", "Microsoft Works Chart" },
+
+ // Microsoft Works Spreadsheet
+ { 0x00030029, "MSWorksSpreadsheet", "Microsoft Works Spreadsheet" },
+
+ // AFX apps - Dean McCrory
+ { 0x0003002A, "MinSvr", "AFX Mini Server" },
+ { 0x0003002B, "HierarchyList", "AFX Hierarchy List" },
+ { 0x0003002C, "BibRef", "AFX BibRef" },
+ { 0x0003002D, "MinSvrMI", "AFX Mini Server MI" },
+ { 0x0003002E, "TestServ", "AFX Test Server" },
+
+ // Ami Pro
+ { 0x0003002F, "AmiProDocument", "Ami Pro Document" },
+
+ // WordPerfect Presentations For Windows
+ { 0x00030030, "WPGraphics", "WordPerfect Presentation" },
+ { 0x00030031, "WPCharts", "WordPerfect Chart" },
+
+ // MicroGrafx Charisma
+ { 0x00030032, "Charisma", "MicroGrafx Charisma" },
+ { 0x00030033, "Charisma_30", "MicroGrafx Charisma 3.0" },
+ { 0x00030034, "CharPres_30", "MicroGrafx Charisma 3.0 Pres" },
+ // MicroGrafx Draw
+ { 0x00030035, "Draw", "MicroGrafx Draw" },
+ // MicroGrafx Designer
+ { 0x00030036, "Designer_40", "MicroGrafx Designer 4.0" },
+
+ // STAR DIVISION
+ { 0x00043AD2, "FontWork", "Star FontWork" },
+
+ { 0, "", "" } };
+
+
+bool SvxMSDffManager::ConvertToOle2( SvStream& rStm, sal_uInt32 nReadLen,
+ const GDIMetaFile * pMtf, const tools::SvRef<SotStorage>& rDest )
+{
+ bool bMtfRead = false;
+ tools::SvRef<SotStorageStream> xOle10Stm = rDest->OpenSotStream( "\1Ole10Native",
+ StreamMode::WRITE| StreamMode::SHARE_DENYALL );
+ if( xOle10Stm->GetError() )
+ return false;
+
+ OUString aSvrName;
+ sal_uInt32 nDummy0;
+ sal_uInt32 nDummy1;
+ sal_uInt32 nBytesRead = 0;
+ do
+ {
+ sal_uInt32 nType(0);
+ sal_uInt32 nRecType(0);
+ sal_uInt32 nStrLen(0);
+
+ rStm.ReadUInt32( nType );
+ rStm.ReadUInt32( nRecType );
+ rStm.ReadUInt32( nStrLen );
+ if( nStrLen )
+ {
+ if( 0x10000L > nStrLen )
+ {
+ std::unique_ptr<char[]> pBuf(new char[ nStrLen ]);
+ rStm.ReadBytes(pBuf.get(), nStrLen);
+ aSvrName = OUString( pBuf.get(), static_cast<sal_uInt16>(nStrLen)-1, osl_getThreadTextEncoding() );
+ }
+ else
+ break;
+ }
+ rStm.ReadUInt32( nDummy0 );
+ rStm.ReadUInt32( nDummy1 );
+ sal_uInt32 nDataLen(0);
+ rStm.ReadUInt32( nDataLen );
+
+ nBytesRead += 6 * sizeof( sal_uInt32 ) + nStrLen + nDataLen;
+
+ if (rStm.good() && nReadLen > nBytesRead && nDataLen)
+ {
+ if( xOle10Stm.is() )
+ {
+ std::unique_ptr<sal_uInt8[]> pData(new sal_uInt8[ nDataLen ]);
+ rStm.ReadBytes(pData.get(), nDataLen);
+
+ // write to ole10 stream
+ xOle10Stm->WriteUInt32( nDataLen );
+ xOle10Stm->WriteBytes(pData.get(), nDataLen);
+ xOle10Stm = tools::SvRef<SotStorageStream>();
+
+ // set the compobj stream
+ const ClsIDs* pIds;
+ for( pIds = aClsIDs; pIds->nId; pIds++ )
+ {
+ if( aSvrName == OUString::createFromAscii(pIds->pSvrName) )
+ break;
+ }
+
+ if( pIds->nId )
+ {
+ // found!
+ SotClipboardFormatId nCbFmt = SotExchange::RegisterFormatName( aSvrName );
+ rDest->SetClass( SvGlobalName( pIds->nId, 0, 0, 0xc0,0,0,0,0,0,0,0x46 ), nCbFmt,
+ OUString::createFromAscii( pIds->pDspName ) );
+ }
+ else
+ {
+ SotClipboardFormatId nCbFmt = SotExchange::RegisterFormatName( aSvrName );
+ rDest->SetClass( SvGlobalName(), nCbFmt, aSvrName );
+ }
+ }
+ else if( nRecType == 5 && !pMtf )
+ {
+ sal_uInt64 nPos = rStm.Tell();
+ sal_uInt16 sz[4];
+ rStm.ReadBytes( sz, 8 );
+ Graphic aGraphic;
+ if( ERRCODE_NONE == GraphicConverter::Import( rStm, aGraphic ) && aGraphic.GetType() != GraphicType::NONE )
+ {
+ const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
+ MakeContentStream( rDest.get(), rMtf );
+ bMtfRead = true;
+ }
+ // set behind the data
+ rStm.Seek( nPos + nDataLen );
+ }
+ else
+ rStm.SeekRel( nDataLen );
+ }
+ } while (rStm.good() && nReadLen >= nBytesRead);
+
+ if( !bMtfRead && pMtf )
+ {
+ MakeContentStream( rDest.get(), *pMtf );
+ return true;
+ }
+
+ return false;
+}
+
+static const char* GetInternalServerName_Impl( const SvGlobalName& aGlobName )
+{
+ if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_60 )
+ || aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
+ return "swriter";
+ else if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_60 )
+ || aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
+ return "scalc";
+ else if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 )
+ || aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
+ return "simpress";
+ else if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_60 )
+ || aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
+ return "sdraw";
+ else if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_60 )
+ || aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
+ return "smath";
+ else if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_60 )
+ || aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
+ return "schart";
+ return nullptr;
+}
+
+OUString SvxMSDffManager::GetFilterNameFromClassID( const SvGlobalName& aGlobName )
+{
+ if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_60 ) )
+ return "StarOffice XML (Writer)";
+
+ if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
+ return "writer8";
+
+ if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_60 ) )
+ return "StarOffice XML (Calc)";
+
+ if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
+ return "calc8";
+
+ if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 ) )
+ return "StarOffice XML (Impress)";
+
+ if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
+ return "impress8";
+
+ if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_60 ) )
+ return "StarOffice XML (Draw)";
+
+ if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
+ return "draw8";
+
+ if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_60 ) )
+ return "StarOffice XML (Math)";
+
+ if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
+ return "math8";
+
+ if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_60 ) )
+ return "StarOffice XML (Chart)";
+
+ if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
+ return "chart8";
+
+ return OUString();
+}
+
+void SvxMSDffManager::ExtractOwnStream(SotStorage& rSrcStg, SvMemoryStream& rMemStream)
+{
+ tools::SvRef<SotStorageStream> xStr
+ = rSrcStg.OpenSotStream("package_stream", StreamMode::STD_READ);
+ xStr->ReadStream(rMemStream);
+}
+
+css::uno::Reference < css::embed::XEmbeddedObject > SvxMSDffManager::CheckForConvertToSOObj( sal_uInt32 nConvertFlags,
+ SotStorage& rSrcStg, const uno::Reference < embed::XStorage >& rDestStorage,
+ const Graphic& rGrf,
+ const tools::Rectangle& rVisArea, OUString const& rBaseURL)
+{
+ uno::Reference < embed::XEmbeddedObject > xObj;
+ SvGlobalName aStgNm = rSrcStg.GetClassName();
+ const char* pName = GetInternalServerName_Impl( aStgNm );
+ OUString sStarName;
+ if ( pName )
+ sStarName = OUString::createFromAscii( pName );
+ else if ( nConvertFlags )
+ {
+ static struct ObjImpType
+ {
+ sal_uInt32 nFlag;
+ const char* pFactoryNm;
+ // GlobalNameId
+ sal_uInt32 n1;
+ sal_uInt16 n2, n3;
+ sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
+ } const aArr[] = {
+ { OLE_MATHTYPE_2_STARMATH, "smath", MSO_EQUATION3_CLASSID },
+ { OLE_MATHTYPE_2_STARMATH, "smath", MSO_EQUATION2_CLASSID },
+ { OLE_WINWORD_2_STARWRITER, "swriter", MSO_WW8_CLASSID },
+ // Excel table
+ { OLE_EXCEL_2_STARCALC, "scalc", MSO_EXCEL5_CLASSID },
+ { OLE_EXCEL_2_STARCALC, "scalc", MSO_EXCEL8_CLASSID },
+ // 114465: additional Excel OLE chart classId to above.
+ { OLE_EXCEL_2_STARCALC, "scalc", MSO_EXCEL8_CHART_CLASSID },
+ // PowerPoint presentation
+ { OLE_POWERPOINT_2_STARIMPRESS, "simpress", MSO_PPT8_CLASSID },
+ // PowerPoint slide
+ { OLE_POWERPOINT_2_STARIMPRESS, "simpress", MSO_PPT8_SLIDE_CLASSID },
+ { 0, nullptr,
+ 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0 }
+ };
+
+ for( const ObjImpType* pArr = aArr; pArr->nFlag; ++pArr )
+ {
+ if( nConvertFlags & pArr->nFlag )
+ {
+ SvGlobalName aTypeName( pArr->n1, pArr->n2, pArr->n3,
+ pArr->b8, pArr->b9, pArr->b10, pArr->b11,
+ pArr->b12, pArr->b13, pArr->b14, pArr->b15 );
+
+ if ( aStgNm == aTypeName )
+ {
+ sStarName = OUString::createFromAscii( pArr->pFactoryNm );
+ break;
+ }
+ }
+ }
+ }
+
+ if ( sStarName.getLength() )
+ {
+ //TODO/MBA: check if (and when) storage and stream will be destroyed!
+ std::shared_ptr<const SfxFilter> pFilter;
+ SvMemoryStream aMemStream;
+ if ( pName )
+ {
+ // TODO/LATER: perhaps we need to retrieve VisArea and Metafile from the storage also
+ SvxMSDffManager::ExtractOwnStream(rSrcStg, aMemStream);
+ }
+ else
+ {
+ tools::SvRef<SotStorage> xStorage = new SotStorage( false, aMemStream );
+ rSrcStg.CopyTo( xStorage.get() );
+ xStorage->Commit();
+ xStorage.clear();
+ OUString aType = SfxFilter::GetTypeFromStorage( rSrcStg );
+ if (aType.getLength() && !utl::ConfigManager::IsFuzzing())
+ {
+ SfxFilterMatcher aMatch( sStarName );
+ pFilter = aMatch.GetFilter4EA( aType );
+ }
+ }
+
+#ifdef DEBUG_FILTER_MSFILTER
+ // extract embedded ole streams into "/tmp/embedded_stream_NNN"
+ static sal_Int32 nOleCount(0);
+ OUString aTmpName("/tmp/embedded_stream_");
+ aTmpName += OUString::number(nOleCount++);
+ aTmpName += ".bin";
+ SvFileStream aTmpStream(aTmpName,StreamMode::READ|StreamMode::WRITE|StreamMode::TRUNC);
+ xMemStream->Seek(0);
+ aTmpStream.WriteStream(*xMemStream);
+ aTmpStream.Close();
+#endif
+ if ( pName || pFilter )
+ {
+ //Reuse current ole name
+ OUString aDstStgName = MSO_OLE_Obj + OUString::number(nMSOleObjCntr);
+
+ OUString aFilterName;
+ if ( pFilter )
+ aFilterName = pFilter->GetName();
+ else
+ aFilterName = SvxMSDffManager::GetFilterNameFromClassID( aStgNm );
+
+ uno::Sequence<beans::PropertyValue> aMedium(aFilterName.isEmpty() ? 3 : 4);
+ auto pMedium = aMedium.getArray();
+ pMedium[0].Name = "InputStream";
+ uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( aMemStream );
+ pMedium[0].Value <<= xStream;
+ pMedium[1].Name = "URL";
+ pMedium[1].Value <<= OUString( "private:stream" );
+ pMedium[2].Name = "DocumentBaseURL";
+ pMedium[2].Value <<= rBaseURL;
+
+ if ( !aFilterName.isEmpty() )
+ {
+ pMedium[3].Name = "FilterName";
+ pMedium[3].Value <<= aFilterName;
+ }
+
+ OUString aName( aDstStgName );
+ comphelper::EmbeddedObjectContainer aCnt( rDestStorage );
+ xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &rBaseURL);
+
+ if ( !xObj.is() )
+ {
+ if( !aFilterName.isEmpty() )
+ {
+ // throw the filter parameter away as workaround
+ aMedium.realloc( 2 );
+ xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &rBaseURL);
+ }
+
+ if ( !xObj.is() )
+ return xObj;
+ }
+
+ // JP 26.10.2001: Bug 93374 / 91928 the writer
+ // objects need the correct visarea needs the
+ // correct visarea, but this is not true for
+ // PowerPoint (see bugdoc 94908b)
+ // SJ: 19.11.2001 bug 94908, also chart objects
+ // needs the correct visarea
+
+ // If pName is set this is an own embedded object, it should have the correct size internally
+ // TODO/LATER: it might make sense in future to set the size stored in internal object
+ if( !pName && ( sStarName == "swriter" || sStarName == "scalc" ) )
+ {
+ // TODO/LATER: ViewAspect must be passed from outside!
+ sal_Int64 nViewAspect = embed::Aspects::MSOLE_CONTENT;
+ MapMode aMapMode( VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nViewAspect ) ) );
+ Size aSz;
+ if ( rVisArea.IsEmpty() )
+ aSz = lcl_GetPrefSize(rGrf, aMapMode );
+ else
+ {
+ aSz = rVisArea.GetSize();
+ aSz = OutputDevice::LogicToLogic( aSz, MapMode( MapUnit::Map100thMM ), aMapMode );
+ }
+
+ // don't modify the object
+ //TODO/LATER: remove those hacks, that needs to be done differently!
+ //xIPObj->EnableSetModified( sal_False );
+ awt::Size aSize;
+ aSize.Width = aSz.Width();
+ aSize.Height = aSz.Height();
+ xObj->setVisualAreaSize( nViewAspect, aSize );
+ //xIPObj->EnableSetModified( sal_True );
+ }
+ else if ( sStarName == "smath" )
+ { // SJ: force the object to recalc its visarea
+ //TODO/LATER: wait for PrinterChangeNotification
+ //xIPObj->OnDocumentPrinterChanged( NULL );
+ }
+ }
+ }
+
+ return xObj;
+}
+
+// TODO/MBA: code review and testing!
+SdrOle2Obj* SvxMSDffManager::CreateSdrOLEFromStorage(
+ SdrModel& rSdrModel,
+ const OUString& rStorageName,
+ tools::SvRef<SotStorage> const & rSrcStorage,
+ const uno::Reference < embed::XStorage >& xDestStorage,
+ const Graphic& rGrf,
+ const tools::Rectangle& rBoundRect,
+ const tools::Rectangle& rVisArea,
+ SvStream* pDataStrm,
+ ErrCode& rError,
+ sal_uInt32 nConvertFlags,
+ sal_Int64 nRecommendedAspect,
+ OUString const& rBaseURL)
+{
+ sal_Int64 nAspect = nRecommendedAspect;
+ SdrOle2Obj* pRet = nullptr;
+ if( rSrcStorage.is() && xDestStorage.is() && rStorageName.getLength() )
+ {
+ comphelper::EmbeddedObjectContainer aCnt( xDestStorage );
+ // does the 01Ole-Stream exist at all?
+ // (that's not the case for e.g. Fontwork )
+ // If that's not the case -> include it as graphic
+ bool bValidStorage = false;
+ OUString aDstStgName = MSO_OLE_Obj + OUString::number( ++nMSOleObjCntr );
+
+ {
+ tools::SvRef<SotStorage> xObjStg = rSrcStorage->OpenSotStorage( rStorageName );
+ if( xObjStg.is() )
+ {
+ {
+ sal_uInt8 aTestA[10]; // exist the \1CompObj-Stream ?
+ tools::SvRef<SotStorageStream> xSrcTst = xObjStg->OpenSotStream( "\1CompObj" );
+ bValidStorage = xSrcTst.is() && sizeof( aTestA ) ==
+ xSrcTst->ReadBytes(aTestA, sizeof(aTestA));
+ if( !bValidStorage )
+ {
+ // or the \1Ole-Stream ?
+ xSrcTst = xObjStg->OpenSotStream( "\1Ole" );
+ bValidStorage = xSrcTst.is() && sizeof(aTestA) ==
+ xSrcTst->ReadBytes(aTestA, sizeof(aTestA));
+ }
+ }
+
+ if( bValidStorage )
+ {
+ if ( nAspect != embed::Aspects::MSOLE_ICON )
+ {
+ // check whether the object is iconified one
+ // usually this information is already known, the only exception
+ // is a kind of embedded objects in Word documents
+ // TODO/LATER: should the caller be notified if the aspect changes in future?
+
+ tools::SvRef<SotStorageStream> xObjInfoSrc = xObjStg->OpenSotStream(
+ "\3ObjInfo", StreamMode::STD_READ );
+ if ( xObjInfoSrc.is() && !xObjInfoSrc->GetError() )
+ {
+ sal_uInt8 nByte = 0;
+ xObjInfoSrc->ReadUChar( nByte );
+ if ( ( nByte >> 4 ) & embed::Aspects::MSOLE_ICON )
+ nAspect = embed::Aspects::MSOLE_ICON;
+ }
+ }
+
+ uno::Reference < embed::XEmbeddedObject > xObj( CheckForConvertToSOObj(
+ nConvertFlags, *xObjStg, xDestStorage, rGrf,
+ rVisArea, rBaseURL));
+ if ( xObj.is() )
+ {
+ // remember file name to use in the title bar
+ INetURLObject aURL(rBaseURL);
+ xObj->setContainerName(aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset));
+
+ svt::EmbeddedObjectRef aObj( xObj, nAspect );
+
+ // TODO/LATER: need MediaType
+ aObj.SetGraphic( rGrf, OUString() );
+
+ // TODO/MBA: check setting of PersistName
+ pRet = new SdrOle2Obj(
+ rSdrModel,
+ aObj,
+ OUString(),
+ rBoundRect);
+
+ // we have the Object, don't create another
+ bValidStorage = false;
+ }
+ }
+ }
+ }
+
+ if( bValidStorage )
+ {
+ // object is not an own object
+ tools::SvRef<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName, StreamMode::READWRITE );
+
+ if ( xObjStor.is() )
+ {
+ tools::SvRef<SotStorage> xSrcStor = rSrcStorage->OpenSotStorage( rStorageName, StreamMode::READ );
+ xSrcStor->CopyTo( xObjStor.get() );
+
+ if( !xObjStor->GetError() )
+ xObjStor->Commit();
+
+ if( xObjStor->GetError() )
+ {
+ rError = xObjStor->GetError();
+ bValidStorage = false;
+ }
+ else if( !xObjStor.is() )
+ bValidStorage = false;
+ }
+ }
+ else if( pDataStrm )
+ {
+ sal_uInt32 nLen(0), nDummy(0);
+ pDataStrm->ReadUInt32( nLen ).ReadUInt32( nDummy );
+ if( ERRCODE_NONE != pDataStrm->GetError() ||
+ // Id in BugDoc - exist there other Ids?
+ // The ConvertToOle2 - does not check for consistent
+ 0x30008 != nDummy )
+ bValidStorage = false;
+ else
+ {
+ // or is it an OLE-1 Stream in the DataStream?
+ tools::SvRef<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName );
+ //TODO/MBA: remove metafile conversion from ConvertToOle2
+ //when is this code used?!
+ GDIMetaFile aMtf;
+ bValidStorage = ConvertToOle2( *pDataStrm, nLen, &aMtf, xObjStor );
+ xObjStor->Commit();
+ }
+ }
+
+ if( bValidStorage )
+ {
+ uno::Reference < embed::XEmbeddedObject > xObj = aCnt.GetEmbeddedObject( aDstStgName );
+ if( xObj.is() )
+ {
+ // remember file name to use in the title bar
+ INetURLObject aURL( rBaseURL );
+ xObj->setContainerName( aURL.GetLastName( INetURLObject::DecodeMechanism::WithCharset ) );
+
+ // the visual area must be retrieved from the metafile (object doesn't know it so far)
+
+ if ( nAspect != embed::Aspects::MSOLE_ICON )
+ {
+ // working with visual area can switch the object to running state
+ try
+ {
+ awt::Size aAwtSz;
+ // the provided visual area should be used, if there is any
+ if ( rVisArea.IsEmpty() )
+ {
+ MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
+ Size aSz(lcl_GetPrefSize(rGrf, MapMode(aMapUnit)));
+ aAwtSz.Width = aSz.Width();
+ aAwtSz.Height = aSz.Height();
+ }
+ else
+ {
+ aAwtSz.Width = rVisArea.GetWidth();
+ aAwtSz.Height = rVisArea.GetHeight();
+ }
+ //xInplaceObj->EnableSetModified( sal_False );
+ xObj->setVisualAreaSize( nAspect, aAwtSz );
+ //xInplaceObj->EnableSetModified( sal_True );
+ }
+ catch( const uno::Exception& )
+ {
+ OSL_FAIL( "Could not set visual area of the object!" );
+ }
+ }
+
+ svt::EmbeddedObjectRef aObj( xObj, nAspect );
+
+ // TODO/LATER: need MediaType
+ aObj.SetGraphic( rGrf, OUString() );
+
+ pRet = new SdrOle2Obj(
+ rSdrModel,
+ aObj,
+ aDstStgName,
+ rBoundRect);
+ }
+ }
+ }
+
+ return pRet;
+}
+
+bool SvxMSDffManager::SetPropValue( const uno::Any& rAny, const uno::Reference< css::beans::XPropertySet > & rXPropSet,
+ const OUString& rPropName )
+{
+ bool bRetValue = false;
+ try
+ {
+ uno::Reference< beans::XPropertySetInfo >
+ aXPropSetInfo( rXPropSet->getPropertySetInfo() );
+ if ( aXPropSetInfo.is() )
+ bRetValue = aXPropSetInfo->hasPropertyByName( rPropName );
+ }
+ catch( const uno::Exception& )
+ {
+ bRetValue = false;
+ }
+ if ( bRetValue )
+ {
+ try
+ {
+ rXPropSet->setPropertyValue( rPropName, rAny );
+ bRetValue = true;
+ }
+ catch( const uno::Exception& )
+ {
+ bRetValue = false;
+ }
+ }
+ return bRetValue;
+}
+
+SvxMSDffImportRec::SvxMSDffImportRec()
+ : pObj( nullptr ),
+ nClientAnchorLen( 0 ),
+ nClientDataLen( 0 ),
+ nXAlign( 0 ), // position n cm from left
+ nYAlign( 0 ), // position n cm below
+ nGroupShapeBooleanProperties(0), // 16 settings: LayoutInCell/AllowOverlap/BehindDocument...
+ nFlags( ShapeFlag::NONE ),
+ nDxTextLeft( 144 ),
+ nDyTextTop( 72 ),
+ nDxTextRight( 144 ),
+ nDyTextBottom( 72 ),
+ nDxWrapDistLeft( 0 ),
+ nDyWrapDistTop( 0 ),
+ nDxWrapDistRight( 0 ),
+ nDyWrapDistBottom(0 ),
+ nCropFromTop( 0 ),
+ nCropFromBottom( 0 ),
+ nCropFromLeft( 0 ),
+ nCropFromRight( 0 ),
+ nNextShapeId( 0 ),
+ nShapeId( 0 ),
+ eShapeType( mso_sptNil ),
+ relativeHorizontalWidth( -1 ),
+ isHorizontalRule( false )
+{
+ eLineStyle = mso_lineSimple; // GPF-Bug #66227#
+ eLineDashing = mso_lineSolid;
+ bDrawHell = false;
+ bHidden = false;
+
+ bReplaceByFly = false;
+ bVFlip = false;
+ bHFlip = false;
+ bAutoWidth = false;
+}
+
+SvxMSDffImportRec::SvxMSDffImportRec(const SvxMSDffImportRec& rCopy)
+ : pObj( rCopy.pObj ),
+ nXAlign( rCopy.nXAlign ),
+ nXRelTo( rCopy.nXRelTo ),
+ nYAlign( rCopy.nYAlign ),
+ nYRelTo( rCopy.nYRelTo ),
+ nGroupShapeBooleanProperties(rCopy.nGroupShapeBooleanProperties),
+ nFlags( rCopy.nFlags ),
+ nDxTextLeft( rCopy.nDxTextLeft ),
+ nDyTextTop( rCopy.nDyTextTop ),
+ nDxTextRight( rCopy.nDxTextRight ),
+ nDyTextBottom( rCopy.nDyTextBottom ),
+ nDxWrapDistLeft( rCopy.nDxWrapDistLeft ),
+ nDyWrapDistTop( rCopy.nDyWrapDistTop ),
+ nDxWrapDistRight( rCopy.nDxWrapDistRight ),
+ nDyWrapDistBottom(rCopy.nDyWrapDistBottom ),
+ nCropFromTop( rCopy.nCropFromTop ),
+ nCropFromBottom( rCopy.nCropFromBottom ),
+ nCropFromLeft( rCopy.nCropFromLeft ),
+ nCropFromRight( rCopy.nCropFromRight ),
+ aTextId( rCopy.aTextId ),
+ nNextShapeId( rCopy.nNextShapeId ),
+ nShapeId( rCopy.nShapeId ),
+ eShapeType( rCopy.eShapeType ),
+ relativeHorizontalWidth( rCopy.relativeHorizontalWidth ),
+ isHorizontalRule( rCopy.isHorizontalRule )
+{
+ eLineStyle = rCopy.eLineStyle; // GPF-Bug #66227#
+ eLineDashing = rCopy.eLineDashing;
+ bDrawHell = rCopy.bDrawHell;
+ bHidden = rCopy.bHidden;
+ bReplaceByFly = rCopy.bReplaceByFly;
+ bAutoWidth = rCopy.bAutoWidth;
+ bVFlip = rCopy.bVFlip;
+ bHFlip = rCopy.bHFlip;
+ nClientAnchorLen = rCopy.nClientAnchorLen;
+ if( rCopy.nClientAnchorLen )
+ {
+ pClientAnchorBuffer.reset( new char[ nClientAnchorLen ] );
+ memcpy( pClientAnchorBuffer.get(),
+ rCopy.pClientAnchorBuffer.get(),
+ nClientAnchorLen );
+ }
+ else
+ pClientAnchorBuffer = nullptr;
+
+ nClientDataLen = rCopy.nClientDataLen;
+ if( rCopy.nClientDataLen )
+ {
+ pClientDataBuffer.reset( new char[ nClientDataLen ] );
+ memcpy( pClientDataBuffer.get(),
+ rCopy.pClientDataBuffer.get(),
+ nClientDataLen );
+ }
+ else
+ pClientDataBuffer = nullptr;
+
+ if (rCopy.pWrapPolygon)
+ pWrapPolygon = rCopy.pWrapPolygon;
+}
+
+SvxMSDffImportRec::~SvxMSDffImportRec()
+{
+}
+
+void SvxMSDffManager::insertShapeId( sal_Int32 nShapeId, SdrObject* pShape )
+{
+ maShapeIdContainer[nShapeId] = pShape;
+}
+
+void SvxMSDffManager::removeShapeId( SdrObject const * pShape )
+{
+ SvxMSDffShapeIdContainer::iterator aIter = std::find_if(maShapeIdContainer.begin(), maShapeIdContainer.end(),
+ [&pShape](const SvxMSDffShapeIdContainer::value_type& rEntry) { return rEntry.second == pShape; });
+ if (aIter != maShapeIdContainer.end())
+ maShapeIdContainer.erase( aIter );
+}
+
+SdrObject* SvxMSDffManager::getShapeForId( sal_Int32 nShapeId )
+{
+ SvxMSDffShapeIdContainer::iterator aIter( maShapeIdContainer.find(nShapeId) );
+ return aIter != maShapeIdContainer.end() ? (*aIter).second : nullptr;
+}
+
+SvxMSDffImportData::SvxMSDffImportData(const tools::Rectangle& rParentRect)
+ : aParentRect(rParentRect)
+{
+}
+
+SvxMSDffImportData::~SvxMSDffImportData()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/msfilter.component b/filter/source/msfilter/msfilter.component
new file mode 100644
index 000000000..0e1a35ee4
--- /dev/null
+++ b/filter/source/msfilter/msfilter.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.vba.VBAMacroResolver"
+ constructor="filter_VBAMacroResolver_get_implementation">
+ <service name="com.sun.star.script.vba.VBAMacroResolver"/>
+ </implementation>
+</component>
diff --git a/filter/source/msfilter/msocximex.cxx b/filter/source/msfilter/msocximex.cxx
new file mode 100644
index 000000000..e3ccf6524
--- /dev/null
+++ b/filter/source/msfilter/msocximex.cxx
@@ -0,0 +1,146 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/form/XFormsSupplier.hpp>
+#include <com/sun/star/form/XForm.hpp>
+#include <osl/diagnose.h>
+#include <filter/msfilter/msocximex.hxx>
+#include <utility>
+
+using namespace ::com::sun::star;
+
+constexpr OUStringLiteral sWW8_form( u"WW-Standard" );
+
+SvxMSConvertOCXControls::SvxMSConvertOCXControls( uno::Reference< frame::XModel > xModel) : mxModel(std::move(xModel))
+{
+}
+
+SvxMSConvertOCXControls::~SvxMSConvertOCXControls()
+{
+}
+
+void SvxMSConvertOCXControls::GetDrawPage()
+{
+ if( !xDrawPage.is() && mxModel.is() )
+ {
+ uno::Reference< drawing::XDrawPageSupplier > xTxtDoc(mxModel,
+ uno::UNO_QUERY);
+ OSL_ENSURE(xTxtDoc.is(),"no XDrawPageSupplier from XModel");
+ xDrawPage = xTxtDoc->getDrawPage();
+ OSL_ENSURE( xDrawPage.is(), "no XDrawPage" );
+ }
+}
+
+
+const uno::Reference< lang::XMultiServiceFactory >&
+ SvxMSConvertOCXControls::GetServiceFactory()
+{
+ if( !xServiceFactory.is() && mxModel.is() )
+ {
+ xServiceFactory = uno::Reference< lang::XMultiServiceFactory >
+ (mxModel, uno::UNO_QUERY);
+ OSL_ENSURE( xServiceFactory.is(),
+ "no XMultiServiceFactory from doc Model" );
+ }
+
+ return xServiceFactory;
+}
+
+const uno::Reference< drawing::XShapes >& SvxMSConvertOCXControls::GetShapes()
+{
+ if( !xShapes.is() )
+ {
+ GetDrawPage();
+ if( xDrawPage.is() )
+ {
+ xShapes = xDrawPage;
+ }
+ }
+ return xShapes;
+}
+
+const uno::Reference< container::XIndexContainer >&
+ SvxMSConvertOCXControls::GetFormComps()
+{
+ if( !xFormComps.is() )
+ {
+ GetDrawPage();
+ if( xDrawPage.is() )
+ {
+ uno::Reference< form::XFormsSupplier > xFormsSupplier( xDrawPage,
+ uno::UNO_QUERY );
+ OSL_ENSURE( xFormsSupplier.is(),
+ "UNO_QUERY failed for XFormsSupplier from XDrawPage" );
+
+ uno::Reference< container::XNameContainer > xNameCont =
+ xFormsSupplier->getForms();
+
+ // The form gets a new name like "WW-Standard[n]" and will
+ // created new in any case.
+ OUString sName( sWW8_form );
+ sal_uInt16 n = 0;
+
+ while( xNameCont->hasByName( sName ) )
+ {
+ sName = sWW8_form + OUString::number( ++n );
+ }
+
+ const uno::Reference< lang::XMultiServiceFactory > &rServiceFactory
+ = GetServiceFactory();
+ if( !rServiceFactory.is() )
+ return xFormComps;
+
+ uno::Reference< uno::XInterface > xCreate =
+ rServiceFactory->createInstance(
+ "com.sun.star.form.component.Form" );
+ if( xCreate.is() )
+ {
+ uno::Reference< beans::XPropertySet > xFormPropSet( xCreate,
+ uno::UNO_QUERY );
+
+ uno::Any aTmp(&sName,cppu::UnoType<OUString>::get());
+ xFormPropSet->setPropertyValue( "Name", aTmp );
+
+ uno::Reference< form::XForm > xForm( xCreate, uno::UNO_QUERY );
+ OSL_ENSURE(xForm.is(), "no Form?");
+
+ uno::Reference< container::XIndexContainer > xForms( xNameCont,
+ uno::UNO_QUERY );
+ OSL_ENSURE( xForms.is(), "XForms not available" );
+
+ aTmp <<= xForm;
+ xForms->insertByIndex( xForms->getCount(), aTmp );
+
+ xFormComps = uno::Reference< container::XIndexContainer >
+ (xCreate, uno::UNO_QUERY);
+ }
+ }
+ }
+
+ return xFormComps;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/msoleexp.cxx b/filter/source/msfilter/msoleexp.cxx
new file mode 100644
index 000000000..9e68e5cb0
--- /dev/null
+++ b/filter/source/msfilter/msoleexp.cxx
@@ -0,0 +1,340 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/embed/XEmbedPersist.hpp>
+#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <comphelper/classids.hxx>
+#include <sfx2/docfilt.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <sot/formats.hxx>
+#include <sot/storage.hxx>
+#include <tools/diagnose_ex.h>
+#include <comphelper/fileformat.h>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <unotools/streamwrap.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <svtools/embedhlp.hxx>
+#include <filter/msfilter/msdffimp.hxx>
+
+#include <filter/msfilter/msoleexp.hxx>
+
+using namespace ::com::sun::star;
+
+static SvGlobalName GetEmbeddedVersion( const SvGlobalName& aAppName )
+{
+ if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) )
+ return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 );
+ else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) )
+ return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 );
+ else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) )
+ return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 );
+ else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
+ return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 );
+ else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
+ return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 );
+ else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
+ return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 );
+
+ return SvGlobalName();
+}
+
+static OUString GetStorageType( const SvGlobalName& aEmbName )
+{
+ if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
+ return "LibreOffice.MathDocument.1";
+ else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
+ return "LibreOffice.WriterDocument.1";
+ else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
+ return "LibreOffice.CalcDocument.1";
+ else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
+ return "LibreOffice.DrawDocument.1";
+ else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
+ return "LibreOffice.ImpressDocument.1";
+ else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
+ return "LibreOffice.ChartDocument.1";
+ return OUString();
+}
+
+static bool UseOldMSExport()
+{
+ uno::Reference< lang::XMultiServiceFactory > xProvider(
+ configuration::theDefaultProvider::get(
+ comphelper::getProcessComponentContext()));
+ try {
+ uno::Sequence< uno::Any > aArg{ uno::Any(
+ OUString( "/org.openoffice.Office.Common/InternalMSExport" )) };
+ uno::Reference< container::XNameAccess > xNameAccess(
+ xProvider->createInstanceWithArguments(
+ "com.sun.star.configuration.ConfigurationUpdateAccess",
+ aArg ),
+ uno::UNO_QUERY );
+ if ( xNameAccess.is() )
+ {
+ uno::Any aResult = xNameAccess->getByName( "UseOldExport" );
+
+ bool bResult;
+ if ( aResult >>= bResult )
+ return bResult;
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ OSL_FAIL( "Could not get access to configuration entry!" );
+ return false;
+}
+
+void SvxMSExportOLEObjects::ExportOLEObject( const css::uno::Reference < css::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg )
+{
+ svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT );
+ ExportOLEObject( aObj, rDestStg );
+}
+
+void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef const & rObj, SotStorage& rDestStg )
+{
+ SvGlobalName aOwnGlobalName;
+ SvGlobalName aObjName( rObj->getClassID() );
+ std::shared_ptr<const SfxFilter> pExpFilter;
+ {
+ static struct ObjExpType {
+ sal_uInt32 nFlag;
+ const char* pFilterNm;
+ // GlobalNameId
+ struct GlobalNameIds {
+ sal_uInt32 n1;
+ sal_uInt16 n2, n3;
+ sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
+ }
+ aGlNmIds[4];
+ } const aArr[] = {
+ { OLE_STARMATH_2_MATHTYPE, "MathType 3.x",
+ {{SO3_SM_CLASSID_60}, {SO3_SM_CLASSID_50},
+ {SO3_SM_CLASSID_40}, {SO3_SM_CLASSID_30 }}},
+ { OLE_STARWRITER_2_WINWORD, "MS Word 97",
+ {{SO3_SW_CLASSID_60}, {SO3_SW_CLASSID_50},
+ {SO3_SW_CLASSID_40}, {SO3_SW_CLASSID_30 }}},
+ { OLE_STARCALC_2_EXCEL, "MS Excel 97",
+ {{SO3_SC_CLASSID_60}, {SO3_SC_CLASSID_50},
+ {SO3_SC_CLASSID_40}, {SO3_SC_CLASSID_30 }}},
+ { OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97",
+ {{SO3_SIMPRESS_CLASSID_60}, {SO3_SIMPRESS_CLASSID_50},
+ {SO3_SIMPRESS_CLASSID_40}, {SO3_SIMPRESS_CLASSID_30 }}},
+ { 0, "",
+ {{SO3_SCH_CLASSID_60}, {SO3_SCH_CLASSID_50},
+ {SO3_SCH_CLASSID_40}, {SO3_SCH_CLASSID_30 }}},
+ { 0, "",
+ {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from
+ {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entries here.
+
+ { 0xffff,nullptr,
+ {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50},
+ {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}}}
+ };
+
+ for( const ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr )
+ {
+ for (const ObjExpType::GlobalNameIds& rId : pArr->aGlNmIds)
+ {
+ SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
+ rId.b8, rId.b9, rId.b10, rId.b11,
+ rId.b12, rId.b13, rId.b14, rId.b15 );
+ if( aObjName == aGlbNm )
+ {
+ aOwnGlobalName = aGlbNm;
+
+ // flags for checking if conversion is wanted at all (SaveOptions?!)
+ if( nConvertFlags & pArr->nFlag )
+ {
+ pExpFilter = SfxFilterMatcher().GetFilter4FilterName(OUString::createFromAscii(pArr->pFilterNm));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if( pExpFilter ) // use this filter for the export
+ {
+ try
+ {
+ if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
+ rObj->changeState( embed::EmbedStates::RUNNING );
+ //TODO/LATER: is stream instead of outputstream a better choice?!
+ //TODO/LATER: a "StoreTo" method at embedded object would be nice
+ SvStream* pStream = new SvMemoryStream;
+ ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream );
+ uno::Sequence < beans::PropertyValue > aSeq{
+ comphelper::makePropertyValue("OutputStream", xOut),
+ comphelper::makePropertyValue("FilterName", pExpFilter->GetName())
+ };
+ uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
+ try
+ {
+ xStor->storeToURL( "private:stream", aSeq );
+ }
+ catch( const uno::Exception& ) {} // #TODO really handle exceptions - interactionalhandler etc. ?
+
+ tools::SvRef<SotStorage> xOLEStor = new SotStorage( pStream, true );
+ xOLEStor->CopyTo( &rDestStg );
+ rDestStg.Commit();
+ }
+ catch( const uno::Exception& )
+ {
+ // TODO/LATER: Error handling
+ OSL_FAIL( "The object could not be exported!" );
+ }
+ }
+ else if( aOwnGlobalName != SvGlobalName() )
+ {
+ // own format, maybe SO6 format or lower
+ SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName );
+ if ( aEmbName != SvGlobalName() && !UseOldMSExport() )
+ {
+ // this is a SO6 embedded object, save in old binary format
+ rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
+ rDestStg.SetClass( aEmbName,
+ SotClipboardFormatId::EMBEDDED_OBJ_OLE,
+ GetStorageType( aEmbName ) );
+ tools::SvRef<SotStorageStream> xExtStm = rDestStg.OpenSotStream(
+ "properties_stream");
+
+ bool bExtentSuccess = false;
+ if( !xExtStm->GetError() )
+ {
+ // write extent
+ //TODO/MBA: check if writing a size is enough
+ if( rObj.GetObject().is() )
+ {
+ // MSOLE objects don't need to be in running state for VisualArea access
+ awt::Size aSize;
+ try
+ {
+ // this is an own object, the content size must be stored in the
+ // extension stream
+ aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
+ }
+ catch( const embed::NoVisualAreaSizeException& )
+ {
+ OSL_FAIL( "Could not get visual area size!" );
+ aSize.Width = 5000;
+ aSize.Height = 5000;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION(
+ "filter.ms", "Unexpected exception while getting visual area size!");
+ aSize.Width = 5000;
+ aSize.Height = 5000;
+ }
+
+ sal_Int32 pRect[4];
+ pRect[0] = 0;
+ pRect[1] = aSize.Width;
+ pRect[2] = 0;
+ pRect[3] = aSize.Height;
+
+ sal_Int8 aWriteSet[16];
+ for ( int ind = 0; ind < 4; ind++ )
+ {
+ sal_Int32 nVal = pRect[ind];
+ for ( int nByte = 0; nByte < 4; nByte++ )
+ {
+ aWriteSet[ind*4+nByte] = static_cast<sal_Int8>(nVal) % 0x100;
+ nVal /= 0x100;
+ }
+ }
+
+ bExtentSuccess = (xExtStm->WriteBytes(aWriteSet, 16) == 16);
+ }
+ }
+
+ if ( bExtentSuccess )
+ {
+ tools::SvRef<SotStorageStream> xEmbStm = rDestStg.OpenSotStream(
+ "package_stream");
+ if( !xEmbStm->GetError() )
+ {
+ try
+ {
+ if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
+ rObj->changeState( embed::EmbedStates::RUNNING );
+ //TODO/LATER: is stream instead of outputstream a better choice?!
+ //TODO/LATER: a "StoreTo" method at embedded object would be nice
+ ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm );
+ uno::Sequence < beans::PropertyValue > aSeq{ comphelper::makePropertyValue(
+ "OutputStream", xOut) };
+ uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
+ xStor->storeToURL( "private:stream", aSeq );
+ }
+ catch( const uno::Exception& )
+ {
+ // TODO/LATER: Error handling
+ OSL_FAIL( "The object could not be exported!" );
+ }
+ }
+ }
+ }
+ else
+ {
+ OSL_FAIL("Own binary format inside own container document!");
+ }
+ }
+ else
+ {
+ // alien objects
+ //TODO/LATER: a "StoreTo" method at embedded object would be nice
+ rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
+ uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
+ uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY );
+ if ( xPers.is() )
+ {
+ uno::Sequence < beans::PropertyValue > aEmptySeq;
+ OUString aTempName( "bla" );
+ try
+ {
+ xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq );
+ }
+ catch ( const uno::Exception& )
+ {}
+
+ tools::SvRef<SotStorage> xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, StreamMode::STD_READ );
+ xOLEStor->CopyTo( &rDestStg );
+ rDestStg.Commit();
+ }
+ }
+
+ //We never need this stream: See #99809# and #i2179#
+ rDestStg.Remove( SVEXT_PERSIST_STREAM );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/mstoolbar.cxx b/filter/source/msfilter/mstoolbar.cxx
new file mode 100644
index 000000000..aa781c471
--- /dev/null
+++ b/filter/source/msfilter/mstoolbar.cxx
@@ -0,0 +1,824 @@
+/* -*- 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 <sal/config.h>
+
+#include <comphelper/propertyvalue.hxx>
+#include <filter/msfilter/mstoolbar.hxx>
+#include <o3tl/safeint.hxx>
+#include <sal/log.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/ui/XUIConfigurationManager.hpp>
+#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
+#include <com/sun/star/ui/XImageManager.hpp>
+#include <com/sun/star/ui/ImageType.hpp>
+#include <com/sun/star/ui/ItemType.hpp>
+#include <com/sun/star/ui/ItemStyle.hpp>
+#include <utility>
+#include <vcl/dibtools.hxx>
+#include <vcl/graph.hxx>
+#include <vcl/bitmapex.hxx>
+#include <sfx2/objsh.hxx>
+#include <filter/msfilter/msvbahelper.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+
+using namespace com::sun::star;
+
+int TBBase::nIndent = 0;
+
+void CustomToolBarImportHelper::ScaleImage( uno::Reference< graphic::XGraphic >& xGraphic, tools::Long nNewSize )
+{
+ Graphic aGraphic( xGraphic );
+ Size aSize = aGraphic.GetSizePixel();
+ if ( aSize.Height() && ( aSize.Height() == aSize.Width() ) )
+ {
+ Graphic aImage(xGraphic);
+ if ( aSize.Height() != nNewSize )
+ {
+ BitmapEx aBitmap = aImage.GetBitmapEx();
+ BitmapEx aBitmapex = BitmapEx::AutoScaleBitmap(aBitmap, nNewSize );
+ aImage = Graphic(aBitmapex);
+ xGraphic = aImage.GetXGraphic();
+ }
+ }
+}
+
+void CustomToolBarImportHelper::applyIcons()
+{
+ for (auto const& concommand : iconcommands)
+ {
+ uno::Sequence<OUString> commands { concommand.sCommand };
+ uno::Sequence< uno::Reference< graphic::XGraphic > > images { concommand.image };
+ auto pimages = images.getArray();
+
+ uno::Reference< ui::XImageManager > xImageManager( getCfgManager()->getImageManager(), uno::UNO_QUERY_THROW );
+ sal_uInt16 nColor = ui::ImageType::COLOR_NORMAL;
+
+ vcl::Window* topwin = Application::GetActiveTopWindow();
+ if ( topwin != nullptr && topwin->GetBackgroundColor().IsDark() )
+ nColor = css::ui::ImageType::COLOR_HIGHCONTRAST;
+
+ ScaleImage( pimages[ 0 ], 16 );
+ xImageManager->replaceImages( ui::ImageType::SIZE_DEFAULT | nColor, commands, images );
+ ScaleImage( pimages[ 0 ], 26 );
+ xImageManager->replaceImages( ui::ImageType::SIZE_LARGE | nColor, commands, images );
+ }
+}
+
+void CustomToolBarImportHelper::addIcon( const uno::Reference< graphic::XGraphic >& xImage, const OUString& sString )
+{
+ iconcontrolitem item;
+ item.sCommand = sString;
+ item.image = xImage;
+ iconcommands.push_back( item );
+}
+
+CustomToolBarImportHelper::CustomToolBarImportHelper( SfxObjectShell& rDocShell, const css::uno::Reference< css::ui::XUIConfigurationManager>& rxAppCfgMgr ) : mrDocSh( rDocShell )
+{
+ m_xCfgSupp.set( mrDocSh.GetModel(), uno::UNO_QUERY_THROW );
+ m_xAppCfgMgr.set( rxAppCfgMgr, uno::UNO_SET_THROW );
+}
+
+uno::Reference< ui::XUIConfigurationManager >
+CustomToolBarImportHelper::getCfgManager()
+{
+ return m_xCfgSupp->getUIConfigurationManager();
+}
+
+
+uno::Any
+CustomToolBarImportHelper::createCommandFromMacro( std::u16string_view sCmd )
+{
+ //"vnd.sun.star.script:Standard.Module1.Main?language=Basic&location=document"
+ // create script url
+ OUString scriptURL
+ = OUString::Concat("vnd.sun.star.script:") + sCmd + "?language=Basic&location=document";
+ return uno::Any( scriptURL );
+}
+
+OUString CustomToolBarImportHelper::MSOCommandToOOCommand( sal_Int16 msoCmd )
+{
+ OUString result;
+ if (pMSOCmdConvertor)
+ result = pMSOCmdConvertor->MSOCommandToOOCommand( msoCmd );
+ return result;
+}
+
+OUString CustomToolBarImportHelper::MSOTCIDToOOCommand( sal_Int16 msoTCID )
+{
+ OUString result;
+ if (pMSOCmdConvertor)
+ result = pMSOCmdConvertor->MSOTCIDToOOCommand( msoTCID );
+ return result;
+}
+
+bool
+CustomToolBarImportHelper::createMenu( const OUString& rName, const uno::Reference< container::XIndexAccess >& xMenuDesc )
+{
+ bool bRes = true;
+ try
+ {
+ uno::Reference< ui::XUIConfigurationManager > xCfgManager( getCfgManager() );
+ OUString sMenuBar = "private:resource/menubar/" + rName;
+ uno::Reference< container::XIndexContainer > xPopup( xCfgManager->createSettings(), uno::UNO_SET_THROW );
+ uno::Reference< beans::XPropertySet > xProps( xPopup, uno::UNO_QUERY_THROW );
+ // set name for menubar
+ xProps->setPropertyValue("UIName", uno::Any( rName ) );
+ if ( xPopup.is() )
+ {
+ uno::Sequence< beans::PropertyValue > aPopupMenu{
+ comphelper::makePropertyValue("CommandURL", "vnd.openoffice.org:" + rName),
+ comphelper::makePropertyValue("Label", rName),
+ comphelper::makePropertyValue("ItemDescriptorContainer", xMenuDesc),
+ comphelper::makePropertyValue("Type", sal_Int32( 0 ))
+ };
+
+ xPopup->insertByIndex( xPopup->getCount(), uno::Any( aPopupMenu ) );
+ xCfgManager->insertSettings( sMenuBar, xPopup );
+ uno::Reference< ui::XUIConfigurationPersistence > xPersistence( xCfgManager, uno::UNO_QUERY_THROW );
+ xPersistence->store();
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ bRes = false;
+ }
+ return bRes;
+}
+
+#ifdef DEBUG_FILTER_MSTOOLBAR
+void TBBase::indent_printf( FILE* fp, const char* format, ... )
+{
+ va_list ap;
+ va_start ( ap, format );
+
+ // indent nIndent spaces
+ for ( int i=0; i<nIndent; ++i)
+ fprintf(fp," ");
+ // append the rest of the message
+ vfprintf( fp, format, ap );
+ va_end( ap );
+}
+#endif
+
+TBCHeader::TBCHeader()
+ : bSignature(0x3)
+ , bVersion(0x01)
+ , bFlagsTCR(0)
+ , tct(0x1) // default to Button
+ , tcid(0)
+ , tbct(0)
+ , bPriority(0)
+{
+}
+
+TBCHeader::~TBCHeader()
+{
+}
+
+bool TBCHeader::Read( SvStream &rS )
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ rS.ReadSChar( bSignature ).ReadSChar( bVersion ).ReadUChar( bFlagsTCR ).ReadUChar( tct ).ReadUInt16( tcid ).ReadUInt32( tbct ).ReadUChar( bPriority );
+ // bit 4 ( from lsb )
+ if ( bFlagsTCR & 0x10 )
+ {
+ width = std::make_shared<sal_uInt16>();
+ height = std::make_shared<sal_uInt16>();
+ rS.ReadUInt16( *width ).ReadUInt16( *height );
+ }
+ return true;
+}
+
+#ifdef DEBUG_FILTER_MSTOOLBAR
+void TBCHeader::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] TBCHeader -- dump\n", nOffSet );
+ indent_printf(fp," bSignature 0x%x\n", bSignature );
+ indent_printf(fp," bVersion 0x%x\n", bVersion );
+ indent_printf(fp," bFlagsTCR 0x%x\n", bFlagsTCR );
+ indent_printf(fp," tct 0x%x\n", tct );
+ indent_printf(fp," tcid 0x%x\n", tcid );
+ indent_printf(fp," tbct 0x%x\n", static_cast< unsigned int >( tbct ));
+ indent_printf(fp," bPriority 0x%x\n", bPriority );
+ if ( width.get() )
+ indent_printf(fp," width %d(0x%x)\n", *width, *width);
+ if ( height.get() )
+ indent_printf(fp," height %d(0x%x)\n", *height, *height);
+}
+#endif
+
+TBCData::TBCData( TBCHeader Header ) : rHeader(std::move( Header ))
+{
+}
+
+bool TBCData::Read(SvStream &rS)
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ if ( !controlGeneralInfo.Read(rS) /*|| !controlSpecificInfo.Read(rS)*/ )
+ return false;
+ switch ( rHeader.getTct() )
+ {
+ case 0x01: // (Button control)
+ case 0x10: // (ExpandingGrid control)
+ controlSpecificInfo = std::make_shared<TBCBSpecific>();
+ break;
+ case 0x0A: // (Popup control)
+ case 0x0C: // (ButtonPopup control)
+ case 0x0D: // (SplitButtonPopup control)
+ case 0x0E: // (SplitButtonMRUPopup control)
+ controlSpecificInfo = std::make_shared<TBCMenuSpecific>();
+ break;
+ case 0x02: // (Edit control)
+ case 0x04: // (ComboBox control)
+ case 0x14: // (GraphicCombo control)
+ case 0x03: // (DropDown control)
+ case 0x06: // (SplitDropDown control)
+ case 0x09: // (GraphicDropDown control)
+ controlSpecificInfo = std::make_shared<TBCComboDropdownSpecific>( rHeader );
+ break;
+ default:
+ break;
+ }
+ if ( controlSpecificInfo )
+ return controlSpecificInfo->Read( rS );
+ //#FIXME I need to be able to handle different controlSpecificInfo types.
+ return true;
+}
+
+TBCMenuSpecific* TBCData::getMenuSpecific()
+{
+ TBCMenuSpecific* pMenu = dynamic_cast< TBCMenuSpecific* >( controlSpecificInfo.get() );
+ return pMenu;
+}
+void TBCData::ImportToolBarControl( CustomToolBarImportHelper& helper, std::vector< css::beans::PropertyValue >& props, bool& bBeginGroup, bool bIsMenuBar )
+{
+ sal_uInt16 nStyle = 0;
+ bBeginGroup = rHeader.isBeginGroup();
+ controlGeneralInfo.ImportToolBarControlData( helper, props );
+ beans::PropertyValue aProp;
+ aProp.Name = "Visible";
+ aProp.Value <<= rHeader.isVisible(); // where is the visible attribute stored
+ props.push_back( aProp );
+ if ( rHeader.getTct() == 0x01
+ || rHeader.getTct() == 0x10 )
+ {
+ TBCBSpecific* pSpecificInfo = dynamic_cast< TBCBSpecific* >( controlSpecificInfo.get() );
+ if ( pSpecificInfo )
+ {
+ // if we have an icon then lets set it for the command
+ OUString sCommand;
+ for (auto const& property : props)
+ {
+ // TODO JNA : couldn't we break if we find CommandURL to avoid keeping on the loop?
+ if ( property.Name == "CommandURL" )
+ property.Value >>= sCommand;
+ }
+ if ( TBCBitMap* pIcon = pSpecificInfo->getIcon() )
+ {
+ // Without a command openoffice won't display the icon
+ if ( !sCommand.isEmpty() )
+ {
+ BitmapEx aBitEx( pIcon->getBitMap() );
+ TBCBitMap* pIconMask = pSpecificInfo->getIconMask();
+ if (pIconMask)
+ {
+ const Bitmap& rMaskBase(pIconMask->getBitMap().GetBitmap());
+ Size aMaskSize = rMaskBase.GetSizePixel();
+ if (aMaskSize.Width() && aMaskSize.Height())
+ {
+ // according to the spec:
+ // "the iconMask is white in all the areas in which the icon is
+ // displayed as transparent and is black in all other areas."
+ aBitEx = BitmapEx(aBitEx.GetBitmap(), rMaskBase.CreateMask(COL_WHITE));
+ }
+ }
+
+ Graphic aGraphic( aBitEx );
+ helper.addIcon( aGraphic.GetXGraphic(), sCommand );
+ }
+ }
+ else if ( pSpecificInfo->getBtnFace() )
+ {
+
+ OUString sBuiltInCmd = helper.MSOTCIDToOOCommand( *pSpecificInfo->getBtnFace() );
+ if ( !sBuiltInCmd.isEmpty() )
+ {
+ uno::Sequence<OUString> sCmds { sBuiltInCmd };
+ uno::Reference< ui::XImageManager > xImageManager( helper.getAppCfgManager()->getImageManager(), uno::UNO_QUERY_THROW );
+ // 0 = default image size
+ uno::Sequence< uno::Reference< graphic::XGraphic > > sImages = xImageManager->getImages( 0, sCmds );
+ if ( sImages.hasElements() && sImages[0].is() )
+ helper.addIcon( sImages[0], sCommand );
+ }
+ }
+ }
+ }
+ else if ( rHeader.getTct() == 0x0a )
+ {
+ aProp.Name = "CommandURL";
+
+ TBCMenuSpecific* pMenu = getMenuSpecific();
+ if ( pMenu )
+ {
+ OUString sMenuBar = "private:resource/menubar/" + pMenu->Name();
+ aProp.Value <<= sMenuBar; // name of popup
+ }
+ nStyle |= ui::ItemStyle::DROP_DOWN;
+ props.push_back( aProp );
+ }
+
+ short icontext = ( rHeader.getTbct() & 0x03 );
+ aProp.Name = "Style";
+ if ( bIsMenuBar )
+ {
+ nStyle |= ui::ItemStyle::TEXT;
+ if ( !icontext || icontext == 0x3 )
+ // Text And image
+ nStyle |= ui::ItemStyle::ICON;
+ }
+ else
+ {
+ if ( ( icontext & 0x02 ) == 0x02 )
+ nStyle |= ui::ItemStyle::TEXT;
+ if ( !icontext || ( icontext & 0x03 ) == 0x03 )
+ nStyle |= ui::ItemStyle::ICON;
+ }
+ aProp.Value <<= nStyle;
+ props.push_back( aProp );
+}
+
+#ifdef DEBUG_FILTER_MSTOOLBAR
+void TBCData::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] TBCData -- dump\n", nOffSet );
+ indent_printf(fp," dumping controlGeneralInfo( TBCGeneralInfo )\n");
+ controlGeneralInfo.Print( fp );
+ //if ( rHeader.getTct() == 1 )
+ if ( controlSpecificInfo.get() )
+ {
+ indent_printf(fp," dumping controlSpecificInfo( TBCBSpecificInfo )\n");
+ controlSpecificInfo->Print( fp );
+ }
+}
+#endif
+
+bool
+WString::Read( SvStream &rS )
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ sal_uInt8 nChars = 0;
+ rS.ReadUChar( nChars );
+ sString = read_uInt16s_ToOUString(rS, nChars);
+ return true;
+}
+
+TBCExtraInfo::TBCExtraInfo()
+ : idHelpContext(0)
+ , tbcu(0)
+ , tbmg(0)
+{
+}
+
+bool
+TBCExtraInfo::Read( SvStream &rS )
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ if( !wstrHelpFile.Read( rS ) )
+ return false;
+
+ rS.ReadInt32( idHelpContext );
+
+ if ( !wstrTag.Read( rS ) || !wstrOnAction.Read( rS ) || !wstrParam.Read( rS ) )
+ return false;
+
+ rS.ReadSChar( tbcu ).ReadSChar( tbmg );
+ return true;
+}
+
+#ifdef DEBUG_FILTER_MSTOOLBAR
+void
+TBCExtraInfo::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] TBCExtraInfo -- dump\n", nOffSet );
+ indent_printf( fp, " wstrHelpFile %s\n",
+ OUStringToOString( wstrHelpFile.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ indent_printf( fp, " idHelpContext 0x%x\n", static_cast< unsigned int >( idHelpContext ) );
+ indent_printf( fp, " wstrTag %s\n",
+ OUStringToOString( wstrTag.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ indent_printf( fp, " wstrOnAction %s\n",
+ OUStringToOString( wstrOnAction.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ indent_printf( fp, " wstrParam %s\n",
+ OUStringToOString( wstrParam.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ indent_printf( fp, " tbcu 0x%x\n", tbcu );
+ indent_printf( fp, " tbmg 0x%x\n", tbmg );
+}
+#endif
+
+OUString const &
+TBCExtraInfo::getOnAction() const
+{
+ return wstrOnAction.getString();
+}
+
+TBCGeneralInfo::TBCGeneralInfo() : bFlags( 0 )
+{
+}
+
+bool TBCGeneralInfo::Read( SvStream &rS )
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ rS.ReadUChar( bFlags );
+
+ if ( ( bFlags & 0x1 ) && !customText.Read( rS ) )
+ return false;
+ if ( ( bFlags & 0x2 ) && ( !descriptionText.Read( rS ) || !tooltip.Read( rS ) ) )
+ return false;
+ if ( ( bFlags & 0x4 ) && !extraInfo.Read( rS ) )
+ return false;
+ return true;
+}
+
+#ifdef DEBUG_FILTER_MSFILTER
+void
+TBCGeneralInfo::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] TBCGeneralInfo -- dump\n", nOffSet );
+ indent_printf( fp, " bFlags 0x%x\n", bFlags );
+ indent_printf( fp, " customText %s\n",
+ OUStringToOString( customText.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ indent_printf( fp, " description %s\n",
+ OUStringToOString( descriptionText.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ indent_printf( fp, " tooltip %s\n",
+ OUStringToOString( tooltip.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ if ( bFlags & 0x4 )
+ extraInfo.Print( fp );
+}
+#endif
+
+void
+TBCGeneralInfo::ImportToolBarControlData( CustomToolBarImportHelper& helper, std::vector< beans::PropertyValue >& sControlData )
+{
+ if ( !(bFlags & 0x5) )
+ return;
+
+ beans::PropertyValue aProp;
+ // probably access to the header would be a better test than seeing if there is an action, e.g.
+ // if ( rHeader.getTct() == 0x01 && rHeader.getTcID() == 0x01 ) // not defined, probably this is a command
+ if ( !extraInfo.getOnAction().isEmpty() )
+ {
+ aProp.Name = "CommandURL";
+ ooo::vba::MacroResolvedInfo aMacroInf = ooo::vba::resolveVBAMacro( &helper.GetDocShell(), extraInfo.getOnAction(), true );
+ if ( aMacroInf.mbFound )
+ aProp.Value = CustomToolBarImportHelper::createCommandFromMacro( aMacroInf.msResolvedMacro );
+ else
+ aProp.Value <<= "UnResolvedMacro[" + extraInfo.getOnAction() + "]";
+ sControlData.push_back( aProp );
+ }
+
+ aProp.Name = "Label";
+ aProp.Value <<= customText.getString().replace('&','~');
+ sControlData.push_back( aProp );
+
+ aProp.Name = "Type";
+ aProp.Value <<= ui::ItemType::DEFAULT;
+ sControlData.push_back( aProp );
+
+ aProp.Name = "Tooltip";
+ aProp.Value <<= tooltip.getString();
+ sControlData.push_back( aProp );
+/*
+aToolbarItem(0).Name = "CommandURL" wstrOnAction
+aToolbarItem(0).Value = Command
+aToolbarItem(1).Name = "Label" customText
+aToolbarItem(1).Value = Label
+aToolbarItem(2).Name = "Type"
+aToolbarItem(2).Value = 0
+aToolbarItem(3).Name = "Visible"
+aToolbarItem(3).Value = true
+*/
+}
+
+TBCMenuSpecific::TBCMenuSpecific() : tbid( 0 )
+{
+}
+
+bool
+TBCMenuSpecific::Read( SvStream &rS)
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ rS.ReadInt32( tbid );
+ if ( tbid == 1 )
+ {
+ name = std::make_shared<WString>();
+ return name->Read( rS );
+ }
+ return true;
+}
+
+#ifdef DEBUG_FILTER_MSFILTER
+void
+TBCMenuSpecific::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] TBCMenuSpecific -- dump\n", nOffSet );
+ indent_printf( fp, " tbid 0x%x\n", static_cast< unsigned int >( tbid ) );
+ if ( tbid == 1 )
+ indent_printf( fp, " name %s\n", OUStringToOString( name->getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+}
+#endif
+
+OUString TBCMenuSpecific::Name()
+{
+ OUString aName;
+ if ( name )
+ aName = name->getString();
+ return aName;
+}
+TBCBSpecific::TBCBSpecific() : bFlags( 0 )
+{
+}
+
+bool TBCBSpecific::Read( SvStream &rS)
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ rS.ReadUChar( bFlags );
+
+ // bFlags determines what we read next
+
+ // bFlags.fCustomBitmap = 1 ( 0x8 ) set
+ if ( bFlags & 0x8 )
+ {
+ icon = std::make_shared<TBCBitMap>();
+ iconMask = std::make_shared<TBCBitMap>();
+ if ( !icon->Read( rS ) || !iconMask->Read( rS ) )
+ return false;
+ }
+ // if bFlags.fCustomBtnFace = 1 ( 0x10 )
+ if ( bFlags & 0x10 )
+ {
+ iBtnFace = std::make_shared<sal_uInt16>();
+ rS.ReadUInt16( *iBtnFace );
+ }
+ // if bFlags.fAccelerator equals 1 ( 0x04 )
+ if ( bFlags & 0x04 )
+ {
+ wstrAcc = std::make_shared<WString>();
+ return wstrAcc->Read( rS );
+ }
+ return true;
+}
+
+
+#ifdef DEBUG_FILTER_MSFILTER
+void TBCBSpecific::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] TBCBSpecific -- dump\n", nOffSet );
+ indent_printf( fp, " bFlags 0x%x\n", bFlags );
+ bool bResult = ( icon.get() != NULL );
+ indent_printf( fp, " icon present? %s\n", bResult ? "true" : "false" );
+ if ( bResult )
+ {
+ Indent b;
+ indent_printf( fp, " icon: \n");
+ icon->Print( fp ); // will dump size
+ }
+ bResult = ( iconMask.get() != NULL );
+ indent_printf( fp, " icon mask present? %s\n", bResult ? "true" : "false" );
+ if ( bResult )
+ {
+ Indent c;
+ indent_printf( fp, " icon mask: \n");
+ iconMask->Print( fp ); // will dump size
+ }
+ if ( iBtnFace.get() )
+ {
+ indent_printf( fp, " iBtnFace 0x%x\n", *iBtnFace );
+ }
+ bResult = ( wstrAcc.get() != NULL );
+ indent_printf( fp, " option string present? %s ->%s<-\n", bResult ? "true" : "false", bResult ? OUStringToOString( wstrAcc->getString(), RTL_TEXTENCODING_UTF8 ).getStr() : "N/A" );
+}
+#endif
+
+TBCBitMap*
+TBCBSpecific::getIcon()
+{
+ return icon.get();
+}
+
+TBCBitMap*
+TBCBSpecific::getIconMask()
+{
+ return iconMask.get();
+}
+
+TBCComboDropdownSpecific::TBCComboDropdownSpecific(const TBCHeader& header )
+{
+ if ( header.getTcID() == 0x01 )
+ data = std::make_shared<TBCCDData>();
+}
+
+bool TBCComboDropdownSpecific::Read( SvStream &rS)
+{
+ nOffSet = rS.Tell();
+ if ( data )
+ return data->Read( rS );
+ return true;
+}
+
+#ifdef DEBUG_FILTER_MSFILTER
+void TBCComboDropdownSpecific::Print( FILE* fp)
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] TBCComboDropdownSpecific -- dump\n", nOffSet );
+ if ( data.get() )
+ data->Print( fp );
+ else
+ indent_printf(fp," no data " );
+}
+#endif
+
+TBCCDData::TBCCDData()
+ : cwstrItems(0)
+ , cwstrMRU(0)
+ , iSel(0)
+ , cLines(0)
+ , dxWidth(0)
+{
+}
+
+TBCCDData::~TBCCDData()
+{
+}
+
+bool TBCCDData::Read( SvStream &rS)
+{
+ nOffSet = rS.Tell();
+ rS.ReadInt16( cwstrItems );
+ if (cwstrItems > 0)
+ {
+ auto nItems = o3tl::make_unsigned(cwstrItems);
+ //each WString is at least one byte
+ if (rS.remainingSize() < nItems)
+ return false;
+ for (decltype(nItems) index = 0; index < nItems; ++index)
+ {
+ WString aString;
+ if ( !aString.Read( rS ) )
+ return false;
+ wstrList.push_back( aString );
+ }
+ }
+ rS.ReadInt16( cwstrMRU ).ReadInt16( iSel ).ReadInt16( cLines ).ReadInt16( dxWidth );
+
+ return wstrEdit.Read( rS );
+}
+
+#ifdef DEBUG_FILTER_MSFILTER
+void TBCCDData::Print( FILE* fp)
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] TBCCDData -- dump\n", nOffSet );
+ indent_printf(fp," cwstrItems items in wstrList %d\n", cwstrItems);
+ for ( sal_Int32 index=0; index < cwstrItems; ++index )
+ {
+ Indent b;
+ indent_printf(fp, " wstrList[%d] %s", static_cast< int >( index ), OUStringToOString( wstrList[index].getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+ indent_printf(fp," cwstrMRU num most recently used string %d item\n", cwstrMRU);
+ indent_printf(fp," iSel index of selected item %d item\n", iSel);
+ indent_printf(fp," cLines num of suggested lines to display %d", cLines);
+ indent_printf(fp," dxWidth width in pixels %d", dxWidth);
+ indent_printf(fp," wstrEdit %s", OUStringToOString( wstrEdit.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+}
+#endif
+
+TBCBitMap::TBCBitMap() : cbDIB( 0 )
+{
+}
+
+TBCBitMap::~TBCBitMap()
+{
+}
+
+bool TBCBitMap::Read( SvStream& rS)
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ rS.ReadInt32( cbDIB );
+ // cbDIB = sizeOf(biHeader) + sizeOf(colors) + sizeOf(bitmapData) + 10
+ return ReadDIBBitmapEx(mBitMap, rS, false, true);
+}
+
+#ifdef DEBUG_FILTER_MSTOOLBAR
+void TBCBitMap::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp, "[ 0x%x ] TBCBitMap -- dump\n", nOffSet );
+ indent_printf(fp, " TBCBitMap size of bitmap data 0x%x\n", static_cast< unsigned int > ( cbDIB ) );
+}
+#endif
+
+TB::TB() : bSignature(0x2),
+bVersion(0x1),
+cCL(0),
+ltbid( 0x1 ),
+ltbtr(0),
+cRowsDefault( 0 ),
+bFlags( 0 )
+{
+}
+
+bool TB::Read(SvStream &rS)
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ rS.ReadUChar( bSignature ).ReadUChar( bVersion ).ReadInt16( cCL ).ReadInt32( ltbid ).ReadUInt32( ltbtr ).ReadUInt16( cRowsDefault ).ReadUInt16( bFlags );
+ name.Read( rS );
+ return true;
+
+}
+
+bool TB::IsEnabled() const
+{
+ return ( bFlags & 0x01 ) != 0x01;
+}
+
+#ifdef DEBUG_FILTER_MSTOOLBAR
+void TB::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] TB -- dump\n", nOffSet );
+ indent_printf(fp," bSignature 0x%x\n", bSignature );
+ indent_printf(fp," bVersion 0x%x\n", bVersion );
+ indent_printf(fp," cCL 0x%x\n", cCL );
+ indent_printf(fp," ltbid 0x%x\n", ltbid );
+ indent_printf(fp," ltbtr 0x%x\n", ltbtr );
+ indent_printf(fp," cRowsDefault 0x%x\n", cRowsDefault );
+ indent_printf(fp," bFlags 0x%x\n", bFlags );
+ indent_printf(fp, " name %s\n", OUStringToOString( name.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+}
+#endif
+
+TBVisualData::TBVisualData() : tbds(0), tbv(0), tbdsDock(0), iRow(0)
+{
+}
+
+bool TBVisualData::Read( SvStream& rS )
+{
+ SAL_INFO("filter.ms", "stream pos " << rS.Tell());
+ nOffSet = rS.Tell();
+ rS.ReadSChar( tbds ).ReadSChar( tbv ).ReadSChar( tbdsDock ).ReadSChar( iRow );
+ rcDock.Read( rS );
+ rcFloat.Read( rS );
+ return true;
+}
+
+#ifdef DEBUG_FILTER_MSTOOLBAR
+void SRECT::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, " left 0x%x\n", left);
+ indent_printf( fp, " top 0x%x\n", top);
+ indent_printf( fp, " right 0x%x\n", right);
+ indent_printf( fp, " bottom 0x%x\n", bottom);
+}
+#endif
+
+#ifdef DEBUG_FILTER_MSTOOLBAR
+void TBVisualData::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] TBVisualData -- dump\n", nOffSet );
+ indent_printf( fp, " tbds 0x%x\n", tbds);
+ indent_printf( fp, " tbv 0x%x\n", tbv);
+ indent_printf( fp, " tbdsDoc 0x%x\n", tbdsDock);
+ indent_printf( fp, " iRow 0x%x\n", iRow);
+ rcDock.Print( fp );
+ rcFloat.Print( fp );
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/msvbahelper.cxx b/filter/source/msfilter/msvbahelper.cxx
new file mode 100644
index 000000000..d55a636fc
--- /dev/null
+++ b/filter/source/msfilter/msvbahelper.cxx
@@ -0,0 +1,768 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <filter/msfilter/msvbahelper.hxx>
+#include <basic/sbstar.hxx>
+#include <basic/basmgr.hxx>
+#include <basic/sbmod.hxx>
+#include <basic/sbmeth.hxx>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/script/vba/XVBACompatibility.hpp>
+#include <com/sun/star/script/ModuleType.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <tools/urlobj.hxx>
+#include <osl/file.hxx>
+#include <sal/log.hxx>
+#include <unotools/pathoptions.hxx>
+#include <rtl/character.hxx>
+#include <sfx2/objsh.hxx>
+#include <o3tl/string_view.hxx>
+#include <svtools/acceleratorexecute.hxx>
+#include <com/sun/star/ui/XUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/ui/XUIConfigurationManager.hpp>
+#include <map>
+
+using namespace ::com::sun::star;
+
+namespace ooo::vba {
+
+constexpr OUStringLiteral sUrlPart0( u"vnd.sun.star.script:" );
+constexpr OUStringLiteral sUrlPart1( u"?language=Basic&location=document" );
+
+OUString makeMacroURL( std::u16string_view sMacroName )
+{
+ return sUrlPart0 + sMacroName + sUrlPart1;
+}
+
+OUString extractMacroName( const OUString& rMacroUrl )
+{
+ if( rMacroUrl.startsWith( sUrlPart0 ) && rMacroUrl.endsWith( sUrlPart1 ) )
+ {
+ return rMacroUrl.copy( sUrlPart0.getLength(),
+ rMacroUrl.getLength() - sUrlPart0.getLength() - sUrlPart1.getLength() );
+ }
+ return OUString();
+}
+
+static std::u16string_view trimMacroName( std::u16string_view rMacroName )
+{
+ // the name may contain whitespaces and may be enclosed in apostrophs
+ std::u16string_view aMacroName = o3tl::trim(rMacroName);
+ size_t nMacroLen = aMacroName.size();
+ if( (nMacroLen >= 2) && (aMacroName[ 0 ] == '\'') && (aMacroName[ nMacroLen - 1 ] == '\'') )
+ aMacroName = o3tl::trim(aMacroName.substr( 1, nMacroLen - 2 ));
+ return aMacroName;
+}
+
+#if HAVE_FEATURE_SCRIPTING
+
+static SfxObjectShell* findShellForUrl( const OUString& sMacroURLOrPath )
+{
+ SfxObjectShell* pFoundShell=nullptr;
+ SfxObjectShell* pShell = SfxObjectShell::GetFirst();
+ INetURLObject aObj;
+ aObj.SetURL( sMacroURLOrPath );
+ bool bIsURL = aObj.GetProtocol() != INetProtocol::NotValid;
+ OUString aURL;
+ if ( bIsURL )
+ aURL = sMacroURLOrPath;
+ else
+ {
+ osl::FileBase::getFileURLFromSystemPath( sMacroURLOrPath, aURL );
+ aObj.SetURL( aURL );
+ }
+ while ( pShell )
+ {
+
+ uno::Reference< frame::XModel > xModel = pShell->GetModel();
+ // are we searching for a template? if so we have to cater for the
+ // fact that in openoffice a document opened from a template is always
+ // a new document :/
+ if ( xModel.is() )
+ {
+ SAL_INFO(
+ "filter.ms",
+ "shell " << pShell << " has model with url " << xModel->getURL()
+ << " and we look for " << aURL);
+ OUString aName = xModel->getURL() ;
+ if (aName.isEmpty())
+ {
+ uno::Reference< frame::XFrame > xFrame( xModel->getCurrentController()->getFrame(), uno::UNO_SET_THROW );
+ uno::Reference< beans::XPropertySet > xProps( xFrame, uno::UNO_QUERY_THROW );
+ xProps->getPropertyValue("Title") >>= aName;
+ aName = o3tl::trim(o3tl::getToken(aName, 0, '-'));
+ if( sMacroURLOrPath.lastIndexOf( aName ) >= 0 )
+ {
+ pFoundShell = pShell;
+ break;
+ }
+ }
+
+ if ( sMacroURLOrPath.endsWithIgnoreAsciiCase( ".dot" ) )
+ {
+ uno::Reference<document::XDocumentPropertiesSupplier> const
+ xDocPropSupp(xModel, uno::UNO_QUERY);
+ if (xDocPropSupp.is())
+ {
+ uno::Reference< document::XDocumentProperties > const
+ xDocProps(xDocPropSupp->getDocumentProperties(),
+ uno::UNO_SET_THROW);
+ OUString sCurrName = xDocProps->getTemplateName();
+ if( sMacroURLOrPath.lastIndexOf( sCurrName ) >= 0 )
+ {
+ pFoundShell = pShell;
+ break;
+ }
+ }
+ }
+ else
+ {
+ // sometimes just the name of the document ( without the path
+ // is used
+ bool bDocNameNoPathMatch = false;
+ if ( !aURL.isEmpty() && aURL.indexOf( '/' ) == -1 )
+ {
+ sal_Int32 lastSlashIndex = xModel->getURL().lastIndexOf( '/' );
+ if ( lastSlashIndex > -1 )
+ {
+ bDocNameNoPathMatch = xModel->getURL().subView( lastSlashIndex + 1 ) == aURL;
+ if ( !bDocNameNoPathMatch )
+ {
+ OUString aTmpName = OUString::Concat("'") + xModel->getURL().subView( lastSlashIndex + 1 ) + "'";
+ bDocNameNoPathMatch = aTmpName == aURL;
+ }
+ }
+ }
+
+ if ( aURL == xModel->getURL() || bDocNameNoPathMatch )
+ {
+ pFoundShell = pShell;
+ break;
+ }
+ }
+ }
+ pShell = SfxObjectShell::GetNext( *pShell );
+ }
+ return pFoundShell;
+}
+
+// sMod can be empty ( but we really need the library to search in )
+// if sMod is empty and a macro is found then sMod is updated
+// if sMod is empty, only standard modules will be searched (no class, document, form modules)
+static bool hasMacro( SfxObjectShell const * pShell, const OUString& sLibrary, OUString& sMod, const OUString& sMacro )
+{
+#if !HAVE_FEATURE_SCRIPTING
+ (void) pShell;
+ (void) sLibrary;
+ (void) sMod;
+ (void) sMacro;
+#else
+ if ( !sLibrary.isEmpty() && !sMacro.isEmpty() )
+ {
+ BasicManager* pBasicMgr = pShell-> GetBasicManager();
+ if ( pBasicMgr )
+ {
+ StarBASIC* pBasic = pBasicMgr->GetLib( sLibrary );
+ if ( !pBasic )
+ {
+ sal_uInt16 nId = pBasicMgr->GetLibId( sLibrary );
+ pBasicMgr->LoadLib( nId );
+ pBasic = pBasicMgr->GetLib( sLibrary );
+ }
+ if ( pBasic )
+ {
+ if ( !sMod.isEmpty() ) // we wish to find the macro is a specific module
+ {
+ SbModule* pModule = pBasic->FindModule( sMod );
+ if ( pModule && pModule->FindMethod( sMacro, SbxClassType::Method ))
+ {
+ return true;
+ }
+ }
+ else
+ {
+ for (auto const& rModuleRef : pBasic->GetModules())
+ {
+ if (rModuleRef && rModuleRef->FindMethod(sMacro, SbxClassType::Method))
+ {
+ sMod = rModuleRef->GetName();
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+#endif
+ return false;
+}
+
+#endif
+
+#if HAVE_FEATURE_SCRIPTING
+
+OUString getDefaultProjectName( SfxObjectShell const * pShell )
+{
+ OUString aPrjName;
+ if( BasicManager* pBasicMgr = pShell ? pShell->GetBasicManager() : nullptr )
+ {
+ aPrjName = pBasicMgr->GetName();
+ if( aPrjName.isEmpty() )
+ aPrjName = "Standard";
+ }
+ return aPrjName;
+}
+
+static void parseMacro( const OUString& sMacro, OUString& sContainer, OUString& sModule, OUString& sProcedure )
+{
+ sal_Int32 nMacroDot = sMacro.lastIndexOf( '.' );
+
+ if ( nMacroDot != -1 )
+ {
+ sProcedure = sMacro.copy( nMacroDot + 1 );
+
+ sal_Int32 nContainerDot = sMacro.lastIndexOf( '.', nMacroDot - 1 );
+ if ( nContainerDot != -1 )
+ {
+ sModule = sMacro.copy( nContainerDot + 1, nMacroDot - nContainerDot - 1 );
+ sContainer = sMacro.copy( 0, nContainerDot );
+ }
+ else
+ sModule = sMacro.copy( 0, nMacroDot );
+ }
+ else
+ sProcedure = sMacro;
+}
+
+#endif
+
+OUString resolveVBAMacro( SfxObjectShell const * pShell, const OUString& rLibName, const OUString& rModuleName, const OUString& rMacroName )
+{
+#if !HAVE_FEATURE_SCRIPTING
+ (void) pShell;
+ (void) rLibName;
+ (void) rModuleName;
+ (void) rMacroName;
+#else
+ if( pShell )
+ {
+ OUString aLibName = rLibName.isEmpty() ? getDefaultProjectName( pShell ) : rLibName ;
+ OUString aModuleName = rModuleName;
+ if( hasMacro( pShell, aLibName, aModuleName, rMacroName ) )
+ return aLibName + "." + aModuleName + "." + rMacroName;
+ }
+#endif
+ return OUString();
+}
+
+MacroResolvedInfo resolveVBAMacro( SfxObjectShell* pShell, const OUString& MacroName, bool bSearchGlobalTemplates )
+{
+#if !HAVE_FEATURE_SCRIPTING
+ (void) pShell;
+ (void) MacroName;
+ (void) bSearchGlobalTemplates;
+
+ return MacroResolvedInfo();
+#else
+ if( !pShell )
+ return MacroResolvedInfo();
+
+ // the name may be enclosed in apostrophs
+ std::u16string_view aMacroName = trimMacroName( MacroName );
+
+ // parse the macro name
+ size_t nDocSepIndex = aMacroName.find( '!' );
+ if( nDocSepIndex > 0 && nDocSepIndex != std::u16string_view::npos )
+ {
+ // macro specified by document name
+ // find document shell for document name and call ourselves
+ // recursively
+
+ // assume for now that the document name is *this* document
+ std::u16string_view sDocUrlOrPath = aMacroName.substr( 0, nDocSepIndex );
+ aMacroName = aMacroName.substr( nDocSepIndex + 1 );
+ SAL_INFO("filter.ms", "doc search, current shell is " << pShell);
+ SfxObjectShell* pFoundShell = nullptr;
+ if( bSearchGlobalTemplates )
+ {
+ SvtPathOptions aPathOpt;
+ const OUString& aAddinPath = aPathOpt.GetAddinPath();
+ if( o3tl::starts_with(sDocUrlOrPath, aAddinPath) )
+ pFoundShell = pShell;
+ }
+ if( !pFoundShell )
+ pFoundShell = findShellForUrl( OUString(sDocUrlOrPath) );
+ SAL_INFO(
+ "filter.ms",
+ "doc search, after find, found shell is " << pFoundShell);
+ return resolveVBAMacro( pFoundShell, OUString(aMacroName) );
+ }
+
+ // macro is contained in 'this' document ( or code imported from a template
+ // where that template is a global template or perhaps the template this
+ // document is created from )
+
+ MacroResolvedInfo aRes( pShell );
+
+ // macro format = Container.Module.Procedure
+ OUString sContainer, sModule, sProcedure;
+ parseMacro( OUString(aMacroName), sContainer, sModule, sProcedure );
+
+#if 0
+ // As long as service VBAProjectNameProvider isn't supported in the model, disable the createInstance call
+ // (the ServiceNotRegisteredException is wrongly caught in ScModelObj::createInstance)
+ uno::Reference< container::XNameContainer > xPrjNameCache;
+ uno::Reference< lang::XMultiServiceFactory> xSF( pShell->GetModel(), uno::UNO_QUERY);
+ if ( xSF.is() ) try
+ {
+ xPrjNameCache.set( xSF->createInstance( "ooo.vba.VBAProjectNameProvider" ), uno::UNO_QUERY );
+ }
+ catch( const uno::Exception& ) // createInstance may throw
+ {
+ }
+#endif
+
+ std::vector< OUString > sSearchList;
+
+ if ( !sContainer.isEmpty() )
+ {
+// service VBAProjectNameProvider not implemented
+#if 0
+ // get the Project associated with the Container
+ if ( xPrjNameCache.is() )
+ {
+ if ( xPrjNameCache->hasByName( sContainer ) )
+ {
+ OUString sProject;
+ xPrjNameCache->getByName( sContainer ) >>= sProject;
+ sContainer = sProject;
+ }
+ }
+#endif
+ sSearchList.push_back( sContainer ); // First Lib to search
+ }
+ else
+ {
+ // Ok, if we have no Container specified then we need to search them in order, this document, template this document created from, global templates,
+ // get the name of Project/Library for 'this' document
+ OUString sThisProject( "Standard" );
+ try
+ {
+ uno::Reference< beans::XPropertySet > xProps( pShell->GetModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< script::vba::XVBACompatibility > xVBAMode( xProps->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY_THROW );
+ sThisProject = xVBAMode->getProjectName();
+ }
+ catch( const uno::Exception& /*e*/) {}
+
+ sSearchList.push_back( sThisProject ); // First Lib to search
+
+// service VBAProjectNameProvider not implemented
+#if 0
+ if ( xPrjNameCache.is() )
+ {
+ // is this document created from a template?
+ uno::Reference< document::XDocumentPropertiesSupplier > const
+ xDocPropSupp(pShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
+
+ OUString sCreatedFrom = xDocProps->getTemplateURL();
+ if ( !sCreatedFrom.isEmpty() )
+ {
+ INetURLObject aObj;
+ aObj.SetURL( sCreatedFrom );
+ bool bIsURL = aObj.GetProtocol() != INetProtocol::NotValid;
+ OUString aURL;
+ if ( bIsURL )
+ aURL = sCreatedFrom;
+ else
+ {
+ osl::FileBase::getFileURLFromSystemPath( sCreatedFrom, aURL );
+ aObj.SetURL( aURL );
+ }
+ sCreatedFrom = aObj.GetLastName();
+ }
+
+ sal_Int32 nIndex = sCreatedFrom.lastIndexOf( '.' );
+ if ( nIndex != -1 )
+ sCreatedFrom = sCreatedFrom.copy( 0, nIndex );
+
+ OUString sPrj;
+ if ( !sCreatedFrom.isEmpty() && xPrjNameCache->hasByName( sCreatedFrom ) )
+ {
+ xPrjNameCache->getByName( sCreatedFrom ) >>= sPrj;
+ // Make sure we don't double up with this project
+ if ( !sPrj.equals( sThisProject ) )
+ sSearchList.push_back( sPrj );
+ }
+
+ // get list of global template Names
+ uno::Sequence< OUString > sTemplateNames = xPrjNameCache->getElementNames();
+ sal_Int32 nLen = sTemplateNames.getLength();
+ for ( sal_Int32 index = 0; ( bSearchGlobalTemplates && index < nLen ); ++index )
+ {
+
+ if ( !sCreatedFrom.equals( sTemplateNames[ index ] ) )
+ {
+ if ( xPrjNameCache->hasByName( sTemplateNames[ index ] ) )
+ {
+ xPrjNameCache->getByName( sTemplateNames[ index ] ) >>= sPrj;
+ // Make sure we don't double up with this project
+ if ( !sPrj.equals( sThisProject ) )
+ sSearchList.push_back( sPrj );
+ }
+ }
+
+ }
+ }
+#endif
+ }
+
+ for (auto const& search : sSearchList)
+ {
+ aRes.mbFound = hasMacro( pShell, search, sModule, sProcedure );
+ if ( aRes.mbFound )
+ {
+ sContainer = search;
+ break;
+ }
+ }
+ //aRes.msResolvedMacro = sProcedure.Insert( '.', 0 ).Insert( sModule, 0).Insert( '.', 0 ).Insert( sContainer, 0 );
+ aRes.msResolvedMacro = sContainer + "." + sModule + "." + sProcedure;
+
+ return aRes;
+#endif
+}
+
+// Treat the args as possible inputs (conversion at bottom of method)
+bool executeMacro( SfxObjectShell* pShell, const OUString& sMacroName, uno::Sequence< uno::Any >& aArgs, uno::Any& aRet, const uno::Any& /*aCaller*/)
+{
+#if !HAVE_FEATURE_SCRIPTING
+ (void) pShell;
+ (void) sMacroName;
+ (void) aArgs;
+ (void) aRet;
+
+ return false;
+#else
+ bool bRes = false;
+ if ( !pShell )
+ return bRes;
+ OUString sUrl = makeMacroURL( sMacroName );
+
+ uno::Sequence< sal_Int16 > aOutArgsIndex;
+ uno::Sequence< uno::Any > aOutArgs;
+
+ try
+ {
+ ErrCode nErr = pShell->CallXScript(sUrl, aArgs, aRet, aOutArgsIndex, aOutArgs, false);
+ sal_Int32 nLen = aOutArgs.getLength();
+ // convert any out params to seem like they were inputs
+ if (nLen)
+ {
+ auto pArgs = aArgs.getArray();
+ for (sal_Int32 index = 0; index < nLen; ++index)
+ {
+ sal_Int32 nOutIndex = aOutArgsIndex[index];
+ pArgs[nOutIndex] = aOutArgs[index];
+ }
+ }
+ bRes = ( nErr == ERRCODE_NONE );
+ }
+ catch ( const uno::Exception& )
+ {
+ bRes = false;
+ }
+ return bRes;
+#endif
+}
+
+
+
+VBAMacroResolver::VBAMacroResolver() :
+ mpObjShell( nullptr )
+{
+}
+
+VBAMacroResolver::~VBAMacroResolver()
+{
+}
+
+// com.sun.star.lang.XServiceInfo interface -----------------------------------
+
+OUString SAL_CALL VBAMacroResolver::getImplementationName()
+{
+ return "com.sun.star.comp.vba.VBAMacroResolver";
+}
+
+sal_Bool SAL_CALL VBAMacroResolver::supportsService( const OUString& rService )
+{
+ return cppu::supportsService(this, rService);
+}
+
+uno::Sequence< OUString > SAL_CALL VBAMacroResolver::getSupportedServiceNames()
+{
+ return { "com.sun.star.script.vba.VBAMacroResolver" };
+}
+
+// com.sun.star.lang.XInitialization interface --------------------------------
+
+void SAL_CALL VBAMacroResolver::initialize( const uno::Sequence< uno::Any >& rArgs )
+{
+ OSL_ENSURE( rArgs.getLength() > 1, "VBAMacroResolver::initialize - missing arguments" );
+ if( rArgs.getLength() < 2 )
+ throw uno::RuntimeException();
+
+ // first argument: document model
+ mxModel.set( rArgs[ 0 ], uno::UNO_QUERY_THROW );
+ mpObjShell = comphelper::getFromUnoTunnel<SfxObjectShell>(mxModel);
+ if( !mpObjShell )
+ throw uno::RuntimeException();
+
+ // second argument: VBA project name
+ if( !(rArgs[ 1 ] >>= maProjectName) || (maProjectName.isEmpty()) )
+ throw uno::RuntimeException();
+}
+
+// com.sun.star.script.vba.XVBAMacroResolver interface ------------------------
+
+OUString SAL_CALL VBAMacroResolver::resolveVBAMacroToScriptURL( const OUString& rVBAMacroName )
+{
+ if( !mpObjShell )
+ throw uno::RuntimeException();
+
+ // the name may be enclosed in apostrophs
+ OUString aMacroName( trimMacroName( rVBAMacroName ) );
+ if( aMacroName.isEmpty() )
+ throw lang::IllegalArgumentException();
+
+ // external references not supported here (syntax is "url!macroname" or "[url]!macroname" or "[url]macroname")
+ if( (aMacroName[ 0 ] == '[') || (aMacroName.indexOf( '!' ) >= 0) )
+ throw lang::IllegalArgumentException();
+
+ // check if macro name starts with project name, replace with "Standard"
+ // TODO: adjust this when custom VBA project name is supported
+ sal_Int32 nDotPos = aMacroName.indexOf( '.' );
+ if( (nDotPos == 0) || (nDotPos + 1 == aMacroName.getLength()) )
+ throw lang::IllegalArgumentException();
+ if( (nDotPos > 0) && aMacroName.matchIgnoreAsciiCase( maProjectName ) )
+ aMacroName = aMacroName.copy( nDotPos + 1 );
+
+ // try to find the macro
+ MacroResolvedInfo aInfo = resolveVBAMacro( mpObjShell, aMacroName );
+ if( !aInfo.mbFound )
+ throw lang::IllegalArgumentException();
+
+ // build and return the script URL
+ return makeMacroURL( aInfo.msResolvedMacro );
+}
+
+OUString SAL_CALL VBAMacroResolver::resolveScriptURLtoVBAMacro( const OUString& /*rScriptURL*/ )
+{
+ OSL_ENSURE( false, "VBAMacroResolver::resolveScriptURLtoVBAMacro - not implemented" );
+ throw uno::RuntimeException();
+}
+
+static bool getModifier( sal_Unicode c, sal_uInt16& mod )
+{
+ if ( c == '+' ) {
+ mod |= KEY_SHIFT;
+ return true;
+ } else if ( c == '^' ) {
+ mod |= KEY_MOD1;
+ return true;
+ } else if ( c == '%' ) {
+ mod |= KEY_MOD2;
+ return true;
+ }
+ return false;
+}
+
+/// @throws uno::RuntimeException
+static sal_uInt16 parseChar( sal_Unicode c )
+{
+ sal_uInt16 nVclKey = 0;
+ // do we care about locale here for letters/digits? probably not
+ if ( rtl::isAsciiAlpha( c ) )
+ {
+ nVclKey |= ( rtl::toAsciiUpperCase( c ) - 'A' ) + KEY_A;
+ if ( rtl::isAsciiUpperCase( c ) )
+ nVclKey |= KEY_SHIFT;
+ }
+ else if ( rtl::isAsciiDigit( c ) )
+ nVclKey |= ( c - '0' ) + KEY_0;
+ else if ( c == '~' ) // special case
+ nVclKey = KEY_RETURN;
+ else if ( c == ' ' ) // special case
+ nVclKey = KEY_SPACE;
+ else // I guess we have a problem ( but not sure if locale specific keys might come into play here )
+ throw uno::RuntimeException();
+ return nVclKey;
+}
+
+namespace {
+
+struct KeyCodeEntry
+{
+ const char* sName;
+ sal_uInt16 nCode;
+};
+
+}
+
+KeyCodeEntry const aMSKeyCodesData[] = {
+ { "BACKSPACE", KEY_BACKSPACE },
+ { "BS", KEY_BACKSPACE },
+ { "DELETE", KEY_DELETE },
+ { "DEL", KEY_DELETE },
+ { "DOWN", KEY_DOWN },
+ { "UP", KEY_UP },
+ { "LEFT", KEY_LEFT },
+ { "RIGHT", KEY_RIGHT },
+ { "END", KEY_END },
+ { "ESCAPE", KEY_ESCAPE },
+ { "ESC", KEY_ESCAPE },
+ { "HELP", KEY_HELP },
+ { "HOME", KEY_HOME },
+ { "PGDN", KEY_PAGEDOWN },
+ { "PGUP", KEY_PAGEUP },
+ { "INSERT", KEY_INSERT },
+ { "SCROLLLOCK", KEY_SCROLLLOCK },
+ { "NUMLOCK", KEY_NUMLOCK },
+ { "TAB", KEY_TAB },
+ { "F1", KEY_F1 },
+ { "F2", KEY_F2 },
+ { "F3", KEY_F3 },
+ { "F4", KEY_F4 },
+ { "F5", KEY_F5 },
+ { "F6", KEY_F6 },
+ { "F7", KEY_F7 },
+ { "F8", KEY_F8 },
+ { "F9", KEY_F9 },
+ { "F10", KEY_F10 },
+ { "F11", KEY_F11 },
+ { "F12", KEY_F12 },
+ { "F13", KEY_F13 },
+ { "F14", KEY_F14 },
+ { "F15", KEY_F15 },
+};
+
+awt::KeyEvent parseKeyEvent( const OUString& Key )
+{
+ static std::map< OUString, sal_uInt16 > s_KeyCodes = []()
+ {
+ std::map< OUString, sal_uInt16 > tmp;
+ for (KeyCodeEntry const & i : aMSKeyCodesData)
+ {
+ tmp[ OUString::createFromAscii( i.sName ) ] = i.nCode;
+ }
+ return tmp;
+ }();
+ OUString sKeyCode;
+ sal_uInt16 nVclKey = 0;
+
+ // parse the modifier if any
+ for ( int i=0; i<Key.getLength(); ++i )
+ {
+ if ( ! getModifier( Key[ i ], nVclKey ) )
+ {
+ sKeyCode = Key.copy( i );
+ break;
+ }
+ }
+
+ // check if keycode is surrounded by '{}', if so scoop out the contents
+ // else it should be just one char of ( 'a-z,A-Z,0-9' )
+ if ( sKeyCode.getLength() == 1 ) // ( a single char )
+ {
+ nVclKey |= parseChar( sKeyCode[ 0 ] );
+ }
+ else // key should be enclosed in '{}'
+ {
+ if ( sKeyCode.getLength() < 3 || sKeyCode[0] != '{' || sKeyCode[sKeyCode.getLength() - 1 ] != '}' )
+ throw uno::RuntimeException();
+
+ sKeyCode = sKeyCode.copy(1, sKeyCode.getLength() - 2 );
+
+ if ( sKeyCode.getLength() == 1 )
+ nVclKey |= parseChar( sKeyCode[ 0 ] );
+ else
+ {
+ auto it = s_KeyCodes.find( sKeyCode );
+ if ( it == s_KeyCodes.end() ) // unknown or unsupported
+ throw uno::RuntimeException();
+ nVclKey |= it->second;
+ }
+ }
+
+ awt::KeyEvent aKeyEvent = svt::AcceleratorExecute::st_VCLKey2AWTKey( vcl::KeyCode( nVclKey ) );
+ return aKeyEvent;
+}
+
+void applyShortCutKeyBinding ( const uno::Reference< frame::XModel >& rxModel, const awt::KeyEvent& rKeyEvent, const OUString& rMacroName )
+{
+ OUString MacroName( rMacroName );
+ if ( !MacroName.isEmpty() )
+ {
+ OUString aMacroName = MacroName.trim();
+ if( aMacroName.startsWith("!") )
+ aMacroName = o3tl::trim(aMacroName.subView(1));
+ SfxObjectShell* pShell = nullptr;
+ if ( rxModel.is() )
+ {
+ pShell = comphelper::getFromUnoTunnel<SfxObjectShell>(rxModel);
+ if ( !pShell )
+ throw uno::RuntimeException();
+ }
+ MacroResolvedInfo aMacroInfo = resolveVBAMacro( pShell, aMacroName );
+ if( !aMacroInfo.mbFound )
+ throw uno::RuntimeException( "The procedure doesn't exist" );
+ MacroName = aMacroInfo.msResolvedMacro;
+ }
+ uno::Reference< ui::XUIConfigurationManagerSupplier > xCfgSupplier(rxModel, uno::UNO_QUERY_THROW);
+ uno::Reference< ui::XUIConfigurationManager > xCfgMgr = xCfgSupplier->getUIConfigurationManager();
+
+ uno::Reference< ui::XAcceleratorConfiguration > xAcc( xCfgMgr->getShortCutManager(), uno::UNO_SET_THROW );
+ if ( MacroName.isEmpty() )
+ // I believe this should really restore the [application] default. Since
+ // afaik we don't actually setup application default bindings on import
+ // we don't even know what the 'default' would be for this key
+ xAcc->removeKeyEvent( rKeyEvent );
+ else
+ xAcc->setKeyEvent( rKeyEvent, ooo::vba::makeMacroURL( MacroName ) );
+
+}
+
+
+} // namespace ooo
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_VBAMacroResolver_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new ooo::vba::VBAMacroResolver());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+
diff --git a/filter/source/msfilter/rtfutil.cxx b/filter/source/msfilter/rtfutil.cxx
new file mode 100644
index 000000000..e20a146c4
--- /dev/null
+++ b/filter/source/msfilter/rtfutil.cxx
@@ -0,0 +1,401 @@
+/* -*- 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 <filter/msfilter/rtfutil.hxx>
+#include <rtl/strbuf.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <svtools/rtfkeywd.hxx>
+#include <rtl/character.hxx>
+#include <tools/stream.hxx>
+#include <sot/storage.hxx>
+
+namespace
+{
+/**
+ * If rOle1 is native OLE1 data of size nOle1Size, wraps it in an OLE2 container.
+ *
+ * The OLE2 root's CLSID is set based on rClassName.
+ */
+void WrapOle1InOle2(SvStream& rOle1, sal_uInt32 nOle1Size, SvStream& rOle2,
+ const OString& rClassName)
+{
+ tools::SvRef<SotStorage> pStorage = new SotStorage(rOle2);
+ OString aAnsiUserType;
+ SvGlobalName aName;
+ if (rClassName == "PBrush")
+ {
+ aAnsiUserType = "Bitmap Image";
+ aName = SvGlobalName(0x0003000A, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 0x46);
+ }
+ else
+ {
+ if (!rClassName.isEmpty() && rClassName != "Package")
+ {
+ SAL_WARN("filter.ms", "WrapOle1InOle2: unexpected class name: '" << rClassName << "'");
+ }
+ aAnsiUserType = "OLE Package";
+ aName = SvGlobalName(0x0003000C, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 0x46);
+ }
+ pStorage->SetClass(aName, SotClipboardFormatId::NONE, "");
+
+ // [MS-OLEDS] 2.3.7 CompObjHeader
+ tools::SvRef<SotStorageStream> pCompObj = pStorage->OpenSotStream("\1CompObj");
+ // Reserved1
+ pCompObj->WriteUInt32(0xfffe0001);
+ // Version
+ pCompObj->WriteUInt32(0x00000a03);
+ // Reserved2
+ pCompObj->WriteUInt32(0xffffffff);
+ pCompObj->WriteUInt32(0x0003000c);
+ pCompObj->WriteUInt32(0x00000000);
+ pCompObj->WriteUInt32(0x000000c0);
+ pCompObj->WriteUInt32(0x46000000);
+ // Rest of CompObjStream
+ // AnsiUserType
+ pCompObj->WriteUInt32(aAnsiUserType.getLength() + 1);
+ pCompObj->WriteOString(aAnsiUserType);
+ pCompObj->WriteChar(0);
+ // AnsiClipboardFormat
+ pCompObj->WriteUInt32(0x00000000);
+ // Reserved1
+ pCompObj->WriteUInt32(rClassName.getLength() + 1);
+ pCompObj->WriteOString(rClassName);
+ pCompObj->WriteChar(0);
+ // UnicodeMarker
+ pCompObj->WriteUInt32(0x71B239F4);
+ // UnicodeUserType
+ pCompObj->WriteUInt32(0x00000000);
+ // UnicodeClipboardFormat
+ pCompObj->WriteUInt32(0x00000000);
+ // Reserved2
+ pCompObj->WriteUInt32(0x00000000);
+ pCompObj->Commit();
+ pCompObj.clear();
+
+ // [MS-OLEDS] 2.3.6 OLENativeStream
+ tools::SvRef<SotStorageStream> pOleNative = pStorage->OpenSotStream("\1Ole10Native");
+ // NativeDataSize
+ pOleNative->WriteUInt32(nOle1Size);
+ pOleNative->WriteStream(rOle1, nOle1Size);
+ pOleNative->Commit();
+ pOleNative.clear();
+
+ pStorage->Commit();
+ pStorage.clear();
+ rOle2.Seek(0);
+}
+}
+
+namespace msfilter::rtfutil
+{
+OString OutHex(sal_uLong nHex, sal_uInt8 nLen)
+{
+ char aNToABuf[] = "0000000000000000";
+
+ OSL_ENSURE(nLen < sizeof(aNToABuf), "nLen is too big");
+ if (nLen >= sizeof(aNToABuf))
+ nLen = (sizeof(aNToABuf) - 1);
+
+ // Set pointer to the buffer end
+ char* pStr = aNToABuf + (sizeof(aNToABuf) - 1);
+ for (sal_uInt8 n = 0; n < nLen; ++n)
+ {
+ *(--pStr) = static_cast<char>(nHex & 0xf) + 48;
+ if (*pStr > '9')
+ *pStr += 39;
+ nHex >>= 4;
+ }
+ return pStr;
+}
+
+// Ideally, this function should work on (sal_uInt32) Unicode scalar values
+// instead of (sal_Unicode) UTF-16 code units. However, at least "Rich Text
+// Format (RTF) Specification Version 1.9.1" available at
+// <https://www.microsoft.com/en-us/download/details.aspx?id=10725> does not
+// look like it allows non-BMP Unicode characters >= 0x10000 in the \uN notation
+// (it only talks about "Unicode character", but then explains how values of N
+// greater than 32767 will be expressed as negative signed 16-bit numbers, so
+// that smells like \uN is limited to BMP).
+// However the "Mathematics" section has an example that shows the code point
+// U+1D44E being encoded as UTF-16 surrogate pair "\u-10187?\u-9138?", so
+// sal_Unicode actually works fine here.
+OString OutChar(sal_Unicode c, int* pUCMode, rtl_TextEncoding eDestEnc, bool* pSuccess,
+ bool bUnicode)
+{
+ if (pSuccess)
+ *pSuccess = true;
+ OStringBuffer aBuf;
+ const char* pStr = nullptr;
+ // 0x0b instead of \n, etc because of the replacements in SwWW8AttrIter::GetSnippet()
+ switch (c)
+ {
+ case 0x0b:
+ // hard line break
+ pStr = OOO_STRING_SVTOOLS_RTF_LINE;
+ break;
+ case '\t':
+ pStr = OOO_STRING_SVTOOLS_RTF_TAB;
+ break;
+ case '\\':
+ case '}':
+ case '{':
+ aBuf.append('\\');
+ aBuf.append(static_cast<char>(c));
+ break;
+ case 0xa0:
+ // non-breaking space
+ pStr = "\\~";
+ break;
+ case 0x1e:
+ // non-breaking hyphen
+ pStr = "\\_";
+ break;
+ case 0x1f:
+ // optional hyphen
+ pStr = "\\-";
+ break;
+ default:
+ if (c >= ' ' && c <= '~')
+ aBuf.append(static_cast<char>(c));
+ else
+ {
+ OUString sBuf(&c, 1);
+ OString sConverted;
+ if (pSuccess)
+ *pSuccess &= sBuf.convertToString(&sConverted, eDestEnc,
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR
+ | RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR);
+ else
+ sBuf.convertToString(&sConverted, eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS);
+ const sal_Int32 nLen = sConverted.getLength();
+
+ if (pUCMode && bUnicode)
+ {
+ if (*pUCMode != nLen)
+ {
+ aBuf.append("\\uc");
+ aBuf.append(nLen);
+ // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.
+ aBuf.append(' ');
+ *pUCMode = nLen;
+ }
+ aBuf.append("\\u");
+ aBuf.append(static_cast<sal_Int32>(c));
+ }
+
+ for (sal_Int32 nI = 0; nI < nLen; ++nI)
+ {
+ aBuf.append("\\'");
+ aBuf.append(OutHex(sConverted[nI], 2));
+ }
+ }
+ }
+ if (pStr)
+ {
+ aBuf.append(pStr);
+ switch (c)
+ {
+ case 0xa0:
+ case 0x1e:
+ case 0x1f:
+ break;
+ default:
+ aBuf.append(' ');
+ }
+ }
+ return aBuf.makeStringAndClear();
+}
+
+OString OutString(const OUString& rStr, rtl_TextEncoding eDestEnc, bool bUnicode)
+{
+ SAL_INFO("filter.ms", __func__ << ", rStr = '" << rStr << "'");
+ OStringBuffer aBuf;
+ int nUCMode = 1;
+ for (sal_Int32 n = 0; n < rStr.getLength(); ++n)
+ aBuf.append(OutChar(rStr[n], &nUCMode, eDestEnc, nullptr, bUnicode));
+ if (nUCMode != 1)
+ {
+ aBuf.append(OOO_STRING_SVTOOLS_RTF_UC);
+ aBuf.append(sal_Int32(1));
+ aBuf.append(
+ " "); // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
+ }
+ return aBuf.makeStringAndClear();
+}
+
+/// Checks if lossless conversion of the string to eDestEnc is possible or not.
+static bool TryOutString(const OUString& rStr, rtl_TextEncoding eDestEnc)
+{
+ int nUCMode = 1;
+ for (sal_Int32 n = 0; n < rStr.getLength(); ++n)
+ {
+ bool bRet;
+ OutChar(rStr[n], &nUCMode, eDestEnc, &bRet);
+ if (!bRet)
+ return false;
+ }
+ return true;
+}
+
+OString OutStringUpr(const char* pToken, const OUString& rStr, rtl_TextEncoding eDestEnc)
+{
+ if (TryOutString(rStr, eDestEnc))
+ return OString::Concat("{") + pToken + " " + OutString(rStr, eDestEnc) + "}";
+
+ return OString::Concat("{" OOO_STRING_SVTOOLS_RTF_UPR "{") + pToken + " "
+ + OutString(rStr, eDestEnc, /*bUnicode =*/false)
+ + "}{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_UD "{" + pToken + " "
+ + OutString(rStr, eDestEnc) + "}}}";
+}
+
+int AsHex(char ch)
+{
+ int ret = 0;
+ if (rtl::isAsciiDigit(static_cast<unsigned char>(ch)))
+ ret = ch - '0';
+ else
+ {
+ if (ch >= 'a' && ch <= 'f')
+ ret = ch - 'a';
+ else if (ch >= 'A' && ch <= 'F')
+ ret = ch - 'A';
+ else
+ return -1;
+ ret += 10;
+ }
+ return ret;
+}
+
+OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, SvStream* pStream, sal_uInt32 nLimit)
+{
+ OStringBuffer aRet;
+
+ sal_uInt32 nBreak = 0;
+ for (sal_uInt32 i = 0; i < nSize; i++)
+ {
+ OString sNo = OString::number(pData[i], 16);
+ if (sNo.getLength() < 2)
+ {
+ if (pStream)
+ pStream->WriteChar('0');
+ else
+ aRet.append('0');
+ }
+ if (pStream)
+ pStream->WriteOString(sNo);
+ else
+ aRet.append(sNo);
+ if (++nBreak == nLimit)
+ {
+ if (pStream)
+ pStream->WriteCharPtr(SAL_NEWLINE_STRING);
+ else
+ aRet.append(SAL_NEWLINE_STRING);
+ nBreak = 0;
+ }
+ }
+
+ return aRet.makeStringAndClear();
+}
+
+bool ExtractOLE2FromObjdata(const OString& rObjdata, SvStream& rOle2)
+{
+ SvMemoryStream aStream;
+ int b = 0;
+ int count = 2;
+
+ // Feed the destination text to a stream.
+ for (int i = 0; i < rObjdata.getLength(); ++i)
+ {
+ char ch = rObjdata[i];
+ if (ch != 0x0d && ch != 0x0a)
+ {
+ b = b << 4;
+ sal_Int8 parsed = msfilter::rtfutil::AsHex(ch);
+ if (parsed == -1)
+ return false;
+ b += parsed;
+ count--;
+ if (!count)
+ {
+ aStream.WriteChar(b);
+ count = 2;
+ b = 0;
+ }
+ }
+ }
+
+ // Skip ObjectHeader, see [MS-OLEDS] 2.2.4.
+ if (!aStream.Tell())
+ return true;
+
+ aStream.Seek(0);
+ sal_uInt32 nData;
+ aStream.ReadUInt32(nData); // OLEVersion
+ aStream.ReadUInt32(nData); // FormatID
+ aStream.ReadUInt32(nData); // ClassName
+ OString aClassName;
+ if (nData)
+ {
+ // -1 because it is null-terminated.
+ aClassName = read_uInt8s_ToOString(aStream, nData - 1);
+ // Skip null-termination.
+ aStream.SeekRel(1);
+ }
+ aStream.ReadUInt32(nData); // TopicName
+ aStream.SeekRel(nData);
+ aStream.ReadUInt32(nData); // ItemName
+ aStream.SeekRel(nData);
+ aStream.ReadUInt32(nData); // NativeDataSize
+
+ if (!nData)
+ return true;
+
+ sal_uInt64 nPos = aStream.Tell();
+ sal_uInt8 aSignature[8];
+ aStream.ReadBytes(aSignature, SAL_N_ELEMENTS(aSignature));
+ aStream.Seek(nPos);
+ const sal_uInt8 aOle2Signature[8] = { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
+ // Don't use Storage::IsStorageFile() here, that would seek to the start of the stream,
+ // where the magic will always mismatch.
+ if (std::memcmp(aSignature, aOle2Signature, SAL_N_ELEMENTS(aSignature)) == 0)
+ {
+ // NativeData
+ rOle2.WriteStream(aStream, nData);
+ }
+ else
+ {
+ SvMemoryStream aStorage;
+ WrapOle1InOle2(aStream, nData, aStorage, aClassName);
+ rOle2.WriteStream(aStorage);
+ }
+ rOle2.Seek(0);
+
+ return true;
+}
+
+bool StripMetafileHeader(const sal_uInt8*& rpGraphicAry, sal_uInt64& rSize)
+{
+ if (rpGraphicAry && (rSize > 0x22))
+ {
+ if ((rpGraphicAry[0] == 0xd7) && (rpGraphicAry[1] == 0xcd) && (rpGraphicAry[2] == 0xc6)
+ && (rpGraphicAry[3] == 0x9a))
+ {
+ // we have to get rid of the metafileheader
+ rpGraphicAry += 22;
+ rSize -= 22;
+ return true;
+ }
+ }
+ return false;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/svdfppt.cxx b/filter/source/msfilter/svdfppt.cxx
new file mode 100644
index 000000000..74f8da16f
--- /dev/null
+++ b/filter/source/msfilter/svdfppt.cxx
@@ -0,0 +1,7832 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <osl/endian.h>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <unotools/tempfile.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/UnitConversion.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/editdata.hxx>
+#include <sot/storage.hxx>
+#include <sot/storinfo.hxx>
+#include <sot/stg.hxx>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/office/XAnnotation.hpp>
+#include <com/sun/star/office/XAnnotationAccess.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/geometry/RealPoint2D.hpp>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
+#include <filter/msfilter/svdfppt.hxx>
+#include <svx/xflgrit.hxx>
+#include <svx/xbtmpit.hxx>
+#include <svx/svdtrans.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdorect.hxx>
+#include <svx/svdopage.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/svdotable.hxx>
+#include <svx/xfillit0.hxx>
+#include <svx/xflbstit.hxx>
+#include <svx/xflbmtit.hxx>
+#include <svx/xflclit.hxx>
+#include <svx/xfltrit.hxx>
+#include <editeng/outlobj.hxx>
+#include <editeng/numdef.hxx>
+#include <svx/sdasitm.hxx>
+#include <svx/sdmetitm.hxx>
+#include <svx/sdtagitm.hxx>
+#include <svx/sdtditm.hxx>
+#include <svx/sdtfsitm.hxx>
+#include <svx/sdtmfitm.hxx>
+#include <svx/xlineit0.hxx>
+#include <svx/xlnclit.hxx>
+#include <svx/xlnwtit.hxx>
+#include <editeng/hngpnctitem.hxx>
+#include <editeng/forbiddenruleitem.hxx>
+#include <svx/svdoashp.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/editids.hrc>
+
+#include <editeng/adjustitem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <svx/svdoutl.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/numitem.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/BitmapReadAccess.hxx>
+#include <svx/svditer.hxx>
+#include <editeng/flditem.hxx>
+#include <tools/zcodec.hxx>
+#include <filter/msfilter/svxmsbas.hxx>
+#include <sfx2/objsh.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/langitem.hxx>
+#include <svx/svdoole2.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/drawing/XControlShape.hpp>
+#include <com/sun/star/form/XFormComponent.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
+#include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/TextVerticalAdjust.hpp>
+#include <editeng/frmdiritem.hxx>
+#include <svx/sdtfchim.hxx>
+#include <com/sun/star/awt/Gradient.hpp>
+#include <com/sun/star/table/XMergeableCellRange.hpp>
+#include <com/sun/star/table/BorderLine2.hpp>
+#include <com/sun/star/table/BorderLineStyle.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <svtools/embedhlp.hxx>
+#include <o3tl/enumrange.hxx>
+#include <o3tl/safeint.hxx>
+#include <o3tl/sorted_vector.hxx>
+#include <sal/log.hxx>
+
+#include <algorithm>
+#include <cassert>
+#include <rtl/strbuf.hxx>
+#include <tools/time.hxx>
+#include <memory>
+
+// PPT ColorScheme Slots
+#define PPT_COLSCHEME (0x08000000)
+#define PPT_COLSCHEME_HINTERGRUND (0x08000000)
+#define PPT_COLSCHEME_TEXT_UND_ZEILEN (0x08000001)
+#define PPT_COLSCHEME_TITELTEXT (0x08000003)
+#define PPT_COLSCHEME_A_UND_HYPERLINK (0x08000006)
+
+#define ANSI_CHARSET 0
+#define SYMBOL_CHARSET 2
+
+/* Font Families */
+#define FF_ROMAN 0x10
+#define FF_SWISS 0x20
+#define FF_MODERN 0x30
+#define FF_SCRIPT 0x40
+#define FF_DECORATIVE 0x50
+
+#define DEFAULT_PITCH 0x00
+#define FIXED_PITCH 0x01
+#define VARIABLE_PITCH 0x02
+
+using namespace ::com::sun::star ;
+using namespace uno ;
+using namespace beans ;
+using namespace drawing ;
+using namespace container ;
+using namespace table ;
+
+PowerPointImportParam::PowerPointImportParam( SvStream& rDocStrm ) :
+ rDocStream ( rDocStrm ),
+ nImportFlags ( 0 )
+{
+}
+
+SvStream& ReadPptCurrentUserAtom( SvStream& rIn, PptCurrentUserAtom& rAtom )
+{
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rIn, aHd );
+ if ( aHd.nRecType == PPT_PST_CurrentUserAtom )
+ {
+ sal_uInt32 nLen;
+ sal_uInt16 nUserNameLen(0), nPad;
+ rIn.ReadUInt32( nLen )
+ .ReadUInt32( rAtom.nMagic )
+ .ReadUInt32( rAtom.nCurrentUserEdit )
+ .ReadUInt16( nUserNameLen )
+ .ReadUInt16( rAtom.nDocFileVersion )
+ .ReadUChar( rAtom.nMajorVersion )
+ .ReadUChar( rAtom.nMinorVersion )
+ .ReadUInt16( nPad );
+ rAtom.aCurrentUser = SvxMSDffManager::MSDFFReadZString( rIn, nUserNameLen, true );
+ }
+ aHd.SeekToEndOfRecord( rIn );
+ return rIn;
+}
+
+void PptSlidePersistAtom::Clear()
+{
+ nReserved = nPsrReference = nFlags = nNumberTexts = nSlideId = 0;
+}
+
+SvStream& ReadPptSlidePersistAtom( SvStream& rIn, PptSlidePersistAtom& rAtom )
+{
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rIn, aHd );
+ rIn
+ .ReadUInt32( rAtom.nPsrReference )
+ .ReadUInt32( rAtom.nFlags )
+ .ReadUInt32( rAtom.nNumberTexts )
+ .ReadUInt32( rAtom.nSlideId );
+ aHd.SeekToEndOfRecord( rIn );
+ return rIn;
+}
+
+PptSlidePersistList::PptSlidePersistList() {}
+
+PptSlidePersistList::~PptSlidePersistList() {}
+
+sal_uInt16 PptSlidePersistList::FindPage(sal_uInt32 nId) const
+{
+ for ( size_t i=0; i < mvEntries.size(); i++ )
+ {
+ if (mvEntries[ i ]->GetSlideId() == nId) return i;
+ }
+ return PPTSLIDEPERSIST_ENTRY_NOTFOUND;
+}
+
+SvStream& ReadPptInteractiveInfoAtom( SvStream& rIn, PptInteractiveInfoAtom& rAtom )
+{
+ rIn.ReadUInt32( rAtom.nSoundRef )
+ .ReadUInt32( rAtom.nExHyperlinkId )
+ .ReadUChar( rAtom.nAction )
+ .ReadUChar( rAtom.nOleVerb )
+ .ReadUChar( rAtom.nJump )
+ .ReadUChar( rAtom.nFlags )
+ .ReadUChar( rAtom.nHyperlinkType )
+ .ReadUChar( rAtom.nUnknown1 )
+ .ReadUChar( rAtom.nUnknown2 )
+ .ReadUChar( rAtom.nUnknown3 );
+ return rIn;
+}
+
+SvStream& ReadPptExOleObjAtom( SvStream& rIn, PptExOleObjAtom& rAtom )
+{
+ sal_uInt32 nDummy1;
+ sal_uInt32 nDummy2;
+ sal_uInt32 nDummy4;
+
+ rIn.ReadUInt32( rAtom.nAspect )
+ .ReadUInt32( nDummy1 )
+ .ReadUInt32( rAtom.nId )
+ .ReadUInt32( nDummy2 )
+ .ReadUInt32( rAtom.nPersistPtr )
+ .ReadUInt32( nDummy4 );
+ return rIn;
+}
+
+SvStream& ReadPptDocumentAtom(SvStream& rIn, PptDocumentAtom& rAtom)
+{
+// Actual format:
+// 00 aSlidePageSizeXY 8
+// 08 aNotesPageSizeXY 8
+// 16 aZoomRatio (OLE) 8
+// 24 nNotesMasterPersist 4
+// 28 nHandoutMasterPersist 4
+// 32 n1stPageNumber 2
+// 34 ePageFormat 2
+// 36 bEmbeddedTrueType 1
+// 37 bOmitTitlePlace 1
+// 38 bRightToLeft 1
+// 39 bShowComments 1
+
+ DffRecordHeader aHd;
+ sal_Int32 nSlideX(0), nSlideY(0), nNoticeX(0), nNoticeY(0), nDummy;
+ sal_uInt16 nSlidePageFormat(0);
+ sal_Int8 nEmbeddedTrueType(0), nTitlePlaceHoldersOmitted(0), nRightToLeft(0), nShowComments(0);
+
+ ReadDffRecordHeader( rIn, aHd );
+ rIn
+ .ReadInt32( nSlideX ).ReadInt32( nSlideY )
+ .ReadInt32( nNoticeX ).ReadInt32( nNoticeY )
+ .ReadInt32( nDummy ).ReadInt32( nDummy ) // skip ZoomRatio
+ .ReadUInt32( rAtom.nNotesMasterPersist )
+ .ReadUInt32( rAtom.nHandoutMasterPersist )
+ .ReadUInt16( rAtom.n1stPageNumber )
+ .ReadUInt16( nSlidePageFormat )
+ .ReadSChar( nEmbeddedTrueType )
+ .ReadSChar( nTitlePlaceHoldersOmitted )
+ .ReadSChar( nRightToLeft )
+ .ReadSChar( nShowComments );
+ // clamp dodgy data to avoid overflow in later calculations
+ const sal_Int32 nPageClamp = SAL_MAX_INT32/5;
+ rAtom.aSlidesPageSize.setWidth( std::clamp<sal_Int32>(nSlideX, -nPageClamp, nPageClamp) );
+ rAtom.aSlidesPageSize.setHeight( std::clamp<sal_Int32>(nSlideY, -nPageClamp, nPageClamp) );
+ const sal_Int32 nNoteClamp = 65536;
+ rAtom.aNotesPageSize.setWidth( std::clamp<sal_Int32>(nNoticeX, -nNoteClamp, nNoteClamp) );
+ rAtom.aNotesPageSize.setHeight( std::clamp<sal_Int32>(nNoticeY, -nNoteClamp, nNoteClamp) );
+ rAtom.eSlidesPageFormat = static_cast<PptPageFormat>(nSlidePageFormat);
+ rAtom.bEmbeddedTrueType = nEmbeddedTrueType;
+ rAtom.bTitlePlaceholdersOmitted = nTitlePlaceHoldersOmitted;
+ rAtom.bRightToLeft = nRightToLeft;
+ rAtom.bShowComments = nShowComments;
+ aHd.SeekToEndOfRecord( rIn );
+ return rIn;
+}
+
+void PptSlideLayoutAtom::Clear()
+{
+ eLayout = PptSlideLayout::TITLESLIDE;
+ for (PptPlaceholder & i : aPlaceholderId)
+ i = PptPlaceholder::NONE;
+}
+
+SvStream& ReadPptSlideLayoutAtom( SvStream& rIn, PptSlideLayoutAtom& rAtom )
+{
+ sal_Int32 nTmp;
+ rIn.ReadInt32(nTmp);
+ rAtom.eLayout = static_cast<PptSlideLayout>(nTmp);
+ static_assert(sizeof(rAtom.aPlaceholderId) == 8, "wrong size of serialized array");
+ rIn.ReadBytes(rAtom.aPlaceholderId, 8);
+ return rIn;
+}
+
+SvStream& ReadPptSlideAtom( SvStream& rIn, PptSlideAtom& rAtom )
+{
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rIn, aHd );
+ ReadPptSlideLayoutAtom( rIn, rAtom.aLayout );
+ rIn.ReadUInt32( rAtom.nMasterId )
+ .ReadUInt32( rAtom.nNotesId )
+ .ReadUInt16( rAtom.nFlags );
+ aHd.SeekToEndOfRecord( rIn );
+ return rIn;
+}
+
+void PptSlideAtom::Clear()
+{
+ nMasterId = nNotesId = 0;
+ nFlags = 0;
+}
+
+SvStream& ReadPptNotesAtom( SvStream& rIn, PptNotesAtom& rAtom )
+{
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rIn, aHd );
+ rIn
+ .ReadUInt32( rAtom.nSlideId )
+ .ReadUInt16( rAtom.nFlags );
+ aHd.SeekToEndOfRecord( rIn );
+ return rIn;
+}
+
+void PptNotesAtom::Clear()
+{
+ nSlideId = 0;
+ nFlags = 0;
+}
+
+PptColorSchemeAtom::PptColorSchemeAtom()
+{
+}
+
+Color PptColorSchemeAtom::GetColor( sal_uInt16 nNum ) const
+{
+ Color aRetval;
+ if ( nNum < 8 )
+ {
+ nNum <<= 2;
+ aRetval.SetRed( aData[ nNum++ ] );
+ aRetval.SetGreen( aData[ nNum++ ] );
+ aRetval.SetBlue( aData[ nNum++ ] );
+ }
+ return aRetval;
+}
+
+SvStream& ReadPptColorSchemeAtom( SvStream& rIn, PptColorSchemeAtom& rAtom )
+{
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rIn, aHd );
+ rIn.ReadBytes(rAtom.aData, 32);
+ aHd.SeekToEndOfRecord( rIn );
+ return rIn;
+}
+
+SvStream& ReadPptFontEntityAtom( SvStream& rIn, PptFontEntityAtom& rAtom )
+{
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rIn, aHd );
+ sal_Unicode nTemp, cData[ 32 ];
+ rIn.ReadBytes(cData, 64);
+
+ sal_uInt8 lfCharset, lfPitchAndFamily;
+
+ rIn.ReadUChar( lfCharset )
+ .ReadUChar( rAtom.lfClipPrecision )
+ .ReadUChar( rAtom.lfQuality )
+ .ReadUChar( lfPitchAndFamily );
+
+ switch( lfCharset )
+ {
+ case SYMBOL_CHARSET :
+ rAtom.eCharSet = RTL_TEXTENCODING_SYMBOL;
+ break;
+ case ANSI_CHARSET :
+ rAtom.eCharSet = RTL_TEXTENCODING_MS_1252;
+ break;
+
+ default :
+ rAtom.eCharSet = osl_getThreadTextEncoding();
+ }
+ switch ( lfPitchAndFamily & 0xf0 )
+ {
+ case FF_ROMAN:
+ rAtom.eFamily = FAMILY_ROMAN;
+ break;
+
+ case FF_SWISS:
+ rAtom.eFamily = FAMILY_SWISS;
+ break;
+
+ case FF_MODERN:
+ rAtom.eFamily = FAMILY_MODERN;
+ break;
+
+ case FF_SCRIPT:
+ rAtom.eFamily = FAMILY_SCRIPT;
+ break;
+
+ case FF_DECORATIVE:
+ rAtom.eFamily = FAMILY_DECORATIVE;
+ break;
+
+ default:
+ rAtom.eFamily = FAMILY_DONTKNOW;
+ break;
+ }
+
+ switch ( lfPitchAndFamily & 0x0f )
+ {
+ case FIXED_PITCH:
+ rAtom.ePitch = PITCH_FIXED;
+ break;
+
+ case DEFAULT_PITCH:
+ case VARIABLE_PITCH:
+ default:
+ rAtom.ePitch = PITCH_VARIABLE;
+ break;
+ }
+ sal_uInt16 i;
+ for ( i = 0; i < 32; i++ )
+ {
+ nTemp = cData[ i ];
+ if ( !nTemp )
+ break;
+#ifdef OSL_BIGENDIAN
+ cData[ i ] = ( nTemp >> 8 ) | ( nTemp << 8 );
+#endif
+ }
+ rAtom.aName = OUString(cData, i);
+ OutputDevice* pDev = Application::GetDefaultDevice();
+ rAtom.bAvailable = pDev->IsFontAvailable( rAtom.aName );
+ aHd.SeekToEndOfRecord( rIn );
+ return rIn;
+}
+
+SvStream& ReadPptUserEditAtom( SvStream& rIn, PptUserEditAtom& rAtom )
+{
+ sal_Int16 lastViewType = 0;
+ ReadDffRecordHeader( rIn, rAtom.aHd );
+ rIn
+ .ReadInt32( rAtom.nLastSlideID )
+ .ReadUInt32( rAtom.nVersion )
+ .ReadUInt32( rAtom.nOffsetLastEdit )
+ .ReadUInt32( rAtom.nOffsetPersistDirectory )
+ .ReadUInt32( rAtom.nDocumentRef )
+ .ReadUInt32( rAtom.nMaxPersistWritten )
+ .ReadInt16( lastViewType );
+ rAtom.eLastViewType = static_cast<PptViewTypeEnum>(lastViewType);
+ rAtom.aHd.SeekToEndOfRecord(rIn);
+ return rIn;
+}
+
+void PptOEPlaceholderAtom::Clear()
+{
+ nPlacementId = 0;
+ nPlaceholderSize = 0;
+ nPlaceholderId = PptPlaceholder::NONE;
+}
+
+SvStream& ReadPptOEPlaceholderAtom( SvStream& rIn, PptOEPlaceholderAtom& rAtom )
+{
+ rIn.ReadUInt32( rAtom.nPlacementId );
+ sal_uInt8 nTmp;
+ rIn.ReadUChar(nTmp);
+ rAtom.nPlaceholderId = static_cast<PptPlaceholder>(nTmp);
+ rIn.ReadUChar( rAtom.nPlaceholderSize );
+ return rIn;
+}
+
+PptSlidePersistEntry::PptSlidePersistEntry() :
+ nSlidePersistStartOffset( 0 ),
+ nSlidePersistEndOffset ( 0 ),
+ nBackgroundOffset ( 0 ),
+ nDrawingDgId ( 0xffffffff ),
+ pBObj ( nullptr ),
+ ePageKind ( PPT_MASTERPAGE ),
+ bNotesMaster ( false ),
+ bHandoutMaster ( false ),
+ bStarDrawFiller ( false )
+{
+ HeaderFooterOfs[ 0 ] = HeaderFooterOfs[ 1 ] = HeaderFooterOfs[ 2 ] = HeaderFooterOfs[ 3 ] = 0;
+}
+
+PptSlidePersistEntry::~PptSlidePersistEntry()
+{
+}
+
+SdrEscherImport::SdrEscherImport( PowerPointImportParam& rParam, const OUString& rBaseURL ) :
+ SvxMSDffManager ( rParam.rDocStream, rBaseURL ),
+ nStreamLen ( 0 ),
+ rImportParam ( rParam )
+{
+}
+
+SdrEscherImport::~SdrEscherImport()
+{
+}
+
+const PptSlideLayoutAtom* SdrEscherImport::GetSlideLayoutAtom() const
+{
+ return nullptr;
+}
+
+bool SdrEscherImport::ReadString( OUString& rStr ) const
+{
+ bool bRet = false;
+ DffRecordHeader aStrHd;
+ ReadDffRecordHeader( rStCtrl, aStrHd );
+ if (aStrHd.nRecType == PPT_PST_TextBytesAtom
+ || aStrHd.nRecType == PPT_PST_TextCharsAtom
+ || aStrHd.nRecType == PPT_PST_CString)
+ {
+ bool bUniCode =
+ (aStrHd.nRecType == PPT_PST_TextCharsAtom
+ || aStrHd.nRecType == PPT_PST_CString);
+ sal_uLong nBytes = aStrHd.nRecLen;
+ rStr = MSDFFReadZString( rStCtrl, nBytes, bUniCode );
+ bRet = aStrHd.SeekToEndOfRecord( rStCtrl );
+ }
+ else
+ aStrHd.SeekToBegOfRecord( rStCtrl );
+ return bRet;
+}
+
+bool SdrEscherImport::GetColorFromPalette(sal_uInt16 /*nNum*/, Color& /*rColor*/) const
+{
+ return false;
+}
+
+bool SdrEscherImport::SeekToShape( SvStream& /*rSt*/, SvxMSDffClientData* /*pClientData*/, sal_uInt32 /*nId*/) const
+{
+ return false;
+}
+
+const PptFontEntityAtom* SdrEscherImport::GetFontEnityAtom( sal_uInt32 nNum ) const
+{
+ if (m_xFonts && nNum < m_xFonts->size())
+ return &(*m_xFonts)[ nNum ];
+ return nullptr;
+}
+
+SdrObject* SdrEscherImport::ReadObjText( PPTTextObj* /*pTextObj*/, SdrObject* pObj, SdPageCapsule /*pPage*/) const
+{
+ return pObj;
+}
+
+void SdrEscherImport::ProcessClientAnchor2( SvStream& rSt, DffRecordHeader& rHd, DffObjData& rObj )
+{
+ sal_Int32 l, t, r, b;
+ if ( rHd.nRecLen == 16 )
+ {
+ rSt.ReadInt32( l ).ReadInt32( t ).ReadInt32( r ).ReadInt32( b );
+ }
+ else
+ {
+ sal_Int16 ls, ts, rs, bs;
+ rSt.ReadInt16( ts ).ReadInt16( ls ).ReadInt16( rs ).ReadInt16( bs ); // the order of coordinates is a bit strange...
+ l = ls;
+ t = ts;
+ r = rs;
+ b = bs;
+ }
+ if (!rSt.good())
+ {
+ SAL_WARN("filter.ms", "ProcessClientAnchor2: short read");
+ return;
+ }
+ Scale( l );
+ Scale( t );
+ Scale( r );
+ Scale( b );
+ rObj.aChildAnchor = tools::Rectangle( l, t, r, b );
+ rObj.bChildAnchor = true;
+};
+
+void SdrEscherImport::RecolorGraphic( SvStream& rSt, sal_uInt32 nRecLen, Graphic& rGraphic )
+{
+ if ( rGraphic.GetType() != GraphicType::GdiMetafile )
+ return;
+
+ sal_uInt16 nX, nGlobalColorsCount, nFillColorsCount;
+
+ rSt.ReadUInt16( nX )
+ .ReadUInt16( nGlobalColorsCount )
+ .ReadUInt16( nFillColorsCount )
+ .ReadUInt16( nX )
+ .ReadUInt16( nX )
+ .ReadUInt16( nX );
+
+ if ( ( nGlobalColorsCount > 64 ) || ( nFillColorsCount > 64 ) )
+ return;
+
+ if ( static_cast<sal_uInt32>( ( nGlobalColorsCount + nFillColorsCount ) * 44 + 12 ) != nRecLen )
+ return;
+
+ sal_uInt32 OriginalGlobalColors[ 64 ];
+ sal_uInt32 NewGlobalColors[ 64 ];
+
+ sal_uInt32 i, j, nGlobalColorsChanged, nFillColorsChanged;
+ nGlobalColorsChanged = nFillColorsChanged = 0;
+
+ sal_uInt32* pCurrentOriginal = OriginalGlobalColors;
+ sal_uInt32* pCurrentNew = NewGlobalColors;
+ sal_uInt32* pCount = &nGlobalColorsChanged;
+ i = nGlobalColorsCount;
+
+ for ( j = 0; j < 2; j++ )
+ {
+ for ( ; i > 0; i-- )
+ {
+ sal_uInt64 nPos = rSt.Tell();
+ sal_uInt16 nChanged;
+ rSt.ReadUInt16( nChanged );
+ if ( nChanged & 1 )
+ {
+ sal_uInt8 nDummy, nRed, nGreen, nBlue;
+ sal_uInt32 nColor = 0;
+ sal_uInt32 nIndex;
+ rSt.ReadUChar( nDummy )
+ .ReadUChar( nRed )
+ .ReadUChar( nDummy )
+ .ReadUChar( nGreen )
+ .ReadUChar( nDummy )
+ .ReadUChar( nBlue )
+ .ReadUInt32( nIndex );
+
+ if ( nIndex < 8 )
+ {
+ Color aColor = MSO_CLR_ToColor( nIndex << 24 );
+ nRed = aColor.GetRed();
+ nGreen = aColor.GetGreen();
+ nBlue = aColor.GetBlue();
+ }
+ nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 );
+ *pCurrentNew++ = nColor;
+ rSt.ReadUChar( nDummy )
+ .ReadUChar( nRed )
+ .ReadUChar( nDummy )
+ .ReadUChar( nGreen )
+ .ReadUChar( nDummy )
+ .ReadUChar( nBlue );
+ nColor = nRed | ( nGreen << 8 ) | ( nBlue << 16 );
+ *pCurrentOriginal++ = nColor;
+ (*pCount)++;
+ }
+ rSt.Seek( nPos + 44 );
+ }
+ pCount = &nFillColorsChanged;
+ i = nFillColorsCount;
+ }
+ if ( !(nGlobalColorsChanged || nFillColorsChanged) )
+ return;
+
+ std::unique_ptr<Color[]> pSearchColors(new Color[ nGlobalColorsChanged ]);
+ std::unique_ptr<Color[]> pReplaceColors(new Color[ nGlobalColorsChanged ]);
+
+ for ( j = 0; j < nGlobalColorsChanged; j++ )
+ {
+ sal_uInt32 nSearch = OriginalGlobalColors[ j ];
+ sal_uInt32 nReplace = NewGlobalColors[ j ];
+
+ pSearchColors[ j ].SetRed( static_cast<sal_uInt8>(nSearch) );
+ pSearchColors[ j ].SetGreen( static_cast<sal_uInt8>( nSearch >> 8 ) );
+ pSearchColors[ j ].SetBlue( static_cast<sal_uInt8>( nSearch >> 16 ) );
+
+ pReplaceColors[ j ].SetRed( static_cast<sal_uInt8>(nReplace) );
+ pReplaceColors[ j ].SetGreen( static_cast<sal_uInt8>( nReplace >> 8 ) );
+ pReplaceColors[ j ].SetBlue( static_cast<sal_uInt8>( nReplace >> 16 ) );
+ }
+ GDIMetaFile aGdiMetaFile( rGraphic.GetGDIMetaFile() );
+ aGdiMetaFile.ReplaceColors( pSearchColors.get(), pReplaceColors.get(),
+ nGlobalColorsChanged );
+ rGraphic = aGdiMetaFile;
+}
+
+sal_uLong DffPropSet::SanitizeEndPos(SvStream &rIn, sal_uLong nEndRecPos)
+{
+ auto nStreamLen = rIn.Tell() + rIn.remainingSize();
+ if (nEndRecPos > nStreamLen)
+ {
+ SAL_WARN("filter.ms", "Parsing error: " << nStreamLen <<
+ " max end pos, but " << nEndRecPos << " claimed, truncating");
+ nEndRecPos = nStreamLen;
+ }
+ return nEndRecPos;
+}
+
+void ProcessData::NotifyFreeObj(SdrObject* pObj)
+{
+ if (rPersistEntry.xSolverContainer)
+ {
+ for (auto & pPtr : rPersistEntry.xSolverContainer->aCList)
+ {
+ if (pPtr->pAObj == pObj)
+ pPtr->pAObj = nullptr;
+ if (pPtr->pBObj == pObj)
+ pPtr->pBObj = nullptr;
+ if (pPtr->pCObj == pObj)
+ pPtr->pCObj = nullptr;
+ }
+ }
+}
+
+/* ProcessObject is called from ImplSdPPTImport::ProcessObj to handle all application specific things,
+ such as the import of text, animation effects, header footer and placeholder.
+
+ The parameter pOriginalObj is the object as it was imported by our general escher import, it must either
+ be deleted or it can be returned to be inserted into the sdr page.
+*/
+SdrObject* SdrEscherImport::ProcessObj( SvStream& rSt, DffObjData& rObjData, SvxMSDffClientData& rClientData, tools::Rectangle& rTextRect, SdrObject* pOriginalObj )
+{
+ if ( dynamic_cast<const SdrObjCustomShape* >(pOriginalObj) != nullptr )
+ pOriginalObj->SetMergedItem( SdrTextFixedCellHeightItem( true ) );
+
+ // we are initializing our return value with the object that was imported by our escher import
+ SdrObject* pRet = pOriginalObj;
+
+ ProcessData& rData = static_cast<ProcessData&>(rClientData);
+ PptSlidePersistEntry& rPersistEntry = rData.rPersistEntry;
+
+ if ( ! (rObjData.nSpFlags & ShapeFlag::Group) ) // sj: #114758# ...
+ {
+ PptOEPlaceholderAtom aPlaceholderAtom;
+
+ if ( maShapeRecords.SeekToContent( rSt, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
+ {
+ sal_Int16 nHeaderFooterInstance = -1;
+ DffRecordHeader aClientDataHd;
+ auto nEndRecPos = SanitizeEndPos(rSt, maShapeRecords.Current()->GetRecEndFilePos());
+ while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
+ {
+ ReadDffRecordHeader( rSt, aClientDataHd );
+ switch ( aClientDataHd.nRecType )
+ {
+ // importing header/footer object from master page
+ case PPT_PST_OEPlaceholderAtom :
+ {
+ ReadPptOEPlaceholderAtom( rSt, aPlaceholderAtom );
+ if ( nHeaderFooterInstance == -1 )
+ {
+ switch ( aPlaceholderAtom.nPlaceholderId )
+ {
+ case PptPlaceholder::MASTERSLIDENUMBER : nHeaderFooterInstance++;
+ [[fallthrough]];
+ case PptPlaceholder::MASTERFOOTER : nHeaderFooterInstance++;
+ [[fallthrough]];
+ case PptPlaceholder::MASTERHEADER : nHeaderFooterInstance++;
+ [[fallthrough]];
+ case PptPlaceholder::MASTERDATE : nHeaderFooterInstance++; break;
+ default: break;
+
+ }
+ if ( ! ( nHeaderFooterInstance & 0xfffc ) ) // is this a valid instance ( 0->3 )
+ rPersistEntry.HeaderFooterOfs[ nHeaderFooterInstance ] = rObjData.rSpHd.GetRecBegFilePos();
+ }
+ }
+ break;
+
+ case PPT_PST_RecolorInfoAtom :
+ {
+ if ( auto pSdrGrafObj = dynamic_cast<SdrGrafObj* >(pRet) )
+ if ( pSdrGrafObj->HasGDIMetaFile() )
+ {
+ Graphic aGraphic( pSdrGrafObj->GetGraphic() );
+ RecolorGraphic( rSt, aClientDataHd.nRecLen, aGraphic );
+ pSdrGrafObj->SetGraphic( aGraphic );
+ }
+ }
+ break;
+ }
+ if (!aClientDataHd.SeekToEndOfRecord(rSt))
+ break;
+ }
+ }
+ if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESSLIDEIMAGE ) && !rPersistEntry.bNotesMaster )
+ {
+ sal_uInt16 nPageNum = pSdrModel->GetPageCount();
+ if ( nPageNum > 0 )
+ nPageNum--;
+
+ // replacing the object which we will return with a SdrPageObj
+ SdrObject::Free( pRet );
+ pRet = new SdrPageObj(
+ *pSdrModel,
+ rObjData.aBoundRect,
+ pSdrModel->GetPage(nPageNum - 1));
+ }
+ else
+ {
+ // try to load some ppt text
+ PPTTextObj aTextObj( rSt, static_cast<SdrPowerPointImport&>(*this), rPersistEntry, &rObjData );
+ if ( aTextObj.Count() || aTextObj.GetOEPlaceHolderAtom() )
+ {
+ bool bVerticalText = false;
+ // and if the text object is not empty, it must be applied to pRet, the object we
+ // initially got from our escher import
+ Degree100 nTextRotationAngle(0);
+ if ( IsProperty( DFF_Prop_txflTextFlow ) )
+ {
+ auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
+ switch( eTextFlow )
+ {
+ case mso_txflBtoT : // Bottom to Top non-@
+ nTextRotationAngle += 9000_deg100;
+ break;
+ case mso_txflTtoBA : /* #68110# */ // Top to Bottom @-font
+ case mso_txflTtoBN : // Top to Bottom non-@
+ case mso_txflVertN : // Vertical, non-@, top to bottom
+ bVerticalText = !bVerticalText; // nTextRotationAngle += 27000;
+ break;
+ // case mso_txflHorzN : // Horizontal non-@, normal
+ // case mso_txflHorzA : // Horizontal @-font, normal
+ default: break;
+ }
+ }
+ sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 );
+ if ( ( nFontDirection == 1 ) || ( nFontDirection == 3 ) )
+ {
+ bVerticalText = !bVerticalText;
+ }
+ const bool bFail = o3tl::checked_multiply<sal_Int32>(nFontDirection, 9000, nFontDirection);
+ if (!bFail)
+ nTextRotationAngle -= Degree100(nFontDirection);
+ else
+ SAL_WARN("filter.ms", "Parsing error: bad fontdirection: " << nFontDirection);
+ aTextObj.SetVertical( bVerticalText );
+ if ( pRet )
+ {
+ bool bDeleteSource = aTextObj.GetOEPlaceHolderAtom() != nullptr;
+ if ( bDeleteSource && dynamic_cast<const SdrGrafObj* >(pRet) == nullptr // we are not allowed to get
+ && dynamic_cast<const SdrObjGroup* >(pRet) == nullptr // grouped placeholder objects
+ && dynamic_cast<const SdrOle2Obj* >(pRet) == nullptr )
+ SdrObject::Free( pRet );
+ }
+ sal_uInt32 nTextFlags = aTextObj.GetTextFlags();
+ sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 25 * 3600 ); // 0.25 cm (emu)
+ sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 25 * 3600 ); // 0.25 cm (emu)
+ sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 13 * 3600 ); // 0.13 cm (emu)
+ sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 13 * 3600 );
+ ScaleEmu( nTextLeft );
+ ScaleEmu( nTextRight );
+ ScaleEmu( nTextTop );
+ ScaleEmu( nTextBottom );
+
+ sal_Int32 nMinFrameWidth = 0;
+ sal_Int32 nMinFrameHeight = 0;
+ bool bAutoGrowWidth, bAutoGrowHeight;
+
+ SdrTextVertAdjust eTVA;
+ SdrTextHorzAdjust eTHA;
+
+ nTextFlags &= PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT
+ | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
+
+ if ( bVerticalText )
+ {
+ eTVA = SDRTEXTVERTADJUST_BLOCK;
+ eTHA = SDRTEXTHORZADJUST_CENTER;
+
+ // read text anchor
+ auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
+
+ switch( eTextAnchor )
+ {
+ case mso_anchorTop:
+ case mso_anchorTopCentered:
+ case mso_anchorTopBaseline:
+ case mso_anchorTopCenteredBaseline:
+ eTHA = SDRTEXTHORZADJUST_RIGHT;
+ break;
+
+ case mso_anchorMiddle :
+ case mso_anchorMiddleCentered:
+ eTHA = SDRTEXTHORZADJUST_CENTER;
+ break;
+
+ case mso_anchorBottom:
+ case mso_anchorBottomCentered:
+ case mso_anchorBottomBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ eTHA = SDRTEXTHORZADJUST_LEFT;
+ break;
+ }
+ switch ( eTextAnchor )
+ {
+ case mso_anchorTopCentered :
+ case mso_anchorMiddleCentered :
+ case mso_anchorBottomCentered :
+ case mso_anchorTopCenteredBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ {
+ // check if it is sensible to use the centered alignment
+ const sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
+ switch (nTextFlags & nMask)
+ {
+ case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT:
+ case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER:
+ case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT:
+ case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK:
+ eTVA = SDRTEXTVERTADJUST_CENTER; // If the textobject has only one type of alignment, then the text has not to be displayed using the full width;
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ nMinFrameWidth = rTextRect.GetWidth() - ( nTextLeft + nTextRight );
+ }
+ else
+ {
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+ eTHA = SDRTEXTHORZADJUST_BLOCK;
+
+ // read text anchor
+ auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
+
+ switch( eTextAnchor )
+ {
+ case mso_anchorTop:
+ case mso_anchorTopCentered:
+ case mso_anchorTopBaseline:
+ case mso_anchorTopCenteredBaseline:
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ break;
+
+ case mso_anchorMiddle :
+ case mso_anchorMiddleCentered:
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+ break;
+
+ case mso_anchorBottom:
+ case mso_anchorBottomCentered:
+ case mso_anchorBottomBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ break;
+ }
+ switch ( eTextAnchor )
+ {
+ case mso_anchorTopCentered :
+ case mso_anchorMiddleCentered :
+ case mso_anchorBottomCentered :
+ case mso_anchorTopCenteredBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ {
+ // check if it is sensible to use the centered alignment
+ const sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
+ switch (nTextFlags & nMask)
+ {
+ case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT:
+ case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER:
+ case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT:
+ case PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK:
+ eTHA = SDRTEXTHORZADJUST_CENTER; // If the textobject has only one type of alignment, then the text has not to be displayed using the full width;
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ nMinFrameHeight = rTextRect.GetHeight() - ( nTextTop + nTextBottom );
+ }
+
+ SdrObjKind eTextKind = SdrObjKind::Rectangle;
+ if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESSLIDEIMAGE )
+ || ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::MASTERNOTESSLIDEIMAGE ) )
+ {
+ aTextObj.SetInstance( TSS_Type::Notes );
+ eTextKind = SdrObjKind::TitleText;
+ }
+ else if ( ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::MASTERNOTESBODYIMAGE )
+ || ( aPlaceholderAtom.nPlaceholderId == PptPlaceholder::NOTESBODY ) )
+ {
+ aTextObj.SetInstance( TSS_Type::Notes );
+ eTextKind = SdrObjKind::Text;
+ }
+
+ TSS_Type nDestinationInstance = aTextObj.GetInstance();
+ if ( rPersistEntry.ePageKind == PPT_MASTERPAGE )
+ {
+ if ( !rPersistEntry.pPresentationObjects )
+ {
+ rPersistEntry.pPresentationObjects.reset( new sal_uInt32[ PPT_STYLESHEETENTRIES ] );
+ memset( rPersistEntry.pPresentationObjects.get(), 0, PPT_STYLESHEETENTRIES * 4 );
+ }
+ if ( !rPersistEntry.pPresentationObjects[ static_cast<int>(nDestinationInstance) ] )
+ rPersistEntry.pPresentationObjects[ static_cast<int>(nDestinationInstance) ] = rObjData.rSpHd.GetRecBegFilePos();
+ }
+ switch ( nDestinationInstance )
+ {
+ case TSS_Type::PageTitle :
+ case TSS_Type::Title :
+ {
+ if ( GetSlideLayoutAtom()->eLayout == PptSlideLayout::TITLEMASTERSLIDE )
+ nDestinationInstance = TSS_Type::Title;
+ else
+ nDestinationInstance = TSS_Type::PageTitle;
+ }
+ break;
+ case TSS_Type::Body :
+ case TSS_Type::HalfBody :
+ case TSS_Type::QuarterBody :
+ nDestinationInstance = TSS_Type::Body;
+ break;
+ default: break;
+ }
+ aTextObj.SetDestinationInstance( nDestinationInstance );
+
+ bool bAutoFit = false; // auto-scale text into shape box
+ switch ( aTextObj.GetInstance() )
+ {
+ case TSS_Type::PageTitle :
+ case TSS_Type::Title : eTextKind = SdrObjKind::TitleText; break;
+ case TSS_Type::Subtitle : eTextKind = SdrObjKind::Text; break;
+ case TSS_Type::Body :
+ case TSS_Type::HalfBody :
+ case TSS_Type::QuarterBody : eTextKind = SdrObjKind::OutlineText; bAutoFit = true; break;
+ default: break;
+ }
+ if ( aTextObj.GetDestinationInstance() != TSS_Type::TextInShape )
+ {
+ if ( !aTextObj.GetOEPlaceHolderAtom() || aTextObj.GetOEPlaceHolderAtom()->nPlaceholderId == PptPlaceholder::NONE )
+ {
+ aTextObj.SetDestinationInstance( TSS_Type::TextInShape );
+ eTextKind = SdrObjKind::Rectangle;
+ }
+ }
+ SdrObject* pTObj = nullptr;
+ bool bWordWrap = GetPropertyValue(DFF_Prop_WrapText, mso_wrapSquare) != mso_wrapNone;
+ bool bFitShapeToText = ( GetPropertyValue( DFF_Prop_FitTextToShape, 0 ) & 2 ) != 0;
+
+ if ( dynamic_cast<const SdrObjCustomShape* >(pRet) != nullptr && ( eTextKind == SdrObjKind::Rectangle ) )
+ {
+ bAutoGrowHeight = bFitShapeToText;
+ bAutoGrowWidth = !bWordWrap;
+ pTObj = pRet;
+ pRet = nullptr;
+ }
+ else
+ {
+ if ( dynamic_cast<const SdrObjCustomShape* >(pRet) != nullptr )
+ {
+ SdrObject::Free( pRet );
+ pRet = nullptr;
+ }
+ pTObj = new SdrRectObj(
+ *pSdrModel,
+ eTextKind != SdrObjKind::Rectangle ? eTextKind : SdrObjKind::Text);
+ SfxItemSet aSet( pSdrModel->GetItemPool() );
+ if ( !pRet )
+ ApplyAttributes( rSt, aSet, rObjData );
+ pTObj->SetMergedItemSet( aSet );
+ if ( pRet )
+ {
+ pTObj->SetMergedItem( XLineStyleItem( drawing::LineStyle_NONE ) );
+ pTObj->SetMergedItem( XFillStyleItem( drawing::FillStyle_NONE ) );
+ }
+ if ( bVerticalText )
+ {
+ bAutoGrowWidth = bFitShapeToText;
+ bAutoGrowHeight = false;
+ }
+ else
+ {
+ bAutoGrowWidth = false;
+
+ // #119885# re-activating bFitShapeToText here, could not find deeper explanations
+ // for it (it was from 2005). Keeping the old comment here for reference
+ // old comment: // bFitShapeToText; can't be used, because we cut the text if it is too height,
+ bAutoGrowHeight = bFitShapeToText;
+ }
+ }
+ pTObj->SetMergedItem( SvxFrameDirectionItem( bVerticalText ? SvxFrameDirection::Vertical_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
+
+ //Autofit text only if there is no auto grow height and width
+ //See fdo#41245
+ if (bAutoFit && !bAutoGrowHeight && !bAutoGrowWidth)
+ {
+ pTObj->SetMergedItem( SdrTextFitToSizeTypeItem(drawing::TextFitToSizeType_AUTOFIT) );
+ }
+
+ if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr )
+ {
+ pTObj->SetMergedItem( makeSdrTextAutoGrowWidthItem( bAutoGrowWidth ) );
+ pTObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bAutoGrowHeight ) );
+ }
+ else
+ {
+ pTObj->SetMergedItem( makeSdrTextWordWrapItem( bWordWrap ) );
+ pTObj->SetMergedItem( makeSdrTextAutoGrowHeightItem( bFitShapeToText ) );
+ }
+
+ pTObj->SetMergedItem( SdrTextVertAdjustItem( eTVA ) );
+ pTObj->SetMergedItem( SdrTextHorzAdjustItem( eTHA ) );
+
+ if ( nMinFrameHeight < 0 )
+ nMinFrameHeight = 0;
+ if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr )
+ pTObj->SetMergedItem( makeSdrTextMinFrameHeightItem( nMinFrameHeight ) );
+
+ if ( nMinFrameWidth < 0 )
+ nMinFrameWidth = 0;
+ if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr )
+ pTObj->SetMergedItem( makeSdrTextMinFrameWidthItem( nMinFrameWidth ) );
+
+ // set margins at the borders of the textbox
+ pTObj->SetMergedItem( makeSdrTextLeftDistItem( nTextLeft ) );
+ pTObj->SetMergedItem( makeSdrTextRightDistItem( nTextRight ) );
+ pTObj->SetMergedItem( makeSdrTextUpperDistItem( nTextTop ) );
+ pTObj->SetMergedItem( makeSdrTextLowerDistItem( nTextBottom ) );
+ pTObj->SetMergedItem( SdrTextFixedCellHeightItem( true ) );
+
+ if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr )
+ pTObj->SetSnapRect( rTextRect );
+ pTObj = ReadObjText( &aTextObj, pTObj, rData.pPage );
+
+ if ( pTObj )
+ {
+ /* check if our new snaprect makes trouble,
+ because we do not display the ADJUST_BLOCK
+ properly if the textsize is bigger than the
+ snaprect of the object. Then we will use
+ ADJUST_CENTER instead of ADJUST_BLOCK.
+ */
+ if ( dynamic_cast<const SdrObjCustomShape* >(pTObj) == nullptr && !bFitShapeToText && !bWordWrap )
+ {
+ SdrTextObj* pText = dynamic_cast<SdrTextObj*>( pTObj );
+ if ( pText )
+ {
+ if ( bVerticalText )
+ {
+ if ( eTVA == SDRTEXTVERTADJUST_BLOCK )
+ {
+ Size aTextSize( pText->GetTextSize() );
+ aTextSize.AdjustWidth(nTextLeft + nTextRight );
+ aTextSize.AdjustHeight(nTextTop + nTextBottom );
+ if ( rTextRect.GetHeight() < aTextSize.Height() )
+ pTObj->SetMergedItem( SdrTextVertAdjustItem( SDRTEXTVERTADJUST_CENTER ) );
+ }
+ }
+ else
+ {
+ if ( eTHA == SDRTEXTHORZADJUST_BLOCK )
+ {
+ Size aTextSize( pText->GetTextSize() );
+ aTextSize.AdjustWidth(nTextLeft + nTextRight );
+ aTextSize.AdjustHeight(nTextTop + nTextBottom );
+ if ( rTextRect.GetWidth() < aTextSize.Width() )
+ pTObj->SetMergedItem( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER ) );
+ }
+ }
+ }
+ }
+ // rotate text with shape?
+ Degree100 nAngle = ( rObjData.nSpFlags & ShapeFlag::FlipV ) ? -mnFix16Angle : mnFix16Angle; // #72116# vertical flip -> rotate by using the other way
+ nAngle += nTextRotationAngle;
+
+ if ( dynamic_cast< const SdrObjCustomShape* >(pTObj) == nullptr )
+ {
+ if ( rObjData.nSpFlags & ShapeFlag::FlipV )
+ {
+ pTObj->Rotate( rTextRect.Center(), 18000_deg100, 0.0, -1.0 );
+ }
+ if ( rObjData.nSpFlags & ShapeFlag::FlipH )
+ nAngle = 36000_deg100 - nAngle;
+ if ( nAngle )
+ pTObj->NbcRotate( rObjData.aBoundRect.Center(), nAngle );
+ }
+ if ( pRet )
+ {
+ SdrObject* pGroup = new SdrObjGroup(*pSdrModel);
+ pGroup->GetSubList()->NbcInsertObject( pRet );
+ pGroup->GetSubList()->NbcInsertObject( pTObj );
+ pRet = pGroup;
+ }
+ else
+ pRet = pTObj;
+ }
+ }
+ }
+ }
+ else
+ {
+ if ( maShapeRecords.SeekToContent( rSt, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART ) )
+ {
+ maShapeRecords.Current()->SeekToBegOfRecord( rSt );
+ DffPropertyReader aSecPropSet( *this );
+ aSecPropSet.ReadPropSet( rSt, &rClientData );
+ sal_Int32 nTableProperties = aSecPropSet.GetPropertyValue( DFF_Prop_tableProperties, 0 );
+ if ( nTableProperties & 3 )
+ {
+ if ( aSecPropSet.SeekToContent( DFF_Prop_tableRowProperties, rSt ) )
+ {
+ sal_Int16 i, nReadRowCount = 0;
+ rSt.ReadInt16( nReadRowCount ).ReadInt16( i ).ReadInt16( i );
+ if (nReadRowCount > 0)
+ {
+ const size_t nMinRecordSize = 4;
+ const size_t nMaxRecords = rSt.remainingSize() / nMinRecordSize;
+
+ auto nRowCount = o3tl::make_unsigned(nReadRowCount);
+ if (nRowCount > nMaxRecords)
+ {
+ SAL_WARN("filter.ms", "Parsing error: " << nMaxRecords <<
+ " max possible entries, but " << nRowCount << " claimed, truncating");
+ nRowCount = nMaxRecords;
+ }
+ if (nRowCount > 0)
+ {
+ std::unique_ptr<sal_uInt32[]> pTableArry(new sal_uInt32[ nRowCount + 2 ]);
+ pTableArry[ 0 ] = nTableProperties;
+ pTableArry[ 1 ] = nRowCount;
+ for (decltype(nRowCount) nRow = 0; nRow < nRowCount; ++nRow)
+ rSt.ReadUInt32(pTableArry[nRow + 2]);
+ rData.pTableRowProperties = std::move(pTableArry);
+ }
+ }
+ }
+ }
+ }
+ }
+ if ( pRet ) // sj: #i38501#, and taking care of connections to group objects
+ {
+ if ( rObjData.nSpFlags & ShapeFlag::Background )
+ {
+ pRet->NbcSetSnapRect( tools::Rectangle( Point(), rData.pPage.page->GetSize() ) ); // set size
+ }
+ if (rPersistEntry.xSolverContainer)
+ {
+ for (auto & pPtr : rPersistEntry.xSolverContainer->aCList)
+ {
+ if ( rObjData.nShapeId == pPtr->nShapeC )
+ pPtr->pCObj = pRet;
+ else
+ {
+ SdrObject* pConnectObj = pRet;
+ if ( pOriginalObj && dynamic_cast< const SdrObjGroup* >(pRet) != nullptr )
+ { /* check if the original object from the escherimport is part of the group object,
+ if this is the case, we will use the original object to connect to */
+ SdrObjListIter aIter( *pRet, SdrIterMode::DeepWithGroups );
+ while( aIter.IsMore() )
+ {
+ SdrObject* pPartObj = aIter.Next();
+ if ( pPartObj == pOriginalObj )
+ {
+ pConnectObj = pPartObj;
+ break;
+ }
+ }
+ }
+ if ( rObjData.nShapeId == pPtr->nShapeA )
+ {
+ pPtr->pAObj = pConnectObj;
+ pPtr->nSpFlagsA = rObjData.nSpFlags;
+ }
+ if ( rObjData.nShapeId == pPtr->nShapeB )
+ {
+ pPtr->pBObj = pConnectObj;
+ pPtr->nSpFlagsB = rObjData.nSpFlags;
+ }
+ }
+ }
+ }
+ if ( rPersistEntry.ePageKind == PPT_MASTERPAGE )
+ { // maybe the escher clusterlist is not correct, but we have to got the right page by using the
+ // spMaster property, so we are patching the table
+ if ( rPersistEntry.nDrawingDgId != 0xffffffff )
+ {
+ sal_uInt32 nSec = ( rObjData.nShapeId >> 10 ) - 1;
+ if ( !maFidcls.empty() && ( nSec < mnIdClusters ) )
+ maFidcls[ nSec ].dgid = rPersistEntry.nDrawingDgId; // insert the correct drawing id;
+ }
+ }
+ if ( GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ) & 0x10 )
+ {
+ if (GetPropertyValue(DFF_Prop_fillType, mso_fillSolid) == mso_fillBackground)
+ {
+ rData.aBackgroundColoredObjects.push_back( pRet );
+ }
+ }
+ }
+ return pRet;
+}
+
+SdrPowerPointImport::SdrPowerPointImport( PowerPointImportParam& rParam, const OUString& rBaseURL ) :
+ SdrEscherImport ( rParam, rBaseURL ),
+ m_bOk ( rStCtrl.GetErrorCode() == ERRCODE_NONE ),
+ m_nPersistPtrCnt ( 0 ),
+ m_pDefaultSheet ( nullptr ),
+ m_nCurrentPageNum ( 0 ),
+ m_nDocStreamPos ( 0 ),
+ m_nPageColorsNum ( 0xFFFF ),
+ m_ePageColorsKind ( PPT_MASTERPAGE ),
+ m_eCurrentPageKind ( PPT_MASTERPAGE )
+{
+ if ( m_bOk )
+ {
+ nStreamLen = rStCtrl.TellEnd();
+
+ // try to allocate the UserEditAtom via CurrentUserAtom
+ sal_uInt32 nCurrentUserEdit = rParam.aCurrentUserAtom.nCurrentUserEdit;
+ if (nCurrentUserEdit && checkSeek(rStCtrl, nCurrentUserEdit))
+ {
+ ReadPptUserEditAtom( rStCtrl, m_aUserEditAtom );
+ }
+ if ( !m_aUserEditAtom.nOffsetPersistDirectory )
+ { // if there is no UserEditAtom try to search the last one
+
+ rStCtrl.Seek( 0 );
+ DffRecordManager aPptRecManager; // contains all first level container and atoms
+ aPptRecManager.Consume( rStCtrl, nStreamLen );
+ DffRecordHeader* pHd;
+ for ( pHd = aPptRecManager.Last(); pHd; pHd = aPptRecManager.Prev() )
+ {
+ if ( pHd->nRecType == PPT_PST_UserEditAtom )
+ {
+ pHd->SeekToBegOfRecord( rStCtrl );
+ ReadPptUserEditAtom( rStCtrl, m_aUserEditAtom );
+ break;
+ }
+ }
+ if ( !pHd )
+ m_bOk = false;
+ }
+ }
+ if ( rStCtrl.GetError() != ERRCODE_NONE )
+ m_bOk = false;
+
+ if ( m_bOk )
+ {
+ m_nPersistPtrCnt = m_aUserEditAtom.nMaxPersistWritten + 1;
+ if ( ( m_nPersistPtrCnt >> 2 ) > nStreamLen ) // sj: at least m_nPersistPtrCnt is not allowed to be greater than filesize
+ m_bOk = false; // (it should not be greater than the PPT_PST_PersistPtrIncrementalBlock, but
+ // we are reading this block later, so we do not have access yet)
+
+ if ( m_bOk && ( m_nPersistPtrCnt < ( SAL_MAX_UINT32 / sizeof( sal_uInt32 ) ) -1 ) )
+ m_pPersistPtr.reset( new (std::nothrow) sal_uInt32[ m_nPersistPtrCnt + 1 ] );
+ if ( !m_pPersistPtr )
+ m_bOk = false;
+ if ( m_bOk )
+ {
+ memset( m_pPersistPtr.get(), 0x00, (m_nPersistPtrCnt+1) * sizeof(sal_uInt32) );
+
+ // SJ: new search mechanism from bottom to top (Issue 21122)
+ PptUserEditAtom aCurrentEditAtom( m_aUserEditAtom );
+ sal_uInt32 nCurrentEditAtomStrmPos = aCurrentEditAtom.aHd.GetRecEndFilePos();
+ while( nCurrentEditAtomStrmPos )
+ {
+ sal_uInt32 nPersistIncPos = aCurrentEditAtom.nOffsetPersistDirectory;
+ if (nPersistIncPos && checkSeek(rStCtrl, nPersistIncPos))
+ {
+ DffRecordHeader aPersistHd;
+ ReadDffRecordHeader( rStCtrl, aPersistHd );
+ if ( aPersistHd.nRecType == PPT_PST_PersistPtrIncrementalBlock )
+ {
+ sal_uLong nPibLen = aPersistHd.GetRecEndFilePos();
+ while (m_bOk && rStCtrl.good() && (rStCtrl.Tell() < nPibLen))
+ {
+ sal_uInt32 nOfs(0);
+ rStCtrl.ReadUInt32( nOfs );
+ sal_uInt32 nCnt = nOfs;
+ nOfs &= 0x000FFFFF;
+ nCnt >>= 20;
+ while (m_bOk && rStCtrl.good() && (nCnt > 0) && (nOfs <= m_nPersistPtrCnt))
+ {
+ sal_uInt32 nPt(0);
+ rStCtrl.ReadUInt32( nPt );
+ if ( !m_pPersistPtr[ nOfs ] )
+ {
+ m_pPersistPtr[ nOfs ] = nPt;
+ if ( m_pPersistPtr[ nOfs ] > nStreamLen )
+ {
+ m_bOk = false;
+ OSL_FAIL("SdrPowerPointImport::Ctor(): Invalid Entry in Persist-Directory!");
+ }
+ }
+ nCnt--;
+ nOfs++;
+ }
+ if ( m_bOk && nCnt > 0 )
+ {
+ OSL_FAIL("SdrPowerPointImport::Ctor(): Not all entries of Persist-Directory read!");
+ m_bOk = false;
+ }
+ }
+ }
+ }
+ nCurrentEditAtomStrmPos = aCurrentEditAtom.nOffsetLastEdit < nCurrentEditAtomStrmPos ? aCurrentEditAtom.nOffsetLastEdit : 0;
+ if (nCurrentEditAtomStrmPos && checkSeek(rStCtrl, nCurrentEditAtomStrmPos))
+ {
+ ReadPptUserEditAtom( rStCtrl, aCurrentEditAtom );
+ }
+ }
+ }
+ }
+ if ( rStCtrl.GetError() != ERRCODE_NONE )
+ m_bOk = false;
+ if ( m_bOk )
+ { // check Document PersistEntry
+ m_nDocStreamPos = m_aUserEditAtom.nDocumentRef;
+ if ( m_nDocStreamPos > m_nPersistPtrCnt )
+ {
+ OSL_FAIL("SdrPowerPointImport::Ctor(): m_aUserEditAtom.nDocumentRef invalid!");
+ m_bOk = false;
+ }
+ }
+ if ( m_bOk )
+ { // check Document FilePos
+ m_nDocStreamPos = m_pPersistPtr[ m_nDocStreamPos ];
+ if ( m_nDocStreamPos >= nStreamLen )
+ {
+ OSL_FAIL("SdrPowerPointImport::Ctor(): m_nDocStreamPos >= nStreamLen!");
+ m_bOk = false;
+ }
+ }
+ if ( m_bOk )
+ {
+ rStCtrl.Seek( m_nDocStreamPos );
+ aDocRecManager.Consume( rStCtrl );
+
+ DffRecordHeader aDocHd;
+ ReadDffRecordHeader( rStCtrl, aDocHd );
+ // read DocumentAtom
+ DffRecordHeader aDocAtomHd;
+ ReadDffRecordHeader( rStCtrl, aDocAtomHd );
+ if ( aDocHd.nRecType == PPT_PST_Document && aDocAtomHd.nRecType == PPT_PST_DocumentAtom )
+ {
+ aDocAtomHd.SeekToBegOfRecord( rStCtrl );
+ ReadPptDocumentAtom( rStCtrl, aDocAtom );
+ }
+ else
+ m_bOk = false;
+
+ if ( m_bOk )
+ {
+ if (!m_xFonts)
+ ReadFontCollection();
+
+ // reading TxPF, TxSI
+ PPTTextParagraphStyleAtomInterpreter aTxPFStyle;
+ PPTTextSpecInfoAtomInterpreter aTxSIStyle; // styles (default language setting ... )
+
+ DffRecordHeader* pEnvHd = aDocRecManager.GetRecordHeader( PPT_PST_Environment );
+ if ( pEnvHd )
+ {
+ pEnvHd->SeekToContent( rStCtrl );
+ DffRecordHeader aTxPFStyleRecHd;
+ if ( SeekToRec( rStCtrl, PPT_PST_TxPFStyleAtom, pEnvHd->GetRecEndFilePos(), &aTxPFStyleRecHd ) )
+ aTxPFStyle.Read( rStCtrl, aTxPFStyleRecHd );
+
+ pEnvHd->SeekToContent( rStCtrl );
+ DffRecordHeader aTxSIStyleRecHd;
+ if ( SeekToRec( rStCtrl, PPT_PST_TxSIStyleAtom, pEnvHd->GetRecEndFilePos(), &aTxSIStyleRecHd ) )
+ {
+ aTxSIStyle.Read( rStCtrl, aTxSIStyleRecHd, PPT_PST_TxSIStyleAtom );
+#ifdef DBG_UTIL
+ if ( !aTxSIStyle.bValid )
+ {
+ if (!(rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT ))
+ {
+ OSL_FAIL( "SdrTextSpecInfoAtomInterpreter::Ctor(): parsing error, this document needs to be analysed (SJ)" );
+ }
+ }
+#endif
+ }
+ }
+
+ // TODO:: PPT_PST_TxPFStyleAtom
+
+ // read SlidePersists
+ m_pMasterPages.reset( new PptSlidePersistList );
+ m_pSlidePages.reset( new PptSlidePersistList );
+ m_pNotePages.reset( new PptSlidePersistList );
+
+ // now always creating the handout page, it will be the first in our masterpage list
+ std::unique_ptr<PptSlidePersistEntry> pE(new PptSlidePersistEntry);
+ pE->aPersistAtom.nPsrReference = aDocAtom.nHandoutMasterPersist;
+ pE->bHandoutMaster = true;
+ if ( !aDocAtom.nHandoutMasterPersist )
+ pE->bStarDrawFiller = true; // this is a dummy master page
+ m_pMasterPages->insert(m_pMasterPages->begin(), std::move(pE));
+
+ DffRecordHeader* pSlideListWithTextHd = aDocRecManager.GetRecordHeader( PPT_PST_SlideListWithText );
+ PptSlidePersistEntry* pPreviousPersist = nullptr;
+ DffRecordHeader* pSlideListHd = aDocRecManager.GetRecordHeader(PPT_PST_List);
+ sal_uLong nPSTList = 0;
+ if (pSlideListHd) nPSTList = pSlideListHd->GetRecBegFilePos();
+ sal_uInt16 nRealPageNum = 0;
+ // Normal PPT document has order of Master slides - Presentation slides - Note slides
+ // for document with the order of Master slides - Note slides - Presentation slides
+ // we need to swap the later two sections
+ bool notePresentationSwap = false;
+ for (sal_uInt16 nPageListNum = 0;
+ pSlideListWithTextHd && nPageListNum < 3; ++nPageListNum)
+ {
+ pSlideListWithTextHd->SeekToContent( rStCtrl );
+ PptSlidePersistList* pPageList = nullptr;
+ sal_uInt32 nSlideListWithTextHdEndOffset = pSlideListWithTextHd->GetRecEndFilePos();
+ nRealPageNum = nPageListNum;
+ while ( SeekToRec( rStCtrl, PPT_PST_SlidePersistAtom, nSlideListWithTextHdEndOffset ) )
+ {
+ if ( pPreviousPersist )
+ pPreviousPersist->nSlidePersistEndOffset = rStCtrl.Tell();
+ std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
+ ReadPptSlidePersistAtom( rStCtrl, pE2->aPersistAtom );
+ pE2->nSlidePersistStartOffset = rStCtrl.Tell();
+ // Note/Presentation section swap
+ if (nPageListNum == 1 && pE2->nSlidePersistStartOffset < nPSTList)
+ {
+ notePresentationSwap = true;
+ }
+ if (notePresentationSwap)
+ {
+ if (nPageListNum == 1) nRealPageNum = 2;
+ else if (nPageListNum == 2) nRealPageNum = 1;
+ }
+
+ pE2->ePageKind = PptPageKind(nRealPageNum);
+ pPreviousPersist = pE2.get();
+ if (!pPageList)
+ {
+ pPageList = GetPageList(PptPageKind(nRealPageNum));
+ }
+ pPageList->push_back(std::move(pE2));
+ }
+ if ( pPreviousPersist )
+ pPreviousPersist->nSlidePersistEndOffset = nSlideListWithTextHdEndOffset;
+ pSlideListWithTextHd = aDocRecManager.GetRecordHeader( PPT_PST_SlideListWithText, SEEK_FROM_CURRENT );
+ }
+
+ // we will ensure that there is at least one master page
+ if (m_pMasterPages->size() == 1) // -> there is only a handout page available
+ {
+ std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
+ pE2->bStarDrawFiller = true; // this is a dummy master page
+ m_pMasterPages->insert(m_pMasterPages->begin() + 1, std::move(pE2));
+ }
+
+ // now we will insert at least one notes master for each master page
+ sal_uInt16 nMasterPage;
+ sal_uInt16 nMasterPages = m_pMasterPages->size() - 1;
+ for ( nMasterPage = 0; nMasterPage < nMasterPages; nMasterPage++ )
+ {
+ std::unique_ptr<PptSlidePersistEntry> pE2(new PptSlidePersistEntry);
+ pE2->bNotesMaster = true;
+ pE2->bStarDrawFiller = true; // this is a dummy master page
+ if ( !nMasterPage && aDocAtom.nNotesMasterPersist )
+ { // special treatment for the first notes master
+ pE2->aPersistAtom.nPsrReference = aDocAtom.nNotesMasterPersist;
+ pE2->bStarDrawFiller = false; // this is a dummy master page
+ }
+ m_pMasterPages->insert(m_pMasterPages->begin() + ((nMasterPage + 1) << 1), std::move(pE2));
+ }
+
+ // read for each page the SlideAtom respectively the NotesAtom if it exists
+ for (sal_uInt16 nPageListNum = 0; nPageListNum < 3; ++nPageListNum)
+ {
+ PptSlidePersistList* pPageList = GetPageList( PptPageKind( nPageListNum ) );
+ for ( size_t nPageNum = 0; nPageNum < pPageList->size(); nPageNum++ )
+ {
+ PptSlidePersistEntry& rE2 = (*pPageList)[ nPageNum ];
+ sal_uLong nPersist = rE2.aPersistAtom.nPsrReference;
+ if ( ( nPersist > 0 ) && ( nPersist < m_nPersistPtrCnt ) )
+ {
+ sal_uLong nFPos = m_pPersistPtr[ nPersist ];
+ if ( nFPos < nStreamLen )
+ {
+ rStCtrl.Seek( nFPos );
+ DffRecordHeader aSlideHd;
+ ReadDffRecordHeader( rStCtrl, aSlideHd );
+ if ( SeekToRec( rStCtrl, PPT_PST_SlideAtom, aSlideHd.GetRecEndFilePos() ) )
+ ReadPptSlideAtom( rStCtrl, rE2.aSlideAtom );
+ else if ( SeekToRec( rStCtrl, PPT_PST_NotesAtom, aSlideHd.GetRecEndFilePos() ) )
+ ReadPptNotesAtom( rStCtrl, rE2.aNotesAtom );
+ aSlideHd.SeekToContent( rStCtrl );
+
+ DffRecordHeader aPPTDrawingHd;
+ if ( SeekToRec( rStCtrl, PPT_PST_PPDrawing, aSlideHd.GetRecEndFilePos(), &aPPTDrawingHd ) )
+ {
+ DffRecordHeader aPPTDgContainer;
+ if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, aPPTDrawingHd.GetRecEndFilePos(), &aPPTDgContainer ) )
+ {
+ if ( SeekToRec( rStCtrl, DFF_msofbtDg, aPPTDrawingHd.GetRecEndFilePos() ) )
+ {
+ DffRecordHeader aDgRecordHeader;
+ ReadDffRecordHeader( rStCtrl, aDgRecordHeader );
+ rE2.nDrawingDgId = aDgRecordHeader.nRecInstance;
+ aDgRecordHeader.SeekToEndOfRecord( rStCtrl );
+ }
+ if ( SeekToRec( rStCtrl, DFF_msofbtSolverContainer, aPPTDgContainer.GetRecEndFilePos() ) )
+ {
+ rE2.xSolverContainer.reset(new SvxMSDffSolverContainer);
+ ReadSvxMSDffSolverContainer(rStCtrl, *rE2.xSolverContainer);
+ }
+ aPPTDgContainer.SeekToBegOfRecord( rStCtrl );
+ SetDgContainer( rStCtrl ); // set this, so that the escherimport is knowing of our drawings
+ }
+ }
+ // office xp is supporting more than one stylesheet
+ if ( ( rE2.ePageKind == PPT_MASTERPAGE ) && ( rE2.aSlideAtom.nMasterId == 0 ) && !rE2.bNotesMaster )
+ {
+ PPTTextSpecInfo aTxSI( 0 );
+ if ( aTxSIStyle.bValid && !aTxSIStyle.aList.empty() )
+ aTxSI = aTxSIStyle.aList[ 0 ];
+
+ rE2.xStyleSheet = std::make_unique<PPTStyleSheet>(aSlideHd, rStCtrl, *this, aTxPFStyle, aTxSI);
+ m_pDefaultSheet = rE2.xStyleSheet.get();
+ }
+ if ( SeekToRec( rStCtrl, PPT_PST_ColorSchemeAtom, aSlideHd.GetRecEndFilePos() ) )
+ ReadPptColorSchemeAtom( rStCtrl, rE2.aColorScheme );
+ else
+ {
+ OSL_FAIL( "SdrPowerPointImport::Ctor(): could not get SlideColorScheme! (SJ)" );
+ }
+ }
+ else
+ {
+ OSL_FAIL("SdrPowerPointImport::Ctor(): Persist entry is flawed! (SJ)");
+ }
+ }
+ }
+ }
+ DffRecordHeader* pHeadersFootersHd = aDocRecManager.GetRecordHeader( PPT_PST_HeadersFooters );
+ if ( pHeadersFootersHd )
+ {
+ HeaderFooterEntry aNormalMaster, aNotesMaster;
+ for ( ; pHeadersFootersHd; pHeadersFootersHd = aDocRecManager.GetRecordHeader( PPT_PST_HeadersFooters, SEEK_FROM_CURRENT ) )
+ {
+ if ( pHeadersFootersHd->nRecInstance == 3 ) // normal master
+ ImportHeaderFooterContainer( *pHeadersFootersHd, aNormalMaster );
+ else if ( pHeadersFootersHd->nRecInstance == 4 ) // notes master
+ ImportHeaderFooterContainer( *pHeadersFootersHd, aNotesMaster );
+ }
+ for (size_t i = 0; i < m_pMasterPages->size(); i++)
+ {
+ if ((*m_pMasterPages)[ i ].bNotesMaster)
+ (*m_pMasterPages)[ i ].xHeaderFooterEntry.reset(new HeaderFooterEntry(aNotesMaster));
+ else
+ (*m_pMasterPages)[ i ].xHeaderFooterEntry.reset(new HeaderFooterEntry(aNormalMaster));
+ }
+ }
+ }
+ }
+ if ( ( rStCtrl.GetError() != ERRCODE_NONE ) || ( m_pDefaultSheet == nullptr ) )
+ m_bOk = false;
+ m_pPPTStyleSheet = m_pDefaultSheet;
+ rStCtrl.Seek( 0 );
+}
+
+SdrPowerPointImport::~SdrPowerPointImport()
+{
+ m_pMasterPages.reset();
+ m_pSlidePages.reset();
+ m_pNotePages.reset();
+}
+
+bool PPTConvertOCXControls::ReadOCXStream( tools::SvRef<SotStorage>& rSrc,
+ css::uno::Reference< css::drawing::XShape > *pShapeRef )
+{
+ bool bRes = false;
+ uno::Reference< form::XFormComponent > xFComp;
+ if ( mpPPTImporter && mpPPTImporter->ReadFormControl( rSrc, xFComp ) )
+ {
+ if ( xFComp.is() )
+ {
+ css::awt::Size aSz; // not used in import
+ bRes = InsertControl( xFComp, aSz,pShapeRef, false/*bFloatingCtrl*/);
+ }
+ }
+ return bRes;
+}
+
+bool PPTConvertOCXControls::InsertControl(
+ const css::uno::Reference< css::form::XFormComponent > &rFComp,
+ const css::awt::Size& rSize,
+ css::uno::Reference< css::drawing::XShape > *pShape,
+ bool /*bFloatingCtrl*/)
+{
+ bool bRetValue = false;
+ try
+ {
+ css::uno::Reference< css::drawing::XShape > xShape;
+
+ const css::uno::Reference< css::container::XIndexContainer > & rFormComps =
+ GetFormComps();
+
+ css::uno::Any aTmp( &rFComp, cppu::UnoType<css::form::XFormComponent>::get() );
+
+ rFormComps->insertByIndex( rFormComps->getCount(), aTmp );
+
+ const css::uno::Reference< css::lang::XMultiServiceFactory > & rServiceFactory =
+ GetServiceFactory();
+ if( rServiceFactory.is() )
+ {
+ css::uno::Reference< css::uno::XInterface > xCreate = rServiceFactory
+ ->createInstance( "com.sun.star.drawing.ControlShape" );
+ if( xCreate.is() )
+ {
+ xShape.set(xCreate, css::uno::UNO_QUERY);
+ if ( xShape.is() )
+ {
+ xShape->setSize(rSize);
+ // set the Control-Model at the Control-Shape
+ css::uno::Reference< css::drawing::XControlShape > xControlShape( xShape,
+ css::uno::UNO_QUERY );
+ css::uno::Reference< css::awt::XControlModel > xControlModel( rFComp,
+ css::uno::UNO_QUERY );
+ if ( xControlShape.is() && xControlModel.is() )
+ {
+ xControlShape->setControl( xControlModel );
+ if (pShape)
+ *pShape = xShape;
+ bRetValue = true;
+ }
+ }
+ }
+ }
+ }
+ catch( ... )
+ {
+ bRetValue = false;
+ }
+ return bRetValue;
+};
+void PPTConvertOCXControls::GetDrawPage()
+{
+ if( xDrawPage.is() || !mxModel.is() )
+ return;
+
+ css::uno::Reference< css::drawing::XDrawPages > xDrawPages;
+ switch( ePageKind )
+ {
+ case PPT_SLIDEPAGE :
+ case PPT_NOTEPAGE :
+ {
+ css::uno::Reference< css::drawing::XDrawPagesSupplier >
+ xDrawPagesSupplier( mxModel, css::uno::UNO_QUERY);
+ if ( xDrawPagesSupplier.is() )
+ xDrawPages = xDrawPagesSupplier->getDrawPages();
+ }
+ break;
+
+ case PPT_MASTERPAGE :
+ {
+ css::uno::Reference< css::drawing::XMasterPagesSupplier >
+ xMasterPagesSupplier( mxModel, css::uno::UNO_QUERY);
+ if ( xMasterPagesSupplier.is() )
+ xDrawPages = xMasterPagesSupplier->getMasterPages();
+ }
+ break;
+ }
+ if ( xDrawPages.is() && xDrawPages->getCount() )
+ {
+ xDrawPages->getCount();
+ css::uno::Any aAny( xDrawPages->getByIndex( xDrawPages->getCount() - 1 ) );
+ aAny >>= xDrawPage;
+ }
+}
+
+static bool SdrPowerPointOLEDecompress( SvStream& rOutput, SvStream& rInput, sal_uInt32 nInputSize )
+{
+ sal_uInt32 nOldPos = rInput.Tell();
+ std::unique_ptr<char[]> pBuf(new char[ nInputSize ]);
+ rInput.ReadBytes(pBuf.get(), nInputSize);
+ ZCodec aZCodec( 0x8000, 0x8000 );
+ aZCodec.BeginCompression();
+ SvMemoryStream aSource( pBuf.get(), nInputSize, StreamMode::READ );
+ aZCodec.Decompress( aSource, rOutput );
+ const bool bSuccess(0 != aZCodec.EndCompression());
+ rInput.Seek( nOldPos );
+ return bSuccess;
+}
+
+// #i32596# - add new parameter <_nCalledByGroup>
+SdrObject* SdrPowerPointImport::ImportOLE( sal_uInt32 nOLEId,
+ const Graphic& rGraf,
+ const tools::Rectangle& rBoundRect,
+ const tools::Rectangle& rVisArea,
+ const int /*_nCalledByGroup*/ ) const
+{
+ SdrObject* pRet = nullptr;
+
+ sal_uInt32 nOldPos = rStCtrl.Tell();
+
+ Graphic aGraphic( rGraf );
+
+ if ( const_cast<SdrPowerPointImport*>(this)->maShapeRecords.SeekToContent( rStCtrl, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
+ {
+ DffRecordHeader aPlaceHd;
+
+ auto nEndRecPos = SanitizeEndPos(rStCtrl, const_cast<SdrPowerPointImport*>(this)->maShapeRecords.Current()->GetRecEndFilePos());
+ while ( ( rStCtrl.GetError() == ERRCODE_NONE )
+ && ( rStCtrl.Tell() < nEndRecPos ) )
+ {
+ ReadDffRecordHeader( rStCtrl, aPlaceHd );
+ if ( aPlaceHd.nRecType == PPT_PST_RecolorInfoAtom )
+ {
+ const_cast<SdrPowerPointImport*>(this)->RecolorGraphic( rStCtrl, aPlaceHd.nRecLen, aGraphic );
+ break;
+ }
+ else
+ {
+ if (!aPlaceHd.SeekToEndOfRecord(rStCtrl))
+ break;
+ }
+ }
+ }
+
+ for (PPTOleEntry& rOe : const_cast<SdrPowerPointImport*>(this)->aOleObjectList)
+ {
+ if ( rOe.nId != nOLEId )
+ continue;
+
+ rStCtrl.Seek( rOe.nRecHdOfs );
+
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rStCtrl, aHd );
+
+ sal_uInt32 nLen = aHd.nRecLen - 4;
+ if ( static_cast<sal_Int32>(nLen) > 0 )
+ {
+ bool bSuccess = false;
+
+ rStCtrl.SeekRel( 4 );
+
+ ::utl::TempFile aTmpFile;
+ aTmpFile.EnableKillingFile();
+
+ if ( aTmpFile.IsValid() )
+ {
+ SvStream* pDest = aTmpFile.GetStream(StreamMode::TRUNC | StreamMode::WRITE);
+ if (pDest)
+ {
+ bSuccess = SdrPowerPointOLEDecompress( *pDest, rStCtrl, nLen );
+ }
+ aTmpFile.CloseStream();
+ }
+ if ( bSuccess )
+ {
+ SvStream* pDest = aTmpFile.GetStream(StreamMode::READ);
+ Storage* pObjStor = pDest ? new Storage( *pDest, true ) : nullptr;
+ if (pObjStor)
+ {
+ tools::SvRef<SotStorage> xObjStor( new SotStorage( pObjStor ) );
+ if ( xObjStor.is() && !xObjStor->GetError() )
+ {
+ if ( xObjStor->GetClassName() == SvGlobalName() )
+ {
+ xObjStor->SetClass( SvGlobalName( pObjStor->GetClassId() ), pObjStor->GetFormat(), pObjStor->GetUserName() );
+ }
+ tools::SvRef<SotStorageStream> xSrcTst = xObjStor->OpenSotStream( "\1Ole" );
+ if ( xSrcTst.is() )
+ {
+ sal_uInt8 aTestA[ 10 ];
+ bool bGetItAsOle = (sizeof(aTestA) == xSrcTst->ReadBytes(aTestA, sizeof(aTestA)));
+ if ( !bGetItAsOle )
+ { // maybe there is a contents stream in here
+ xSrcTst = xObjStor->OpenSotStream( "Contents", StreamMode::READWRITE | StreamMode::NOCREATE );
+ bGetItAsOle = (xSrcTst.is() &&
+ sizeof(aTestA) == xSrcTst->ReadBytes(aTestA, sizeof(aTestA)));
+ }
+ if ( bGetItAsOle )
+ {
+ OUString aNm;
+ // if ( nSvxMSDffOLEConvFlags )
+ {
+ uno::Reference < embed::XStorage > xDestStorage( rOe.pShell->GetStorage() );
+ uno::Reference < embed::XEmbeddedObject > xObj =
+ CheckForConvertToSOObj(nSvxMSDffOLEConvFlags, *xObjStor, xDestStorage, rGraf, rVisArea, maBaseURL);
+ if( xObj.is() )
+ {
+ rOe.pShell->getEmbeddedObjectContainer().InsertEmbeddedObject( xObj, aNm );
+
+ svt::EmbeddedObjectRef aObj( xObj, rOe.nAspect );
+
+ // TODO/LATER: need MediaType for Graphic
+ aObj.SetGraphic( rGraf, OUString() );
+ pRet = new SdrOle2Obj(
+ *pSdrModel,
+ aObj,
+ aNm,
+ rBoundRect);
+ }
+ }
+ if ( !pRet && ( rOe.nType == PPT_PST_ExControl ) )
+ {
+ uno::Reference< frame::XModel > xModel( rOe.pShell->GetModel() );
+ PPTConvertOCXControls aPPTConvertOCXControls( this, xModel, m_eCurrentPageKind );
+ css::uno::Reference< css::drawing::XShape > xShape;
+ if ( aPPTConvertOCXControls.ReadOCXStream( xObjStor, &xShape ) )
+ pRet = SdrObject::getSdrObjectFromXShape(xShape);
+
+ }
+ if ( !pRet )
+ {
+ aNm = rOe.pShell->getEmbeddedObjectContainer().CreateUniqueObjectName();
+
+ // object is not an own object
+ const css::uno::Reference < css::embed::XStorage >& rStorage = rOe.pShell->GetStorage();
+ if (rStorage.is())
+ {
+ tools::SvRef<SotStorage> xTarget = SotStorage::OpenOLEStorage(rStorage, aNm, StreamMode::READWRITE);
+ if (xObjStor.is() && xTarget.is())
+ {
+ xObjStor->CopyTo(xTarget.get());
+ if (!xTarget->GetError())
+ xTarget->Commit();
+ }
+ xTarget.clear();
+ }
+
+ uno::Reference < embed::XEmbeddedObject > xObj =
+ rOe.pShell->getEmbeddedObjectContainer().GetEmbeddedObject( aNm );
+ if ( xObj.is() )
+ {
+ if ( rOe.nAspect != embed::Aspects::MSOLE_ICON )
+ {
+ //TODO/LATER: keep on hacking?!
+ // we don't want to be modified
+ //xInplaceObj->EnableSetModified( sal_False );
+ if ( rVisArea.IsEmpty() )
+ {
+ MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( rOe.nAspect ) );
+ Size aSize( OutputDevice::LogicToLogic( aGraphic.GetPrefSize(),
+ aGraphic.GetPrefMapMode(), MapMode( aMapUnit ) ) );
+
+ awt::Size aSz;
+ aSz.Width = aSize.Width();
+ aSz.Height = aSize.Height();
+ xObj->setVisualAreaSize( rOe.nAspect, aSz );
+ }
+ else
+ {
+ awt::Size aSize( rVisArea.GetSize().Width(), rVisArea.GetSize().Height() );
+ xObj->setVisualAreaSize( rOe.nAspect, aSize );
+ }
+ //xInplaceObj->EnableSetModified( sal_True );
+ }
+
+ svt::EmbeddedObjectRef aObj( xObj, rOe.nAspect );
+
+ // TODO/LATER: need MediaType for Graphic
+ aObj.SetGraphic( aGraphic, OUString() );
+
+ pRet = new SdrOle2Obj(
+ *pSdrModel,
+ aObj,
+ aNm,
+ rBoundRect);
+ }
+ }
+ }
+ }
+ }
+ }
+ aTmpFile.CloseStream();
+ }
+ }
+ }
+ rStCtrl.Seek( nOldPos );
+
+ return pRet;
+}
+
+std::unique_ptr<SvMemoryStream> SdrPowerPointImport::ImportExOleObjStg( sal_uInt32 nPersistPtr, sal_uInt32& nOleId ) const
+{
+ std::unique_ptr<SvMemoryStream> pRet;
+ if ( nPersistPtr && ( nPersistPtr < m_nPersistPtrCnt ) )
+ {
+ sal_uInt32 nOldPos, nOfs = m_pPersistPtr[ nPersistPtr ];
+ nOldPos = rStCtrl.Tell();
+ rStCtrl.Seek( nOfs );
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rStCtrl, aHd );
+ if ( aHd.nRecType == DFF_PST_ExOleObjStg )
+ {
+ sal_uInt32 nLen = aHd.nRecLen - 4;
+ if ( static_cast<sal_Int32>(nLen) > 0 )
+ {
+ rStCtrl.ReadUInt32( nOleId );
+ pRet.reset(new SvMemoryStream);
+ ZCodec aZCodec( 0x8000, 0x8000 );
+ aZCodec.BeginCompression();
+ aZCodec.Decompress( rStCtrl, *pRet );
+ if ( !aZCodec.EndCompression() )
+ {
+ pRet.reset();
+ }
+ }
+ }
+ rStCtrl.Seek( nOldPos );
+ }
+ return pRet;
+}
+
+void SdrPowerPointImport::SeekOle( SfxObjectShell* pShell, sal_uInt32 nFilterOptions )
+{
+ if ( !pShell )
+ return;
+
+ DffRecordHeader* pHd;
+
+ sal_uInt32 nOldPos = rStCtrl.Tell();
+ if ( nFilterOptions & 1 )
+ {
+ pHd = aDocRecManager.GetRecordHeader( PPT_PST_List );
+ if ( pHd )
+ {
+ // we try to locate the basic atom
+ pHd->SeekToContent( rStCtrl );
+ if ( SeekToRec( rStCtrl, PPT_PST_VBAInfo, pHd->GetRecEndFilePos(), pHd ) )
+ {
+ if ( SeekToRec( rStCtrl, PPT_PST_VBAInfoAtom, pHd->GetRecEndFilePos(), pHd ) )
+ {
+ sal_uInt32 nPersistPtr, nIDoNotKnow1, nIDoNotKnow2;
+ rStCtrl.ReadUInt32( nPersistPtr )
+ .ReadUInt32( nIDoNotKnow1 )
+ .ReadUInt32( nIDoNotKnow2 );
+
+ sal_uInt32 nOleId;
+ std::unique_ptr<SvMemoryStream> pBas = ImportExOleObjStg( nPersistPtr, nOleId );
+ if ( pBas )
+ {
+ tools::SvRef<SotStorage> xSource( new SotStorage( pBas.release(), true ) );
+ tools::SvRef<SotStorage> xDest( new SotStorage( new SvMemoryStream(), true ) );
+ if ( xSource.is() && xDest.is() )
+ {
+ // is this a visual basic storage ?
+ tools::SvRef<SotStorage> xSubStorage = xSource->OpenSotStorage( "VBA",
+ StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL );
+ if( xSubStorage.is() && ( ERRCODE_NONE == xSubStorage->GetError() ) )
+ {
+ tools::SvRef<SotStorage> xMacros = xDest->OpenSotStorage( "MACROS" );
+ if ( xMacros.is() )
+ {
+ SvStorageInfoList aList;
+ xSource->FillInfoList( &aList );
+ SvStorageInfoList::size_type i;
+
+ bool bCopied = true;
+ for ( i = 0; i < aList.size(); i++ ) // copy all entries
+ {
+ const SvStorageInfo& rInfo = aList[ i ];
+ if ( !xSource->CopyTo( rInfo.GetName(), xMacros.get(), rInfo.GetName() ) )
+ bCopied = false;
+ }
+ if ( i && bCopied )
+ {
+ uno::Reference < embed::XStorage > xDoc( pShell->GetStorage() );
+ if ( xDoc.is() )
+ {
+ tools::SvRef<SotStorage> xVBA = SotStorage::OpenOLEStorage( xDoc, SvxImportMSVBasic::GetMSBasicStorageName() );
+ if ( xVBA.is() && ( xVBA->GetError() == ERRCODE_NONE ) )
+ {
+ tools::SvRef<SotStorage> xSubVBA = xVBA->OpenSotStorage( "_MS_VBA_Overhead" );
+ if ( xSubVBA.is() && ( xSubVBA->GetError() == ERRCODE_NONE ) )
+ {
+ tools::SvRef<SotStorageStream> xOriginal = xSubVBA->OpenSotStream( "_MS_VBA_Overhead2" );
+ if ( xOriginal.is() && ( xOriginal->GetError() == ERRCODE_NONE ) )
+ {
+ if ( nPersistPtr && ( nPersistPtr < m_nPersistPtrCnt ) )
+ {
+ rStCtrl.Seek( m_pPersistPtr[ nPersistPtr ] );
+ ReadDffRecordHeader( rStCtrl, *pHd );
+
+ xOriginal->WriteUInt32( nIDoNotKnow1 )
+ .WriteUInt32( nIDoNotKnow2 );
+
+ sal_uInt32 nToCopy, nBufSize;
+ nToCopy = pHd->nRecLen;
+ std::unique_ptr<sal_uInt8[]> pBuf(new sal_uInt8[ 0x40000 ]); // 256KB Buffer
+ while ( nToCopy )
+ {
+ nBufSize = ( nToCopy >= 0x40000 ) ? 0x40000 : nToCopy;
+ rStCtrl.ReadBytes(pBuf.get(), nBufSize);
+ xOriginal->WriteBytes(pBuf.get(), nBufSize);
+ nToCopy -= nBufSize;
+ }
+ }
+ }
+ }
+ }
+ xVBA->Commit();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ pHd = aDocRecManager.GetRecordHeader( PPT_PST_ExObjList );
+ if ( pHd )
+ {
+ DffRecordHeader* pExEmbed = nullptr;
+
+ pHd->SeekToBegOfRecord( rStCtrl );
+ DffRecordManager aExObjListManager( rStCtrl );
+ sal_uInt16 i, nRecType(PPT_PST_ExEmbed);
+
+ for ( i = 0; i < 2; i++ )
+ {
+ switch ( i )
+ {
+ case 0 : nRecType = PPT_PST_ExEmbed; break;
+ case 1 : nRecType = PPT_PST_ExControl; break;
+ }
+ for ( pExEmbed = aExObjListManager.GetRecordHeader( nRecType );
+ pExEmbed; pExEmbed = aExObjListManager.GetRecordHeader( nRecType, SEEK_FROM_CURRENT ) )
+ {
+ pExEmbed->SeekToContent( rStCtrl );
+
+ DffRecordHeader aExOleAtHd;
+ if ( SeekToRec( rStCtrl, PPT_PST_ExOleObjAtom, pExEmbed->GetRecEndFilePos(), &aExOleAtHd ) )
+ {
+ PptExOleObjAtom aAt;
+ ReadPptExOleObjAtom( rStCtrl, aAt );
+
+ if ( aAt.nPersistPtr && ( aAt.nPersistPtr < m_nPersistPtrCnt ) )
+ {
+ rStCtrl.Seek( m_pPersistPtr[ aAt.nPersistPtr ] );
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rStCtrl, aHd );
+ if ( aHd.nRecType == DFF_PST_ExOleObjStg )
+ {
+ sal_uInt32 nId;
+ rStCtrl.ReadUInt32( nId );
+ aOleObjectList.emplace_back(
+ aAt.nId, aHd.nFilePos, pShell, nRecType, aAt.nAspect );
+ }
+ }
+ }
+ }
+ }
+ }
+ rStCtrl.Seek( nOldPos );
+}
+
+bool SdrPowerPointImport::ReadFontCollection()
+{
+ bool bRet = false;
+ DffRecordHeader* pEnvHd = aDocRecManager.GetRecordHeader( PPT_PST_Environment );
+ if ( pEnvHd )
+ {
+ sal_uInt64 nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it later
+ pEnvHd->SeekToContent( rStCtrl );
+ DffRecordHeader aListHd;
+ if ( SeekToRec( rStCtrl, PPT_PST_FontCollection, pEnvHd->GetRecEndFilePos(), &aListHd ) )
+ {
+ sal_uInt16 nCount2 = 0;
+ while ( SeekToRec( rStCtrl, PPT_PST_FontEntityAtom, aListHd.GetRecEndFilePos() ) )
+ {
+ bRet = true;
+ if (!m_xFonts)
+ m_xFonts.emplace();
+ PptFontEntityAtom aFontAtom;
+ ReadPptFontEntityAtom( rStCtrl, aFontAtom );
+
+ vcl::Font aFont;
+ aFont.SetCharSet( aFontAtom.eCharSet );
+ aFont.SetFamilyName( aFontAtom.aName );
+ aFont.SetFamily( aFontAtom.eFamily );
+ aFont.SetPitch( aFontAtom.ePitch );
+ aFont.SetFontHeight( 100 );
+
+ // following block is necessary, because our old PowerPoint export did not set the
+ // correct charset
+ if ( aFontAtom.aName.equalsIgnoreAsciiCase( "Wingdings" ) ||
+ aFontAtom.aName.equalsIgnoreAsciiCase( "Wingdings 2" ) ||
+ aFontAtom.aName.equalsIgnoreAsciiCase( "Wingdings 3" ) ||
+ aFontAtom.aName.equalsIgnoreAsciiCase( "Monotype Sorts" ) ||
+ aFontAtom.aName.equalsIgnoreAsciiCase( "Monotype Sorts 2" ) ||
+ aFontAtom.aName.equalsIgnoreAsciiCase( "Webdings" ) ||
+ aFontAtom.aName.equalsIgnoreAsciiCase( "StarBats" ) ||
+ aFontAtom.aName.equalsIgnoreAsciiCase( "StarMath" ) ||
+ aFontAtom.aName.equalsIgnoreAsciiCase( "ZapfDingbats" ) )
+ {
+ aFontAtom.eCharSet = RTL_TEXTENCODING_SYMBOL;
+ };
+ m_xFonts->insert(m_xFonts->begin() + nCount2++, std::move(aFontAtom));
+ }
+ }
+ rStCtrl.Seek( nOldFPos ); // restore FilePos
+ }
+ return bRet;
+}
+
+PptSlidePersistList* SdrPowerPointImport::GetPageList(PptPageKind ePageKind) const
+{
+ switch (ePageKind)
+ {
+ case PPT_MASTERPAGE:
+ return m_pMasterPages.get();
+ case PPT_SLIDEPAGE:
+ return m_pSlidePages.get();
+ case PPT_NOTEPAGE:
+ return m_pNotePages.get();
+ }
+ return nullptr;
+}
+
+SdrOutliner* SdrPowerPointImport::GetDrawOutliner( SdrTextObj const * pSdrText )
+{
+ if ( !pSdrText )
+ return nullptr;
+ else
+ return &pSdrText->ImpGetDrawOutliner();
+}
+
+
+SdrObject* SdrPowerPointImport::ReadObjText( PPTTextObj* pTextObj, SdrObject* pSdrObj, SdPageCapsule pPage ) const
+{
+ SdrTextObj* pText = dynamic_cast<SdrTextObj*>( pSdrObj );
+ if ( pText )
+ {
+ if ( !ApplyTextObj( pTextObj, pText, pPage, nullptr, nullptr ) )
+ pSdrObj = nullptr;
+ }
+ return pSdrObj;
+}
+
+SdrObject* SdrPowerPointImport::ApplyTextObj( PPTTextObj* pTextObj, SdrTextObj* pSdrText, SdPageCapsule /*pPage*/,
+ SfxStyleSheet* pSheet, SfxStyleSheet** ppStyleSheetAry ) const
+{
+ SdrTextObj* pText = pSdrText;
+ if ( pTextObj->Count() )
+ {
+ TSS_Type nDestinationInstance = pTextObj->GetDestinationInstance() ;
+ SdrOutliner& rOutliner = pText->ImpGetDrawOutliner();
+ bool bUndoEnabled = rOutliner.IsUndoEnabled();
+ rOutliner.EnableUndo(false);
+
+ if ( ( pText->GetObjInventor() == SdrInventor::Default ) && ( pText->GetObjIdentifier() == SdrObjKind::TitleText ) ) // Outliner-Style for Title-Text object?!? (->of DL)
+ rOutliner.Init( OutlinerMode::TitleObject ); // Outliner reset
+
+ bool bOldUpdateMode = rOutliner.SetUpdateLayout( false );
+ if ( pSheet )
+ {
+ if ( rOutliner.GetStyleSheet( 0 ) != pSheet )
+ rOutliner.SetStyleSheet( 0, pSheet );
+ }
+ rOutliner.SetVertical( pTextObj->GetVertical() );
+ for ( PPTParagraphObj* pPara = pTextObj->First(); pPara; pPara = pTextObj->Next() )
+ {
+ sal_uInt32 nTextSize = pPara->GetTextSize();
+ if ( ! ( nTextSize & 0xffff0000 ) )
+ {
+ PPTPortionObj* pPortion;
+ std::unique_ptr<sal_Unicode[]> pParaText(new sal_Unicode[ nTextSize ]);
+ sal_Int32 nCurrentIndex = 0;
+ for ( pPortion = pPara->First(); pPortion; pPortion = pPara->Next() )
+ {
+ if ( pPortion->mpFieldItem )
+ pParaText[ nCurrentIndex++ ] = ' ';
+ else
+ {
+ sal_Int32 nCharacters = pPortion->Count();
+ const sal_Unicode* pSource = pPortion->maString.getStr();
+ sal_Unicode* pDest = pParaText.get() + nCurrentIndex;
+
+ sal_uInt32 nFont;
+ pPortion->GetAttrib( PPT_CharAttr_Font, nFont, pTextObj->GetInstance() );
+ const PptFontEntityAtom* pFontEnityAtom = GetFontEnityAtom( nFont );
+ if ( pFontEnityAtom && ( pFontEnityAtom->eCharSet == RTL_TEXTENCODING_SYMBOL ) )
+ {
+ sal_Unicode nUnicode;
+ for (sal_Int32 i = 0; i < nCharacters; i++ )
+ {
+ nUnicode = pSource[ i ];
+ if ( ! ( nUnicode & 0xff00 ) )
+ nUnicode |= 0xf000;
+ pDest[ i ] = nUnicode;
+ }
+ }
+ else
+ memcpy( pDest, pSource, nCharacters << 1 );
+ nCurrentIndex += nCharacters;
+ }
+ }
+ sal_Int32 nParaIndex = pTextObj->GetCurrentIndex();
+ SfxStyleSheet* pS = ppStyleSheetAry ? ppStyleSheetAry[ pPara->mxParaSet->mnDepth ] : pSheet;
+
+ ESelection aSelection( nParaIndex, 0, nParaIndex, 0 );
+ rOutliner.Insert( OUString(), nParaIndex, pPara->mxParaSet->mnDepth );
+ rOutliner.QuickInsertText( OUString(pParaText.get(), nCurrentIndex), aSelection );
+ rOutliner.SetParaAttribs( nParaIndex, rOutliner.GetEmptyItemSet() );
+ if ( pS )
+ rOutliner.SetStyleSheet( nParaIndex, pS );
+
+ for ( pPortion = pPara->First(); pPortion; pPortion = pPara->Next() )
+ {
+ SfxItemSet aPortionAttribs( rOutliner.GetEmptyItemSet() );
+ std::unique_ptr<SvxFieldItem> pFieldItem(pPortion->GetTextField());
+ if ( pFieldItem )
+ {
+ rOutliner.QuickInsertField( *pFieldItem, ESelection( nParaIndex, aSelection.nEndPos, nParaIndex, aSelection.nEndPos + 1 ) );
+ aSelection.nEndPos++;
+ }
+ else
+ {
+ const sal_Unicode *pF, *pPtr = pPortion->maString.getStr();
+ const sal_Unicode *pMax = pPtr + pPortion->maString.getLength();
+ sal_Int32 nLen;
+ for ( pF = pPtr; pPtr < pMax; pPtr++ )
+ {
+ if ( *pPtr == 0xb )
+ {
+ nLen = pPtr - pF;
+ if ( nLen )
+ aSelection.nEndPos =
+ sal::static_int_cast< sal_uInt16 >(
+ aSelection.nEndPos + nLen );
+ pF = pPtr + 1;
+ rOutliner.QuickInsertLineBreak( ESelection( nParaIndex, aSelection.nEndPos, nParaIndex, aSelection.nEndPos + 1 ) );
+ aSelection.nEndPos++;
+ }
+ }
+ nLen = pPtr - pF;
+ if ( nLen )
+ aSelection.nEndPos = sal::static_int_cast< sal_uInt16 >(
+ aSelection.nEndPos + nLen );
+ }
+ pPortion->ApplyTo( aPortionAttribs, const_cast<SdrPowerPointImport&>(*this), nDestinationInstance, pTextObj );
+ rOutliner.QuickSetAttribs( aPortionAttribs, aSelection );
+ aSelection.nStartPos = aSelection.nEndPos;
+ }
+ std::optional< sal_Int16 > oStartNumbering;
+ SfxItemSet aParagraphAttribs( rOutliner.GetEmptyItemSet() );
+ pPara->ApplyTo( aParagraphAttribs, oStartNumbering, *this, nDestinationInstance );
+
+ sal_uInt32 nIsBullet2 = 0; //, nInstance = nDestinationInstance != 0xffffffff ? nDestinationInstance : pTextObj->GetInstance();
+ pPara->GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet2, nDestinationInstance );
+ if ( !nIsBullet2 )
+ aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
+
+ if ( !aSelection.nStartPos ) // in PPT empty paragraphs never gets a bullet
+ {
+ aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
+ }
+ aSelection.nStartPos = 0;
+ rOutliner.QuickSetAttribs( aParagraphAttribs, aSelection );
+ }
+ }
+ std::optional<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
+ rOutliner.Clear();
+ rOutliner.SetUpdateLayout( bOldUpdateMode );
+ rOutliner.EnableUndo(bUndoEnabled);
+ pText->SetOutlinerParaObject( std::move(pNewText) );
+ }
+ return pText;
+}
+
+bool SdrPowerPointImport::SeekToDocument( DffRecordHeader* pRecHd ) const
+{
+ bool bRet;
+ sal_uInt64 nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it, if the situation should happen
+ rStCtrl.Seek( m_nDocStreamPos );
+ DffRecordHeader aDocHd;
+ ReadDffRecordHeader( rStCtrl, aDocHd );
+ bRet = aDocHd.nRecType == PPT_PST_Document;
+ if ( bRet )
+ {
+ if ( pRecHd )
+ *pRecHd = aDocHd;
+ else
+ aDocHd.SeekToBegOfRecord( rStCtrl );
+ }
+ if ( !bRet )
+ rStCtrl.Seek( nOldFPos ); // restore FilePos
+ return bRet;
+}
+
+bool SdrPowerPointImport::SeekToContentOfProgTag( sal_Int32 nVersion, SvStream& rSt,
+ const DffRecordHeader& rSourceHd, DffRecordHeader& rContentHd )
+{
+ bool bRetValue = false;
+ sal_uInt32 nOldPos = rSt.Tell();
+
+ DffRecordHeader aProgTagsHd, aProgTagBinaryDataHd;
+ rSourceHd.SeekToContent( rSt );
+ bool bFound = rSourceHd.nRecType == PPT_PST_ProgTags;
+ if ( !bFound )
+ bFound = SeekToRec( rSt, PPT_PST_ProgTags, rSourceHd.GetRecEndFilePos(), &aProgTagsHd );
+ if ( bFound )
+ {
+ while( SeekToRec( rSt, PPT_PST_ProgBinaryTag, aProgTagsHd.GetRecEndFilePos(), &aProgTagBinaryDataHd ) )
+ {
+ ReadDffRecordHeader( rSt, rContentHd );
+ if ( rContentHd.nRecType == PPT_PST_CString )
+ {
+ sal_uInt16 n = 6;
+ sal_uInt32 i = rContentHd.nRecLen >> 1;
+ if ( i > n )
+ {
+ OUString aPre = read_uInt16s_ToOUString(rSt, n);
+ n = static_cast<sal_uInt16>( i - 6 );
+ OUString aSuf = read_uInt16s_ToOUString(rSt, n);
+ sal_Int32 nV = aSuf.toInt32();
+ if ( ( nV == nVersion ) && ( aPre == "___PPT" ) )
+ {
+ if (!rContentHd.SeekToEndOfRecord(rSt))
+ {
+ break;
+ }
+ ReadDffRecordHeader( rSt, rContentHd );
+ if ( rContentHd.nRecType == PPT_PST_BinaryTagData )
+ {
+ bRetValue = true;
+ break;
+ }
+ }
+ }
+ }
+ if (!aProgTagBinaryDataHd.SeekToEndOfRecord(rSt))
+ break;
+ }
+ }
+ if ( !bRetValue )
+ rSt.Seek( nOldPos );
+ return bRetValue;
+}
+
+sal_uInt32 SdrPowerPointImport::GetCurrentPageId()
+{
+ PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
+ if ( pList && m_nCurrentPageNum < pList->size() )
+ return (*pList)[ m_nCurrentPageNum ].aPersistAtom.nSlideId;
+ return 0;
+}
+
+bool SdrPowerPointImport::SeekToCurrentPage( DffRecordHeader* pRecHd ) const
+{
+ bool bRet = false;
+ PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
+ if ( pList && ( m_nCurrentPageNum < pList->size() ) )
+ {
+ sal_uLong nPersist = (*pList)[ m_nCurrentPageNum ].aPersistAtom.nPsrReference;
+ if ( nPersist > 0 && nPersist < m_nPersistPtrCnt )
+ {
+ sal_uLong nFPos = m_pPersistPtr[ nPersist ];
+ if ( nFPos < nStreamLen )
+ {
+ rStCtrl.Seek( nFPos );
+ if ( pRecHd )
+ ReadDffRecordHeader( rStCtrl, *pRecHd );
+ bRet = true;
+ }
+ }
+ }
+ return bRet;
+}
+
+sal_uInt16 SdrPowerPointImport::GetPageCount( PptPageKind ePageKind ) const
+{
+ PptSlidePersistList* pList = GetPageList( ePageKind );
+ if ( pList )
+ return pList->size();
+ return 0;
+}
+
+void SdrPowerPointImport::SetPageNum( sal_uInt16 nPageNum, PptPageKind eKind )
+{
+ m_eCurrentPageKind = eKind;
+ m_nCurrentPageNum = nPageNum;
+
+ m_pPPTStyleSheet = nullptr;
+
+ bool bHasMasterPage = true;
+ sal_uInt16 nMasterIndex = 0;
+
+ if ( eKind == PPT_MASTERPAGE )
+ nMasterIndex = nPageNum;
+ else
+ {
+ if ( HasMasterPage( nPageNum, eKind ) )
+ nMasterIndex = GetMasterPageIndex( nPageNum, eKind );
+ else
+ bHasMasterPage = false;
+ }
+ if ( bHasMasterPage )
+ {
+ PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
+ if ( pPageList && nMasterIndex < pPageList->size() )
+ {
+ PptSlidePersistEntry* pMasterPersist = &(*pPageList)[ nMasterIndex ];
+ if (!pMasterPersist->xStyleSheet && pMasterPersist->aSlideAtom.nMasterId)
+ {
+ nMasterIndex = m_pMasterPages->FindPage( pMasterPersist->aSlideAtom.nMasterId );
+ if ( nMasterIndex != PPTSLIDEPERSIST_ENTRY_NOTFOUND )
+ pMasterPersist = &(*pPageList)[ nMasterIndex ];
+ }
+ m_pPPTStyleSheet = pMasterPersist->xStyleSheet.get();
+ }
+ }
+ if ( !m_pPPTStyleSheet )
+ m_pPPTStyleSheet = m_pDefaultSheet;
+}
+
+Size SdrPowerPointImport::GetPageSize() const
+{
+ Size aRet( IsNoteOrHandout( m_nCurrentPageNum ) ? aDocAtom.GetNotesPageSize() : aDocAtom.GetSlidesPageSize() );
+ Scale( aRet );
+ // PPT works with units of 576 dpi in any case. To avoid inaccuracies
+ // I do round the last decimal digit away.
+ if ( nMapMul > 2 * nMapDiv )
+ {
+ MapUnit eMap = pSdrModel->GetScaleUnit();
+ bool bInch = IsInch( eMap );
+ tools::Long nInchMul = 1, nInchDiv = 1;
+ if ( bInch )
+ { // temporarily convert size (for rounding it) from inch to metric units
+ Fraction aFact(GetMapFactor(eMap,MapUnit::Map100thMM).X());
+ nInchMul = aFact.GetNumerator();
+ nInchDiv = aFact.GetDenominator();
+ aRet.setWidth( BigMulDiv( aRet.Width(), nInchMul, nInchDiv ) );
+ aRet.setHeight( BigMulDiv( aRet.Height(), nInchMul, nInchDiv ) );
+ }
+ aRet.AdjustWidth(5 ); aRet.setWidth( aRet.Width() / 10 ); aRet.setWidth( aRet.Width() * 10 );
+ aRet.AdjustHeight(5 ); aRet.setHeight( aRet.Height() / 10 ); aRet.setHeight( aRet.Height() * 10 );
+ if ( bInch )
+ {
+ aRet.setWidth( BigMulDiv( aRet.Width(), nInchDiv, nInchMul ) );
+ aRet.setHeight( BigMulDiv( aRet.Height(), nInchDiv, nInchMul ) );
+ }
+ }
+ return aRet;
+}
+
+bool SdrPowerPointImport::GetColorFromPalette( sal_uInt16 nNum, Color& rColor ) const
+{
+ if ( m_nPageColorsNum != m_nCurrentPageNum || m_ePageColorsKind != m_eCurrentPageKind )
+ {
+ sal_uInt16 nSlideFlags = 0;
+ PptSlidePersistList* pPageList = GetPageList( m_eCurrentPageKind );
+ if ( pPageList && ( m_nCurrentPageNum < pPageList->size() ) )
+ {
+ assert( !pPageList->is_null( m_nCurrentPageNum ) );
+ const PptSlidePersistEntry& rE = (*pPageList)[ m_nCurrentPageNum ];
+ nSlideFlags = rE.aSlideAtom.nFlags;
+ if ( ! ( nSlideFlags & 2 ) )
+ const_cast<SdrPowerPointImport*>(this)->m_aPageColors = rE.aColorScheme;
+ }
+ if ( nSlideFlags & 2 ) // follow master colorscheme?
+ {
+ PptSlidePersistList* pPageList2 = GetPageList( PPT_MASTERPAGE );
+ if ( pPageList2 )
+ {
+ PptSlidePersistEntry* pMasterPersist = nullptr;
+ if ( m_eCurrentPageKind == PPT_MASTERPAGE )
+ pMasterPersist = &(*pPageList2)[ m_nCurrentPageNum ];
+ else
+ {
+ if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
+ {
+ sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
+ if ( nMasterNum < pPageList2->size() )
+ pMasterPersist = &(*pPageList2)[ nMasterNum ];
+ }
+ }
+ if ( pMasterPersist )
+ {
+ while( (pMasterPersist->aSlideAtom.nFlags & 2) // it is possible that a masterpage
+ && pMasterPersist->aSlideAtom.nMasterId ) // itself is following a master colorscheme
+ {
+ auto nOrigMasterId = pMasterPersist->aSlideAtom.nMasterId;
+ sal_uInt16 nNextMaster = m_pMasterPages->FindPage(nOrigMasterId);
+ if (nNextMaster == PPTSLIDEPERSIST_ENTRY_NOTFOUND)
+ break;
+ pMasterPersist = &(*pPageList2)[ nNextMaster ];
+ if (pMasterPersist->aSlideAtom.nMasterId == nOrigMasterId)
+ {
+ SAL_WARN("filter.ms", "loop in atom chain");
+ break;
+ }
+ }
+ const_cast<SdrPowerPointImport*>(this)->m_aPageColors = pMasterPersist->aColorScheme;
+ }
+ }
+ }
+ // register current color scheme
+ const_cast<SdrPowerPointImport*>(this)->m_nPageColorsNum = m_nCurrentPageNum;
+ const_cast<SdrPowerPointImport*>(this)->m_ePageColorsKind = m_eCurrentPageKind;
+ }
+ rColor = m_aPageColors.GetColor( nNum );
+ return true;
+}
+
+bool SdrPowerPointImport::SeekToShape( SvStream& rSt, SvxMSDffClientData* pClientData, sal_uInt32 nId ) const
+{
+ bool bRet = SvxMSDffManager::SeekToShape( rSt, pClientData, nId );
+ if (!bRet && pClientData)
+ {
+ ProcessData& rData = *static_cast<ProcessData*>(pClientData);
+ PptSlidePersistEntry& rPersistEntry = rData.rPersistEntry;
+ if ( rPersistEntry.ePageKind == PPT_SLIDEPAGE )
+ {
+ if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
+ {
+ sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
+ PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
+ if ( pPageList && ( nMasterNum < pPageList->size() ) )
+ {
+ assert( !pPageList->is_null( nMasterNum ) );
+ const PptSlidePersistEntry& rPersist = (*pPageList)[ nMasterNum ]; // get the masterpage's persistentry
+ if ( rPersist.pPresentationObjects )
+ {
+ sal_uInt32 nCurrent(0);
+ DffRecordList* pCList = maShapeRecords.pCList; // we got a backup of the current position
+ if ( pCList )
+ nCurrent = pCList->nCurrent;
+ if ( const_cast<SdrPowerPointImport*>(this)->maShapeRecords.SeekToContent( rSt, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
+ {
+ sal_uInt32 nStreamPos = rSt.Tell();
+ PPTTextObj aTextObj( rSt, const_cast<SdrPowerPointImport&>(*this), rPersistEntry, nullptr );
+ if ( aTextObj.Count() || aTextObj.GetOEPlaceHolderAtom() )
+ {
+ sal_uInt32 nShapePos = 0;
+ switch ( aTextObj.GetInstance() )
+ {
+ case TSS_Type::Title :
+ nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::PageTitle) ];
+ break;
+ case TSS_Type::PageTitle :
+ nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::PageTitle) ];
+ break;
+ case TSS_Type::Subtitle :
+ case TSS_Type::HalfBody :
+ case TSS_Type::QuarterBody :
+ case TSS_Type::Body :
+ nShapePos = rPersist.pPresentationObjects[ int(TSS_Type::Body) ];
+ break;
+ default: break;
+ }
+ if ( nShapePos )
+ {
+ rSt.Seek( nShapePos );
+ bRet = true;
+ }
+ }
+ if ( !bRet )
+ rSt.Seek( nStreamPos );
+ }
+ if ( pCList ) // restoring
+ pCList->nCurrent = nCurrent;
+ const_cast<SdrPowerPointImport*>(this)->maShapeRecords.pCList = pCList;
+ }
+ }
+ }
+ }
+ }
+ return bRet;
+}
+
+rtl::Reference<SdrPage> SdrPowerPointImport::MakeBlankPage( bool bMaster ) const
+{
+ rtl::Reference<SdrPage> pRet = pSdrModel->AllocPage( bMaster );
+ pRet->SetSize( GetPageSize() );
+
+ return pRet;
+}
+
+static void ImportComment10( SvxMSDffManager const & rMan, SvStream& rStCtrl, SdrPage* pPage, DffRecordHeader const & rComment10Hd )
+{
+ OUString sAuthor;
+ OUString sText;
+ OUString sInitials;
+
+ sal_Int32 nIndex = 0;
+ util::DateTime aDateTime;
+ sal_Int32 nPosX = 0;
+ sal_Int32 nPosY = 0;
+
+
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rStCtrl, rComment10Hd.GetRecEndFilePos());
+ while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
+ {
+ DffRecordHeader aCommentHd;
+ ReadDffRecordHeader( rStCtrl, aCommentHd );
+ switch( aCommentHd.nRecType )
+ {
+ case PPT_PST_CString :
+ {
+ OUString aString = SvxMSDffManager::MSDFFReadZString( rStCtrl,
+ aCommentHd.nRecLen, true );
+ switch ( aCommentHd.nRecInstance )
+ {
+ case 0 : sAuthor = aString; break;
+ case 1 : sText = aString; break;
+ case 2 : sInitials = aString; break;
+ }
+ }
+ break;
+
+ case PPT_PST_CommentAtom10 :
+ {
+ sal_uInt16 millisec = 0;
+ rStCtrl.ReadInt32( nIndex )
+ .ReadInt16( aDateTime.Year )
+ .ReadUInt16( aDateTime.Month )
+ .ReadUInt16( aDateTime.Day ) // DayOfWeek
+ .ReadUInt16( aDateTime.Day )
+ .ReadUInt16( aDateTime.Hours )
+ .ReadUInt16( aDateTime.Minutes )
+ .ReadUInt16( aDateTime.Seconds )
+ .ReadUInt16( millisec )
+ .ReadInt32( nPosX )
+ .ReadInt32( nPosY );
+
+ aDateTime.NanoSeconds = millisec * ::tools::Time::nanoPerMilli;
+ }
+ break;
+ }
+ if (!aCommentHd.SeekToEndOfRecord(rStCtrl))
+ break;
+ }
+ Point aPosition( nPosX, nPosY );
+ rMan.Scale( aPosition );
+
+ try
+ {
+ uno::Reference< office::XAnnotationAccess > xAnnotationAccess( pPage->getUnoPage(), UNO_QUERY_THROW );
+ uno::Reference< office::XAnnotation > xAnnotation( xAnnotationAccess->createAndInsertAnnotation() );
+ xAnnotation->setPosition( geometry::RealPoint2D( aPosition.X() / 100.0, aPosition.Y() / 100.0 ) );
+ xAnnotation->setAuthor( sAuthor );
+ xAnnotation->setDateTime( aDateTime );
+ xAnnotation->setInitials( sInitials );
+ uno::Reference< text::XText > xText( xAnnotation->getTextRange() );
+ xText->setString( sText );
+ }
+ catch( const uno::Exception& )
+ {
+
+ }
+}
+
+
+// be sure not to import masterpages with this method
+void SdrPowerPointImport::ImportPage( SdrPage* pRet, const PptSlidePersistEntry* pMasterPersist )
+{
+ sal_uInt32 nOldPos = rStCtrl.Tell();
+ PptSlidePersistList* pList = GetPageList( m_eCurrentPageKind );
+ if ( ( !pList ) || ( pList->size() <= m_nCurrentPageNum ) )
+ return;
+ PptSlidePersistEntry& rSlidePersist = (*pList)[ m_nCurrentPageNum ];
+ if ( rSlidePersist.bStarDrawFiller )
+ return;
+
+ DffRecordHeader aPageHd;
+ if ( SeekToCurrentPage( &aPageHd ) )
+ {
+ rSlidePersist.xHeaderFooterEntry.reset(new HeaderFooterEntry(pMasterPersist));
+ ProcessData aProcessData( rSlidePersist, SdPageCapsule(pRet) );
+ auto nEndRecPos = SanitizeEndPos(rStCtrl, aPageHd.GetRecEndFilePos());
+ while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
+ {
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rStCtrl, aHd );
+ switch ( aHd.nRecType )
+ {
+ case PPT_PST_HeadersFooters :
+ {
+ ImportHeaderFooterContainer(aHd, *rSlidePersist.xHeaderFooterEntry);
+ }
+ break;
+
+ case PPT_PST_ProgTags :
+ {
+ DffRecordHeader aContentDataHd;
+ if ( SeekToContentOfProgTag( 10, rStCtrl, aHd, aContentDataHd ) )
+ {
+ DffRecordHeader aComment10Hd;
+ while( ( rStCtrl.GetError() == ERRCODE_NONE ) && SeekToRec( rStCtrl, PPT_PST_Comment10, aContentDataHd.GetRecEndFilePos(), &aComment10Hd ) )
+ {
+ ImportComment10( *this, rStCtrl, pRet, aComment10Hd );
+ if (!aComment10Hd.SeekToEndOfRecord(rStCtrl))
+ break;
+ }
+ }
+ }
+ break;
+
+ case PPT_PST_PPDrawing :
+ {
+ DffRecordHeader aPPDrawHd;
+ if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, aHd.GetRecEndFilePos(), &aPPDrawHd ) )
+ {
+ sal_uInt32 nPPDrawOfs = rStCtrl.Tell();
+
+ // importing the background object before importing the page
+ auto nPPEndRecPos = SanitizeEndPos(rStCtrl, aPPDrawHd.GetRecEndFilePos());
+ while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nPPEndRecPos ) )
+ {
+ DffRecordHeader aEscherObjListHd;
+ ReadDffRecordHeader( rStCtrl, aEscherObjListHd );
+ switch ( aEscherObjListHd.nRecType )
+ {
+ case DFF_msofbtSpContainer :
+ {
+ tools::Rectangle aPageSize( Point(), pRet->GetSize() );
+ if ( rSlidePersist.aSlideAtom.nFlags & 4 ) // follow master background?
+ {
+ if ( HasMasterPage( m_nCurrentPageNum, m_eCurrentPageKind ) )
+ {
+ sal_uInt16 nMasterNum = GetMasterPageIndex( m_nCurrentPageNum, m_eCurrentPageKind );
+ PptSlidePersistList* pPageList = GetPageList( PPT_MASTERPAGE );
+ PptSlidePersistEntry* pE = &(*pPageList)[ nMasterNum ];
+ while( ( pE->aSlideAtom.nFlags & 4 ) && pE->aSlideAtom.nMasterId )
+ {
+ auto nOrigMasterId = pE->aSlideAtom.nMasterId;
+ sal_uInt16 nNextMaster = m_pMasterPages->FindPage(nOrigMasterId);
+ if ( nNextMaster == PPTSLIDEPERSIST_ENTRY_NOTFOUND )
+ break;
+ else
+ pE = &(*pPageList)[ nNextMaster ];
+ if (pE->aSlideAtom.nMasterId == nOrigMasterId)
+ {
+ SAL_WARN("filter.ms", "loop in atom chain");
+ break;
+ }
+ }
+ if ( pE->nBackgroundOffset )
+ {
+ // do not follow master colorscheme?
+ sal_uInt32 nPos = rStCtrl.Tell();
+ rStCtrl.Seek( pE->nBackgroundOffset );
+ rSlidePersist.pBObj = ImportObj( rStCtrl, aProcessData, aPageSize, aPageSize, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
+ rStCtrl.Seek( nPos );
+ }
+ }
+ }
+ else
+ {
+ DffRecordHeader aShapeHd;
+ ReadDffRecordHeader( rStCtrl, aShapeHd );
+ if ( aShapeHd.nRecType == DFF_msofbtSp )
+ {
+ sal_uInt32 nSpFlags;
+ rStCtrl.ReadUInt32( nSpFlags ).ReadUInt32( nSpFlags );
+ if (rStCtrl.good() && ShapeFlag(nSpFlags) & ShapeFlag::Background)
+ {
+ aEscherObjListHd.SeekToBegOfRecord( rStCtrl );
+ rSlidePersist.pBObj = ImportObj( rStCtrl, aProcessData, aPageSize, aPageSize, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
+ }
+ }
+ }
+ }
+ break;
+ }
+ if ( aEscherObjListHd.nRecType == DFF_msofbtSpContainer )
+ break;
+ if (!aEscherObjListHd.SeekToEndOfRecord(rStCtrl))
+ break;
+ }
+
+ // now importing page
+ rStCtrl.Seek( nPPDrawOfs );
+ auto nHdEndRecPos = SanitizeEndPos(rStCtrl, aPPDrawHd.GetRecEndFilePos());
+ while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nHdEndRecPos ) )
+ {
+ DffRecordHeader aEscherObjListHd;
+ ReadDffRecordHeader( rStCtrl, aEscherObjListHd );
+ switch ( aEscherObjListHd.nRecType )
+ {
+ case DFF_msofbtSpgrContainer :
+ {
+ DffRecordHeader aShapeHd;
+ if ( SeekToRec( rStCtrl, DFF_msofbtSpContainer, aEscherObjListHd.GetRecEndFilePos(), &aShapeHd ) )
+ {
+ if (!aShapeHd.SeekToEndOfRecord(rStCtrl))
+ {
+ break;
+ }
+ auto nListEndRecPos = SanitizeEndPos(rStCtrl, aEscherObjListHd.GetRecEndFilePos());
+ while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nListEndRecPos ) )
+ {
+ ReadDffRecordHeader( rStCtrl, aShapeHd );
+ if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) || ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) )
+ {
+ tools::Rectangle aEmpty;
+ aShapeHd.SeekToBegOfRecord( rStCtrl );
+ sal_Int32 nShapeId;
+ aProcessData.pTableRowProperties.reset();
+ SdrObject* pObj = ImportObj( rStCtrl, aProcessData, aEmpty, aEmpty, 0, &nShapeId );
+ if ( pObj )
+ {
+ if ( aProcessData.pTableRowProperties )
+ pObj = CreateTable(pObj, aProcessData.pTableRowProperties.get(), aProcessData.rPersistEntry.xSolverContainer.get(), aProcessData.aBackgroundColoredObjects);
+
+ pRet->NbcInsertObject( pObj );
+
+ if( nShapeId )
+ insertShapeId( nShapeId, pObj );
+ }
+ }
+ bool bSuccess = aShapeHd.SeekToEndOfRecord(rStCtrl);
+ if (!bSuccess)
+ break;
+ }
+ }
+ }
+ break;
+ }
+ if ( aEscherObjListHd.nRecType == DFF_msofbtSpgrContainer )
+ break;
+ if (!aEscherObjListHd.SeekToEndOfRecord(rStCtrl))
+ break;
+ }
+
+ // Handle shapes where the fill matches the background
+ // fill (mso_fillBackground).
+ if (rSlidePersist.ePageKind == PPT_SLIDEPAGE)
+ {
+ if (!aProcessData.aBackgroundColoredObjects.empty())
+ {
+ if (!rSlidePersist.pBObj)
+ {
+ for (auto pObject : aProcessData.aBackgroundColoredObjects)
+ {
+ // The shape wants a background, but the slide doesn't have
+ // one: default to white.
+ SfxItemSet aNewSet(*pObject->GetMergedItemSet().GetPool());
+ aNewSet.Put(XFillStyleItem(css::drawing::FillStyle_SOLID));
+ aNewSet.Put(XFillColorItem(OUString(), COL_WHITE));
+ pObject->SetMergedItemSet(aNewSet);
+ }
+ }
+ }
+ }
+
+ if ( rSlidePersist.pBObj )
+ {
+ // #i99386# transfer the attributes from the temporary BackgroundObject
+ // to the Page and delete it.
+ pRet->getSdrPageProperties().ClearItem();
+ pRet->getSdrPageProperties().PutItemSet(rSlidePersist.pBObj->GetMergedItemSet());
+ if (rSlidePersist.xSolverContainer)
+ {
+ for (auto & pPtr : rSlidePersist.xSolverContainer->aCList)
+ {
+ // check connections to the group object
+ if (pPtr->pAObj == rSlidePersist.pBObj)
+ pPtr->pAObj = nullptr;
+ if (pPtr->pBObj == rSlidePersist.pBObj)
+ pPtr->pBObj = nullptr;
+ if (pPtr->pCObj == rSlidePersist.pBObj)
+ pPtr->pCObj = nullptr;
+ }
+ }
+ SdrObject::Free(rSlidePersist.pBObj);
+ }
+ }
+ }
+ break;
+ }
+ if (!aHd.SeekToEndOfRecord(rStCtrl))
+ break;
+ }
+ if (rSlidePersist.xSolverContainer)
+ SolveSolver(*rSlidePersist.xSolverContainer);
+ }
+ rStCtrl.Seek( nOldPos );
+}
+
+const PptSlideLayoutAtom* SdrPowerPointImport::GetSlideLayoutAtom() const
+{
+ PptSlidePersistList* pPageList = GetPageList( m_eCurrentPageKind );
+ if ( pPageList && m_nCurrentPageNum < pPageList->size() )
+ {
+ assert( !pPageList->is_null( m_nCurrentPageNum ) );
+ return &(*pPageList)[ m_nCurrentPageNum ].aSlideAtom.aLayout;
+ }
+ return nullptr;
+}
+
+bool SdrPowerPointImport::IsNoteOrHandout( sal_uInt16 nPageNum ) const
+{
+ bool bNote = m_eCurrentPageKind == PPT_NOTEPAGE;
+ if ( m_eCurrentPageKind == PPT_MASTERPAGE )
+ bNote = ( nPageNum & 1 ) == 0;
+ return bNote;
+}
+
+sal_uInt32 SdrPowerPointImport::GetMasterPageId( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
+{
+ PptSlidePersistList* pPageList = GetPageList( ePageKind );
+ if ( pPageList && nPageNum < pPageList->size() )
+ return (*pPageList)[ nPageNum ].aSlideAtom.nMasterId;
+ return 0;
+}
+
+sal_uInt32 SdrPowerPointImport::GetNotesPageId( sal_uInt16 nPageNum ) const
+{
+ PptSlidePersistList* pPageList=GetPageList( PPT_SLIDEPAGE );
+ if ( pPageList && nPageNum < pPageList->size() )
+ return (*pPageList)[ nPageNum ].aSlideAtom.nNotesId;
+ return 0;
+}
+
+bool SdrPowerPointImport::HasMasterPage( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
+{
+ if ( ePageKind == PPT_NOTEPAGE )
+ return aDocAtom.nNotesMasterPersist != 0;
+ if ( ePageKind == PPT_MASTERPAGE )
+ return false;
+ return GetMasterPageId( nPageNum, ePageKind ) != 0;
+}
+
+sal_uInt16 SdrPowerPointImport::GetMasterPageIndex( sal_uInt16 nPageNum, PptPageKind ePageKind ) const
+{
+ sal_uInt16 nIdx = 0;
+ if ( ePageKind == PPT_NOTEPAGE )
+ return 2;
+ sal_uInt32 nId = GetMasterPageId( nPageNum, ePageKind );
+ if (nId && m_pMasterPages)
+ {
+ nIdx = m_pMasterPages->FindPage( nId );
+ if ( nIdx == PPTSLIDEPERSIST_ENTRY_NOTFOUND )
+ nIdx = 0;
+ }
+ return nIdx;
+}
+
+SdrObject* SdrPowerPointImport::ImportPageBackgroundObject( const SdrPage& rPage, sal_uInt32& nBgFileOffset )
+{
+ SdrObject* pRet = nullptr;
+ std::optional<SfxItemSet> pSet;
+ sal_uInt64 nOldFPos = rStCtrl.Tell(); // remember FilePos for restoring it later
+ DffRecordHeader aPageHd;
+ if ( SeekToCurrentPage( &aPageHd ) )
+ { // and now search for the background attributes of the Page
+ sal_uLong nPageRecEnd = aPageHd.GetRecEndFilePos();
+ DffRecordHeader aPPDrawHd;
+ if ( SeekToRec( rStCtrl, PPT_PST_PPDrawing, nPageRecEnd, &aPPDrawHd ) )
+ {
+ sal_uLong nPPDrawEnd = aPPDrawHd.GetRecEndFilePos();
+ DffRecordHeader aEscherF002Hd;
+ if ( SeekToRec( rStCtrl, DFF_msofbtDgContainer, nPPDrawEnd, &aEscherF002Hd ) )
+ {
+ sal_uLong nEscherF002End = aEscherF002Hd.GetRecEndFilePos();
+ DffRecordHeader aEscherObjectHd;
+ if ( SeekToRec( rStCtrl, DFF_msofbtSpContainer, nEscherF002End, &aEscherObjectHd ) )
+ {
+ nBgFileOffset = aEscherObjectHd.GetRecBegFilePos();
+ //sal_uLong nEscherObjectEnd = aEscherObjectHd.GetRecEndFilePos();
+ //DffRecordHeader aEscherPropertiesHd;
+ if ( SeekToRec( rStCtrl, DFF_msofbtOPT,nEscherF002End ) )
+ {
+ ReadDffPropSet( rStCtrl, static_cast<DffPropertyReader&>(*this) );
+ mnFix16Angle = Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation, 0 ) );
+ sal_uInt32 nColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );
+ pSet.emplace( pSdrModel->GetItemPool() );
+ DffObjData aObjData( aEscherObjectHd, tools::Rectangle( 0, 0, 28000, 21000 ), 0 );
+ ApplyAttributes( rStCtrl, *pSet, aObjData );
+ Color aColor( MSO_CLR_ToColor( nColor ) );
+ pSet->Put( XFillColorItem( OUString(), aColor ) );
+ }
+ }
+ }
+ }
+ }
+ rStCtrl.Seek( nOldFPos ); // restore FilePos
+ if ( !pSet )
+ {
+ pSet.emplace( pSdrModel->GetItemPool() );
+ pSet->Put( XFillStyleItem( drawing::FillStyle_NONE ) );
+ }
+ pSet->Put( XLineStyleItem( drawing::LineStyle_NONE ) );
+ tools::Rectangle aRect(
+ rPage.GetLeftBorder(),
+ rPage.GetUpperBorder(),
+ rPage.GetWidth() - rPage.GetRightBorder(),
+ rPage.GetHeight() - rPage.GetLowerBorder());
+
+ pRet = new SdrRectObj(
+ *pSdrModel,
+ aRect);
+
+ pRet->SetMergedItemSet(*pSet);
+ pRet->SetMarkProtect( true );
+ pRet->SetMoveProtect( true );
+ pRet->SetResizeProtect( true );
+ return pRet;
+}
+
+HeaderFooterEntry::HeaderFooterEntry( const PptSlidePersistEntry* pMPE ) :
+ pMasterPersist ( pMPE ),
+ nAtom ( 0 )
+{
+ if ( pMPE )
+ {
+ HeaderFooterEntry* pMHFE = pMPE->xHeaderFooterEntry.get();
+ if ( pMHFE )
+ {
+ nAtom = pMPE->xHeaderFooterEntry->nAtom;
+ pPlaceholder[ 0 ] = pMHFE->pPlaceholder[ 0 ];
+ pPlaceholder[ 1 ] = pMHFE->pPlaceholder[ 1 ];
+ pPlaceholder[ 2 ] = pMHFE->pPlaceholder[ 2 ];
+ pPlaceholder[ 3 ] = pMHFE->pPlaceholder[ 3 ];
+ }
+ }
+}
+
+sal_uInt32 HeaderFooterEntry::IsToDisplay( sal_uInt32 nInstance )
+{
+ sal_uInt32 nMask = 0;
+ switch ( nInstance )
+ {
+ case 0 : nMask = 0x010000; break;
+ case 1 : nMask = 0x100000; break;
+ case 2 : nMask = 0x200000; break;
+ case 3 : nMask = 0x080000; break;
+ }
+ return ( nAtom & nMask );
+}
+
+// The following method checks if the slide is using a different colorscheme than
+// its master, if this is the fact, then the HeaderFooter must probably be
+// imported as real sdrobject. In this case, the return value is the offset to the
+// master header footer object, so it can be re-loaded with a different color set
+sal_uInt32 HeaderFooterEntry::NeedToImportInstance( const sal_uInt32 nInstance, const PptSlidePersistEntry& rSlidePersist )
+{
+ sal_uInt32 nRet = 0;
+ if ( pMasterPersist )
+ {
+ if ( !( rSlidePersist.aSlideAtom.nFlags & 2 ) )
+ { // not following the master persist, so we have to check if the colors are changed
+ if ( memcmp( &rSlidePersist.aColorScheme, &pMasterPersist->aColorScheme, 32 ) )
+ {
+ nRet = pMasterPersist->HeaderFooterOfs[ nInstance ];
+ }
+ }
+ }
+ return nRet;
+}
+
+void SdrEscherImport::ImportHeaderFooterContainer( DffRecordHeader const & rHd, HeaderFooterEntry& rE )
+{
+ rHd.SeekToContent( rStCtrl );
+ auto nEndRecPos = SanitizeEndPos(rStCtrl, rHd.GetRecEndFilePos());
+ while ( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( rStCtrl.Tell() < nEndRecPos ) )
+ {
+ DffRecordHeader aHd;
+ ReadDffRecordHeader( rStCtrl, aHd );
+ switch ( aHd.nRecType )
+ {
+ case PPT_PST_HeadersFootersAtom :
+ rStCtrl.ReadUInt32( rE.nAtom );
+ break;
+
+ case PPT_PST_CString :
+ {
+ if ( aHd.nRecInstance < 4 )
+ {
+ rE.pPlaceholder[ aHd.nRecInstance ] = MSDFFReadZString( rStCtrl,
+ aHd.nRecLen, true );
+ }
+ }
+ break;
+ }
+ if (!aHd.SeekToEndOfRecord(rStCtrl))
+ break;
+ }
+}
+
+PPTBuGraEntry::PPTBuGraEntry( Graphic aGraphic, sal_uInt32 nInst ) :
+ nInstance ( nInst ),
+ aBuGra (std::move( aGraphic )) {}
+
+PPTExtParaLevel::PPTExtParaLevel()
+: mnExtParagraphMask( 0 )
+, mnBuBlip( 0xffff )
+, mnHasAnm( 0 )
+, mnAnmScheme( 0 )
+, mpfPP10Ext( 0 )
+, mnExtCharacterMask( 0 )
+, mcfPP10Ext( 0 )
+, mbSet( false )
+{}
+
+SvStream& ReadPPTExtParaLevel( SvStream& rIn, PPTExtParaLevel& rLevel )
+{
+ rLevel.mbSet = true;
+ rIn.ReadUInt32( rLevel.mnExtParagraphMask );
+ if ( rLevel.mnExtParagraphMask & 0x00800000 )
+ rIn.ReadUInt16( rLevel.mnBuBlip );
+ if ( rLevel.mnExtParagraphMask & 0x02000000 )
+ rIn.ReadUInt16( rLevel.mnHasAnm );
+ if ( rLevel.mnExtParagraphMask & 0x01000000 )
+ rIn.ReadUInt32( rLevel.mnAnmScheme );
+ if ( rLevel.mnExtParagraphMask & 0x04000000 )
+ rIn.ReadUInt32( rLevel.mpfPP10Ext );
+ rIn.ReadUInt32( rLevel.mnExtCharacterMask );
+ if ( rLevel.mnExtCharacterMask & 0x100000 )
+ rIn.ReadUInt32( rLevel.mcfPP10Ext );
+ return rIn;
+}
+
+bool PPTExtParaProv::GetGraphic( sal_uInt32 nInstance, Graphic& rGraph ) const
+{
+ bool bRetValue = false;
+ PPTBuGraEntry* pPtr = nullptr;
+ if ( nInstance < aBuGraList.size() )
+ {
+ pPtr = aBuGraList[ nInstance ].get();
+ if ( pPtr->nInstance == nInstance )
+ bRetValue = true;
+ }
+ if ( !bRetValue )
+ {
+ for (std::unique_ptr<PPTBuGraEntry> const & i : aBuGraList)
+ {
+ pPtr = i.get();
+ if ( pPtr->nInstance == nInstance )
+ {
+ bRetValue = true;
+ break;
+ }
+ }
+ }
+ if ( bRetValue )
+ rGraph = pPtr->aBuGra;
+ return bRetValue;
+}
+
+PPTExtParaProv::PPTExtParaProv( SdrPowerPointImport& rMan, SvStream& rSt, const DffRecordHeader* pHd ) :
+ bStyles ( false )
+{
+ sal_uInt32 nOldPos = rSt.Tell();
+
+ // here we have to get the graphical bullets...
+
+ DffRecordHeader aHd;
+ DffRecordHeader aContentDataHd;
+
+ const DffRecordHeader* pListHd = rMan.aDocRecManager.GetRecordHeader( PPT_PST_List );
+ if( pListHd )
+ pListHd->SeekToContent( rSt );
+ if ( pListHd && SdrPowerPointImport::SeekToContentOfProgTag( 9, rSt, *pListHd, aContentDataHd ) )
+ {
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rSt, aContentDataHd.GetRecEndFilePos());
+ while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
+ {
+ ReadDffRecordHeader( rSt, aHd );
+ switch ( aHd.nRecType )
+ {
+ case PPT_PST_ExtendedBuGraContainer :
+ {
+ auto nHdEndRecPos = DffPropSet::SanitizeEndPos(rSt, aHd.GetRecEndFilePos());
+ while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nHdEndRecPos ) )
+ {
+ DffRecordHeader aBuGraAtomHd;
+ ReadDffRecordHeader( rSt, aBuGraAtomHd );
+ if ( aBuGraAtomHd.nRecType == PPT_PST_ExtendedBuGraAtom )
+ {
+ sal_uInt16 nType;
+ rSt.ReadUInt16( nType );
+ Graphic aGraphic;
+ if ( SvxMSDffManager::GetBLIPDirect( rSt, aGraphic ) )
+ {
+ sal_uInt32 nInstance = aBuGraAtomHd.nRecInstance;
+ PPTBuGraEntry* pBuGra = new PPTBuGraEntry( std::move(aGraphic), nInstance );
+ size_t n = 0;
+ size_t nBuGraCount = aBuGraList.size();
+ if ( nBuGraCount )
+ {
+ if ( aBuGraList[ nBuGraCount - 1 ]->nInstance < nInstance )
+ n = nBuGraCount;
+ else
+ { // maybe the instances are not sorted, we sort it
+ for ( n = 0; n < nBuGraCount; n++ )
+ { // sorting fields ( hi >> lo )
+ if ( aBuGraList[ n ]->nInstance < nInstance )
+ break;
+ }
+ }
+ }
+ if ( n < nBuGraCount ) {
+ aBuGraList.emplace( aBuGraList.begin() + n, pBuGra );
+ } else {
+ aBuGraList.emplace_back( pBuGra );
+ }
+ }
+#ifdef DBG_UTIL
+ else OSL_FAIL( "PPTExParaProv::PPTExParaProv - bullet graphic is not valid (SJ)" );
+#endif
+ }
+#ifdef DBG_UTIL
+ else OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom interpreting the PPT_PST_ExtendedBuGraContainer (SJ)" );
+#endif
+ if (!aBuGraAtomHd.SeekToEndOfRecord(rSt))
+ break;
+ }
+ }
+ break;
+
+ case PPT_PST_ExtendedPresRuleContainer :
+ aExtendedPresRules.Consume( rSt, aHd.GetRecEndFilePos() );
+ break;
+#ifdef DBG_UTIL
+ default :
+ OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom reading ppt2000 num rules (SJ)" );
+ break;
+ case PPT_PST_MasterText : // first seen in: ms-tt02.ppt
+ case PPT_PST_SrKinsoku :
+ case PPT_PST_TextDefaults9Atom :
+ case PPT_PST_PresentationAdvisorFlags9Atom :
+ case PPT_PST_HtmlDocInfo9Atom :
+ case PPT_PST_GridSpacing10Atom :
+ case PPT_PST_CommentIndex10 :
+ case PPT_PST_DocToolbarStates10Atom :
+ break;
+#endif
+ }
+ if (!aHd.SeekToEndOfRecord(rSt))
+ break;
+ }
+ }
+
+ if ( pHd && SdrPowerPointImport::SeekToContentOfProgTag( 9, rSt, *pHd, aContentDataHd ) )
+ { // get the extended paragraph styles on mainmaster ( graphical bullets, num ruling ... )
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rSt, aContentDataHd.GetRecEndFilePos());
+ while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nEndRecPos ) )
+ {
+ ReadDffRecordHeader( rSt, aHd );
+ switch ( aHd.nRecType )
+ {
+ case PPT_PST_ExtendedParagraphMasterAtom :
+ {
+ if ( aHd.nRecInstance < PPT_STYLESHEETENTRIES )
+ {
+ sal_uInt16 nDepth = 0, i = 0;
+ rSt.ReadUInt16(nDepth);
+ nDepth = std::min<sal_uInt16>(nDepth, nMaxPPTLevels);
+ auto nHdEndRecPos = DffPropSet::SanitizeEndPos(rSt, aHd.GetRecEndFilePos());
+ while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < nHdEndRecPos ) && ( i < nDepth ) )
+ {
+ bStyles = true;
+ ReadPPTExtParaLevel( rSt, aExtParaSheet[ static_cast<TSS_Type>(aHd.nRecInstance) ].aExtParaLevel[ i++ ] );
+ }
+#ifdef DBG_UTIL
+ if ( rSt.Tell() != aHd.GetRecEndFilePos() )
+ OSL_FAIL( "PPTExParaProv::PPTExParaProv - error reading PPT_PST_ExtendedParagraphMasterAtom (SJ)" );
+#endif
+ }
+#ifdef DBG_UTIL
+ else OSL_FAIL( "PPTExParaProv::PPTExParaProv - instance out of range (SJ)" );
+#endif
+ }
+ break;
+ default :
+ OSL_FAIL( "PPTExParaProv::PPTExParaProv - unknown atom, assuming PPT_PST_ExtendedParagraphMasterAtom (SJ)" );
+ break;
+ case PPT_PST_HashCodeAtom :
+ case PPT_PST_BuildList :
+ case PPT_PST_SlideFlags10Atom :
+ case PPT_PST_SlideTime10Atom :
+ case 0xf144 :
+ break;
+ }
+ if (!aHd.SeekToEndOfRecord(rSt))
+ break;
+ }
+ }
+ rSt.Seek( nOldPos );
+}
+
+PPTExtParaProv::~PPTExtParaProv()
+{
+}
+
+PPTNumberFormatCreator::PPTNumberFormatCreator( std::unique_ptr<PPTExtParaProv> pParaProv )
+ : nIsBullet(0)
+ , nBulletChar(0)
+ , nBulletFont(0)
+ , nBulletHeight(0)
+ , nBulletColor(0)
+ , nTextOfs(0)
+ , nBulletOfs(0)
+ , pExtParaProv(std::move(pParaProv))
+{
+}
+
+PPTNumberFormatCreator::~PPTNumberFormatCreator()
+{
+}
+
+bool PPTNumberFormatCreator::ImplGetExtNumberFormat( SdrPowerPointImport const & rManager,
+ SvxNumberFormat& rNumberFormat, sal_uInt32 nLevel, TSS_Type nInstance, TSS_Type nDestinationInstance,
+ std::optional< sal_Int16 >& rStartNumbering, sal_uInt32 nFontHeight, PPTParagraphObj const * pPara )
+{
+ bool bHardAttribute = ( nDestinationInstance == TSS_Type::Unknown );
+
+ sal_uInt32 nBuFlags = 0;
+ sal_uInt16 nHasAnm = 0;
+ sal_uInt32 nAnmScheme = 0xFFFF0003;
+ sal_uInt16 nBuBlip = 0xffff;
+
+ const PPTExtParaProv* pParaProv = pExtParaProv.get();
+ if ( !pExtParaProv )
+ pParaProv = pPara ? pPara->mrStyleSheet.pExtParaProv.get()
+ : rManager.m_pPPTStyleSheet->pExtParaProv.get();
+ if ( pPara )
+ {
+ nBuFlags = pPara->mxParaSet->mnExtParagraphMask;
+ if ( nBuFlags )
+ {
+ if ( nBuFlags & 0x00800000 )
+ nBuBlip = pPara->mxParaSet->mnBuBlip;
+ if ( nBuFlags & 0x01000000 )
+ nAnmScheme = pPara->mxParaSet->mnAnmScheme;
+ if ( nBuFlags & 0x02000000 )
+ nHasAnm = pPara->mxParaSet->mnHasAnm;
+ bHardAttribute = true;
+ }
+ }
+
+ if ( ( nBuFlags & 0x03800000 ) != 0x03800000 ) // merge style sheet
+ {
+ // we have to read the master attributes
+ if (pParaProv && nLevel < nMaxPPTLevels)
+ {
+ if ( pParaProv->bStyles )
+ {
+ const PPTExtParaLevel& rLev = pParaProv->aExtParaSheet[ nInstance ].aExtParaLevel[ nLevel ];
+ if ( rLev.mbSet )
+ {
+ sal_uInt32 nMaBuFlags = rLev.mnExtParagraphMask;
+
+ if ( (!( nBuFlags & 0x00800000)) && ( nMaBuFlags & 0x00800000 ) )
+ {
+ if (!( nBuFlags & 0x02000000)) // if there is a BuStart without BuInstance,
+ nBuBlip = rLev.mnBuBlip; // then there is no graphical Bullet possible
+ }
+ if ( (!( nBuFlags & 0x01000000)) && ( nMaBuFlags & 0x01000000 ) )
+ nAnmScheme = rLev.mnAnmScheme;
+ if ( (!( nBuFlags & 0x02000000)) && ( nMaBuFlags & 0x02000000 ) )
+ nHasAnm = rLev.mnHasAnm;
+ nBuFlags |= nMaBuFlags;
+ }
+ }
+ }
+ }
+ if ( nBuBlip != 0xffff ) // set graphical bullet
+ {
+ Graphic aGraphic;
+ if ( pParaProv && pParaProv->GetGraphic( nBuBlip, aGraphic ) )
+ {
+ SvxBrushItem aBrush( aGraphic, GPOS_MM, SID_ATTR_BRUSH );
+ rNumberFormat.SetGraphicBrush( &aBrush );
+ sal_uInt32 nHeight = static_cast<sal_uInt32>( static_cast<double>(nFontHeight) * 0.2540 * nBulletHeight + 0.5 );
+ Size aPrefSize( aGraphic.GetPrefSize() );
+ sal_uInt32 nWidth;
+ if (aPrefSize.Height())
+ nWidth = ( nHeight * aPrefSize.Width() ) / aPrefSize.Height();
+ else
+ nWidth = 0;
+ rNumberFormat.SetGraphicSize( Size( nWidth, nHeight ) );
+ rNumberFormat.SetNumberingType ( SVX_NUM_BITMAP );
+ }
+ }
+ else if ( nHasAnm )
+ {
+ switch( static_cast< sal_uInt16 >( nAnmScheme ) )
+ {
+ default :
+ case 0 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
+ rNumberFormat.SetSuffix( "." );
+ }
+ break;
+ case 1 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
+ rNumberFormat.SetSuffix( "." );
+ }
+ break;
+ case 2 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
+ rNumberFormat.SetSuffix( ")" );
+ }
+ break;
+ case 3 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
+ rNumberFormat.SetSuffix( "." );
+ }
+ break;
+ case 4 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
+ rNumberFormat.SetSuffix( ")" );
+ rNumberFormat.SetPrefix( "(" );
+ }
+ break;
+ case 5 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
+ rNumberFormat.SetSuffix( ")" );
+ }
+ break;
+ case 6 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_LOWER );
+ rNumberFormat.SetSuffix( "." );
+ }
+ break;
+ case 7 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
+ rNumberFormat.SetSuffix( "." );
+ }
+ break;
+ case 8 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
+ rNumberFormat.SetSuffix( ")" );
+ rNumberFormat.SetPrefix( "(" );
+ }
+ break;
+ case 9 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_CHARS_LOWER_LETTER );
+ rNumberFormat.SetSuffix( ")" );
+ }
+ break;
+ case 10 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
+ rNumberFormat.SetSuffix( ")" );
+ rNumberFormat.SetPrefix( "(" );
+ }
+ break;
+ case 11 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_CHARS_UPPER_LETTER );
+ rNumberFormat.SetSuffix( ")" );
+ }
+ break;
+ case 12 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
+ rNumberFormat.SetSuffix( ")" );
+ rNumberFormat.SetPrefix( "(" );
+ }
+ break;
+ case 13 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ARABIC );
+ }
+ break;
+ case 14 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
+ rNumberFormat.SetSuffix( ")" );
+ rNumberFormat.SetPrefix( "(" );
+ }
+ break;
+ case 15 :
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_ROMAN_UPPER );
+ rNumberFormat.SetSuffix( ")" );
+ }
+ break;
+ case 16: // Simplified Chinese.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH );
+ }
+ break;
+ case 17: // Simplified Chinese with single-byte period.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH );
+ rNumberFormat.SetSuffix( "." );
+ }
+ break;
+ case 18: // Double byte circle numbers.
+ case 19: // Wingdings white circle numbers.
+ case 20: // Wingdings black circle numbers.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_CIRCLE_NUMBER );
+ }
+ break;
+ case 21: // Traditional Chinese.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH_TW );
+ }
+ break;
+ case 22: // Traditional Chinese with single-byte period.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_UPPER_ZH_TW );
+ rNumberFormat.SetSuffix( "." );
+ }
+ break;
+ case 25: // Bidi Hebrew 2 with ANSI minus symbol.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_HEBREW );
+ rNumberFormat.SetSuffix( "-" );
+ }
+ break;
+ case 26: // Japanese/Korean.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH );
+ }
+ break;
+ case 27: // Japanese/Korean with single-byte period.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH );
+ rNumberFormat.SetSuffix( "." );
+ }
+ break;
+ case 28: // Double-byte Arabic numbers.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_FULL_WIDTH_ARABIC );
+ }
+ break;
+ case 29: // Double-byte Arabic numbers with double-byte period.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_FULL_WIDTH_ARABIC );
+ rNumberFormat.SetSuffix( OUString( u'\xff0e' ) );
+ }
+ break;
+ case 38: // Japanese with double-byte period.
+ {
+ rNumberFormat.SetNumberingType( SVX_NUM_NUMBER_LOWER_ZH ); // No such type. Instead with Lower Chinese Number
+ rNumberFormat.SetSuffix( OUString( u'\xff0e' ) );
+ }
+ break;
+ }
+ rStartNumbering = std::optional< sal_Int16 >( nAnmScheme >> 16 );
+ sal_Int16 nBuStart = *rStartNumbering;
+ //The Seventh bit of nBuFlags that specifies whether fBulletHasAutoNumber exists,
+ //and fBulletHasAutoNumber that specifies whether this paragraph has an automatic numbering scheme.
+ if ( ( nBuFlags & 0x02000000 ) && ( nBuStart != -1 ))
+ {
+ rNumberFormat.SetStart( static_cast<sal_uInt16>(nBuStart) );
+ }
+ }
+ return bHardAttribute;
+}
+
+void PPTNumberFormatCreator::GetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat, sal_uInt32 nLevel, const PPTParaLevel& rParaLevel, const PPTCharLevel& rCharLevel, TSS_Type nInstance )
+{
+ nIsBullet = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn ) ) != 0 ? 1 : 0;
+ nBulletChar = rParaLevel.mnBulletChar;
+
+ bool bBuHardFont;
+ bBuHardFont = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
+ if ( bBuHardFont )
+ nBulletFont = rParaLevel.mnBulletFont;
+ else
+ nBulletFont = rCharLevel.mnFont;
+ nBulletHeight = rParaLevel.mnBulletHeight;
+ nBulletColor = rParaLevel.mnBulletColor;
+ nTextOfs = rParaLevel.mnTextOfs;
+ nBulletOfs = rParaLevel.mnBulletOfs;
+
+ std::optional< sal_Int16 > oStartNumbering;
+ ImplGetExtNumberFormat( rManager, rNumberFormat, nLevel, nInstance, TSS_Type::Unknown, oStartNumbering, rCharLevel.mnFontHeight, nullptr );
+ if ( ( rNumberFormat.GetNumberingType() != SVX_NUM_BITMAP ) && ( nBulletHeight > 0x7fff ) )
+ nBulletHeight = rCharLevel.mnFontHeight ? ((- static_cast<sal_Int16>(nBulletHeight)) * 100 ) / rCharLevel.mnFontHeight : 100;
+ ImplGetNumberFormat( rManager, rNumberFormat );
+ switch ( rNumberFormat.GetNumberingType() )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER :
+ case SVX_NUM_CHARS_LOWER_LETTER :
+ case SVX_NUM_ROMAN_UPPER :
+ case SVX_NUM_ROMAN_LOWER :
+ case SVX_NUM_ARABIC :
+ case SVX_NUM_CHARS_UPPER_LETTER_N :
+ case SVX_NUM_CHARS_LOWER_LETTER_N :
+ {
+ sal_uInt32 nFont = rCharLevel.mnFont;
+ const PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nFont );
+ if ( pFontEnityAtom )
+ {
+ vcl::Font aFont;
+ aFont.SetCharSet( pFontEnityAtom->eCharSet );
+ aFont.SetFamilyName( pFontEnityAtom->aName );
+ aFont.SetFamily( pFontEnityAtom->eFamily );
+ aFont.SetPitch( pFontEnityAtom->ePitch );
+ rNumberFormat.SetBulletFont( &aFont );
+ }
+ }
+ break;
+ default: break;
+ }
+}
+
+bool PPTNumberFormatCreator::GetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat, PPTParagraphObj* pParaObj,
+ TSS_Type nDestinationInstance, std::optional< sal_Int16 >& rStartNumbering )
+{
+ sal_uInt32 nHardCount = 0;
+ nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletOn, nIsBullet, nDestinationInstance ) ? 1 : 0;
+ nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletChar, nBulletChar, nDestinationInstance ) ? 1 : 0;
+ nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletFont, nBulletFont, nDestinationInstance ) ? 1 : 0;
+ nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletHeight, nBulletHeight, nDestinationInstance ) ? 1 : 0;
+ nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletColor, nBulletColor, nDestinationInstance ) ? 1 : 0;
+ nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_TextOfs, nTextOfs, nDestinationInstance ) ? 1 : 0;
+ nHardCount += pParaObj->GetAttrib( PPT_ParaAttr_BulletOfs, nBulletOfs, nDestinationInstance ) ? 1 : 0;
+
+ if ( nIsBullet )
+ rNumberFormat.SetNumberingType( SVX_NUM_CHAR_SPECIAL );
+
+ sal_uInt32 nFontHeight = 24;
+ PPTPortionObj* pPtr = pParaObj->First();
+ if ( pPtr )
+ pPtr->GetAttrib( PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance );
+ if ( nIsBullet )
+ nHardCount += ImplGetExtNumberFormat( rManager, rNumberFormat, pParaObj->mxParaSet->mnDepth,
+ pParaObj->mnInstance, nDestinationInstance, rStartNumbering, nFontHeight, pParaObj ) ? 1 : 0;
+
+ if ( rNumberFormat.GetNumberingType() != SVX_NUM_BITMAP )
+ pParaObj->UpdateBulletRelSize( nBulletHeight );
+ if ( nHardCount )
+ {
+ ImplGetNumberFormat( rManager, rNumberFormat );
+ switch ( rNumberFormat.GetNumberingType() )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER :
+ case SVX_NUM_CHARS_LOWER_LETTER :
+ case SVX_NUM_ROMAN_UPPER :
+ case SVX_NUM_ROMAN_LOWER :
+ case SVX_NUM_ARABIC :
+ case SVX_NUM_CHARS_UPPER_LETTER_N :
+ case SVX_NUM_CHARS_LOWER_LETTER_N :
+ {
+ if ( pPtr )
+ {
+ sal_uInt32 nFont;
+ pPtr->GetAttrib( PPT_CharAttr_Font, nFont, nDestinationInstance );
+ const PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nFont );
+ if ( pFontEnityAtom )
+ {
+ vcl::Font aFont;
+ aFont.SetCharSet( pFontEnityAtom->eCharSet );
+ aFont.SetFamilyName( pFontEnityAtom->aName );
+ aFont.SetFamily( pFontEnityAtom->eFamily );
+ aFont.SetPitch( pFontEnityAtom->ePitch );
+ rNumberFormat.SetBulletFont( &aFont );
+ }
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+ return nHardCount != 0;
+}
+
+void PPTNumberFormatCreator::ImplGetNumberFormat( SdrPowerPointImport const & rManager, SvxNumberFormat& rNumberFormat )
+{
+ vcl::Font aFont;
+ const PptFontEntityAtom* pAtom = rManager.GetFontEnityAtom( nBulletFont );
+ if ( pAtom )
+ {
+ rtl_TextEncoding eCharSet( pAtom->eCharSet );
+ aFont.SetFamilyName( pAtom->aName );
+ aFont.SetCharSet( eCharSet );
+ aFont.SetFamily( pAtom->eFamily );
+ aFont.SetPitch( pAtom->ePitch );
+ }
+ Color aCol( rManager.MSO_TEXT_CLR_ToColor( nBulletColor ) );
+ aFont.SetColor( aCol );
+
+ sal_uInt16 nBuChar = static_cast<sal_uInt16>(nBulletChar);
+ if ( aFont.GetCharSet() == RTL_TEXTENCODING_SYMBOL )
+ {
+ nBuChar &= 0x00ff;
+ nBuChar |= 0xf000;
+ }
+ rNumberFormat.SetBulletFont( &aFont );
+ rNumberFormat.SetBulletChar( nBuChar );
+ rNumberFormat.SetBulletRelSize( static_cast<sal_uInt16>(nBulletHeight) );
+ rNumberFormat.SetBulletColor( aCol );
+ sal_uInt32 nAbsLSpace = convertMasterUnitToMm100(nTextOfs);
+ sal_uInt32 nFirstLineOffset = nAbsLSpace - convertMasterUnitToMm100(nBulletOfs);
+ rNumberFormat.SetAbsLSpace( nAbsLSpace );
+ rNumberFormat.SetFirstLineOffset( -static_cast<sal_Int32>(nFirstLineOffset) );
+}
+
+PPTCharSheet::PPTCharSheet( TSS_Type nInstance )
+{
+ sal_uInt32 nColor = PPT_COLSCHEME_TEXT_UND_ZEILEN;
+ sal_uInt16 nFontHeight(0);
+ switch ( nInstance )
+ {
+ case TSS_Type::PageTitle :
+ case TSS_Type::Title :
+ {
+ nColor = PPT_COLSCHEME_TITELTEXT;
+ nFontHeight = 44;
+ }
+ break;
+ case TSS_Type::Body :
+ case TSS_Type::Subtitle :
+ case TSS_Type::HalfBody :
+ case TSS_Type::QuarterBody :
+ nFontHeight = 32;
+ break;
+ case TSS_Type::Notes :
+ nFontHeight = 12;
+ break;
+ case TSS_Type::Unused :
+ case TSS_Type::TextInShape :
+ nFontHeight = 24;
+ break;
+ default: break;
+ }
+ for (PPTCharLevel & nDepth : maCharLevel)
+ {
+ nDepth.mnFlags = 0;
+ nDepth.mnFont = 0;
+ nDepth.mnAsianOrComplexFont = 0xffff;
+ nDepth.mnFontHeight = nFontHeight;
+ nDepth.mnFontColor = nColor;
+ nDepth.mnFontColorInStyleSheet = Color( static_cast<sal_uInt8>(nColor), static_cast<sal_uInt8>( nColor >> 8 ), static_cast<sal_uInt8>( nColor >> 16 ) );
+ nDepth.mnEscapement = 0;
+ }
+}
+
+void PPTCharSheet::Read( SvStream& rIn, sal_uInt32 nLevel)
+{
+ // character attributes
+ sal_uInt32 nCMask(0);
+ sal_uInt16 nVal16;
+ rIn.ReadUInt32(nCMask);
+
+ if ( nCMask & 0x0000FFFF )
+ {
+ sal_uInt16 nBitAttr(0);
+ maCharLevel[ nLevel ].mnFlags &= ~static_cast<sal_uInt16>(nCMask);
+ rIn.ReadUInt16( nBitAttr ); // Bit attributes (bold, underlined, ...)
+ maCharLevel[ nLevel ].mnFlags |= nBitAttr;
+ }
+ if ( nCMask & ( 1 << PPT_CharAttr_Font ) ) // 0x00010000
+ rIn.ReadUInt16( maCharLevel[ nLevel ].mnFont );
+ if ( nCMask & ( 1 << PPT_CharAttr_AsianOrComplexFont ) ) // 0x00200000
+ rIn.ReadUInt16( maCharLevel[ nLevel ].mnAsianOrComplexFont );
+ if ( nCMask & ( 1 << PPT_CharAttr_ANSITypeface ) ) // 0x00400000
+ rIn.ReadUInt16( nVal16 );
+ if ( nCMask & ( 1 << PPT_CharAttr_Symbol ) ) // 0x00800000
+ rIn.ReadUInt16( nVal16 );
+ if ( nCMask & ( 1 << PPT_CharAttr_FontHeight ) ) // 0x00020000
+ rIn.ReadUInt16( maCharLevel[ nLevel ].mnFontHeight );
+ if ( nCMask & ( 1 << PPT_CharAttr_FontColor ) ) // 0x00040000
+ {
+ rIn.ReadUInt32( maCharLevel[ nLevel ].mnFontColor );
+ if( ! (maCharLevel[ nLevel ].mnFontColor & 0xff000000 ) )
+ maCharLevel[ nLevel ].mnFontColor = PPT_COLSCHEME_HINTERGRUND;
+ }
+ if ( nCMask & ( 1 << PPT_CharAttr_Escapement ) ) // 0x00080000
+ rIn.ReadUInt16( maCharLevel[ nLevel ].mnEscapement );
+ if ( nCMask & 0x00100000 ) // 0x00100000
+ rIn.ReadUInt16( nVal16 );
+
+ nCMask >>= 24;
+ while( nCMask )
+ {
+ if ( nCMask & 1 )
+ {
+ OSL_FAIL( "PPTCharSheet::Read - unknown attribute, send me this document (SJ)" );
+ rIn.ReadUInt16( nVal16 );
+ }
+ nCMask >>= 1;
+ }
+}
+
+PPTParaSheet::PPTParaSheet( TSS_Type nInstance )
+{
+ sal_uInt16 nBuFlags = 0;
+ sal_uInt32 nBulletColor = 0x8000000;
+ sal_uInt16 nUpperDist = 0;
+
+ switch ( nInstance )
+ {
+ case TSS_Type::PageTitle :
+ case TSS_Type::Title :
+ nBulletColor = PPT_COLSCHEME_TITELTEXT;
+ break;
+ case TSS_Type::Body :
+ case TSS_Type::Subtitle :
+ case TSS_Type::HalfBody :
+ case TSS_Type::QuarterBody :
+ {
+ nBuFlags = 1;
+ nUpperDist = 0x14;
+ }
+ break;
+ case TSS_Type::Notes :
+ nUpperDist = 0x1e;
+ break;
+ default: break;
+ }
+ for (PPTParaLevel & i : maParaLevel)
+ {
+ i.mnBuFlags = nBuFlags;
+ i.mnBulletChar = 0x2022;
+ i.mnBulletFont = 0;
+ i.mnBulletHeight = 100;
+ i.mnBulletColor = nBulletColor;
+ i.mnAdjust = 0;
+ i.mnLineFeed = 100;
+ i.mnLowerDist = 0;
+ i.mnUpperDist = nUpperDist;
+ i.mnTextOfs = 0;
+ i.mnBulletOfs = 0;
+ i.mnDefaultTab = 0x240;
+ i.mnAsianLineBreak = 0;
+ i.mnBiDi = 0;
+ }
+}
+
+void PPTParaSheet::Read( SdrPowerPointImport const &
+#ifdef DBG_UTIL
+ rManager
+#endif
+ , SvStream& rIn
+ , sal_uInt32 nLevel, bool bFirst )
+{
+ // paragraph attributes
+ sal_uInt32 nPMask(0);
+ rIn.ReadUInt32(nPMask);
+
+ sal_uInt16 nMask16 = static_cast<sal_uInt16>(nPMask) & 0xf;
+ if ( nMask16 )
+ {
+ sal_uInt16 nVal16(0);
+ rIn.ReadUInt16( nVal16 );
+ maParaLevel[ nLevel ].mnBuFlags &=~ nMask16;
+ nVal16 &= nMask16;
+ maParaLevel[ nLevel ].mnBuFlags |= nVal16;
+ }
+ if ( nPMask & 0x0080 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletChar );
+ if ( nPMask & 0x0010 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletFont );
+ if ( nPMask & 0x0040 )
+ {
+ sal_uInt16 nVal16(0);
+ rIn.ReadUInt16( nVal16 );
+ maParaLevel[ nLevel ].mnBulletHeight = nVal16;
+ }
+ if ( nPMask & 0x0020 )
+ {
+ sal_uInt32 nVal32(0);
+ rIn.ReadUInt32(nVal32);
+ maParaLevel[ nLevel ].mnBulletColor = nVal32;
+ }
+ if ( bFirst )
+ {
+ if ( nPMask & 0xF00 )
+ {
+ // AbsJust!
+ sal_uInt16 nVal16(0);
+ rIn.ReadUInt16( nVal16 );
+ maParaLevel[ nLevel ].mnAdjust = nVal16 & 3;
+ }
+ if ( nPMask & 0x1000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnLineFeed );
+ if ( nPMask & 0x2000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnUpperDist );
+ if ( nPMask & 0x4000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnLowerDist );
+ if ( nPMask & 0x8000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnTextOfs );
+ if ( nPMask & 0x10000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletOfs );
+ if ( nPMask & 0x20000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnDefaultTab );
+ if ( nPMask & 0x200000 )
+ {
+ sal_uInt16 nVal16;
+ sal_uInt32 nVal32;
+ // number of tabulators
+ rIn.ReadUInt16( nVal16 );
+ if (!rIn.good() || rIn.remainingSize() / sizeof(nVal32) < nVal16)
+ return;
+ for (sal_uInt16 i = 0; i < nVal16; ++i)
+ rIn.ReadUInt32( nVal32 ); // reading the tabulators
+ }
+ if ( nPMask & 0x40000 )
+ {
+ sal_uInt16 nVal16;
+ rIn.ReadUInt16( nVal16 );
+ }
+ if ( nPMask & 0x80000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnAsianLineBreak );
+ if ( nPMask & 0x100000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnBiDi );
+ }
+ else
+ {
+ if ( nPMask & 0x800 )
+ {
+ sal_uInt16 nVal16(0);
+ rIn.ReadUInt16( nVal16 );
+ maParaLevel[ nLevel ].mnAdjust = nVal16 & 3;
+ }
+ if ( nPMask & 0x1000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnLineFeed );
+ if ( nPMask & 0x2000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnUpperDist );
+ if ( nPMask & 0x4000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnLowerDist );
+ if ( nPMask & 0x8000 )
+ {
+ sal_uInt16 nVal16;
+ rIn.ReadUInt16( nVal16 );
+ }
+ if ( nPMask & 0x100 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnTextOfs );
+ if ( nPMask & 0x200 )
+ {
+ sal_uInt16 nVal16;
+ rIn.ReadUInt16( nVal16 );
+ }
+ if ( nPMask & 0x400 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnBulletOfs );
+ if ( nPMask & 0x10000 )
+ {
+ sal_uInt16 nVal16;
+ rIn.ReadUInt16( nVal16 );
+ }
+ if ( nPMask & 0xe0000 )
+ {
+ sal_uInt16 nFlagsToModifyMask = static_cast<sal_uInt16>( ( nPMask >> 17 ) & 7 );
+ sal_uInt16 nVal16(0);
+ rIn.ReadUInt16( nVal16 );
+ // bits that are not involved to zero
+ nVal16 &= nFlagsToModifyMask;
+ // bits that are to change to zero
+ maParaLevel[ nLevel ].mnAsianLineBreak &=~nFlagsToModifyMask;
+ // now set the corresponding bits
+ maParaLevel[ nLevel ].mnAsianLineBreak |= nVal16;
+ }
+ if ( nPMask & 0x100000 )
+ {
+ sal_uInt16 nVal16;
+ sal_uInt32 nVal32;
+ // number of tabulators
+ rIn.ReadUInt16( nVal16 );
+ if (!rIn.good() || rIn.remainingSize() / sizeof(nVal32) < nVal16)
+ return;
+ for (sal_uInt16 i = 0; i < nVal16; ++i)
+ rIn.ReadUInt32( nVal32 ); // reading the tabulators
+ }
+ if ( nPMask & 0x200000 )
+ rIn.ReadUInt16( maParaLevel[ nLevel ].mnBiDi );
+ }
+
+ nPMask >>= 22;
+ while( nPMask )
+ {
+ if ( nPMask & 1 )
+ {
+#ifdef DBG_UTIL
+ if (!(rManager.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
+ {
+ OSL_FAIL( "PPTParaSheet::Read - unknown attribute, send me this document (SJ)" );
+ }
+#endif
+ sal_uInt16 nVal16;
+ rIn.ReadUInt16( nVal16 );
+ }
+ nPMask >>= 1;
+ }
+}
+
+void PPTParaSheet::UpdateBulletRelSize( sal_uInt32 nLevel, sal_uInt16 nFontHeight )
+{
+ if ( maParaLevel[ nLevel ].mnBulletHeight > 0x7fff ) // a negative value is the absolute bullet height
+ {
+ sal_Int16 nBulletRelSize = static_cast<sal_Int16>(maParaLevel[ nLevel ].mnBulletHeight);
+ nBulletRelSize = nFontHeight ? ((-nBulletRelSize) * 100 ) / nFontHeight : 100;
+ if ( nBulletRelSize < 0 ) //bullet size over flow
+ nBulletRelSize = 100;
+ maParaLevel[ nLevel ].mnBulletHeight = nBulletRelSize;
+ }
+}
+
+PPTStyleSheet::PPTStyleSheet( const DffRecordHeader& rSlideHd, SvStream& rIn, SdrPowerPointImport& rManager,
+ const PPTTextParagraphStyleAtomInterpreter& rTxPFStyle,
+ const PPTTextSpecInfo& rTextSpecInfo ) :
+
+ PPTNumberFormatCreator ( std::make_unique<PPTExtParaProv>( rManager, rIn, &rSlideHd ) ),
+ maTxSI ( rTextSpecInfo )
+{
+ sal_uInt32 nOldFilePos = rIn.Tell();
+
+ // default stylesheets
+ mpCharSheet[ TSS_Type::PageTitle ] = std::make_unique<PPTCharSheet>( TSS_Type::PageTitle );
+ mpCharSheet[ TSS_Type::Body ] = std::make_unique<PPTCharSheet>( TSS_Type::Body );
+ mpCharSheet[ TSS_Type::Notes ] = std::make_unique<PPTCharSheet>( TSS_Type::Notes );
+ mpCharSheet[ TSS_Type::Unused ] = std::make_unique<PPTCharSheet>( TSS_Type::Unused ); // this entry is not used by ppt
+ mpCharSheet[ TSS_Type::TextInShape ] = std::make_unique<PPTCharSheet>( TSS_Type::TextInShape );
+ mpParaSheet[ TSS_Type::PageTitle ] = std::make_unique<PPTParaSheet>( TSS_Type::PageTitle );
+ mpParaSheet[ TSS_Type::Body ] = std::make_unique<PPTParaSheet>( TSS_Type::Body );
+ mpParaSheet[ TSS_Type::Notes ] = std::make_unique<PPTParaSheet>( TSS_Type::Notes );
+ mpParaSheet[ TSS_Type::Unused ] = std::make_unique<PPTParaSheet>( TSS_Type::Unused );
+ mpParaSheet[ TSS_Type::TextInShape ] = std::make_unique<PPTParaSheet>( TSS_Type::TextInShape );
+ // mpCharSheet[ TSS_Type::QuarterBody ], mpCharSheet[ TSS_Type::HalfBody ], mpCharSheet[ TSS_Type::Title ], mpCharSheet[ TSS_Type::Subtitle ] intentionally null
+ // mpParaSheet[ TSS_Type::QuarterBody ], mpParaSheet[ TSS_Type::HalfBody ], mpParaSheet[ TSS_Type::Title ], mpParaSheet[ TSS_Type::Subtitle ] intentionally null
+
+ /* SJ: try to locate the txMasterStyleAtom in the Environment
+
+ it seems that the environment TextStyle is having a higher priority
+ than the TextStyle that can be found within the master page
+ */
+ bool bFoundTxMasterStyleAtom04 = false;
+ DffRecordHeader* pEnvHeader = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment );
+ if ( pEnvHeader )
+ {
+ pEnvHeader->SeekToContent( rIn );
+ DffRecordHeader aTxMasterStyleHd;
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pEnvHeader->GetRecEndFilePos());
+ while (rIn.Tell() < nEndRecPos)
+ {
+ ReadDffRecordHeader( rIn, aTxMasterStyleHd );
+ if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom )
+ {
+ sal_uInt16 nLevelCnt(0);
+ rIn.ReadUInt16(nLevelCnt);
+
+ sal_uInt16 nLev = 0;
+ bool bFirst = true;
+ bFoundTxMasterStyleAtom04 = true;
+ auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd.GetRecEndFilePos());
+ while (rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt && nLev < nMaxPPTLevels)
+ {
+ if ( nLev )
+ {
+ mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev ] = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev - 1 ];
+ mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ] = mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev - 1 ];
+ }
+ mpParaSheet[ TSS_Type::TextInShape ]->Read( rManager, rIn, nLev, bFirst );
+ if ( !nLev )
+ {
+ // set paragraph defaults for instance 4 (TSS_Type::TextInShape)
+ if ( rTxPFStyle.bValid )
+ {
+ PPTParaLevel& rParaLevel = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ 0 ];
+ rParaLevel.mnAsianLineBreak = 0;
+ if ( rTxPFStyle.bForbiddenRules )
+ rParaLevel.mnAsianLineBreak |= 1;
+ if ( !rTxPFStyle.bLatinTextWrap )
+ rParaLevel.mnAsianLineBreak |= 2;
+ if ( rTxPFStyle.bHangingPunctuation )
+ rParaLevel.mnAsianLineBreak |= 4;
+ }
+ }
+ mpCharSheet[ TSS_Type::TextInShape ]->Read( rIn, nLev );
+ mpParaSheet[ TSS_Type::TextInShape ]->UpdateBulletRelSize( nLev, mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ].mnFontHeight );
+ bFirst = false;
+ nLev++;
+ }
+ break;
+ }
+ else
+ {
+ if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
+ break;
+ }
+ }
+ }
+
+ rSlideHd.SeekToContent( rIn );
+
+ DffRecordHeader aTxMasterStyleHd;
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rSlideHd.GetRecEndFilePos());
+ while (rIn.Tell() < nEndRecPos)
+ {
+ ReadDffRecordHeader( rIn, aTxMasterStyleHd );
+ if ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom )
+ break;
+ else
+ {
+ if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
+ break;
+ }
+ }
+ while ( ( aTxMasterStyleHd.nRecType == PPT_PST_TxMasterStyleAtom ) && ( rIn.Tell() < nEndRecPos ) ) //TODO: aTxMasterStyleHd may be used without having been properly initialized
+ {
+ TSS_Type nInstance = static_cast<TSS_Type>(aTxMasterStyleHd.nRecInstance);
+ if ( ( nInstance <= TSS_Type::LAST ) &&
+ ( ( nInstance != TSS_Type::TextInShape ) || !bFoundTxMasterStyleAtom04 ) )
+ {
+ if ( nInstance > TSS_Type::TextInShape )
+ {
+ mpCharSheet[ nInstance ].reset(); // be sure to delete the old one if this instance comes twice
+ mpParaSheet[ nInstance ].reset();
+
+ switch ( nInstance )
+ {
+ case TSS_Type::Subtitle :
+ {
+ mpCharSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
+ mpParaSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
+ }
+ break;
+ case TSS_Type::Title :
+ {
+ mpCharSheet[ TSS_Type::Title ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::PageTitle ] ) );
+ mpParaSheet[ TSS_Type::Title ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::PageTitle ] ) );
+ }
+ break;
+ case TSS_Type::HalfBody :
+ {
+ mpCharSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
+ mpParaSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
+ }
+ break;
+
+ case TSS_Type::QuarterBody :
+ {
+ mpCharSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
+ mpParaSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
+ }
+ break;
+ default: break;
+ }
+ }
+ sal_uInt16 nLevelCnt(0);
+ rIn.ReadUInt16(nLevelCnt);
+ if (nLevelCnt > nMaxPPTLevels)
+ {
+ OSL_FAIL( "PPTStyleSheet::Ppt-TextStylesheet has more than 5 levels! (SJ)" );
+ nLevelCnt = nMaxPPTLevels;
+ }
+ sal_uInt16 nLev = 0;
+ bool bFirst = true;
+
+ auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd.GetRecEndFilePos());
+ while ( rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt )
+ {
+ if ( nLev && ( nInstance < TSS_Type::Subtitle ) )
+ {
+ mpParaSheet[ nInstance ]->maParaLevel[ nLev ] = mpParaSheet[ nInstance ]->maParaLevel[ nLev - 1 ];
+ mpCharSheet[ nInstance ]->maCharLevel[ nLev ] = mpCharSheet[ nInstance ]->maCharLevel[ nLev - 1 ];
+ }
+
+ // Exception: Template 5, 6 (MasterTitle Title and SubTitle)
+ if ( nInstance >= TSS_Type::Subtitle )
+ {
+ bFirst = false;
+
+ sal_uInt16 nDontKnow;
+ rIn.ReadUInt16( nDontKnow );
+ }
+ mpParaSheet[ nInstance ]->Read( rManager, rIn, nLev, bFirst );
+ mpCharSheet[ nInstance ]->Read( rIn, nLev );
+ mpParaSheet[ nInstance ]->UpdateBulletRelSize( nLev, mpCharSheet[ nInstance ]->maCharLevel[ nLev ].mnFontHeight );
+ bFirst = false;
+ nLev++;
+ }
+#ifdef DBG_UTIL
+ if (!(rManager.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
+ {
+ if ( rIn.GetError() == ERRCODE_NONE )
+ {
+ OStringBuffer aMsg;
+ if ( rIn.Tell() > aTxMasterStyleHd.GetRecEndFilePos() )
+ {
+ aMsg.append("\n reading too many bytes:" +
+ OString::number(rIn.Tell() - aTxMasterStyleHd.GetRecEndFilePos()));
+ }
+ if ( rIn.Tell() < aTxMasterStyleHd.GetRecEndFilePos() )
+ {
+ aMsg.append("\n reading too few bytes:" +
+ OString::number(aTxMasterStyleHd.GetRecEndFilePos() - rIn.Tell()));
+ }
+ if (aMsg.getLength())
+ {
+ aMsg.insert(0, "PptStyleSheet::operator>>[]");
+ OSL_FAIL(aMsg.getStr());
+ }
+ }
+ if ( rIn.Tell() != aTxMasterStyleHd.GetRecEndFilePos() )
+ SAL_WARN( "filter.ms", "SJ: Wrong number of bytes read during import of PPT style");
+ }
+#endif
+ }
+ if (!aTxMasterStyleHd.SeekToEndOfRecord(rIn))
+ break;
+ ReadDffRecordHeader( rIn, aTxMasterStyleHd );
+ }
+ if ( !mpCharSheet[ TSS_Type::Subtitle ] )
+ {
+ mpCharSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
+ mpParaSheet[ TSS_Type::Subtitle ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
+ }
+ if ( !mpCharSheet[ TSS_Type::Title ] )
+ {
+ mpCharSheet[ TSS_Type::Title ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::PageTitle ] ) );
+ mpParaSheet[ TSS_Type::Title ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::PageTitle ] ) );
+ }
+ if ( !mpCharSheet[ TSS_Type::HalfBody ] )
+ {
+ mpCharSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
+ mpParaSheet[ TSS_Type::HalfBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
+ }
+ if ( !mpCharSheet[ TSS_Type::QuarterBody ] )
+ {
+ mpCharSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTCharSheet>( *( mpCharSheet[ TSS_Type::Body ] ) );
+ mpParaSheet[ TSS_Type::QuarterBody ] = std::make_unique<PPTParaSheet>( *( mpParaSheet[ TSS_Type::Body ] ) );
+ }
+ if ( !bFoundTxMasterStyleAtom04 )
+ { // try to locate the txMasterStyleAtom in the Environment
+ DffRecordHeader* pEnvHeader2 = rManager.aDocRecManager.GetRecordHeader( PPT_PST_Environment );
+ if ( pEnvHeader2 )
+ {
+ pEnvHeader2->SeekToContent( rIn );
+ DffRecordHeader aTxMasterStyleHd2;
+ auto nEnvEndRecPos = DffPropSet::SanitizeEndPos(rIn, pEnvHeader2->GetRecEndFilePos());
+ while (rIn.Tell() < nEnvEndRecPos)
+ {
+ ReadDffRecordHeader( rIn, aTxMasterStyleHd2 );
+ if ( aTxMasterStyleHd2.nRecType == PPT_PST_TxMasterStyleAtom )
+ {
+ sal_uInt16 nLevelCnt;
+ rIn.ReadUInt16( nLevelCnt );
+
+ sal_uInt16 nLev = 0;
+ bool bFirst = true;
+ auto nTxEndRecPos = DffPropSet::SanitizeEndPos(rIn, aTxMasterStyleHd2.GetRecEndFilePos());
+ while ( rIn.GetError() == ERRCODE_NONE && rIn.Tell() < nTxEndRecPos && nLev < nLevelCnt )
+ {
+ if ( nLev )
+ {
+ mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev ] = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ nLev - 1 ];
+ mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ] = mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev - 1 ];
+ }
+ mpParaSheet[ TSS_Type::TextInShape ]->Read( rManager, rIn, nLev, bFirst );
+ if ( !nLev )
+ {
+ // set paragraph defaults for instance 4 (TSS_Type::TextInShape)
+ if ( rTxPFStyle.bValid )
+ {
+ PPTParaLevel& rParaLevel = mpParaSheet[ TSS_Type::TextInShape ]->maParaLevel[ 0 ];
+ rParaLevel.mnAsianLineBreak = 0;
+ if ( rTxPFStyle.bForbiddenRules )
+ rParaLevel.mnAsianLineBreak |= 1;
+ if ( !rTxPFStyle.bLatinTextWrap )
+ rParaLevel.mnAsianLineBreak |= 2;
+ if ( rTxPFStyle.bHangingPunctuation )
+ rParaLevel.mnAsianLineBreak |= 4;
+ }
+ }
+ mpCharSheet[ TSS_Type::TextInShape ]->Read( rIn, nLev );
+ mpParaSheet[ TSS_Type::TextInShape ]->UpdateBulletRelSize( nLev, mpCharSheet[ TSS_Type::TextInShape ]->maCharLevel[ nLev ].mnFontHeight );
+ bFirst = false;
+ nLev++;
+ }
+ break;
+ }
+ else
+ {
+ if (!aTxMasterStyleHd2.SeekToEndOfRecord(rIn))
+ break;
+ }
+ }
+ }
+ }
+ rIn.Seek( nOldFilePos );
+
+ // will create the default numbulletitem for each instance
+ for ( auto i : o3tl::enumrange<TSS_Type>() )
+ {
+ sal_uInt16 nLevels, nDepth = 0;
+ SvxNumRuleType eNumRuleType;
+
+ switch ( i )
+ {
+ case TSS_Type::PageTitle :
+ case TSS_Type::Title :
+ nLevels = 1;
+ eNumRuleType = SvxNumRuleType::NUMBERING;
+ break;
+ case TSS_Type::Subtitle :
+ nLevels = SVX_MAX_NUM;
+ eNumRuleType = SvxNumRuleType::NUMBERING;
+ break;
+ case TSS_Type::Body :
+ case TSS_Type::HalfBody :
+ case TSS_Type::QuarterBody :
+ nLevels = SVX_MAX_NUM;
+ eNumRuleType = SvxNumRuleType::PRESENTATION_NUMBERING;
+ break;
+ default :
+ case TSS_Type::Notes :
+ case TSS_Type::Unused :
+ case TSS_Type::TextInShape :
+ nLevels = SVX_MAX_NUM;
+ eNumRuleType = SvxNumRuleType::NUMBERING;
+ break;
+ }
+ SvxNumRule aRule( SvxNumRuleFlags::BULLET_REL_SIZE | SvxNumRuleFlags::BULLET_COLOR,
+ nLevels, false, eNumRuleType );
+ for ( sal_uInt16 nCount = 0; nDepth < nLevels; nCount++ )
+ {
+ const PPTParaLevel& rParaLevel = mpParaSheet[ i ]->maParaLevel[ nCount ];
+ const PPTCharLevel& rCharLevel = mpCharSheet[ i ]->maCharLevel[ nCount ];
+ SvxNumberFormat aNumberFormat( SVX_NUM_CHAR_SPECIAL );
+ aNumberFormat.SetBulletChar( ' ' );
+ GetNumberFormat( rManager, aNumberFormat, nCount, rParaLevel, rCharLevel, i );
+ aRule.SetLevel( nDepth++, aNumberFormat );
+ if ( nCount >= 4 )
+ {
+ for ( ;nDepth < nLevels; nDepth++ )
+ aRule.SetLevel( nDepth, aNumberFormat );
+ }
+ }
+ mpNumBulletItem[ i ] = std::make_unique<SvxNumBulletItem>( std::move(aRule), EE_PARA_NUMBULLET );
+ }
+}
+
+PPTStyleSheet::~PPTStyleSheet()
+{
+ for ( auto i : o3tl::enumrange<TSS_Type>() )
+ {
+ mpCharSheet[i].reset();
+ mpParaSheet[i].reset();
+ mpNumBulletItem[i].reset();
+ }
+}
+
+PPTParaPropSet::PPTParaPropSet()
+ : mnOriginalTextPos(0)
+ , mxParaSet( new ImplPPTParaPropSet )
+{
+ mxParaSet->mnHasAnm = 1;
+}
+
+PPTParaPropSet::PPTParaPropSet( PPTParaPropSet const & rParaPropSet )
+{
+ mxParaSet = rParaPropSet.mxParaSet;
+ mnOriginalTextPos = rParaPropSet.mnOriginalTextPos;
+}
+
+PPTParaPropSet::~PPTParaPropSet()
+{
+}
+
+PPTParaPropSet& PPTParaPropSet::operator=( const PPTParaPropSet& rParaPropSet )
+{
+ if ( this != &rParaPropSet )
+ {
+ mxParaSet = rParaPropSet.mxParaSet;
+ mnOriginalTextPos = rParaPropSet.mnOriginalTextPos;
+ }
+ return *this;
+}
+
+PPTCharPropSet::PPTCharPropSet(sal_uInt32 nParagraph)
+ : mnOriginalTextPos(0)
+ , mnParagraph(nParagraph)
+{
+ mnHylinkOrigColor = 0;
+ mbIsHyperlink = false;
+ mbHardHylinkOrigColor = false;
+ mnLanguage[ 0 ] = mnLanguage[ 1 ] = mnLanguage[ 2 ] = LANGUAGE_SYSTEM;
+}
+
+PPTCharPropSet::PPTCharPropSet( const PPTCharPropSet& rCharPropSet )
+ : mpImplPPTCharPropSet( rCharPropSet.mpImplPPTCharPropSet )
+{
+ mnHylinkOrigColor = rCharPropSet.mnHylinkOrigColor;
+ mbIsHyperlink = rCharPropSet.mbIsHyperlink;
+ mbHardHylinkOrigColor = rCharPropSet.mbHardHylinkOrigColor;
+
+ mnParagraph = rCharPropSet.mnParagraph;
+ mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
+ maString = rCharPropSet.maString;
+ mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
+ mnLanguage[ 0 ] = rCharPropSet.mnLanguage[ 0 ];
+ mnLanguage[ 1 ] = rCharPropSet.mnLanguage[ 1 ];
+ mnLanguage[ 2 ] = rCharPropSet.mnLanguage[ 2 ];
+}
+
+PPTCharPropSet::PPTCharPropSet( const PPTCharPropSet& rCharPropSet, sal_uInt32 nParagraph )
+ : mpImplPPTCharPropSet(rCharPropSet.mpImplPPTCharPropSet)
+{
+ mnHylinkOrigColor = rCharPropSet.mnHylinkOrigColor;
+ mbIsHyperlink = rCharPropSet.mbIsHyperlink;
+ mbHardHylinkOrigColor = rCharPropSet.mbHardHylinkOrigColor;
+
+ mnParagraph = nParagraph;
+ mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
+ maString = rCharPropSet.maString;
+ mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
+ mnLanguage[ 0 ] = mnLanguage[ 1 ] = mnLanguage[ 2 ] = LANGUAGE_SYSTEM;
+}
+
+PPTCharPropSet::~PPTCharPropSet()
+{
+}
+
+PPTCharPropSet& PPTCharPropSet::operator=( const PPTCharPropSet& rCharPropSet )
+{
+ if ( this != &rCharPropSet )
+ {
+ mpImplPPTCharPropSet = rCharPropSet.mpImplPPTCharPropSet;
+ mnOriginalTextPos = rCharPropSet.mnOriginalTextPos;
+ mnParagraph = rCharPropSet.mnParagraph;
+ maString = rCharPropSet.maString;
+ mpFieldItem.reset( rCharPropSet.mpFieldItem ? new SvxFieldItem( *rCharPropSet.mpFieldItem ) : nullptr );
+ }
+ return *this;
+}
+
+void PPTCharPropSet::SetFont( sal_uInt16 nFont )
+{
+ sal_uInt32 nMask = 1 << PPT_CharAttr_Font;
+ bool bDoNotMake = (mpImplPPTCharPropSet->mnAttrSet & nMask) != 0;
+
+ if ( bDoNotMake )
+ bDoNotMake = nFont == mpImplPPTCharPropSet->mnFont;
+
+ if ( !bDoNotMake )
+ {
+ mpImplPPTCharPropSet->mnFont = nFont;
+ mpImplPPTCharPropSet->mnAttrSet |= nMask;
+ }
+}
+
+void PPTCharPropSet::SetColor( sal_uInt32 nColor )
+{
+ mpImplPPTCharPropSet->mnColor = nColor;
+ mpImplPPTCharPropSet->mnAttrSet |= 1 << PPT_CharAttr_FontColor;
+}
+
+PPTRuler::PPTRuler()
+ : nFlags(0)
+ , nDefaultTab(0x240)
+ , nTabCount(0)
+{
+}
+
+PPTRuler::~PPTRuler()
+{
+};
+
+
+PPTTextRulerInterpreter::PPTTextRulerInterpreter() :
+ mxImplRuler ( new PPTRuler() )
+{
+}
+
+PPTTextRulerInterpreter::PPTTextRulerInterpreter( PPTTextRulerInterpreter const & rRuler )
+{
+ mxImplRuler = rRuler.mxImplRuler;
+}
+
+PPTTextRulerInterpreter::PPTTextRulerInterpreter( sal_uInt32 nFileOfs, DffRecordHeader const & rHeader, SvStream& rIn ) :
+ mxImplRuler ( new PPTRuler() )
+{
+ if ( nFileOfs == 0xffffffff )
+ return;
+
+ sal_uInt32 nOldPos = rIn.Tell();
+ DffRecordHeader rHd;
+ if ( nFileOfs )
+ {
+ rIn.Seek( nFileOfs );
+ ReadDffRecordHeader( rIn, rHd );
+ }
+ else
+ {
+ rHeader.SeekToContent( rIn );
+ if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextRulerAtom, rHeader.GetRecEndFilePos(), &rHd ) )
+ nFileOfs++;
+ }
+ if ( nFileOfs )
+ {
+ bool bRecordOk = true;
+
+ sal_Int16 nTCount(0);
+ sal_Int32 i;
+ rIn.ReadInt32( mxImplRuler->nFlags );
+
+ // number of indent levels, unused now
+ if ( mxImplRuler->nFlags & 2 )
+ rIn.ReadInt16( nTCount );
+ if ( mxImplRuler->nFlags & 1 )
+ rIn.ReadUInt16( mxImplRuler->nDefaultTab );
+ if ( mxImplRuler->nFlags & 4 )
+ {
+ rIn.ReadInt16(nTCount);
+
+ const size_t nMaxPossibleRecords = rIn.remainingSize() / (2*sizeof(sal_uInt16));
+ const sal_uInt16 nTabCount(nTCount);
+
+ bRecordOk = nTabCount <= nMaxPossibleRecords;
+
+ if (nTCount && bRecordOk)
+ {
+ mxImplRuler->nTabCount = nTabCount;
+ mxImplRuler->pTab.reset( new PPTTabEntry[ mxImplRuler->nTabCount ] );
+ for ( i = 0; i < nTCount; i++ )
+ {
+ rIn.ReadUInt16( mxImplRuler->pTab[ i ].nOffset )
+ .ReadUInt16( mxImplRuler->pTab[ i ].nStyle );
+ }
+ }
+ }
+
+ if (bRecordOk)
+ {
+ for ( i = 0; i < 5; i++ )
+ {
+ if ( mxImplRuler->nFlags & ( 8 << i ) )
+ rIn.ReadUInt16( mxImplRuler->nTextOfs[ i ] );
+ if ( mxImplRuler->nFlags & ( 256 << i ) )
+ rIn.ReadUInt16( mxImplRuler->nBulletOfs[ i ] );
+ if( mxImplRuler->nBulletOfs[ i ] > 0x7fff)
+ {
+ // workaround
+ // when bullet offset is > 0x7fff, the paragraph should look like
+ // * first line text
+ // second line text
+
+ // we add to bullet para indent 0xffff - bullet offset. It looks like
+ // best we can do for now
+ mxImplRuler->nTextOfs[ i ] += 0xffff - mxImplRuler->nBulletOfs[ i ];
+ mxImplRuler->nBulletOfs[ i ] = 0;
+ }
+ }
+ }
+ }
+ rIn.Seek( nOldPos );
+}
+
+bool PPTTextRulerInterpreter::GetDefaultTab( sal_uInt16& nValue ) const
+{
+ if ( ! ( mxImplRuler->nFlags & 1 ) )
+ return false;
+ nValue = mxImplRuler->nDefaultTab;
+ return true;
+}
+
+bool PPTTextRulerInterpreter::GetTextOfs( sal_uInt32 nLevel, sal_uInt16& nValue ) const
+{
+ if ( ! ( ( nLevel < 5 ) && ( mxImplRuler->nFlags & ( 8 << nLevel ) ) ) )
+ return false;
+ nValue = mxImplRuler->nTextOfs[ nLevel ];
+ return true;
+}
+
+bool PPTTextRulerInterpreter::GetBulletOfs( sal_uInt32 nLevel, sal_uInt16& nValue ) const
+{
+ if ( ! ( ( nLevel < 5 ) && ( mxImplRuler->nFlags & ( 256 << nLevel ) ) ) )
+ return false;
+ nValue = mxImplRuler->nBulletOfs[ nLevel ];
+ return true;
+}
+
+PPTTextRulerInterpreter& PPTTextRulerInterpreter::operator=( const PPTTextRulerInterpreter& rRuler )
+{
+ if ( this != &rRuler )
+ {
+ mxImplRuler = rRuler.mxImplRuler;
+ }
+ return *this;
+}
+
+PPTTextRulerInterpreter::~PPTTextRulerInterpreter()
+{
+}
+
+PPTTextParagraphStyleAtomInterpreter::PPTTextParagraphStyleAtomInterpreter() :
+ bValid ( false ),
+ bForbiddenRules ( false ),
+ bHangingPunctuation ( false ),
+ bLatinTextWrap ( false )
+{
+}
+
+bool PPTTextParagraphStyleAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd )
+{
+ bValid = false;
+ rRecHd.SeekToContent( rIn );
+ sal_uInt32 nDummy32, nFlags, nRecEndPos = rRecHd.GetRecEndFilePos();
+ sal_uInt16 nDummy16;
+
+ rIn.ReadUInt16( nDummy16 )
+ .ReadUInt32( nFlags );
+
+ if ( nFlags & 0xf && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 ); // BuFlags
+ if ( nFlags & 0x80 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 ); // BuChar
+ if ( nFlags & 0x10 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 ); // nBuFont;
+ if ( nFlags & 0x40 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 ); // nBuHeight;
+ if ( nFlags & 0x0020 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt32( nDummy32 ); // nBuColor;
+ if ( nFlags & 0x800 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 ); // AbsJust!
+ if ( nFlags & 0x400 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 );
+ if ( nFlags & 0x200 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 );
+ if ( nFlags & 0x100 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 );
+ if ( nFlags & 0x1000 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 ); // LineFeed
+ if ( nFlags & 0x2000 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 ); // nUpperDist
+ if ( nFlags & 0x4000 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 ); // nLowerDist
+ if ( nFlags & 0x8000 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 );
+ if ( nFlags & 0x10000 && ( rIn.Tell() < nRecEndPos ) )
+ rIn.ReadUInt16( nDummy16 );
+ if ( nFlags & 0xe0000 && ( rIn.Tell() < nRecEndPos ) )
+ {
+ rIn.ReadUInt16( nDummy16 );
+ if ( nFlags & 0x20000 )
+ bForbiddenRules = ( nDummy16 & 1 ) == 1;
+ if ( nFlags & 0x40000 )
+ bLatinTextWrap = ( nDummy16 & 2 ) == 0;
+ if ( nFlags & 0x80000 )
+ bHangingPunctuation = ( nDummy16 & 4 ) == 4;
+ }
+ nFlags &=~ 0xfffff;
+ sal_uInt32 nMask = 0x100000;
+ while ( nFlags && nMask && ( rIn.Tell() < nRecEndPos ) )
+ {
+ if ( nFlags & nMask )
+ {
+ rIn.ReadUInt16( nDummy16 );
+ nFlags ^= nMask;
+ }
+ nMask <<= 1;
+ }
+ bValid = rIn.Tell() == nRecEndPos;
+ return bValid;
+}
+
+PPTTextSpecInfo::PPTTextSpecInfo( sal_uInt32 _nCharIdx ) :
+ nCharIdx ( _nCharIdx ),
+ nDontKnow ( 1 )
+{
+ nLanguage[ 0 ] = LANGUAGE_PROCESS_OR_USER_DEFAULT;
+ nLanguage[ 1 ] = LANGUAGE_SYSTEM;
+ nLanguage[ 2 ] = LANGUAGE_SYSTEM;
+}
+
+PPTTextSpecInfoAtomInterpreter::PPTTextSpecInfoAtomInterpreter() :
+ bValid ( false )
+{
+}
+
+bool PPTTextSpecInfoAtomInterpreter::Read( SvStream& rIn, const DffRecordHeader& rRecHd,
+ sal_uInt16 nRecordType, const PPTTextSpecInfo* pTextSpecDefault )
+{
+ bValid = false;
+ sal_uInt32 nCharIdx = 0;
+ rRecHd.SeekToContent( rIn );
+
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rRecHd.GetRecEndFilePos());
+ while (rIn.Tell() < nEndRecPos && rIn.good())
+ {
+ if ( nRecordType == PPT_PST_TextSpecInfoAtom )
+ {
+ sal_uInt32 nCharCount(0);
+ rIn.ReadUInt32( nCharCount );
+ nCharIdx += nCharCount;
+ }
+
+ sal_uInt32 nFlags(0);
+ rIn.ReadUInt32(nFlags);
+
+ PPTTextSpecInfo aEntry( nCharIdx );
+ if ( pTextSpecDefault )
+ {
+ aEntry.nDontKnow = pTextSpecDefault->nDontKnow;
+ aEntry.nLanguage[ 0 ] = pTextSpecDefault->nLanguage[ 0 ];
+ aEntry.nLanguage[ 1 ] = pTextSpecDefault->nLanguage[ 1 ];
+ aEntry.nLanguage[ 2 ] = pTextSpecDefault->nLanguage[ 2 ];
+ }
+ for (sal_uInt32 i = 1; nFlags && i ; i <<= 1)
+ {
+ sal_uInt16 nLang = 0;
+ switch( nFlags & i )
+ {
+ case 0 : break;
+ case 1 : rIn.ReadUInt16( aEntry.nDontKnow ); break;
+ case 2 : rIn.ReadUInt16( nLang ); break;
+ case 4 : rIn.ReadUInt16( nLang ); break;
+ default :
+ {
+ rIn.SeekRel( 2 );
+ }
+ }
+ if ( nLang )
+ {
+ // #i119985#, we could probably handle this better if we have a
+ // place to override the final language for weak
+ // characters/fields to fallback to, rather than the current
+ // application locale. Assuming that we can determine what the
+ // default fallback language for a given .ppt, etc is during
+ // load time.
+ if (i == 2)
+ {
+ aEntry.nLanguage[ 0 ] = aEntry.nLanguage[ 1 ] = aEntry.nLanguage[ 2 ] = LanguageType(nLang);
+ }
+ }
+ nFlags &= ~i;
+ }
+ aList.push_back( aEntry );
+ }
+ bValid = rIn.Tell() == rRecHd.GetRecEndFilePos();
+ return bValid;
+}
+
+PPTTextSpecInfoAtomInterpreter::~PPTTextSpecInfoAtomInterpreter()
+{
+}
+
+void StyleTextProp9::Read( SvStream& rIn )
+{
+ rIn.ReadUInt32( mnExtParagraphMask );
+ if ( mnExtParagraphMask & 0x800000 )
+ rIn.ReadUInt16( mnBuBlip );
+ if ( mnExtParagraphMask & 0x2000000 )
+ rIn.ReadUInt16( mnHasAnm );
+ if ( mnExtParagraphMask & 0x1000000 )
+ rIn.ReadUInt32( mnAnmScheme );
+ if ( mnExtParagraphMask & 0x4000000 )
+ rIn.ReadUInt32( mpfPP10Ext );
+ rIn.ReadUInt32( mnExtCharacterMask );
+ if ( mnExtCharacterMask & 0x100000 )
+ rIn.ReadUInt32( mncfPP10Ext );
+ rIn.ReadUInt32( mnSpecialInfoMask );
+ if ( mnSpecialInfoMask & 0x20 )
+ rIn.ReadUInt32( mnPP10Ext );
+ if ( mnSpecialInfoMask & 0x40 )
+ rIn.ReadUInt16( mfBidi );
+}
+
+PPTStyleTextPropReader::PPTStyleTextPropReader( SvStream& rIn, const DffRecordHeader& rTextHeader,
+ PPTTextRulerInterpreter const & rRuler, const DffRecordHeader& rExtParaHd, TSS_Type nInstance )
+{
+ Init(rIn, rTextHeader, rRuler, rExtParaHd, nInstance);
+}
+
+void PPTStyleTextPropReader::ReadParaProps( SvStream& rIn, const DffRecordHeader& rTextHeader,
+ const OUString& aString, PPTTextRulerInterpreter const & rRuler,
+ sal_uInt32& nCharCount, bool& bTextPropAtom )
+{
+ sal_uInt32 nMask = 0; //TODO: nMask initialized here to suppress warning for now, see corresponding TODO below
+ sal_uInt32 nCharReadCnt = 0;
+ sal_uInt16 nDummy16;
+
+ sal_uInt16 nStringLen = aString.getLength();
+
+ DffRecordHeader aTextHd2;
+ rTextHeader.SeekToContent( rIn );
+ if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_StyleTextPropAtom, rTextHeader.GetRecEndFilePos(), &aTextHd2 ) )
+ bTextPropAtom = true;
+ while ( nCharReadCnt <= nStringLen )
+ {
+ PPTParaPropSet aParaPropSet;
+ ImplPPTParaPropSet& aSet = *aParaPropSet.mxParaSet;
+ if ( bTextPropAtom )
+ {
+ rIn.ReadUInt32( nCharCount )
+ .ReadUInt16( aParaPropSet.mxParaSet->mnDepth ); // indent depth
+
+ aParaPropSet.mxParaSet->mnDepth = // taking care of about using not more than 9 outliner levels
+ std::min(sal_uInt16(8),
+ aParaPropSet.mxParaSet->mnDepth);
+
+ nCharCount--;
+
+ rIn.ReadUInt32( nMask );
+ aSet.mnAttrSet = nMask & 0x207df7;
+ sal_uInt16 nBulFlg = 0;
+ if ( nMask & 0xF )
+ rIn.ReadUInt16( nBulFlg ); // Bullet-HardAttr-Flags
+ aSet.mpArry[ PPT_ParaAttr_BulletOn ] = ( nBulFlg & 1 ) ? 1 : 0;
+ aSet.mpArry[ PPT_ParaAttr_BuHardFont ] = ( nBulFlg & 2 ) ? 1 : 0;
+ aSet.mpArry[ PPT_ParaAttr_BuHardColor ] = ( nBulFlg & 4 ) ? 1 : 0;
+
+ // NOTE: one might think that the hard-coded numbers here are the
+ // same as the PPT_ParaAttr_* constants, but it's NOT always true!
+ if ( nMask & 0x0080 ) // buChar
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletChar ] );
+ if (!rIn.good())
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletChar);
+ }
+ }
+ if ( nMask & 0x0010 ) // buTypeface
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletFont ] );
+ if (!rIn.good())
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletFont);
+ }
+ }
+ if ( nMask & 0x0040 ) // buSize
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletHeight ] );
+ if (!rIn.good()
+ || !((nMask & (1 << PPT_ParaAttr_BuHardHeight))
+ && (nBulFlg & (1 << PPT_ParaAttr_BuHardHeight))))
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletHeight);
+ }
+ }
+ if ( nMask & 0x0020 ) // buColor
+ {
+ sal_uInt32 nVal32;
+ rIn.ReadUInt32( nVal32 );
+ if (!rIn.good())
+ {
+ aSet.mnBulletColor = 0; // no flag for this? default it
+ }
+ else
+ {
+ sal_uInt32 nHiByte;
+ nHiByte = nVal32 >> 24;
+ if ( nHiByte <= 8 )
+ nVal32 = nHiByte | PPT_COLSCHEME;
+ aSet.mnBulletColor = nVal32;
+ }
+ }
+ if ( nMask & 0x0800 ) // pfAlignment
+ {
+ rIn.ReadUInt16( nDummy16 );
+ if (!rIn.good())
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_Adjust);
+ }
+ else
+ {
+ aSet.mpArry[ PPT_ParaAttr_Adjust ] = nDummy16 & 3;
+ }
+ }
+ if ( nMask & 0x1000 ) // pfLineSpacing
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_LineFeed ] );
+ if (!rIn.good())
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_LineFeed);
+ }
+ }
+ if ( nMask & 0x2000 ) // pfSpaceBefore
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_UpperDist ] );
+ if (!rIn.good())
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_UpperDist);
+ }
+ }
+ if ( nMask & 0x4000 ) // pfSpaceAfter
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_LowerDist ] );
+ if (!rIn.good())
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_LowerDist);
+ }
+ }
+ if ( nMask & 0x100 ) // pfLeftMargin
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_TextOfs ] );
+ if (!rIn.good())
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_TextOfs);
+ }
+ else
+ {
+ aSet.mnAttrSet |= 1 << PPT_ParaAttr_TextOfs;
+ }
+ }
+ if ( nMask & 0x400 ) // pfIndent
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BulletOfs ] );
+ if (!rIn.good())
+ {
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BulletOfs);
+ }
+ else
+ {
+ aSet.mnAttrSet |= 1 << PPT_ParaAttr_BulletOfs;
+ }
+ }
+ if ( nMask & 0x8000 ) // pfDefaultTabSize
+ {
+ rIn.ReadUInt16( nDummy16 );
+ if (!rIn.good())
+ {
+ // TODO?
+ }
+ }
+ if ( nMask & 0x100000 ) // pfTabStops
+ {
+ sal_uInt16 i, nDistance, nAlignment, nNumberOfTabStops = 0;
+ rIn.ReadUInt16( nNumberOfTabStops );
+ if (!rIn.good())
+ {
+ // TODO?
+ }
+ else
+ {
+ const size_t nMinRecordSize = 4;
+ const size_t nMaxRecords = rIn.remainingSize() / nMinRecordSize;
+ if (nNumberOfTabStops > nMaxRecords)
+ {
+ SAL_WARN("filter.ms", "Parsing error: " << nMaxRecords <<
+ " max possible entries, but " << nNumberOfTabStops << " claimed, truncating");
+ nNumberOfTabStops = nMaxRecords;
+ }
+ for (i = 0; i < nNumberOfTabStops; ++i)
+ {
+ rIn.ReadUInt16( nDistance )
+ .ReadUInt16( nAlignment );
+ }
+ }
+ }
+ if ( nMask & 0x10000 ) // pfBaseLine
+ {
+ rIn.ReadUInt16( nDummy16 );
+ if (!rIn.good())
+ {
+ // TODO?
+ }
+ }
+ if ( nMask & 0xe0000 ) // pfCharWrap, pfWordWrap, pfOverflow
+ {
+ rIn.ReadUInt16( nDummy16 );
+ if (!rIn.good())
+ { // clear flag to avoid invalid access
+ aSet.mnAttrSet &= ~((1 << PPT_ParaAttr_AsianLB_1)
+ | (1 << PPT_ParaAttr_AsianLB_2)
+ | (1 << PPT_ParaAttr_AsianLB_3));
+ }
+ else
+ {
+ if (nMask & 0x20000)
+ aSet.mpArry[PPT_ParaAttr_AsianLB_1] = nDummy16 & 1;
+ if (nMask & 0x40000)
+ aSet.mpArry[PPT_ParaAttr_AsianLB_2] = (nDummy16 >> 1) & 1;
+ if (nMask & 0x80000)
+ aSet.mpArry[PPT_ParaAttr_AsianLB_3] = (nDummy16 >> 2) & 1;
+ aSet.mnAttrSet |= ((nMask >> 17) & 7) << PPT_ParaAttr_AsianLB_1;
+ }
+ }
+ if ( nMask & 0x200000 ) // pfTextDirection
+ {
+ rIn.ReadUInt16( aSet.mpArry[ PPT_ParaAttr_BiDi ] );
+ if (!rIn.good())
+ { // clear flag to avoid invalid access
+ aSet.mnAttrSet &= ~(1 << PPT_ParaAttr_BiDi);
+ }
+ }
+ }
+ else
+ nCharCount = nStringLen;
+
+ //if the textofs attr has been read at above, need not to reset.
+ if ( ( !( aSet.mnAttrSet & 1 << PPT_ParaAttr_TextOfs ) ) && rRuler.GetTextOfs( aParaPropSet.mxParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_TextOfs ] ) )
+ aSet.mnAttrSet |= 1 << PPT_ParaAttr_TextOfs;
+ if ( ( !( aSet.mnAttrSet & 1 << PPT_ParaAttr_BulletOfs ) ) && rRuler.GetBulletOfs( aParaPropSet.mxParaSet->mnDepth, aSet.mpArry[ PPT_ParaAttr_BulletOfs ] ) )
+ aSet.mnAttrSet |= 1 << PPT_ParaAttr_BulletOfs;
+ if ( rRuler.GetDefaultTab( aSet.mpArry[ PPT_ParaAttr_DefaultTab ] ) )
+ aSet.mnAttrSet |= 1 << PPT_ParaAttr_DefaultTab;
+
+ if ( ( nCharCount > nStringLen ) || ( nStringLen < nCharReadCnt + nCharCount ) )
+ {
+ bTextPropAtom = false;
+ nCharCount = nStringLen - nCharReadCnt;
+ // please fix the right hand side of
+ // PPTParaPropSet& PPTParaPropSet::operator=(PPTParaPropSet&),
+ // it should be a const reference
+ PPTParaPropSet aTmpPPTParaPropSet;
+ aParaPropSet = aTmpPPTParaPropSet;
+ OSL_FAIL( "SJ:PPTStyleTextPropReader::could not get this PPT_PST_StyleTextPropAtom by reading the paragraph attributes" );
+ }
+ PPTParaPropSet* pPara = new PPTParaPropSet( aParaPropSet );
+ pPara->mnOriginalTextPos = nCharReadCnt;
+ aParaPropList.emplace_back( pPara );
+ if ( nCharCount )
+ {
+ sal_uInt32 nCount;
+ const sal_Unicode* pDat = aString.getStr() + nCharReadCnt;
+ for ( nCount = 0; nCount < nCharCount; nCount++ )
+ {
+ if ( pDat[ nCount ] == 0xd )
+ {
+ pPara = new PPTParaPropSet( aParaPropSet );
+ pPara->mnOriginalTextPos = nCharReadCnt + nCount + 1;
+ aParaPropList.emplace_back( pPara );
+ }
+ }
+ }
+ nCharReadCnt += nCharCount + 1;
+ }
+}
+
+void PPTStyleTextPropReader::ReadCharProps( SvStream& rIn, PPTCharPropSet& aCharPropSet, const OUString& aString,
+ sal_uInt32& nCharCount, sal_uInt32 nCharReadCnt,
+ bool& bTextPropAtom, sal_uInt32 nExtParaPos,
+ const std::vector< StyleTextProp9 >& aStyleTextProp9,
+ sal_uInt32& nExtParaFlags, sal_uInt16& nBuBlip,
+ sal_uInt16& nHasAnm, sal_uInt32& nAnmScheme )
+{
+ sal_uInt16 nStringLen = aString.getLength();
+
+ sal_uInt16 nDummy16;
+ rIn.ReadUInt16( nDummy16 );
+ nCharCount = (rIn.good()) ? nDummy16 : 0;
+ rIn.ReadUInt16( nDummy16 );
+
+ sal_Int32 nCharsToRead = nStringLen - ( nCharReadCnt + nCharCount );
+ if ( nCharsToRead < 0 )
+ {
+ nCharCount = nStringLen - nCharReadCnt;
+ if ( nCharsToRead < -1 )
+ {
+ bTextPropAtom = false;
+ OSL_FAIL( "SJ:PPTStyleTextPropReader::could not get this PPT_PST_StyleTextPropAtom by reading the character attributes" );
+ }
+ }
+ ImplPPTCharPropSet& aSet = *aCharPropSet.mpImplPPTCharPropSet;
+
+ // character attributes
+ sal_uInt32 nMask(0);
+ rIn.ReadUInt32( nMask );
+ if ( static_cast<sal_uInt16>(nMask) )
+ {
+ aSet.mnAttrSet |= static_cast<sal_uInt16>(nMask);
+ rIn.ReadUInt16( aSet.mnFlags );
+ }
+ if ( nMask & 0x10000 ) // cfTypeface
+ {
+ rIn.ReadUInt16( aSet.mnFont );
+ aSet.mnAttrSet |= 1 << PPT_CharAttr_Font;
+ }
+ if ( nMask & 0x200000 ) // cfFEOldTypeface
+ {
+ rIn.ReadUInt16( aSet.mnAsianOrComplexFont );
+ aSet.mnAttrSet |= 1 << PPT_CharAttr_AsianOrComplexFont;
+ }
+ if ( nMask & 0x400000 ) // cfANSITypeface
+ {
+ rIn.ReadUInt16( aSet.mnANSITypeface );
+ aSet.mnAttrSet |= 1 << PPT_CharAttr_ANSITypeface;
+ }
+ if ( nMask & 0x800000 ) // cfSymbolTypeface
+ {
+ rIn.ReadUInt16( aSet.mnSymbolFont );
+ aSet.mnAttrSet |= 1 << PPT_CharAttr_Symbol;
+ }
+ if ( nMask & 0x20000 ) // cfSize
+ {
+ rIn.ReadUInt16( aSet.mnFontHeight );
+ aSet.mnAttrSet |= 1 << PPT_CharAttr_FontHeight;
+ }
+ if ( nMask & 0x40000 ) // cfColor
+ {
+ sal_uInt32 nVal(0);
+ rIn.ReadUInt32( nVal );
+ if ( !( nVal & 0xff000000 ) )
+ nVal = PPT_COLSCHEME_HINTERGRUND;
+ aSet.mnColor = nVal;
+ aSet.mnAttrSet |= 1 << PPT_CharAttr_FontColor;
+ }
+ if ( nMask & 0x80000 ) // cfPosition
+ {
+ rIn.ReadUInt16( aSet.mnEscapement );
+ aSet.mnAttrSet |= 1 << PPT_CharAttr_Escapement;
+ }
+ if ( !nExtParaPos )
+ return;
+
+ sal_uInt32 nExtBuInd = nMask & 0x3c00;
+ if ( nExtBuInd )
+ nExtBuInd = ( aSet.mnFlags & 0x3c00 ) >> 10;
+ if ( nExtBuInd < aStyleTextProp9.size() )
+ {
+ nExtParaFlags = aStyleTextProp9[ nExtBuInd ].mnExtParagraphMask;
+ nBuBlip = aStyleTextProp9[ nExtBuInd ].mnBuBlip;
+ nHasAnm = aStyleTextProp9[ nExtBuInd ].mnHasAnm;
+ nAnmScheme = aStyleTextProp9[ nExtBuInd ].mnAnmScheme;
+ }
+}
+
+void PPTStyleTextPropReader::Init( SvStream& rIn, const DffRecordHeader& rTextHeader,
+ PPTTextRulerInterpreter const & rRuler, const DffRecordHeader& rExtParaHd, TSS_Type nInstance )
+{
+ sal_uInt32 nOldPos = rIn.Tell();
+ sal_uInt32 nExtParaPos = ( rExtParaHd.nRecType == PPT_PST_ExtendedParagraphAtom ) ? rExtParaHd.nFilePos + 8 : 0;
+
+ std::vector< StyleTextProp9 > aStyleTextProp9;
+ if ( rExtParaHd.nRecType == PPT_PST_ExtendedParagraphAtom )
+ {
+ rIn.Seek( rExtParaHd.nFilePos + 8 );
+
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, rExtParaHd.GetRecEndFilePos());
+ while( ( rIn.GetError() == ERRCODE_NONE ) && ( rIn.Tell() < nEndRecPos ) )
+ {
+ aStyleTextProp9.emplace_back();
+ aStyleTextProp9.back().Read( rIn );
+ }
+ rIn.Seek( nOldPos );
+ }
+
+ OUString aString;
+ DffRecordHeader aTextHd;
+ ReadDffRecordHeader( rIn, aTextHd );
+ sal_uInt32 nMaxLen = aTextHd.nRecLen;
+ if ( nMaxLen >= 0xFFFF )
+ nMaxLen = 0xFFFE;
+
+ if( aTextHd.nRecType == PPT_PST_TextCharsAtom )
+ {
+ std::vector<sal_Unicode> aBuf(( nMaxLen >> 1 ) + 1);
+ void* pDest = aBuf.data();
+ auto nRead = rIn.ReadBytes(pDest, nMaxLen);
+ if (nRead != nMaxLen)
+ memset(static_cast<char*>(pDest) + nRead, 0, nMaxLen - nRead);
+ nMaxLen >>= 1;
+ aBuf[nMaxLen] = 0;
+
+ sal_uInt32 i;
+ sal_Unicode* pPtr = aBuf.data();
+
+#ifdef OSL_BIGENDIAN
+ sal_Unicode nTemp;
+ for ( i = 0; i < nMaxLen; i++ )
+ {
+ nTemp = *pPtr;
+ *pPtr++ = ( nTemp << 8 ) | ( nTemp >> 8 );
+ }
+ pPtr = aBuf.data();
+#endif
+
+ for ( i = 0; i < nMaxLen; pPtr++, i++ )
+ {
+ sal_Unicode nChar = *pPtr;
+ if ( !nChar )
+ break;
+ if ( ( nChar & 0xff00 ) == 0xf000 ) // in this special case we got a symbol
+ aSpecMarkerList.push_back( static_cast<sal_uInt32>( i | PPT_SPEC_SYMBOL ) );
+ else if ( nChar == 0xd )
+ {
+ if ( nInstance == TSS_Type::PageTitle )
+ *pPtr = 0xb;
+ else
+ aSpecMarkerList.push_back( static_cast<sal_uInt32>( i | PPT_SPEC_NEWLINE ) );
+ }
+ }
+ if ( i )
+ aString = OUString(aBuf.data(), i);
+ }
+ else if( aTextHd.nRecType == PPT_PST_TextBytesAtom )
+ {
+ std::unique_ptr<char[]> pBuf(new char[ nMaxLen + 1 ]);
+ nMaxLen = rIn.ReadBytes(pBuf.get(), nMaxLen);
+ pBuf[ nMaxLen ] = 0;
+ char* pPtr = pBuf.get();
+ for (;;)
+ {
+ char cLo = *pPtr;
+ if ( cLo == 0 )
+ break;
+ if ( cLo == 0xd )
+ {
+ if ( nInstance == TSS_Type::PageTitle )
+ *pPtr = 0xb;
+ else
+ aSpecMarkerList.push_back( static_cast<sal_uInt32>( (pPtr - pBuf.get()) | PPT_SPEC_NEWLINE ) );
+ }
+ pPtr++;
+ }
+ sal_Int32 nLen = pPtr - pBuf.get();
+ if ( nLen )
+ aString = OUString( pBuf.get(), nLen, RTL_TEXTENCODING_MS_1252 );
+ }
+ else
+ {
+ // no chars, but potentially char/para props?
+ sal_uInt32 nCharCount;
+ bool bTextPropAtom = false;
+ ReadParaProps( rIn, rTextHeader, aString, rRuler, nCharCount, bTextPropAtom );
+
+ if ( bTextPropAtom )
+ {
+ // yeah, StyleTextProp is there, read it all & push to
+ // aParaPropList
+ PPTCharPropSet aCharPropSet(0);
+ aCharPropSet.mnOriginalTextPos = 0;
+
+ sal_uInt32 nExtParaFlags = 0, nAnmScheme = 0;
+ sal_uInt16 nBuBlip = 0xffff, nHasAnm = 0;
+ ReadCharProps( rIn, aCharPropSet, aString, nCharCount, 0/*nCharReadCnt*/,
+ bTextPropAtom, nExtParaPos, aStyleTextProp9, nExtParaFlags,
+ nBuBlip, nHasAnm, nAnmScheme );
+
+ aCharPropList.push_back(std::make_unique<PPTCharPropSet>(aCharPropSet, 0));
+ }
+ }
+
+ if ( !aString.isEmpty() )
+ {
+ sal_uInt32 nCharCount;
+ bool bTextPropAtom = false;
+
+ ReadParaProps( rIn, rTextHeader, aString, rRuler, nCharCount, bTextPropAtom );
+
+ bool bEmptyParaPossible = true;
+ sal_uInt32 nCharReadCnt = 0;
+ sal_uInt32 nCurrentPara = 0;
+ size_t i = 1; // points to the next element to process
+ sal_uInt32 nCurrentSpecMarker = aSpecMarkerList.empty() ? 0 : aSpecMarkerList[0];
+ sal_uInt32 nStringLen = aString.getLength();
+
+ while ( nCharReadCnt < nStringLen )
+ {
+ sal_uInt32 nExtParaFlags = 0, nLatestParaUpdate = 0xffffffff, nAnmScheme = 0;
+ sal_uInt16 nBuBlip = 0xffff, nHasAnm = 0;
+
+ PPTCharPropSet aCharPropSet( nCurrentPara );
+ if ( bTextPropAtom )
+ {
+ ReadCharProps( rIn, aCharPropSet, aString, nCharCount, nCharReadCnt,
+ bTextPropAtom, nExtParaPos, aStyleTextProp9, nExtParaFlags,
+ nBuBlip, nHasAnm, nAnmScheme );
+ if (!rIn.good())
+ break;
+ }
+ else
+ nCharCount = nStringLen;
+
+ sal_uInt32 nLen;
+ while( nCharCount )
+ {
+ if ( nExtParaPos && ( nLatestParaUpdate != nCurrentPara ) && ( nCurrentPara < aParaPropList.size() ) )
+ {
+ PPTParaPropSet* pPropSet = aParaPropList[ nCurrentPara ].get();
+ pPropSet->mxParaSet->mnExtParagraphMask = nExtParaFlags;
+ if ( nExtParaFlags & 0x800000 )
+ pPropSet->mxParaSet->mnBuBlip = nBuBlip;
+ if ( nExtParaFlags & 0x01000000 )
+ pPropSet->mxParaSet->mnAnmScheme = nAnmScheme;
+ if ( nExtParaFlags & 0x02000000 )
+ pPropSet->mxParaSet->mnHasAnm = nHasAnm;
+ nLatestParaUpdate = nCurrentPara;
+ }
+ aCharPropSet.mnOriginalTextPos = nCharReadCnt;
+ if ( nCurrentSpecMarker && ( ( nCurrentSpecMarker & 0xffff ) < ( nCharReadCnt + nCharCount ) ) )
+ {
+ if ( nCurrentSpecMarker & PPT_SPEC_NEWLINE )
+ {
+ nLen = ( nCurrentSpecMarker & 0xffff ) - nCharReadCnt;
+ if ( nLen )
+ aCharPropSet.maString = aString.copy( nCharReadCnt, nLen );
+ else if ( bEmptyParaPossible )
+ aCharPropSet.maString.clear();
+ if ( nLen || bEmptyParaPossible )
+ aCharPropList.push_back(
+ std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
+ nCurrentPara++;
+ nLen++;
+ nCharReadCnt += nLen;
+ nCharCount -= nLen;
+ bEmptyParaPossible = true;
+ }
+ else if ( nCurrentSpecMarker & PPT_SPEC_SYMBOL )
+ {
+ if ( ( nCurrentSpecMarker & 0xffff ) != nCharReadCnt )
+ {
+ nLen = ( nCurrentSpecMarker & 0xffff ) - nCharReadCnt;
+ aCharPropSet.maString = aString.copy(nCharReadCnt, nLen);
+ aCharPropList.push_back(
+ std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
+ nCharCount -= nLen;
+ nCharReadCnt += nLen;
+ }
+ PPTCharPropSet* pCPropSet = new PPTCharPropSet( aCharPropSet, nCurrentPara );
+ pCPropSet->maString = aString.copy(nCharReadCnt, 1);
+ if ( aCharPropSet.mpImplPPTCharPropSet->mnAttrSet & ( 1 << PPT_CharAttr_Symbol ) )
+ pCPropSet->SetFont( aCharPropSet.mpImplPPTCharPropSet->mnSymbolFont );
+ aCharPropList.emplace_back( pCPropSet );
+ nCharCount--;
+ nCharReadCnt++;
+ bEmptyParaPossible = false;
+ }
+ nCurrentSpecMarker = ( i < aSpecMarkerList.size() ) ? aSpecMarkerList[ i++ ] : 0;
+ }
+ else
+ {
+ if (nCharReadCnt > o3tl::make_unsigned(aString.getLength()))
+ aCharPropSet.maString = OUString();
+ else
+ {
+ sal_Int32 nStrLen = nCharCount;
+ sal_Int32 nMaxStrLen = aString.getLength() - nCharReadCnt;
+ if (nStrLen > nMaxStrLen)
+ nStrLen = nMaxStrLen;
+ aCharPropSet.maString = aString.copy(nCharReadCnt, nStrLen);
+ }
+ aCharPropList.push_back(
+ std::make_unique<PPTCharPropSet>(aCharPropSet, nCurrentPara));
+ nCharReadCnt += nCharCount;
+ bEmptyParaPossible = false;
+ break;
+ }
+ }
+ }
+ if ( !aCharPropList.empty() && ( aCharPropList.back()->mnParagraph != nCurrentPara ) )
+ {
+ PPTCharPropSet* pCharPropSet = new PPTCharPropSet( *aCharPropList.back(), nCurrentPara );
+ pCharPropSet->maString.clear();
+ pCharPropSet->mnOriginalTextPos = nStringLen - 1;
+ aCharPropList.emplace_back( pCharPropSet );
+ }
+ }
+ rIn.Seek( nOldPos );
+}
+
+PPTStyleTextPropReader::~PPTStyleTextPropReader()
+{
+}
+
+PPTPortionObj::PPTPortionObj( const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt32 nDepth ) :
+ PPTCharPropSet ( 0 ),
+ mrStyleSheet ( rStyleSheet ),
+ mnInstance ( nInstance ),
+ mnDepth ( std::min<sal_uInt32>( nDepth, 4 ) )
+{
+}
+
+PPTPortionObj::PPTPortionObj( const PPTCharPropSet& rCharPropSet, const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt32 nDepth ) :
+ PPTCharPropSet ( rCharPropSet ),
+ mrStyleSheet ( rStyleSheet ),
+ mnInstance ( nInstance ),
+ mnDepth ( std::min<sal_uInt32>( nDepth, 4 ) )
+{
+}
+
+PPTPortionObj::PPTPortionObj( const PPTPortionObj& rPortionObj ) :
+ PPTCharPropSet ( rPortionObj ),
+ mrStyleSheet ( rPortionObj.mrStyleSheet ),
+ mnInstance ( rPortionObj.mnInstance ),
+ mnDepth ( rPortionObj.mnDepth )
+{
+}
+
+PPTPortionObj::~PPTPortionObj()
+{
+}
+
+bool PPTPortionObj::GetAttrib( sal_uInt32 nAttr, sal_uInt32& rRetValue, TSS_Type nDestinationInstance ) const
+{
+ sal_uInt32 nMask = 1 << nAttr;
+ rRetValue = 0;
+
+ bool bIsHardAttribute = ( ( mpImplPPTCharPropSet->mnAttrSet & nMask ) != 0 );
+
+ if ( bIsHardAttribute )
+ {
+ switch ( nAttr )
+ {
+ case PPT_CharAttr_Bold :
+ case PPT_CharAttr_Italic :
+ case PPT_CharAttr_Underline :
+ case PPT_CharAttr_Shadow :
+ case PPT_CharAttr_Strikeout :
+ case PPT_CharAttr_Embossed :
+ rRetValue = ( mpImplPPTCharPropSet->mnFlags & nMask ) ? 1 : 0;
+ break;
+ case PPT_CharAttr_Font :
+ rRetValue = mpImplPPTCharPropSet->mnFont;
+ break;
+ case PPT_CharAttr_AsianOrComplexFont :
+ rRetValue = mpImplPPTCharPropSet->mnAsianOrComplexFont;
+ break;
+ case PPT_CharAttr_FontHeight :
+ rRetValue = mpImplPPTCharPropSet->mnFontHeight;
+ break;
+ case PPT_CharAttr_FontColor :
+ rRetValue = mpImplPPTCharPropSet->mnColor;
+ break;
+ case PPT_CharAttr_Escapement :
+ rRetValue = mpImplPPTCharPropSet->mnEscapement;
+ break;
+ default :
+ OSL_FAIL( "SJ:PPTPortionObj::GetAttrib ( hard attribute does not exist )" );
+ }
+ }
+ else
+ {
+ const PPTCharLevel& rCharLevel = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ];
+ PPTCharLevel* pCharLevel = nullptr;
+ if ( ( nDestinationInstance == TSS_Type::Unknown )
+ || ( mnDepth && ( ( mnInstance == TSS_Type::Subtitle ) || ( mnInstance == TSS_Type::TextInShape ) ) ) )
+ bIsHardAttribute = true;
+ else if ( nDestinationInstance != mnInstance )
+ pCharLevel = &mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[ mnDepth ];
+ switch( nAttr )
+ {
+ case PPT_CharAttr_Bold :
+ case PPT_CharAttr_Italic :
+ case PPT_CharAttr_Underline :
+ case PPT_CharAttr_Shadow :
+ case PPT_CharAttr_Strikeout :
+ case PPT_CharAttr_Embossed :
+ {
+ rRetValue = ( rCharLevel.mnFlags & nMask ) ? 1 : 0;
+ if ( pCharLevel )
+ {
+ sal_uInt32 nTmp = ( pCharLevel->mnFlags & nMask ) ? 1 : 0;
+ if ( rRetValue != nTmp )
+ bIsHardAttribute = true;
+ }
+ }
+ break;
+ case PPT_CharAttr_Font :
+ {
+ rRetValue = rCharLevel.mnFont;
+ if ( pCharLevel && ( rRetValue != pCharLevel->mnFont ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_CharAttr_AsianOrComplexFont :
+ {
+ rRetValue = rCharLevel.mnAsianOrComplexFont;
+ if ( pCharLevel && ( rRetValue != pCharLevel->mnAsianOrComplexFont ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_CharAttr_FontHeight :
+ {
+ rRetValue = rCharLevel.mnFontHeight;
+ if ( pCharLevel && ( rRetValue != pCharLevel->mnFontHeight ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_CharAttr_FontColor :
+ {
+ rRetValue = rCharLevel.mnFontColor;
+ if ( pCharLevel && ( rRetValue != pCharLevel->mnFontColor ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_CharAttr_Escapement :
+ {
+ rRetValue = rCharLevel.mnEscapement;
+ if ( pCharLevel && ( rRetValue != pCharLevel->mnEscapement ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ default :
+ OSL_FAIL( "SJ:PPTPortionObj::GetAttrib ( attribute does not exist )" );
+ }
+ }
+ return bIsHardAttribute;
+}
+
+void PPTPortionObj::ApplyTo( SfxItemSet& rSet, SdrPowerPointImport& rManager, TSS_Type nDestinationInstance )
+{
+ ApplyTo( rSet, rManager, nDestinationInstance, nullptr );
+}
+
+void PPTPortionObj::ApplyTo( SfxItemSet& rSet, SdrPowerPointImport& rManager, TSS_Type nDestinationInstance, const PPTTextObj* pTextObj )
+{
+ sal_uInt32 nVal;
+ if ( GetAttrib( PPT_CharAttr_Bold, nVal, nDestinationInstance ) )
+ {
+ rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
+ rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ) );
+ rSet.Put( SvxWeightItem( nVal != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ) );
+ }
+ if ( GetAttrib( PPT_CharAttr_Italic, nVal, nDestinationInstance ) )
+ {
+ rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
+ rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC_CJK ) );
+ rSet.Put( SvxPostureItem( nVal != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC_CTL ) );
+ }
+ if ( GetAttrib( PPT_CharAttr_Underline, nVal, nDestinationInstance ) )
+ rSet.Put( SvxUnderlineItem( nVal != 0 ? LINESTYLE_SINGLE : LINESTYLE_NONE, EE_CHAR_UNDERLINE ) );
+
+ if ( GetAttrib( PPT_CharAttr_Shadow, nVal, nDestinationInstance ) )
+ rSet.Put( SvxShadowedItem( nVal != 0, EE_CHAR_SHADOW ) );
+
+ if ( GetAttrib( PPT_CharAttr_Strikeout, nVal, nDestinationInstance ) )
+ rSet.Put( SvxCrossedOutItem( nVal != 0 ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) );
+
+ sal_uInt32 nAsianFontId = 0xffff;
+ if ( GetAttrib( PPT_CharAttr_AsianOrComplexFont, nAsianFontId, nDestinationInstance ) )
+ {
+ if ( nAsianFontId != 0xffff )
+ {
+ const PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nAsianFontId );
+ if ( pFontEnityAtom )
+ {
+ rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName,
+ OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CJK ) );
+ rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName,
+ OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CTL ) );
+ }
+ }
+ }
+ if ( GetAttrib( PPT_CharAttr_Font, nVal, nDestinationInstance ) )
+ {
+ const PptFontEntityAtom* pFontEnityAtom = rManager.GetFontEnityAtom( nVal );
+ if ( pFontEnityAtom )
+ {
+ rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO ) );
+
+ // #i119475# bullet font info for CJK and CTL
+ if ( RTL_TEXTENCODING_SYMBOL == pFontEnityAtom->eCharSet )
+ {
+ rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CJK ) );
+ rSet.Put( SvxFontItem( pFontEnityAtom->eFamily, pFontEnityAtom->aName, OUString(), pFontEnityAtom->ePitch, pFontEnityAtom->eCharSet, EE_CHAR_FONTINFO_CTL ) );
+ }
+ }
+ }
+ if ( GetAttrib( PPT_CharAttr_FontHeight, nVal, nDestinationInstance ) ) // Schriftgrad in Point
+ {
+ sal_uInt32 nHeight = rManager.ScalePoint( nVal );
+ rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT ) );
+ rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CJK ) );
+ rSet.Put( SvxFontHeightItem( nHeight, 100, EE_CHAR_FONTHEIGHT_CTL ) );
+ }
+
+ if ( GetAttrib( PPT_CharAttr_Embossed, nVal, nDestinationInstance ) )
+ rSet.Put( SvxCharReliefItem( nVal != 0 ? FontRelief::Embossed : FontRelief::NONE, EE_CHAR_RELIEF ) );
+ if ( nVal ) /* if Embossed is set, the font color depends to the fillstyle/color of the object,
+ if the object has no fillstyle, the font color depends to fillstyle of the background */
+ {
+ Color aDefColor( COL_BLACK );
+ sal_uInt32 eFillType = mso_fillSolid;
+ if ( rManager.GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ) & 0x10 )
+ eFillType = rManager.GetPropertyValue(DFF_Prop_fillType, mso_fillSolid);
+ else
+ eFillType = mso_fillBackground;
+ switch( eFillType )
+ {
+ case mso_fillShade :
+ case mso_fillShadeCenter :
+ case mso_fillShadeShape :
+ case mso_fillShadeScale :
+ case mso_fillShadeTitle :
+ case mso_fillSolid :
+ aDefColor = rManager.MSO_CLR_ToColor( rManager.GetPropertyValue( DFF_Prop_fillColor, 0 ) );
+ break;
+ case mso_fillPattern :
+ aDefColor = rManager.MSO_CLR_ToColor( rManager.GetPropertyValue( DFF_Prop_fillBackColor, 0 ) );
+ break;
+ case mso_fillTexture :
+ {
+ Graphic aGraf;
+ if ( rManager.GetBLIP( rManager.GetPropertyValue( DFF_Prop_fillBlip, 0 ), aGraf ) )
+ {
+ Bitmap aBmp( aGraf.GetBitmapEx().GetBitmap() );
+ Size aSize( aBmp.GetSizePixel() );
+ if ( aSize.Width() && aSize.Height() )
+ {
+ if ( aSize.Width () > 64 )
+ aSize.setWidth( 64 );
+ if ( aSize.Height() > 64 )
+ aSize.setHeight( 64 );
+
+ Bitmap::ScopedReadAccess pAcc(aBmp);
+ if( pAcc )
+ {
+ sal_uLong nRt = 0, nGn = 0, nBl = 0;
+ const tools::Long nWidth = aSize.Width();
+ const tools::Long nHeight = aSize.Height();
+
+ if( pAcc->HasPalette() )
+ {
+ for( tools::Long nY = 0; nY < nHeight; nY++ )
+ {
+ Scanline pScanline = pAcc->GetScanline( nY );
+ for( tools::Long nX = 0; nX < nWidth; nX++ )
+ {
+ const BitmapColor& rCol = pAcc->GetPaletteColor( pAcc->GetIndexFromData( pScanline, nX ) );
+ nRt+=rCol.GetRed(); nGn+=rCol.GetGreen(); nBl+=rCol.GetBlue();
+ }
+ }
+ }
+ else
+ {
+ for( tools::Long nY = 0; nY < nHeight; nY++ )
+ {
+ Scanline pScanline = pAcc->GetScanline( nY );
+ for( tools::Long nX = 0; nX < nWidth; nX++ )
+ {
+ const BitmapColor aCol( pAcc->GetPixelFromData( pScanline, nX ) );
+ nRt+=aCol.GetRed(); nGn+=aCol.GetGreen(); nBl+=aCol.GetBlue();
+ }
+ }
+ }
+ pAcc.reset();
+ sal_uInt32 nC = aSize.Width() * aSize.Height();
+ nRt /= nC;
+ nGn /= nC;
+ nBl /= nC;
+ aDefColor = Color(sal_uInt8( nRt ), sal_uInt8( nGn ),sal_uInt8( nBl ) );
+ }
+ }
+ }
+ }
+ break;
+ case mso_fillBackground :
+ {
+ if ( pTextObj ) // the textobject is needed
+ {
+ const SfxItemSet* pItemSet = pTextObj->GetBackground();
+ if ( pItemSet )
+ {
+ const XFillStyleItem* pFillStyleItem = pItemSet->GetItemIfSet( XATTR_FILLSTYLE, false );
+ if ( pFillStyleItem )
+ {
+ drawing::FillStyle eFillStyle = pFillStyleItem->GetValue();
+ switch( eFillStyle )
+ {
+ case drawing::FillStyle_SOLID :
+ {
+ const XColorItem* pFillColorItem = pItemSet->GetItemIfSet( XATTR_FILLCOLOR, false );
+ if ( pFillColorItem )
+ aDefColor = pFillColorItem->GetColorValue();
+ }
+ break;
+ case drawing::FillStyle_GRADIENT :
+ {
+ const XFillGradientItem* pGradientItem = pItemSet->GetItemIfSet( XATTR_FILLGRADIENT, false );
+ if ( pGradientItem )
+ aDefColor = pGradientItem->GetGradientValue().GetStartColor();
+ }
+ break;
+ case drawing::FillStyle_HATCH :
+ case drawing::FillStyle_BITMAP :
+ aDefColor = COL_WHITE;
+ break;
+ default: break;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default: break;
+ }
+ rSet.Put( SvxColorItem( aDefColor, EE_CHAR_COLOR ) );
+ }
+ else
+ {
+ if ( GetAttrib( PPT_CharAttr_FontColor, nVal, nDestinationInstance ) ) // text color (4Byte-Arg)
+ {
+ Color aCol( rManager.MSO_TEXT_CLR_ToColor( nVal ) );
+ rSet.Put( SvxColorItem( aCol, EE_CHAR_COLOR ) );
+ if ( nDestinationInstance == TSS_Type::Unknown )
+ mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ].mnFontColorInStyleSheet = aCol;
+ }
+ else if ( nVal & 0x0f000000 ) // this is not a hard attribute, but maybe the page has a different colorscheme,
+ { // so that in this case we must use a hard color attribute
+ Color aCol( rManager.MSO_TEXT_CLR_ToColor( nVal ) );
+ Color& aColorInSheet = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[ mnDepth ].mnFontColorInStyleSheet;
+ if ( aColorInSheet != aCol )
+ rSet.Put( SvxColorItem( aCol, EE_CHAR_COLOR ) );
+ }
+ }
+
+ if ( GetAttrib( PPT_CharAttr_Escapement, nVal, nDestinationInstance ) ) // super-/subscript in %
+ {
+ sal_uInt16 nEsc = 0;
+ sal_uInt8 nProp = 100;
+
+ if ( nVal )
+ {
+ nEsc = static_cast<sal_Int16>(nVal);
+ nProp = DFLT_ESC_PROP;
+ }
+ SvxEscapementItem aItem( nEsc, nProp, EE_CHAR_ESCAPEMENT );
+ rSet.Put( aItem );
+ }
+ if ( mnLanguage[ 0 ] )
+ rSet.Put( SvxLanguageItem( mnLanguage[ 0 ], EE_CHAR_LANGUAGE ) );
+ if ( mnLanguage[ 1 ] )
+ rSet.Put( SvxLanguageItem( mnLanguage[ 1 ], EE_CHAR_LANGUAGE_CJK ) );
+ if ( mnLanguage[ 2 ] )
+ rSet.Put( SvxLanguageItem( mnLanguage[ 2 ], EE_CHAR_LANGUAGE_CTL ) );
+}
+
+SvxFieldItem* PPTPortionObj::GetTextField()
+{
+ if ( mpFieldItem )
+ return new SvxFieldItem( *mpFieldItem );
+ return nullptr;
+}
+
+namespace
+{
+ sal_uInt16 sanitizeForMaxPPTLevels(sal_uInt16 nDepth)
+ {
+ if (nDepth >= nMaxPPTLevels)
+ {
+ SAL_WARN("filter.ms", "Para Style Sheet depth " << nDepth << " but " << nMaxPPTLevels - 1 << " is max possible");
+ nDepth = nMaxPPTLevels - 1;
+ }
+ return nDepth;
+ }
+}
+
+PPTParagraphObj::PPTParagraphObj( const PPTStyleSheet& rStyleSheet, TSS_Type nInstance, sal_uInt16 nDepth ) :
+ PPTNumberFormatCreator ( nullptr ),
+ mrStyleSheet ( rStyleSheet ),
+ mnInstance ( nInstance ),
+ mnCurrentObject ( 0 )
+{
+ mxParaSet->mnDepth = sanitizeForMaxPPTLevels(nDepth);
+}
+
+PPTParagraphObj::PPTParagraphObj( PPTStyleTextPropReader& rPropReader,
+ size_t const nCurParaPos, size_t& rnCurCharPos,
+ const PPTStyleSheet& rStyleSheet,
+ TSS_Type nInstance, PPTTextRulerInterpreter const & rRuler ) :
+ PPTParaPropSet ( *rPropReader.aParaPropList[nCurParaPos] ),
+ PPTNumberFormatCreator ( nullptr ),
+ PPTTextRulerInterpreter ( rRuler ),
+ mrStyleSheet ( rStyleSheet ),
+ mnInstance ( nInstance ),
+ mnCurrentObject ( 0 )
+{
+ if (rnCurCharPos >= rPropReader.aCharPropList.size())
+ return;
+
+ sal_uInt32 const nCurrentParagraph =
+ rPropReader.aCharPropList[rnCurCharPos]->mnParagraph;
+ for (; rnCurCharPos < rPropReader.aCharPropList.size() &&
+ rPropReader.aCharPropList[rnCurCharPos]->mnParagraph == nCurrentParagraph;
+ ++rnCurCharPos)
+ {
+ PPTCharPropSet *const pCharPropSet =
+ rPropReader.aCharPropList[rnCurCharPos].get();
+ std::unique_ptr<PPTPortionObj> pPPTPortion(new PPTPortionObj(
+ *pCharPropSet, rStyleSheet, nInstance, mxParaSet->mnDepth));
+ m_PortionList.push_back(std::move(pPPTPortion));
+ }
+}
+
+PPTParagraphObj::~PPTParagraphObj()
+{
+}
+
+void PPTParagraphObj::AppendPortion( PPTPortionObj& rPPTPortion )
+{
+ m_PortionList.push_back(
+ std::make_unique<PPTPortionObj>(rPPTPortion));
+}
+
+void PPTParagraphObj::UpdateBulletRelSize( sal_uInt32& nBulletRelSize ) const
+{
+ if ( nBulletRelSize <= 0x7fff ) // a negative value is the absolute bullet height
+ return;
+
+ sal_uInt16 nFontHeight = 0;
+ if (!m_PortionList.empty())
+ {
+ PPTPortionObj const& rPortion = *m_PortionList.front();
+ if (rPortion.mpImplPPTCharPropSet->mnAttrSet & (1 << PPT_CharAttr_FontHeight))
+ {
+ nFontHeight = rPortion.mpImplPPTCharPropSet->mnFontHeight;
+ }
+ }
+ // if we do not have a hard attributed fontheight, the fontheight is taken from the style
+ if ( !nFontHeight )
+ {
+ nFontHeight = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[sanitizeForMaxPPTLevels(mxParaSet->mnDepth)].mnFontHeight;
+ }
+ nBulletRelSize = nFontHeight ? ((- static_cast<sal_Int16>(nBulletRelSize)) * 100 ) / nFontHeight : 100;
+}
+
+bool PPTParagraphObj::GetAttrib( sal_uInt32 nAttr, sal_uInt32& rRetValue, TSS_Type nDestinationInstance )
+{
+ sal_uInt32 nMask = 1 << nAttr;
+ rRetValue = 0;
+
+ if ( nAttr > 21 )
+ {
+ OSL_FAIL( "SJ:PPTParagraphObj::GetAttrib - attribute does not exist" );
+ return false;
+ }
+
+ bool bIsHardAttribute = ( ( mxParaSet->mnAttrSet & nMask ) != 0 );
+
+ sal_uInt16 nDepth = sanitizeForMaxPPTLevels(mxParaSet->mnDepth);
+
+ if ( bIsHardAttribute )
+ {
+ if ( nAttr == PPT_ParaAttr_BulletColor )
+ {
+ bool bHardBulletColor;
+ if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardColor ) )
+ bHardBulletColor = mxParaSet->mpArry[ PPT_ParaAttr_BuHardColor ] != 0;
+ else
+ bHardBulletColor = ( mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth].mnBuFlags
+ & ( 1 << PPT_ParaAttr_BuHardColor ) ) != 0;
+ if ( bHardBulletColor )
+ rRetValue = mxParaSet->mnBulletColor;
+ else
+ {
+ rRetValue = PPT_COLSCHEME_TEXT_UND_ZEILEN;
+ if ((nDestinationInstance != TSS_Type::Unknown) && !m_PortionList.empty())
+ {
+ PPTPortionObj const& rPortion = *m_PortionList.front();
+ if (rPortion.mpImplPPTCharPropSet->mnAttrSet & (1 << PPT_CharAttr_FontColor))
+ {
+ rRetValue = rPortion.mpImplPPTCharPropSet->mnColor;
+ }
+ else
+ {
+ rRetValue = mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[nDepth].mnFontColor;
+ }
+ }
+ }
+ }
+ else if ( nAttr == PPT_ParaAttr_BulletFont )
+ {
+ bool bHardBuFont;
+ if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardFont ) )
+ bHardBuFont = mxParaSet->mpArry[ PPT_ParaAttr_BuHardFont ] != 0;
+ else
+ bHardBuFont = ( mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth].mnBuFlags
+ & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
+ if ( bHardBuFont )
+ rRetValue = mxParaSet->mpArry[ PPT_ParaAttr_BulletFont ];
+ else
+ {
+ // it is the font used which assigned to the first character of the following text
+ rRetValue = 0;
+ if ((nDestinationInstance != TSS_Type::Unknown) && !m_PortionList.empty())
+ {
+ PPTPortionObj const& rPortion = *m_PortionList.front();
+ if (rPortion.mpImplPPTCharPropSet->mnAttrSet & ( 1 << PPT_CharAttr_Font ) )
+ {
+ rRetValue = rPortion.mpImplPPTCharPropSet->mnFont;
+ }
+ else
+ {
+ rRetValue = mrStyleSheet.mpCharSheet[ nDestinationInstance ]->maCharLevel[nDepth].mnFont;
+ }
+ }
+ }
+ }
+ else
+ rRetValue = mxParaSet->mpArry[ nAttr ];
+ }
+ else
+ {
+ const PPTParaLevel& rParaLevel = mrStyleSheet.mpParaSheet[ mnInstance ]->maParaLevel[nDepth];
+
+ PPTParaLevel* pParaLevel = nullptr;
+ if ( ( nDestinationInstance == TSS_Type::Unknown )
+ || ( nDepth && ( ( mnInstance == TSS_Type::Subtitle ) || ( mnInstance == TSS_Type::TextInShape ) ) ) )
+ bIsHardAttribute = true;
+ else if ( nDestinationInstance != mnInstance )
+ pParaLevel = &mrStyleSheet.mpParaSheet[ nDestinationInstance ]->maParaLevel[nDepth];
+ switch ( nAttr )
+ {
+ case PPT_ParaAttr_BulletOn :
+ {
+ rRetValue = rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BulletOn );
+ if ( pParaLevel )
+ {
+ if ( rRetValue != ( static_cast<sal_uInt32>(pParaLevel->mnBuFlags) & ( 1 << PPT_ParaAttr_BulletOn ) ) )
+ bIsHardAttribute = true;
+ }
+ }
+ break;
+ case PPT_ParaAttr_BuHardFont :
+ case PPT_ParaAttr_BuHardColor :
+ case PPT_ParaAttr_BuHardHeight :
+ OSL_FAIL( "SJ:PPTParagraphObj::GetAttrib - this attribute does not make sense" );
+ break;
+ case PPT_ParaAttr_BulletChar :
+ {
+ rRetValue = rParaLevel.mnBulletChar;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletChar ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_BulletFont :
+ {
+ bool bHardBuFont;
+ if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardFont ) )
+ bHardBuFont = mxParaSet->mpArry[ PPT_ParaAttr_BuHardFont ] != 0;
+ else
+ bHardBuFont = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardFont ) ) != 0;
+ if ( bHardBuFont )
+ {
+ rRetValue = rParaLevel.mnBulletFont;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletFont ) )
+ bIsHardAttribute = true;
+ }
+ else
+ {
+ if (!m_PortionList.empty())
+ {
+ PPTPortionObj const& rPortion = *m_PortionList.front();
+ bIsHardAttribute = rPortion.GetAttrib(
+ PPT_CharAttr_Font, rRetValue, nDestinationInstance);
+ }
+ else
+ {
+ rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFont;
+ bIsHardAttribute = true;
+ }
+ }
+ }
+ break;
+ case PPT_ParaAttr_BulletHeight :
+ {
+ rRetValue = rParaLevel.mnBulletHeight;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletHeight ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_BulletColor :
+ {
+ bool bHardBulletColor;
+ if ( mxParaSet->mnAttrSet & ( 1 << PPT_ParaAttr_BuHardColor ) )
+ bHardBulletColor = mxParaSet->mpArry[ PPT_ParaAttr_BuHardColor ] != 0;
+ else
+ bHardBulletColor = ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardColor ) ) != 0;
+ if ( bHardBulletColor )
+ {
+ rRetValue = rParaLevel.mnBulletColor;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletColor ) )
+ bIsHardAttribute = true;
+ }
+ else
+ {
+ if (!m_PortionList.empty())
+ {
+ PPTPortionObj const& rPortion = *m_PortionList.front();
+ if (rPortion.mbIsHyperlink )
+ {
+ if( rPortion.mbHardHylinkOrigColor )
+ rRetValue = rPortion.mnHylinkOrigColor;
+ else
+ rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFontColor;
+ bIsHardAttribute = true;
+ }
+ else
+ {
+ bIsHardAttribute = rPortion.GetAttrib( PPT_CharAttr_FontColor, rRetValue, nDestinationInstance );
+ }
+ }
+ else
+ {
+ rRetValue = mrStyleSheet.mpCharSheet[ mnInstance ]->maCharLevel[nDepth].mnFontColor;
+ bIsHardAttribute = true;
+ }
+ }
+ }
+ break;
+ case PPT_ParaAttr_Adjust :
+ {
+ rRetValue = rParaLevel.mnAdjust;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnAdjust ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_LineFeed :
+ {
+ rRetValue = rParaLevel.mnLineFeed;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnLineFeed ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_UpperDist :
+ {
+ rRetValue = rParaLevel.mnUpperDist;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnUpperDist ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_LowerDist :
+ {
+ rRetValue = rParaLevel.mnLowerDist;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnLowerDist ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_TextOfs :
+ {
+ rRetValue = rParaLevel.mnTextOfs;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnTextOfs ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_BulletOfs :
+ {
+ rRetValue = rParaLevel.mnBulletOfs;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnBulletOfs ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_DefaultTab :
+ {
+ rRetValue = rParaLevel.mnDefaultTab;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnDefaultTab ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_AsianLB_1 :
+ {
+ rRetValue = rParaLevel.mnAsianLineBreak & 1;
+ if ( pParaLevel && ( rRetValue != ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) & 1 ) ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_AsianLB_2 :
+ {
+ rRetValue = ( rParaLevel.mnAsianLineBreak >> 1 ) & 1;
+ if ( pParaLevel && ( rRetValue != ( ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) >> 1 ) & 1 ) ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_AsianLB_3 :
+ {
+ rRetValue = ( rParaLevel.mnAsianLineBreak >> 2 ) & 1;
+ if ( pParaLevel && ( rRetValue != ( ( static_cast<sal_uInt32>(pParaLevel->mnAsianLineBreak) >> 2 ) & 1 ) ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ case PPT_ParaAttr_BiDi :
+ {
+ rRetValue = rParaLevel.mnBiDi;
+ if ( pParaLevel && ( rRetValue != pParaLevel->mnBiDi ) )
+ bIsHardAttribute = true;
+ }
+ break;
+ }
+ }
+ return bIsHardAttribute;
+}
+
+void PPTParagraphObj::ApplyTo( SfxItemSet& rSet, std::optional< sal_Int16 >& rStartNumbering, SdrPowerPointImport const & rManager, TSS_Type nDestinationInstance )
+{
+ sal_Int16 nVal2;
+ sal_uInt32 nVal, nUpperDist, nLowerDist;
+ TSS_Type nInstance = nDestinationInstance != TSS_Type::Unknown ? nDestinationInstance : mnInstance;
+
+ if ( ( nDestinationInstance != TSS_Type::Unknown ) || ( mxParaSet->mnDepth <= 1 ) )
+ {
+ SvxNumBulletItem* pNumBulletItem = mrStyleSheet.mpNumBulletItem[ nInstance ].get();
+ if ( pNumBulletItem )
+ {
+ SvxNumberFormat aNumberFormat( SVX_NUM_NUMBER_NONE );
+ if ( GetNumberFormat( rManager, aNumberFormat, this, nDestinationInstance, rStartNumbering ) )
+ {
+ if ( aNumberFormat.GetNumberingType() == SVX_NUM_NUMBER_NONE )
+ {
+ aNumberFormat.SetAbsLSpace( 0 );
+ aNumberFormat.SetFirstLineOffset( 0 );
+ aNumberFormat.SetCharTextDistance( 0 );
+ aNumberFormat.SetFirstLineIndent( 0 );
+ aNumberFormat.SetIndentAt( 0 );
+ }
+ SvxNumBulletItem aNewNumBulletItem( *pNumBulletItem );
+ SvxNumRule& rRule = aNewNumBulletItem.GetNumRule();
+ rRule.SetLevel( mxParaSet->mnDepth, aNumberFormat );
+ for (sal_uInt16 i = 0; i < rRule.GetLevelCount(); ++i)
+ {
+ if ( i != mxParaSet->mnDepth )
+ {
+ sal_uInt16 n = sanitizeForMaxPPTLevels(i);
+
+ SvxNumberFormat aNumberFormat2( rRule.GetLevel( i ) );
+ const PPTParaLevel& rParaLevel = mrStyleSheet.mpParaSheet[ nInstance ]->maParaLevel[ n ];
+ const PPTCharLevel& rCharLevel = mrStyleSheet.mpCharSheet[ nInstance ]->maCharLevel[ n ];
+ sal_uInt32 nColor;
+ if ( rParaLevel.mnBuFlags & ( 1 << PPT_ParaAttr_BuHardColor ) )
+ nColor = rParaLevel.mnBulletColor;
+ else
+ nColor = rCharLevel.mnFontColor;
+ aNumberFormat2.SetBulletColor( rManager.MSO_TEXT_CLR_ToColor( nColor ) );
+ rRule.SetLevel( i, aNumberFormat2 );
+ }
+ }
+ rSet.Put( aNewNumBulletItem );
+ }
+ }
+ }
+
+ sal_uInt32 nIsBullet2, _nTextOfs, _nBulletOfs;
+ GetAttrib(PPT_ParaAttr_BulletOn, nIsBullet2, nDestinationInstance);
+ GetAttrib(PPT_ParaAttr_TextOfs, _nTextOfs, nDestinationInstance);
+ GetAttrib(PPT_ParaAttr_BulletOfs, _nBulletOfs, nDestinationInstance);
+ if ( !nIsBullet2 )
+ {
+ SvxLRSpaceItem aLRSpaceItem( EE_PARA_LRSPACE );
+ auto const nAbsLSpace = convertMasterUnitToMm100(_nTextOfs);
+ auto const nFirstLineOffset = nAbsLSpace - convertMasterUnitToMm100(_nBulletOfs);
+ aLRSpaceItem.SetLeft( nAbsLSpace );
+ aLRSpaceItem.SetTextFirstLineOffsetValue( -nFirstLineOffset );
+ rSet.Put( aLRSpaceItem );
+ }
+ else
+ {
+ SvxLRSpaceItem aLRSpaceItem( EE_PARA_LRSPACE );
+ aLRSpaceItem.SetLeft( 0 );
+ aLRSpaceItem.SetTextFirstLineOffsetValue( 0 );
+ rSet.Put( aLRSpaceItem );
+ }
+ if ( GetAttrib( PPT_ParaAttr_Adjust, nVal, nDestinationInstance ) )
+ {
+ if ( nVal <= 3 )
+ { // paragraph adjustment
+ static SvxAdjust const aAdj[ 4 ] = { SvxAdjust::Left, SvxAdjust::Center, SvxAdjust::Right, SvxAdjust::Block };
+ rSet.Put( SvxAdjustItem( aAdj[ nVal ], EE_PARA_JUST ) );
+ }
+ }
+
+ if ( GetAttrib( PPT_ParaAttr_AsianLB_1, nVal, nDestinationInstance ) )
+ rSet.Put(SvxForbiddenRuleItem(nVal != 0, EE_PARA_FORBIDDENRULES));
+ if ( GetAttrib( PPT_ParaAttr_AsianLB_3, nVal, nDestinationInstance ) )
+ rSet.Put(SvxHangingPunctuationItem(nVal != 0, EE_PARA_HANGINGPUNCTUATION));
+
+ if ( GetAttrib( PPT_ParaAttr_BiDi, nVal, nDestinationInstance ) )
+ rSet.Put( SvxFrameDirectionItem( nVal == 1 ? SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
+
+ // LineSpacing
+ PPTPortionObj* pPortion = First();
+ bool bIsHardAttribute = GetAttrib( PPT_ParaAttr_LineFeed, nVal, nDestinationInstance );
+ nVal2 = static_cast<sal_Int16>(nVal);
+ sal_uInt32 nFont = sal_uInt32();
+ if ( pPortion && pPortion->GetAttrib( PPT_CharAttr_Font, nFont, nDestinationInstance ) )
+ bIsHardAttribute = true;
+
+ if ( bIsHardAttribute )
+ {
+ SdrTextFixedCellHeightItem aHeightItem(true);
+ aHeightItem.SetWhich(SDRATTR_TEXT_USEFIXEDCELLHEIGHT);
+ rSet.Put( aHeightItem );
+ SvxLineSpacingItem aItem( 200, EE_PARA_SBL );
+ if ( nVal2 <= 0 ) {
+ aItem.SetLineHeight( static_cast<sal_uInt16>( rManager.ScalePoint( -nVal2 ) / 8 ) );
+ aItem.SetLineSpaceRule( SvxLineSpaceRule::Fix );
+ aItem.SetInterLineSpaceRule(SvxInterLineSpaceRule::Off);
+ } else
+ {
+ sal_uInt16 nPropLineSpace = static_cast<sal_uInt16>(nVal2);
+ aItem.SetPropLineSpace( nPropLineSpace );
+ aItem.SetLineSpaceRule( SvxLineSpaceRule::Auto );
+ }
+ rSet.Put( aItem );
+ }
+
+ // Paragraph Spacing
+ bIsHardAttribute = ( static_cast<sal_uInt32>(GetAttrib( PPT_ParaAttr_UpperDist, nUpperDist, nDestinationInstance )) +
+ static_cast<sal_uInt32>(GetAttrib( PPT_ParaAttr_LowerDist, nLowerDist, nDestinationInstance )) ) != 0;
+ if ( ( nUpperDist > 0 ) || ( nLowerDist > 0 ) )
+ {
+ if (!m_PortionList.empty())
+ {
+ sal_uInt32 nFontHeight = 0;
+ m_PortionList.back()->GetAttrib(
+ PPT_CharAttr_FontHeight, nFontHeight, nDestinationInstance);
+ if ( static_cast<sal_Int16>(nUpperDist) > 0 )
+ nUpperDist = - static_cast<sal_Int16>( ( nFontHeight * nUpperDist * 100 ) / 1000 );
+ if ( static_cast<sal_Int16>(nLowerDist) > 0 )
+ nLowerDist = - static_cast<sal_Int16>( ( nFontHeight * nLowerDist * 100 ) / 1000 );
+ }
+ bIsHardAttribute = true;
+ }
+ if ( bIsHardAttribute )
+ {
+ SvxULSpaceItem aULSpaceItem( EE_PARA_ULSPACE );
+ nVal2 = static_cast<sal_Int16>(nUpperDist);
+ if ( nVal2 <= 0 )
+ aULSpaceItem.SetUpper(static_cast<sal_uInt16>(convertMasterUnitToMm100(-nVal2)));
+ else
+ {
+ aULSpaceItem.SetUpperValue( 0 );
+ aULSpaceItem.SetPropUpper( static_cast<sal_uInt16>(nUpperDist) == 100 ? 101 : static_cast<sal_uInt16>(nUpperDist) );
+ }
+ nVal2 = static_cast<sal_Int16>(nLowerDist);
+ if ( nVal2 <= 0 )
+ aULSpaceItem.SetLower(static_cast<sal_uInt16>(convertMasterUnitToMm100(-nVal2)));
+ else
+ {
+ aULSpaceItem.SetLowerValue( 0 );
+ aULSpaceItem.SetPropLower( static_cast<sal_uInt16>(nLowerDist) == 100 ? 101 : static_cast<sal_uInt16>(nLowerDist) );
+ }
+ rSet.Put( aULSpaceItem );
+ }
+
+ sal_uInt32 i, nDefaultTab, nTab, nTextOfs2 = 0;
+ sal_uInt32 nLatestManTab = 0;
+ GetAttrib( PPT_ParaAttr_TextOfs, nTextOfs2, nDestinationInstance );
+ GetAttrib( PPT_ParaAttr_BulletOfs, nTab, nDestinationInstance );
+ GetAttrib( PPT_ParaAttr_DefaultTab, nDefaultTab, nDestinationInstance );
+
+ SvxTabStopItem aTabItem( 0, 0, SvxTabAdjust::Default, EE_PARA_TABS );
+ if ( GetTabCount() )
+ {
+ for ( i = 0; i < GetTabCount(); i++ )
+ {
+ SvxTabAdjust eTabAdjust;
+ nTab = GetTabOffsetByIndex( static_cast<sal_uInt16>(i) );
+ switch( GetTabStyleByIndex( static_cast<sal_uInt16>(i) ) )
+ {
+ case 1 : eTabAdjust = SvxTabAdjust::Center; break;
+ case 2 : eTabAdjust = SvxTabAdjust::Right; break;
+ case 3 : eTabAdjust = SvxTabAdjust::Decimal; break;
+ default : eTabAdjust = SvxTabAdjust::Left;
+ }
+ aTabItem.Insert(SvxTabStop(convertMasterUnitToMm100(nTab), eTabAdjust));
+ }
+ nLatestManTab = nTab;
+ }
+ if ( nIsBullet2 == 0 )
+ aTabItem.Insert( SvxTabStop( sal_uInt16(0) ) );
+ if ( nDefaultTab )
+ {
+ nTab = std::max( nTextOfs2, nLatestManTab );
+ nTab /= nDefaultTab;
+ nTab = nDefaultTab * ( 1 + nTab );
+ for ( i = 0; ( i < 20 ) && ( nTab < 0x1b00 ); i++ )
+ {
+ aTabItem.Insert( SvxTabStop( convertMasterUnitToMm100(nTab)));
+ nTab += nDefaultTab;
+ }
+ }
+ rSet.Put( aTabItem );
+}
+
+sal_uInt32 PPTParagraphObj::GetTextSize()
+{
+ sal_uInt32 nCount, nRetValue = 0;
+ for (const std::unique_ptr<PPTPortionObj> & i : m_PortionList)
+ {
+ PPTPortionObj const& rPortionObj = *i;
+ nCount = rPortionObj.Count();
+ if ((!nCount) && rPortionObj.mpFieldItem)
+ nCount++;
+ nRetValue += nCount;
+ }
+ return nRetValue;
+}
+
+PPTPortionObj* PPTParagraphObj::First()
+{
+ mnCurrentObject = 0;
+ if (m_PortionList.empty())
+ return nullptr;
+ return m_PortionList.front().get();
+}
+
+PPTPortionObj* PPTParagraphObj::Next()
+{
+ sal_uInt32 i = mnCurrentObject + 1;
+ if (i >= m_PortionList.size())
+ return nullptr;
+ mnCurrentObject++;
+ return m_PortionList[i].get();
+}
+
+PPTFieldEntry::~PPTFieldEntry()
+{
+}
+
+void PPTFieldEntry::GetDateTime( const sal_uInt32 nVal, SvxDateFormat& eDateFormat, SvxTimeFormat& eTimeFormat )
+{
+ eDateFormat = SvxDateFormat::AppDefault;
+ eTimeFormat = SvxTimeFormat::AppDefault;
+ // evaluate ID
+ switch( nVal )
+ {
+ case 0:
+ case 6:
+ eDateFormat = SvxDateFormat::A;
+ break;
+ case 1:
+ eDateFormat = SvxDateFormat::F;
+ break;
+ case 2:
+ case 3:
+ eDateFormat = SvxDateFormat::D;
+ break;
+ case 4:
+ case 5:
+ eDateFormat = SvxDateFormat::C;
+ break;
+ case 7:
+ eDateFormat = SvxDateFormat::A;
+ [[fallthrough]];
+ case 9:
+ eTimeFormat = SvxTimeFormat::HH24_MM;
+ break;
+ case 8:
+ eDateFormat = SvxDateFormat::A;
+ [[fallthrough]];
+ case 11:
+ eTimeFormat = SvxTimeFormat::HH12_MM;
+ break;
+ case 10:
+ eTimeFormat = SvxTimeFormat::HH24_MM_SS;
+ break;
+ case 12:
+ eTimeFormat = SvxTimeFormat::HH12_MM_SS;
+ break;
+ }
+}
+
+void PPTFieldEntry::SetDateTime( sal_uInt32 nVal )
+{
+ SvxDateFormat eDateFormat;
+ SvxTimeFormat eTimeFormat;
+ GetDateTime( nVal, eDateFormat, eTimeFormat );
+ if ( eDateFormat != SvxDateFormat::AppDefault )
+ xField1.reset(new SvxFieldItem(SvxDateField( Date( Date::SYSTEM ), SvxDateType::Var, eDateFormat ), EE_FEATURE_FIELD));
+ if ( eTimeFormat != SvxTimeFormat::AppDefault )
+ {
+ std::unique_ptr<SvxFieldItem> xFieldItem(new SvxFieldItem(SvxExtTimeField( tools::Time( tools::Time::SYSTEM ), SvxTimeType::Var, eTimeFormat ), EE_FEATURE_FIELD));
+ if (xField1)
+ xField2 = std::move(xFieldItem);
+ else
+ xField1 = std::move(xFieldItem);
+ }
+}
+
+PPTTextObj::PPTTextObj( SvStream& rIn, SdrPowerPointImport& rSdrPowerPointImport, PptSlidePersistEntry& rPersistEntry, DffObjData const * pObjData ) :
+ mxImplTextObj ( new ImplPPTTextObj( rPersistEntry ) )
+{
+ mxImplTextObj->mnShapeId = 0;
+ mxImplTextObj->mnShapeMaster = 0;
+ mxImplTextObj->mnDestinationInstance = mxImplTextObj->mnInstance = TSS_Type::TextInShape;
+ mxImplTextObj->mnCurrentObject = 0;
+ mxImplTextObj->mnParagraphCount = 0;
+ mxImplTextObj->mnTextFlags = 0;
+ mxImplTextObj->meShapeType = ( pObjData && pObjData->bShapeType ) ? pObjData->eShapeType : mso_sptMin;
+
+ DffRecordHeader aExtParaHd;
+ aExtParaHd.nRecType = 0; // set empty
+
+
+ DffRecordHeader aShapeContainerHd;
+ ReadDffRecordHeader( rIn, aShapeContainerHd );
+
+ if ( !(( pObjData == nullptr ) || ( pObjData->bShapeType )) )
+ return;
+
+ PPTExtParaProv* pExtParaProv = rSdrPowerPointImport.m_pPPTStyleSheet->pExtParaProv.get();
+ if ( pObjData )
+ {
+ mxImplTextObj->mnShapeId = pObjData->nShapeId;
+ if ( pObjData->nSpFlags & ShapeFlag::HaveMaster )
+ mxImplTextObj->mnShapeMaster = rSdrPowerPointImport.GetPropertyValue( DFF_Prop_hspMaster, 0 );
+ }
+ // ClientData
+ if ( rSdrPowerPointImport.maShapeRecords.SeekToContent( rIn, DFF_msofbtClientData, SEEK_FROM_CURRENT_AND_RESTART ) )
+ {
+ sal_uInt32 nOldPos = rIn.Tell();
+ DffRecordHeader& aClientDataContainerHd = *rSdrPowerPointImport.maShapeRecords.Current();
+ DffRecordHeader aPlaceHolderAtomHd;
+ if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_OEPlaceholderAtom, aClientDataContainerHd.GetRecEndFilePos(), &aPlaceHolderAtomHd ) )
+ {
+ mxImplTextObj->mpPlaceHolderAtom.reset( new PptOEPlaceholderAtom );
+ ReadPptOEPlaceholderAtom( rIn, *( mxImplTextObj->mpPlaceHolderAtom ) );
+ }
+ rIn.Seek( nOldPos );
+ DffRecordHeader aProgTagHd;
+ if ( SdrPowerPointImport::SeekToContentOfProgTag( 9, rIn, aClientDataContainerHd, aProgTagHd ) )
+ {
+ ReadDffRecordHeader( rIn, aExtParaHd );
+ }
+ }
+
+ // ClientTextBox
+ if ( !rSdrPowerPointImport.maShapeRecords.SeekToContent( rIn, DFF_msofbtClientTextbox, SEEK_FROM_CURRENT_AND_RESTART ) )
+ return;
+
+ bool bStatus = true;
+
+
+ DffRecordHeader aClientTextBoxHd( *rSdrPowerPointImport.maShapeRecords.Current() );
+ sal_uInt32 nTextRulerAtomOfs = 0; // case of zero -> this atom may be found in aClientDataContainerHd;
+ // case of -1 -> there is no atom of this kind
+ // else -> this is the fileofs where we can get it
+
+ // checkout if this is a referenced
+ // textobj, if so the we will patch
+ // the ClientTextBoxHd for a
+ // equivalent one
+ DffRecordHeader aTextHd;
+ if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_OutlineTextRefAtom, aClientTextBoxHd.GetRecEndFilePos(), &aTextHd ) )
+ {
+ sal_uInt32 nRefNum;
+ rIn.ReadUInt32( nRefNum );
+
+ if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextRulerAtom, aClientTextBoxHd.GetRecEndFilePos() ) )
+ nTextRulerAtomOfs = rIn.Tell();
+ else
+ nTextRulerAtomOfs = 0xffffffff;
+
+ switch( rSdrPowerPointImport.m_eCurrentPageKind )
+ {
+ case PPT_NOTEPAGE :
+ case PPT_MASTERPAGE :
+ case PPT_SLIDEPAGE :
+ break;
+ default :
+ bStatus = false;
+ }
+ if ( bStatus )
+ {
+ sal_uInt32 nSlideId = rSdrPowerPointImport.GetCurrentPageId();
+ if ( !nSlideId )
+ bStatus = false;
+ else
+ {
+ if ( !aExtParaHd.nRecType )
+ {
+ sal_uInt32 nOldPos = rIn.Tell();
+ // try to locate the referenced ExtendedParaHd
+ DffRecordHeader* pHd = pExtParaProv->
+ aExtendedPresRules.GetRecordHeader( PPT_PST_ExtendedParagraphHeaderAtom,
+ SEEK_FROM_CURRENT_AND_RESTART );
+ DffRecordHeader aPresRuleHd;
+ DffRecordHeader* pFirst = pHd;
+
+ while ( pHd )
+ {
+ pHd->SeekToContent( rIn );
+ sal_uInt32 nTmpSlideId(0), nTmpRef;
+ rIn.ReadUInt32( nTmpSlideId )
+ .ReadUInt32( nTmpRef ); // this seems to be the instance
+
+ if ( ( nTmpSlideId == nSlideId ) && ( pHd->nRecInstance == nRefNum ) )
+ {
+ if (!pHd->SeekToEndOfRecord(rIn))
+ break;
+ ReadDffRecordHeader( rIn, aPresRuleHd );
+ if ( aPresRuleHd.nRecType == PPT_PST_ExtendedParagraphAtom )
+ {
+ aExtParaHd = aPresRuleHd;
+ break;
+ }
+ }
+ pHd = pExtParaProv->
+ aExtendedPresRules.GetRecordHeader( PPT_PST_ExtendedParagraphHeaderAtom,
+ SEEK_FROM_CURRENT_AND_RESTART );
+ if ( pHd == pFirst )
+ break;
+ }
+ rIn.Seek( nOldPos );
+ }
+ // now pHd points to the right SlideListWithText Container
+ PptSlidePersistList* pPageList = rSdrPowerPointImport.GetPageList( rSdrPowerPointImport.m_eCurrentPageKind );
+ PptSlidePersistEntry* pE = nullptr;
+ if ( pPageList && ( rSdrPowerPointImport.m_nCurrentPageNum < pPageList->size() ) )
+ pE = &(*pPageList)[ rSdrPowerPointImport.m_nCurrentPageNum ];
+ if ( (!pE) || (!pE->nSlidePersistStartOffset) || ( pE->aPersistAtom.nSlideId != nSlideId ) )
+ bStatus = false;
+ else
+ {
+ auto nOffset(pE->nSlidePersistStartOffset);
+ bStatus = (nOffset == rIn.Seek(nOffset));
+ // now we got the right page and are searching for the right
+ // TextHeaderAtom
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pE->nSlidePersistEndOffset);
+ while (bStatus && rIn.Tell() < nEndRecPos)
+ {
+ ReadDffRecordHeader( rIn, aClientTextBoxHd );
+ if ( aClientTextBoxHd.nRecType == PPT_PST_TextHeaderAtom )
+ {
+ if ( aClientTextBoxHd.nRecInstance == nRefNum )
+ {
+ aClientTextBoxHd.SeekToEndOfRecord( rIn );
+ break;
+ }
+ }
+ if (!aClientTextBoxHd.SeekToEndOfRecord(rIn))
+ break;
+ }
+ if ( rIn.Tell() > pE->nSlidePersistEndOffset )
+ bStatus = false;
+ else
+ { // patching the RecordHeader
+ aClientTextBoxHd.nFilePos -= DFF_COMMON_RECORD_HEADER_SIZE;
+ aClientTextBoxHd.nRecLen += DFF_COMMON_RECORD_HEADER_SIZE;
+ aClientTextBoxHd.nRecType = DFF_msofbtClientTextbox;
+ aClientTextBoxHd.nRecVer = DFF_PSFLAG_CONTAINER;
+
+ // we have to calculate the correct record len
+ DffRecordHeader aTmpHd;
+ nEndRecPos = DffPropSet::SanitizeEndPos(rIn, pE->nSlidePersistEndOffset);
+ while (rIn.Tell() < nEndRecPos)
+ {
+ ReadDffRecordHeader( rIn, aTmpHd );
+ if ( ( aTmpHd.nRecType == PPT_PST_SlidePersistAtom ) || ( aTmpHd.nRecType == PPT_PST_TextHeaderAtom ) )
+ break;
+ if (!aTmpHd.SeekToEndOfRecord(rIn))
+ break;
+ aClientTextBoxHd.nRecLen += aTmpHd.nRecLen + DFF_COMMON_RECORD_HEADER_SIZE;
+ }
+ aClientTextBoxHd.SeekToContent( rIn );
+ }
+ }
+ }
+ }
+ }
+
+ if ( !bStatus )
+ return;
+
+ if ( !SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextHeaderAtom, aClientTextBoxHd.GetRecEndFilePos(), &aTextHd ) )
+ return;
+
+ // TextHeaderAtom is always the first Atom
+ sal_uInt16 nTmp(0);
+ rIn.ReadUInt16(nTmp); // this number tells us the TxMasterStyleAtom Instance
+ if (nTmp > 8)
+ nTmp = 4;
+ TSS_Type nInstance = static_cast<TSS_Type>(nTmp);
+ aTextHd.SeekToEndOfRecord( rIn );
+ mxImplTextObj->mnInstance = nInstance;
+
+ sal_uInt32 nFilePos = rIn.Tell();
+ if ( !(rSdrPowerPointImport.SeekToRec2( PPT_PST_TextBytesAtom,
+ PPT_PST_TextCharsAtom,
+ aClientTextBoxHd.GetRecEndFilePos() )
+ || SvxMSDffManager::SeekToRec( rIn,
+ PPT_PST_StyleTextPropAtom,
+ aClientTextBoxHd.GetRecEndFilePos() )) )
+ return;
+
+ PPTTextRulerInterpreter aTextRulerInterpreter( nTextRulerAtomOfs, aClientTextBoxHd, rIn );
+
+ PPTStyleTextPropReader aStyleTextPropReader( rIn, aClientTextBoxHd,
+ aTextRulerInterpreter, aExtParaHd, nInstance );
+ sal_uInt32 nParagraphs = mxImplTextObj->mnParagraphCount = aStyleTextPropReader.aParaPropList.size();
+ if ( !nParagraphs )
+ return;
+
+ // the language settings will be merged into the list of PPTCharPropSet
+ DffRecordHeader aTextSpecInfoHd;
+ PPTTextSpecInfoAtomInterpreter aTextSpecInfoAtomInterpreter;
+ if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_TextSpecInfoAtom,
+ aClientTextBoxHd.GetRecEndFilePos(), &aTextSpecInfoHd ) )
+ {
+ if ( aTextSpecInfoAtomInterpreter.Read( rIn, aTextSpecInfoHd, PPT_PST_TextSpecInfoAtom,
+ &(rSdrPowerPointImport.m_pPPTStyleSheet->maTxSI) ) )
+ {
+ size_t nI = 0;
+ for (const PPTTextSpecInfo& rSpecInfo : aTextSpecInfoAtomInterpreter.aList)
+ {
+ sal_uInt32 nCharIdx = rSpecInfo.nCharIdx;
+
+ // portions and text have to been split in some cases
+ for ( ; nI < aStyleTextPropReader.aCharPropList.size(); ++nI)
+ {
+ PPTCharPropSet* pSet = aStyleTextPropReader.aCharPropList[nI].get();
+ if (pSet->mnOriginalTextPos >= nCharIdx)
+ break;
+ pSet->mnLanguage[0] = rSpecInfo.nLanguage[0];
+ pSet->mnLanguage[1] = rSpecInfo.nLanguage[1];
+ pSet->mnLanguage[2] = rSpecInfo.nLanguage[2];
+ // test if the current portion needs to be split
+ if (pSet->maString.getLength() <= 1)
+ continue;
+ sal_Int32 nIndexOfNextPortion = pSet->maString.getLength() + pSet->mnOriginalTextPos;
+ sal_Int32 nNewLen = nIndexOfNextPortion - nCharIdx;
+ if (nNewLen <= 0)
+ continue;
+ sal_Int32 nOldLen = pSet->maString.getLength() - nNewLen;
+ if (nOldLen <= 0)
+ continue;
+ OUString aString(pSet->maString);
+ PPTCharPropSet* pNew = new PPTCharPropSet(*pSet);
+ pSet->maString = aString.copy(0, nOldLen);
+ pNew->maString = aString.copy(nOldLen, nNewLen);
+ pNew->mnOriginalTextPos += nOldLen;
+ aStyleTextPropReader.aCharPropList.emplace(aStyleTextPropReader.aCharPropList.begin() + nI + 1, pNew);
+ }
+ }
+ }
+#ifdef DBG_UTIL
+ else
+ {
+ if (!(rSdrPowerPointImport.rImportParam.nImportFlags & PPT_IMPORTFLAGS_NO_TEXT_ASSERT))
+ {
+ OSL_FAIL( "SdrTextSpecInfoAtomInterpreter::Ctor(): parsing error, this document needs to be analysed (SJ)" );
+ }
+ }
+#endif
+ }
+ // now will search for possible textextensions such as date/time fields
+ // or ParaTabStops and append them on this textobj
+ rIn.Seek( nFilePos );
+ ::std::vector< std::unique_ptr<PPTFieldEntry> > FieldList;
+ auto nEndRecPos = DffPropSet::SanitizeEndPos(rIn, aClientTextBoxHd.GetRecEndFilePos());
+ while (rIn.Tell() < nEndRecPos)
+ {
+ ReadDffRecordHeader( rIn, aTextHd );
+ sal_uInt16 nVal = 0;
+ std::unique_ptr<PPTFieldEntry> xEntry;
+ switch ( aTextHd.nRecType )
+ {
+ case PPT_PST_DateTimeMCAtom :
+ {
+ xEntry.reset(new PPTFieldEntry);
+ rIn.ReadUInt16(xEntry->nPos)
+ .ReadUInt16( nVal )
+ .ReadUInt16( nVal );
+ xEntry->SetDateTime( nVal & 0xff );
+ }
+ break;
+
+ case PPT_PST_FooterMCAtom :
+ {
+ xEntry.reset(new PPTFieldEntry);
+ rIn.ReadUInt16(xEntry->nPos);
+ xEntry->xField1.reset(new SvxFieldItem(SvxFooterField(), EE_FEATURE_FIELD));
+ }
+ break;
+
+ case PPT_PST_HeaderMCAtom :
+ {
+ xEntry.reset(new PPTFieldEntry);
+ rIn.ReadUInt16(xEntry->nPos);
+ xEntry->xField1.reset(new SvxFieldItem(SvxHeaderField(), EE_FEATURE_FIELD));
+ }
+ break;
+
+ case PPT_PST_GenericDateMCAtom :
+ {
+ xEntry.reset(new PPTFieldEntry);
+ rIn.ReadUInt16(xEntry->nPos);
+ xEntry->xField1.reset(new SvxFieldItem(SvxDateTimeField(), EE_FEATURE_FIELD));
+ if (rPersistEntry.xHeaderFooterEntry) // sj: #i34111# on master pages it is possible
+ { // that there is no HeaderFooterEntry available
+ if (rPersistEntry.xHeaderFooterEntry->nAtom & 0x20000) // auto date time
+ xEntry->SetDateTime(rPersistEntry.xHeaderFooterEntry->nAtom & 0xff);
+ else
+ xEntry->xString = rPersistEntry.xHeaderFooterEntry->pPlaceholder[nVal];
+ }
+ }
+ break;
+
+ case PPT_PST_SlideNumberMCAtom :
+ case PPT_PST_RTFDateTimeMCAtom :
+ {
+ xEntry.reset(new PPTFieldEntry);
+ if ( aTextHd.nRecLen >= 4 )
+ {
+ rIn.ReadUInt16(xEntry->nPos)
+ .ReadUInt16( nVal );
+
+ // evaluate ID
+ //SvxFieldItem* pFieldItem = NULL;
+ switch( aTextHd.nRecType )
+ {
+ case PPT_PST_SlideNumberMCAtom:
+ xEntry->xField1.reset(new SvxFieldItem(SvxPageField(), EE_FEATURE_FIELD));
+ break;
+
+ case PPT_PST_RTFDateTimeMCAtom:
+ {
+ // Rude workaround for one special case reported
+ // by a customer. (#i75203#)
+
+ // Don't even attempt to handle the general use
+ // case for PPT_PST_RTFDateTimeMCAtom (a generic
+ // MS style date/time format string). Just handle
+ // the special case where the format string
+ // contains only one or several possibly empty
+ // quoted strings. I.e. something that doesn't
+ // expand to any date or time at all, but to a
+ // fixed string. How on earth somebody manages to
+ // produce such things in PPT slides I have no
+ // idea.
+ if (nVal == 0)
+ {
+ OUStringBuffer aStr;
+ bool inquote = false;
+ for (int nLen = 0; nLen < 64; ++nLen)
+ {
+ sal_Unicode n(0);
+ rIn.ReadUtf16( n );
+
+ // Collect quoted characters into aStr
+ if ( n == '\'')
+ inquote = !inquote;
+ else if (!n)
+ {
+ // End of format string
+ xEntry->xString = aStr.makeStringAndClear();
+ break;
+ }
+ else if (!inquote)
+ {
+ // Non-quoted character, i.e. a real
+ // format specifier. We don't handle
+ // those. Sorry.
+ break;
+ }
+ else
+ {
+ aStr.append(OUStringChar(n));
+ }
+ }
+ }
+ if (!xEntry->xString)
+ {
+ // Handle as previously
+ xEntry->xField1.reset(new SvxFieldItem( SvxDateField( Date( Date::SYSTEM ), SvxDateType::Fix ), EE_FEATURE_FIELD ));
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ case PPT_PST_InteractiveInfo :
+ {
+ DffRecordHeader aHdInteractiveInfoAtom;
+ if ( SvxMSDffManager::SeekToRec( rIn, PPT_PST_InteractiveInfoAtom, aTextHd.GetRecEndFilePos(), &aHdInteractiveInfoAtom ) )
+ {
+ PptInteractiveInfoAtom aInteractiveInfoAtom;
+ ReadPptInteractiveInfoAtom( rIn, aInteractiveInfoAtom );
+ for (const SdHyperlinkEntry& rHyperlink : rSdrPowerPointImport.m_aHyperList)
+ {
+ if ( rHyperlink.nIndex == aInteractiveInfoAtom.nExHyperlinkId )
+ {
+ if (!aTextHd.SeekToEndOfRecord(rIn))
+ {
+ break;
+ }
+ ReadDffRecordHeader( rIn, aTextHd );
+ if ( aTextHd.nRecType != PPT_PST_TxInteractiveInfoAtom )
+ {
+ aTextHd.SeekToBegOfRecord( rIn );
+ continue;
+ }
+ else
+ {
+ sal_uInt32 nStartPos, nEndPos;
+ rIn.ReadUInt32( nStartPos )
+ .ReadUInt32( nEndPos );
+ if ( nEndPos )
+ {
+ xEntry.reset(new PPTFieldEntry);
+ xEntry->nPos = static_cast<sal_uInt16>(nStartPos);
+ xEntry->nTextRangeEnd = static_cast<sal_uInt16>(nEndPos);
+ OUString aTarget( rHyperlink.aTarget );
+ if ( !rHyperlink.aConvSubString.isEmpty() )
+ {
+ aTarget += "#" + rHyperlink.aConvSubString;
+ }
+ xEntry->xField1.reset(new SvxFieldItem( SvxURLField( aTarget, OUString(), SvxURLFormat::Repr ), EE_FEATURE_FIELD ));
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ if (!aTextHd.SeekToEndOfRecord(rIn))
+ break;
+ if (xEntry)
+ {
+ // sorting fields ( hi >> lo )
+ auto it = std::find_if(FieldList.begin(), FieldList.end(),
+ [&xEntry](const std::unique_ptr<PPTFieldEntry>& rxField) {
+ return rxField->nPos < xEntry->nPos; });
+ if ( it != FieldList.end() ) {
+ FieldList.insert(it, std::move(xEntry));
+ } else {
+ FieldList.push_back( std::move(xEntry));
+ }
+ }
+ }
+ if ( !FieldList.empty() )
+ {
+ auto FE = FieldList.begin();
+ auto& aCharPropList = aStyleTextPropReader.aCharPropList;
+
+ sal_Int32 i = nParagraphs - 1;
+ sal_Int32 n = aCharPropList.size() - 1;
+
+ // at this point we just have a list of textportions(aCharPropList)
+ // the next while loop tries to resolve the list of fields(pFieldList)
+ while( ( FE < FieldList.end() ) && ( n >= 0 ) && ( i >= 0 ) )
+ {
+ PPTCharPropSet* pSet = aCharPropList[n].get();
+ OUString aString( pSet->maString );
+ sal_uInt32 nCount = aString.getLength();
+ sal_uInt32 nPos = pSet->mnOriginalTextPos + nCount;
+ while ( ( FE < FieldList.end() ) && nCount-- )
+ {
+ nPos--;
+ FE = std::find_if(FE, FieldList.end(),
+ [&nPos](const std::unique_ptr<PPTFieldEntry>& rxField) {return rxField->nPos <= nPos;});
+ if (FE == FieldList.end())
+ break;
+
+ if ( (*FE)->nPos == nPos )
+ {
+ if ( aString[nCount] == 0x2a )
+ {
+ sal_uInt32 nBehind = aString.getLength() - ( nCount + 1 );
+ pSet->maString.clear();
+ if ( nBehind )
+ {
+ PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
+ pNewCPS->maString = aString.copy( nCount + 1, nBehind );
+ aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
+ }
+ if ( (*FE)->xField2 )
+ {
+ PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
+ pNewCPS->mpFieldItem = std::move((*FE)->xField2);
+ aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
+
+ pNewCPS = new PPTCharPropSet( *pSet );
+ pNewCPS->maString = " ";
+ aCharPropList.emplace( aCharPropList.begin() + n + 1, pNewCPS );
+ }
+ if ( nCount )
+ {
+ PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pSet );
+ pNewCPS->maString = aString.copy( 0, nCount );
+ aCharPropList.emplace( aCharPropList.begin() + n++, pNewCPS );
+ }
+ if ( (*FE)->xField1 )
+ {
+ pSet->mpFieldItem = std::move((*FE)->xField1);
+ }
+ else if ( (*FE)->xString )
+ pSet->maString = *(*FE)->xString;
+ }
+ else
+ {
+ if ( (*FE)->nTextRangeEnd ) // text range hyperlink
+ {
+ sal_uInt32 nHyperLen = (*FE)->nTextRangeEnd - nPos;
+ if ( nHyperLen )
+ {
+ PPTCharPropSet* pBefCPS = nullptr;
+ if ( nCount )
+ {
+ pBefCPS = new PPTCharPropSet( *pSet );
+ pSet->maString = pSet->maString.copy(nCount);
+ }
+ sal_uInt32 nIdx = n;
+ sal_Int32 nHyperLenLeft = nHyperLen;
+
+ while ( ( aCharPropList.size() > nIdx ) && nHyperLenLeft )
+ {
+ // the textrange hyperlink can take more than 1 paragraph
+ // the solution here is to clone the hyperlink...
+
+ PPTCharPropSet* pCurrent = aCharPropList[ nIdx ].get();
+ sal_Int32 nNextStringLen = pCurrent->maString.getLength();
+
+ DBG_ASSERT( (*FE)->xField1, "missing field!" );
+ if (!(*FE)->xField1)
+ break;
+
+ const SvxURLField* pField = static_cast<const SvxURLField*>((*FE)->xField1->GetField());
+
+ pCurrent->mbIsHyperlink = true;
+ pCurrent->mnHylinkOrigColor = pCurrent->mpImplPPTCharPropSet->mnColor;
+ pCurrent->mbHardHylinkOrigColor = ( ( pCurrent->mpImplPPTCharPropSet->mnAttrSet >>PPT_CharAttr_FontColor ) & 1)>0;
+
+ // add missing attribute to show underline property
+ pCurrent->mpImplPPTCharPropSet->mnAttrSet |= 1 << PPT_CharAttr_Underline;
+ pCurrent->mpImplPPTCharPropSet->mnFlags = 1 << PPT_CharAttr_Underline;
+
+ if ( pCurrent->mpFieldItem )
+ {
+ pCurrent->SetColor( PPT_COLSCHEME_A_UND_HYPERLINK );
+ if ( dynamic_cast< const SvxURLField* >(pCurrent->mpFieldItem->GetField()) != nullptr)
+ break;
+ nHyperLenLeft--;
+ }
+ else if ( nNextStringLen )
+ {
+ if ( nNextStringLen <= nHyperLenLeft )
+ {
+ pCurrent->mpFieldItem.reset( new SvxFieldItem( SvxURLField( pField->GetURL(), pCurrent->maString, SvxURLFormat::Repr ), EE_FEATURE_FIELD ) );
+ nHyperLenLeft -= nNextStringLen;
+
+ if ( nHyperLenLeft )
+ {
+ // if the next portion is in a higher paragraph,
+ // the textrange is to decrease (because of the LineBreak character)
+ if ( aCharPropList.size() > ( nIdx + 1 ) )
+ {
+ PPTCharPropSet* pNext = aCharPropList[ nIdx + 1 ].get();
+ if ( pNext->mnParagraph > pCurrent->mnParagraph )
+ nHyperLenLeft--;
+ }
+ }
+ }
+ else
+ {
+ PPTCharPropSet* pNewCPS = new PPTCharPropSet( *pCurrent );
+ pNewCPS->maString = pCurrent->maString.copy( nHyperLenLeft,( nNextStringLen - nHyperLenLeft ) );
+ aCharPropList.emplace( aCharPropList.begin() + nIdx + 1, pNewCPS );
+ OUString aRepresentation = pCurrent->maString.copy( 0, nHyperLenLeft );
+ pCurrent->mpFieldItem.reset( new SvxFieldItem( SvxURLField( pField->GetURL(), aRepresentation, SvxURLFormat::Repr ), EE_FEATURE_FIELD ) );
+ nHyperLenLeft = 0;
+ }
+ pCurrent->maString.clear();
+ pCurrent->SetColor( PPT_COLSCHEME_A_UND_HYPERLINK );
+ }
+ nIdx++;
+ }
+ (*FE)->xField1.reset();
+
+ if ( pBefCPS )
+ {
+ pBefCPS->maString = aString.copy( 0, nCount );
+ aCharPropList.emplace( aCharPropList.begin() + n, pBefCPS );
+ n++;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ n--;
+ }
+ }
+ mxImplTextObj->maParagraphList.resize( nParagraphs );
+ for (size_t nCurCharPos = 0, nCurPos = 0;
+ nCurPos < aStyleTextPropReader.aParaPropList.size();
+ ++nCurPos)
+ {
+ mxImplTextObj->maParagraphList[ nCurPos ].reset(
+ new PPTParagraphObj(
+ aStyleTextPropReader, nCurPos, nCurCharPos,
+ *rSdrPowerPointImport.m_pPPTStyleSheet,
+ nInstance, aTextRulerInterpreter ) );
+
+ sal_uInt32 nParaAdjust, nFlags = 0;
+ mxImplTextObj->maParagraphList[ nCurPos ]->GetAttrib( PPT_ParaAttr_Adjust, nParaAdjust, GetInstance() );
+
+ switch ( nParaAdjust )
+ {
+ case 0 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT; break;
+ case 1 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER; break;
+ case 2 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT; break;
+ case 3 : nFlags = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK; break;
+ }
+ mxImplTextObj->mnTextFlags |= nFlags;
+ }
+}
+
+PPTTextObj::PPTTextObj( PPTTextObj const & rTextObj )
+{
+ mxImplTextObj = rTextObj.mxImplTextObj;
+}
+
+PPTTextObj::~PPTTextObj()
+{
+}
+
+PPTParagraphObj* PPTTextObj::First()
+{
+ mxImplTextObj->mnCurrentObject = 0;
+ if ( !mxImplTextObj->mnParagraphCount )
+ return nullptr;
+ return mxImplTextObj->maParagraphList[ 0 ].get();
+}
+
+PPTParagraphObj* PPTTextObj::Next()
+{
+ sal_uInt32 i = mxImplTextObj->mnCurrentObject + 1;
+ if ( i >= mxImplTextObj->mnParagraphCount )
+ return nullptr;
+ mxImplTextObj->mnCurrentObject++;
+ return mxImplTextObj->maParagraphList[ i ].get();
+}
+
+const SfxItemSet* PPTTextObj::GetBackground() const
+{
+ if ( mxImplTextObj->mrPersistEntry.pBObj )
+ return &mxImplTextObj->mrPersistEntry.pBObj->GetMergedItemSet();
+ else
+ return nullptr;
+}
+
+PPTTextObj& PPTTextObj::operator=( const PPTTextObj& rTextObj )
+{
+ if ( this != &rTextObj )
+ {
+ mxImplTextObj = rTextObj.mxImplTextObj;
+ }
+ return *this;
+}
+
+static bool IsLine( const SdrObject* pObj )
+{
+ auto pSdrPathObj = dynamic_cast< const SdrPathObj* >(pObj);
+ return pSdrPathObj && pSdrPathObj->IsLine() && pSdrPathObj->GetPointCount() == 2;
+}
+
+static bool GetCellPosition( const SdrObject* pObj, const o3tl::sorted_vector< sal_Int32 >& rRows, const o3tl::sorted_vector< sal_Int32 >& rColumns,
+ sal_Int32& nTableIndex, sal_Int32& nRow, sal_Int32& nRowCount, sal_Int32& nColumn, sal_Int32& nColumnCount )
+{
+ tools::Rectangle aSnapRect( pObj->GetSnapRect() );
+ bool bCellObject = ( aSnapRect.GetWidth() > 1 ) && ( aSnapRect.GetHeight() > 1 );
+ if ( bCellObject )
+ {
+ auto aRowIter = rRows.find( aSnapRect.Top() );
+ auto aColumnIter = rColumns.find( aSnapRect.Left() );
+ if ( ( aRowIter == rRows.end() ) || ( aColumnIter == rColumns.end() ) )
+ bCellObject = false;
+ else
+ {
+ nRowCount = 1;
+ nRow = std::distance( rRows.begin(), aRowIter );
+ while( ++aRowIter != rRows.end() )
+ {
+ if ( *aRowIter >= aSnapRect.Bottom() )
+ break;
+ nRowCount++;
+ }
+ nColumnCount = 1;
+ nColumn = std::distance( rColumns.begin(), aColumnIter );
+ while( ++aColumnIter != rColumns.end() )
+ {
+ if ( *aColumnIter >= aSnapRect.Right() )
+ break;
+ nColumnCount++;
+ }
+ nTableIndex = nRow * rColumns.size() + nColumn;
+ }
+ }
+ return bCellObject;
+}
+
+#define LinePositionLeft 0x01000000
+#define LinePositionTop 0x02000000
+#define LinePositionRight 0x04000000
+#define LinePositionBottom 0x08000000
+#define LinePositionTLBR 0x10000000
+#define LinePositionBLTR 0x20000000
+
+
+static void GetRowPositions( const tools::Rectangle& rSnapRect, const o3tl::sorted_vector< sal_Int32 >& rRows,
+ const o3tl::sorted_vector< sal_Int32 >& rColumns, std::vector< sal_Int32 >& rPositions, sal_Int32 nColumn, sal_Int32 nFlags )
+{
+ auto aRow = rRows.find( rSnapRect.Top() );
+ if ( aRow == rRows.end() )
+ return;
+
+ sal_Int32 nRow = std::distance( rRows.begin(), aRow );
+ while( ( aRow != rRows.end() ) && ((*aRow) < rSnapRect.Bottom() ) )
+ {
+ if ( nFlags & LinePositionLeft )
+ rPositions.push_back( ( ( nRow * rColumns.size() ) + nColumn ) | LinePositionLeft );
+ if ( nFlags & LinePositionRight )
+ rPositions.push_back( ( ( nRow * rColumns.size() ) + ( nColumn - 1 ) ) | LinePositionRight );
+
+ ++nRow;
+ ++aRow;
+ }
+}
+
+
+static void GetColumnPositions( const tools::Rectangle& rSnapRect,
+ const o3tl::sorted_vector< sal_Int32 >& rColumns, std::vector< sal_Int32 >& rPositions, sal_Int32 nRow, sal_Int32 nFlags )
+{
+ auto aColumn = rColumns.find( rSnapRect.Left() );
+ if ( aColumn == rColumns.end() )
+ return;
+
+ sal_Int32 nColumn = std::distance( rColumns.begin(), aColumn );
+ while( ( aColumn != rColumns.end() ) && ((*aColumn) < rSnapRect.Right() ) )
+ {
+ if ( nFlags & LinePositionTop )
+ rPositions.push_back( ( ( nRow * rColumns.size() ) + nColumn ) | LinePositionTop );
+ if ( nFlags & LinePositionBottom )
+ rPositions.push_back( ( ( ( nRow - 1 ) * rColumns.size() ) + nColumn ) | LinePositionBottom );
+
+ ++nColumn;
+ ++aColumn;
+ }
+}
+
+static void GetLinePositions( const SdrObject* pObj, const o3tl::sorted_vector< sal_Int32 >& rRows, const o3tl::sorted_vector< sal_Int32 >& rColumns,
+ std::vector< sal_Int32 >& rPositions, const tools::Rectangle& rGroupSnap )
+{
+ tools::Rectangle aSnapRect( pObj->GetSnapRect() );
+ if ( aSnapRect.Left() == aSnapRect.Right() )
+ {
+ auto aColumn = rColumns.find( aSnapRect.Left() );
+ if ( ( aColumn != rColumns.end() ) || ( aSnapRect.Left() == rGroupSnap.Right() ) )
+ {
+ sal_Int32 nColumn, nFlags;
+ if ( aColumn != rColumns.end() )
+ {
+ nColumn = std::distance( rColumns.begin(), aColumn );
+ nFlags = LinePositionLeft;
+ if ( aColumn != rColumns.begin() )
+ nFlags |= LinePositionRight;
+ }
+ else
+ {
+ nColumn = rColumns.size();
+ nFlags = LinePositionRight;
+ }
+ GetRowPositions( aSnapRect, rRows, rColumns, rPositions, nColumn, nFlags );
+ }
+ }
+ else if ( aSnapRect.Top() == aSnapRect.Bottom() )
+ {
+ auto aRow = rRows.find( aSnapRect.Top() );
+ if ( ( aRow != rRows.end() ) || ( aSnapRect.Top() == rGroupSnap.Bottom() ) )
+ {
+ sal_Int32 nRow, nFlags;
+ if ( aRow != rRows.end() )
+ {
+ nRow = std::distance( rRows.begin(), aRow );
+ nFlags = LinePositionTop;
+ if ( aRow != rRows.begin() )
+ nFlags |= LinePositionBottom;
+ }
+ else
+ {
+ nRow = rRows.size();
+ nFlags = LinePositionBottom;
+ }
+ GetColumnPositions( aSnapRect, rColumns, rPositions, nRow, nFlags );
+ }
+ }
+ else
+ {
+ sal_uInt32 nPosition = 0;
+ Point aPt1( static_cast<const SdrPathObj*>(pObj)->GetPoint( 0 ) );
+ Point aPt2( static_cast<const SdrPathObj*>(pObj)->GetPoint( 1 ) );
+ if ( aPt1.X() < aPt2.X() )
+ nPosition |= aPt1.Y() < aPt2.Y() ? LinePositionTLBR : LinePositionBLTR;
+ else
+ nPosition |= aPt1.Y() < aPt2.Y() ? LinePositionBLTR : LinePositionTLBR;
+
+ auto aRow = rRows.find( std::min(aPt1.Y(), aPt2.Y() ) );
+ auto aColumn = rColumns.find( std::min(aPt1.X(), aPt2.X() ) );
+ if ( ( aRow != rRows.end() ) && ( aColumn != rColumns.end() ) )
+ {
+ nPosition |= ( std::distance( rRows.begin(), aRow ) * rColumns.size() ) + std::distance( rColumns.begin(), aColumn );
+ rPositions.push_back( nPosition );
+ }
+ }
+}
+
+static void CreateTableRows( const Reference< XTableRows >& xTableRows, const o3tl::sorted_vector< sal_Int32 >& rRows, sal_Int32 nTableBottom )
+{
+ if ( rRows.size() > 1 )
+ xTableRows->insertByIndex( 0, rRows.size() - 1 );
+
+ auto aIter = rRows.begin();
+ sal_Int32 nLastPosition( *aIter );
+ for ( sal_Int32 n = 0; n < xTableRows->getCount(); n++ )
+ {
+ sal_Int32 nHeight;
+ if ( ++aIter != rRows.end() )
+ {
+ if (o3tl::checked_sub<sal_Int32>(*aIter, nLastPosition, nHeight))
+ throw lang::IllegalArgumentException();
+ nLastPosition = *aIter;
+ }
+ else
+ {
+ if (o3tl::checked_sub<sal_Int32>(nTableBottom, nLastPosition, nHeight))
+ throw lang::IllegalArgumentException();
+ }
+
+ Reference< XPropertySet > xPropSet( xTableRows->getByIndex( n ), UNO_QUERY_THROW );
+ xPropSet->setPropertyValue( "Height", Any( nHeight ) );
+ }
+}
+
+static void CreateTableColumns( const Reference< XTableColumns >& xTableColumns, const o3tl::sorted_vector< sal_Int32 >& rColumns, sal_Int32 nTableRight )
+{
+ if ( rColumns.size() > 1 )
+ xTableColumns->insertByIndex( 0, rColumns.size() - 1 );
+
+ auto aIter = rColumns.begin();
+ sal_Int32 nLastPosition( *aIter );
+ for ( sal_Int32 n = 0; n < xTableColumns->getCount(); n++ )
+ {
+ sal_Int32 nWidth;
+ if ( ++aIter != rColumns.end() )
+ {
+ if (o3tl::checked_sub<sal_Int32>(*aIter, nLastPosition, nWidth))
+ throw lang::IllegalArgumentException();
+ nLastPosition = *aIter;
+ }
+ else
+ {
+ if (o3tl::checked_sub<sal_Int32>(nTableRight, nLastPosition, nWidth))
+ throw lang::IllegalArgumentException();
+ }
+
+ Reference< XPropertySet > xPropSet( xTableColumns->getByIndex( n ), UNO_QUERY_THROW );
+ xPropSet->setPropertyValue( "Width", Any( nWidth ) );
+ }
+}
+
+static void MergeCells( const Reference< XTable >& xTable, sal_Int32 nCol, sal_Int32 nRow, sal_Int32 nColSpan, sal_Int32 nRowSpan )
+{
+ DBG_ASSERT( (nColSpan > 1) || (nRowSpan > 1), "nonsense parameter!!" );
+ DBG_ASSERT( (nCol >= 0) && (nCol < xTable->getColumnCount()) && (nRow >= 0) && (nRow < xTable->getRowCount()), "the cell does not exists!!" );
+ DBG_ASSERT( (nColSpan >= 1) && ((nCol + nColSpan - 1) < xTable->getColumnCount()), "nColSpan botch!" );
+ DBG_ASSERT( (nRowSpan >= 1) && ((nRow + nRowSpan - 1) < xTable->getRowCount()), "nRowSpan botch!" );
+
+ if( xTable.is() ) try
+ {
+ Reference< XMergeableCellRange > xRange( xTable->createCursorByRange( xTable->getCellRangeByPosition( nCol, nRow,nCol + nColSpan - 1, nRow + nRowSpan - 1 ) ), UNO_QUERY_THROW );
+ if( xRange->isMergeable() )
+ xRange->merge();
+ }
+ catch( const Exception& )
+ {
+ DBG_UNHANDLED_EXCEPTION("filter.ms");
+ }
+}
+
+static void ApplyCellAttributes( const SdrObject* pObj, Reference< XCell > const & xCell )
+{
+ try
+ {
+ Reference< XPropertySet > xPropSet( xCell, UNO_QUERY_THROW );
+
+ const sal_Int32 nLeftDist(pObj->GetMergedItem(SDRATTR_TEXT_LEFTDIST).GetValue());
+ const sal_Int32 nRightDist(pObj->GetMergedItem(SDRATTR_TEXT_RIGHTDIST).GetValue());
+ const sal_Int32 nUpperDist(pObj->GetMergedItem(SDRATTR_TEXT_UPPERDIST).GetValue());
+ const sal_Int32 nLowerDist(pObj->GetMergedItem(SDRATTR_TEXT_LOWERDIST).GetValue());
+ xPropSet->setPropertyValue( "TextUpperDistance", Any( nUpperDist ) );
+ xPropSet->setPropertyValue( "TextRightDistance", Any( nRightDist ) );
+ xPropSet->setPropertyValue( "TextLeftDistance", Any( nLeftDist ) );
+ xPropSet->setPropertyValue( "TextLowerDistance", Any( nLowerDist ) );
+
+ const SdrTextVertAdjust eTextVertAdjust(pObj->GetMergedItem(SDRATTR_TEXT_VERTADJUST).GetValue());
+ drawing::TextVerticalAdjust eVA( drawing::TextVerticalAdjust_TOP );
+ if ( eTextVertAdjust == SDRTEXTVERTADJUST_CENTER )
+ eVA = drawing::TextVerticalAdjust_CENTER;
+ else if ( eTextVertAdjust == SDRTEXTVERTADJUST_BOTTOM )
+ eVA = drawing::TextVerticalAdjust_BOTTOM;
+ xPropSet->setPropertyValue( "TextVerticalAdjust", Any( eVA ) );
+
+ //set textHorizontalAdjust and TextWritingMode attr
+ const sal_Int32 eHA(pObj->GetMergedItem(SDRATTR_TEXT_HORZADJUST).GetValue());
+ const SvxFrameDirection eDirection = pObj->GetMergedItem(EE_PARA_WRITINGDIR).GetValue();
+ xPropSet->setPropertyValue( "TextHorizontalAdjust" , Any( eHA ) );
+ if ( eDirection == SvxFrameDirection::Vertical_RL_TB )
+ {//vertical writing
+ xPropSet->setPropertyValue( "TextWritingMode" , Any( css::text::WritingMode_TB_RL ) );
+ }
+ drawing::FillStyle eFillStyle(pObj->GetMergedItem( XATTR_FILLSTYLE ).GetValue());
+ css::drawing::FillStyle eFS( css::drawing::FillStyle_NONE );
+ switch( eFillStyle )
+ {
+ case drawing::FillStyle_SOLID :
+ {
+ eFS = css::drawing::FillStyle_SOLID;
+ Color aFillColor( pObj->GetMergedItem( XATTR_FILLCOLOR ).GetColorValue() );
+ xPropSet->setPropertyValue( "FillColor", Any( aFillColor ) );
+ }
+ break;
+ case drawing::FillStyle_GRADIENT :
+ {
+ eFS = css::drawing::FillStyle_GRADIENT;
+ XGradient aXGradient(pObj->GetMergedItem(XATTR_FILLGRADIENT).GetGradientValue());
+
+ css::awt::Gradient aGradient;
+ aGradient.Style = aXGradient.GetGradientStyle();
+ aGradient.StartColor = static_cast<sal_Int32>(aXGradient.GetStartColor());
+ aGradient.EndColor = static_cast<sal_Int32>(aXGradient.GetEndColor());
+ aGradient.Angle = static_cast<short>(aXGradient.GetAngle());
+ aGradient.Border = aXGradient.GetBorder();
+ aGradient.XOffset = aXGradient.GetXOffset();
+ aGradient.YOffset = aXGradient.GetYOffset();
+ aGradient.StartIntensity = aXGradient.GetStartIntens();
+ aGradient.EndIntensity = aXGradient.GetEndIntens();
+ aGradient.StepCount = aXGradient.GetSteps();
+
+ xPropSet->setPropertyValue( "FillGradient", Any( aGradient ) );
+ }
+ break;
+ case drawing::FillStyle_HATCH :
+ eFS = css::drawing::FillStyle_HATCH;
+ break;
+ case drawing::FillStyle_BITMAP :
+ {
+ eFS = css::drawing::FillStyle_BITMAP;
+
+ const XFillBitmapItem & rXFillBitmapItem(pObj->GetMergedItem( XATTR_FILLBITMAP ));
+ uno::Reference<graphic::XGraphic> xGraphic = rXFillBitmapItem.GetGraphicObject().GetGraphic().GetXGraphic();
+ uno::Reference<awt::XBitmap> xBitmap(xGraphic, uno::UNO_QUERY);
+ xPropSet->setPropertyValue("FillBitmap", uno::Any(xBitmap));
+
+ const XFillBmpStretchItem & rStretchItem(pObj->GetMergedItem( XATTR_FILLBMP_STRETCH ));
+ const XFillBmpTileItem & rTileItem(pObj->GetMergedItem( XATTR_FILLBMP_TILE ));
+ if( rTileItem.GetValue() )
+ xPropSet->setPropertyValue("FillBitmapMode", uno::Any(drawing::BitmapMode_REPEAT));
+ else if( rStretchItem.GetValue() )
+ xPropSet->setPropertyValue("FillBitmapMode", uno::Any(drawing::BitmapMode_STRETCH));
+ else
+ xPropSet->setPropertyValue("FillBitmapMode", uno::Any(drawing::BitmapMode_NO_REPEAT));
+ }
+ break;
+ default:
+ case drawing::FillStyle_NONE :
+ eFS = css::drawing::FillStyle_NONE;
+ break;
+
+ }
+ xPropSet->setPropertyValue( "FillStyle", Any( eFS ) );
+ if ( eFillStyle != drawing::FillStyle_NONE )
+ {
+ sal_Int16 nFillTransparence( pObj->GetMergedItem( XATTR_FILLTRANSPARENCE ).GetValue() );
+ xPropSet->setPropertyValue( "FillTransparence", Any( nFillTransparence ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ }
+}
+
+static void ApplyCellLineAttributes( const SdrObject* pLine, Reference< XTable > const & xTable, const std::vector< sal_Int32 >& vPositions, sal_Int32 nColumns )
+{
+ try
+ {
+ drawing::LineStyle eLineStyle(pLine->GetMergedItem( XATTR_LINESTYLE ).GetValue());
+ css::table::BorderLine2 aBorderLine;
+ switch( eLineStyle )
+ {
+ case drawing::LineStyle_DASH :
+ case drawing::LineStyle_SOLID :
+ {
+ Color aLineColor( pLine->GetMergedItem( XATTR_LINECOLOR ).GetColorValue() );
+ aBorderLine.Color = sal_Int32(aLineColor);
+ // Avoid width = 0, the min value should be 1.
+ sal_Int32 nLineWidth = std::max(sal_Int32(1), pLine->GetMergedItem(XATTR_LINEWIDTH) .GetValue() / 4);
+ aBorderLine.LineWidth = static_cast< sal_Int16 >( nLineWidth );
+ aBorderLine.LineStyle = eLineStyle == drawing::LineStyle_SOLID ? table::BorderLineStyle::SOLID : table::BorderLineStyle::DASHED;
+ }
+ break;
+ default:
+ case drawing::LineStyle_NONE :
+ {
+ aBorderLine.LineWidth = 0;
+ aBorderLine.LineStyle = table::BorderLineStyle::NONE;
+ }
+ break;
+ }
+ for (auto const& vPos : vPositions)
+ {
+ sal_Int32 nPosition = vPos & 0xffffff;
+ sal_Int32 nFlags = vPos &~0xffffff;
+ sal_Int32 nRow = nPosition / nColumns;
+ sal_Int32 nColumn = nPosition - ( nRow * nColumns );
+ Reference< XCell > xCell( xTable->getCellByPosition( nColumn, nRow ) );
+ Reference< XPropertySet > xPropSet( xCell, UNO_QUERY_THROW );
+
+ if ( nFlags & LinePositionLeft )
+ xPropSet->setPropertyValue( "LeftBorder", Any( aBorderLine ) );
+ if ( nFlags & LinePositionTop )
+ xPropSet->setPropertyValue( "TopBorder", Any( aBorderLine ) );
+ if ( nFlags & LinePositionRight )
+ xPropSet->setPropertyValue( "RightBorder", Any( aBorderLine ) );
+ if ( nFlags & LinePositionBottom )
+ xPropSet->setPropertyValue( "BottomBorder", Any( aBorderLine ) );
+ if ( nFlags & LinePositionTLBR )
+ xPropSet->setPropertyValue( "DiagonalTLBR", Any( true ) );
+ if ( nFlags & LinePositionBLTR )
+ xPropSet->setPropertyValue( "DiagonalBLTR", Any( true ) );
+ }
+ }
+ catch( const Exception& )
+ {
+ }
+}
+
+SdrObject* SdrPowerPointImport::CreateTable(SdrObject* pGroup, const sal_uInt32* pTableArry, SvxMSDffSolverContainer* pSolverContainer, std::vector<SdrObject*>& rBackgroundColoredObjects)
+{
+ SdrObject* pRet = pGroup;
+
+ sal_uInt32 nRows = pTableArry[ 1 ];
+ if (!nRows)
+ return pRet;
+
+ const SdrObjGroup* pObjGroup = dynamic_cast<const SdrObjGroup*>(pGroup);
+ if (!pObjGroup)
+ return pRet;
+
+ SdrObjList* pSubList(pObjGroup->GetSubList());
+ if (!pSubList)
+ return pRet;
+
+ o3tl::sorted_vector< sal_Int32 > aRows;
+ o3tl::sorted_vector< sal_Int32 > aColumns;
+
+ SdrObjListIter aGroupIter( pSubList, SdrIterMode::DeepNoGroups, false );
+ while( aGroupIter.IsMore() )
+ {
+ const SdrObject* pObj( aGroupIter.Next() );
+ if ( !IsLine( pObj ) )
+ {
+ tools::Rectangle aSnapRect( pObj->GetSnapRect() );
+ aRows.insert( aSnapRect.Top() );
+ aColumns.insert( aSnapRect.Left() );
+ }
+ }
+
+ if (aRows.empty())
+ return pRet;
+
+ sdr::table::SdrTableObj* pTable = new sdr::table::SdrTableObj(*pSdrModel);
+ pTable->uno_lock();
+ Reference< XTable > xTable( pTable->getTable() );
+
+ try
+ {
+ CreateTableRows( xTable->getRows(), aRows, pGroup->GetSnapRect().Bottom() );
+ CreateTableColumns( xTable->getColumns(), aColumns, pGroup->GetSnapRect().Right() );
+
+ sal_Int32 nCellCount = aRows.size() * aColumns.size();
+ std::unique_ptr<sal_Int32[]> pMergedCellIndexTable(new sal_Int32[ nCellCount ]);
+ for ( sal_Int32 i = 0; i < nCellCount; i++ )
+ pMergedCellIndexTable[ i ] = i;
+
+ aGroupIter.Reset();
+ while( aGroupIter.IsMore() )
+ {
+ SdrObject* pObj( aGroupIter.Next() );
+ if ( !IsLine( pObj ) )
+ {
+ sal_Int32 nTableIndex = 0;
+ sal_Int32 nRow = 0;
+ sal_Int32 nRowCount = 0;
+ sal_Int32 nColumn = 0;
+ sal_Int32 nColumnCount = 0;
+ if ( GetCellPosition( pObj, aRows, aColumns, nTableIndex, nRow, nRowCount, nColumn, nColumnCount ) )
+ {
+ Reference< XCell > xCell( xTable->getCellByPosition( nColumn, nRow ) );
+
+ ApplyCellAttributes( pObj, xCell );
+
+ if ( ( nRowCount > 1 ) || ( nColumnCount > 1 ) ) // cell merging
+ {
+ MergeCells( xTable, nColumn, nRow, nColumnCount, nRowCount );
+ for ( sal_Int32 nRowIter = 0; nRowIter < nRowCount; nRowIter++ )
+ {
+ for ( sal_Int32 nColumnIter = 0; nColumnIter < nColumnCount; nColumnIter++ )
+ { // now set the correct index for the merged cell
+ pMergedCellIndexTable[ ( ( nRow + nRowIter ) * aColumns.size() ) + nColumn + nColumnIter ] = nTableIndex;
+ }
+ }
+ }
+
+ // applying text
+ OutlinerParaObject* pParaObject = pObj->GetOutlinerParaObject();
+ if ( pParaObject )
+ {
+ SdrText* pSdrText = pTable->getText( nTableIndex );
+ if ( pSdrText )
+ pSdrText->SetOutlinerParaObject(*pParaObject);
+ }
+ }
+ }
+ }
+ aGroupIter.Reset();
+ while( aGroupIter.IsMore() )
+ {
+ SdrObject* pObj( aGroupIter.Next() );
+ if ( IsLine( pObj ) )
+ {
+ std::vector< sal_Int32 > vPositions; // containing cell indexes + cell position
+ GetLinePositions( pObj, aRows, aColumns, vPositions, pGroup->GetSnapRect() );
+
+ // correcting merged cell position
+ for (auto & vPos : vPositions)
+ {
+ sal_Int32 nOldPosition = vPos & 0xffff;
+ sal_Int32 nOldFlags = vPos & 0xffff0000;
+ sal_Int32 nNewPosition = pMergedCellIndexTable[ nOldPosition ] | nOldFlags;
+ vPos = nNewPosition;
+ }
+ ApplyCellLineAttributes( pObj, xTable, vPositions, aColumns.size() );
+ }
+ }
+ pMergedCellIndexTable.reset();
+
+ // we are replacing the whole group object by a single table object, so
+ // possibly connections to the group object have to be removed.
+ if ( pSolverContainer )
+ {
+ for (auto & pPtr : pSolverContainer->aCList)
+ {
+ // check connections to the group object
+ if ( pPtr->pAObj == pGroup )
+ pPtr->pAObj = nullptr;
+ if ( pPtr->pBObj == pGroup )
+ pPtr->pBObj = nullptr;
+
+ // check connections to all its subobjects
+ SdrObjListIter aIter( *pGroup, SdrIterMode::DeepWithGroups );
+ while( aIter.IsMore() )
+ {
+ SdrObject* pPartObj = aIter.Next();
+ if ( pPtr->pAObj == pPartObj )
+ pPtr->pAObj = nullptr;
+ if ( pPtr->pBObj == pPartObj )
+ pPtr->pBObj = nullptr;
+ }
+ //In MS, the one_row_one_col table is made up of five
+ //shape,the connector is connected to some part of a
+ //table. But for us, the connector is connected to the
+ //whole group table,so the connector obj is a group
+ //table when export by us. We should process this
+ //situation when importing.
+ if ( pPtr->pAObj == pGroup )
+ pPtr->pAObj = pTable;
+ if ( pPtr->pBObj == pGroup )
+ pPtr->pBObj = pTable;
+ }
+ }
+ pTable->uno_unlock();
+ pTable->SetSnapRect( pGroup->GetSnapRect() );
+ pRet = pTable;
+
+ //Remove Objects from shape map
+ SdrObjListIter aIter( *pGroup, SdrIterMode::DeepWithGroups );
+ while( aIter.IsMore() )
+ {
+ SdrObject* pPartObj = aIter.Next();
+ removeShapeId(pPartObj);
+ // ofz#41510 make sure rBackgroundColoredObjects doesn't contain deleted objects
+ std::replace(rBackgroundColoredObjects.begin(), rBackgroundColoredObjects.end(), pPartObj, pRet);
+ }
+
+ SdrObject::Free( pGroup );
+ }
+ catch( const Exception& )
+ {
+ pTable->uno_unlock();
+ SdrObject* pObj = pTable;
+ SdrObject::Free( pObj );
+ }
+
+ return pRet;
+}
+
+bool SdrPowerPointImport::IsVerticalText() const
+{
+ bool bVerticalText = false;
+ if ( IsProperty( DFF_Prop_txflTextFlow ) )
+ {
+ auto eTextFlow = GetPropertyValue(DFF_Prop_txflTextFlow, 0) & 0xFFFF;
+ switch( eTextFlow )
+ {
+ case mso_txflTtoBA : // Top to Bottom @-font, above -> below
+ case mso_txflTtoBN : // Top to Bottom non-@, above -> below
+ case mso_txflVertN : // Vertical, non-@, above -> below
+ bVerticalText = !bVerticalText;
+ break;
+ default: break;
+ }
+ }
+
+ return bVerticalText;
+}
+
+void SdrPowerPointImport::ApplyTextAnchorAttributes( PPTTextObj const & rTextObj, SfxItemSet& rSet ) const
+{
+ SdrTextVertAdjust eTVA;
+ SdrTextHorzAdjust eTHA;
+
+ sal_uInt32 nTextFlags = rTextObj.GetTextFlags();
+
+ nTextFlags &= PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT
+ | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_CENTER | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_BLOCK;
+
+ if ( IsVerticalText() )
+ {
+ eTVA = SDRTEXTVERTADJUST_BLOCK;
+ eTHA = SDRTEXTHORZADJUST_CENTER;
+
+ // read text anchor
+ auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
+
+ switch( eTextAnchor )
+ {
+ case mso_anchorTop:
+ case mso_anchorTopCentered:
+ eTHA = SDRTEXTHORZADJUST_RIGHT;
+ break;
+
+ case mso_anchorMiddle :
+ case mso_anchorMiddleCentered:
+ eTHA = SDRTEXTHORZADJUST_CENTER;
+ break;
+
+ case mso_anchorBottom:
+ case mso_anchorBottomCentered:
+ eTHA = SDRTEXTHORZADJUST_LEFT;
+ break;
+
+ default:
+ break;
+ }
+ // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction
+ switch ( eTextAnchor )
+ {
+ case mso_anchorTopCentered :
+ case mso_anchorMiddleCentered :
+ case mso_anchorBottomCentered :
+ {
+ // check if it is sensible to use the centered alignment
+ sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT;
+ if ( ( nTextFlags & nMask ) != nMask ) // if the textobject has left or also right aligned paragraphs
+ eTVA = SDRTEXTVERTADJUST_CENTER; // the text has to be displayed using the full width;
+ }
+ break;
+
+ default :
+ {
+ if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT )
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ else if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT )
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ }
+ break;
+ }
+ }
+ else
+ {
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+ eTHA = SDRTEXTHORZADJUST_BLOCK;
+
+ // read text anchor
+ auto eTextAnchor = GetPropertyValue(DFF_Prop_anchorText, mso_anchorTop);
+
+ switch( eTextAnchor )
+ {
+ case mso_anchorTop:
+ case mso_anchorTopCentered:
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ break;
+
+ case mso_anchorMiddle :
+ case mso_anchorMiddleCentered:
+ eTVA = SDRTEXTVERTADJUST_CENTER;
+ break;
+
+ case mso_anchorBottom:
+ case mso_anchorBottomCentered:
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ break;
+
+ default:
+ break;
+ }
+
+ // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction
+ switch ( eTextAnchor )
+ {
+ case mso_anchorTopCentered :
+ case mso_anchorMiddleCentered :
+ case mso_anchorBottomCentered :
+ {
+ // check if it is sensible to use the centered alignment
+ sal_uInt32 nMask = PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT | PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT;
+ if ( ( nTextFlags & nMask ) != nMask ) // if the textobject has left or also right aligned paragraphs
+ eTHA = SDRTEXTHORZADJUST_CENTER; // the text has to be displayed using the full width;
+ }
+ break;
+
+ default :
+ {
+ if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_LEFT )
+ eTHA = SDRTEXTHORZADJUST_LEFT;
+ else if ( nTextFlags == PPT_TEXTOBJ_FLAGS_PARA_ALIGNMENT_USED_RIGHT )
+ eTHA = SDRTEXTHORZADJUST_RIGHT;
+ }
+ break;
+ }
+ }
+ rSet.Put( SdrTextVertAdjustItem( eTVA ) );
+ rSet.Put( SdrTextHorzAdjustItem( eTHA ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/svxmsbas2.cxx b/filter/source/msfilter/svxmsbas2.cxx
new file mode 100644
index 000000000..8a4ce43f1
--- /dev/null
+++ b/filter/source/msfilter/svxmsbas2.cxx
@@ -0,0 +1,80 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <config_features.h>
+
+#include <basic/basmgr.hxx>
+#include <sfx2/objsh.hxx>
+#include <sot/storage.hxx>
+#include <svx/svxerr.hxx>
+#include <filter/msfilter/svxmsbas.hxx>
+
+using namespace com::sun::star;
+
+ErrCode SvxImportMSVBasic::SaveOrDelMSVBAStorage( bool bSaveInto,
+ const OUString& rStorageName )
+{
+ ErrCode nRet = ERRCODE_NONE;
+ uno::Reference < embed::XStorage > xSrcRoot( rDocSh.GetStorage() );
+ OUString aDstStgName( GetMSBasicStorageName() );
+ tools::SvRef<SotStorage> xVBAStg( SotStorage::OpenOLEStorage( xSrcRoot, aDstStgName,
+ StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL ) );
+ if( xVBAStg.is() && !xVBAStg->GetError() )
+ {
+ xVBAStg = nullptr;
+ if( bSaveInto )
+ {
+#if HAVE_FEATURE_SCRIPTING
+ BasicManager *pBasicMan = rDocSh.GetBasicManager();
+ if( pBasicMan && pBasicMan->IsBasicModified() )
+ nRet = ERRCODE_SVX_MODIFIED_VBASIC_STORAGE;
+#endif
+ tools::SvRef<SotStorage> xSrc = SotStorage::OpenOLEStorage( xSrcRoot, aDstStgName, StreamMode::STD_READ );
+ tools::SvRef<SotStorage> xDst = xRoot->OpenSotStorage( rStorageName, StreamMode::READWRITE | StreamMode::TRUNC );
+ xSrc->CopyTo( xDst.get() );
+ xDst->Commit();
+ ErrCode nError = xDst->GetError();
+ if ( nError == ERRCODE_NONE )
+ nError = xSrc->GetError();
+ if ( nError != ERRCODE_NONE )
+ xRoot->SetError( nError );
+ }
+ }
+
+ return nRet;
+}
+
+// check if the MS-VBA-Storage exists in the RootStorage of the DocShell.
+// If it exists, then return the WarningId for losing the information.
+ErrCode SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( SfxObjectShell &rDocSh)
+{
+ uno::Reference < embed::XStorage > xSrcRoot( rDocSh.GetStorage() );
+ tools::SvRef<SotStorage> xVBAStg( SotStorage::OpenOLEStorage( xSrcRoot, GetMSBasicStorageName(),
+ StreamMode::READ | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL ));
+ return ( xVBAStg.is() && !xVBAStg->GetError() )
+ ? ERRCODE_SVX_VBASIC_STORAGE_EXIST
+ : ERRCODE_NONE;
+}
+
+OUString SvxImportMSVBasic::GetMSBasicStorageName()
+{
+ return "_MS_VBA_Macros";
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/util.cxx b/filter/source/msfilter/util.cxx
new file mode 100644
index 000000000..aea2f816b
--- /dev/null
+++ b/filter/source/msfilter/util.cxx
@@ -0,0 +1,1340 @@
+/* -*- 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 <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/lang/Locale.hpp>
+#include <rtl/ustring.hxx>
+#include <comphelper/string.hxx>
+#include <unotools/fontcvt.hxx>
+#include <unotools/fontdefs.hxx>
+#include <utility>
+#include <vcl/BitmapPalette.hxx>
+#include <filter/msfilter/escherex.hxx>
+#include <filter/msfilter/util.hxx>
+#include <o3tl/string_view.hxx>
+#include <memory>
+#include <unordered_map>
+
+namespace msfilter::util {
+
+rtl_TextEncoding getBestTextEncodingFromLocale(const css::lang::Locale &rLocale)
+{
+ // Obviously not comprehensive, feel free to expand these, they're for ultimate fallbacks
+ // in last-ditch broken-file-format cases to guess the right 8bit encodings
+ const OUString &rLanguage = rLocale.Language;
+ if (rLanguage == "cs" || rLanguage == "hu" || rLanguage == "pl")
+ return RTL_TEXTENCODING_MS_1250;
+ if (rLanguage == "ru" || rLanguage == "uk")
+ return RTL_TEXTENCODING_MS_1251;
+ if (rLanguage == "el")
+ return RTL_TEXTENCODING_MS_1253;
+ if (rLanguage == "tr")
+ return RTL_TEXTENCODING_MS_1254;
+ if (rLanguage == "lt")
+ return RTL_TEXTENCODING_MS_1257;
+ if (rLanguage == "th")
+ return RTL_TEXTENCODING_MS_874;
+ if (rLanguage == "vi")
+ return RTL_TEXTENCODING_MS_1258;
+ return RTL_TEXTENCODING_MS_1252;
+}
+
+::Color BGRToRGB(sal_uInt32 nColor)
+{
+ sal_uInt8
+ r(static_cast<sal_uInt8>(nColor&0xFF)),
+ g(static_cast<sal_uInt8>((nColor>>8)&0xFF)),
+ b(static_cast<sal_uInt8>((nColor>>16)&0xFF)),
+ t(static_cast<sal_uInt8>((nColor>>24)&0xFF));
+ return ::Color(ColorTransparency, t, r, g, b);
+}
+
+DateTime DTTM2DateTime( tools::Long lDTTM )
+{
+ /*
+ mint short :6 0000003F minutes (0-59)
+ hr short :5 000007C0 hours (0-23)
+ dom short :5 0000F800 days of month (1-31)
+ mon short :4 000F0000 months (1-12)
+ yr short :9 1FF00000 years (1900-2411)-1900
+ wdy short :3 E0000000 weekday(Sunday=0
+ Monday=1
+ ( wdy can be ignored ) Tuesday=2
+ Wednesday=3
+ Thursday=4
+ Friday=5
+ Saturday=6)
+ */
+ DateTime aDateTime(Date( 0 ), ::tools::Time( 0 ));
+ if( lDTTM )
+ {
+ sal_uInt16 lMin = static_cast<sal_uInt16>(lDTTM & 0x0000003F);
+ lDTTM >>= 6;
+ sal_uInt16 lHour= static_cast<sal_uInt16>(lDTTM & 0x0000001F);
+ lDTTM >>= 5;
+ sal_uInt16 lDay = static_cast<sal_uInt16>(lDTTM & 0x0000001F);
+ lDTTM >>= 5;
+ sal_uInt16 lMon = static_cast<sal_uInt16>(lDTTM & 0x0000000F);
+ lDTTM >>= 4;
+ sal_uInt16 lYear= static_cast<sal_uInt16>(lDTTM & 0x000001FF) + 1900;
+ aDateTime = DateTime(Date(lDay, lMon, lYear), tools::Time(lHour, lMin));
+ }
+ return aDateTime;
+}
+
+sal_Unicode bestFitOpenSymbolToMSFont(sal_Unicode cChar,
+ rtl_TextEncoding& rChrSet, OUString& rFontName)
+{
+ std::unique_ptr<StarSymbolToMSMultiFont> pConvert(CreateStarSymbolToMSMultiFont());
+ OUString sFont = pConvert->ConvertChar(cChar);
+ pConvert.reset();
+ if (!sFont.isEmpty())
+ {
+ cChar = static_cast< sal_Unicode >(cChar | 0xF000);
+ rFontName = sFont;
+ rChrSet = RTL_TEXTENCODING_SYMBOL;
+ }
+ else if (cChar < 0xE000 || cChar > 0xF8FF)
+ {
+ /*
+ Ok we can't fit into a known windows unicode font, but
+ we are not in the private area, so we are a
+ standardized symbol, so turn off the symbol bit and
+ let words own font substitution kick in
+ */
+ rChrSet = RTL_TEXTENCODING_UNICODE;
+ sal_Int32 nIndex = 0;
+ rFontName = ::GetNextFontToken(rFontName, nIndex);
+ }
+ else
+ {
+ /*
+ Well we don't have an available substitution, and we're
+ in our private area, so give up and show a standard
+ bullet symbol
+ */
+ rFontName = "Wingdings";
+ cChar = u'\x6C';
+ }
+ return cChar;
+}
+
+
+OString ConvertColor( const Color &rColor )
+{
+ static constexpr OStringLiteral AUTO( "auto" );
+
+ if ( rColor == COL_AUTO )
+ return AUTO;
+
+ const char pHexDigits[] = "0123456789ABCDEF";
+ char pBuffer[] = "000000";
+
+ pBuffer[0] = pHexDigits[ ( rColor.GetRed() >> 4 ) & 0x0F ];
+ pBuffer[1] = pHexDigits[ rColor.GetRed() & 0x0F ];
+ pBuffer[2] = pHexDigits[ ( rColor.GetGreen() >> 4 ) & 0x0F ];
+ pBuffer[3] = pHexDigits[ rColor.GetGreen() & 0x0F ];
+ pBuffer[4] = pHexDigits[ ( rColor.GetBlue() >> 4 ) & 0x0F ];
+ pBuffer[5] = pHexDigits[ rColor.GetBlue() & 0x0F ];
+
+ return OString( pBuffer );
+}
+
+OUString ConvertColorOU( const Color &rColor )
+{
+ static constexpr OUStringLiteral AUTO( u"auto" );
+
+ if ( rColor == COL_AUTO )
+ return AUTO;
+
+ const char pHexDigits[] = "0123456789ABCDEF";
+ sal_Unicode pBuffer[] = u"000000";
+
+ pBuffer[0] = pHexDigits[ ( rColor.GetRed() >> 4 ) & 0x0F ];
+ pBuffer[1] = pHexDigits[ rColor.GetRed() & 0x0F ];
+ pBuffer[2] = pHexDigits[ ( rColor.GetGreen() >> 4 ) & 0x0F ];
+ pBuffer[3] = pHexDigits[ rColor.GetGreen() & 0x0F ];
+ pBuffer[4] = pHexDigits[ ( rColor.GetBlue() >> 4 ) & 0x0F ];
+ pBuffer[5] = pHexDigits[ rColor.GetBlue() & 0x0F ];
+
+ return OUString( pBuffer );
+}
+
+#define IN2MM100( v ) static_cast< sal_Int32 >( (v) * 2540.0 + 0.5 )
+#define MM2MM100( v ) static_cast< sal_Int32 >( (v) * 100.0 + 0.5 )
+
+// see XclPaperSize pPaperSizeTable in calc and aDinTab in i18nutil
+const ApiPaperSize spPaperSizeTable[] =
+{
+ { 0, 0 }, // 0 - (undefined)
+ { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 1 - Letter paper
+ { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 2 - Letter small paper
+ { IN2MM100( 11 ), IN2MM100( 17 ) }, // 3 - Tabloid paper
+ { IN2MM100( 17 ), IN2MM100( 11 ) }, // 4 - Ledger paper
+ { IN2MM100( 8.5 ), IN2MM100( 14 ) }, // 5 - Legal paper
+ { IN2MM100( 5.5 ), IN2MM100( 8.5 ) }, // 6 - Statement paper
+ { IN2MM100( 7.25 ), IN2MM100( 10.5 ) }, // 7 - Executive paper
+ { MM2MM100( 297 ), MM2MM100( 420 ) }, // 8 - A3 paper
+ { MM2MM100( 210 ), MM2MM100( 297 ) }, // 9 - A4 paper
+ { MM2MM100( 210 ), MM2MM100( 297 ) }, // 10 - A4 small paper
+ { MM2MM100( 148 ), MM2MM100( 210 ) }, // 11 - A5 paper
+ /* for JIS vs ISO B confusion see:
+ https://docs.microsoft.com/en-us/windows/win32/intl/paper-sizes
+ http://wiki.openoffice.org/wiki/DefaultPaperSize comments
+ http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf */
+ { MM2MM100( 257 ), MM2MM100( 364 ) }, // 12 - B4 (JIS) paper
+ { MM2MM100( 182 ), MM2MM100( 257 ) }, // 13 - B5 (JIS) paper
+ { IN2MM100( 8.5 ), IN2MM100( 13 ) }, // 14 - Folio paper
+ { MM2MM100( 215 ), MM2MM100( 275 ) }, // 15 - Quarto paper
+ { IN2MM100( 10 ), IN2MM100( 14 ) }, // 16 - Standard paper
+ { IN2MM100( 11 ), IN2MM100( 17 ) }, // 17 - Standard paper
+ { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 18 - Note paper
+ { IN2MM100( 3.875 ), IN2MM100( 8.875 ) }, // 19 - #9 envelope
+ { IN2MM100( 4.125 ), IN2MM100( 9.5 ) }, // 20 - #10 envelope
+ { IN2MM100( 4.5 ), IN2MM100( 10.375 ) }, // 21 - #11 envelope
+ { IN2MM100( 4.75 ), IN2MM100( 11 ) }, // 22 - #12 envelope
+ { IN2MM100( 5 ), IN2MM100( 11.5 ) }, // 23 - #14 envelope
+ { IN2MM100( 17 ), IN2MM100( 22 ) }, // 24 - C paper
+ { IN2MM100( 22 ), IN2MM100( 34 ) }, // 25 - D paper
+ { IN2MM100( 34 ), IN2MM100( 44 ) }, // 26 - E paper
+ { MM2MM100( 110 ), MM2MM100( 220 ) }, // 27 - DL envelope
+ { MM2MM100( 162 ), MM2MM100( 229 ) }, // 28 - C5 envelope
+ { MM2MM100( 324 ), MM2MM100( 458 ) }, // 29 - C3 envelope
+ { MM2MM100( 229 ), MM2MM100( 324 ) }, // 30 - C4 envelope
+ { MM2MM100( 114 ), MM2MM100( 162 ) }, // 31 - C6 envelope
+ { MM2MM100( 114 ), MM2MM100( 229 ) }, // 32 - C65 envelope
+ { MM2MM100( 250 ), MM2MM100( 353 ) }, // 33 - B4 envelope
+ { MM2MM100( 176 ), MM2MM100( 250 ) }, // 34 - B5 envelope
+ { MM2MM100( 176 ), MM2MM100( 125 ) }, // 35 - B6 envelope
+ { MM2MM100( 110 ), MM2MM100( 230 ) }, // 36 - Italy envelope
+ { IN2MM100( 3.875 ), IN2MM100( 7.5 ) }, // 37 - Monarch envelope
+ { IN2MM100( 3.625 ), IN2MM100( 6.5 ) }, // 38 - 6 3/4 envelope
+ { IN2MM100( 14.875 ), IN2MM100( 11 ) }, // 39 - US standard fanfold
+ { IN2MM100( 8.5 ), IN2MM100( 12 ) }, // 40 - German standard fanfold
+ { IN2MM100( 8.5 ), IN2MM100( 13 ) }, // 41 - German legal fanfold
+ { MM2MM100( 250 ), MM2MM100( 353 ) }, // 42 - ISO B4
+ { MM2MM100( 200 ), MM2MM100( 148 ) }, // 43 - Japanese double postcard
+ { IN2MM100( 9 ), IN2MM100( 11 ) }, // 44 - Standard paper
+ { IN2MM100( 10 ), IN2MM100( 11 ) }, // 45 - Standard paper
+ { IN2MM100( 15 ), IN2MM100( 11 ) }, // 46 - Standard paper
+ { MM2MM100( 220 ), MM2MM100( 220 ) }, // 47 - Invite envelope
+ { 0, 0 }, // 48 - (undefined)
+ { 0, 0 }, // 49 - (undefined)
+ /* See: https://docs.microsoft.com/en-us/windows/win32/intl/paper-sizes */
+ { IN2MM100( 9.5 ), IN2MM100( 12 ) }, // 50 - Letter extra paper
+ { IN2MM100( 9.5 ), IN2MM100( 15 ) }, // 51 - Legal extra paper
+ { IN2MM100( 11.69 ), IN2MM100( 18 ) }, // 52 - Tabloid extra paper
+ { MM2MM100( 235 ), MM2MM100( 322 ) }, // 53 - A4 extra paper
+ { IN2MM100( 8.5 ), IN2MM100( 11 ) }, // 54 - Letter transverse paper
+ { MM2MM100( 210 ), MM2MM100( 297 ) }, // 55 - A4 transverse paper
+ { IN2MM100( 9.5 ), IN2MM100( 12 ) }, // 56 - Letter extra transverse paper
+ { MM2MM100( 227 ), MM2MM100( 356 ) }, // 57 - SuperA/SuperA/A4 paper
+ { MM2MM100( 305 ), MM2MM100( 487 ) }, // 58 - SuperB/SuperB/A3 paper
+ { IN2MM100( 8.5 ), IN2MM100( 12.69 ) }, // 59 - Letter plus paper
+ { MM2MM100( 210 ), MM2MM100( 330 ) }, // 60 - A4 plus paper
+ { MM2MM100( 148 ), MM2MM100( 210 ) }, // 61 - A5 transverse paper
+ { MM2MM100( 182 ), MM2MM100( 257 ) }, // 62 - JIS B5 transverse paper
+ { MM2MM100( 322 ), MM2MM100( 445 ) }, // 63 - A3 extra paper
+ { MM2MM100( 174 ), MM2MM100( 235 ) }, // 64 - A5 extra paper
+ { MM2MM100( 201 ), MM2MM100( 276 ) }, // 65 - ISO B5 extra paper
+ { MM2MM100( 420 ), MM2MM100( 594 ) }, // 66 - A2 paper
+ { MM2MM100( 297 ), MM2MM100( 420 ) }, // 67 - A3 transverse paper
+ { MM2MM100( 322 ), MM2MM100( 445 ) }, // 68 - A3 extra transverse paper
+ { MM2MM100( 200 ), MM2MM100( 148 ) }, // 69 - Japanese double postcard
+ { MM2MM100( 105 ), MM2MM100( 148 ), }, // 70 - A6 paper
+ { 0, 0 }, // 71 - Japanese Envelope Kaku #2
+ { 0, 0 }, // 72 - Japanese Envelope Kaku #3
+ { 0, 0 }, // 73 - Japanese Envelope Chou #3
+ { 0, 0 }, // 74 - Japanese Envelope Chou #4
+ { IN2MM100( 11 ), IN2MM100( 8.5 ) }, // 75 - Letter Rotated
+ { MM2MM100( 420 ), MM2MM100( 297 ) }, // 76 - A3 Rotated
+ { MM2MM100( 297 ), MM2MM100( 210 ) }, // 77 - A4 Rotated
+ { MM2MM100( 210 ), MM2MM100( 148 ) }, // 78 - A5 Rotated
+ { MM2MM100( 364 ), MM2MM100( 257 ) }, // 79 - B4 (JIS) Rotated
+ { MM2MM100( 257 ), MM2MM100( 182 ) }, // 80 - B5 (JIS) Rotated
+ { MM2MM100( 148 ), MM2MM100( 100 ) }, // 81 - Japanese Postcard Rotated
+ { MM2MM100( 148 ), MM2MM100( 200 ) }, // 82 - Double Japanese Postcard Rotated
+ { MM2MM100( 148 ), MM2MM100( 105 ) }, // 83 - A6 Rotated
+ { 0, 0 }, // 84 - Japanese Envelope Kaku #2 Rotated
+ { 0, 0 }, // 85 - Japanese Envelope Kaku #3 Rotated
+ { 0, 0 }, // 86 - Japanese Envelope Chou #3 Rotated
+ { 0, 0 }, // 87 - Japanese Envelope Chou #4 Rotated
+ { MM2MM100( 128 ), MM2MM100( 182 ) }, // 88 - B6 (JIS)
+ { MM2MM100( 182 ), MM2MM100( 128 ) }, // 89 - B6 (JIS) Rotated
+ { IN2MM100( 12 ), IN2MM100( 11 ) } // 90 - 12x11
+};
+
+sal_Int32 PaperSizeConv::getMSPaperSizeIndex( const css::awt::Size& rSize )
+{
+ // Need to find the best match for current size
+ sal_Int32 nDeltaWidth = 0;
+ sal_Int32 nDeltaHeight = 0;
+
+ sal_Int32 nPaperSizeIndex = 0; // Undefined
+ const ApiPaperSize* pItem = spPaperSizeTable;
+ const ApiPaperSize* pEnd = spPaperSizeTable + SAL_N_ELEMENTS( spPaperSizeTable );
+ for ( ; pItem != pEnd; ++pItem )
+ {
+ sal_Int32 nCurDeltaHeight = std::abs( pItem->mnHeight - rSize.Height );
+ sal_Int32 nCurDeltaWidth = std::abs( pItem->mnWidth - rSize.Width );
+ if ( pItem == spPaperSizeTable ) // initialize delta with first item
+ {
+ nDeltaWidth = nCurDeltaWidth;
+ nDeltaHeight = nCurDeltaHeight;
+ }
+ else
+ {
+ if ( nCurDeltaWidth < nDeltaWidth && nCurDeltaHeight < nDeltaHeight )
+ {
+ nDeltaWidth = nCurDeltaWidth;
+ nDeltaHeight = nCurDeltaHeight;
+ nPaperSizeIndex = (pItem - spPaperSizeTable);
+ }
+ }
+ }
+ sal_Int32 nTol = 10; // hmm not sure is this the best way
+ if ( nDeltaWidth <= nTol && nDeltaHeight <= nTol )
+ return nPaperSizeIndex;
+ return 0;
+}
+
+const ApiPaperSize& PaperSizeConv::getApiSizeForMSPaperSizeIndex( sal_Int32 nMSOPaperIndex )
+{
+ if ( nMSOPaperIndex < 0 || nMSOPaperIndex > sal_Int32(SAL_N_ELEMENTS( spPaperSizeTable )) - 1 )
+ return spPaperSizeTable[ 0 ];
+ return spPaperSizeTable[ nMSOPaperIndex ];
+}
+
+std::u16string_view findQuotedText( std::u16string_view rCommand,
+ const char* cStartQuote, const sal_Unicode uEndQuote )
+{
+ std::u16string_view sRet;
+ OUString sStartQuote( OUString::createFromAscii(cStartQuote) );
+ size_t nStartIndex = rCommand.find( sStartQuote );
+ if( nStartIndex != std::u16string_view::npos )
+ {
+ sal_Int32 nStartLength = sStartQuote.getLength();
+ size_t nEndIndex = rCommand.find( uEndQuote, nStartIndex + nStartLength);
+ if( nEndIndex != std::u16string_view::npos && nEndIndex > nStartIndex )
+ {
+ sRet = rCommand.substr( nStartIndex + nStartLength, nEndIndex - nStartIndex - nStartLength);
+ }
+ }
+ return sRet;
+
+}
+
+WW8ReadFieldParams::WW8ReadFieldParams( OUString _aData )
+ : aData(std::move( _aData ))
+ , nFnd( 0 )
+ , nNext( 0 )
+ , nSavPtr( 0 )
+{
+
+ /*
+ First look for an opening bracket or a space or a question mark or a backslash, so that the field (i.e. INCLUDEPICTURE or EINFUEGENGRAFIK or...) gets read over
+ */
+ const sal_Int32 nLen = aData.getLength();
+
+ while ( nNext<nLen && aData[nNext]==' ' )
+ ++nNext;
+
+ while ( nNext<nLen )
+ {
+ const sal_Unicode c = aData[nNext];
+ if ( c==' ' || c=='"' || c=='\\' || c==132 || c==0x201c )
+ break;
+ ++nNext;
+ }
+
+ nFnd = nNext;
+ nSavPtr = nNext;
+}
+
+OUString WW8ReadFieldParams::GetResult() const
+{
+ if (nFnd<0 && nSavPtr>nFnd)
+ return OUString();
+ else
+ {
+ return nSavPtr < nFnd ? aData.copy(nFnd) : aData.copy(nFnd, nSavPtr-nFnd);
+ }
+}
+
+
+bool WW8ReadFieldParams::GoToTokenParam()
+{
+ const sal_Int32 nOld = nNext;
+ if( -2 == SkipToNextToken() )
+ return GetTokenSttPtr()>=0;
+ nNext = nOld;
+ return false;
+}
+
+// ret: -2: NOT a '\' parameter but normal text
+sal_Int32 WW8ReadFieldParams::SkipToNextToken()
+{
+ if ( nNext<0 || nNext>=aData.getLength() )
+ return -1;
+
+ nFnd = FindNextStringPiece(nNext);
+ if ( nFnd<0 )
+ return -1;
+
+ nSavPtr = nNext;
+
+ if (nFnd+1<aData.getLength() && aData[nFnd+1]!='\\' && aData[nFnd]=='\\')
+ {
+ const sal_Int32 nRet = aData[++nFnd];
+ nNext = ++nFnd; // and set after
+ return nRet;
+ }
+
+ if ( nSavPtr>0 && (aData[nSavPtr-1]=='"' || aData[nSavPtr-1]==0x201d ) )
+ {
+ --nSavPtr;
+ }
+ return -2;
+}
+
+// FindNextPara searches the next backslash parameter or the next string
+// until the next blank or "\" or closing quotation mark
+// or the end of the string of pStr.
+//
+// Output ppNext (if ppNext != 0) search begin of next parameter resp. 0
+//
+// Return value: 0 if end of string reached,
+// otherwise beginning of the parameter resp. string
+//
+sal_Int32 WW8ReadFieldParams::FindNextStringPiece(const sal_Int32 nStart)
+{
+ const sal_Int32 nLen = aData.getLength();
+ sal_Int32 n = nStart<0 ? nFnd : nStart; // start
+ sal_Int32 n2; // end
+
+ nNext = -1; // if not found -> Default
+
+ while ( n<nLen && aData[n]==' ' )
+ ++n;
+
+ if ( n==nLen )
+ return -1;
+
+ if ( aData[n]==0x13 )
+ {
+ // Skip the nested field code since it's not supported
+ while ( n<nLen && aData[n]!=0x14 )
+ ++n;
+ if ( n==nLen )
+ return -1;
+ }
+
+ // quotation marks before paragraph?
+ if ( aData[n]=='"' || aData[n]==0x201c || aData[n]==132 || aData[n]==0x14 )
+ {
+ n++; // read over quotation marks
+ n2 = n; // search for the end from here on
+ while( (nLen > n2)
+ && (aData[n2] != '"')
+ && (aData[n2] != 0x201d)
+ && (aData[n2] != 147)
+ && (aData[n2] != 0x15) )
+ n2++; // search for the end of the paragraph
+ }
+ else // no quotation mark
+ {
+ n2 = n; // search for the end from here on
+ while ( n2<nLen && aData[n2]!=' ' ) // search for the end of the paragraph
+ {
+ if ( aData[n2]=='\\' )
+ {
+ if ( n2+1<nLen && aData[n2+1]=='\\' )
+ n2 += 2; // double backslash -> OK
+ else
+ {
+ if( n2 > n )
+ n2--;
+ break; // single backslash -> end
+ }
+ }
+ else
+ n2++; // no backslash -> OK
+ }
+ }
+ if( nLen > n2 )
+ {
+ if (aData[n2]!=' ') ++n2;
+ nNext = n2;
+ }
+ return n;
+}
+
+
+// read parameters "1-3" or 1-3 with both values between 1 and nMax
+bool WW8ReadFieldParams::GetTokenSttFromTo(sal_Int32* pFrom, sal_Int32* pTo, sal_Int32 nMax)
+{
+ sal_Int32 nStart = 0;
+ sal_Int32 nEnd = 0;
+ if ( GoToTokenParam() )
+ {
+
+ const OUString sParams( GetResult() );
+
+ sal_Int32 nIndex = 0;
+ const std::u16string_view sStart = o3tl::getToken(sParams, 0, '-', nIndex);
+ if (nIndex>=0)
+ {
+ nStart = o3tl::toInt32(sStart);
+ nEnd = o3tl::toInt32(sParams.subView(nIndex));
+ }
+ }
+ if( pFrom ) *pFrom = nStart;
+ if( pTo ) *pTo = nEnd;
+
+ return nStart && nEnd && (nMax >= nStart) && (nMax >= nEnd);
+}
+
+static EquationResult Read_SubF_Combined(WW8ReadFieldParams& rReadParam)
+{
+ EquationResult aResult;
+
+ OUString sCombinedCharacters;
+ WW8ReadFieldParams aOriFldParam = rReadParam;
+ const sal_Int32 cGetChar = rReadParam.SkipToNextToken();
+ switch( cGetChar )
+ {
+ case 'a':
+ case 'A':
+ if ( !rReadParam.GetResult().startsWithIgnoreAsciiCase("d") )
+ {
+ break;
+ }
+ (void)rReadParam.SkipToNextToken();
+ [[fallthrough]];
+ case -2:
+ {
+ if ( rReadParam.GetResult().startsWithIgnoreAsciiCase("(") )
+ {
+ for (int i=0;i<2;i++)
+ {
+ if ('s' == rReadParam.SkipToNextToken())
+ {
+ const sal_Int32 cChar = rReadParam.SkipToNextToken();
+ if (-2 != rReadParam.SkipToNextToken())
+ break;
+ const OUString sF = rReadParam.GetResult();
+ if ((('u' == cChar) && sF.startsWithIgnoreAsciiCase("p"))
+ || (('d' == cChar) && sF.startsWithIgnoreAsciiCase("o")))
+ {
+ if (-2 == rReadParam.SkipToNextToken())
+ {
+ OUString sPart = rReadParam.GetResult();
+ sal_Int32 nBegin = sPart.indexOf('(');
+
+ // Word disallows brackets in this field, which
+ // aids figuring out the case of an end of )) vs )
+ sal_Int32 nEnd = sPart.indexOf(')');
+
+ if (nBegin != -1 && nEnd != -1)
+ {
+ sCombinedCharacters +=
+ sPart.subView(nBegin+1,nEnd-nBegin-1);
+ }
+ }
+ }
+ }
+ }
+ if (!sCombinedCharacters.isEmpty())
+ {
+ aResult.sType = "CombinedCharacters";
+ aResult.sResult = sCombinedCharacters;
+ }
+ else
+ {
+ const OUString sPart = aOriFldParam.GetResult();
+ sal_Int32 nBegin = sPart.indexOf('(');
+ sal_Int32 nEnd = sPart.indexOf(',');
+ if ( nEnd == -1 )
+ {
+ nEnd = sPart.indexOf(')');
+ }
+ if ( nBegin != -1 && nEnd != -1 )
+ {
+ // skip certain leading characters
+ for (int i = nBegin;i < nEnd-1;i++)
+ {
+ const sal_Unicode cC = sPart[nBegin+1];
+ if ( cC < 32 )
+ {
+ nBegin++;
+ }
+ else
+ break;
+ }
+ sCombinedCharacters = sPart.copy( nBegin+1, nEnd-nBegin-1 );
+ if ( !sCombinedCharacters.isEmpty() )
+ {
+ aResult.sType = "Input";
+ aResult.sResult = sCombinedCharacters;
+ }
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return aResult;
+}
+
+EquationResult ParseCombinedChars(const OUString& rStr)
+{
+ EquationResult aResult;
+ WW8ReadFieldParams aReadParam( rStr );
+ const sal_Int32 cChar = aReadParam.SkipToNextToken();
+ if ('o' == cChar || 'O' == cChar)
+ aResult = Read_SubF_Combined(aReadParam);
+ return aResult;
+}
+
+OString GetOOXMLPresetGeometry( std::u16string_view rShapeType )
+{
+ typedef std::unordered_map<std::u16string_view, OString> CustomShapeTypeTranslationHashMap;
+ static const CustomShapeTypeTranslationHashMap aCustomShapeTypeTranslationHashMap{
+ // { "non-primitive", mso_sptMin },
+ { u"frame", "frame" },
+ { u"rectangle", "rect" },
+ { u"round-rectangle", "roundRect" },
+ { u"ellipse", "ellipse" },
+ { u"diamond", "diamond" },
+ { u"isosceles-triangle", "triangle" },
+ { u"right-triangle", "rtTriangle" },
+ { u"parallelogram", "parallelogram" },
+ { u"trapezoid", "trapezoid" },
+ { u"hexagon", "hexagon" },
+ { u"octagon", "octagon" },
+ { u"cross", "plus" },
+ { u"star5", "star5" },
+ { u"right-arrow", "rightArrow" },
+ // { u"mso-spt14", mso_sptThickArrow },
+ { u"pentagon-right", "homePlate" },
+ { u"cube", "cube" },
+ // { u"mso-spt17", mso_sptBalloon },
+ // { u"mso-spt18", mso_sptSeal },
+ { u"mso-spt19", "arc" },
+ { u"mso-spt20", "line" },
+ { u"mso-spt21", "plaque" },
+ { u"can", "can" },
+ { u"ring", "donut" },
+ { u"mso-spt24", "textPlain" },
+ { u"mso-spt25", "textStop" },
+ { u"mso-spt26", "textTriangle" },
+ { u"mso-spt27", "textCanDown" },
+ { u"mso-spt28", "textWave1" },
+ { u"mso-spt29", "textArchUpPour" },
+ { u"mso-spt30", "textCanDown" },
+ { u"mso-spt31", "textArchUp" },
+ { u"mso-spt32", "straightConnector1" },
+ { u"mso-spt33", "bentConnector2" },
+ { u"mso-spt34", "bentConnector3" },
+ { u"mso-spt35", "bentConnector4" },
+ { u"mso-spt36", "bentConnector5" },
+ { u"mso-spt37", "curvedConnector2" },
+ { u"mso-spt38", "curvedConnector3" },
+ { u"mso-spt39", "curvedConnector4" },
+ { u"mso-spt40", "curvedConnector5" },
+ { u"mso-spt41", "callout1" },
+ { u"mso-spt42", "callout2" },
+ { u"mso-spt43", "callout3" },
+ { u"mso-spt44", "accentCallout1" },
+ { u"mso-spt45", "accentCallout2" },
+ { u"mso-spt46", "accentCallout3" },
+ { u"line-callout-1", "borderCallout1" },
+ { u"line-callout-2", "borderCallout2" },
+ { u"line-callout-3", "borderCallout3" },
+ { u"mso-spt49", "borderCallout3" },
+ { u"mso-spt50", "accentBorderCallout1" },
+ { u"mso-spt51", "accentBorderCallout2" },
+ { u"mso-spt52", "accentBorderCallout3" },
+ { u"mso-spt53", "ribbon" },
+ { u"mso-spt54", "ribbon2" },
+ { u"chevron", "chevron" },
+ { u"pentagon", "pentagon" },
+ { u"forbidden", "noSmoking" },
+ { u"star8", "star8" },
+ { u"mso-spt59", "star16" },
+ { u"mso-spt60", "star32" },
+ { u"rectangular-callout", "wedgeRectCallout" },
+ { u"round-rectangular-callout", "wedgeRoundRectCallout" },
+ { u"round-callout", "wedgeEllipseCallout" },
+ { u"mso-spt64", "wave" },
+ { u"paper", "foldedCorner" },
+ { u"left-arrow", "leftArrow" },
+ { u"down-arrow", "downArrow" },
+ { u"up-arrow", "upArrow" },
+ { u"left-right-arrow", "leftRightArrow" },
+ { u"up-down-arrow", "upDownArrow" },
+ { u"mso-spt71", "irregularSeal1" },
+ { u"bang", "irregularSeal2" },
+ { u"lightning", "lightningBolt" },
+ { u"heart", "heart" },
+ { u"quad-arrow", "quadArrow" },
+ { u"left-arrow-callout", "leftArrowCallout" },
+ { u"right-arrow-callout", "rightArrowCallout" },
+ { u"up-arrow-callout", "upArrowCallout" },
+ { u"down-arrow-callout", "downArrowCallout" },
+ { u"left-right-arrow-callout", "leftRightArrowCallout" },
+ { u"up-down-arrow-callout", "upDownArrowCallout" },
+ { u"quad-arrow-callout", "quadArrowCallout" },
+ { u"quad-bevel", "bevel" },
+ { u"left-bracket", "leftBracket" },
+ { u"right-bracket", "rightBracket" },
+ { u"left-brace", "leftBrace" },
+ { u"right-brace", "rightBrace" },
+ { u"mso-spt89", "leftUpArrow" },
+ { u"mso-spt90", "bentUpArrow" },
+ { u"mso-spt91", "bentArrow" },
+ { u"star24", "star24" },
+ { u"striped-right-arrow", "stripedRightArrow" },
+ { u"notched-right-arrow", "notchedRightArrow" },
+ { u"block-arc", "blockArc" },
+ { u"smiley", "smileyFace" },
+ { u"vertical-scroll", "verticalScroll" },
+ { u"horizontal-scroll", "horizontalScroll" },
+ { u"circular-arrow", "circularArrow" },
+ { u"mso-spt100", "pie" }, // looks like MSO_SPT is wrong here
+ { u"mso-spt101", "uturnArrow" },
+ { u"mso-spt102", "curvedRightArrow" },
+ { u"mso-spt103", "curvedLeftArrow" },
+ { u"mso-spt104", "curvedUpArrow" },
+ { u"mso-spt105", "curvedDownArrow" },
+ { u"cloud-callout", "cloudCallout" },
+ { u"mso-spt107", "ellipseRibbon" },
+ { u"mso-spt108", "ellipseRibbon2" },
+ { u"flowchart-process", "flowChartProcess" },
+ { u"flowchart-decision", "flowChartDecision" },
+ { u"flowchart-data", "flowChartInputOutput" },
+ { u"flowchart-predefined-process", "flowChartPredefinedProcess" },
+ { u"flowchart-internal-storage", "flowChartInternalStorage" },
+ { u"flowchart-document", "flowChartDocument" },
+ { u"flowchart-multidocument", "flowChartMultidocument" },
+ { u"flowchart-terminator", "flowChartTerminator" },
+ { u"flowchart-preparation", "flowChartPreparation" },
+ { u"flowchart-manual-input", "flowChartManualInput" },
+ { u"flowchart-manual-operation", "flowChartManualOperation" },
+ { u"flowchart-connector", "flowChartConnector" },
+ { u"flowchart-card", "flowChartPunchedCard" },
+ { u"flowchart-punched-tape", "flowChartPunchedTape" },
+ { u"flowchart-summing-junction", "flowChartSummingJunction" },
+ { u"flowchart-or", "flowChartOr" },
+ { u"flowchart-collate", "flowChartCollate" },
+ { u"flowchart-sort", "flowChartSort" },
+ { u"flowchart-extract", "flowChartExtract" },
+ { u"flowchart-merge", "flowChartMerge" },
+ { u"mso-spt129", "flowChartOfflineStorage" },
+ { u"flowchart-stored-data", "flowChartOnlineStorage" },
+ { u"flowchart-sequential-access", "flowChartMagneticTape" },
+ { u"flowchart-magnetic-disk", "flowChartMagneticDisk" },
+ { u"flowchart-direct-access-storage", "flowChartMagneticDrum" },
+ { u"flowchart-display", "flowChartDisplay" },
+ { u"flowchart-delay", "flowChartDelay" },
+ // { u"fontwork-plain-text", "textPlainText" },
+ // { u"fontwork-stop", "textStop" },
+ // { u"fontwork-triangle-up", "textTriangle" },
+ // { u"fontwork-triangle-down", "textTriangleInverted" },
+ // { u"fontwork-chevron-up", "textChevron" },
+ // { u"fontwork-chevron-down", "textChevronInverted" },
+ // { u"mso-spt142", "textRingInside" },
+ // { u"mso-spt143", "textRingOutside" },
+ // { u"fontwork-arch-up-curve", "textArchUpCurve" },
+ // { u"fontwork-arch-down-curve", "textArchDownCurve" },
+ // { u"fontwork-circle-curve", "textCircleCurve" },
+ // { u"fontwork-open-circle-curve", "textButtonCurve" },
+ // { u"fontwork-arch-up-pour", "textArchUpPour" },
+ // { u"fontwork-arch-down-pour", "textArchDownPour" },
+ // { u"fontwork-circle-pour", "textCirclePour" },
+ // { u"fontwork-open-circle-pour", "textButtonPour" },
+ // { u"fontwork-curve-up", "textCurveUp" },
+ // { u"fontwork-curve-down", "textCurveDown" },
+ // { u"fontwork-fade-up-and-right", "textCascadeUp" },
+ // { u"fontwork-fade-up-and-left", "textCascadeDown" },
+ // { u"fontwork-wave", "textWave1" },
+ // { u"mso-spt157", "textWave2" },
+ // { u"mso-spt158", "textWave3" },
+ // { u"mso-spt159", "textWave4" },
+ // { u"fontwork-inflate", "textInflate" },
+ // { u"mso-spt161", "textDeflate" },
+ // { u"mso-spt162", "textInflateBottom" },
+ // { u"mso-spt163", "textDeflateBottom" },
+ // { u"mso-spt164", "textInflateTop" },
+ // { u"mso-spt165", "textDeflateTop" },
+ // { u"mso-spt166", "textDeflateInflate" },
+ // { u"mso-spt167", "textDeflateInflateDeflate" },
+ // { u"fontwork-fade-right", "textFadeRight" },
+ // { u"fontwork-fade-left", "textFadeLeft" },
+ // { u"fontwork-fade-up", "textFadeUp" },
+ // { u"fontwork-fade-down", "textFadeDown" },
+ // { u"fontwork-slant-up", "textSlantUp" },
+ // { u"fontwork-slant-down", "textSlantDown" },
+ // { u"mso-spt174", "textCanUp" },
+ // { u"mso-spt175", "textCanDown" },
+ { u"flowchart-alternate-process", "flowChartAlternateProcess" },
+ { u"flowchart-off-page-connector", "flowChartOffpageConnector" },
+ { u"mso-spt178", "callout1" },
+ { u"mso-spt179", "accentCallout1" },
+ { u"mso-spt180", "borderCallout1" },
+ { u"mso-spt182", "leftRightUpArrow" },
+ { u"sun", "sun" },
+ { u"moon", "moon" },
+ { u"bracket-pair", "bracketPair" },
+ { u"brace-pair", "bracePair" },
+ { u"star4", "star4" },
+ { u"mso-spt188", "doubleWave" },
+ { u"mso-spt189", "actionButtonBlank" },
+ { u"mso-spt190", "actionButtonHome" },
+ { u"mso-spt191", "actionButtonHelp" },
+ { u"mso-spt192", "actionButtonInformation" },
+ { u"mso-spt193", "actionButtonForwardNext" },
+ { u"mso-spt194", "actionButtonBackPrevious" },
+ { u"mso-spt195", "actionButtonEnd" },
+ { u"mso-spt196", "actionButtonBeginning" },
+ { u"mso-spt197", "actionButtonReturn" },
+ { u"mso-spt198", "actionButtonDocument" },
+ { u"mso-spt199", "actionButtonSound" },
+ { u"mso-spt200", "actionButtonMovie" },
+ // { u"mso-spt201", "hostControl" },
+ { u"mso-spt202", "rect" },
+ { u"ooxml-actionButtonSound", "actionButtonSound" },
+ { u"ooxml-borderCallout1", "borderCallout1" },
+ { u"ooxml-plaqueTabs", "plaqueTabs" },
+ { u"ooxml-curvedLeftArrow", "curvedLeftArrow" },
+ { u"ooxml-octagon", "octagon" },
+ { u"ooxml-leftRightRibbon", "leftRightRibbon" },
+ { u"ooxml-actionButtonInformation", "actionButtonInformation" },
+ { u"ooxml-bentConnector5", "bentConnector5" },
+ { u"ooxml-circularArrow", "circularArrow" },
+ { u"ooxml-downArrowCallout", "downArrowCallout" },
+ { u"ooxml-mathMinus", "mathMinus" },
+ { u"ooxml-gear9", "gear9" },
+ { u"ooxml-round1Rect", "round1Rect" },
+ { u"ooxml-sun", "sun" },
+ { u"ooxml-plaque", "plaque" },
+ { u"ooxml-chevron", "chevron" },
+ { u"ooxml-flowChartPreparation", "flowChartPreparation" },
+ { u"ooxml-diagStripe", "diagStripe" },
+ { u"ooxml-pentagon", "pentagon" },
+ { u"ooxml-funnel", "funnel" },
+ { u"ooxml-chartStar", "chartStar" },
+ { u"ooxml-accentBorderCallout1", "accentBorderCallout1" },
+ { u"ooxml-notchedRightArrow", "notchedRightArrow" },
+ { u"ooxml-rightBracket", "rightBracket" },
+ { u"ooxml-flowChartOffpageConnector", "flowChartOffpageConnector" },
+ { u"ooxml-leftRightArrow", "leftRightArrow" },
+ { u"ooxml-decagon", "decagon" },
+ { u"ooxml-actionButtonHelp", "actionButtonHelp" },
+ { u"ooxml-star24", "star24" },
+ { u"ooxml-mathDivide", "mathDivide" },
+ { u"ooxml-curvedConnector4", "curvedConnector4" },
+ { u"ooxml-flowChartOr", "flowChartOr" },
+ { u"ooxml-borderCallout3", "borderCallout3" },
+ { u"ooxml-upDownArrowCallout", "upDownArrowCallout" },
+ { u"ooxml-flowChartDecision", "flowChartDecision" },
+ { u"ooxml-leftRightArrowCallout", "leftRightArrowCallout" },
+ { u"ooxml-flowChartManualOperation", "flowChartManualOperation" },
+ { u"ooxml-snipRoundRect", "snipRoundRect" },
+ { u"ooxml-mathPlus", "mathPlus" },
+ { u"ooxml-actionButtonForwardNext", "actionButtonForwardNext" },
+ { u"ooxml-can", "can" },
+ { u"ooxml-foldedCorner", "foldedCorner" },
+ { u"ooxml-star32", "star32" },
+ { u"ooxml-flowChartInternalStorage", "flowChartInternalStorage" },
+ { u"ooxml-upDownArrow", "upDownArrow" },
+ { u"ooxml-irregularSeal2", "irregularSeal2" },
+ { u"ooxml-mathEqual", "mathEqual" },
+ { u"ooxml-star12", "star12" },
+ { u"ooxml-uturnArrow", "uturnArrow" },
+ { u"ooxml-squareTabs", "squareTabs" },
+ { u"ooxml-leftRightUpArrow", "leftRightUpArrow" },
+ { u"ooxml-homePlate", "homePlate" },
+ { u"ooxml-dodecagon", "dodecagon" },
+ { u"ooxml-leftArrowCallout", "leftArrowCallout" },
+ { u"ooxml-chord", "chord" },
+ { u"ooxml-quadArrowCallout", "quadArrowCallout" },
+ { u"ooxml-actionButtonBeginning", "actionButtonBeginning" },
+ { u"ooxml-ellipse", "ellipse" },
+ { u"ooxml-actionButtonEnd", "actionButtonEnd" },
+ { u"ooxml-arc", "arc" },
+ { u"ooxml-star16", "star16" },
+ { u"ooxml-parallelogram", "parallelogram" },
+ { u"ooxml-bevel", "bevel" },
+ { u"ooxml-roundRect", "roundRect" },
+ { u"ooxml-accentCallout1", "accentCallout1" },
+ { u"ooxml-flowChartSort", "flowChartSort" },
+ { u"ooxml-star8", "star8" },
+ { u"ooxml-flowChartAlternateProcess", "flowChartAlternateProcess" },
+ { u"ooxml-moon", "moon" },
+ { u"ooxml-star6", "star6" },
+ { u"ooxml-round2SameRect", "round2SameRect" },
+ { u"ooxml-nonIsoscelesTrapezoid", "nonIsoscelesTrapezoid" },
+ { u"ooxml-diamond", "diamond" },
+ { u"ooxml-ellipseRibbon", "ellipseRibbon" },
+ { u"ooxml-callout2", "callout2" },
+ { u"ooxml-pie", "pie" },
+ { u"ooxml-star4", "star4" },
+ { u"ooxml-flowChartPredefinedProcess", "flowChartPredefinedProcess" },
+ { u"ooxml-flowChartPunchedTape", "flowChartPunchedTape" },
+ { u"ooxml-curvedConnector2", "curvedConnector2" },
+ { u"ooxml-bentConnector3", "bentConnector3" },
+ { u"ooxml-cornerTabs", "cornerTabs" },
+ { u"ooxml-hexagon", "hexagon" },
+ { u"ooxml-flowChartConnector", "flowChartConnector" },
+ { u"ooxml-flowChartMagneticDisk", "flowChartMagneticDisk" },
+ { u"ooxml-heart", "heart" },
+ { u"ooxml-ribbon2", "ribbon2" },
+ { u"ooxml-bracePair", "bracePair" },
+ { u"ooxml-flowChartExtract", "flowChartExtract" },
+ { u"ooxml-actionButtonHome", "actionButtonHome" },
+ { u"ooxml-accentBorderCallout3", "accentBorderCallout3" },
+ { u"ooxml-flowChartOfflineStorage", "flowChartOfflineStorage" },
+ { u"ooxml-irregularSeal1", "irregularSeal1" },
+ { u"ooxml-quadArrow", "quadArrow" },
+ { u"ooxml-leftBrace", "leftBrace" },
+ { u"ooxml-leftBracket", "leftBracket" },
+ { u"ooxml-blockArc", "blockArc" },
+ { u"ooxml-curvedConnector3", "curvedConnector3" },
+ { u"ooxml-wedgeRoundRectCallout", "wedgeRoundRectCallout" },
+ { u"ooxml-actionButtonMovie", "actionButtonMovie" },
+ { u"ooxml-flowChartOnlineStorage", "flowChartOnlineStorage" },
+ { u"ooxml-gear6", "gear6" },
+ { u"ooxml-halfFrame", "halfFrame" },
+ { u"ooxml-snip2SameRect", "snip2SameRect" },
+ { u"ooxml-triangle", "triangle" },
+ { u"ooxml-teardrop", "teardrop" },
+ { u"ooxml-flowChartDocument", "flowChartDocument" },
+ { u"ooxml-rightArrowCallout", "rightArrowCallout" },
+ { u"ooxml-rightBrace", "rightBrace" },
+ { u"ooxml-chartPlus", "chartPlus" },
+ { u"ooxml-flowChartManualInput", "flowChartManualInput" },
+ { u"ooxml-flowChartMerge", "flowChartMerge" },
+ { u"ooxml-line", "line" },
+ { u"ooxml-downArrow", "downArrow" },
+ { u"ooxml-upArrow", "upArrow" },
+ { u"ooxml-curvedDownArrow", "curvedDownArrow" },
+ { u"ooxml-actionButtonReturn", "actionButtonReturn" },
+ { u"ooxml-flowChartInputOutput", "flowChartInputOutput" },
+ { u"ooxml-bracketPair", "bracketPair" },
+ { u"ooxml-smileyFace", "smileyFace" },
+ { u"ooxml-actionButtonBlank", "actionButtonBlank" },
+ { u"ooxml-wave", "wave" },
+ { u"ooxml-swooshArrow", "swooshArrow" },
+ { u"ooxml-flowChartSummingJunction", "flowChartSummingJunction" },
+ { u"ooxml-lightningBolt", "lightningBolt" },
+ { u"ooxml-flowChartDisplay", "flowChartDisplay" },
+ { u"ooxml-actionButtonBackPrevious", "actionButtonBackPrevious" },
+ { u"ooxml-frame", "frame" },
+ { u"ooxml-rtTriangle", "rtTriangle" },
+ { u"ooxml-flowChartMagneticTape", "flowChartMagneticTape" },
+ { u"ooxml-curvedRightArrow", "curvedRightArrow" },
+ { u"ooxml-leftUpArrow", "leftUpArrow" },
+ { u"ooxml-wedgeEllipseCallout", "wedgeEllipseCallout" },
+ { u"ooxml-doubleWave", "doubleWave" },
+ { u"ooxml-bentArrow", "bentArrow" },
+ { u"ooxml-star10", "star10" },
+ { u"ooxml-leftArrow", "leftArrow" },
+ { u"ooxml-curvedUpArrow", "curvedUpArrow" },
+ { u"ooxml-snip1Rect", "snip1Rect" },
+ { u"ooxml-ellipseRibbon2", "ellipseRibbon2" },
+ { u"ooxml-plus", "plus" },
+ { u"ooxml-accentCallout3", "accentCallout3" },
+ { u"ooxml-leftCircularArrow", "leftCircularArrow" },
+ { u"ooxml-rightArrow", "rightArrow" },
+ { u"ooxml-flowChartPunchedCard", "flowChartPunchedCard" },
+ { u"ooxml-snip2DiagRect", "snip2DiagRect" },
+ { u"ooxml-verticalScroll", "verticalScroll" },
+ { u"ooxml-star7", "star7" },
+ { u"ooxml-chartX", "chartX" },
+ { u"ooxml-cloud", "cloud" },
+ { u"ooxml-cube", "cube" },
+ { u"ooxml-round2DiagRect", "round2DiagRect" },
+ { u"ooxml-flowChartMultidocument", "flowChartMultidocument" },
+ { u"ooxml-actionButtonDocument", "actionButtonDocument" },
+ { u"ooxml-flowChartTerminator", "flowChartTerminator" },
+ { u"ooxml-flowChartDelay", "flowChartDelay" },
+ { u"ooxml-curvedConnector5", "curvedConnector5" },
+ { u"ooxml-horizontalScroll", "horizontalScroll" },
+ { u"ooxml-bentConnector4", "bentConnector4" },
+ { u"ooxml-leftRightCircularArrow", "leftRightCircularArrow" },
+ { u"ooxml-wedgeRectCallout", "wedgeRectCallout" },
+ { u"ooxml-accentCallout2", "accentCallout2" },
+ { u"ooxml-flowChartMagneticDrum", "flowChartMagneticDrum" },
+ { u"ooxml-corner", "corner" },
+ { u"ooxml-borderCallout2", "borderCallout2" },
+ { u"ooxml-donut", "donut" },
+ { u"ooxml-flowChartCollate", "flowChartCollate" },
+ { u"ooxml-mathNotEqual", "mathNotEqual" },
+ { u"ooxml-bentConnector2", "bentConnector2" },
+ { u"ooxml-mathMultiply", "mathMultiply" },
+ { u"ooxml-heptagon", "heptagon" },
+ { u"ooxml-rect", "rect" },
+ { u"ooxml-accentBorderCallout2", "accentBorderCallout2" },
+ { u"ooxml-pieWedge", "pieWedge" },
+ { u"ooxml-upArrowCallout", "upArrowCallout" },
+ { u"ooxml-flowChartProcess", "flowChartProcess" },
+ { u"ooxml-star5", "star5" },
+ { u"ooxml-lineInv", "lineInv" },
+ { u"ooxml-straightConnector1", "straightConnector1" },
+ { u"ooxml-stripedRightArrow", "stripedRightArrow" },
+ { u"ooxml-callout3", "callout3" },
+ { u"ooxml-bentUpArrow", "bentUpArrow" },
+ { u"ooxml-noSmoking", "noSmoking" },
+ { u"ooxml-trapezoid", "trapezoid" },
+ { u"ooxml-cloudCallout", "cloudCallout" },
+ { u"ooxml-callout1", "callout1" },
+ { u"ooxml-ribbon", "ribbon" },
+ { u"ooxml-rect", "rect" },
+ };
+ auto i(aCustomShapeTypeTranslationHashMap.find(rShapeType));
+ return i == aCustomShapeTypeTranslationHashMap.end() ? "rect" : i->second;
+}
+
+MSO_SPT GETVMLShapeType(std::u16string_view aType)
+{
+ typedef std::unordered_map<std::string_view, MSO_SPT> DMLToVMLTranslationHashMap;
+ static const DMLToVMLTranslationHashMap aDMLToVMLMap{
+ {"notPrimitive", mso_sptNotPrimitive},
+ {"rectangle", mso_sptRectangle},
+ {"roundRectangle", mso_sptRoundRectangle},
+ {"ellipse", mso_sptEllipse},
+ {"diamond", mso_sptDiamond},
+ {"triangle", mso_sptIsocelesTriangle},
+ {"rtTriangle", mso_sptRightTriangle},
+ {"parallelogram", mso_sptParallelogram},
+ {"trapezoid", mso_sptTrapezoid},
+ {"hexagon", mso_sptHexagon},
+ {"octagon", mso_sptOctagon},
+ {"plus", mso_sptPlus},
+ {"star5", mso_sptStar},
+ {"rightArrow", mso_sptArrow},
+ {"thickArrow", mso_sptThickArrow},
+ {"homePlate", mso_sptHomePlate},
+ {"cube", mso_sptCube},
+ {"wedgeRoundRectCallout", mso_sptBalloon},
+ {"star16", mso_sptSeal},
+ {"arc", mso_sptArc},
+ {"line", mso_sptLine},
+ {"plaque", mso_sptPlaque},
+ {"can", mso_sptCan},
+ {"donut", mso_sptDonut},
+ {"textPlain", mso_sptTextSimple},
+ {"textStop", mso_sptTextOctagon},
+ {"textTriangle", mso_sptTextHexagon},
+ {"textCanDown", mso_sptTextCurve},
+ {"textWave1", mso_sptTextWave},
+ {"textArchUpPour", mso_sptTextRing},
+ {"textCanDown", mso_sptTextOnCurve},
+ {"textArchUp", mso_sptTextOnRing},
+ {"straightConnector1", mso_sptStraightConnector1},
+ {"bentConnector2", mso_sptBentConnector2},
+ {"bentConnector3", mso_sptBentConnector3},
+ {"bentConnector4", mso_sptBentConnector4},
+ {"bentConnector5", mso_sptBentConnector5},
+ {"curvedConnector2", mso_sptCurvedConnector2},
+ {"curvedConnector3", mso_sptCurvedConnector3},
+ {"curvedConnector4", mso_sptCurvedConnector4},
+ {"curvedConnector5", mso_sptCurvedConnector5},
+ {"callout1", mso_sptCallout1},
+ {"callout2", mso_sptCallout2},
+ {"callout3", mso_sptCallout3},
+ {"accentCallout1", mso_sptAccentCallout1},
+ {"accentCallout2", mso_sptAccentCallout2},
+ {"accentCallout3", mso_sptAccentCallout3},
+ {"borderCallout1", mso_sptBorderCallout1},
+ {"borderCallout2", mso_sptBorderCallout2},
+ {"borderCallout3", mso_sptBorderCallout3},
+ {"accentBorderCallout1", mso_sptAccentBorderCallout1},
+ {"accentBorderCallout2", mso_sptAccentBorderCallout2},
+ {"accentBorderCallout3", mso_sptAccentBorderCallout3},
+ {"ribbon", mso_sptRibbon},
+ {"ribbon2", mso_sptRibbon2},
+ {"chevron", mso_sptChevron},
+ {"pentagon", mso_sptPentagon},
+ {"noSmoking", mso_sptNoSmoking},
+ {"star8", mso_sptSeal8},
+ {"star16", mso_sptSeal16},
+ {"star32", mso_sptSeal32},
+ {"wedgeRectCallout", mso_sptWedgeRectCallout},
+ {"wedgeRoundRectCallout", mso_sptWedgeRRectCallout},
+ {"wedgeEllipseCallout", mso_sptWedgeEllipseCallout},
+ {"wave", mso_sptWave},
+ {"foldedCorner", mso_sptFoldedCorner},
+ {"leftArrow", mso_sptLeftArrow},
+ {"downArrow", mso_sptDownArrow},
+ {"upArrow", mso_sptUpArrow},
+ {"leftRightArrow", mso_sptLeftRightArrow},
+ {"upDownArrow", mso_sptUpDownArrow},
+ {"irregularSeal1", mso_sptIrregularSeal1},
+ {"irregularSeal2", mso_sptIrregularSeal2},
+ {"lightningBolt", mso_sptLightningBolt},
+ {"heart", mso_sptHeart},
+ {"pictureFrame", mso_sptPictureFrame},
+ {"quadArrow", mso_sptQuadArrow},
+ {"leftArrowCallout", mso_sptLeftArrowCallout},
+ {"rightArrowCallout", mso_sptRightArrowCallout},
+ {"upArrowCallout", mso_sptUpArrowCallout},
+ {"downArrowCallout", mso_sptDownArrowCallout},
+ {"leftRightArrowCallout", mso_sptLeftRightArrowCallout},
+ {"upDownArrowCallout", mso_sptUpDownArrowCallout},
+ {"quadArrowCallout", mso_sptQuadArrowCallout},
+ {"bevel", mso_sptBevel},
+ {"leftBracket", mso_sptLeftBracket},
+ {"rightBracket", mso_sptRightBracket},
+ {"leftBrace", mso_sptLeftBrace},
+ {"rightBrace", mso_sptRightBrace},
+ {"leftUpArrow", mso_sptLeftUpArrow},
+ {"bentUpArrow", mso_sptBentUpArrow},
+ {"bentArrow", mso_sptBentArrow},
+ {"star24", mso_sptSeal24},
+ {"stripedRightArrow", mso_sptStripedRightArrow},
+ {"notchedRightArrow", mso_sptNotchedRightArrow},
+ {"blockArc", mso_sptBlockArc},
+ {"smileyFace", mso_sptSmileyFace},
+ {"verticalScroll", mso_sptVerticalScroll},
+ {"horizontalScroll", mso_sptHorizontalScroll},
+ {"circularArrow", mso_sptCircularArrow},
+ {"notchedCircularArrow", mso_sptNotchedCircularArrow},
+ {"uturnArrow", mso_sptUturnArrow},
+ {"curvedRightArrow", mso_sptCurvedRightArrow},
+ {"curvedLeftArrow", mso_sptCurvedLeftArrow},
+ {"curvedUpArrow", mso_sptCurvedUpArrow},
+ {"curvedDownArrow", mso_sptCurvedDownArrow},
+ {"cloudCallout", mso_sptCloudCallout},
+ {"ellipseRibbon", mso_sptEllipseRibbon},
+ {"ellipseRibbon2", mso_sptEllipseRibbon2},
+ {"flowChartProcess", mso_sptFlowChartProcess},
+ {"flowChartDecision", mso_sptFlowChartDecision},
+ {"flowChartInputOutput", mso_sptFlowChartInputOutput},
+ {"flowChartPredefinedProcess", mso_sptFlowChartPredefinedProcess},
+ {"flowChartInternalStorage", mso_sptFlowChartInternalStorage},
+ {"flowChartDocument", mso_sptFlowChartDocument},
+ {"flowChartMultidocument", mso_sptFlowChartMultidocument},
+ {"flowChartTerminator", mso_sptFlowChartTerminator},
+ {"flowChartPreparation", mso_sptFlowChartPreparation},
+ {"flowChartManualInput", mso_sptFlowChartManualInput},
+ {"flowChartManualOperation", mso_sptFlowChartManualOperation},
+ {"flowChartConnector", mso_sptFlowChartConnector},
+ {"flowChartPunchedCard", mso_sptFlowChartPunchedCard},
+ {"flowChartPunchedTape", mso_sptFlowChartPunchedTape},
+ {"flowChartSummingJunction", mso_sptFlowChartSummingJunction},
+ {"flowChartOr", mso_sptFlowChartOr},
+ {"flowChartCollate", mso_sptFlowChartCollate},
+ {"flowChartSort", mso_sptFlowChartSort},
+ {"flowChartExtract", mso_sptFlowChartExtract},
+ {"flowChartMerge", mso_sptFlowChartMerge},
+ {"flowChartOfflineStorage", mso_sptFlowChartOfflineStorage},
+ {"flowChartOnlineStorage", mso_sptFlowChartOnlineStorage},
+ {"flowChartMagneticTape", mso_sptFlowChartMagneticTape},
+ {"flowChartMagneticDisk", mso_sptFlowChartMagneticDisk},
+ {"flowChartMagneticDrum", mso_sptFlowChartMagneticDrum},
+ {"flowChartDisplay", mso_sptFlowChartDisplay},
+ {"flowChartDelay", mso_sptFlowChartDelay},
+ {"textPlain", mso_sptTextPlainText},
+ {"textStop", mso_sptTextStop},
+ {"textTriangle", mso_sptTextTriangle},
+ {"textTriangleInverted", mso_sptTextTriangleInverted},
+ {"textChevron", mso_sptTextChevron},
+ {"textChevronInverted", mso_sptTextChevronInverted},
+ {"textRingInside", mso_sptTextRingInside},
+ {"textRingOutside", mso_sptTextRingOutside},
+ {"textArchUp", mso_sptTextArchUpCurve},
+ {"textArchDown", mso_sptTextArchDownCurve},
+ {"textCircle", mso_sptTextCircleCurve},
+ {"textButton", mso_sptTextButtonCurve},
+ {"textArchUpPour", mso_sptTextArchUpPour},
+ {"textArchDownPour", mso_sptTextArchDownPour},
+ {"textCirclePour", mso_sptTextCirclePour},
+ {"textButtonPour", mso_sptTextButtonPour},
+ {"textCurveUp", mso_sptTextCurveUp},
+ {"textCurveDown", mso_sptTextCurveDown},
+ {"textCascadeUp", mso_sptTextCascadeUp},
+ {"textCascadeDown", mso_sptTextCascadeDown},
+ {"textWave1", mso_sptTextWave1},
+ {"textWave2", mso_sptTextWave2},
+ {"textWave3", mso_sptTextWave3},
+ {"textWave4", mso_sptTextWave4},
+ {"textInflate", mso_sptTextInflate},
+ {"textDeflate", mso_sptTextDeflate},
+ {"textInflateBottom", mso_sptTextInflateBottom},
+ {"textDeflateBottom", mso_sptTextDeflateBottom},
+ {"textInflateTop", mso_sptTextInflateTop},
+ {"textDeflateTop", mso_sptTextDeflateTop},
+ {"textDeflateInflate", mso_sptTextDeflateInflate},
+ {"textDeflateInflateDeflate", mso_sptTextDeflateInflateDeflate},
+ {"textFadeRight", mso_sptTextFadeRight},
+ {"textFadeLeft", mso_sptTextFadeLeft},
+ {"textFadeUp", mso_sptTextFadeUp},
+ {"textFadeDown", mso_sptTextFadeDown},
+ {"textSlantUp", mso_sptTextSlantUp},
+ {"textSlantDown", mso_sptTextSlantDown},
+ {"textCanUp", mso_sptTextCanUp},
+ {"textCanDown", mso_sptTextCanDown},
+ {"flowChartAlternateProcess", mso_sptFlowChartAlternateProcess},
+ {"flowChartOffpageConnector", mso_sptFlowChartOffpageConnector},
+ {"callout1", mso_sptCallout90},
+ {"accentCallout1", mso_sptAccentCallout90},
+ {"borderCallout1", mso_sptBorderCallout90},
+ {"accentBorderCallout1", mso_sptAccentBorderCallout90},
+ {"leftRightUpArrow", mso_sptLeftRightUpArrow},
+ {"sun", mso_sptSun},
+ {"moon", mso_sptMoon},
+ {"bracketPair", mso_sptBracketPair},
+ {"bracePair", mso_sptBracePair},
+ {"star4", mso_sptSeal4},
+ {"doubleWave", mso_sptDoubleWave},
+ {"actionButtonBlank", mso_sptActionButtonBlank},
+ {"actionButtonHome", mso_sptActionButtonHome},
+ {"actionButtonHelp", mso_sptActionButtonHelp},
+ {"actionButtonInformation", mso_sptActionButtonInformation},
+ {"actionButtonForwardNext", mso_sptActionButtonForwardNext},
+ {"actionButtonBackPrevious", mso_sptActionButtonBackPrevious},
+ {"actionButtonEnd", mso_sptActionButtonEnd},
+ {"actionButtonBeginning", mso_sptActionButtonBeginning},
+ {"actionButtonReturn", mso_sptActionButtonReturn},
+ {"actionButtonDocument", mso_sptActionButtonDocument},
+ {"actionButtonSound", mso_sptActionButtonSound},
+ {"actionButtonMovie", mso_sptActionButtonMovie},
+ {"hostControl", mso_sptHostControl},
+ {"textBox", mso_sptTextBox},
+ };
+
+ auto i(aDMLToVMLMap.find(GetOOXMLPresetGeometry(aType)));
+ return i == aDMLToVMLMap.end() ? mso_sptNil : i->second;
+}
+
+bool HasTextBoxContent(sal_uInt32 nShapeType)
+{
+ switch (nShapeType)
+ {
+ case ESCHER_ShpInst_TextPlainText:
+ case ESCHER_ShpInst_TextSlantUp:
+ case ESCHER_ShpInst_TextDeflateInflateDeflate:
+ return false;
+ default:
+ return true;
+ }
+}
+
+namespace
+{
+
+// Scheme means pattern of chromatic values.
+// [2,2,1] -> red and green are approximately equal and blue is the dominant color (e.g. blue)
+// [1,1,1] -> all chromatic values are approximately equal (e.g. white, gray, black)
+void CalculateScheme(const BitmapColor& rBitmapColor, std::vector<int> &vScheme, sal_uInt16 nVariance)
+{
+ vScheme.resize(3,1);
+ if( rBitmapColor.GetRed() < rBitmapColor.GetGreen() + nVariance )
+ ++vScheme[0];
+ if( rBitmapColor.GetRed() < rBitmapColor.GetBlue() + nVariance )
+ ++vScheme[0];
+ if( rBitmapColor.GetGreen() < rBitmapColor.GetRed() + nVariance )
+ ++vScheme[1];
+ if( rBitmapColor.GetGreen() < rBitmapColor.GetBlue() + nVariance )
+ ++vScheme[1];
+ if( rBitmapColor.GetBlue() < rBitmapColor.GetRed() + nVariance )
+ ++vScheme[2];
+ if( rBitmapColor.GetBlue() < rBitmapColor.GetGreen() + nVariance )
+ ++vScheme[2];
+}
+
+bool HasSimilarScheme(const BitmapColor& rBitmapColor1, const BitmapColor& rBitmapColor2, sal_uInt16 nVariance)
+{
+ std::vector<int> vScheme1, vScheme2;
+ CalculateScheme(rBitmapColor1, vScheme1, nVariance);
+ CalculateScheme(rBitmapColor2, vScheme2, nVariance);
+ for( int i = 0; i < 3; ++i )
+ {
+ if( vScheme1[i] != vScheme2[i] )
+ return false;
+ }
+ return true;
+}
+
+// Find the best match in the color palette using scheme of the input color
+sal_uInt16 GetBestIndex(const BitmapPalette& rPalette, const BitmapColor& rBitmapColor)
+{
+ sal_uInt16 nReturn = 0;
+ sal_uInt16 nLastErr = SAL_MAX_UINT16;
+ bool bFound = false;
+
+ // Prefer those colors which have similar scheme as the input
+ // Allow bigger and bigger variance of the schemes until we find
+ // a color in the palette with similar scheme.
+ for( sal_uInt16 nVariance = 0; nVariance <= 255; ++nVariance )
+ {
+ for( sal_uInt16 i = 0; i < rPalette.GetEntryCount(); ++i )
+ {
+ if( HasSimilarScheme(rBitmapColor, rPalette[i], nVariance) )
+ {
+ const sal_uInt16 nActErr = rBitmapColor.GetColorError( rPalette[i] );
+ if( nActErr < nLastErr )
+ {
+ nLastErr = nActErr;
+ nReturn = i;
+ bFound = true;
+ }
+ }
+ }
+ if( bFound )
+ return nReturn;
+ }
+ return nReturn;
+}
+}
+
+sal_uInt8 TransColToIco( const Color& rCol )
+{
+ sal_uInt8 nCol = 0; // ->Auto
+ switch( sal_uInt32(rCol) )
+ {
+ case sal_uInt32(COL_BLACK): nCol = 1; break;
+ case sal_uInt32(COL_BLUE): nCol = 9; break;
+ case sal_uInt32(COL_GREEN): nCol = 11; break;
+ case sal_uInt32(COL_CYAN): nCol = 10; break;
+ case sal_uInt32(COL_RED): nCol = 13; break;
+ case sal_uInt32(COL_MAGENTA): nCol = 12; break;
+ case sal_uInt32(COL_BROWN): nCol = 14; break;
+ case sal_uInt32(COL_GRAY): nCol = 15; break;
+ case sal_uInt32(COL_LIGHTGRAY): nCol = 16; break;
+ case sal_uInt32(COL_LIGHTBLUE): nCol = 2; break;
+ case sal_uInt32(COL_LIGHTGREEN): nCol = 4; break;
+ case sal_uInt32(COL_LIGHTCYAN): nCol = 3; break;
+ case sal_uInt32(COL_LIGHTRED): nCol = 6; break;
+ case sal_uInt32(COL_LIGHTMAGENTA): nCol = 5; break;
+ case sal_uInt32(COL_YELLOW): nCol = 7; break;
+ case sal_uInt32(COL_WHITE): nCol = 8; break;
+ case sal_uInt32(COL_AUTO): nCol = 0; break;
+
+ default:
+ static const BitmapPalette aBmpPal {
+ COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,
+ COL_LIGHTMAGENTA,COL_LIGHTRED, COL_YELLOW, COL_WHITE,
+ COL_BLUE, COL_CYAN, COL_GREEN, COL_MAGENTA,
+ COL_RED, COL_BROWN, COL_GRAY, COL_LIGHTGRAY
+ };
+
+ nCol = static_cast< sal_uInt8 >(GetBestIndex(aBmpPal, rCol) + 1);
+ break;
+ }
+ return nCol;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/msfilter/viscache.hxx b/filter/source/msfilter/viscache.hxx
new file mode 100644
index 000000000..5111969b3
--- /dev/null
+++ b/filter/source/msfilter/viscache.hxx
@@ -0,0 +1,52 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <memory>
+#include <sfx2/objsh.hxx>
+#include <vcl/gdimtf.hxx>
+
+class SvStream;
+
+class Impl_OlePres
+{
+ SotClipboardFormatId nFormat;
+ sal_uInt16 nAspect;
+ std::unique_ptr<GDIMetaFile>
+ pMtf;
+
+ sal_uInt32 nAdvFlags;
+ Size aSize; // size in 100TH_MM
+public:
+ explicit Impl_OlePres()
+ : nFormat( SotClipboardFormatId::GDIMETAFILE )
+ , nAspect( ASPECT_CONTENT )
+ , nAdvFlags( 0x2 ) // found in document
+ {}
+ void SetMtf( const GDIMetaFile & rMtf )
+ {
+ pMtf.reset( new GDIMetaFile( rMtf ) );
+ }
+ void SetAspect( sal_uInt16 nAsp ) { nAspect = nAsp; }
+ void SetAdviseFlags( sal_uLong nAdv ) { nAdvFlags = nAdv; }
+ void SetSize( const Size & rSize ) { aSize = rSize; }
+ void Write( SvStream & rStm );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/odfflatxml/OdfFlatXml.cxx b/filter/source/odfflatxml/OdfFlatXml.cxx
new file mode 100644
index 000000000..4d6005431
--- /dev/null
+++ b/filter/source/odfflatxml/OdfFlatXml.cxx
@@ -0,0 +1,260 @@
+/* -*- 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 <comphelper/processfactory.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <cppuhelper/weak.hxx>
+#include <osl/diagnose.h>
+#include <sal/log.hxx>
+
+#include <sax/tools/documenthandleradapter.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <com/sun/star/xml/XImportFilter.hpp>
+#include <com/sun/star/xml/XImportFilter2.hpp>
+#include <com/sun/star/xml/XExportFilter.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/xml/sax/XFastParser.hpp>
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <tools/diagnose_ex.h>
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::sax;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::xml;
+using namespace ::com::sun::star::xml::sax;
+
+namespace filter::odfflatxml {
+ namespace {
+
+ /*
+ * OdfFlatXml export and imports ODF flat XML documents by plugging a pass-through
+ * filter implementation into XmlFilterAdaptor.
+ */
+ class OdfFlatXml : public WeakImplHelper<XImportFilter, XImportFilter2,
+ XExportFilter, DocumentHandlerAdapter, css::lang::XServiceInfo>
+ {
+ private:
+ Reference< XComponentContext > m_xContext;
+
+ public:
+
+ explicit OdfFlatXml(const Reference<XComponentContext> &r) :
+ m_xContext(r)
+ {
+ }
+
+ // XImportFilter
+ virtual sal_Bool SAL_CALL
+ importer(const Sequence< PropertyValue >& sourceData,
+ const Reference< XDocumentHandler >& docHandler,
+ const Sequence< OUString >& userData) override;
+
+ // XImportFilter2
+ virtual sal_Bool SAL_CALL
+ importer(const Sequence< PropertyValue >& sourceData,
+ const Reference< XFastParser >& fastParser,
+ const Sequence< OUString >& userData) override;
+
+ // XExportFilter
+ virtual sal_Bool SAL_CALL
+ exporter(
+ const Sequence< PropertyValue >& sourceData,
+ const Sequence< OUString >& userData) override;
+
+ OUString SAL_CALL getImplementationName() override
+ { return "com.sun.star.comp.filter.OdfFlatXml"; }
+
+ sal_Bool SAL_CALL supportsService(OUString const & ServiceName) override
+ { return cppu::supportsService(this, ServiceName); }
+
+ css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
+ {
+ return css::uno::Sequence<OUString>{
+ "com.sun.star.document.ImportFilter",
+ "com.sun.star.document.ExportFilter"};
+ }
+
+ };
+
+ }
+}
+
+using namespace ::filter::odfflatxml;
+
+sal_Bool
+OdfFlatXml::importer(
+ const Sequence< PropertyValue >& sourceData,
+ const Reference< XDocumentHandler >& docHandler,
+ const Sequence< OUString >& /* userData */)
+{
+ // Read InputStream to read from and a URL used for the system id
+ // of the InputSource we create from the given sourceData sequence
+ Reference<XInputStream> inputStream;
+ OUString paramName;
+ OUString url;
+
+ sal_Int32 paramCount = sourceData.getLength();
+ for (sal_Int32 paramIdx = 0; paramIdx < paramCount; paramIdx++)
+ {
+ paramName = sourceData[paramIdx].Name;
+ if ( paramName == "InputStream" )
+ sourceData[paramIdx].Value >>= inputStream;
+ else if ( paramName == "URL" )
+ sourceData[paramIdx].Value >>= url;
+ }
+
+ OSL_ASSERT(inputStream.is());
+ if (!inputStream.is())
+ return false;
+
+ InputSource inputSource;
+ inputSource.sSystemId = url;
+ inputSource.sPublicId = url;
+ inputSource.aInputStream = inputStream;
+ try
+ {
+ css::uno::Reference< css::io::XSeekable > xSeekable( inputStream, css::uno::UNO_QUERY );
+ if ( xSeekable.is() )
+ xSeekable->seek( 0 );
+
+ css::uno::Reference< css::xml::sax::XFastParser > xFastParser (docHandler, UNO_QUERY );
+ if( xFastParser.is() )
+ xFastParser->parseStream( inputSource );
+ else
+ {
+ Reference<XParser> saxParser = Parser::create(m_xContext);
+ saxParser->setDocumentHandler(docHandler);
+ saxParser->parseStream(inputSource);
+ }
+ }
+ catch (const Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("filter.odfflatxml", "");
+ return false;
+ }
+ catch (const std::exception &exc)
+ {
+ SAL_WARN("filter.odfflatxml", exc.what());
+ return false;
+ }
+ return true;
+}
+
+sal_Bool
+OdfFlatXml::importer(
+ const Sequence< PropertyValue >& sourceData,
+ const Reference< XFastParser >& xFastParser,
+ const Sequence< OUString >& /* userData */)
+{
+ // Read InputStream to read from and a URL used for the system id
+ // of the InputSource we create from the given sourceData sequence
+ Reference<XInputStream> inputStream;
+ OUString paramName;
+ OUString url;
+
+ sal_Int32 paramCount = sourceData.getLength();
+ for (sal_Int32 paramIdx = 0; paramIdx < paramCount; paramIdx++)
+ {
+ paramName = sourceData[paramIdx].Name;
+ if ( paramName == "InputStream" )
+ sourceData[paramIdx].Value >>= inputStream;
+ else if ( paramName == "URL" )
+ sourceData[paramIdx].Value >>= url;
+ }
+
+ OSL_ASSERT(inputStream.is());
+ if (!inputStream.is())
+ return false;
+
+ InputSource inputSource;
+ inputSource.sSystemId = url;
+ inputSource.sPublicId = url;
+ inputSource.aInputStream = inputStream;
+ try
+ {
+ css::uno::Reference< css::io::XSeekable > xSeekable( inputStream, css::uno::UNO_QUERY );
+ if ( xSeekable.is() )
+ xSeekable->seek( 0 );
+
+ xFastParser->parseStream( inputSource );
+ }
+ catch (const Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("filter.odfflatxml", "");
+ return false;
+ }
+ catch (const std::exception &exc)
+ {
+ SAL_WARN("filter.odfflatxml", exc.what());
+ return false;
+ }
+ return true;
+}
+
+sal_Bool
+OdfFlatXml::exporter(const Sequence< PropertyValue >& sourceData,
+ const Sequence< OUString >& /*msUserData*/)
+{
+ OUString paramName;
+ Reference<XOutputStream> outputStream;
+
+ // Read output stream and target URL from the parameters given in sourceData.
+ sal_Int32 paramCount = sourceData.getLength();
+ for (sal_Int32 paramIdx = 0; paramIdx < paramCount; paramIdx++)
+ {
+ paramName = sourceData[paramIdx].Name;
+ if ( paramName == "OutputStream" )
+ sourceData[paramIdx].Value >>= outputStream;
+ }
+
+ if (!getDelegate().is())
+ {
+ Reference< XDocumentHandler > saxWriter = Writer::create(m_xContext);
+ setDelegate(saxWriter);
+ }
+ // get data source interface ...
+ Reference<XActiveDataSource> dataSource(getDelegate(), UNO_QUERY);
+ OSL_ASSERT(dataSource.is());
+ if (!dataSource.is())
+ return false;
+ OSL_ASSERT(outputStream.is());
+ if (!outputStream.is())
+ return false;
+ dataSource->setOutputStream(outputStream);
+
+ return true;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_OdfFlatXml_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new OdfFlatXml(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/odfflatxml/odfflatxml.component b/filter/source/odfflatxml/odfflatxml.component
new file mode 100644
index 000000000..5f8bcfa9d
--- /dev/null
+++ b/filter/source/odfflatxml/odfflatxml.component
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+-->
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.filter.OdfFlatXml"
+ constructor="filter_OdfFlatXml_get_implementation" single-instance="true">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExportFilter"/>
+ </implementation>
+</component>
diff --git a/filter/source/pdf/impdialog.cxx b/filter/source/pdf/impdialog.cxx
new file mode 100644
index 000000000..bd8db8369
--- /dev/null
+++ b/filter/source/pdf/impdialog.cxx
@@ -0,0 +1,1638 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "impdialog.hxx"
+#include <strings.hrc>
+#include <officecfg/Office/Common.hxx>
+#include <vcl/errinf.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/passwd.hxx>
+#include <unotools/resmgr.hxx>
+#include <tools/diagnose_ex.h>
+#include <sfx2/objsh.hxx>
+#include <svx/AccessibilityCheckDialog.hxx>
+
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/storagehelper.hxx>
+
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/security/DocumentDigitalSignatures.hpp>
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+static OUString PDFFilterResId(TranslateId aId)
+{
+ return Translate::get(aId, Translate::Create("flt"));
+}
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+/** Tabbed PDF dialog implementation
+ Please note: the default used here are the same as per specification,
+ They should be the same in PDFFilter::implExport and in PDFExport::PDFExport
+ */
+ImpPDFTabDialog::ImpPDFTabDialog(weld::Window* pParent, const Sequence< PropertyValue >& rFilterData,
+ const Reference< XComponent >& rxDoc)
+ : SfxTabDialogController(pParent, "filter/ui/pdfoptionsdialog.ui", "PdfOptionsDialog"),
+ mrDoc(rxDoc),
+ mpParent(pParent),
+ maConfigItem( u"Office.Common/Filter/PDF/Export/", &rFilterData ),
+ maConfigI18N( u"Office.Common/I18N/CTL/" ),
+ mbIsPresentation( false ),
+ mbIsSpreadsheet( false ),
+ mbIsWriter( false ),
+
+ mbSelectionPresent( false ),
+ mbUseCTLFont( false ),
+ mbUseLosslessCompression( true ),
+ mnQuality( 90 ),
+ mbReduceImageResolution( false ),
+ mnMaxImageResolution( 300 ),
+ mbUseTaggedPDF( false ),
+ mbUseTaggedPDFUserSelection( false ),
+ mbExportNotes( true ),
+ mbViewPDF( false ),
+ mbUseReferenceXObject( false ),
+ mbExportNotesPages( false ),
+ mbExportOnlyNotesPages( false ),
+ mbUseTransitionEffects( false ),
+ mbIsSkipEmptyPages( true ),
+ mbIsExportPlaceholders( false ),
+ mbAddStream( false ),
+ mnFormsType( 0 ),
+ mbExportFormFields( true ),
+ mbAllowDuplicateFieldNames( false ),
+ mbExportBookmarks( true ),
+ mbExportHiddenSlides ( false ),
+ mbSinglePageSheets ( false ),
+ mnOpenBookmarkLevels( -1 ),
+
+ mbHideViewerToolbar( false ),
+ mbHideViewerMenubar( false ),
+ mbHideViewerWindowControls( false ),
+ mbResizeWinToInit( false ),
+ mbCenterWindow( false ),
+ mbOpenInFullScreenMode( false ),
+ mbDisplayPDFDocumentTitle( false ),
+ mnMagnification( 0 ),
+ mnInitialView( 0 ),
+ mnZoom( 0 ),
+ mnInitialPage( 1 ),
+ mnPageLayout( 0 ),
+ mbFirstPageLeft( false ),
+
+ mbEncrypt( false ),
+ mbRestrictPermissions( false ),
+ mnPrint( 0 ),
+ mnChangesAllowed( 0 ),
+ mbCanCopyOrExtract( false ),
+ mbCanExtractForAccessibility( true ),
+
+ mbIsRangeChecked( false ),
+ msPageRange( ' ' ),
+
+ mbSelectionIsChecked( false ),
+ mbExportRelativeFsysLinks( false ),
+ mnViewPDFMode( 0 ),
+ mbConvertOOoTargets( false ),
+ mbExportBmkToPDFDestination( false ),
+
+ mbSignPDF( false )
+{
+ // check for selection
+ try
+ {
+ Reference< frame::XController > xController( Reference< frame::XModel >( rxDoc, UNO_QUERY_THROW )->getCurrentController() );
+ if( xController.is() )
+ {
+ Reference< view::XSelectionSupplier > xView( xController, UNO_QUERY );
+ if( xView.is() )
+ maSelection = xView->getSelection();
+ }
+ }
+ catch(const RuntimeException &)
+ {
+ }
+ mbSelectionPresent = maSelection.hasValue();
+ if ( mbSelectionPresent )
+ {
+ Reference< drawing::XShapes > xShapes;
+ if ( !( maSelection >>= xShapes ) ) // XShapes is always a selection
+ {
+ // even if nothing is selected in writer the selection is not empty
+ Reference< container::XIndexAccess > xIndexAccess;
+ if ( maSelection >>= xIndexAccess )
+ {
+ sal_Int32 nLen = xIndexAccess->getCount();
+ if ( !nLen )
+ mbSelectionPresent = false;
+ else if ( nLen == 1 )
+ {
+ Reference< text::XTextRange > xTextRange( xIndexAccess->getByIndex( 0 ), UNO_QUERY );
+ if ( xTextRange.is() && ( xTextRange->getString().isEmpty() ) )
+ mbSelectionPresent = false;
+ }
+ }
+ }
+ }
+
+ // check if source document is a presentation or a spreadsheet or a textdocument
+ try
+ {
+ Reference< XServiceInfo > xInfo( rxDoc, UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ if ( xInfo->supportsService( "com.sun.star.presentation.PresentationDocument" ) )
+ mbIsPresentation = true;
+ if ( xInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
+ mbIsSpreadsheet = true;
+ if ( xInfo->supportsService( "com.sun.star.text.GenericTextDocument" ) )
+ mbIsWriter = true;
+ }
+ }
+ catch(const RuntimeException &)
+ {
+ }
+
+ // get the CTL (Complex Text Layout) from general options, returns sal_True if we have a CTL font on our hands.
+ mbUseCTLFont = maConfigI18N.ReadBool( "CTLFont", false );
+
+ mbUseLosslessCompression = maConfigItem.ReadBool( "UseLosslessCompression", false );
+ mnQuality = maConfigItem.ReadInt32( "Quality", 90 );
+ mbReduceImageResolution = maConfigItem.ReadBool( "ReduceImageResolution", false );
+ mnMaxImageResolution = maConfigItem.ReadInt32( "MaxImageResolution", 300 );
+
+ // this is always the user selection, independent from the PDF/A forced selection
+ mbUseTaggedPDF = maConfigItem.ReadBool( "UseTaggedPDF", false );
+ mbUseTaggedPDFUserSelection = mbUseTaggedPDF;
+
+ mnPDFTypeSelection = maConfigItem.ReadInt32( "SelectPdfVersion", 0 );
+ mbPDFUACompliance = maConfigItem.ReadBool("PDFUACompliance", false);
+
+ if ( mbIsPresentation )
+ {
+ mbExportNotesPages = maConfigItem.ReadBool( "ExportNotesPages", false );
+ mbExportOnlyNotesPages = maConfigItem.ReadBool( "ExportOnlyNotesPages", false );
+ }
+ mbExportNotes = maConfigItem.ReadBool( "ExportNotes", false );
+ mbViewPDF = maConfigItem.ReadBool( "ViewPDFAfterExport", false );
+
+ mbExportBookmarks = maConfigItem.ReadBool( "ExportBookmarks", true );
+ if ( mbIsPresentation )
+ mbExportHiddenSlides = maConfigItem.ReadBool( "ExportHiddenSlides", false );
+ if ( mbIsSpreadsheet )
+ mbSinglePageSheets = maConfigItem.ReadBool( "SinglePageSheets", false );
+ mnOpenBookmarkLevels = maConfigItem.ReadInt32( "OpenBookmarkLevels", -1 );
+ mbUseTransitionEffects = maConfigItem.ReadBool( "UseTransitionEffects", true );
+ mbIsSkipEmptyPages = maConfigItem.ReadBool( "IsSkipEmptyPages", false );
+ mbIsExportPlaceholders = maConfigItem.ReadBool( "ExportPlaceholders", false );
+ mbAddStream = maConfigItem.ReadBool( "IsAddStream", false );
+
+ mbExportFormFields = maConfigItem.ReadBool( "ExportFormFields", true );
+ mnFormsType = maConfigItem.ReadInt32( "FormsType", 0 );
+ if ( ( mnFormsType < 0 ) || ( mnFormsType > 3 ) )
+ mnFormsType = 0;
+ mbAllowDuplicateFieldNames = maConfigItem.ReadBool( "AllowDuplicateFieldNames", false );
+
+ // prepare values for the Viewer tab page
+ mbHideViewerToolbar = maConfigItem.ReadBool( "HideViewerToolbar", false );
+ mbHideViewerMenubar = maConfigItem.ReadBool( "HideViewerMenubar", false );
+ mbHideViewerWindowControls = maConfigItem.ReadBool( "HideViewerWindowControls", false );
+ mbResizeWinToInit = maConfigItem.ReadBool( "ResizeWindowToInitialPage", false );
+ mbCenterWindow = maConfigItem.ReadBool( "CenterWindow", false );
+ mbOpenInFullScreenMode = maConfigItem.ReadBool( "OpenInFullScreenMode", false );
+ mbDisplayPDFDocumentTitle = maConfigItem.ReadBool( "DisplayPDFDocumentTitle", true );
+
+ mnInitialView = maConfigItem.ReadInt32( "InitialView", 0 );
+ mnMagnification = maConfigItem.ReadInt32( "Magnification", 0 );
+ mnZoom = maConfigItem.ReadInt32( "Zoom", 100 );
+ mnPageLayout = maConfigItem.ReadInt32( "PageLayout", 0 );
+ mbFirstPageLeft = maConfigItem.ReadBool( "FirstPageOnLeft", false );
+ mnInitialPage = maConfigItem.ReadInt32( "InitialPage", 1 );
+ if( mnInitialPage < 1 )
+ mnInitialPage = 1;
+
+ // prepare values for the security tab page
+ mnPrint = maConfigItem.ReadInt32( "Printing", 2 );
+ mnChangesAllowed = maConfigItem.ReadInt32( "Changes", 4 );
+ mbCanCopyOrExtract = maConfigItem.ReadBool( "EnableCopyingOfContent", true );
+ mbCanExtractForAccessibility = maConfigItem.ReadBool( "EnableTextAccessForAccessibilityTools", true );
+
+ // prepare values for relative links
+ mbExportRelativeFsysLinks = maConfigItem.ReadBool( "ExportLinksRelativeFsys", false );
+
+ mnViewPDFMode = maConfigItem.ReadInt32( "PDFViewSelection", 0 );
+
+ mbConvertOOoTargets = maConfigItem.ReadBool( "ConvertOOoTargetToPDFTarget", false );
+ mbExportBmkToPDFDestination = maConfigItem.ReadBool( "ExportBookmarksToPDFDestination", false );
+
+ // prepare values for digital signatures
+ mbSignPDF = maConfigItem.ReadBool( "SignPDF", false );
+
+ // queue the tab pages for later creation (created when first shown)
+ AddTabPage("general", ImpPDFTabGeneralPage::Create, nullptr );
+ AddTabPage("digitalsignatures", ImpPDFTabSigningPage::Create, nullptr);
+ AddTabPage("security", ImpPDFTabSecurityPage::Create, nullptr);
+ AddTabPage("links", ImpPDFTabLinksPage::Create, nullptr);
+ AddTabPage("userinterface", ImpPDFTabViewerPage::Create, nullptr);
+ AddTabPage("initialview", ImpPDFTabOpnFtrPage::Create, nullptr);
+
+ SetCurPageId("general");
+
+ // get the string property value (from sfx2/source/dialog/mailmodel.cxx) to overwrite the text for the Ok button
+ OUString sOkButtonText = maConfigItem.ReadString( "_OkButtonString", OUString() );
+
+ // change text on the Ok button: get the relevant string from resources, update it on the button
+ // according to the exported pdf file destination: send as e-mail or write to file?
+ if (!sOkButtonText.isEmpty())
+ GetOKButton().set_label(sOkButtonText);
+
+ GetCancelButton().connect_clicked(LINK(this, ImpPDFTabDialog, CancelHdl));
+ GetOKButton().connect_clicked(LINK(this, ImpPDFTabDialog, OkHdl));
+
+ // remove the reset button, not needed in this tabbed dialog
+ RemoveResetButton();
+}
+
+ImpPDFTabSecurityPage* ImpPDFTabDialog::getSecurityPage() const
+{
+ SfxTabPage* pSecurityPage = GetTabPage("security");
+ if (pSecurityPage)
+ {
+ return static_cast<ImpPDFTabSecurityPage*>(pSecurityPage);
+ }
+ return nullptr;
+}
+
+
+ImpPDFTabLinksPage* ImpPDFTabDialog::getLinksPage() const
+{
+ SfxTabPage* pLinksPage = GetTabPage("links");
+ if (pLinksPage)
+ {
+ return static_cast<ImpPDFTabLinksPage*>(pLinksPage);
+ }
+ return nullptr;
+}
+
+
+ImpPDFTabGeneralPage* ImpPDFTabDialog::getGeneralPage() const
+{
+ SfxTabPage* pGeneralPage = GetTabPage("general");
+ if (pGeneralPage)
+ {
+ return static_cast<ImpPDFTabGeneralPage*>(pGeneralPage);
+ }
+ return nullptr;
+}
+
+IMPL_LINK_NOARG(ImpPDFTabDialog, CancelHdl, weld::Button&, void)
+{
+ m_xDialog->response(RET_CANCEL);
+}
+
+IMPL_LINK_NOARG(ImpPDFTabDialog, OkHdl, weld::Button&, void)
+{
+ if (getGeneralPage()->IsPdfUaSelected())
+ {
+ SfxObjectShell* pShell = SfxObjectShell::GetShellFromComponent(mrDoc);
+ if (pShell)
+ {
+ sfx::AccessibilityIssueCollection aCollection = pShell->runAccessibilityCheck();
+ if (!aCollection.getIssues().empty())
+ {
+ mpAccessibilityCheckDialog = std::make_shared<svx::AccessibilityCheckDialog>(mpParent, aCollection);
+ weld::DialogController::runAsync(mpAccessibilityCheckDialog, [this](sal_Int32 retValue){
+ m_xDialog->response(retValue);
+ });
+ }
+ else
+ {
+ m_xDialog->response(RET_OK);
+ }
+ }
+ else
+ {
+ m_xDialog->response(RET_OK);
+ }
+ }
+ else
+ {
+ m_xDialog->response(RET_OK);
+ }
+}
+
+ImpPDFTabDialog::~ImpPDFTabDialog()
+{
+ maConfigItem.WriteModifiedConfig();
+ maConfigI18N.WriteModifiedConfig();
+ if (mpAccessibilityCheckDialog)
+ {
+ mpAccessibilityCheckDialog->response(RET_CANCEL);
+ }
+}
+
+void ImpPDFTabDialog::PageCreated(const OString& rId, SfxTabPage& rPage)
+{
+ if (rId == "general")
+ static_cast<ImpPDFTabGeneralPage&>(rPage).SetFilterConfigItem(this);
+ else if (rId == "userinterface")
+ {
+ static_cast<ImpPDFTabViewerPage&>(rPage).SetFilterConfigItem(this);
+ }
+ else if (rId == "initialview")
+ {
+ static_cast<ImpPDFTabOpnFtrPage&>(rPage).SetFilterConfigItem(this);
+ }
+ else if (rId == "links")
+ {
+ static_cast<ImpPDFTabLinksPage&>(rPage).SetFilterConfigItem(this);
+ }
+ else if (rId == "security")
+ {
+ static_cast<ImpPDFTabSecurityPage&>(rPage).SetFilterConfigItem(this);
+ }
+ else if (rId == "digitalsignatures")
+ {
+ static_cast<ImpPDFTabSigningPage&>(rPage).SetFilterConfigItem(this);
+ }
+}
+
+
+Sequence< PropertyValue > ImpPDFTabDialog::GetFilterData()
+{
+ // updating the FilterData sequence and storing FilterData to configuration
+ if (ImpPDFTabGeneralPage* pPage = static_cast<ImpPDFTabGeneralPage*>(GetTabPage("general")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabViewerPage* pPage = static_cast<ImpPDFTabViewerPage*>(GetTabPage("userinterface")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabOpnFtrPage* pPage = static_cast<ImpPDFTabOpnFtrPage*>(GetTabPage("initialview")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabLinksPage* pPage = static_cast<ImpPDFTabLinksPage*>(GetTabPage("links")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabSecurityPage* pPage = static_cast<ImpPDFTabSecurityPage*>( GetTabPage("security")))
+ pPage->GetFilterConfigItem(this);
+ if (ImpPDFTabSigningPage* pPage = static_cast<ImpPDFTabSigningPage*>(GetTabPage("digitalsignatures")))
+ pPage->GetFilterConfigItem(this);
+
+ // prepare the items to be returned
+ maConfigItem.WriteBool( "UseLosslessCompression", mbUseLosslessCompression );
+ maConfigItem.WriteInt32("Quality", mnQuality );
+ maConfigItem.WriteBool( "ReduceImageResolution", mbReduceImageResolution );
+ maConfigItem.WriteInt32("MaxImageResolution", mnMaxImageResolution );
+
+ // always write the user selection, never the overridden value
+ const bool bIsPDFUA = mbPDFUACompliance;
+ const bool bIsPDFA = (1 == mnPDFTypeSelection) || (2 == mnPDFTypeSelection) || (3 == mnPDFTypeSelection);
+ const bool bUserSelectionTags = bIsPDFA || bIsPDFUA;
+ maConfigItem.WriteBool("UseTaggedPDF", bUserSelectionTags ? mbUseTaggedPDFUserSelection : mbUseTaggedPDF);
+ maConfigItem.WriteInt32("SelectPdfVersion", mnPDFTypeSelection );
+ maConfigItem.WriteBool("PDFUACompliance", mbPDFUACompliance);
+
+ if ( mbIsPresentation )
+ {
+ maConfigItem.WriteBool( "ExportNotesPages", mbExportNotesPages );
+ maConfigItem.WriteBool( "ExportOnlyNotesPages", mbExportOnlyNotesPages );
+ }
+ maConfigItem.WriteBool( "ExportNotes", mbExportNotes );
+ maConfigItem.WriteBool( "ViewPDFAfterExport", mbViewPDF );
+
+ maConfigItem.WriteBool( "ExportBookmarks", mbExportBookmarks );
+ if ( mbIsPresentation )
+ maConfigItem.WriteBool( "ExportHiddenSlides", mbExportHiddenSlides );
+ if ( mbIsSpreadsheet )
+ maConfigItem.WriteBool( "SinglePageSheets", mbSinglePageSheets );
+ maConfigItem.WriteBool( "UseTransitionEffects", mbUseTransitionEffects );
+ maConfigItem.WriteBool( "IsSkipEmptyPages", mbIsSkipEmptyPages );
+ maConfigItem.WriteBool( "ExportPlaceholders", mbIsExportPlaceholders );
+ maConfigItem.WriteBool( "IsAddStream", mbAddStream );
+
+ /*
+ * FIXME: the entries are only implicitly defined by the resource file. Should there
+ * ever be an additional form submit format this could get invalid.
+ */
+ maConfigItem.WriteInt32( "FormsType", mnFormsType );
+ maConfigItem.WriteBool( "ExportFormFields", mbExportFormFields );
+ maConfigItem.WriteBool( "AllowDuplicateFieldNames", mbAllowDuplicateFieldNames );
+
+ maConfigItem.WriteBool( "HideViewerToolbar", mbHideViewerToolbar );
+ maConfigItem.WriteBool( "HideViewerMenubar", mbHideViewerMenubar );
+ maConfigItem.WriteBool( "HideViewerWindowControls", mbHideViewerWindowControls );
+ maConfigItem.WriteBool( "ResizeWindowToInitialPage", mbResizeWinToInit );
+ maConfigItem.WriteBool( "CenterWindow", mbCenterWindow );
+ maConfigItem.WriteBool( "OpenInFullScreenMode", mbOpenInFullScreenMode );
+ maConfigItem.WriteBool( "DisplayPDFDocumentTitle", mbDisplayPDFDocumentTitle );
+ maConfigItem.WriteInt32( "InitialView", mnInitialView );
+ maConfigItem.WriteInt32( "Magnification", mnMagnification);
+ maConfigItem.WriteInt32( "Zoom", mnZoom );
+ maConfigItem.WriteInt32( "InitialPage", mnInitialPage );
+ maConfigItem.WriteInt32( "PageLayout", mnPageLayout );
+ maConfigItem.WriteBool( "FirstPageOnLeft", mbFirstPageLeft );
+ maConfigItem.WriteInt32( "OpenBookmarkLevels", mnOpenBookmarkLevels );
+
+ maConfigItem.WriteBool( "ExportLinksRelativeFsys", mbExportRelativeFsysLinks );
+ maConfigItem.WriteInt32("PDFViewSelection", mnViewPDFMode );
+ maConfigItem.WriteBool( "ConvertOOoTargetToPDFTarget", mbConvertOOoTargets );
+ maConfigItem.WriteBool( "ExportBookmarksToPDFDestination", mbExportBmkToPDFDestination );
+
+ maConfigItem.WriteBool( "SignPDF", mbSignPDF );
+
+ maConfigItem.WriteInt32( "Printing", mnPrint );
+ maConfigItem.WriteInt32( "Changes", mnChangesAllowed );
+ maConfigItem.WriteBool( "EnableCopyingOfContent", mbCanCopyOrExtract );
+ maConfigItem.WriteBool( "EnableTextAccessForAccessibilityTools", mbCanExtractForAccessibility );
+
+ std::vector<beans::PropertyValue> aRet
+ {
+ comphelper::makePropertyValue("Watermark", maWatermarkText),
+ comphelper::makePropertyValue("EncryptFile", mbEncrypt),
+ comphelper::makePropertyValue("PreparedPasswords", mxPreparedPasswords),
+ comphelper::makePropertyValue("RestrictPermissions", mbRestrictPermissions),
+ comphelper::makePropertyValue("PreparedPermissionPassword", maPreparedOwnerPassword)
+ };
+ if( mbIsRangeChecked )
+ aRet.push_back(comphelper::makePropertyValue("PageRange", msPageRange));
+ else if( mbSelectionIsChecked )
+ aRet.push_back(comphelper::makePropertyValue("Selection", maSelection));
+
+ aRet.push_back(comphelper::makePropertyValue("SignatureLocation", msSignLocation));
+ aRet.push_back(comphelper::makePropertyValue("SignatureReason", msSignReason));
+ aRet.push_back(comphelper::makePropertyValue("SignatureContactInfo", msSignContact));
+ aRet.push_back(comphelper::makePropertyValue("SignaturePassword", msSignPassword));
+ aRet.push_back(comphelper::makePropertyValue("SignatureCertificate", maSignCertificate));
+ aRet.push_back(comphelper::makePropertyValue("SignatureTSA", msSignTSA));
+ aRet.push_back(comphelper::makePropertyValue("UseReferenceXObject", mbUseReferenceXObject));
+
+ return comphelper::concatSequences(maConfigItem.GetFilterData(), comphelper::containerToSequence(aRet));
+}
+
+
+ImpPDFTabGeneralPage::ImpPDFTabGeneralPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdfgeneralpage.ui", "PdfGeneralPage", &rCoreSet)
+ , mbUseTaggedPDFUserSelection(false)
+ , mbIsPresentation(false)
+ , mbIsSpreadsheet(false)
+ , mbIsWriter(false)
+ , mpParent(nullptr)
+ , mxRbAll(m_xBuilder->weld_radio_button("all"))
+ , mxRbRange(m_xBuilder->weld_radio_button("range"))
+ , mxRbSelection(m_xBuilder->weld_radio_button("selection"))
+ , mxEdPages(m_xBuilder->weld_entry("pages"))
+ , mxSelectedSheets(m_xBuilder->weld_label("selectedsheets"))
+ , mxRbLosslessCompression(m_xBuilder->weld_radio_button("losslesscompress"))
+ , mxRbJPEGCompression(m_xBuilder->weld_radio_button("jpegcompress"))
+ , mxQualityFrame(m_xBuilder->weld_widget("qualityframe"))
+ , mxNfQuality(m_xBuilder->weld_metric_spin_button("quality", FieldUnit::PERCENT))
+ , mxCbReduceImageResolution(m_xBuilder->weld_check_button("reduceresolution"))
+ , mxCoReduceImageResolution(m_xBuilder->weld_combo_box("resolution"))
+ , mxCbPDFA(m_xBuilder->weld_check_button("pdfa"))
+ , mxCbPDFUA(m_xBuilder->weld_check_button("pdfua"))
+ , mxRbPDFAVersion(m_xBuilder->weld_combo_box("pdfaversion"))
+ , mxCbTaggedPDF(m_xBuilder->weld_check_button("tagged"))
+ , mxCbExportFormFields(m_xBuilder->weld_check_button("forms"))
+ , mxFormsFrame(m_xBuilder->weld_widget("formsframe"))
+ , mxLbFormsFormat(m_xBuilder->weld_combo_box("format"))
+ , mxCbAllowDuplicateFieldNames(m_xBuilder->weld_check_button("allowdups"))
+ , mxCbExportBookmarks(m_xBuilder->weld_check_button("bookmarks"))
+ , mxCbExportHiddenSlides(m_xBuilder->weld_check_button("hiddenpages"))
+ , mxCbSinglePageSheets(m_xBuilder->weld_check_button("singlepagesheets"))
+ , mxCbExportNotes(m_xBuilder->weld_check_button("comments"))
+ , mxCbViewPDF(m_xBuilder->weld_check_button("viewpdf"))
+ , mxCbUseReferenceXObject(m_xBuilder->weld_check_button("usereferencexobject"))
+ , mxCbExportNotesPages(m_xBuilder->weld_check_button("notes"))
+ , mxCbExportOnlyNotesPages(m_xBuilder->weld_check_button("onlynotes"))
+ , mxCbExportEmptyPages(m_xBuilder->weld_check_button("emptypages"))
+ , mxCbExportPlaceholders(m_xBuilder->weld_check_button("exportplaceholders"))
+ , mxCbAddStream(m_xBuilder->weld_check_button("embed"))
+ , mxCbWatermark(m_xBuilder->weld_check_button("watermark"))
+ , mxFtWatermark(m_xBuilder->weld_label("watermarklabel"))
+ , mxEdWatermark(m_xBuilder->weld_entry("watermarkentry"))
+ , mxSlidesFt(m_xBuilder->weld_label("slides"))
+ , mxSheetsFt(m_xBuilder->weld_label("selectedsheets"))
+{
+}
+
+ImpPDFTabGeneralPage::~ImpPDFTabGeneralPage()
+{
+}
+
+void ImpPDFTabGeneralPage::SetFilterConfigItem(ImpPDFTabDialog* pParent)
+{
+ mpParent = pParent;
+
+ // init this class data
+ mxRbRange->connect_toggled( LINK( this, ImpPDFTabGeneralPage, TogglePagesHdl ) );
+
+ mxRbAll->set_active(true);
+ mxRbAll->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleAllHdl ) );
+ TogglePagesHdl();
+
+ const bool bSelectionPresent = pParent->mbSelectionPresent;
+ mxRbSelection->set_sensitive( bSelectionPresent );
+ if ( bSelectionPresent )
+ mxRbSelection->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleSelectionHdl ) );
+ mbIsPresentation = pParent->mbIsPresentation;
+ mbIsWriter = pParent->mbIsWriter;
+ mbIsSpreadsheet = pParent->mbIsSpreadsheet;
+
+ mxCbExportEmptyPages->set_sensitive( mbIsWriter );
+ mxCbExportPlaceholders->set_sensitive( mbIsWriter );
+
+ mxRbLosslessCompression->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleCompressionHdl ) );
+ const bool bUseLosslessCompression = pParent->mbUseLosslessCompression;
+ if ( bUseLosslessCompression )
+ mxRbLosslessCompression->set_active(true);
+ else
+ mxRbJPEGCompression->set_active(true);
+
+ mxNfQuality->set_value( pParent->mnQuality, FieldUnit::PERCENT );
+ mxQualityFrame->set_sensitive(!bUseLosslessCompression);
+
+ mxCbReduceImageResolution->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleReduceImageResolutionHdl));
+ const bool bReduceImageResolution = pParent->mbReduceImageResolution;
+ mxCbReduceImageResolution->set_active( bReduceImageResolution );
+ OUString aStrRes = OUString::number( pParent->mnMaxImageResolution ) + " DPI";
+ mxCoReduceImageResolution->set_entry_text(aStrRes);
+ mxCoReduceImageResolution->set_sensitive( bReduceImageResolution );
+ mxCbWatermark->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleWatermarkHdl ) );
+ mxFtWatermark->set_sensitive(false );
+ mxEdWatermark->set_sensitive( false );
+ mxCbPDFA->connect_toggled(LINK(this, ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle));
+
+ const bool bIsPDFA = (pParent->mnPDFTypeSelection>=1) && (pParent->mnPDFTypeSelection <= 3);
+ mxCbPDFA->set_active(bIsPDFA);
+ switch( pParent->mnPDFTypeSelection )
+ {
+ case 1: // PDF/A-1
+ mxRbPDFAVersion->set_active_id("1");
+ break;
+ case 2: // PDF/A-2
+ mxRbPDFAVersion->set_active_id("2");
+ break;
+ case 3: // PDF/A-3
+ default: // PDF 1.x
+ mxRbPDFAVersion->set_active_id("3");
+ break;
+ }
+
+ const bool bIsPDFUA = pParent->mbPDFUACompliance;
+ mxCbPDFUA->set_active(bIsPDFUA);
+ mxCbPDFUA->connect_toggled(LINK(this, ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle));
+
+ // the TogglePDFVersionOrUniversalAccessibilityHandle handler will read or write the *UserSelection based
+ // on the mxCbPDFA (= bIsPDFA) state, so we have to prepare the correct input state.
+ if (bIsPDFA || bIsPDFUA)
+ mxCbTaggedPDF->set_active(pParent->mbUseTaggedPDFUserSelection);
+ else
+ mbUseTaggedPDFUserSelection = pParent->mbUseTaggedPDFUserSelection;
+ TogglePDFVersionOrUniversalAccessibilityHandle(*mxCbPDFA);
+
+ mxCbExportFormFields->set_active(pParent->mbExportFormFields);
+ mxCbExportFormFields->connect_toggled( LINK( this, ImpPDFTabGeneralPage, ToggleExportFormFieldsHdl ) );
+
+ mxLbFormsFormat->set_active(static_cast<sal_uInt16>(pParent->mnFormsType));
+ mxCbAllowDuplicateFieldNames->set_active( pParent->mbAllowDuplicateFieldNames );
+ mxFormsFrame->set_sensitive(pParent->mbExportFormFields);
+
+ mxCbExportBookmarks->set_active( pParent->mbExportBookmarks );
+
+ mxCbExportNotes->set_active( pParent->mbExportNotes );
+ mxCbViewPDF->set_active( pParent->mbViewPDF);
+
+ if ( mbIsPresentation )
+ {
+ mxRbRange->set_label(mxSlidesFt->get_label());
+ mxCbExportNotesPages->show();
+ mxCbExportNotesPages->set_active(pParent->mbExportNotesPages);
+ mxCbExportNotesPages->connect_toggled( LINK(this, ImpPDFTabGeneralPage, ToggleExportNotesPagesHdl ) );
+ mxCbExportOnlyNotesPages->show();
+ mxCbExportOnlyNotesPages->set_active(pParent->mbExportOnlyNotesPages);
+ // tdf#116473 Initially enable Export only note pages option depending on the checked state of Export notes pages option
+ mxCbExportOnlyNotesPages->set_sensitive(mxCbExportNotesPages->get_active());
+ mxCbExportHiddenSlides->show();
+ mxCbExportHiddenSlides->set_active(pParent->mbExportHiddenSlides);
+ }
+ else
+ {
+ mxCbExportNotesPages->hide();
+ mxCbExportNotesPages->set_active(false);
+ mxCbExportOnlyNotesPages->hide();
+ mxCbExportOnlyNotesPages->set_active(false);
+ mxCbExportHiddenSlides->hide();
+ mxCbExportHiddenSlides->set_active(false);
+ }
+
+ if( mbIsSpreadsheet )
+ {
+ mxRbSelection->set_label(mxSheetsFt->get_label());
+ // tdf#105965 Make Selection/Selected sheets the default PDF export range setting for spreadsheets
+ mxRbSelection->set_active(true);
+
+ mxCbSinglePageSheets->show();
+ mxCbSinglePageSheets->set_active(pParent->mbSinglePageSheets);
+ }
+ else
+ {
+ mxCbSinglePageSheets->hide();
+ mxCbSinglePageSheets->set_active(false);
+ }
+
+ mxCbExportPlaceholders->set_visible(mbIsWriter);
+ if( mbIsWriter )
+ {
+ // tdf#54908 Make selection active if there is a selection in Writer's version
+ mxRbSelection->set_active( bSelectionPresent );
+ }
+ else
+ {
+ mxCbExportPlaceholders->set_active(false);
+ }
+ mxCbExportEmptyPages->set_active(!pParent->mbIsSkipEmptyPages);
+ mxCbExportPlaceholders->set_active(pParent->mbIsExportPlaceholders);
+
+ mxCbAddStream->show();
+ mxCbAddStream->set_active(pParent->mbAddStream);
+
+ mxCbAddStream->connect_toggled(LINK(this, ImpPDFTabGeneralPage, ToggleAddStreamHdl));
+ ToggleAddStreamHdl(*mxCbAddStream); // init addstream dependencies
+}
+
+void ImpPDFTabGeneralPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ // updating the FilterData sequence and storing FilterData to configuration
+ pParent->mbUseLosslessCompression = mxRbLosslessCompression->get_active();
+ pParent->mnQuality = static_cast<sal_Int32>(mxNfQuality->get_value(FieldUnit::PERCENT));
+ pParent->mbReduceImageResolution = mxCbReduceImageResolution->get_active();
+ pParent->mnMaxImageResolution = mxCoReduceImageResolution->get_active_text().toInt32();
+ pParent->mbExportNotes = mxCbExportNotes->get_active();
+ pParent->mbViewPDF = mxCbViewPDF->get_active();
+ pParent->mbUseReferenceXObject = mxCbUseReferenceXObject->get_active();
+ if ( mbIsPresentation )
+ {
+ pParent->mbExportNotesPages = mxCbExportNotesPages->get_active();
+ pParent->mbExportOnlyNotesPages = mxCbExportOnlyNotesPages->get_active();
+ }
+ pParent->mbExportBookmarks = mxCbExportBookmarks->get_active();
+ if ( mbIsPresentation )
+ pParent->mbExportHiddenSlides = mxCbExportHiddenSlides->get_active();
+
+ if (mbIsSpreadsheet)
+ pParent->mbSinglePageSheets = mxCbSinglePageSheets->get_active();
+
+ pParent->mbIsSkipEmptyPages = !mxCbExportEmptyPages->get_active();
+ pParent->mbIsExportPlaceholders = mxCbExportPlaceholders->get_active();
+ pParent->mbAddStream = mxCbAddStream->get_visible() && mxCbAddStream->get_active();
+
+ pParent->mbIsRangeChecked = false;
+ if( mxRbRange->get_active() )
+ {
+ pParent->mbIsRangeChecked = true;
+ pParent->msPageRange = mxEdPages->get_text(); //FIXME all right on other languages ?
+ }
+ else if( mxRbSelection->get_active() )
+ {
+ pParent->mbSelectionIsChecked = mxRbSelection->get_active();
+ }
+
+ pParent->mnPDFTypeSelection = 0;
+ pParent->mbUseTaggedPDF = mxCbTaggedPDF->get_active();
+
+ const bool bIsPDFA = mxCbPDFA->get_active();
+ const bool bIsPDFUA = mxCbPDFUA->get_active();
+
+ if (bIsPDFA)
+ {
+ pParent->mnPDFTypeSelection = 3;
+ OUString currentPDFAMode = mxRbPDFAVersion->get_active_id();
+ if( currentPDFAMode == "1" )
+ pParent->mnPDFTypeSelection = 1;
+ else if(currentPDFAMode == "2")
+ pParent->mnPDFTypeSelection = 2;
+ }
+
+ pParent->mbPDFUACompliance = bIsPDFUA;
+
+ if (!bIsPDFA && !bIsPDFUA)
+ mbUseTaggedPDFUserSelection = pParent->mbUseTaggedPDF;
+
+ pParent->mbUseTaggedPDFUserSelection = mbUseTaggedPDFUserSelection;
+ pParent->mbExportFormFields = mxCbExportFormFields->get_active();
+
+ if( mxCbWatermark->get_active() )
+ pParent->maWatermarkText = mxEdWatermark->get_text();
+
+ /*
+ * FIXME: the entries are only implicitly defined by the resource file. Should there
+ * ever be an additional form submit format this could get invalid.
+ */
+ pParent->mnFormsType = mxLbFormsFormat->get_active();
+ pParent->mbAllowDuplicateFieldNames = mxCbAllowDuplicateFieldNames->get_active();
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabGeneralPage::Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabGeneralPage>(pPage, pController, *rAttrSet);
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleAllHdl, weld::Toggleable&, void)
+{
+ EnableExportNotesPages();
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePagesHdl, weld::Toggleable&, void)
+{
+ TogglePagesHdl();
+ EnableExportNotesPages();
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleSelectionHdl, weld::Toggleable&, void)
+{
+ EnableExportNotesPages();
+}
+
+void ImpPDFTabGeneralPage::TogglePagesHdl()
+{
+ mxEdPages->set_sensitive( mxRbRange->get_active() );
+ if (mxRbRange->get_active())
+ mxEdPages->grab_focus();
+}
+
+void ImpPDFTabGeneralPage::EnableExportNotesPages()
+{
+ if ( mbIsPresentation )
+ {
+ mxCbExportNotesPages->set_sensitive( !mxRbSelection->get_active() );
+ mxCbExportOnlyNotesPages->set_sensitive( !mxRbSelection->get_active() && mxCbExportNotesPages->get_active() );
+ }
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleExportFormFieldsHdl, weld::Toggleable&, void)
+{
+ mxFormsFrame->set_sensitive(mxCbExportFormFields->get_active());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleExportNotesPagesHdl, weld::Toggleable&, void)
+{
+ mxCbExportOnlyNotesPages->set_sensitive(mxCbExportNotesPages->get_active());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleCompressionHdl, weld::Toggleable&, void)
+{
+ mxQualityFrame->set_sensitive(mxRbJPEGCompression->get_active());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleReduceImageResolutionHdl, weld::Toggleable&, void)
+{
+ mxCoReduceImageResolution->set_sensitive(mxCbReduceImageResolution->get_active());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleWatermarkHdl, weld::Toggleable&, void)
+{
+ mxEdWatermark->set_sensitive(mxCbWatermark->get_active());
+ mxFtWatermark->set_sensitive(mxCbWatermark->get_active());
+ if (mxCbWatermark->get_active())
+ mxEdWatermark->grab_focus();
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, ToggleAddStreamHdl, weld::Toggleable&, void)
+{
+ if (!mxCbAddStream->get_visible())
+ return;
+
+ if( mxCbAddStream->get_active() )
+ {
+ mxRbAll->set_active(true);
+ mxRbRange->set_sensitive( false );
+ mxRbSelection->set_sensitive( false );
+ mxEdPages->set_sensitive( false );
+ mxRbAll->set_sensitive( false );
+ }
+ else
+ {
+ mxRbAll->set_sensitive(true);
+ mxRbRange->set_sensitive(true);
+ mxRbSelection->set_sensitive(true);
+ }
+}
+
+IMPL_LINK_NOARG(ImpPDFTabGeneralPage, TogglePDFVersionOrUniversalAccessibilityHandle, weld::Toggleable&, void)
+{
+ const bool bIsPDFA = mxCbPDFA->get_active();
+ const bool bIsPDFUA = mxCbPDFUA->get_active();
+
+ // set the security page status (and its controls as well)
+ ImpPDFTabSecurityPage* pSecPage = mpParent ? mpParent->getSecurityPage() : nullptr;
+ if (pSecPage)
+ pSecPage->ImplPDFASecurityControl(!bIsPDFA);
+
+ mxCbTaggedPDF->set_sensitive(!bIsPDFA && !bIsPDFUA);
+ mxRbPDFAVersion->set_sensitive(bIsPDFA);
+
+ if (bIsPDFA || bIsPDFUA)
+ {
+ // store the users selection of subordinate controls and set required PDF/A values
+ mbUseTaggedPDFUserSelection = mxCbTaggedPDF->get_active();
+ mxCbTaggedPDF->set_active(true);
+
+ // if a password was set, inform the user that this will not be used
+ if (pSecPage && pSecPage->hasPassword())
+ {
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xContainer.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ PDFFilterResId(STR_WARN_PASSWORD_PDFA)));
+ xBox->run();
+ }
+ }
+ else
+ {
+ // restore the users values of subordinate controls
+ mxCbTaggedPDF->set_active(mbUseTaggedPDFUserSelection);
+ }
+
+ // PDF/A doesn't allow launch action, so enable/disable the selection on the Link page
+ ImpPDFTabLinksPage* pLinksPage = mpParent ? mpParent->getLinksPage() : nullptr;
+ if (pLinksPage)
+ pLinksPage->ImplPDFALinkControl(!bIsPDFA);
+}
+
+/// The option features tab page
+ImpPDFTabOpnFtrPage::ImpPDFTabOpnFtrPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdfviewpage.ui", "PdfViewPage", &rCoreSet)
+ , mbUseCTLFont(false)
+ , mxRbOpnPageOnly(m_xBuilder->weld_radio_button("pageonly"))
+ , mxRbOpnOutline(m_xBuilder->weld_radio_button("outline"))
+ , mxRbOpnThumbs(m_xBuilder->weld_radio_button("thumbs"))
+ , mxNumInitialPage(m_xBuilder->weld_spin_button("page"))
+ , mxRbMagnDefault(m_xBuilder->weld_radio_button("fitdefault"))
+ , mxRbMagnFitWin(m_xBuilder->weld_radio_button("fitwin"))
+ , mxRbMagnFitWidth(m_xBuilder->weld_radio_button("fitwidth"))
+ , mxRbMagnFitVisible(m_xBuilder->weld_radio_button("fitvis"))
+ , mxRbMagnZoom(m_xBuilder->weld_radio_button("fitzoom"))
+ , mxNumZoom(m_xBuilder->weld_spin_button("zoom"))
+ , mxRbPgLyDefault(m_xBuilder->weld_radio_button("defaultlayout"))
+ , mxRbPgLySinglePage(m_xBuilder->weld_radio_button("singlelayout"))
+ , mxRbPgLyContinue(m_xBuilder->weld_radio_button("contlayout"))
+ , mxRbPgLyContinueFacing(m_xBuilder->weld_radio_button("contfacinglayout"))
+ , mxCbPgLyFirstOnLeft(m_xBuilder->weld_check_button("firstonleft"))
+{
+ mxRbMagnDefault->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+ mxRbMagnFitWin->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+ mxRbMagnFitWidth->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+ mxRbMagnFitVisible->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+ mxRbMagnZoom->connect_toggled( LINK( this, ImpPDFTabOpnFtrPage, ToggleRbMagnHdl ) );
+}
+
+ImpPDFTabOpnFtrPage::~ImpPDFTabOpnFtrPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabOpnFtrPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabOpnFtrPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabOpnFtrPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ pParent->mnInitialView = 0;
+ if( mxRbOpnOutline->get_active() )
+ pParent->mnInitialView = 1;
+ else if( mxRbOpnThumbs->get_active() )
+ pParent->mnInitialView = 2;
+
+ pParent->mnMagnification = 0;
+ if( mxRbMagnFitWin->get_active() )
+ pParent->mnMagnification = 1;
+ else if( mxRbMagnFitWidth->get_active() )
+ pParent->mnMagnification = 2;
+ else if( mxRbMagnFitVisible->get_active() )
+ pParent->mnMagnification = 3;
+ else if( mxRbMagnZoom->get_active() )
+ {
+ pParent->mnMagnification = 4;
+ pParent->mnZoom = mxNumZoom->get_value();
+ }
+
+ pParent->mnInitialPage = mxNumInitialPage->get_value();
+
+ pParent->mnPageLayout = 0;
+ if( mxRbPgLySinglePage->get_active() )
+ pParent->mnPageLayout = 1;
+ else if( mxRbPgLyContinue->get_active() )
+ pParent->mnPageLayout = 2;
+ else if( mxRbPgLyContinueFacing->get_active() )
+ pParent->mnPageLayout = 3;
+
+ pParent->mbFirstPageLeft = mbUseCTLFont && mxCbPgLyFirstOnLeft->get_active();
+}
+
+void ImpPDFTabOpnFtrPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ mbUseCTLFont = pParent->mbUseCTLFont;
+ switch( pParent->mnPageLayout )
+ {
+ default:
+ case 0:
+ mxRbPgLyDefault->set_active(true);
+ break;
+ case 1:
+ mxRbPgLySinglePage->set_active(true);
+ break;
+ case 2:
+ mxRbPgLyContinue->set_active(true);
+ break;
+ case 3:
+ mxRbPgLyContinueFacing->set_active(true);
+ break;
+ }
+
+ switch( pParent->mnInitialView )
+ {
+ default:
+ case 0:
+ mxRbOpnPageOnly->set_active(true);
+ break;
+ case 1:
+ mxRbOpnOutline->set_active(true);
+ break;
+ case 2:
+ mxRbOpnThumbs->set_active(true);
+ break;
+ }
+
+ switch( pParent->mnMagnification )
+ {
+ default:
+ case 0:
+ mxRbMagnDefault->set_active(true);
+ mxNumZoom->set_sensitive(false);
+ break;
+ case 1:
+ mxRbMagnFitWin->set_active(true);
+ mxNumZoom->set_sensitive(false);
+ break;
+ case 2:
+ mxRbMagnFitWidth->set_active(true);
+ mxNumZoom->set_sensitive(false);
+ break;
+ case 3:
+ mxRbMagnFitVisible->set_active(true);
+ mxNumZoom->set_sensitive(false);
+ break;
+ case 4:
+ mxRbMagnZoom->set_active(true);
+ mxNumZoom->set_sensitive(true);
+ break;
+ }
+
+ mxNumZoom->set_value(pParent->mnZoom);
+ mxNumInitialPage->set_value(pParent->mnInitialPage);
+
+ if (!mbUseCTLFont)
+ mxCbPgLyFirstOnLeft->hide();
+ else
+ {
+ mxRbPgLyContinueFacing->connect_toggled(LINK(this, ImpPDFTabOpnFtrPage, ToggleRbPgLyContinueFacingHdl));
+ mxCbPgLyFirstOnLeft->set_active(pParent->mbFirstPageLeft);
+ ToggleRbPgLyContinueFacingHdl();
+ }
+}
+
+IMPL_LINK_NOARG(ImpPDFTabOpnFtrPage, ToggleRbPgLyContinueFacingHdl, weld::Toggleable&, void)
+{
+ ToggleRbPgLyContinueFacingHdl();
+}
+
+void ImpPDFTabOpnFtrPage::ToggleRbPgLyContinueFacingHdl()
+{
+ mxCbPgLyFirstOnLeft->set_sensitive(mxRbPgLyContinueFacing->get_active());
+}
+
+IMPL_LINK_NOARG( ImpPDFTabOpnFtrPage, ToggleRbMagnHdl, weld::Toggleable&, void )
+{
+ mxNumZoom->set_sensitive(mxRbMagnZoom->get_active());
+}
+
+/// The Viewer preferences tab page
+ImpPDFTabViewerPage::ImpPDFTabViewerPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet )
+ : SfxTabPage(pPage, pController, "filter/ui/pdfuserinterfacepage.ui", "PdfUserInterfacePage", &rCoreSet)
+ , mbIsPresentation(false)
+ , m_xCbResWinInit(m_xBuilder->weld_check_button("resize"))
+ , m_xCbCenterWindow(m_xBuilder->weld_check_button("center"))
+ , m_xCbOpenFullScreen(m_xBuilder->weld_check_button("open"))
+ , m_xCbDispDocTitle(m_xBuilder->weld_check_button("display"))
+ , m_xCbHideViewerMenubar(m_xBuilder->weld_check_button("menubar"))
+ , m_xCbHideViewerToolbar(m_xBuilder->weld_check_button("toolbar"))
+ , m_xCbHideViewerWindowControls(m_xBuilder->weld_check_button("window"))
+ , m_xCbTransitionEffects(m_xBuilder->weld_check_button("effects"))
+ , m_xRbAllBookmarkLevels(m_xBuilder->weld_radio_button("allbookmarks"))
+ , m_xRbVisibleBookmarkLevels(m_xBuilder->weld_radio_button("visiblebookmark"))
+ , m_xNumBookmarkLevels(m_xBuilder->weld_spin_button("visiblelevel"))
+{
+ m_xRbAllBookmarkLevels->connect_toggled(LINK(this, ImpPDFTabViewerPage, ToggleRbBookmarksHdl));
+ m_xRbVisibleBookmarkLevels->connect_toggled(LINK(this, ImpPDFTabViewerPage, ToggleRbBookmarksHdl));
+}
+
+ImpPDFTabViewerPage::~ImpPDFTabViewerPage()
+{
+}
+
+IMPL_LINK_NOARG( ImpPDFTabViewerPage, ToggleRbBookmarksHdl, weld::Toggleable&, void )
+{
+ m_xNumBookmarkLevels->set_sensitive(m_xRbVisibleBookmarkLevels->get_active());
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabViewerPage::Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabViewerPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabViewerPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ pParent->mbHideViewerMenubar = m_xCbHideViewerMenubar->get_active();
+ pParent->mbHideViewerToolbar = m_xCbHideViewerToolbar->get_active();
+ pParent->mbHideViewerWindowControls = m_xCbHideViewerWindowControls->get_active();
+ pParent->mbResizeWinToInit = m_xCbResWinInit->get_active();
+ pParent->mbOpenInFullScreenMode = m_xCbOpenFullScreen->get_active();
+ pParent->mbCenterWindow = m_xCbCenterWindow->get_active();
+ pParent->mbDisplayPDFDocumentTitle = m_xCbDispDocTitle->get_active();
+ pParent->mbUseTransitionEffects = m_xCbTransitionEffects->get_active();
+ pParent->mnOpenBookmarkLevels = m_xRbAllBookmarkLevels->get_active() ?
+ -1 : static_cast<sal_Int32>(m_xNumBookmarkLevels->get_value());
+}
+
+void ImpPDFTabViewerPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ m_xCbHideViewerMenubar->set_active( pParent->mbHideViewerMenubar );
+ m_xCbHideViewerToolbar->set_active( pParent->mbHideViewerToolbar );
+ m_xCbHideViewerWindowControls->set_active( pParent->mbHideViewerWindowControls );
+
+ m_xCbResWinInit->set_active( pParent->mbResizeWinToInit );
+ m_xCbOpenFullScreen->set_active( pParent->mbOpenInFullScreenMode );
+ m_xCbCenterWindow->set_active( pParent->mbCenterWindow );
+ m_xCbDispDocTitle->set_active( pParent->mbDisplayPDFDocumentTitle );
+ mbIsPresentation = pParent->mbIsPresentation;
+ m_xCbTransitionEffects->set_active( pParent->mbUseTransitionEffects );
+ m_xCbTransitionEffects->set_sensitive( mbIsPresentation );
+ if( pParent->mnOpenBookmarkLevels < 0 )
+ {
+ m_xRbAllBookmarkLevels->set_active(true);
+ m_xNumBookmarkLevels->set_sensitive( false );
+ }
+ else
+ {
+ m_xRbVisibleBookmarkLevels->set_active(true);
+ m_xNumBookmarkLevels->set_sensitive(true);
+ m_xNumBookmarkLevels->set_value(pParent->mnOpenBookmarkLevels);
+ }
+}
+
+/// The Security preferences tab page
+ImpPDFTabSecurityPage::ImpPDFTabSecurityPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& i_rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdfsecuritypage.ui", "PdfSecurityPage", &i_rCoreSet)
+ , msUserPwdTitle( PDFFilterResId( STR_PDF_EXPORT_UDPWD ) )
+ , mbHaveOwnerPassword( false )
+ , mbHaveUserPassword( false )
+ , msOwnerPwdTitle( PDFFilterResId( STR_PDF_EXPORT_ODPWD ) )
+ , mxPbSetPwd(m_xBuilder->weld_button("setpassword"))
+ , mxUserPwdSet(m_xBuilder->weld_widget("userpwdset"))
+ , mxUserPwdUnset(m_xBuilder->weld_widget("userpwdunset"))
+ , mxUserPwdPdfa(m_xBuilder->weld_widget("userpwdpdfa"))
+ , mxOwnerPwdSet(m_xBuilder->weld_widget("ownerpwdset"))
+ , mxOwnerPwdUnset(m_xBuilder->weld_widget("ownerpwdunset"))
+ , mxOwnerPwdPdfa(m_xBuilder->weld_widget("ownerpwdpdfa"))
+ , mxPrintPermissions(m_xBuilder->weld_widget("printing"))
+ , mxRbPrintNone(m_xBuilder->weld_radio_button("printnone"))
+ , mxRbPrintLowRes(m_xBuilder->weld_radio_button("printlow"))
+ , mxRbPrintHighRes(m_xBuilder->weld_radio_button("printhigh"))
+ , mxChangesAllowed(m_xBuilder->weld_widget("changes"))
+ , mxRbChangesNone(m_xBuilder->weld_radio_button("changenone"))
+ , mxRbChangesInsDel(m_xBuilder->weld_radio_button("changeinsdel"))
+ , mxRbChangesFillForm(m_xBuilder->weld_radio_button("changeform"))
+ , mxRbChangesComment(m_xBuilder->weld_radio_button("changecomment"))
+ , mxRbChangesAnyNoCopy(m_xBuilder->weld_radio_button("changeany"))
+ , mxContent(m_xBuilder->weld_widget("content"))
+ , mxCbEnableCopy(m_xBuilder->weld_check_button("enablecopy"))
+ , mxCbEnableAccessibility(m_xBuilder->weld_check_button("enablea11y"))
+ , mxPasswordTitle(m_xBuilder->weld_label("setpasswordstitle"))
+{
+ msStrSetPwd = mxPasswordTitle->get_label();
+ mxPbSetPwd->connect_clicked(LINK(this, ImpPDFTabSecurityPage, ClickmaPbSetPwdHdl));
+}
+
+ImpPDFTabSecurityPage::~ImpPDFTabSecurityPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabSecurityPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabSecurityPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabSecurityPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ // please note that in PDF/A-1a mode even if this are copied back,
+ // the security settings are forced disabled in PDFExport::Export
+ pParent->mbEncrypt = mbHaveUserPassword;
+ pParent->mxPreparedPasswords = mxPreparedPasswords;
+
+ pParent->mbRestrictPermissions = mbHaveOwnerPassword;
+ pParent->maPreparedOwnerPassword = maPreparedOwnerPassword;
+
+ // verify print status
+ pParent->mnPrint = 0;
+ if (mxRbPrintLowRes->get_active())
+ pParent->mnPrint = 1;
+ else if (mxRbPrintHighRes->get_active())
+ pParent->mnPrint = 2;
+
+ // verify changes permitted
+ pParent->mnChangesAllowed = 0;
+
+ if( mxRbChangesInsDel->get_active() )
+ pParent->mnChangesAllowed = 1;
+ else if( mxRbChangesFillForm->get_active() )
+ pParent->mnChangesAllowed = 2;
+ else if( mxRbChangesComment->get_active() )
+ pParent->mnChangesAllowed = 3;
+ else if( mxRbChangesAnyNoCopy->get_active() )
+ pParent->mnChangesAllowed = 4;
+
+ pParent->mbCanCopyOrExtract = mxCbEnableCopy->get_active();
+ pParent->mbCanExtractForAccessibility = mxCbEnableAccessibility->get_active();
+}
+
+void ImpPDFTabSecurityPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ switch( pParent->mnPrint )
+ {
+ default:
+ case 0:
+ mxRbPrintNone->set_active(true);
+ break;
+ case 1:
+ mxRbPrintLowRes->set_active(true);
+ break;
+ case 2:
+ mxRbPrintHighRes->set_active(true);
+ break;
+ }
+
+ switch( pParent->mnChangesAllowed )
+ {
+ default:
+ case 0:
+ mxRbChangesNone->set_active(true);
+ break;
+ case 1:
+ mxRbChangesInsDel->set_active(true);
+ break;
+ case 2:
+ mxRbChangesFillForm->set_active(true);
+ break;
+ case 3:
+ mxRbChangesComment->set_active(true);
+ break;
+ case 4:
+ mxRbChangesAnyNoCopy->set_active(true);
+ break;
+ }
+
+ mxCbEnableCopy->set_active(pParent->mbCanCopyOrExtract);
+ mxCbEnableAccessibility->set_active(pParent->mbCanExtractForAccessibility);
+
+ // set the status of this windows, according to the PDFA selection
+ enablePermissionControls();
+
+ ImpPDFTabGeneralPage* pGeneralPage = pParent->getGeneralPage();
+
+ if (pGeneralPage)
+ ImplPDFASecurityControl(!pGeneralPage->IsPdfaSelected());
+}
+
+IMPL_LINK_NOARG(ImpPDFTabSecurityPage, ClickmaPbSetPwdHdl, weld::Button&, void)
+{
+ SfxPasswordDialog aPwdDialog(m_xContainer.get(), &msUserPwdTitle);
+ aPwdDialog.SetMinLen(0);
+ aPwdDialog.ShowMinLengthText(false);
+ aPwdDialog.ShowExtras( SfxShowExtras::CONFIRM | SfxShowExtras::PASSWORD2 | SfxShowExtras::CONFIRM2 );
+ aPwdDialog.set_title(msStrSetPwd);
+ aPwdDialog.SetGroup2Text(msOwnerPwdTitle);
+ aPwdDialog.AllowAsciiOnly();
+ if (aPwdDialog.run() == RET_OK) // OK issued get password and set it
+ {
+ OUString aUserPW(aPwdDialog.GetPassword());
+ OUString aOwnerPW(aPwdDialog.GetPassword2());
+
+ mbHaveUserPassword = !aUserPW.isEmpty();
+ mbHaveOwnerPassword = !aOwnerPW.isEmpty();
+
+ mxPreparedPasswords = vcl::PDFWriter::InitEncryption( aOwnerPW, aUserPW );
+ if (!mxPreparedPasswords.is()) {
+ OUString msg;
+ ErrorHandler::GetErrorString(ERRCODE_IO_NOTSUPPORTED, msg); //TODO: handle failure
+ std::unique_ptr<weld::MessageDialog>(
+ Application::CreateMessageDialog(
+ GetFrameWeld(), VclMessageType::Error, VclButtonsType::Ok, msg))
+ ->run();
+ return;
+ }
+
+ if( mbHaveOwnerPassword )
+ {
+ maPreparedOwnerPassword = comphelper::OStorageHelper::CreatePackageEncryptionData( aOwnerPW );
+ }
+ else
+ maPreparedOwnerPassword = Sequence< NamedValue >();
+ }
+ enablePermissionControls();
+}
+
+void ImpPDFTabSecurityPage::enablePermissionControls()
+{
+ bool bIsPDFASel = false;
+ ImpPDFTabDialog* pParent = static_cast<ImpPDFTabDialog*>(GetDialogController());
+ ImpPDFTabGeneralPage* pGeneralPage = pParent ? pParent->getGeneralPage() : nullptr;
+ if (pGeneralPage)
+ {
+ bIsPDFASel = pGeneralPage->IsPdfaSelected();
+ }
+ if (bIsPDFASel)
+ {
+ mxUserPwdPdfa->show();
+ mxUserPwdSet->hide();
+ mxUserPwdUnset->hide();
+ }
+ else
+ {
+ if (mbHaveUserPassword && m_xContainer->get_sensitive())
+ {
+ mxUserPwdSet->show();
+ mxUserPwdUnset->hide();
+ mxUserPwdPdfa->hide();
+ }
+ else
+ {
+ mxUserPwdUnset->show();
+ mxUserPwdSet->hide();
+ mxUserPwdPdfa->hide();
+ }
+ }
+
+ bool bLocalEnable = mbHaveOwnerPassword && m_xContainer->get_sensitive();
+ if (bIsPDFASel)
+ {
+ mxOwnerPwdPdfa->show();
+ mxOwnerPwdSet->hide();
+ mxOwnerPwdUnset->hide();
+ }
+ else
+ {
+ if (bLocalEnable)
+ {
+ mxOwnerPwdSet->show();
+ mxOwnerPwdUnset->hide();
+ mxOwnerPwdPdfa->hide();
+ }
+ else
+ {
+ mxOwnerPwdUnset->show();
+ mxOwnerPwdSet->hide();
+ mxOwnerPwdPdfa->hide();
+ }
+ }
+
+ mxPrintPermissions->set_sensitive(bLocalEnable);
+ mxChangesAllowed->set_sensitive(bLocalEnable);
+ mxContent->set_sensitive(bLocalEnable);
+}
+
+// This tab page is under control of the PDF/A-1a checkbox:
+// TODO: implement a method to do it.
+void ImpPDFTabSecurityPage::ImplPDFASecurityControl( bool bEnableSecurity )
+{
+ m_xContainer->set_sensitive(bEnableSecurity);
+ // after enable, check the status of control as if the dialog was initialized
+ enablePermissionControls();
+}
+
+/// The link preferences tab page (relative and other stuff)
+ImpPDFTabLinksPage::ImpPDFTabLinksPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdflinkspage.ui", "PdfLinksPage", &rCoreSet)
+ , mbOpnLnksDefaultUserState(false)
+ , mbOpnLnksLaunchUserState(false)
+ , mbOpnLnksBrowserUserState(false)
+ , m_xCbExprtBmkrToNmDst(m_xBuilder->weld_check_button("export"))
+ , m_xCbOOoToPDFTargets(m_xBuilder->weld_check_button("convert"))
+ , m_xCbExportRelativeFsysLinks(m_xBuilder->weld_check_button("exporturl"))
+ , m_xRbOpnLnksDefault(m_xBuilder->weld_radio_button("default"))
+ , m_xRbOpnLnksLaunch(m_xBuilder->weld_radio_button("openpdf"))
+ , m_xRbOpnLnksBrowser(m_xBuilder->weld_radio_button("openinternet"))
+{
+}
+
+ImpPDFTabLinksPage::~ImpPDFTabLinksPage()
+{
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabLinksPage::Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabLinksPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabLinksPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ pParent->mbExportRelativeFsysLinks = m_xCbExportRelativeFsysLinks->get_active();
+
+ bool bIsPDFASel = false;
+ ImpPDFTabGeneralPage* pGeneralPage = pParent->getGeneralPage();
+ if (pGeneralPage)
+ bIsPDFASel = pGeneralPage->IsPdfaSelected();
+ // if PDF/A-1 was not selected while exiting dialog...
+ if( !bIsPDFASel )
+ {
+ // ...get the control states
+ mbOpnLnksDefaultUserState = m_xRbOpnLnksDefault->get_active();
+ mbOpnLnksLaunchUserState = m_xRbOpnLnksLaunch->get_active();
+ mbOpnLnksBrowserUserState = m_xRbOpnLnksBrowser->get_active();
+ }
+ // the control states, or the saved is used
+ // to form the stored selection
+ pParent->mnViewPDFMode = 0;
+ if( mbOpnLnksBrowserUserState )
+ pParent->mnViewPDFMode = 2;
+ else if( mbOpnLnksLaunchUserState )
+ pParent->mnViewPDFMode = 1;
+
+ pParent->mbConvertOOoTargets = m_xCbOOoToPDFTargets->get_active();
+ pParent->mbExportBmkToPDFDestination = m_xCbExprtBmkrToNmDst->get_active();
+}
+
+void ImpPDFTabLinksPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ m_xCbOOoToPDFTargets->set_active(pParent->mbConvertOOoTargets);
+ m_xCbExprtBmkrToNmDst->set_active(pParent->mbExportBmkToPDFDestination);
+
+ m_xRbOpnLnksDefault->connect_toggled(LINK(this, ImpPDFTabLinksPage, ClickRbOpnLnksDefaultHdl));
+ m_xRbOpnLnksBrowser->connect_toggled(LINK(this, ImpPDFTabLinksPage, ClickRbOpnLnksBrowserHdl));
+
+ m_xCbExportRelativeFsysLinks->set_active(pParent->mbExportRelativeFsysLinks);
+ switch( pParent->mnViewPDFMode )
+ {
+ default:
+ case 0:
+ m_xRbOpnLnksDefault->set_active(true);
+ mbOpnLnksDefaultUserState = true;
+ break;
+ case 1:
+ m_xRbOpnLnksLaunch->set_active(true);
+ mbOpnLnksLaunchUserState = true;
+ break;
+ case 2:
+ m_xRbOpnLnksBrowser->set_active(true);
+ mbOpnLnksBrowserUserState = true;
+ break;
+ }
+
+ // now check the status of PDF/A selection
+ // and set the link action accordingly
+ // PDF/A-2 doesn't allow launch action on links
+
+ ImpPDFTabGeneralPage* pGeneralPage = pParent->getGeneralPage();
+ if (pGeneralPage)
+ ImplPDFALinkControl(!pGeneralPage->mxCbPDFA->get_active());
+}
+
+
+/** Called from general tab, with PDFA/1 selection status.
+ Retrieves/store the status of Launch action selection.
+ */
+void ImpPDFTabLinksPage::ImplPDFALinkControl( bool bEnableLaunch )
+{
+ // set the value and position of link type selection
+ if( bEnableLaunch )
+ {
+ m_xRbOpnLnksLaunch->set_sensitive(true);
+ // restore user state with no PDF/A-1 selected
+ m_xRbOpnLnksDefault->set_active(mbOpnLnksDefaultUserState);
+ m_xRbOpnLnksLaunch->set_active(mbOpnLnksLaunchUserState);
+ m_xRbOpnLnksBrowser->set_active(mbOpnLnksBrowserUserState);
+ }
+ else
+ {
+ // save user state with no PDF/A-1 selected
+ mbOpnLnksDefaultUserState = m_xRbOpnLnksDefault->get_active();
+ mbOpnLnksLaunchUserState = m_xRbOpnLnksLaunch->get_active();
+ mbOpnLnksBrowserUserState = m_xRbOpnLnksBrowser->get_active();
+ m_xRbOpnLnksLaunch->set_sensitive(false);
+ if (mbOpnLnksLaunchUserState)
+ m_xRbOpnLnksBrowser->set_active(true);
+ }
+}
+
+/// Reset the memory of Launch action present when PDF/A-1 was requested
+IMPL_LINK_NOARG(ImpPDFTabLinksPage, ClickRbOpnLnksDefaultHdl, weld::Toggleable&, void)
+{
+ mbOpnLnksDefaultUserState = m_xRbOpnLnksDefault->get_active();
+ mbOpnLnksLaunchUserState = m_xRbOpnLnksLaunch->get_active();
+ mbOpnLnksBrowserUserState = m_xRbOpnLnksBrowser->get_active();
+}
+
+/// Reset the memory of a launch action present when PDF/A-1 was requested
+IMPL_LINK_NOARG(ImpPDFTabLinksPage, ClickRbOpnLnksBrowserHdl, weld::Toggleable&, void)
+{
+ mbOpnLnksDefaultUserState = m_xRbOpnLnksDefault->get_active();
+ mbOpnLnksLaunchUserState = m_xRbOpnLnksLaunch->get_active();
+ mbOpnLnksBrowserUserState = m_xRbOpnLnksBrowser->get_active();
+}
+
+ImplErrorDialog::ImplErrorDialog(weld::Window* pParent, const std::set<vcl::PDFWriter::ErrorCode>& rErrors)
+ : MessageDialogController(pParent, "filter/ui/warnpdfdialog.ui", "WarnPDFDialog", "grid")
+ , m_xErrors(m_xBuilder->weld_tree_view("errors"))
+ , m_xExplanation(m_xBuilder->weld_label("message"))
+{
+ int nWidth = m_xErrors->get_approximate_digit_width() * 26;
+ int nHeight = m_xErrors->get_height_rows(9);
+ m_xErrors->set_size_request(nWidth, nHeight);
+ m_xExplanation->set_size_request(nWidth, nHeight);
+
+ for (auto const& error : rErrors)
+ {
+ switch(error)
+ {
+ case vcl::PDFWriter::Warning_Transparency_Omitted_PDFA:
+ m_xErrors->append(PDFFilterResId(STR_WARN_TRANSP_PDFA), PDFFilterResId(STR_WARN_TRANSP_PDFA_SHORT), "dialog-warning");
+ break;
+ case vcl::PDFWriter::Warning_Transparency_Omitted_PDF13:
+ m_xErrors->append(PDFFilterResId(STR_WARN_TRANSP_VERSION), PDFFilterResId(STR_WARN_TRANSP_VERSION_SHORT), "dialog-warning");
+ break;
+ case vcl::PDFWriter::Warning_FormAction_Omitted_PDFA:
+ m_xErrors->append(PDFFilterResId(STR_WARN_FORMACTION_PDFA), PDFFilterResId(STR_WARN_FORMACTION_PDFA_SHORT), "dialog-warning");
+ break;
+ case vcl::PDFWriter::Warning_Transparency_Converted:
+ m_xErrors->append(PDFFilterResId(STR_WARN_TRANSP_CONVERTED), PDFFilterResId(STR_WARN_TRANSP_CONVERTED_SHORT), "dialog-warning");
+ break;
+ case vcl::PDFWriter::Error_Signature_Failed:
+ m_xErrors->append(PDFFilterResId(STR_ERR_PDF_EXPORT_ABORTED), PDFFilterResId(STR_ERR_SIGNATURE_FAILED), "dialog-error");
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (m_xErrors->n_children() > 0)
+ {
+ m_xErrors->select(0);
+ m_xExplanation->set_label(m_xErrors->get_id(0));
+ }
+
+ m_xErrors->connect_changed(LINK(this, ImplErrorDialog, SelectHdl));
+}
+
+IMPL_LINK_NOARG(ImplErrorDialog, SelectHdl, weld::TreeView&, void)
+{
+ OUString aExplanation = m_xErrors->get_selected_id();
+ m_xExplanation->set_label(aExplanation);
+}
+
+/// The digital signatures tab page
+ImpPDFTabSigningPage::ImpPDFTabSigningPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rCoreSet)
+ : SfxTabPage(pPage, pController, "filter/ui/pdfsignpage.ui", "PdfSignPage", &rCoreSet)
+ , mxEdSignCert(m_xBuilder->weld_entry("cert"))
+ , mxPbSignCertSelect(m_xBuilder->weld_button("select"))
+ , mxPbSignCertClear(m_xBuilder->weld_button("clear"))
+ , mxEdSignPassword(m_xBuilder->weld_entry("password"))
+ , mxEdSignLocation(m_xBuilder->weld_entry("location"))
+ , mxEdSignContactInfo(m_xBuilder->weld_entry("contact"))
+ , mxEdSignReason(m_xBuilder->weld_entry("reason"))
+ , mxLBSignTSA(m_xBuilder->weld_combo_box("tsa"))
+{
+ mxPbSignCertSelect->set_sensitive(true);
+ mxPbSignCertSelect->connect_clicked(LINK(this, ImpPDFTabSigningPage, ClickmaPbSignCertSelect));
+ mxPbSignCertClear->connect_clicked(LINK(this, ImpPDFTabSigningPage, ClickmaPbSignCertClear));
+}
+
+ImpPDFTabSigningPage::~ImpPDFTabSigningPage()
+{
+}
+
+IMPL_LINK_NOARG(ImpPDFTabSigningPage, ClickmaPbSignCertSelect, weld::Button&, void)
+{
+ Reference< security::XDocumentDigitalSignatures > xSigner(
+ security::DocumentDigitalSignatures::createDefault(
+ comphelper::getProcessComponentContext()));
+ xSigner->setParentWindow(GetFrameWeld()->GetXWindow());
+
+ // The use may provide a description while choosing a certificate.
+ OUString aDescription;
+ maSignCertificate = xSigner->selectSigningCertificateWithType(
+ security::CertificateKind::CertificateKind_X509, aDescription);
+
+ if (!maSignCertificate.is())
+ return;
+
+ mxEdSignCert->set_text(maSignCertificate->getSubjectName());
+ mxPbSignCertClear->set_sensitive(true);
+ mxEdSignLocation->set_sensitive(true);
+ mxEdSignPassword->set_sensitive(true);
+ mxEdSignContactInfo->set_sensitive(true);
+ mxEdSignReason->set_sensitive(true);
+ mxEdSignReason->set_text(aDescription);
+
+ try
+ {
+ std::optional<css::uno::Sequence<OUString>> aTSAURLs(officecfg::Office::Common::Security::Scripting::TSAURLs::get());
+ if (aTSAURLs)
+ {
+ const css::uno::Sequence<OUString>& rTSAURLs = *aTSAURLs;
+ for (auto const& elem : rTSAURLs)
+ {
+ mxLBSignTSA->append_text(elem);
+ }
+ }
+ }
+ catch (const uno::Exception &)
+ {
+ TOOLS_INFO_EXCEPTION("filter.pdf", "TSAURLsDialog::TSAURLsDialog()");
+ }
+
+ // If more than only the "None" entry is there, enable the ListBox
+ if (mxLBSignTSA->get_count() > 1)
+ mxLBSignTSA->set_sensitive(true);
+}
+
+IMPL_LINK_NOARG(ImpPDFTabSigningPage, ClickmaPbSignCertClear, weld::Button&, void)
+{
+ mxEdSignCert->set_text("");
+ maSignCertificate.clear();
+ mxPbSignCertClear->set_sensitive(false);
+ mxEdSignLocation->set_sensitive(false);
+ mxEdSignPassword->set_sensitive(false);
+ mxEdSignContactInfo->set_sensitive(false);
+ mxEdSignReason->set_sensitive(false);
+ mxLBSignTSA->set_sensitive(false);
+}
+
+std::unique_ptr<SfxTabPage> ImpPDFTabSigningPage::Create( weld::Container* pPage, weld::DialogController* pController,
+ const SfxItemSet* rAttrSet)
+{
+ return std::make_unique<ImpPDFTabSigningPage>(pPage, pController, *rAttrSet);
+}
+
+void ImpPDFTabSigningPage::GetFilterConfigItem( ImpPDFTabDialog* pParent )
+{
+ pParent->mbSignPDF = maSignCertificate.is();
+ pParent->maSignCertificate = maSignCertificate;
+ pParent->msSignLocation = mxEdSignLocation->get_text();
+ pParent->msSignPassword = mxEdSignPassword->get_text();
+ pParent->msSignContact = mxEdSignContactInfo->get_text();
+ pParent->msSignReason = mxEdSignReason->get_text();
+ // Entry 0 is 'None'
+ if (mxLBSignTSA->get_active() >= 1)
+ pParent->msSignTSA = mxLBSignTSA->get_active_text();
+}
+
+void ImpPDFTabSigningPage::SetFilterConfigItem( const ImpPDFTabDialog* pParent )
+{
+ mxEdSignLocation->set_sensitive(false);
+ mxEdSignPassword->set_sensitive(false);
+ mxEdSignContactInfo->set_sensitive(false);
+ mxEdSignReason->set_sensitive(false);
+ mxLBSignTSA->set_sensitive(false);
+ mxPbSignCertClear->set_sensitive(false);
+
+ if (pParent->mbSignPDF)
+ {
+ mxEdSignPassword->set_text(pParent->msSignPassword);
+ mxEdSignLocation->set_text(pParent->msSignLocation);
+ mxEdSignContactInfo->set_text(pParent->msSignContact);
+ mxEdSignReason->set_text(pParent->msSignReason);
+ maSignCertificate = pParent->maSignCertificate;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/impdialog.hxx b/filter/source/pdf/impdialog.hxx
new file mode 100644
index 000000000..219d47e6d
--- /dev/null
+++ b/filter/source/pdf/impdialog.hxx
@@ -0,0 +1,419 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sfx2/tabdlg.hxx>
+#include <svx/AccessibilityCheckDialog.hxx>
+
+#include <vcl/pdfwriter.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <vcl/weld.hxx>
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+class ImpPDFTabGeneralPage;
+class ImpPDFTabViewerPage;
+class ImpPDFTabOpnFtrPage;
+class ImpPDFTabLinksPage;
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::lang;
+
+class ImplErrorDialog : public weld::MessageDialogController
+{
+private:
+ std::unique_ptr<weld::TreeView> m_xErrors;
+ std::unique_ptr<weld::Label> m_xExplanation;
+
+ DECL_LINK(SelectHdl, weld::TreeView&, void);
+
+public:
+ explicit ImplErrorDialog(weld::Window* pParent, const std::set<vcl::PDFWriter::ErrorCode>& rErrorCodes);
+};
+
+
+class ImpPDFTabSecurityPage;
+class ImpPDFTabLinksPage;
+
+
+/// Class tabbed dialog
+class ImpPDFTabDialog final : public SfxTabDialogController
+{
+ css::uno::Reference<css::lang::XComponent> mrDoc;
+ weld::Window* mpParent;
+
+ FilterConfigItem maConfigItem;
+ FilterConfigItem maConfigI18N;
+
+ Any maSelection;
+
+ DECL_LINK(CancelHdl, weld::Button&, void);
+ DECL_LINK(OkHdl, weld::Button&, void);
+
+ // the following data are the configuration used throughout the dialog and pages
+ bool mbIsPresentation;
+ bool mbIsSpreadsheet;
+ bool mbIsWriter;
+ bool mbSelectionPresent;
+ bool mbUseCTLFont;
+ bool mbUseLosslessCompression;
+ sal_Int32 mnQuality;
+ bool mbReduceImageResolution;
+ sal_Int32 mnMaxImageResolution;
+ bool mbUseTaggedPDF;
+ bool mbUseTaggedPDFUserSelection;
+ sal_Int32 mnPDFTypeSelection;
+ bool mbPDFUACompliance;
+ bool mbExportNotes;
+ bool mbViewPDF;
+ bool mbUseReferenceXObject;
+ bool mbExportNotesPages;
+ bool mbExportOnlyNotesPages;
+ bool mbUseTransitionEffects;
+ bool mbIsSkipEmptyPages;
+ bool mbIsExportPlaceholders;
+ bool mbAddStream;
+ sal_Int32 mnFormsType;
+ bool mbExportFormFields;
+ bool mbAllowDuplicateFieldNames;
+ bool mbExportBookmarks;
+ bool mbExportHiddenSlides;
+ bool mbSinglePageSheets;
+ sal_Int32 mnOpenBookmarkLevels;
+
+ bool mbHideViewerToolbar;
+ bool mbHideViewerMenubar;
+ bool mbHideViewerWindowControls;
+ bool mbResizeWinToInit;
+ bool mbCenterWindow;
+ bool mbOpenInFullScreenMode;
+ bool mbDisplayPDFDocumentTitle;
+ sal_Int32 mnMagnification;
+ sal_Int32 mnInitialView;
+ sal_Int32 mnZoom;
+ sal_Int32 mnInitialPage;
+
+ sal_Int32 mnPageLayout;
+ bool mbFirstPageLeft;
+
+ bool mbEncrypt;
+
+ bool mbRestrictPermissions;
+ css::uno::Sequence< css::beans::NamedValue > maPreparedOwnerPassword;
+ sal_Int32 mnPrint;
+ sal_Int32 mnChangesAllowed;
+ bool mbCanCopyOrExtract;
+ bool mbCanExtractForAccessibility;
+ css::uno::Reference< css::beans::XMaterialHolder > mxPreparedPasswords;
+
+ std::shared_ptr< svx::AccessibilityCheckDialog > mpAccessibilityCheckDialog;
+
+ bool mbIsRangeChecked;
+ OUString msPageRange;
+ bool mbSelectionIsChecked;
+
+ bool mbExportRelativeFsysLinks;
+ sal_Int32 mnViewPDFMode;
+ bool mbConvertOOoTargets;
+ bool mbExportBmkToPDFDestination;
+
+ bool mbSignPDF;
+ OUString msSignPassword;
+ OUString msSignLocation;
+ OUString msSignContact;
+ OUString msSignReason;
+ css::uno::Reference< css::security::XCertificate > maSignCertificate;
+ OUString msSignTSA;
+
+ OUString maWatermarkText;
+
+public:
+
+ friend class ImpPDFTabGeneralPage;
+ friend class ImpPDFTabViewerPage;
+ friend class ImpPDFTabOpnFtrPage;
+ friend class ImpPDFTabSecurityPage;
+ friend class ImpPDFTabLinksPage;
+ friend class ImpPDFTabSigningPage;
+
+ ImpPDFTabDialog(weld::Window* pParent, const Sequence< PropertyValue >& rFilterData,
+ const css::uno::Reference< XComponent >& rDoc);
+ virtual ~ImpPDFTabDialog() override;
+
+ Sequence< PropertyValue > GetFilterData();
+
+ ImpPDFTabSecurityPage* getSecurityPage() const;
+ ImpPDFTabLinksPage* getLinksPage() const;
+ ImpPDFTabGeneralPage* getGeneralPage() const;
+
+private:
+ virtual void PageCreated(const OString& rId, SfxTabPage& rPage) override;
+};
+
+
+/// Class tab page general
+class ImpPDFTabGeneralPage : public SfxTabPage
+{
+ friend class ImpPDFTabLinksPage;
+
+ bool mbUseTaggedPDFUserSelection;
+ bool mbIsPresentation;
+ bool mbIsSpreadsheet;
+ bool mbIsWriter;
+ ImpPDFTabDialog* mpParent;
+
+ std::unique_ptr<weld::RadioButton> mxRbAll;
+ std::unique_ptr<weld::RadioButton> mxRbRange;
+ std::unique_ptr<weld::RadioButton> mxRbSelection;
+ std::unique_ptr<weld::Entry> mxEdPages;
+ std::unique_ptr<weld::Label> mxSelectedSheets;
+ std::unique_ptr<weld::RadioButton> mxRbLosslessCompression;
+ std::unique_ptr<weld::RadioButton> mxRbJPEGCompression;
+ std::unique_ptr<weld::Widget> mxQualityFrame;
+ std::unique_ptr<weld::MetricSpinButton> mxNfQuality;
+ std::unique_ptr<weld::CheckButton> mxCbReduceImageResolution;
+ std::unique_ptr<weld::ComboBox> mxCoReduceImageResolution;
+ std::unique_ptr<weld::CheckButton> mxCbPDFA;
+ std::unique_ptr<weld::CheckButton> mxCbPDFUA;
+ std::unique_ptr<weld::ComboBox> mxRbPDFAVersion;
+ std::unique_ptr<weld::CheckButton> mxCbTaggedPDF;
+ std::unique_ptr<weld::CheckButton> mxCbExportFormFields;
+ std::unique_ptr<weld::Widget> mxFormsFrame;
+ std::unique_ptr<weld::ComboBox> mxLbFormsFormat;
+ std::unique_ptr<weld::CheckButton> mxCbAllowDuplicateFieldNames;
+ std::unique_ptr<weld::CheckButton> mxCbExportBookmarks;
+ std::unique_ptr<weld::CheckButton> mxCbExportHiddenSlides;
+ std::unique_ptr<weld::CheckButton> mxCbSinglePageSheets;
+ std::unique_ptr<weld::CheckButton> mxCbExportNotes;
+ std::unique_ptr<weld::CheckButton> mxCbViewPDF;
+ std::unique_ptr<weld::CheckButton> mxCbUseReferenceXObject;
+ std::unique_ptr<weld::CheckButton> mxCbExportNotesPages;
+ std::unique_ptr<weld::CheckButton> mxCbExportOnlyNotesPages;
+ std::unique_ptr<weld::CheckButton> mxCbExportEmptyPages;
+ std::unique_ptr<weld::CheckButton> mxCbExportPlaceholders;
+ std::unique_ptr<weld::CheckButton> mxCbAddStream;
+ std::unique_ptr<weld::CheckButton> mxCbWatermark;
+ std::unique_ptr<weld::Label> mxFtWatermark;
+ std::unique_ptr<weld::Entry> mxEdWatermark;
+ std::unique_ptr<weld::Label> mxSlidesFt;
+ std::unique_ptr<weld::Label> mxSheetsFt;
+
+ DECL_LINK(ToggleAllHdl, weld::Toggleable&, void);
+ DECL_LINK(TogglePagesHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleSelectionHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleCompressionHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleReduceImageResolutionHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleWatermarkHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleAddStreamHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleExportFormFieldsHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleExportNotesPagesHdl, weld::Toggleable&, void);
+
+ void TogglePagesHdl();
+ void EnableExportNotesPages();
+
+ DECL_LINK(TogglePDFVersionOrUniversalAccessibilityHandle, weld::Toggleable&, void);
+
+public:
+
+ ImpPDFTabGeneralPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabGeneralPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ void GetFilterConfigItem(ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem(ImpPDFTabDialog* paParent);
+ bool IsPdfaSelected() const { return mxCbPDFA->get_active(); }
+ bool IsPdfUaSelected() const { return mxCbPDFUA->get_active(); }
+};
+
+/// Class tab page viewer
+class ImpPDFTabOpnFtrPage : public SfxTabPage
+{
+ bool mbUseCTLFont;
+
+ std::unique_ptr<weld::RadioButton> mxRbOpnPageOnly;
+ std::unique_ptr<weld::RadioButton> mxRbOpnOutline;
+ std::unique_ptr<weld::RadioButton> mxRbOpnThumbs;
+ std::unique_ptr<weld::SpinButton> mxNumInitialPage;
+ std::unique_ptr<weld::RadioButton> mxRbMagnDefault;
+ std::unique_ptr<weld::RadioButton> mxRbMagnFitWin;
+ std::unique_ptr<weld::RadioButton> mxRbMagnFitWidth;
+ std::unique_ptr<weld::RadioButton> mxRbMagnFitVisible;
+ std::unique_ptr<weld::RadioButton> mxRbMagnZoom;
+ std::unique_ptr<weld::SpinButton> mxNumZoom;
+ std::unique_ptr<weld::RadioButton> mxRbPgLyDefault;
+ std::unique_ptr<weld::RadioButton> mxRbPgLySinglePage;
+ std::unique_ptr<weld::RadioButton> mxRbPgLyContinue;
+ std::unique_ptr<weld::RadioButton> mxRbPgLyContinueFacing;
+ std::unique_ptr<weld::CheckButton> mxCbPgLyFirstOnLeft;
+
+ DECL_LINK(ToggleRbPgLyContinueFacingHdl, weld::Toggleable&, void);
+ DECL_LINK(ToggleRbMagnHdl, weld::Toggleable&, void);
+
+ void ToggleRbPgLyContinueFacingHdl();
+
+public:
+ ImpPDFTabOpnFtrPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabOpnFtrPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet );
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+};
+
+/// Class tab page viewer
+class ImpPDFTabViewerPage : public SfxTabPage
+{
+ bool mbIsPresentation;
+
+ std::unique_ptr<weld::CheckButton> m_xCbResWinInit;
+ std::unique_ptr<weld::CheckButton> m_xCbCenterWindow;
+ std::unique_ptr<weld::CheckButton> m_xCbOpenFullScreen;
+ std::unique_ptr<weld::CheckButton> m_xCbDispDocTitle;
+ std::unique_ptr<weld::CheckButton> m_xCbHideViewerMenubar;
+ std::unique_ptr<weld::CheckButton> m_xCbHideViewerToolbar;
+ std::unique_ptr<weld::CheckButton> m_xCbHideViewerWindowControls;
+ std::unique_ptr<weld::CheckButton> m_xCbTransitionEffects;
+ std::unique_ptr<weld::RadioButton> m_xRbAllBookmarkLevels;
+ std::unique_ptr<weld::RadioButton> m_xRbVisibleBookmarkLevels;
+ std::unique_ptr<weld::SpinButton>m_xNumBookmarkLevels;
+
+ DECL_LINK(ToggleRbBookmarksHdl, weld::Toggleable&, void);
+
+public:
+ ImpPDFTabViewerPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabViewerPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet );
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+};
+
+/// Class security tab page
+class ImpPDFTabSecurityPage : public SfxTabPage
+{
+ OUString msStrSetPwd;
+ OUString msUserPwdTitle;
+ bool mbHaveOwnerPassword;
+ bool mbHaveUserPassword;
+ css::uno::Sequence< css::beans::NamedValue > maPreparedOwnerPassword;
+ OUString msOwnerPwdTitle;
+
+ css::uno::Reference< css::beans::XMaterialHolder > mxPreparedPasswords;
+
+ std::unique_ptr<weld::Button> mxPbSetPwd;
+ std::unique_ptr<weld::Widget> mxUserPwdSet;
+ std::unique_ptr<weld::Widget> mxUserPwdUnset;
+ std::unique_ptr<weld::Widget> mxUserPwdPdfa;
+ std::unique_ptr<weld::Widget> mxOwnerPwdSet;
+ std::unique_ptr<weld::Widget> mxOwnerPwdUnset;
+ std::unique_ptr<weld::Widget> mxOwnerPwdPdfa;
+ std::unique_ptr<weld::Widget> mxPrintPermissions;
+ std::unique_ptr<weld::RadioButton> mxRbPrintNone;
+ std::unique_ptr<weld::RadioButton> mxRbPrintLowRes;
+ std::unique_ptr<weld::RadioButton> mxRbPrintHighRes;
+ std::unique_ptr<weld::Widget> mxChangesAllowed;
+ std::unique_ptr<weld::RadioButton> mxRbChangesNone;
+ std::unique_ptr<weld::RadioButton> mxRbChangesInsDel;
+ std::unique_ptr<weld::RadioButton> mxRbChangesFillForm;
+ std::unique_ptr<weld::RadioButton> mxRbChangesComment;
+ std::unique_ptr<weld::RadioButton> mxRbChangesAnyNoCopy;
+ std::unique_ptr<weld::Widget> mxContent;
+ std::unique_ptr<weld::CheckButton> mxCbEnableCopy;
+ std::unique_ptr<weld::CheckButton> mxCbEnableAccessibility;
+ std::unique_ptr<weld::Label> mxPasswordTitle;
+
+ DECL_LINK(ClickmaPbSetPwdHdl, weld::Button&, void);
+
+ void enablePermissionControls();
+
+public:
+ ImpPDFTabSecurityPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabSecurityPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+ void ImplPDFASecurityControl( bool bEnableSecurity );
+ bool hasPassword() const { return mbHaveOwnerPassword || mbHaveUserPassword; }
+};
+
+/// Implements the relative link stuff
+class ImpPDFTabLinksPage : public SfxTabPage
+{
+ bool mbOpnLnksDefaultUserState;
+ bool mbOpnLnksLaunchUserState;
+ bool mbOpnLnksBrowserUserState;
+
+ std::unique_ptr<weld::CheckButton> m_xCbExprtBmkrToNmDst;
+ std::unique_ptr<weld::CheckButton> m_xCbOOoToPDFTargets;
+ std::unique_ptr<weld::CheckButton> m_xCbExportRelativeFsysLinks;
+ std::unique_ptr<weld::RadioButton> m_xRbOpnLnksDefault;
+ std::unique_ptr<weld::RadioButton> m_xRbOpnLnksLaunch;
+ std::unique_ptr<weld::RadioButton> m_xRbOpnLnksBrowser;
+
+ DECL_LINK(ClickRbOpnLnksDefaultHdl, weld::Toggleable&, void);
+ DECL_LINK(ClickRbOpnLnksBrowserHdl, weld::Toggleable&, void);
+
+public:
+ ImpPDFTabLinksPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabLinksPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet);
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+
+ void ImplPDFALinkControl( bool bEnableLaunch );
+};
+
+//class to implement the digital signing
+class ImpPDFTabSigningPage : public SfxTabPage
+{
+ css::uno::Reference< css::security::XCertificate > maSignCertificate;
+
+ std::unique_ptr<weld::Entry> mxEdSignCert;
+ std::unique_ptr<weld::Button> mxPbSignCertSelect;
+ std::unique_ptr<weld::Button> mxPbSignCertClear;
+ std::unique_ptr<weld::Entry> mxEdSignPassword;
+ std::unique_ptr<weld::Entry> mxEdSignLocation;
+ std::unique_ptr<weld::Entry> mxEdSignContactInfo;
+ std::unique_ptr<weld::Entry> mxEdSignReason;
+ std::unique_ptr<weld::ComboBox> mxLBSignTSA;
+
+ DECL_LINK(ClickmaPbSignCertSelect, weld::Button&, void);
+ DECL_LINK(ClickmaPbSignCertClear, weld::Button&, void);
+
+public:
+ ImpPDFTabSigningPage(weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet);
+ virtual ~ImpPDFTabSigningPage() override;
+
+ static std::unique_ptr<SfxTabPage> Create( weld::Container* pPage, weld::DialogController* pController, const SfxItemSet* rAttrSet );
+
+ void GetFilterConfigItem( ImpPDFTabDialog* paParent);
+ void SetFilterConfigItem( const ImpPDFTabDialog* paParent );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfdecomposer.cxx b/filter/source/pdf/pdfdecomposer.cxx
new file mode 100644
index 000000000..7a032bf36
--- /dev/null
+++ b/filter/source/pdf/pdfdecomposer.cxx
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * 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 <vector>
+
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <cppuhelper/implbase2.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
+#include <vcl/bitmapex.hxx>
+#include <vcl/pdfread.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/BinaryDataContainer.hxx>
+#include <vcl/BinaryDataContainerTools.hxx>
+#include <toolkit/helper/vclunohelper.hxx>
+
+#include <com/sun/star/graphic/XPdfDecomposer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/XBinaryDataContainer.hpp>
+
+using namespace css;
+
+namespace
+{
+/// Class to convert the PDF data into a XPrimitive2D (containing only a bitmap).
+class XPdfDecomposer
+ : public ::cppu::WeakAggImplHelper2<graphic::XPdfDecomposer, lang::XServiceInfo>
+{
+public:
+ explicit XPdfDecomposer(uno::Reference<uno::XComponentContext> const& context);
+ XPdfDecomposer(const XPdfDecomposer&) = delete;
+ XPdfDecomposer& operator=(const XPdfDecomposer&) = delete;
+
+ // XPdfDecomposer
+ uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL
+ getDecomposition(const uno::Reference<util::XBinaryDataContainer>& xDataContainer,
+ const uno::Sequence<beans::PropertyValue>& xDecompositionParameters) override;
+
+ // XServiceInfo
+ OUString SAL_CALL getImplementationName() override;
+ sal_Bool SAL_CALL supportsService(const OUString&) override;
+ uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+XPdfDecomposer::XPdfDecomposer(uno::Reference<uno::XComponentContext> const&) {}
+
+uno::Sequence<uno::Reference<graphic::XPrimitive2D>> SAL_CALL
+XPdfDecomposer::getDecomposition(const uno::Reference<util::XBinaryDataContainer>& xDataContainer,
+ const uno::Sequence<beans::PropertyValue>& xParameters)
+{
+ sal_Int32 nPageIndex = -1;
+
+ for (const beans::PropertyValue& rProperty : xParameters)
+ {
+ if (rProperty.Name == "PageIndex")
+ {
+ rProperty.Value >>= nPageIndex;
+ break;
+ }
+ }
+
+ if (nPageIndex < 0)
+ nPageIndex = 0;
+
+ BinaryDataContainer aDataContainer = vcl::convertUnoBinaryDataContainer(xDataContainer);
+
+ std::vector<BitmapEx> aBitmaps;
+ int rv = vcl::RenderPDFBitmaps(aDataContainer.getData(), aDataContainer.getSize(), aBitmaps,
+ nPageIndex, 1);
+ if (rv == 0)
+ return {}; // happens if we do not have PDFium
+
+ BitmapEx aReplacement(aBitmaps[0]);
+
+ // short form for scale and translate transformation
+ const Size aBitmapSize(aReplacement.GetSizePixel());
+ // ImpGraphic::getPrefMapMode() requires mm100 for bitmaps rendered from vector graphic data.
+ const Size aMM100(
+ Application::GetDefaultDevice()->PixelToLogic(aBitmapSize, MapMode(MapUnit::Map100thMM)));
+ const basegfx::B2DHomMatrix aBitmapTransform(basegfx::utils::createScaleTranslateB2DHomMatrix(
+ aMM100.getWidth(), aMM100.getHeight(), 0, 0));
+
+ // create primitive
+ return drawinglayer::primitive2d::Primitive2DContainer{
+ new drawinglayer::primitive2d::BitmapPrimitive2D(
+ VCLUnoHelper::CreateVCLXBitmap(aReplacement), aBitmapTransform)
+ }
+ .toSequence();
+}
+
+OUString SAL_CALL XPdfDecomposer::getImplementationName()
+{
+ return "com.sun.star.comp.PDF.PDFDecomposer";
+}
+
+sal_Bool SAL_CALL XPdfDecomposer::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL XPdfDecomposer::getSupportedServiceNames()
+{
+ return { "com.sun.star.graphic.PdfTools" };
+}
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_PdfDecomposer_get_implementation(css::uno::XComponentContext* context,
+ css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XPdfDecomposer(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/filter/source/pdf/pdfdialog.cxx b/filter/source/pdf/pdfdialog.cxx
new file mode 100644
index 000000000..7c3e5dda1
--- /dev/null
+++ b/filter/source/pdf/pdfdialog.cxx
@@ -0,0 +1,139 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "pdfdialog.hxx"
+#include "impdialog.hxx"
+#include <vcl/svapp.hxx>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+
+PDFDialog::PDFDialog( const Reference< XComponentContext > &rxContext )
+: PDFDialog_Base( rxContext )
+{
+}
+
+
+PDFDialog::~PDFDialog()
+{
+}
+
+
+Sequence< sal_Int8 > SAL_CALL PDFDialog::getImplementationId()
+{
+ return css::uno::Sequence<sal_Int8>();
+}
+
+
+OUString SAL_CALL PDFDialog::getImplementationName()
+{
+ return "com.sun.star.comp.PDF.PDFDialog";
+}
+
+
+Sequence< OUString > SAL_CALL PDFDialog::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.PDFDialog" };
+}
+
+std::unique_ptr<weld::DialogController> PDFDialog::createDialog(const css::uno::Reference<css::awt::XWindow>& rParent)
+{
+ if( mxSrcDoc.is() )
+ return std::make_unique<ImpPDFTabDialog>(Application::GetFrameWeld(rParent), maFilterData, mxSrcDoc);
+ return nullptr;
+}
+
+void PDFDialog::executedDialog( sal_Int16 nExecutionResult )
+{
+ if (nExecutionResult && m_xDialog)
+ maFilterData = static_cast<ImpPDFTabDialog*>(m_xDialog.get())->GetFilterData();
+ destroyDialog();
+}
+
+Reference< XPropertySetInfo > SAL_CALL PDFDialog::getPropertySetInfo()
+{
+ Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) );
+ return xInfo;
+}
+
+::cppu::IPropertyArrayHelper& PDFDialog::getInfoHelper()
+{
+ return *getArrayHelper();
+}
+
+::cppu::IPropertyArrayHelper* PDFDialog::createArrayHelper() const
+{
+ Sequence< Property > aProps;
+ describeProperties(aProps);
+ return new ::cppu::OPropertyArrayHelper( aProps );
+}
+
+
+Sequence< PropertyValue > SAL_CALL PDFDialog::getPropertyValues()
+{
+ sal_Int32 i, nCount;
+
+ for( i = 0, nCount = maMediaDescriptor.getLength(); i < nCount; i++ )
+ {
+ if ( maMediaDescriptor[ i ].Name == "FilterData" )
+ break;
+ }
+
+ if( i == nCount )
+ maMediaDescriptor.realloc( ++nCount );
+ auto pMediaDescriptor = maMediaDescriptor.getArray();
+
+ pMediaDescriptor[ i ].Name = "FilterData";
+ pMediaDescriptor[ i ].Value <<= maFilterData;
+
+ return maMediaDescriptor;
+}
+
+
+void SAL_CALL PDFDialog::setPropertyValues( const Sequence< PropertyValue >& rProps )
+{
+ maMediaDescriptor = rProps;
+
+ for( const PropertyValue& rProp : std::as_const(maMediaDescriptor) )
+ {
+ if ( rProp.Name == "FilterData" )
+ {
+ rProp.Value >>= maFilterData;
+ break;
+ }
+ }
+}
+
+
+void SAL_CALL PDFDialog::setSourceDocument( const Reference< XComponent >& xDoc )
+{
+ mxSrcDoc = xDoc;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_PDFDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new PDFDialog(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfdialog.hxx b/filter/source/pdf/pdfdialog.hxx
new file mode 100644
index 000000000..fcfd1d097
--- /dev/null
+++ b/filter/source/pdf/pdfdialog.hxx
@@ -0,0 +1,72 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <svtools/genericunodialog.hxx>
+
+#include <comphelper/proparrhlp.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+
+typedef ::cppu::ImplInheritanceHelper < ::svt::OGenericUnoDialog, XPropertyAccess, XExporter > PDFDialog_Base;
+
+class PDFDialog final:
+ public PDFDialog_Base,
+ public ::comphelper::OPropertyArrayUsageHelper< PDFDialog >
+{
+private:
+ Sequence< PropertyValue > maMediaDescriptor;
+ Sequence< PropertyValue > maFilterData;
+ Reference< XComponent > mxSrcDoc;
+
+ // OGenericUnoDialog
+ virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+ virtual std::unique_ptr<weld::DialogController> createDialog(const css::uno::Reference<css::awt::XWindow>& rParent) override;
+ virtual void executedDialog( sal_Int16 nExecutionResult ) override;
+ virtual Reference< XPropertySetInfo> SAL_CALL getPropertySetInfo() override;
+ virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override;
+ virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const override;
+
+ // XPropertyAccess
+ using OPropertySetHelper::getPropertyValues;
+ virtual Sequence< PropertyValue > SAL_CALL getPropertyValues( ) override;
+ using OPropertySetHelper::setPropertyValues;
+ virtual void SAL_CALL setPropertyValues( const Sequence< PropertyValue >& aProps ) override;
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) override;
+
+public:
+
+ explicit PDFDialog( const Reference< XComponentContext >& rxContext );
+ virtual ~PDFDialog() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx
new file mode 100644
index 000000000..7a233aad0
--- /dev/null
+++ b/filter/source/pdf/pdfexport.cxx
@@ -0,0 +1,1374 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <osl/file.hxx>
+#include <tools/debug.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/poly.hxx>
+#include <tools/diagnose_ex.h>
+#include <unotools/resmgr.hxx>
+#include <utility>
+#include <vcl/canvastools.hxx>
+#include <vcl/mapmod.hxx>
+#include <vcl/gdimtf.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequence.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/polygon/b2dpolypolygon.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <toolkit/awt/vclxdevice.hxx>
+#include <unotools/configmgr.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <basegfx/matrix/b2dhommatrix.hxx>
+
+#include "pdfexport.hxx"
+#include <strings.hrc>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/configuration/theDefaultProvider.hpp>
+#include <com/sun/star/awt/XDevice.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/frame/ModuleManager.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/view/XViewSettingsSupplier.hpp>
+#include <com/sun/star/task/XInteractionRequest.hpp>
+#include <com/sun/star/task/PDFExportException.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/drawing/XShapes.hpp>
+#include <com/sun/star/security/XCertificate.hpp>
+#include <com/sun/star/beans/XMaterialHolder.hpp>
+#include <com/sun/star/xml/crypto/SEInitializer.hpp>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::view;
+using namespace ::com::sun::star::graphic;
+
+
+PDFExport::PDFExport( const Reference< XComponent >& rxSrcDoc,
+ const Reference< task::XStatusIndicator >& rxStatusIndicator,
+ const Reference< task::XInteractionHandler >& rxIH,
+ const Reference< XComponentContext >& xContext ) :
+ mxSrcDoc ( rxSrcDoc ),
+ mxContext ( xContext ),
+ mxStatusIndicator ( rxStatusIndicator ),
+ mxIH ( rxIH ),
+ mbUseTaggedPDF ( false ),
+ mnPDFTypeSelection ( 0 ),
+ mbPDFUACompliance ( false),
+ mbExportNotes ( true ),
+ mbExportPlaceholders ( false ),
+ mbUseReferenceXObject ( false ),
+ mbExportNotesPages ( false ),
+ mbExportOnlyNotesPages ( false ),
+ mbUseTransitionEffects ( true ),
+ mbExportBookmarks ( true ),
+ mbExportHiddenSlides ( false ),
+ mbSinglePageSheets ( false ),
+ mnOpenBookmarkLevels ( -1 ),
+ mbUseLosslessCompression ( false ),
+ mbReduceImageResolution ( true ),
+ mbSkipEmptyPages ( true ),
+ mbAddStream ( false ),
+ mnMaxImageResolution ( 300 ),
+ mnQuality ( 80 ),
+ mnFormsFormat ( 0 ),
+ mbExportFormFields ( true ),
+ mbAllowDuplicateFieldNames ( false ),
+ mnProgressValue ( 0 ),
+ mbRemoveTransparencies ( false ),
+
+ mbIsRedactMode ( false ),
+ maWatermarkColor ( COL_LIGHTGREEN ),
+ maWatermarkFontName ( "Helvetica" ),
+
+ mbHideViewerToolbar ( false ),
+ mbHideViewerMenubar ( false ),
+ mbHideViewerWindowControls ( false ),
+ mbFitWindow ( false ),
+ mbCenterWindow ( false ),
+ mbOpenInFullScreenMode ( false ),
+ mbDisplayPDFDocumentTitle ( true ),
+ mnPDFDocumentMode ( 0 ),
+ mnPDFDocumentAction ( 0 ),
+ mnZoom ( 100 ),
+ mnInitialPage ( 1 ),
+ mnPDFPageLayout ( 0 ),
+
+ mbEncrypt ( false ),
+ mbRestrictPermissions ( false ),
+ mnPrintAllowed ( 2 ),
+ mnChangesAllowed ( 4 ),
+ mbCanCopyOrExtract ( true ),
+ mbCanExtractForAccessibility( true ),
+
+ // #i56629
+ mbExportRelativeFsysLinks ( false ),
+ mnDefaultLinkAction ( 0 ),
+ mbConvertOOoTargetToPDFTarget( false ),
+ mbExportBmkToDest ( false ),
+ mbSignPDF ( false )
+{
+}
+
+
+PDFExport::~PDFExport()
+{
+}
+
+
+bool PDFExport::ExportSelection( vcl::PDFWriter& rPDFWriter,
+ Reference< css::view::XRenderable > const & rRenderable,
+ const Any& rSelection,
+ const StringRangeEnumerator& rRangeEnum,
+ Sequence< PropertyValue >& rRenderOptions,
+ sal_Int32 nPageCount )
+{
+ bool bRet = false;
+ try
+ {
+ Any* pFirstPage = nullptr;
+ Any* pLastPage = nullptr;
+
+ bool bExportNotesPages = false;
+
+ auto rRenderOptionsRange = asNonConstRange(rRenderOptions);
+ for( sal_Int32 nData = 0, nDataCount = rRenderOptions.getLength(); nData < nDataCount; ++nData )
+ {
+ if ( rRenderOptions[ nData ].Name == "IsFirstPage" )
+ pFirstPage = &rRenderOptionsRange[ nData ].Value;
+ else if ( rRenderOptions[ nData ].Name == "IsLastPage" )
+ pLastPage = &rRenderOptionsRange[ nData ].Value;
+ else if ( rRenderOptions[ nData ].Name == "ExportNotesPages" )
+ rRenderOptionsRange[ nData ].Value >>= bExportNotesPages;
+ }
+
+ OutputDevice* pOut = rPDFWriter.GetReferenceDevice();
+
+ if( pOut )
+ {
+ if ( nPageCount )
+ {
+ vcl::PDFExtOutDevData& rPDFExtOutDevData = dynamic_cast<vcl::PDFExtOutDevData&>(*pOut->GetExtOutDevData());
+ rPDFExtOutDevData.SetIsExportNotesPages( bExportNotesPages );
+
+ sal_Int32 nCurrentPage(0);
+ StringRangeEnumerator::Iterator aIter = rRangeEnum.begin();
+ StringRangeEnumerator::Iterator aEnd = rRangeEnum.end();
+ while ( aIter != aEnd )
+ {
+ const Sequence< PropertyValue > aRenderer( rRenderable->getRenderer( *aIter, rSelection, rRenderOptions ) );
+ awt::Size aPageSize;
+
+ for( const PropertyValue& rProp : aRenderer )
+ {
+ if ( rProp.Name == "PageSize" )
+ {
+ rProp.Value >>= aPageSize;
+ break;
+ }
+ }
+
+ rPDFExtOutDevData.SetCurrentPageNumber( nCurrentPage );
+
+ GDIMetaFile aMtf;
+ const MapMode aMapMode( MapUnit::Map100thMM );
+ const Size aMtfSize( aPageSize.Width, aPageSize.Height );
+
+ pOut->Push();
+ pOut->EnableOutput( false );
+ pOut->SetMapMode( aMapMode );
+
+ aMtf.SetPrefSize( aMtfSize );
+ aMtf.SetPrefMapMode( aMapMode );
+ aMtf.Record( pOut );
+
+ // #i35176#
+ // IsLastPage property.
+ const sal_Int32 nCurrentRenderer = *aIter;
+ ++aIter;
+ if ( pLastPage && aIter == aEnd )
+ *pLastPage <<= true;
+
+ rRenderable->render( nCurrentRenderer, rSelection, rRenderOptions );
+
+ aMtf.Stop();
+ aMtf.WindStart();
+
+ bool bEmptyPage = false;
+ if( aMtf.GetActionSize() &&
+ ( !mbSkipEmptyPages || aPageSize.Width || aPageSize.Height ) )
+ {
+ // We convert the whole metafile into a bitmap to get rid of the
+ // text covered by redaction shapes
+ if (mbIsRedactMode)
+ {
+ try
+ {
+ Graphic aGraph(aMtf);
+ // use antialiasing to improve how graphic objects look
+ BitmapEx bmp = aGraph.GetBitmapEx(GraphicConversionParameters(Size(0, 0), false, true, false));
+ Graphic bgraph(bmp);
+ aMtf = bgraph.GetGDIMetaFile();
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.pdf", "Something went wrong while converting metafile to bitmap");
+ }
+ }
+
+ ImplExportPage(rPDFWriter, rPDFExtOutDevData, aMtf);
+ bRet = true;
+ }
+ else
+ {
+ bEmptyPage = true;
+ }
+
+ pOut->Pop();
+
+ if ( mxStatusIndicator.is() )
+ mxStatusIndicator->setValue( mnProgressValue );
+ if ( pFirstPage )
+ *pFirstPage <<= false;
+
+ ++mnProgressValue;
+ if (!bEmptyPage)
+ {
+ // Calculate the page number in the PDF output, which may be smaller than the page number in
+ // case of hidden slides or a partial export.
+ ++nCurrentPage;
+ }
+ }
+ }
+ else
+ {
+ bRet = true; // #i18334# nPageCount == 0,
+ rPDFWriter.NewPage( 10000, 10000 ); // creating dummy page
+ rPDFWriter.SetMapMode(MapMode(MapUnit::Map100thMM));
+ }
+ }
+ }
+ catch(const RuntimeException &)
+ {
+ }
+ return bRet;
+}
+
+namespace {
+
+class PDFExportStreamDoc : public vcl::PDFOutputStream
+{
+private:
+
+ Reference< XComponent > m_xSrcDoc;
+ Sequence< beans::NamedValue > m_aPreparedPassword;
+
+public:
+
+ PDFExportStreamDoc( const Reference< XComponent >& xDoc, const Sequence<beans::NamedValue>& rPwd )
+ : m_xSrcDoc( xDoc ),
+ m_aPreparedPassword( rPwd )
+ {}
+
+ virtual void write( const Reference< XOutputStream >& xStream ) override;
+};
+
+}
+
+void PDFExportStreamDoc::write( const Reference< XOutputStream >& xStream )
+{
+ Reference< css::frame::XStorable > xStore( m_xSrcDoc, UNO_QUERY );
+ if( !xStore.is() )
+ return;
+
+ Sequence< beans::PropertyValue > aArgs( 2 + (m_aPreparedPassword.hasElements() ? 1 : 0) );
+ aArgs.getArray()[0].Name = "FilterName";
+ aArgs.getArray()[1].Name = "OutputStream";
+ aArgs.getArray()[1].Value <<= xStream;
+ if( m_aPreparedPassword.hasElements() )
+ {
+ aArgs.getArray()[2].Name = "EncryptionData";
+ aArgs.getArray()[2].Value <<= m_aPreparedPassword;
+ }
+
+ try
+ {
+ xStore->storeToURL( "private:stream", aArgs );
+ }
+ catch( const IOException& )
+ {
+ }
+}
+
+
+static OUString getMimetypeForDocument( const Reference< XComponentContext >& xContext,
+ const Reference< XComponent >& xDoc ) noexcept
+{
+ OUString aDocMimetype;
+ try
+ {
+ // get document service name
+ Reference< css::frame::XStorable > xStore( xDoc, UNO_QUERY );
+ Reference< frame::XModuleManager2 > xModuleManager = frame::ModuleManager::create(xContext);
+ if( xStore.is() )
+ {
+ OUString aDocServiceName = xModuleManager->identify( Reference< XInterface >( xStore, uno::UNO_QUERY ) );
+ if ( !aDocServiceName.isEmpty() )
+ {
+ // get the actual filter name
+ Reference< lang::XMultiServiceFactory > xConfigProvider =
+ configuration::theDefaultProvider::get( xContext );
+ beans::NamedValue aPathProp;
+ aPathProp.Name = "nodepath";
+ aPathProp.Value <<= OUString( "/org.openoffice.Setup/Office/Factories/" );
+ uno::Sequence< uno::Any > aArgs{ uno::Any(aPathProp) };
+
+ Reference< container::XNameAccess > xSOFConfig(
+ xConfigProvider->createInstanceWithArguments(
+ "com.sun.star.configuration.ConfigurationAccess", aArgs ),
+ uno::UNO_QUERY );
+
+ Reference< container::XNameAccess > xApplConfig;
+ xSOFConfig->getByName( aDocServiceName ) >>= xApplConfig;
+ if ( xApplConfig.is() )
+ {
+ OUString aFilterName;
+ xApplConfig->getByName( "ooSetupFactoryActualFilter" ) >>= aFilterName;
+ if( !aFilterName.isEmpty() )
+ {
+ // find the related type name
+ OUString aTypeName;
+ Reference< container::XNameAccess > xFilterFactory(
+ xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.FilterFactory", xContext),
+ uno::UNO_QUERY );
+
+ Sequence< beans::PropertyValue > aFilterData;
+ xFilterFactory->getByName( aFilterName ) >>= aFilterData;
+ for ( const beans::PropertyValue& rProp : std::as_const(aFilterData) )
+ if ( rProp.Name == "Type" )
+ rProp.Value >>= aTypeName;
+
+ if ( !aTypeName.isEmpty() )
+ {
+ // find the mediatype
+ Reference< container::XNameAccess > xTypeDetection(
+ xContext->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", xContext),
+ UNO_QUERY );
+
+ Sequence< beans::PropertyValue > aTypeData;
+ xTypeDetection->getByName( aTypeName ) >>= aTypeData;
+ for ( const beans::PropertyValue& rProp : std::as_const(aTypeData) )
+ if ( rProp.Name == "MediaType" )
+ rProp.Value >>= aDocMimetype;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ }
+ return aDocMimetype;
+}
+
+uno::Reference<security::XCertificate>
+PDFExport::GetCertificateFromSubjectName(const std::u16string_view& rSubjectName) const
+{
+ uno::Reference<xml::crypto::XSEInitializer> xSEInitializer
+ = xml::crypto::SEInitializer::create(mxContext);
+ uno::Reference<xml::crypto::XXMLSecurityContext> xSecurityContext
+ = xSEInitializer->createSecurityContext(OUString());
+ uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
+ = xSecurityContext->getSecurityEnvironment();
+ for (const auto& xCertificate : xSecurityEnvironment->getPersonalCertificates())
+ {
+ if (xCertificate->getSubjectName() == rSubjectName)
+ {
+ return xCertificate;
+ }
+ }
+
+ return {};
+}
+
+bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >& rFilterData )
+{
+ INetURLObject aURL( rFile );
+ bool bRet = false;
+
+ std::set< vcl::PDFWriter::ErrorCode > aErrors;
+
+ if( aURL.GetProtocol() != INetProtocol::File )
+ {
+ OUString aTmp;
+
+ if( osl::FileBase::getFileURLFromSystemPath( rFile, aTmp ) == osl::FileBase::E_None )
+ aURL = INetURLObject(aTmp);
+ }
+
+ if( aURL.GetProtocol() == INetProtocol::File )
+ {
+ Reference< XRenderable > xRenderable( mxSrcDoc, UNO_QUERY );
+
+ if( xRenderable.is() )
+ {
+ rtl::Reference<VCLXDevice> xDevice(new VCLXDevice);
+ OUString aPageRange;
+ Any aSelection;
+ vcl::PDFWriter::PDFWriterContext aContext;
+ OUString aOpenPassword, aPermissionPassword;
+ Reference< beans::XMaterialHolder > xEnc;
+ Sequence< beans::NamedValue > aPreparedPermissionPassword;
+
+
+ // getting the string for the creator
+ OUString aCreator;
+ Reference< XServiceInfo > xInfo( mxSrcDoc, UNO_QUERY );
+ if ( xInfo.is() )
+ {
+ if ( xInfo->supportsService( "com.sun.star.presentation.PresentationDocument" ) )
+ aCreator += "Impress";
+ else if ( xInfo->supportsService( "com.sun.star.drawing.DrawingDocument" ) )
+ aCreator += "Draw";
+ else if ( xInfo->supportsService( "com.sun.star.text.TextDocument" ) )
+ aCreator += "Writer";
+ else if ( xInfo->supportsService( "com.sun.star.sheet.SpreadsheetDocument" ) )
+ aCreator += "Calc";
+ else if ( xInfo->supportsService( "com.sun.star.formula.FormulaProperties" ) )
+ aCreator += "Math";
+ }
+
+ Reference< document::XDocumentPropertiesSupplier > xDocumentPropsSupplier( mxSrcDoc, UNO_QUERY );
+ if ( xDocumentPropsSupplier.is() )
+ {
+ Reference< document::XDocumentProperties > xDocumentProps( xDocumentPropsSupplier->getDocumentProperties() );
+ if ( xDocumentProps.is() )
+ {
+ aContext.DocumentInfo.Title = xDocumentProps->getTitle();
+ aContext.DocumentInfo.Author = xDocumentProps->getAuthor();
+ aContext.DocumentInfo.Subject = xDocumentProps->getSubject();
+ aContext.DocumentInfo.Keywords = ::comphelper::string::convertCommaSeparated(xDocumentProps->getKeywords());
+ }
+ }
+ // getting the string for the producer
+ OUString aProducerOverride = officecfg::Office::Common::Save::Document::GeneratorOverride::get();
+ if( !aProducerOverride.isEmpty())
+ aContext.DocumentInfo.Producer = aProducerOverride;
+ else
+ aContext.DocumentInfo.Producer =
+ utl::ConfigManager::getProductName() +
+ " " +
+ utl::ConfigManager::getProductVersion();
+
+ aContext.DocumentInfo.Creator = aCreator;
+
+ OUString aSignCertificateSubjectName;
+ for ( const beans::PropertyValue& rProp : rFilterData )
+ {
+ if ( rProp.Name == "PageRange" )
+ rProp.Value >>= aPageRange;
+ else if ( rProp.Name == "Selection" )
+ aSelection = rProp.Value;
+ else if ( rProp.Name == "UseLosslessCompression" )
+ rProp.Value >>= mbUseLosslessCompression;
+ else if ( rProp.Name == "Quality" )
+ rProp.Value >>= mnQuality;
+ else if ( rProp.Name == "ReduceImageResolution" )
+ rProp.Value >>= mbReduceImageResolution;
+ else if ( rProp.Name == "IsSkipEmptyPages" )
+ rProp.Value >>= mbSkipEmptyPages;
+ else if ( rProp.Name == "MaxImageResolution" )
+ rProp.Value >>= mnMaxImageResolution;
+ else if ( rProp.Name == "UseTaggedPDF" )
+ rProp.Value >>= mbUseTaggedPDF;
+ else if ( rProp.Name == "SelectPdfVersion" )
+ rProp.Value >>= mnPDFTypeSelection;
+ else if ( rProp.Name == "PDFUACompliance" )
+ rProp.Value >>= mbPDFUACompliance;
+ else if ( rProp.Name == "ExportNotes" )
+ rProp.Value >>= mbExportNotes;
+ else if ( rProp.Name == "ExportNotesPages" )
+ rProp.Value >>= mbExportNotesPages;
+ else if ( rProp.Name == "ExportOnlyNotesPages" )
+ rProp.Value >>= mbExportOnlyNotesPages;
+ else if ( rProp.Name == "UseTransitionEffects" )
+ rProp.Value >>= mbUseTransitionEffects;
+ else if ( rProp.Name == "ExportFormFields" )
+ rProp.Value >>= mbExportFormFields;
+ else if ( rProp.Name == "FormsType" )
+ rProp.Value >>= mnFormsFormat;
+ else if ( rProp.Name == "AllowDuplicateFieldNames" )
+ rProp.Value >>= mbAllowDuplicateFieldNames;
+ // viewer properties
+ else if ( rProp.Name == "HideViewerToolbar" )
+ rProp.Value >>= mbHideViewerToolbar;
+ else if ( rProp.Name == "HideViewerMenubar" )
+ rProp.Value >>= mbHideViewerMenubar;
+ else if ( rProp.Name == "HideViewerWindowControls" )
+ rProp.Value >>= mbHideViewerWindowControls;
+ else if ( rProp.Name == "ResizeWindowToInitialPage" )
+ rProp.Value >>= mbFitWindow;
+ else if ( rProp.Name == "CenterWindow" )
+ rProp.Value >>= mbCenterWindow;
+ else if ( rProp.Name == "OpenInFullScreenMode" )
+ rProp.Value >>= mbOpenInFullScreenMode;
+ else if ( rProp.Name == "DisplayPDFDocumentTitle" )
+ rProp.Value >>= mbDisplayPDFDocumentTitle;
+ else if ( rProp.Name == "InitialView" )
+ rProp.Value >>= mnPDFDocumentMode;
+ else if ( rProp.Name == "Magnification" )
+ rProp.Value >>= mnPDFDocumentAction;
+ else if ( rProp.Name == "Zoom" )
+ rProp.Value >>= mnZoom;
+ else if ( rProp.Name == "InitialPage" )
+ rProp.Value >>= mnInitialPage;
+ else if ( rProp.Name == "PageLayout" )
+ rProp.Value >>= mnPDFPageLayout;
+ else if ( rProp.Name == "FirstPageOnLeft" )
+ rProp.Value >>= aContext.FirstPageLeft;
+ else if ( rProp.Name == "IsAddStream" )
+ rProp.Value >>= mbAddStream;
+ else if ( rProp.Name == "Watermark" )
+ rProp.Value >>= msWatermark;
+ else if ( rProp.Name == "WatermarkColor" )
+ {
+ sal_Int32 nColor{};
+ if (rProp.Value >>= nColor)
+ {
+ maWatermarkColor = Color(ColorTransparency, nColor);
+ }
+ }
+ else if (rProp.Name == "WatermarkFontHeight")
+ {
+ sal_Int32 nFontHeight{};
+ if (rProp.Value >>= nFontHeight)
+ {
+ moWatermarkFontHeight = nFontHeight;
+ }
+ }
+ else if (rProp.Name == "WatermarkRotateAngle")
+ {
+ sal_Int32 nRotateAngle{};
+ if (rProp.Value >>= nRotateAngle)
+ {
+ moWatermarkRotateAngle = Degree10(nRotateAngle);
+ }
+ }
+ else if (rProp.Name == "WatermarkFontName")
+ {
+ OUString aFontName{};
+ if (rProp.Value >>= aFontName)
+ {
+ maWatermarkFontName = aFontName;
+ }
+ }
+ else if ( rProp.Name == "TiledWatermark" )
+ rProp.Value >>= msTiledWatermark;
+ // now all the security related properties...
+ else if ( rProp.Name == "EncryptFile" )
+ rProp.Value >>= mbEncrypt;
+ else if ( rProp.Name == "DocumentOpenPassword" )
+ rProp.Value >>= aOpenPassword;
+ else if ( rProp.Name == "RestrictPermissions" )
+ rProp.Value >>= mbRestrictPermissions;
+ else if ( rProp.Name == "PermissionPassword" )
+ rProp.Value >>= aPermissionPassword;
+ else if ( rProp.Name == "PreparedPasswords" )
+ rProp.Value >>= xEnc;
+ else if ( rProp.Name == "PreparedPermissionPassword" )
+ rProp.Value >>= aPreparedPermissionPassword;
+ else if ( rProp.Name == "Printing" )
+ rProp.Value >>= mnPrintAllowed;
+ else if ( rProp.Name == "Changes" )
+ rProp.Value >>= mnChangesAllowed;
+ else if ( rProp.Name == "EnableCopyingOfContent" )
+ rProp.Value >>= mbCanCopyOrExtract;
+ else if ( rProp.Name == "EnableTextAccessForAccessibilityTools" )
+ rProp.Value >>= mbCanExtractForAccessibility;
+ // i56629 links extra (relative links and other related stuff)
+ else if ( rProp.Name == "ExportLinksRelativeFsys" )
+ rProp.Value >>= mbExportRelativeFsysLinks;
+ else if ( rProp.Name == "PDFViewSelection" )
+ rProp.Value >>= mnDefaultLinkAction;
+ else if ( rProp.Name == "ConvertOOoTargetToPDFTarget" )
+ rProp.Value >>= mbConvertOOoTargetToPDFTarget;
+ else if ( rProp.Name == "ExportBookmarksToPDFDestination" )
+ rProp.Value >>= mbExportBmkToDest;
+ else if ( rProp.Name == "ExportBookmarks" )
+ rProp.Value >>= mbExportBookmarks;
+ else if ( rProp.Name == "ExportHiddenSlides" )
+ rProp.Value >>= mbExportHiddenSlides;
+ else if ( rProp.Name == "SinglePageSheets" )
+ rProp.Value >>= mbSinglePageSheets;
+ else if ( rProp.Name == "OpenBookmarkLevels" )
+ rProp.Value >>= mnOpenBookmarkLevels;
+ else if ( rProp.Name == "SignPDF" )
+ rProp.Value >>= mbSignPDF;
+ else if ( rProp.Name == "SignatureLocation" )
+ rProp.Value >>= msSignLocation;
+ else if ( rProp.Name == "SignatureReason" )
+ rProp.Value >>= msSignReason;
+ else if ( rProp.Name == "SignatureContactInfo" )
+ rProp.Value >>= msSignContact;
+ else if ( rProp.Name == "SignaturePassword" )
+ rProp.Value >>= msSignPassword;
+ else if ( rProp.Name == "SignatureCertificate" )
+ rProp.Value >>= maSignCertificate;
+ else if (rProp.Name == "SignCertificateSubjectName")
+ rProp.Value >>= aSignCertificateSubjectName;
+ else if ( rProp.Name == "SignatureTSA" )
+ rProp.Value >>= msSignTSA;
+ else if ( rProp.Name == "ExportPlaceholders" )
+ rProp.Value >>= mbExportPlaceholders;
+ else if ( rProp.Name == "UseReferenceXObject" )
+ rProp.Value >>= mbUseReferenceXObject;
+ // Redaction & bitmap related stuff
+ else if ( rProp.Name == "IsRedactMode" )
+ rProp.Value >>= mbIsRedactMode;
+ }
+
+ if (!maSignCertificate.is() && !aSignCertificateSubjectName.isEmpty())
+ {
+ maSignCertificate = GetCertificateFromSubjectName(aSignCertificateSubjectName);
+ }
+
+ aContext.URL = aURL.GetMainURL(INetURLObject::DecodeMechanism::ToIUri);
+
+ // set the correct version, depending on user request
+ switch( mnPDFTypeSelection )
+ {
+ default:
+ case 0:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_6;
+ break;
+ case 1:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_1;
+ mbUseTaggedPDF = true; // force the tagged PDF as well
+ mbRemoveTransparencies = true; // does not allow transparencies
+ mbEncrypt = false; // no encryption
+ xEnc.clear();
+ break;
+ case 2:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_2;
+ mbUseTaggedPDF = true; // force the tagged PDF as well
+ mbRemoveTransparencies = false; // does allow transparencies
+ mbEncrypt = false; // no encryption
+ xEnc.clear();
+ break;
+ case 3:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_A_3;
+ mbUseTaggedPDF = true; // force the tagged PDF as well
+ mbRemoveTransparencies = false; // does allow transparencies
+ mbEncrypt = false; // no encryption
+ xEnc.clear();
+ break;
+ case 15:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_5;
+ break;
+ case 16:
+ aContext.Version = vcl::PDFWriter::PDFVersion::PDF_1_6;
+ break;
+ }
+
+ // PDF/UA support
+ aContext.UniversalAccessibilityCompliance = mbPDFUACompliance;
+ if (mbPDFUACompliance)
+ {
+ mbUseTaggedPDF = true;
+ }
+
+ // copy in context the values default in the constructor or set by the FilterData sequence of properties
+ aContext.Tagged = mbUseTaggedPDF;
+
+ // values used in viewer
+ aContext.HideViewerToolbar = mbHideViewerToolbar;
+ aContext.HideViewerMenubar = mbHideViewerMenubar;
+ aContext.HideViewerWindowControls = mbHideViewerWindowControls;
+ aContext.FitWindow = mbFitWindow;
+ aContext.CenterWindow = mbCenterWindow;
+ aContext.OpenInFullScreenMode = mbOpenInFullScreenMode;
+ aContext.DisplayPDFDocumentTitle = mbDisplayPDFDocumentTitle;
+ aContext.InitialPage = mnInitialPage-1;
+ aContext.OpenBookmarkLevels = mnOpenBookmarkLevels;
+
+ switch( mnPDFDocumentMode )
+ {
+ default:
+ case 0:
+ aContext.PDFDocumentMode = vcl::PDFWriter::ModeDefault;
+ break;
+ case 1:
+ aContext.PDFDocumentMode = vcl::PDFWriter::UseOutlines;
+ break;
+ case 2:
+ aContext.PDFDocumentMode = vcl::PDFWriter::UseThumbs;
+ break;
+ }
+ switch( mnPDFDocumentAction )
+ {
+ default:
+ case 0:
+ aContext.PDFDocumentAction = vcl::PDFWriter::ActionDefault;
+ break;
+ case 1:
+ aContext.PDFDocumentAction = vcl::PDFWriter::FitInWindow;
+ break;
+ case 2:
+ aContext.PDFDocumentAction = vcl::PDFWriter::FitWidth;
+ break;
+ case 3:
+ aContext.PDFDocumentAction = vcl::PDFWriter::FitVisible;
+ break;
+ case 4:
+ aContext.PDFDocumentAction = vcl::PDFWriter::ActionZoom;
+ aContext.Zoom = mnZoom;
+ break;
+ }
+
+ switch( mnPDFPageLayout )
+ {
+ default:
+ case 0:
+ aContext.PageLayout = vcl::PDFWriter::DefaultLayout;
+ break;
+ case 1:
+ aContext.PageLayout = vcl::PDFWriter::SinglePage;
+ break;
+ case 2:
+ aContext.PageLayout = vcl::PDFWriter::Continuous;
+ break;
+ case 3:
+ aContext.PageLayout = vcl::PDFWriter::ContinuousFacing;
+ break;
+ }
+
+ aContext.FirstPageLeft = false;
+
+ // check if PDF/A, which does not allow encryption
+ if( aContext.Version != vcl::PDFWriter::PDFVersion::PDF_A_1 )
+ {
+ // set check for permission change password
+ // if not enabled and no permission password, force permissions to default as if PDF where without encryption
+ if( mbRestrictPermissions && (xEnc.is() || !aPermissionPassword.isEmpty()) )
+ {
+ mbEncrypt = true; // permission set as desired, done after
+ }
+ else
+ {
+ // force permission to default
+ mnPrintAllowed = 2 ;
+ mnChangesAllowed = 4 ;
+ mbCanCopyOrExtract = true;
+ mbCanExtractForAccessibility = true ;
+ }
+
+ switch( mnPrintAllowed )
+ {
+ case 0: // initialized when aContext is build, means no printing
+ break;
+ default:
+ case 2:
+ aContext.Encryption.CanPrintFull = true;
+ [[fallthrough]];
+ case 1:
+ aContext.Encryption.CanPrintTheDocument = true;
+ break;
+ }
+
+ switch( mnChangesAllowed )
+ {
+ case 0: // already in struct PDFSecPermissions CTOR
+ break;
+ case 1:
+ aContext.Encryption.CanAssemble = true;
+ break;
+ case 2:
+ aContext.Encryption.CanFillInteractive = true;
+ break;
+ case 3:
+ aContext.Encryption.CanAddOrModify = true;
+ break;
+ default:
+ case 4:
+ aContext.Encryption.CanModifyTheContent =
+ aContext.Encryption.CanCopyOrExtract =
+ aContext.Encryption.CanAddOrModify =
+ aContext.Encryption.CanFillInteractive = true;
+ break;
+ }
+
+ aContext.Encryption.CanCopyOrExtract = mbCanCopyOrExtract;
+ aContext.Encryption.CanExtractForAccessibility = mbCanExtractForAccessibility;
+ if( mbEncrypt && ! xEnc.is() )
+ xEnc = vcl::PDFWriter::InitEncryption( aPermissionPassword, aOpenPassword );
+ if( mbEncrypt && !aPermissionPassword.isEmpty() && ! aPreparedPermissionPassword.hasElements() )
+ aPreparedPermissionPassword = comphelper::OStorageHelper::CreatePackageEncryptionData( aPermissionPassword );
+ }
+ // after this point we don't need the legacy clear passwords anymore
+ // however they are still inside the passed filter data sequence
+ // which is sadly out of our control
+ aPermissionPassword.clear();
+ aOpenPassword.clear();
+
+ /*
+ * FIXME: the entries are only implicitly defined by the resource file. Should there
+ * ever be an additional form submit format this could get invalid.
+ */
+ switch( mnFormsFormat )
+ {
+ case 1:
+ aContext.SubmitFormat = vcl::PDFWriter::PDF;
+ break;
+ case 2:
+ aContext.SubmitFormat = vcl::PDFWriter::HTML;
+ break;
+ case 3:
+ aContext.SubmitFormat = vcl::PDFWriter::XML;
+ break;
+ default:
+ case 0:
+ aContext.SubmitFormat = vcl::PDFWriter::FDF;
+ break;
+ }
+ aContext.AllowDuplicateFieldNames = mbAllowDuplicateFieldNames;
+
+ // get model
+ Reference< frame::XModel > xModel( mxSrcDoc, UNO_QUERY );
+ {
+ // #i56629: Relative link stuff
+ // set the base URL of the file: then base URL
+ aContext.BaseURL = xModel->getURL();
+ // relative link option is private to PDF Export filter and limited to local filesystem only
+ aContext.RelFsys = mbExportRelativeFsysLinks;
+ // determine the default acton for PDF links
+ switch( mnDefaultLinkAction )
+ {
+ default:
+ // default: URI, without fragment conversion (the bookmark in PDF may not work)
+ case 0:
+ aContext.DefaultLinkAction = vcl::PDFWriter::URIAction;
+ break;
+ case 1:
+ // view PDF through the reader application
+ aContext.ForcePDFAction = true;
+ aContext.DefaultLinkAction = vcl::PDFWriter::LaunchAction;
+ break;
+ case 2:
+ // view PDF through an Internet browser
+ aContext.DefaultLinkAction = vcl::PDFWriter::URIActionDestination;
+ break;
+ }
+ aContext.ConvertOOoTargetToPDFTarget = mbConvertOOoTargetToPDFTarget;
+
+ // check for Link Launch action, not allowed on PDF/A-1
+ // this code chunk checks when the filter is called from scripting
+ if( aContext.Version == vcl::PDFWriter::PDFVersion::PDF_A_1 &&
+ aContext.DefaultLinkAction == vcl::PDFWriter::LaunchAction )
+ {
+ // force the similar allowed URI action
+ aContext.DefaultLinkAction = vcl::PDFWriter::URIActionDestination;
+ // and remove the remote goto action forced on PDF file
+ aContext.ForcePDFAction = false;
+ }
+ }
+
+ aContext.SignPDF = mbSignPDF;
+ aContext.SignLocation = msSignLocation;
+ aContext.SignContact = msSignContact;
+ aContext.SignReason = msSignReason;
+ aContext.SignPassword = msSignPassword;
+ aContext.SignCertificate = maSignCertificate;
+ aContext.SignTSA = msSignTSA;
+ aContext.UseReferenceXObject = mbUseReferenceXObject;
+
+ // all context data set, time to create the printing device
+ vcl::PDFWriter aPDFWriter( aContext, xEnc );
+ OutputDevice* pOut = aPDFWriter.GetReferenceDevice();
+
+ DBG_ASSERT( pOut, "PDFExport::Export: no reference device" );
+ xDevice->SetOutputDevice(pOut);
+
+ if( mbAddStream )
+ {
+ // export stream
+ // get mimetype
+ OUString aSrcMimetype = getMimetypeForDocument( mxContext, mxSrcDoc );
+ aPDFWriter.AddStream( aSrcMimetype,
+ new PDFExportStreamDoc( mxSrcDoc, aPreparedPermissionPassword )
+ );
+ }
+
+ if ( pOut )
+ {
+ DBG_ASSERT( pOut->GetExtOutDevData() == nullptr, "PDFExport: ExtOutDevData already set!!!" );
+ vcl::PDFExtOutDevData aPDFExtOutDevData( *pOut );
+ pOut->SetExtOutDevData( &aPDFExtOutDevData );
+ aPDFExtOutDevData.SetIsExportNotes( mbExportNotes );
+ aPDFExtOutDevData.SetIsExportTaggedPDF( mbUseTaggedPDF );
+ aPDFExtOutDevData.SetIsExportTransitionEffects( mbUseTransitionEffects );
+ aPDFExtOutDevData.SetIsExportFormFields( mbExportFormFields );
+ aPDFExtOutDevData.SetIsExportBookmarks( mbExportBookmarks );
+ aPDFExtOutDevData.SetIsExportHiddenSlides( mbExportHiddenSlides );
+ aPDFExtOutDevData.SetIsSinglePageSheets( mbSinglePageSheets );
+ aPDFExtOutDevData.SetIsLosslessCompression( mbUseLosslessCompression );
+ aPDFExtOutDevData.SetCompressionQuality( mnQuality );
+ aPDFExtOutDevData.SetIsReduceImageResolution( mbReduceImageResolution );
+ aPDFExtOutDevData.SetIsExportNamedDestinations( mbExportBmkToDest );
+
+ Sequence< PropertyValue > aRenderOptions{
+ comphelper::makePropertyValue("RenderDevice", uno::Reference<awt::XDevice>(xDevice)),
+ comphelper::makePropertyValue("ExportNotesPages", false),
+ comphelper::makePropertyValue("IsFirstPage", true),
+ comphelper::makePropertyValue("IsLastPage", false),
+ comphelper::makePropertyValue("IsSkipEmptyPages", mbSkipEmptyPages),
+ comphelper::makePropertyValue("PageRange", aPageRange),
+ comphelper::makePropertyValue("ExportPlaceholders", mbExportPlaceholders),
+ comphelper::makePropertyValue("SinglePageSheets", mbSinglePageSheets)
+ };
+ Any& rExportNotesValue = aRenderOptions.getArray()[ 1 ].Value;
+
+ if( !aPageRange.isEmpty() || !aSelection.hasValue() )
+ {
+ aSelection = Any();
+ aSelection <<= mxSrcDoc;
+ }
+ bool bExportNotesPages = false;
+ bool bReChangeToNormalView = false;
+ static const OUStringLiteral sShowOnlineLayout( u"ShowOnlineLayout" );
+ bool bReHideWhitespace = false;
+ static const OUStringLiteral sHideWhitespace(u"HideWhitespace");
+ uno::Reference< beans::XPropertySet > xViewProperties;
+
+ if ( aCreator == "Writer" )
+ {
+ // #i92835: if Writer is in web layout mode this has to be switched to normal view and back to web view in the end
+ try
+ {
+ Reference< view::XViewSettingsSupplier > xVSettingsSupplier( xModel->getCurrentController(), uno::UNO_QUERY_THROW );
+ xViewProperties = xVSettingsSupplier->getViewSettings();
+ xViewProperties->getPropertyValue( sShowOnlineLayout ) >>= bReChangeToNormalView;
+ if( bReChangeToNormalView )
+ {
+ xViewProperties->setPropertyValue( sShowOnlineLayout, uno::Any( false ) );
+ }
+
+ // Also, disable hide-whitespace during export.
+ xViewProperties->getPropertyValue(sHideWhitespace) >>= bReHideWhitespace;
+ if (bReHideWhitespace)
+ {
+ xViewProperties->setPropertyValue(sHideWhitespace, uno::Any(false));
+ }
+ }
+ catch( const uno::Exception& )
+ {
+ }
+
+ }
+
+ const sal_Int32 nPageCount = xRenderable->getRendererCount( aSelection, aRenderOptions );
+
+ if ( mbExportNotesPages && aCreator == "Impress" )
+ {
+ uno::Reference< drawing::XShapes > xShapes; // do not allow to export notes when exporting a selection
+ if ( ! ( aSelection >>= xShapes ) )
+ bExportNotesPages = true;
+ }
+ const bool bExportPages = !bExportNotesPages || !mbExportOnlyNotesPages;
+
+ if( aPageRange.isEmpty() || mbSinglePageSheets)
+ {
+ aPageRange = OUString::number( 1 ) + "-" + OUString::number(nPageCount );
+ }
+ StringRangeEnumerator aRangeEnum( aPageRange, 0, nPageCount-1 );
+
+ if ( mxStatusIndicator.is() )
+ {
+ std::locale loc(Translate::Create("flt"));
+ sal_Int32 nTotalPageCount = aRangeEnum.size();
+ if ( bExportPages && bExportNotesPages )
+ nTotalPageCount *= 2;
+ mxStatusIndicator->start(Translate::get(PDF_PROGRESS_BAR, loc), nTotalPageCount);
+ }
+
+ bRet = nPageCount > 0;
+
+ if ( bRet && bExportPages )
+ bRet = ExportSelection( aPDFWriter, xRenderable, aSelection, aRangeEnum, aRenderOptions, nPageCount );
+
+ if ( bRet && bExportNotesPages )
+ {
+ rExportNotesValue <<= true;
+ bRet = ExportSelection( aPDFWriter, xRenderable, aSelection, aRangeEnum, aRenderOptions, nPageCount );
+ }
+ if ( mxStatusIndicator.is() )
+ mxStatusIndicator->end();
+
+ // if during the export the doc locale was set copy it to PDF writer
+ const css::lang::Locale& rLoc( aPDFExtOutDevData.GetDocumentLocale() );
+ if( !rLoc.Language.isEmpty() )
+ aPDFWriter.SetDocumentLocale( rLoc );
+
+ if( bRet )
+ {
+ aPDFExtOutDevData.PlayGlobalActions( aPDFWriter );
+ bRet = aPDFWriter.Emit();
+ aErrors = aPDFWriter.GetErrors();
+ }
+ pOut->SetExtOutDevData( nullptr );
+ if( bReChangeToNormalView )
+ {
+ try
+ {
+ xViewProperties->setPropertyValue( sShowOnlineLayout, uno::Any( true ) );
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ if( bReHideWhitespace )
+ {
+ try
+ {
+ xViewProperties->setPropertyValue( sHideWhitespace, uno::Any( true ) );
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ }
+ }
+ }
+
+ // show eventual errors during export
+ showErrors( aErrors );
+
+ return bRet;
+}
+
+
+namespace
+{
+
+typedef cppu::WeakComponentImplHelper< task::XInteractionRequest > PDFErrorRequestBase;
+
+class PDFErrorRequest : private cppu::BaseMutex,
+ public PDFErrorRequestBase
+{
+ task::PDFExportException maExc;
+public:
+ explicit PDFErrorRequest( task::PDFExportException aExc );
+
+ // XInteractionRequest
+ virtual uno::Any SAL_CALL getRequest() override;
+ virtual uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL getContinuations() override;
+};
+
+
+PDFErrorRequest::PDFErrorRequest( task::PDFExportException aExc ) :
+ PDFErrorRequestBase( m_aMutex ),
+ maExc(std::move( aExc ))
+{
+}
+
+
+uno::Any SAL_CALL PDFErrorRequest::getRequest()
+{
+ osl::MutexGuard const guard( m_aMutex );
+
+ uno::Any aRet;
+ aRet <<= maExc;
+ return aRet;
+}
+
+
+uno::Sequence< uno::Reference< task::XInteractionContinuation > > SAL_CALL PDFErrorRequest::getContinuations()
+{
+ return uno::Sequence< uno::Reference< task::XInteractionContinuation > >();
+}
+
+} // end anonymous namespace
+
+
+void PDFExport::showErrors( const std::set< vcl::PDFWriter::ErrorCode >& rErrors )
+{
+ if( ! rErrors.empty() && mxIH.is() )
+ {
+ task::PDFExportException aExc;
+ aExc.ErrorCodes = comphelper::containerToSequence<sal_Int32>( rErrors );
+ Reference< task::XInteractionRequest > xReq( new PDFErrorRequest( std::move(aExc) ) );
+ mxIH->handle( xReq );
+ }
+}
+
+
+void PDFExport::ImplExportPage( vcl::PDFWriter& rWriter, vcl::PDFExtOutDevData& rPDFExtOutDevData, const GDIMetaFile& rMtf )
+{
+ //Rectangle(Point, Size) creates a rectangle off by 1, use Rectangle(long, long, long, long) instead
+ basegfx::B2DPolygon aSize(tools::Polygon(tools::Rectangle(0, 0, rMtf.GetPrefSize().Width(), rMtf.GetPrefSize().Height())).getB2DPolygon());
+ basegfx::B2DPolygon aSizePDF(OutputDevice::LogicToLogic(aSize, rMtf.GetPrefMapMode(), MapMode(MapUnit::MapPoint)));
+ basegfx::B2DRange aRangePDF(aSizePDF.getB2DRange());
+ tools::Rectangle aPageRect( Point(), rMtf.GetPrefSize() );
+
+ rWriter.NewPage( aRangePDF.getWidth(), aRangePDF.getHeight() );
+ rWriter.SetMapMode( rMtf.GetPrefMapMode() );
+
+ vcl::PDFWriter::PlayMetafileContext aCtx;
+ GDIMetaFile aMtf;
+ if( mbRemoveTransparencies )
+ {
+ aCtx.m_bTransparenciesWereRemoved = rWriter.GetReferenceDevice()->
+ RemoveTransparenciesFromMetaFile( rMtf, aMtf, mnMaxImageResolution, mnMaxImageResolution,
+ false, true, mbReduceImageResolution );
+ // tdf#134736 if the metafile was replaced then rPDFExtOutDevData's PageSyncData mActions
+ // all still point to MetaAction indexes in the original metafile that are now invalid.
+ // Throw them all away in the absence of a way to reposition them to new positions of
+ // their replacements.
+ if (aCtx.m_bTransparenciesWereRemoved)
+ rPDFExtOutDevData.ResetSyncData();
+ }
+ else
+ {
+ aMtf = rMtf;
+ }
+ aCtx.m_nMaxImageResolution = mbReduceImageResolution ? mnMaxImageResolution : 0;
+ aCtx.m_bOnlyLosslessCompression = mbUseLosslessCompression;
+ aCtx.m_nJPEGQuality = mnQuality;
+
+
+ rWriter.SetClipRegion( basegfx::B2DPolyPolygon(
+ basegfx::utils::createPolygonFromRect( vcl::unotools::b2DRectangleFromRectangle(aPageRect) ) ) );
+
+ rWriter.PlayMetafile( aMtf, aCtx, &rPDFExtOutDevData );
+
+ rPDFExtOutDevData.ResetSyncData();
+
+ if (!msWatermark.isEmpty())
+ {
+ ImplWriteWatermark( rWriter, Size(aRangePDF.getWidth(), aRangePDF.getHeight()) );
+ }
+ else if (!msTiledWatermark.isEmpty())
+ {
+ ImplWriteTiledWatermark( rWriter, Size(aRangePDF.getWidth(), aRangePDF.getHeight()) );
+ }
+}
+
+
+void PDFExport::ImplWriteWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize )
+{
+ vcl::Font aFont( maWatermarkFontName, Size( 0, moWatermarkFontHeight ? *moWatermarkFontHeight : 3*rPageSize.Height()/4 ) );
+ aFont.SetItalic( ITALIC_NONE );
+ aFont.SetWidthType( WIDTH_NORMAL );
+ aFont.SetWeight( WEIGHT_NORMAL );
+ aFont.SetAlignment( ALIGN_BOTTOM );
+ tools::Long nTextWidth = rPageSize.Width();
+ if( rPageSize.Width() < rPageSize.Height() )
+ {
+ nTextWidth = rPageSize.Height();
+ aFont.SetOrientation( 2700_deg10 );
+ }
+
+ if (moWatermarkRotateAngle)
+ {
+ aFont.SetOrientation(*moWatermarkRotateAngle);
+ if (rPageSize.Width() < rPageSize.Height())
+ {
+ // Set text width based on the shorter side, so rotation can't push text outside the
+ // page boundaries.
+ nTextWidth = rPageSize.Width();
+ }
+ }
+
+ // adjust font height for text to fit
+ OutputDevice* pDev = rWriter.GetReferenceDevice();
+ pDev->Push();
+ pDev->SetFont( aFont );
+ pDev->SetMapMode( MapMode( MapUnit::MapPoint ) );
+ int w = 0;
+ if (moWatermarkFontHeight)
+ {
+ w = pDev->GetTextWidth(msWatermark);
+ }
+ else
+ {
+ while( ( w = pDev->GetTextWidth( msWatermark ) ) > nTextWidth )
+ {
+ if (w == 0)
+ break;
+ tools::Long nNewHeight = aFont.GetFontHeight() * nTextWidth / w;
+ if( nNewHeight == aFont.GetFontHeight() )
+ {
+ nNewHeight--;
+ if( nNewHeight <= 0 )
+ break;
+ }
+ aFont.SetFontHeight( nNewHeight );
+ pDev->SetFont( aFont );
+ }
+ }
+ tools::Long nTextHeight = pDev->GetTextHeight();
+ // leave some maneuvering room for rounding issues, also
+ // some fonts go a little outside ascent/descent
+ nTextHeight += nTextHeight/20;
+ pDev->Pop();
+
+ rWriter.Push();
+ rWriter.SetMapMode( MapMode( MapUnit::MapPoint ) );
+ rWriter.SetFont( aFont );
+ rWriter.SetTextColor(maWatermarkColor);
+ Point aTextPoint;
+ tools::Rectangle aTextRect;
+ if( rPageSize.Width() > rPageSize.Height() )
+ {
+ aTextPoint = Point( (rPageSize.Width()-w)/2,
+ rPageSize.Height()-(rPageSize.Height()-nTextHeight)/2 );
+ aTextRect = tools::Rectangle( Point( (rPageSize.Width()-w)/2,
+ (rPageSize.Height()-nTextHeight)/2 ),
+ Size( w, nTextHeight ) );
+ }
+ else
+ {
+ aTextPoint = Point( (rPageSize.Width()-nTextHeight)/2,
+ (rPageSize.Height()-w)/2 );
+ aTextRect = tools::Rectangle( aTextPoint, Size( nTextHeight, w ) );
+ }
+
+ if (moWatermarkRotateAngle)
+ {
+ // First set the text's starting point to the center of the page.
+ tools::Rectangle aPageRectangle(Point(0, 0), rPageSize);
+ aTextPoint = aPageRectangle.Center();
+ // Then adjust it so that the text remains centered, based on the rotation angle.
+ basegfx::B2DPolygon aTextPolygon
+ = basegfx::utils::createPolygonFromRect(basegfx::B2DRectangle(0, -nTextHeight, w, 0));
+ basegfx::B2DHomMatrix aMatrix;
+ aMatrix.rotate(-1 * toRadians(*moWatermarkRotateAngle));
+ aTextPolygon.transform(aMatrix);
+ basegfx::B2DPoint aPolygonCenter = aTextPolygon.getB2DRange().getCenter();
+ aTextPoint.AdjustX(-aPolygonCenter.getX());
+ aTextPoint.AdjustY(-aPolygonCenter.getY());
+
+ aTextRect = aPageRectangle;
+ }
+
+ rWriter.SetClipRegion();
+ rWriter.BeginTransparencyGroup();
+ rWriter.DrawText( aTextPoint, msWatermark );
+ rWriter.EndTransparencyGroup( aTextRect, 50 );
+ rWriter.Pop();
+}
+
+void PDFExport::ImplWriteTiledWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize )
+{
+ OUString watermark = msTiledWatermark;
+ // Maximum number of characters in one line.
+ // it is set to 21 to make it look like tiled watermarks as online in secure view
+ const int lineLength = 21;
+ vcl::Font aFont( "Liberation Sans", Size( 0, 40 ) );
+ aFont.SetItalic( ITALIC_NONE );
+ aFont.SetWidthType( WIDTH_NORMAL );
+ aFont.SetWeight( WEIGHT_NORMAL );
+ aFont.SetAlignment( ALIGN_BOTTOM );
+ aFont.SetFontHeight(40);
+ aFont.SetOrientation(450_deg10);
+
+ OutputDevice* pDev = rWriter.GetReferenceDevice();
+ pDev->SetFont(aFont);
+ pDev->Push();
+ pDev->SetFont(aFont);
+ pDev->SetMapMode( MapMode( MapUnit::MapPoint ) );
+ int w = 0;
+ int watermarkcount = ((rPageSize.Width()) / 200)+1;
+ tools::Long nTextWidth = rPageSize.Width() / (watermarkcount*1.5);
+ OUString oneLineText = watermark;
+
+ if(watermark.getLength() > lineLength)
+ oneLineText = watermark.copy(0, lineLength);
+
+ while((w = pDev->GetTextWidth(oneLineText)) > nTextWidth)
+ {
+ if(w==0)
+ break;
+
+ tools::Long nNewHeight = aFont.GetFontHeight() * nTextWidth / w;
+ aFont.SetFontHeight(nNewHeight);
+ pDev->SetFont( aFont );
+ }
+ // maximum number of watermark count for the width
+ if(watermarkcount > 8)
+ watermarkcount = 8;
+
+ pDev->Pop();
+
+ rWriter.Push();
+ rWriter.SetMapMode( MapMode( MapUnit::MapPoint ) );
+ rWriter.SetFont(aFont);
+ rWriter.SetTextColor( Color(19,20,22) );
+ // center watermarks horizontally
+ Point aTextPoint( (rPageSize.Width()/2) - (((nTextWidth*watermarkcount)+(watermarkcount-1)*nTextWidth)/2),
+ pDev->GetTextHeight());
+
+ for( int i = 0; i < watermarkcount; i ++)
+ {
+ while(aTextPoint.getY()+pDev->GetTextHeight()*3 <= rPageSize.Height())
+ {
+ tools::Rectangle aTextRect(aTextPoint, Size(nTextWidth*2,pDev->GetTextHeight()*4));
+
+ pDev->Push();
+ rWriter.SetClipRegion();
+ rWriter.BeginTransparencyGroup();
+ rWriter.SetTextColor( Color(19,20,22) );
+ rWriter.DrawText(aTextRect, watermark, DrawTextFlags::MultiLine|DrawTextFlags::Center|DrawTextFlags::VCenter|DrawTextFlags::WordBreak|DrawTextFlags::Bottom);
+ rWriter.EndTransparencyGroup( aTextRect, 50 );
+ pDev->Pop();
+
+ pDev->Push();
+ rWriter.SetClipRegion();
+ rWriter.BeginTransparencyGroup();
+ rWriter.SetTextColor( Color(236,235,233) );
+ rWriter.DrawText(aTextRect, watermark, DrawTextFlags::MultiLine|DrawTextFlags::Center|DrawTextFlags::VCenter|DrawTextFlags::WordBreak|DrawTextFlags::Bottom);
+ rWriter.EndTransparencyGroup( aTextRect, 50 );
+ pDev->Pop();
+
+ aTextPoint.Move(0, pDev->GetTextHeight()*3);
+ }
+ aTextPoint=Point( aTextPoint.getX(), pDev->GetTextHeight() );
+ aTextPoint.Move( nTextWidth*1.5, 0 );
+ }
+
+ rWriter.Pop();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfexport.hxx b/filter/source/pdf/pdfexport.hxx
new file mode 100644
index 000000000..dfd371c31
--- /dev/null
+++ b/filter/source/pdf/pdfexport.hxx
@@ -0,0 +1,145 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <tools/multisel.hxx>
+#include <vcl/pdfwriter.hxx>
+#include <vcl/pdfextoutdevdata.hxx>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/view/XRenderable.hpp>
+
+class GDIMetaFile;
+class Size;
+
+namespace vcl { class PDFWriter; }
+
+class PDFExport
+{
+private:
+
+ css::uno::Reference< css::lang::XComponent > mxSrcDoc;
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::task::XStatusIndicator > mxStatusIndicator;
+ css::uno::Reference< css::task::XInteractionHandler > mxIH;
+
+ bool mbUseTaggedPDF;
+ sal_Int32 mnPDFTypeSelection;
+ bool mbPDFUACompliance;
+ bool mbExportNotes;
+ bool mbExportPlaceholders;
+ bool mbUseReferenceXObject;
+ bool mbExportNotesPages;
+ bool mbExportOnlyNotesPages;
+ bool mbUseTransitionEffects;
+ bool mbExportBookmarks;
+ bool mbExportHiddenSlides;
+ bool mbSinglePageSheets;
+ sal_Int32 mnOpenBookmarkLevels;
+
+ bool mbUseLosslessCompression;
+ bool mbReduceImageResolution;
+ bool mbSkipEmptyPages;
+ bool mbAddStream;
+ sal_Int32 mnMaxImageResolution;
+ sal_Int32 mnQuality;
+ sal_Int32 mnFormsFormat;
+ bool mbExportFormFields;
+ bool mbAllowDuplicateFieldNames;
+ sal_Int32 mnProgressValue;
+ bool mbRemoveTransparencies;
+
+ bool mbIsRedactMode;
+
+ OUString msWatermark;
+ Color maWatermarkColor;
+ std::optional<sal_Int32> moWatermarkFontHeight;
+ OUString maWatermarkFontName;
+ std::optional<Degree10> moWatermarkRotateAngle;
+ OUString msTiledWatermark;
+
+ // these variable are here only to have a location in filter/pdf to set the default
+ // to be used by the macro (when the FilterData are set by the macro itself)
+ bool mbHideViewerToolbar;
+ bool mbHideViewerMenubar;
+ bool mbHideViewerWindowControls;
+ bool mbFitWindow;
+ bool mbCenterWindow;
+ bool mbOpenInFullScreenMode;
+ bool mbDisplayPDFDocumentTitle;
+ sal_Int32 mnPDFDocumentMode;
+ sal_Int32 mnPDFDocumentAction;
+ sal_Int32 mnZoom;
+ sal_Int32 mnInitialPage;
+ sal_Int32 mnPDFPageLayout;
+
+ bool mbEncrypt;
+ bool mbRestrictPermissions;
+ sal_Int32 mnPrintAllowed;
+ sal_Int32 mnChangesAllowed;
+ bool mbCanCopyOrExtract;
+ bool mbCanExtractForAccessibility;
+
+ // #i56629
+ bool mbExportRelativeFsysLinks;
+ sal_Int32 mnDefaultLinkAction;
+ bool mbConvertOOoTargetToPDFTarget;
+ bool mbExportBmkToDest;
+ void ImplExportPage( vcl::PDFWriter& rWriter, vcl::PDFExtOutDevData& rPDFExtOutDevData,
+ const GDIMetaFile& rMtf );
+
+ bool mbSignPDF;
+ OUString msSignLocation;
+ OUString msSignContact;
+ OUString msSignReason;
+ OUString msSignPassword;
+ css::uno::Reference< css::security::XCertificate > maSignCertificate;
+ OUString msSignTSA;
+
+ void ImplWriteWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize );
+ void ImplWriteTiledWatermark( vcl::PDFWriter& rWriter, const Size& rPageSize );
+ css::uno::Reference<css::security::XCertificate> GetCertificateFromSubjectName(const std::u16string_view& rSubjectName) const;
+
+
+public:
+
+ PDFExport( const css::uno::Reference< css::lang::XComponent >& rxSrcDoc,
+ const css::uno::Reference< css::task::XStatusIndicator >& xStatusIndicator,
+ const css::uno::Reference< css::task::XInteractionHandler >& xIH,
+ const css::uno::Reference< css::uno::XComponentContext >& xFact );
+ ~PDFExport();
+
+ bool ExportSelection( vcl::PDFWriter& rPDFWriter,
+ css::uno::Reference< css::view::XRenderable > const & rRenderable,
+ const css::uno::Any& rSelection,
+ const StringRangeEnumerator& rRangeEnum,
+ css::uno::Sequence< css::beans::PropertyValue >& rRenderOptions,
+ sal_Int32 nPageCount );
+
+ bool Export( const OUString& rFile, const css::uno::Sequence< css::beans::PropertyValue >& rFilterData );
+
+ void showErrors( const std::set<vcl::PDFWriter::ErrorCode>& );
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdffilter.component b/filter/source/pdf/pdffilter.component
new file mode 100644
index 000000000..5f3dc7879
--- /dev/null
+++ b/filter/source/pdf/pdffilter.component
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.PDF.PDFDialog"
+ constructor="filter_PDFDialog_get_implementation">
+ <service name="com.sun.star.document.PDFDialog"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.PDF.PDFFilter"
+ constructor="filter_PDFFilter_get_implementation">
+ <service name="com.sun.star.document.PDFFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.PDF.PDFExportInteractionHandler"
+ constructor="filter_PDFExportInteractionHandler_get_implementation">
+ <service name="com.sun.star.filter.pdfexport.PDFExportInteractionHandler"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.PDF.PDFDecomposer"
+ constructor="filter_PdfDecomposer_get_implementation">
+ <service name="com.sun.star.graphic.PdfTools"/>
+ </implementation>
+</component>
diff --git a/filter/source/pdf/pdffilter.cxx b/filter/source/pdf/pdffilter.cxx
new file mode 100644
index 000000000..746a1dd9b
--- /dev/null
+++ b/filter/source/pdf/pdffilter.cxx
@@ -0,0 +1,295 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "pdffilter.hxx"
+#include "pdfexport.hxx"
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <svl/outstrm.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <unotools/tempfile.hxx>
+#include <vcl/FilterConfigItem.hxx>
+#include <memory>
+
+#include <com/sun/star/io/XOutputStream.hpp>
+
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/sequence.hxx>
+
+#include <boost/property_tree/json_parser/error.hpp>
+
+using namespace ::com::sun::star::io;
+
+PDFFilter::PDFFilter( const Reference< XComponentContext > &rxContext ) :
+ mxContext( rxContext )
+{
+}
+
+
+PDFFilter::~PDFFilter()
+{
+}
+
+
+bool PDFFilter::implExport( const Sequence< PropertyValue >& rDescriptor )
+{
+ Reference< XOutputStream > xOStm;
+ Sequence< PropertyValue > aFilterData;
+ OUString aFilterOptions;
+ sal_Int32 nLength = rDescriptor.getLength();
+ const PropertyValue* pValue = rDescriptor.getConstArray();
+ bool bIsRedactMode = false;
+ bool bRet = false;
+ Reference< task::XStatusIndicator > xStatusIndicator;
+ Reference< task::XInteractionHandler > xIH;
+
+ for (sal_Int32 i = 0; i < nLength; ++i)
+ {
+ if ( pValue[ i ].Name == "OutputStream" )
+ pValue[ i ].Value >>= xOStm;
+ else if ( pValue[ i ].Name == "FilterData" )
+ pValue[ i ].Value >>= aFilterData;
+ else if ( pValue[ i ].Name == "FilterOptions" )
+ pValue[ i ].Value >>= aFilterOptions;
+ else if ( pValue[ i ].Name == "StatusIndicator" )
+ pValue[ i ].Value >>= xStatusIndicator;
+ else if ( pValue[i].Name == "InteractionHandler" )
+ pValue[i].Value >>= xIH;
+ }
+
+ for (sal_Int32 i = 0 ; i < nLength; ++i)
+ {
+ if ( pValue[i].Name == "IsRedactMode")
+ pValue[i].Value >>= bIsRedactMode;
+ }
+
+ if (!aFilterData.hasElements() && aFilterOptions.startsWith("{"))
+ {
+ try
+ {
+ // Allow setting filter data keys from the cmdline.
+ std::vector<PropertyValue> aData
+ = comphelper::JsonToPropertyValues(aFilterOptions.toUtf8());
+ aFilterData = comphelper::containerToSequence(aData);
+ }
+ catch (const boost::property_tree::json_parser::json_parser_error& e)
+ {
+ // This wasn't a valid json; maybe came from import filter (tdf#150846)
+ SAL_WARN("filter.pdf", "error parsing FilterOptions: " << e.message());
+ }
+ }
+
+ /* we don't get FilterData if we are exporting directly
+ to pdf, but we have to use the last user settings (especially for the CompressMode) */
+ if ( !aFilterData.hasElements() )
+ {
+ FilterConfigItem aCfgItem( u"Office.Common/Filter/PDF/Export/" );
+ aCfgItem.ReadBool( "UseLosslessCompression", false );
+ aCfgItem.ReadInt32( "Quality", 90 );
+ aCfgItem.ReadBool( "ReduceImageResolution", false );
+ aCfgItem.ReadInt32( "MaxImageResolution", 300 );
+ aCfgItem.ReadBool( "UseTaggedPDF", false );
+ aCfgItem.ReadInt32( "SelectPdfVersion", 0 );
+ aCfgItem.ReadBool("PDFUACompliance", false);
+ aCfgItem.ReadBool( "ExportNotes", false );
+ aCfgItem.ReadBool( "ExportPlaceholders", false );
+ aCfgItem.ReadBool( "ExportNotesPages", false );
+ aCfgItem.ReadBool( "ExportOnlyNotesPages", false );
+ aCfgItem.ReadBool( "UseTransitionEffects", true );
+ aCfgItem.ReadBool( "IsSkipEmptyPages", false );
+ aCfgItem.ReadBool( "ExportFormFields", true );
+ aCfgItem.ReadInt32( "FormsType", 0 );
+ aCfgItem.ReadBool( "HideViewerToolbar", false );
+ aCfgItem.ReadBool( "HideViewerMenubar", false );
+ aCfgItem.ReadBool( "HideViewerWindowControls", false );
+ aCfgItem.ReadBool( "ResizeWindowToInitialPage", false );
+ aCfgItem.ReadBool( "CenterWindow", false );
+ aCfgItem.ReadBool( "OpenInFullScreenMode", false );
+ aCfgItem.ReadBool( "DisplayPDFDocumentTitle", true );
+ aCfgItem.ReadInt32( "InitialView", 0 );
+ aCfgItem.ReadInt32( "Magnification", 0 );
+ aCfgItem.ReadInt32( "Zoom", 100 );
+ aCfgItem.ReadInt32( "PageLayout", 0 );
+ aCfgItem.ReadBool( "FirstPageOnLeft", false );
+ aCfgItem.ReadInt32( "InitialPage", 1 );
+ aCfgItem.ReadBool( "IsAddStream", false );
+
+ // the encryption is not available when exporting directly, since the encryption is off by default and the selection
+ // (encrypt or not) is not persistent; it's available through macro though,
+ // provided the correct property values are set, see help
+
+ // now, the relative link stuff
+ aCfgItem.ReadBool( "ExportLinksRelativeFsys", false );
+ aCfgItem.ReadInt32("PDFViewSelection", 0 );
+ aCfgItem.ReadBool( "ConvertOOoTargetToPDFTarget", false );
+ aCfgItem.ReadBool( "ExportBookmarksToPDFDestination", false );
+
+ aCfgItem.ReadBool( "ExportBookmarks", true );
+ aCfgItem.ReadBool( "ExportHiddenSlides", false );
+ aCfgItem.ReadBool( "SinglePageSheets", false );
+ aCfgItem.ReadInt32( "OpenBookmarkLevels", -1 );
+
+ aCfgItem.ReadBool( "IsRedactMode", false);
+
+ aFilterData = aCfgItem.GetFilterData();
+ }
+
+
+ if (bIsRedactMode)
+ {
+ bool bFound = false;
+
+ for (PropertyValue& rProp : asNonConstRange(aFilterData))
+ {
+ if (rProp.Name == "IsRedactMode")
+ {
+ rProp.Value <<= bIsRedactMode;
+ bFound = true;
+ break;
+ }
+ }
+
+ if (!bFound)
+ {
+ sal_Int32 nNewSize = aFilterData.getLength() + 1;
+ aFilterData.realloc( nNewSize );
+ auto pFilterData = aFilterData.getArray();
+ pFilterData[nNewSize - 1].Name = "IsRedactMode";
+ pFilterData[nNewSize - 1].Value <<= bIsRedactMode;
+ }
+ }
+
+ if( mxSrcDoc.is() && xOStm.is() )
+ {
+ PDFExport aExport( mxSrcDoc, xStatusIndicator, xIH, mxContext );
+ ::utl::TempFile aTempFile;
+
+ aTempFile.EnableKillingFile();
+ bRet = aExport.Export( aTempFile.GetURL(), aFilterData );
+
+ if( bRet )
+ {
+ std::unique_ptr<SvStream> pIStm(::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), StreamMode::READ ));
+
+ if( pIStm )
+ {
+ SvOutputStream aOStm( xOStm );
+
+ aOStm.WriteStream( *pIStm );
+ bRet = ( aOStm.Tell() && ( aOStm.GetError() == ERRCODE_NONE ) );
+ }
+ }
+ }
+
+ return bRet;
+}
+
+namespace {
+
+class FocusWindowWaitCursor
+{
+private:
+
+ VclPtr<vcl::Window> m_pFocusWindow;
+
+public:
+ FocusWindowWaitCursor() :
+ m_pFocusWindow( Application::GetFocusWindow() )
+ {
+ if( m_pFocusWindow )
+ {
+ m_pFocusWindow->AddEventListener( LINK( this, FocusWindowWaitCursor, DestroyedLink ) );
+ m_pFocusWindow->EnterWait();
+ }
+ }
+
+ ~FocusWindowWaitCursor()
+ {
+ if( m_pFocusWindow )
+ {
+ m_pFocusWindow->LeaveWait();
+ m_pFocusWindow->RemoveEventListener( LINK( this, FocusWindowWaitCursor, DestroyedLink ) );
+ }
+ }
+
+ DECL_LINK( DestroyedLink, VclWindowEvent&, void );
+};
+
+}
+
+IMPL_LINK( FocusWindowWaitCursor, DestroyedLink, VclWindowEvent&, rEvent, void )
+{
+ if( rEvent.GetId() == VclEventId::ObjectDying )
+ m_pFocusWindow = nullptr;
+}
+
+
+sal_Bool SAL_CALL PDFFilter::filter( const Sequence< PropertyValue >& rDescriptor )
+{
+ FocusWindowWaitCursor aCur;
+
+ const bool bRet = implExport( rDescriptor );
+
+ return bRet;
+}
+
+
+void SAL_CALL PDFFilter::cancel( )
+{
+}
+
+
+void SAL_CALL PDFFilter::setSourceDocument( const Reference< XComponent >& xDoc )
+{
+ mxSrcDoc = xDoc;
+}
+
+
+void SAL_CALL PDFFilter::initialize( const css::uno::Sequence< css::uno::Any >& )
+{
+}
+
+
+OUString SAL_CALL PDFFilter::getImplementationName()
+{
+ return "com.sun.star.comp.PDF.PDFFilter";
+}
+
+
+sal_Bool SAL_CALL PDFFilter::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+
+css::uno::Sequence< OUString > SAL_CALL PDFFilter::getSupportedServiceNames( )
+{
+ return { "com.sun.star.document.PDFFilter" };
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_PDFFilter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new PDFFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdffilter.hxx b/filter/source/pdf/pdffilter.hxx
new file mode 100644
index 000000000..28869272c
--- /dev/null
+++ b/filter/source/pdf/pdffilter.hxx
@@ -0,0 +1,70 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+
+
+class PDFFilter : public cppu::WeakImplHelper < XFilter, XExporter, XInitialization, XServiceInfo >
+{
+private:
+
+ Reference< XComponentContext > mxContext;
+ Reference< XComponent > mxSrcDoc;
+
+ bool implExport( const Sequence< PropertyValue >& rDescriptor );
+
+protected:
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& rDescriptor ) override;
+ virtual void SAL_CALL cancel( ) override;
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+public:
+
+ explicit PDFFilter( const Reference< XComponentContext >& rxContext );
+ virtual ~PDFFilter() override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfinteract.cxx b/filter/source/pdf/pdfinteract.cxx
new file mode 100644
index 000000000..cf38cf4a0
--- /dev/null
+++ b/filter/source/pdf/pdfinteract.cxx
@@ -0,0 +1,97 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "pdfinteract.hxx"
+#include "impdialog.hxx"
+
+#include <com/sun/star/task/XInteractionRequest.hpp>
+#include <com/sun/star/task/PDFExportException.hpp>
+#include <comphelper/namedvaluecollection.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <vcl/svapp.hxx>
+
+PDFInteractionHandler::PDFInteractionHandler()
+{
+}
+
+PDFInteractionHandler::~PDFInteractionHandler()
+{
+}
+
+void SAL_CALL PDFInteractionHandler::handle( const Reference< task::XInteractionRequest >& i_xRequest )
+{
+ handleInteractionRequest( i_xRequest );
+}
+
+void SAL_CALL PDFInteractionHandler::initialize(const css::uno::Sequence<css::uno::Any>& rArguments)
+{
+ comphelper::NamedValueCollection aProperties(rArguments);
+ if (aProperties.has("Parent"))
+ aProperties.get("Parent") >>= m_xParent;
+}
+
+sal_Bool SAL_CALL PDFInteractionHandler::handleInteractionRequest( const Reference< task::XInteractionRequest >& i_xRequest )
+{
+ bool bHandled = false;
+
+ Any aRequest( i_xRequest->getRequest() );
+ task::PDFExportException aExc;
+ if( aRequest >>= aExc )
+ {
+ std::set< vcl::PDFWriter::ErrorCode > aCodes;
+ sal_Int32 nCodes = aExc.ErrorCodes.getLength();
+ for( sal_Int32 i = 0; i < nCodes; i++ )
+ aCodes.insert( static_cast<vcl::PDFWriter::ErrorCode>(aExc.ErrorCodes.getConstArray()[i]) );
+
+ ImplErrorDialog aDlg(Application::GetFrameWeld(m_xParent), aCodes);
+ aDlg.run();
+ bHandled = true;
+ }
+ return bHandled;
+}
+
+
+
+OUString SAL_CALL PDFInteractionHandler::getImplementationName()
+{
+ return "com.sun.star.comp.PDF.PDFExportInteractionHandler";
+}
+
+
+sal_Bool SAL_CALL PDFInteractionHandler::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+
+css::uno::Sequence< OUString > SAL_CALL PDFInteractionHandler::getSupportedServiceNames( )
+{
+ return { "com.sun.star.filter.pdfexport.PDFExportInteractionHandler" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_PDFExportInteractionHandler_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new PDFInteractionHandler());
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/pdf/pdfinteract.hxx b/filter/source/pdf/pdfinteract.hxx
new file mode 100644
index 000000000..0af5c260b
--- /dev/null
+++ b/filter/source/pdf/pdfinteract.hxx
@@ -0,0 +1,61 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/task/XInteractionHandler2.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+
+class PDFInteractionHandler : public cppu::WeakImplHelper<css::lang::XInitialization,
+ css::task::XInteractionHandler2,
+ XServiceInfo>
+{
+private:
+ css::uno::Reference<css::awt::XWindow> m_xParent;
+protected:
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& rArguments) override;
+
+ // XInteractionHandler
+ virtual void SAL_CALL handle( const Reference< task::XInteractionRequest >& ) override;
+
+ // XInteractionHandler2
+ virtual sal_Bool SAL_CALL handleInteractionRequest( const Reference< task::XInteractionRequest >& ) override;
+
+public:
+
+ PDFInteractionHandler();
+ virtual ~PDFInteractionHandler() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/storagefilterdetect/filterdetect.cxx b/filter/source/storagefilterdetect/filterdetect.cxx
new file mode 100644
index 000000000..05eb74769
--- /dev/null
+++ b/filter/source/storagefilterdetect/filterdetect.cxx
@@ -0,0 +1,192 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "filterdetect.hxx"
+
+#include <comphelper/documentconstants.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <tools/urlobj.hxx>
+#include <sfx2/brokenpackageint.hxx>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <utility>
+
+using namespace ::com::sun::star;
+using utl::MediaDescriptor;
+
+namespace {
+
+OUString getInternalFromMediaType(std::u16string_view aMediaType)
+{
+ // OpenDocument types
+ if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_ASCII ) return "writer8";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_TEMPLATE_ASCII ) return "writer8_template";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_WEB_ASCII ) return "writerweb8_writer_template";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_ASCII ) return "writerglobal8";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_TEXT_GLOBAL_TEMPLATE_ASCII ) return "writerglobal8_template";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_ASCII ) return "draw8";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_DRAWING_TEMPLATE_ASCII ) return "draw8_template";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_ASCII ) return "impress8";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_PRESENTATION_TEMPLATE_ASCII ) return "impress8_template";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_ASCII ) return "calc8";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_SPREADSHEET_TEMPLATE_ASCII ) return "calc8_template";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_CHART_ASCII ) return "chart8";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_FORMULA_ASCII ) return "math8";
+ else if ( aMediaType == MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART_ASCII ) return "StarBaseReportChart";
+
+ // OOo legacy types
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_WRITER_ASCII ) return "writer_StarOffice_XML_Writer";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_WRITER_TEMPLATE_ASCII ) return "writer_StarOffice_XML_Writer_Template";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_WRITER_WEB_ASCII ) return "writer_web_StarOffice_XML_Writer_Web_Template";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_WRITER_GLOBAL_ASCII ) return "writer_globaldocument_StarOffice_XML_Writer_GlobalDocument";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_DRAW_ASCII ) return "draw_StarOffice_XML_Draw";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_DRAW_TEMPLATE_ASCII ) return "draw_StarOffice_XML_Draw_Template";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_IMPRESS_ASCII ) return "impress_StarOffice_XML_Impress";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_IMPRESS_TEMPLATE_ASCII ) return "impress_StarOffice_XML_Impress_Template";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_CALC_ASCII ) return "calc_StarOffice_XML_Calc";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_CALC_TEMPLATE_ASCII ) return "calc_StarOffice_XML_Calc_Template";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_CHART_ASCII ) return "chart_StarOffice_XML_Chart";
+ else if ( aMediaType == MIMETYPE_VND_SUN_XML_MATH_ASCII ) return "math_StarOffice_XML_Math";
+
+ // Unknown type
+ return OUString();
+}
+
+}
+
+StorageFilterDetect::StorageFilterDetect(uno::Reference<uno::XComponentContext> xCxt) :
+ mxCxt(std::move(xCxt)) {}
+
+StorageFilterDetect::~StorageFilterDetect() {}
+
+OUString SAL_CALL StorageFilterDetect::detect(uno::Sequence<beans::PropertyValue>& rDescriptor)
+{
+ MediaDescriptor aMediaDesc( rDescriptor );
+ OUString aTypeName;
+
+ try
+ {
+ uno::Reference< io::XInputStream > xInStream( aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM], uno::UNO_QUERY );
+ if ( !xInStream.is() )
+ return OUString();
+
+ uno::Reference< embed::XStorage > xStorage = ::comphelper::OStorageHelper::GetStorageFromInputStream( xInStream, mxCxt );
+ if ( !xStorage.is() )
+ return OUString();
+
+ uno::Reference< beans::XPropertySet > xStorageProperties( xStorage, uno::UNO_QUERY );
+ if ( !xStorageProperties.is() )
+ return OUString();
+
+ OUString aMediaType;
+ xStorageProperties->getPropertyValue( "MediaType" ) >>= aMediaType;
+ aTypeName = getInternalFromMediaType( aMediaType );
+ }
+
+ catch( const lang::WrappedTargetException& aWrap )
+ {
+ packages::zip::ZipIOException aZipException;
+ // We don't do any type detection on broken packages (f.e. because it might be impossible),
+ // so for repairing we'll use the requested type, which was detected by the flat detection.
+ OUString aRequestedTypeName = aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_TYPENAME, OUString() );
+ if ( ( aWrap.TargetException >>= aZipException ) && !aRequestedTypeName.isEmpty() )
+ {
+ // The package is a broken one.
+ uno::Reference< task::XInteractionHandler > xInteraction =
+ aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_INTERACTIONHANDLER, uno::Reference< task::XInteractionHandler >() );
+
+ if ( xInteraction.is() )
+ {
+ INetURLObject aParser( aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_URL, OUString() ) );
+ OUString aDocumentTitle = aParser.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset );
+ bool bRepairPackage = aMediaDesc.getUnpackedValueOrDefault( "RepairPackage", false );
+ // fdo#46310 Don't try to repair if the user rejected it once.
+ bool bRepairAllowed = aMediaDesc.getUnpackedValueOrDefault( "RepairAllowed", true );
+
+ if ( !bRepairPackage && bRepairAllowed )
+ {
+ // Ask the user whether he wants to try to repair.
+ RequestPackageReparation aRequest( aDocumentTitle );
+ xInteraction->handle( aRequest.GetRequest() );
+
+ if ( aRequest.isApproved() )
+ {
+ aTypeName = aRequestedTypeName;
+ aMediaDesc[MediaDescriptor::PROP_DOCUMENTTITLE] <<= aDocumentTitle;
+ aMediaDesc[MediaDescriptor::PROP_ASTEMPLATE] <<= true;
+ aMediaDesc["RepairPackage"] <<= true;
+ }
+ else
+ {
+ // Repair either not allowed or not successful.
+ NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
+ xInteraction->handle( aNotifyRequest.GetRequest() );
+ aMediaDesc["RepairAllowed"] <<= false;
+ }
+
+ // Write the changes back.
+ aMediaDesc >> rDescriptor;
+ }
+ }
+ }
+ }
+ catch( uno::RuntimeException& )
+ {
+ throw;
+ }
+ catch( uno::Exception& )
+ {}
+
+ return aTypeName;
+}
+
+// XInitialization
+void SAL_CALL StorageFilterDetect::initialize(const uno::Sequence<uno::Any>& /*aArguments*/) {}
+
+// XServiceInfo
+OUString SAL_CALL StorageFilterDetect::getImplementationName()
+{
+ return "com.sun.star.comp.filters.StorageFilterDetect";
+}
+
+sal_Bool SAL_CALL StorageFilterDetect::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL StorageFilterDetect::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ExtendedTypeDetection", "com.sun.star.comp.filters.StorageFilterDetect" };
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_StorageFilterDetect_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new StorageFilterDetect(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/storagefilterdetect/filterdetect.hxx b/filter/source/storagefilterdetect/filterdetect.hxx
new file mode 100644
index 000000000..052e2c2ff
--- /dev/null
+++ b/filter/source/storagefilterdetect/filterdetect.hxx
@@ -0,0 +1,56 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+class StorageFilterDetect : public cppu::WeakImplHelper<
+ css::document::XExtendedFilterDetection,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo>
+{
+ css::uno::Reference<css::uno::XComponentContext> mxCxt;
+
+public:
+
+ explicit StorageFilterDetect (css::uno::Reference<css::uno::XComponentContext> xCxt);
+ virtual ~StorageFilterDetect() override;
+
+ // XExtendedFilterDetection
+ virtual OUString SAL_CALL detect(css::uno::Sequence<css::beans::PropertyValue>& rDescriptor) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize(const css::uno::Sequence<css::uno::Any>& aArguments) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/storagefilterdetect/storagefd.component b/filter/source/storagefilterdetect/storagefd.component
new file mode 100644
index 000000000..4a2ea0bf4
--- /dev/null
+++ b/filter/source/storagefilterdetect/storagefd.component
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.filters.StorageFilterDetect"
+ constructor="filter_StorageFilterDetect_get_implementation">
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+</component>
diff --git a/filter/source/svg/.eslintrc.js b/filter/source/svg/.eslintrc.js
new file mode 100644
index 000000000..8daf37eab
--- /dev/null
+++ b/filter/source/svg/.eslintrc.js
@@ -0,0 +1,250 @@
+module.exports = {
+ "env": {
+ "browser": true,
+ "es6": true
+ },
+ "extends": "eslint:recommended",
+ "rules": {
+ "accessor-pairs": "error",
+ "array-bracket-spacing": "off",
+ "array-callback-return": "error",
+ "arrow-body-style": "error",
+ "arrow-parens": "error",
+ "arrow-spacing": "error",
+ "block-scoped-var": "off",
+ "block-spacing": [
+ "error",
+ "always"
+ ],
+ "brace-style": "off",
+ "callback-return": "error",
+ "camelcase": "off",
+ "capitalized-comments": "off",
+ "class-methods-use-this": "error",
+ "comma-dangle": "error",
+ "comma-spacing": "off",
+ "comma-style": [
+ "error",
+ "last"
+ ],
+ "complexity": "off",
+ "computed-property-spacing": "off",
+ "consistent-return": "off",
+ "consistent-this": "off",
+ "curly": "off",
+ "default-case": "off",
+ "dot-location": [
+ "error",
+ "property"
+ ],
+ "dot-notation": "off",
+ "eol-last": "error",
+ "eqeqeq": "off",
+ "func-call-spacing": "error",
+ "func-name-matching": "error",
+ "func-names": [
+ "error",
+ "never"
+ ],
+ "func-style": "off",
+ "generator-star-spacing": "error",
+ "global-require": "error",
+ "guard-for-in": "off",
+ "handle-callback-err": "error",
+ "id-denylist": "error",
+ "id-length": "off",
+ "id-match": "error",
+ "indent": "off",
+ "init-declarations": "off",
+ "jsx-quotes": "error",
+ "key-spacing": "off",
+ "keyword-spacing": "off",
+ "line-comment-position": "off",
+ "linebreak-style": [
+ "error",
+ "unix"
+ ],
+ "lines-around-comment": "off",
+ "lines-around-directive": "off",
+ "max-depth": "off",
+ "max-len": "off",
+ "max-lines": "off",
+ "max-nested-callbacks": "error",
+ "max-params": "off",
+ "max-statements": "off",
+ "max-statements-per-line": "off",
+ "multiline-ternary": "off",
+ "new-parens": "error",
+ "newline-after-var": "off",
+ "newline-before-return": "off",
+ "newline-per-chained-call": "off",
+ "no-alert": "off",
+ "no-array-constructor": "error",
+ "no-await-in-loop": "error",
+ "no-bitwise": "off",
+ "no-caller": "error",
+ "no-catch-shadow": "error",
+ "no-compare-neg-zero": "error",
+ "no-confusing-arrow": "error",
+ "no-continue": "off",
+ "no-div-regex": "error",
+ "no-duplicate-imports": "error",
+ "no-else-return": "off",
+ "no-empty-function": "off",
+ "no-eq-null": "off",
+ "no-eval": "off",
+ "no-extend-native": "error",
+ "no-extra-bind": "error",
+ "no-extra-label": "error",
+ "no-extra-parens": "off",
+ "no-floating-decimal": "error",
+ "no-implicit-globals": "off",
+ "no-implied-eval": "off",
+ "no-inline-comments": "off",
+ "no-inner-declarations": [
+ "error",
+ "functions"
+ ],
+ "no-invalid-this": "error",
+ "no-iterator": "error",
+ "no-label-var": "error",
+ "no-labels": "error",
+ "no-lone-blocks": "error",
+ "no-lonely-if": "off",
+ "no-loop-func": "error",
+ "no-magic-numbers": "off",
+ "no-mixed-operators": "off",
+ "no-mixed-requires": "error",
+ "no-multi-assign": "off",
+ "no-multi-spaces": "off",
+ "no-multi-str": "error",
+ "no-multiple-empty-lines": "off",
+ "no-native-reassign": "error",
+ "no-negated-condition": "off",
+ "no-negated-in-lhs": "error",
+ "no-nested-ternary": "error",
+ "no-new": "error",
+ "no-new-func": "error",
+ "no-new-object": "error",
+ "no-new-require": "error",
+ "no-new-wrappers": "error",
+ "no-octal-escape": "error",
+ "no-param-reassign": "off",
+ "no-path-concat": "error",
+ "no-plusplus": "off",
+ "no-process-env": "error",
+ "no-process-exit": "error",
+ "no-proto": "error",
+ "no-prototype-builtins": "off",
+ "no-restricted-globals": "error",
+ "no-restricted-imports": "error",
+ "no-restricted-modules": "error",
+ "no-restricted-properties": "error",
+ "no-restricted-syntax": "error",
+ "no-return-assign": [
+ "error",
+ "except-parens"
+ ],
+ "no-return-await": "error",
+ "no-script-url": "error",
+ "no-self-compare": "error",
+ "no-sequences": "error",
+ "no-shadow": "off",
+ "no-shadow-restricted-names": "error",
+ "no-spaced-func": "error",
+ "no-sync": "error",
+ "no-tabs": "off",
+ "no-template-curly-in-string": "error",
+ "no-ternary": "off",
+ "no-throw-literal": "off",
+ "no-trailing-spaces": "off",
+ "no-undef-init": "off",
+ "no-undefined": "off",
+ "no-underscore-dangle": "off",
+ "no-unmodified-loop-condition": "off",
+ "no-unneeded-ternary": "off",
+ "no-unused-expressions": "error",
+ "no-use-before-define": "off",
+ "no-useless-call": "error",
+ "no-useless-computed-key": "error",
+ "no-useless-concat": "off",
+ "no-useless-constructor": "error",
+ "no-useless-escape": "error",
+ "no-useless-rename": "error",
+ "no-useless-return": "off",
+ "no-var": "off",
+ "no-void": "error",
+ "no-warning-comments": "off",
+ "no-whitespace-before-property": "error",
+ "no-with": "error",
+ "nonblock-statement-body-position": [
+ "error",
+ "any"
+ ],
+ "object-curly-newline": "off",
+ "object-curly-spacing": "off",
+ "object-property-newline": [
+ "error",
+ {
+ "allowMultiplePropertiesPerLine": true
+ }
+ ],
+ "object-shorthand": "off",
+ "one-var": "off",
+ "one-var-declaration-per-line": "off",
+ "operator-assignment": "off",
+ "operator-linebreak": "off",
+ "padded-blocks": "off",
+ "prefer-arrow-callback": "off",
+ "prefer-const": "off",
+ "prefer-destructuring": [
+ "error",
+ {
+ "array": false,
+ "object": false
+ }
+ ],
+ "prefer-numeric-literals": "error",
+ "prefer-promise-reject-errors": "error",
+ "prefer-reflect": "off",
+ "prefer-rest-params": "off",
+ "prefer-spread": "error",
+ "prefer-template": "off",
+ "quote-props": "off",
+ "quotes": [
+ "error",
+ "single"
+ ],
+ "radix": [
+ "error",
+ "as-needed"
+ ],
+ "require-await": "error",
+ "require-jsdoc": "off",
+ "rest-spread-spacing": "error",
+ "semi": "off",
+ "semi-spacing": "off",
+ "sort-imports": "error",
+ "sort-keys": "off",
+ "sort-vars": "off",
+ "space-before-blocks": "off",
+ "space-before-function-paren": "off",
+ "space-in-parens": "off",
+ "space-infix-ops": "off",
+ "space-unary-ops": "off",
+ "spaced-comment": "off",
+ "strict": "off",
+ "symbol-description": "error",
+ "template-curly-spacing": "error",
+ "template-tag-spacing": "error",
+ "unicode-bom": [
+ "error",
+ "never"
+ ],
+ "valid-jsdoc": "off",
+ "vars-on-top": "off",
+ "wrap-iife": "error",
+ "wrap-regex": "off",
+ "yield-star-spacing": "error"
+ }
+}; \ No newline at end of file
diff --git a/filter/source/svg/gentoken.py b/filter/source/svg/gentoken.py
new file mode 100644
index 000000000..c78d066d7
--- /dev/null
+++ b/filter/source/svg/gentoken.py
@@ -0,0 +1,60 @@
+# 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/.
+#
+
+import sys
+
+tokenfile_name = sys.argv[1]
+hxx_name = sys.argv[2]
+gperf_name = sys.argv[3]
+
+gperf_header = r"""%language=C++
+%global-table
+%null-strings
+%struct-type
+struct xmltoken
+{
+ const char *name; sal_Int32 nToken;
+}
+%%
+"""
+
+tokens = {}
+
+with open(tokenfile_name) as tokenfile:
+ for line in tokenfile:
+ line = line.strip()
+ if line:
+ arr = line.split()
+ if len(arr) < 2:
+ t = "XML_" + arr[0]
+ t = t.replace('-', '_').replace('.', '_').replace(':', '_')
+ t = t.replace('+', 'PLUS')
+ arr.append(t)
+ tokens[arr[0]] = arr[1].upper()
+
+hxx = open(hxx_name, 'w')
+gperf = open(gperf_name, 'w')
+
+gperf.write(gperf_header)
+
+hxx.write("#ifndef INCLUDED_AUTOGEN_TOKEN_HXX\n")
+hxx.write("#define INCLUDED_AUTOGEN_TOKEN_HXX\n\n")
+hxx.write("#include <sal/types.h>\n\n" )
+
+i = 0;
+for token in sorted(tokens.keys()):
+ i += 1;
+ hxx.write("const sal_Int32 {} = {};\n".format(tokens[token], i))
+ gperf.write("{},{}\n".format(token, tokens[token]))
+
+gperf.write("%%\n")
+hxx.write("const sal_Int32 XML_TOKEN_COUNT = {};\n".format(i))
+hxx.write("const sal_Int32 XML_TOKEN_INVALID = -1;\n\n")
+hxx.write("#endif\n")
+
+hxx.close()
+gperf.close()
diff --git a/filter/source/svg/js2hxx.py b/filter/source/svg/js2hxx.py
new file mode 100755
index 000000000..38bcab12b
--- /dev/null
+++ b/filter/source/svg/js2hxx.py
@@ -0,0 +1,149 @@
+#!/usr/bin/env python
+#
+# 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/.
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# Major Contributor(s):
+# Copyright (C) 2011 Marco Cecchetti <mrcekets@gmail.com>
+#
+# All Rights Reserved.
+#
+# For minor contributions see the git repository.
+
+import os, sys
+
+MAX_LINES = 150
+VARIABLE_NAME = 'aSVGScript'
+
+def get_var_decl(n):
+ return 'static const char %s%d[] =' % ( VARIABLE_NAME, n )
+
+script_name = os.path.basename( sys.argv[0] )
+infile_name = sys.argv[1]
+outfile_name = sys.argv[2]
+
+
+# collect input JavaScript file lines
+if( not os.path.isfile( infile_name ) ):
+ print ( '%s: error: file "%s" not found' % ( script_name, infile_name ) )
+ sys.exit( -1 )
+
+infile = open( infile_name, 'r' )
+in_lines = [line.rstrip() for line in infile.readlines()]
+infile.close()
+
+
+valid_lines=[]
+is_multiline_comment = False
+lineNumber = 0
+emptyLineCount = 0
+for line in in_lines:
+ lineNumber += 1
+ index = line.find('"')
+ if( index != -1 ):
+ print ( '%s: warning: processed file contains \'"\' at %d:%d' % ( script_name, lineNumber, index ) )
+
+ sline = line.strip()
+
+ # strip comment lines except multilines comments that begins with one '/' and exactly 5 '*'
+ if( is_multiline_comment and sline.endswith( '*/' ) ):
+ is_multiline_comment = False
+ continue
+
+ if( is_multiline_comment ):
+ continue
+
+ if( sline.startswith( '//' ) ):
+ continue
+
+ if( sline.startswith( '/*' ) and sline.endswith( '*/' ) ):
+ continue
+
+ if( ( sline.startswith( '/*' ) and not sline.startswith( '/*****' ) )
+ or sline.startswith( '/******' ) ):
+ is_multiline_comment = True
+ continue
+
+ # disable any debug printer
+ dline = line.replace( 'NAVDBG.on', 'NAVDBG.off' )
+ dline = dline.replace( 'ANIMDBG.on', 'ANIMDBG.off' )
+ dline = dline.replace( 'DebugPrinter.on', 'DebugPrinter.off' )
+
+ escaped_line = '%s' % dline
+ escaped_line = escaped_line.rstrip().lstrip()
+
+ # no more than 2 consecutive empty lines
+ if( escaped_line == '' ):
+ emptyLineCount += 1
+ else:
+ emptyLineCount = 0
+
+ if( emptyLineCount > 2 ):
+ continue
+
+ # append to some escape sequence another '\'
+ escaped_line = escaped_line.replace( '\\', '\\\\' )
+ escaped_line = escaped_line.replace( '\n', '\\n')
+ escaped_line = escaped_line.replace( '\t', '\\t' )
+
+ valid_lines.append( escaped_line )
+
+
+# compute the number of needed fragments that is of C constant strings
+total_valid_lines = len (valid_lines) + 2
+total_fragments = total_valid_lines / MAX_LINES
+if( ( total_valid_lines % MAX_LINES ) != 0 ):
+ total_fragments += 1
+
+
+
+out_lines = []
+out_lines.append( '' )
+out_lines.append( '#define N_SVGSCRIPT_FRAGMENTS %d' % total_fragments )
+out_lines.append( '' )
+out_lines.append( get_var_decl( 0 ) )
+out_lines.append( '"<![CDATA[\\n\\' )
+i = 2
+fragment = 0
+for line in valid_lines:
+ out_lines.append( line + '\\n\\' )
+ if( i == MAX_LINES ):
+ i = 0
+ fragment += 1
+ out_lines.append( '";' )
+ out_lines.append( '' )
+ out_lines.append( get_var_decl( fragment ) )
+ out_lines.append( '"\\' )
+ i += 1
+
+out_lines.append( ']]>";' )
+out_lines.append( '' )
+
+out_lines.append('static const char * g_SVGScripts[N_SVGSCRIPT_FRAGMENTS] = {')
+for j in range(0, fragment+1):
+ out_lines.append(" %s%d," % (VARIABLE_NAME, j))
+out_lines.append('};')
+
+outfile = open( outfile_name, 'w' )
+if( not os.path.isfile( outfile_name ) ):
+ print ( '%s: error: I cannot create file "%s"' % ( script_name, outfile_name ) )
+ sys.exit( -1 )
+
+
+# C++ header
+header_info = '/* !! This file is auto-generated, do not edit !! */'
+
+outfile.write( header_info +'\n\n' )
+
+for line in out_lines:
+ outfile.write( line + '\n' )
+
+outfile.close()
diff --git a/filter/source/svg/presentation_engine.js b/filter/source/svg/presentation_engine.js
new file mode 100644
index 000000000..6473963f8
--- /dev/null
+++ b/filter/source/svg/presentation_engine.js
@@ -0,0 +1,19575 @@
+/* -*- Mode: JS; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * - Presentation Engine - *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
+
+/**
+ * WARNING: any comment that should not be striped out by the script
+ * generating the C++ header file must start with a '/' and exactly 5 '*'
+ * not striped examples: '/*****', '/***** *'
+ * striped examples: '/** ***' (not contiguous), '/******' (more than 5)
+ *
+ * NOTE: This file combines several works, under different
+ * licenses. See the @licstart / @licend sections below.
+ */
+
+/*! Hammer.JS - v2.0.7 - 2016-04-22
+ * http://hammerjs.github.io/
+ *
+ * Copyright (c) 2016 Jorik Tangelder;
+ * Licensed under the MIT license */
+(function(window, document, exportName, undefined) {
+ 'use strict';
+
+var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
+var TEST_ELEMENT = document.createElement('div');
+
+var TYPE_FUNCTION = 'function';
+
+var round = Math.round;
+var abs = Math.abs;
+var now = Date.now;
+
+/**
+ * polyfill for IE11
+ */
+if (!Math.trunc) {
+ Math.trunc = function (v) {
+ return v < 0 ? Math.ceil(v) : Math.floor(v);
+ };
+}
+
+/**
+ * set a timeout with a given scope
+ * @param {Function} fn
+ * @param {Number} timeout
+ * @param {Object} context
+ * @returns {number}
+ */
+function setTimeoutContext(fn, timeout, context) {
+ return setTimeout(bindFn(fn, context), timeout);
+}
+
+/**
+ * if the argument is an array, we want to execute the fn on each entry
+ * if it aint an array we don't want to do a thing.
+ * this is used by all the methods that accept a single and array argument.
+ * @param {*|Array} arg
+ * @param {String} fn
+ * @param {Object} [context]
+ * @returns {Boolean}
+ */
+function invokeArrayArg(arg, fn, context) {
+ if (Array.isArray(arg)) {
+ each(arg, context[fn], context);
+ return true;
+ }
+ return false;
+}
+
+/**
+ * walk objects and arrays
+ * @param {Object} obj
+ * @param {Function} iterator
+ * @param {Object} context
+ */
+function each(obj, iterator, context) {
+ var i;
+
+ if (!obj) {
+ return;
+ }
+
+ if (obj.forEach) {
+ obj.forEach(iterator, context);
+ } else if (obj.length !== undefined) {
+ i = 0;
+ while (i < obj.length) {
+ iterator.call(context, obj[i], i, obj);
+ i++;
+ }
+ } else {
+ for (i in obj) {
+ obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
+ }
+ }
+}
+
+/**
+ * wrap a method with a deprecation warning and stack trace
+ * @param {Function} method
+ * @param {String} name
+ * @param {String} message
+ * @returns {Function} A new function wrapping the supplied method.
+ */
+function deprecate(method, name, message) {
+ var deprecationMessage = 'DEPRECATED METHOD: ' + name + '\n' + message + ' AT \n';
+ return function() {
+ var e = new Error('get-stack-trace');
+ var stack = e && e.stack ? e.stack.replace(/^[^\(]+?[\n$]/gm, '')
+ .replace(/^\s+at\s+/gm, '')
+ .replace(/^Object.<anonymous>\s*\(/gm, '{anonymous}()@') : 'Unknown Stack Trace';
+
+ var log = window.console && (window.console.warn || window.console.log);
+ if (log) {
+ log.call(window.console, deprecationMessage, stack);
+ }
+ return method.apply(this, arguments);
+ };
+}
+
+/**
+ * extend object.
+ * means that properties in dest will be overwritten by the ones in src.
+ * @param {Object} target
+ * @param {...Object} objects_to_assign
+ * @returns {Object} target
+ */
+var assign;
+if (typeof Object.assign !== 'function') {
+ assign = function assign(target) {
+ if (target === undefined || target === null) {
+ throw new TypeError('Cannot convert undefined or null to object');
+ }
+
+ var output = Object(target);
+ for (var index = 1; index < arguments.length; index++) {
+ var source = arguments[index];
+ if (source !== undefined && source !== null) {
+ for (var nextKey in source) {
+ if (source.hasOwnProperty(nextKey)) {
+ output[nextKey] = source[nextKey];
+ }
+ }
+ }
+ }
+ return output;
+ };
+} else {
+ assign = Object.assign;
+}
+
+/**
+ * extend object.
+ * means that properties in dest will be overwritten by the ones in src.
+ * @param {Object} dest
+ * @param {Object} src
+ * @param {Boolean} [merge=false]
+ * @returns {Object} dest
+ */
+var extend = deprecate(function extend(dest, src, merge) {
+ var keys = Object.keys(src);
+ var i = 0;
+ while (i < keys.length) {
+ if (!merge || (merge && dest[keys[i]] === undefined)) {
+ dest[keys[i]] = src[keys[i]];
+ }
+ i++;
+ }
+ return dest;
+}, 'extend', 'Use `assign`.');
+
+/**
+ * merge the values from src in the dest.
+ * means that properties that exist in dest will not be overwritten by src
+ * @param {Object} dest
+ * @param {Object} src
+ * @returns {Object} dest
+ */
+var merge = deprecate(function merge(dest, src) {
+ return extend(dest, src, true);
+}, 'merge', 'Use `assign`.');
+
+/**
+ * simple class inheritance
+ * @param {Function} child
+ * @param {Function} base
+ * @param {Object} [properties]
+ */
+function inherit(child, base, properties) {
+ var baseP = base.prototype,
+ childP;
+
+ childP = child.prototype = Object.create(baseP);
+ childP.constructor = child;
+ childP._super = baseP;
+
+ if (properties) {
+ assign(childP, properties);
+ }
+}
+
+/**
+ * simple function bind
+ * @param {Function} fn
+ * @param {Object} context
+ * @returns {Function}
+ */
+function bindFn(fn, context) {
+ return function boundFn() {
+ return fn.apply(context, arguments);
+ };
+}
+
+/**
+ * let a boolean value also be a function that must return a boolean
+ * this first item in args will be used as the context
+ * @param {Boolean|Function} val
+ * @param {Array} [args]
+ * @returns {Boolean}
+ */
+function boolOrFn(val, args) {
+ if (typeof val == TYPE_FUNCTION) {
+ return val.apply(args ? args[0] || undefined : undefined, args);
+ }
+ return val;
+}
+
+/**
+ * use the val2 when val1 is undefined
+ * @param {*} val1
+ * @param {*} val2
+ * @returns {*}
+ */
+function ifUndefined(val1, val2) {
+ return (val1 === undefined) ? val2 : val1;
+}
+
+/**
+ * addEventListener with multiple events at once
+ * @param {EventTarget} target
+ * @param {String} types
+ * @param {Function} handler
+ */
+function addEventListeners(target, types, handler) {
+ each(splitStr(types), function(type) {
+ target.addEventListener(type, handler, false);
+ });
+}
+
+/**
+ * removeEventListener with multiple events at once
+ * @param {EventTarget} target
+ * @param {String} types
+ * @param {Function} handler
+ */
+function removeEventListeners(target, types, handler) {
+ each(splitStr(types), function(type) {
+ target.removeEventListener(type, handler, false);
+ });
+}
+
+/**
+ * find if a node is in the given parent
+ * @method hasParent
+ * @param {HTMLElement} node
+ * @param {HTMLElement} parent
+ * @return {Boolean} found
+ */
+function hasParent(node, parent) {
+ while (node) {
+ if (node == parent) {
+ return true;
+ }
+ node = node.parentNode;
+ }
+ return false;
+}
+
+/**
+ * small indexOf wrapper
+ * @param {String} str
+ * @param {String} find
+ * @returns {Boolean} found
+ */
+function inStr(str, find) {
+ return str.indexOf(find) > -1;
+}
+
+/**
+ * split string on whitespace
+ * @param {String} str
+ * @returns {Array} words
+ */
+function splitStr(str) {
+ return str.trim().split(/\s+/g);
+}
+
+/**
+ * find if an array contains the object using indexOf or a simple polyFill
+ * @param {Array} src
+ * @param {String} find
+ * @param {String} [findByKey]
+ * @return {Boolean|Number} false when not found, or the index
+ */
+function inArray(src, find, findByKey) {
+ if (src.indexOf && !findByKey) {
+ return src.indexOf(find);
+ } else {
+ var i = 0;
+ while (i < src.length) {
+ if ((findByKey && src[i][findByKey] == find) || (!findByKey && src[i] === find)) {
+ return i;
+ }
+ i++;
+ }
+ return -1;
+ }
+}
+
+/**
+ * convert array-like objects to real arrays
+ * @param {Object} obj
+ * @returns {Array}
+ */
+function toArray(obj) {
+ return Array.prototype.slice.call(obj, 0);
+}
+
+/**
+ * unique array with objects based on a key (like 'id') or just by the array's value
+ * @param {Array} src [{id:1},{id:2},{id:1}]
+ * @param {String} [key]
+ * @param {Boolean} [sort=False]
+ * @returns {Array} [{id:1},{id:2}]
+ */
+function uniqueArray(src, key, sort) {
+ var results = [];
+ var values = [];
+ var i = 0;
+
+ while (i < src.length) {
+ var val = key ? src[i][key] : src[i];
+ if (inArray(values, val) < 0) {
+ results.push(src[i]);
+ }
+ values[i] = val;
+ i++;
+ }
+
+ if (sort) {
+ if (!key) {
+ results = results.sort();
+ } else {
+ results = results.sort(function sortUniqueArray(a, b) {
+ return a[key] > b[key];
+ });
+ }
+ }
+
+ return results;
+}
+
+/**
+ * get the prefixed property
+ * @param {Object} obj
+ * @param {String} property
+ * @returns {String|Undefined} prefixed
+ */
+function prefixed(obj, property) {
+ // tml: Have to check for obj being undefined
+ if (obj === undefined) {
+ return undefined;
+ }
+
+ var prefix, prop;
+ var camelProp = property[0].toUpperCase() + property.slice(1);
+
+ var i = 0;
+ while (i < VENDOR_PREFIXES.length) {
+ prefix = VENDOR_PREFIXES[i];
+ prop = (prefix) ? prefix + camelProp : property;
+
+ if (prop in obj) {
+ return prop;
+ }
+ i++;
+ }
+ return undefined;
+}
+
+/**
+ * get a unique id
+ * @returns {number} uniqueId
+ */
+var _uniqueId = 1;
+function uniqueId() {
+ return _uniqueId++;
+}
+
+/**
+ * get the window object of an element
+ * @param {HTMLElement} element
+ * @returns {DocumentView|Window}
+ */
+function getWindowForElement(element) {
+ var doc = element.ownerDocument || element;
+ return (doc.defaultView || doc.parentWindow || window);
+}
+
+var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
+
+var SUPPORT_TOUCH = ('ontouchstart' in window);
+var SUPPORT_POINTER_EVENTS = prefixed(window, 'PointerEvent') !== undefined;
+var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
+
+var INPUT_TYPE_TOUCH = 'touch';
+var INPUT_TYPE_PEN = 'pen';
+var INPUT_TYPE_MOUSE = 'mouse';
+var INPUT_TYPE_KINECT = 'kinect';
+
+var COMPUTE_INTERVAL = 25;
+
+var INPUT_START = 1;
+var INPUT_MOVE = 2;
+var INPUT_END = 4;
+var INPUT_CANCEL = 8;
+
+var DIRECTION_NONE = 1;
+var DIRECTION_LEFT = 2;
+var DIRECTION_RIGHT = 4;
+var DIRECTION_UP = 8;
+var DIRECTION_DOWN = 16;
+
+var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
+var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
+var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
+
+var PROPS_XY = ['x', 'y'];
+var PROPS_CLIENT_XY = ['clientX', 'clientY'];
+
+/**
+ * create new input type manager
+ * @param {Manager} manager
+ * @param {Function} callback
+ * @returns {Input}
+ * @constructor
+ */
+function Input(manager, callback) {
+ var self = this;
+ this.manager = manager;
+ this.callback = callback;
+ this.element = manager.element;
+ this.target = manager.options.inputTarget;
+
+ // smaller wrapper around the handler, for the scope and the enabled state of the manager,
+ // so when disabled the input events are completely bypassed.
+ this.domHandler = function(ev) {
+ if (boolOrFn(manager.options.enable, [manager])) {
+ self.handler(ev);
+ }
+ };
+
+ this.init();
+
+}
+
+Input.prototype = {
+ /**
+ * should handle the inputEvent data and trigger the callback
+ * @virtual
+ */
+ handler: function() { },
+
+ /**
+ * bind the events
+ */
+ init: function() {
+ this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
+ this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
+ this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
+ },
+
+ /**
+ * unbind the events
+ */
+ destroy: function() {
+ this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
+ this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
+ this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
+ }
+};
+
+/**
+ * create new input type manager
+ * called by the Manager constructor
+ * @param {Hammer} manager
+ * @returns {Input}
+ */
+function createInputInstance(manager) {
+ var Type;
+ var inputClass = manager.options.inputClass;
+
+ if (inputClass) {
+ Type = inputClass;
+ } else if (!SUPPORT_TOUCH && SUPPORT_POINTER_EVENTS) {
+ Type = PointerEventInput;
+ } else if (SUPPORT_ONLY_TOUCH) {
+ Type = TouchInput;
+ } else if (!SUPPORT_TOUCH) {
+ Type = MouseInput;
+ } else {
+ Type = TouchMouseInput;
+ }
+ return new (Type)(manager, inputHandler);
+}
+
+/**
+ * handle input events
+ * @param {Manager} manager
+ * @param {String} eventType
+ * @param {Object} input
+ */
+function inputHandler(manager, eventType, input) {
+ var pointersLen = input.pointers.length;
+ var changedPointersLen = input.changedPointers.length;
+ var isFirst = (eventType & INPUT_START && (pointersLen - changedPointersLen === 0));
+ var isFinal = (eventType & (INPUT_END | INPUT_CANCEL) && (pointersLen - changedPointersLen === 0));
+
+ input.isFirst = !!isFirst;
+ input.isFinal = !!isFinal;
+
+ if (isFirst) {
+ manager.session = {};
+ }
+
+ // source event is the normalized value of the domEvents
+ // like 'touchstart, mouseup, pointerdown'
+ input.eventType = eventType;
+
+ // compute scale, rotation etc
+ computeInputData(manager, input);
+
+ // emit secret event
+ manager.emit('hammer.input', input);
+
+ manager.recognize(input);
+ manager.session.prevInput = input;
+}
+
+/**
+ * extend the data with some usable properties like scale, rotate, velocity etc
+ * @param {Object} manager
+ * @param {Object} input
+ */
+function computeInputData(manager, input) {
+ var session = manager.session;
+ var pointers = input.pointers;
+ var pointersLength = pointers.length;
+
+ // store the first input to calculate the distance and direction
+ if (!session.firstInput) {
+ session.firstInput = simpleCloneInputData(input);
+ }
+
+ // to compute scale and rotation we need to store the multiple touches
+ if (pointersLength > 1 && !session.firstMultiple) {
+ session.firstMultiple = simpleCloneInputData(input);
+ } else if (pointersLength === 1) {
+ session.firstMultiple = false;
+ }
+
+ var firstInput = session.firstInput;
+ var firstMultiple = session.firstMultiple;
+ var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
+
+ var center = input.center = getCenter(pointers);
+ input.timeStamp = now();
+ input.deltaTime = input.timeStamp - firstInput.timeStamp;
+
+ input.angle = getAngle(offsetCenter, center);
+ input.distance = getDistance(offsetCenter, center);
+
+ computeDeltaXY(session, input);
+ input.offsetDirection = getDirection(input.deltaX, input.deltaY);
+
+ var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
+ input.overallVelocityX = overallVelocity.x;
+ input.overallVelocityY = overallVelocity.y;
+ input.overallVelocity = (abs(overallVelocity.x) > abs(overallVelocity.y)) ? overallVelocity.x : overallVelocity.y;
+
+ input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
+ input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
+
+ input.maxPointers = !session.prevInput ? input.pointers.length : ((input.pointers.length >
+ session.prevInput.maxPointers) ? input.pointers.length : session.prevInput.maxPointers);
+
+ computeIntervalInputData(session, input);
+
+ // find the correct target
+ var target = manager.element;
+ if (hasParent(input.srcEvent.target, target)) {
+ target = input.srcEvent.target;
+ }
+ input.target = target;
+}
+
+function computeDeltaXY(session, input) {
+ var center = input.center;
+ var offset = session.offsetDelta || {};
+ var prevDelta = session.prevDelta || {};
+ var prevInput = session.prevInput || {};
+
+ if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
+ prevDelta = session.prevDelta = {
+ x: prevInput.deltaX || 0,
+ y: prevInput.deltaY || 0
+ };
+
+ offset = session.offsetDelta = {
+ x: center.x,
+ y: center.y
+ };
+ }
+
+ input.deltaX = prevDelta.x + (center.x - offset.x);
+ input.deltaY = prevDelta.y + (center.y - offset.y);
+}
+
+/**
+ * velocity is calculated every x ms
+ * @param {Object} session
+ * @param {Object} input
+ */
+function computeIntervalInputData(session, input) {
+ var last = session.lastInterval || input,
+ deltaTime = input.timeStamp - last.timeStamp,
+ velocity, velocityX, velocityY, direction;
+
+ if (input.eventType != INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
+ var deltaX = input.deltaX - last.deltaX;
+ var deltaY = input.deltaY - last.deltaY;
+
+ var v = getVelocity(deltaTime, deltaX, deltaY);
+ velocityX = v.x;
+ velocityY = v.y;
+ velocity = (abs(v.x) > abs(v.y)) ? v.x : v.y;
+ direction = getDirection(deltaX, deltaY);
+
+ session.lastInterval = input;
+ } else {
+ // use latest velocity info if it doesn't overtake a minimum period
+ velocity = last.velocity;
+ velocityX = last.velocityX;
+ velocityY = last.velocityY;
+ direction = last.direction;
+ }
+
+ input.velocity = velocity;
+ input.velocityX = velocityX;
+ input.velocityY = velocityY;
+ input.direction = direction;
+}
+
+/**
+ * create a simple clone from the input used for storage of firstInput and firstMultiple
+ * @param {Object} input
+ * @returns {Object} clonedInputData
+ */
+function simpleCloneInputData(input) {
+ // make a simple copy of the pointers because we will get a reference if we don't
+ // we only need clientXY for the calculations
+ var pointers = [];
+ var i = 0;
+ while (i < input.pointers.length) {
+ pointers[i] = {
+ clientX: round(input.pointers[i].clientX),
+ clientY: round(input.pointers[i].clientY)
+ };
+ i++;
+ }
+
+ return {
+ timeStamp: now(),
+ pointers: pointers,
+ center: getCenter(pointers),
+ deltaX: input.deltaX,
+ deltaY: input.deltaY
+ };
+}
+
+/**
+ * get the center of all the pointers
+ * @param {Array} pointers
+ * @return {Object} center contains `x` and `y` properties
+ */
+function getCenter(pointers) {
+ var pointersLength = pointers.length;
+
+ // no need to loop when only one touch
+ if (pointersLength === 1) {
+ return {
+ x: round(pointers[0].clientX),
+ y: round(pointers[0].clientY)
+ };
+ }
+
+ var x = 0, y = 0, i = 0;
+ while (i < pointersLength) {
+ x += pointers[i].clientX;
+ y += pointers[i].clientY;
+ i++;
+ }
+
+ return {
+ x: round(x / pointersLength),
+ y: round(y / pointersLength)
+ };
+}
+
+/**
+ * calculate the velocity between two points. unit is in px per ms.
+ * @param {Number} deltaTime
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Object} velocity `x` and `y`
+ */
+function getVelocity(deltaTime, x, y) {
+ return {
+ x: x / deltaTime || 0,
+ y: y / deltaTime || 0
+ };
+}
+
+/**
+ * get the direction between two points
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Number} direction
+ */
+function getDirection(x, y) {
+ if (x === y) {
+ return DIRECTION_NONE;
+ }
+
+ if (abs(x) >= abs(y)) {
+ return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
+ }
+ return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
+}
+
+/**
+ * calculate the absolute distance between two points
+ * @param {Object} p1 {x, y}
+ * @param {Object} p2 {x, y}
+ * @param {Array} [props] containing x and y keys
+ * @return {Number} distance
+ */
+function getDistance(p1, p2, props) {
+ if (!props) {
+ props = PROPS_XY;
+ }
+ var x = p2[props[0]] - p1[props[0]],
+ y = p2[props[1]] - p1[props[1]];
+
+ return Math.sqrt((x * x) + (y * y));
+}
+
+/**
+ * calculate the angle between two coordinates
+ * @param {Object} p1
+ * @param {Object} p2
+ * @param {Array} [props] containing x and y keys
+ * @return {Number} angle
+ */
+function getAngle(p1, p2, props) {
+ if (!props) {
+ props = PROPS_XY;
+ }
+ var x = p2[props[0]] - p1[props[0]],
+ y = p2[props[1]] - p1[props[1]];
+ return Math.atan2(y, x) * 180 / Math.PI;
+}
+
+/**
+ * calculate the rotation degrees between two pointersets
+ * @param {Array} start array of pointers
+ * @param {Array} end array of pointers
+ * @return {Number} rotation
+ */
+function getRotation(start, end) {
+ return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
+}
+
+/**
+ * calculate the scale factor between two pointersets
+ * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
+ * @param {Array} start array of pointers
+ * @param {Array} end array of pointers
+ * @return {Number} scale
+ */
+function getScale(start, end) {
+ return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
+}
+
+var MOUSE_INPUT_MAP = {
+ mousedown: INPUT_START,
+ mousemove: INPUT_MOVE,
+ mouseup: INPUT_END
+};
+
+var MOUSE_ELEMENT_EVENTS = 'mousedown';
+var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
+
+/**
+ * Mouse events input
+ * @constructor
+ * @extends Input
+ */
+function MouseInput() {
+ this.evEl = MOUSE_ELEMENT_EVENTS;
+ this.evWin = MOUSE_WINDOW_EVENTS;
+
+ this.pressed = false; // mousedown state
+
+ Input.apply(this, arguments);
+}
+
+inherit(MouseInput, Input, {
+ /**
+ * handle mouse events
+ * @param {Object} ev
+ */
+ handler: function MEhandler(ev) {
+ // console.log('==> MouseInput handler');
+ var eventType = MOUSE_INPUT_MAP[ev.type];
+
+ // on start we want to have the left mouse button down
+ if (eventType & INPUT_START && ev.button === 0) {
+ this.pressed = true;
+ }
+
+ if (eventType & INPUT_MOVE && ev.which !== 1) {
+ eventType = INPUT_END;
+ }
+
+ // mouse must be down
+ if (!this.pressed) {
+ return;
+ }
+
+ if (eventType & INPUT_END) {
+ this.pressed = false;
+ }
+
+ this.callback(this.manager, eventType, {
+ pointers: [ev],
+ changedPointers: [ev],
+ pointerType: INPUT_TYPE_MOUSE,
+ srcEvent: ev
+ });
+ }
+});
+
+var POINTER_INPUT_MAP = {
+ pointerdown: INPUT_START,
+ pointermove: INPUT_MOVE,
+ pointerup: INPUT_END,
+ pointercancel: INPUT_CANCEL,
+ pointerout: INPUT_CANCEL
+};
+
+// in IE10 the pointer types is defined as an enum
+var IE10_POINTER_TYPE_ENUM = {
+ 2: INPUT_TYPE_TOUCH,
+ 3: INPUT_TYPE_PEN,
+ 4: INPUT_TYPE_MOUSE,
+ 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
+};
+
+var POINTER_ELEMENT_EVENTS = 'pointerdown';
+var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel';
+
+// IE10 has prefixed support, and case-sensitive
+if (window.MSPointerEvent && !window.PointerEvent) {
+ POINTER_ELEMENT_EVENTS = 'MSPointerDown';
+ POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
+}
+
+/**
+ * Pointer events input
+ * @constructor
+ * @extends Input
+ */
+function PointerEventInput() {
+ this.evEl = POINTER_ELEMENT_EVENTS;
+ this.evWin = POINTER_WINDOW_EVENTS;
+
+ Input.apply(this, arguments);
+
+ this.store = (this.manager.session.pointerEvents = []);
+}
+
+inherit(PointerEventInput, Input, {
+ /**
+ * handle mouse events
+ * @param {Object} ev
+ */
+ handler: function PEhandler(ev) {
+ // console.log('==> PointerEventInput handler');
+ var store = this.store;
+ var removePointer = false;
+
+ var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
+ var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
+ var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
+
+ var isTouch = (pointerType == INPUT_TYPE_TOUCH);
+
+ // get index of the event in the store
+ var storeIndex = inArray(store, ev.pointerId, 'pointerId');
+
+ // start and mouse must be down
+ if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
+ if (storeIndex < 0) {
+ store.push(ev);
+ storeIndex = store.length - 1;
+ }
+ } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
+ removePointer = true;
+ }
+
+ // it not found, so the pointer hasn't been down (so it's probably a hover)
+ if (storeIndex < 0) {
+ return;
+ }
+
+ // update the event in the store
+ store[storeIndex] = ev;
+
+ this.callback(this.manager, eventType, {
+ pointers: store,
+ changedPointers: [ev],
+ pointerType: pointerType,
+ srcEvent: ev
+ });
+
+ if (removePointer) {
+ // remove from the store
+ store.splice(storeIndex, 1);
+ }
+ }
+});
+
+var SINGLE_TOUCH_INPUT_MAP = {
+ touchstart: INPUT_START,
+ touchmove: INPUT_MOVE,
+ touchend: INPUT_END,
+ touchcancel: INPUT_CANCEL
+};
+
+var SINGLE_TOUCH_TARGET_EVENTS = 'touchstart';
+var SINGLE_TOUCH_WINDOW_EVENTS = 'touchstart touchmove touchend touchcancel';
+
+/**
+ * Touch events input
+ * @constructor
+ * @extends Input
+ */
+function SingleTouchInput() {
+ this.evTarget = SINGLE_TOUCH_TARGET_EVENTS;
+ this.evWin = SINGLE_TOUCH_WINDOW_EVENTS;
+ this.started = false;
+
+ Input.apply(this, arguments);
+}
+
+inherit(SingleTouchInput, Input, {
+ handler: function TEhandler(ev) {
+ // console.log('==> SingleTouchInput handler');
+ var type = SINGLE_TOUCH_INPUT_MAP[ev.type];
+
+ // should we handle the touch events?
+ if (type === INPUT_START) {
+ this.started = true;
+ }
+
+ if (!this.started) {
+ return;
+ }
+
+ var touches = normalizeSingleTouches.call(this, ev, type);
+
+ // when done, reset the started state
+ if (type & (INPUT_END | INPUT_CANCEL) && touches[0].length - touches[1].length === 0) {
+ this.started = false;
+ }
+
+ this.callback(this.manager, type, {
+ pointers: touches[0],
+ changedPointers: touches[1],
+ pointerType: INPUT_TYPE_TOUCH,
+ srcEvent: ev
+ });
+ }
+});
+
+/**
+ * @this {TouchInput}
+ * @param {Object} ev
+ * @param {Number} type flag
+ * @returns {undefined|Array} [all, changed]
+ */
+function normalizeSingleTouches(ev, type) {
+ var all = toArray(ev.touches);
+ var changed = toArray(ev.changedTouches);
+
+ if (type & (INPUT_END | INPUT_CANCEL)) {
+ all = uniqueArray(all.concat(changed), 'identifier', true);
+ }
+
+ return [all, changed];
+}
+
+var TOUCH_INPUT_MAP = {
+ touchstart: INPUT_START,
+ touchmove: INPUT_MOVE,
+ touchend: INPUT_END,
+ touchcancel: INPUT_CANCEL
+};
+
+var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
+
+/**
+ * Multi-user touch events input
+ * @constructor
+ * @extends Input
+ */
+function TouchInput() {
+ this.evTarget = TOUCH_TARGET_EVENTS;
+ this.targetIds = {};
+
+ Input.apply(this, arguments);
+}
+
+inherit(TouchInput, Input, {
+ handler: function MTEhandler(ev) {
+ // console.log('==> TouchInput handler');
+ var type = TOUCH_INPUT_MAP[ev.type];
+ var touches = getTouches.call(this, ev, type);
+ if (!touches) {
+ return;
+ }
+
+ this.callback(this.manager, type, {
+ pointers: touches[0],
+ changedPointers: touches[1],
+ pointerType: INPUT_TYPE_TOUCH,
+ srcEvent: ev
+ });
+ }
+});
+
+/**
+ * @this {TouchInput}
+ * @param {Object} ev
+ * @param {Number} type flag
+ * @returns {undefined|Array} [all, changed]
+ */
+function getTouches(ev, type) {
+ var allTouches = toArray(ev.touches);
+ var targetIds = this.targetIds;
+
+ // when there is only one touch, the process can be simplified
+ if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
+ targetIds[allTouches[0].identifier] = true;
+ return [allTouches, allTouches];
+ }
+
+ var i,
+ targetTouches,
+ changedTouches = toArray(ev.changedTouches),
+ changedTargetTouches = [],
+ target = this.target;
+
+ // get target touches from touches
+ targetTouches = allTouches.filter(function(touch) {
+ return hasParent(touch.target, target);
+ });
+
+ // collect touches
+ if (type === INPUT_START) {
+ i = 0;
+ while (i < targetTouches.length) {
+ targetIds[targetTouches[i].identifier] = true;
+ i++;
+ }
+ }
+
+ // filter changed touches to only contain touches that exist in the collected target ids
+ i = 0;
+ while (i < changedTouches.length) {
+ if (targetIds[changedTouches[i].identifier]) {
+ changedTargetTouches.push(changedTouches[i]);
+ }
+
+ // cleanup removed touches
+ if (type & (INPUT_END | INPUT_CANCEL)) {
+ delete targetIds[changedTouches[i].identifier];
+ }
+ i++;
+ }
+
+ if (!changedTargetTouches.length) {
+ return;
+ }
+
+ return [
+ // merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
+ uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true),
+ changedTargetTouches
+ ];
+}
+
+/**
+ * Combined touch and mouse input
+ *
+ * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
+ * This because touch devices also emit mouse events while doing a touch.
+ *
+ * @constructor
+ * @extends Input
+ */
+
+var DEDUP_TIMEOUT = 2500;
+var DEDUP_DISTANCE = 25;
+
+function TouchMouseInput() {
+ Input.apply(this, arguments);
+
+ var handler = bindFn(this.handler, this);
+ this.touch = new TouchInput(this.manager, handler);
+ this.mouse = new MouseInput(this.manager, handler);
+
+ this.primaryTouch = null;
+ this.lastTouches = [];
+}
+
+inherit(TouchMouseInput, Input, {
+ /**
+ * handle mouse and touch events
+ * @param {Hammer} manager
+ * @param {String} inputEvent
+ * @param {Object} inputData
+ */
+ handler: function TMEhandler(manager, inputEvent, inputData) {
+ // console.log('==> TouchMouseInput handler');
+ var isTouch = (inputData.pointerType == INPUT_TYPE_TOUCH),
+ isMouse = (inputData.pointerType == INPUT_TYPE_MOUSE);
+
+ if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
+ return;
+ }
+
+ // when we're in a touch event, record touches to de-dupe synthetic mouse event
+ if (isTouch) {
+ recordTouches.call(this, inputEvent, inputData);
+ } else if (isMouse && isSyntheticEvent.call(this, inputData)) {
+ return;
+ }
+
+ this.callback(manager, inputEvent, inputData);
+ },
+
+ /**
+ * remove the event listeners
+ */
+ destroy: function destroy() {
+ this.touch.destroy();
+ this.mouse.destroy();
+ }
+});
+
+function recordTouches(eventType, eventData) {
+ if (eventType & INPUT_START) {
+ this.primaryTouch = eventData.changedPointers[0].identifier;
+ setLastTouch.call(this, eventData);
+ } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
+ setLastTouch.call(this, eventData);
+ }
+}
+
+function setLastTouch(eventData) {
+ var touch = eventData.changedPointers[0];
+
+ if (touch.identifier === this.primaryTouch) {
+ var lastTouch = {x: touch.clientX, y: touch.clientY};
+ this.lastTouches.push(lastTouch);
+ var lts = this.lastTouches;
+ var removeLastTouch = function() {
+ var i = lts.indexOf(lastTouch);
+ if (i > -1) {
+ lts.splice(i, 1);
+ }
+ };
+ setTimeout(removeLastTouch, DEDUP_TIMEOUT);
+ }
+}
+
+function isSyntheticEvent(eventData) {
+ var x = eventData.srcEvent.clientX, y = eventData.srcEvent.clientY;
+ for (var i = 0; i < this.lastTouches.length; i++) {
+ var t = this.lastTouches[i];
+ var dx = Math.abs(x - t.x), dy = Math.abs(y - t.y);
+ if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
+ return true;
+ }
+ }
+ return false;
+}
+
+var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
+var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
+
+// magical touchAction value
+var TOUCH_ACTION_COMPUTE = 'compute';
+var TOUCH_ACTION_AUTO = 'auto';
+var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
+var TOUCH_ACTION_NONE = 'none';
+var TOUCH_ACTION_PAN_X = 'pan-x';
+var TOUCH_ACTION_PAN_Y = 'pan-y';
+var TOUCH_ACTION_MAP = getTouchActionProps();
+
+/**
+ * Touch Action
+ * sets the touchAction property or uses the js alternative
+ * @param {Manager} manager
+ * @param {String} value
+ * @constructor
+ */
+function TouchAction(manager, value) {
+ this.manager = manager;
+ this.set(value);
+}
+
+TouchAction.prototype = {
+ /**
+ * set the touchAction value on the element or enable the polyfill
+ * @param {String} value
+ */
+ set: function(value) {
+ // find out the touch-action by the event handlers
+ if (value == TOUCH_ACTION_COMPUTE) {
+ value = this.compute();
+ }
+
+ if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
+ this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
+ }
+ this.actions = value.toLowerCase().trim();
+ },
+
+ /**
+ * just re-set the touchAction value
+ */
+ update: function() {
+ this.set(this.manager.options.touchAction);
+ },
+
+ /**
+ * compute the value for the touchAction property based on the recognizer's settings
+ * @returns {String} value
+ */
+ compute: function() {
+ var actions = [];
+ each(this.manager.recognizers, function(recognizer) {
+ if (boolOrFn(recognizer.options.enable, [recognizer])) {
+ actions = actions.concat(recognizer.getTouchAction());
+ }
+ });
+ return cleanTouchActions(actions.join(' '));
+ },
+
+ /**
+ * this method is called on each input cycle and provides the preventing of the browser behavior
+ * @param {Object} input
+ */
+ preventDefaults: function(input) {
+ var srcEvent = input.srcEvent;
+ var direction = input.offsetDirection;
+
+ // if the touch action did prevented once this session
+ if (this.manager.session.prevented) {
+ srcEvent.preventDefault();
+ return;
+ }
+
+ var actions = this.actions;
+ var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
+ var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
+ var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
+
+ if (hasNone) {
+ //do not prevent defaults if this is a tap gesture
+
+ var isTapPointer = input.pointers.length === 1;
+ var isTapMovement = input.distance < 2;
+ var isTapTouchTime = input.deltaTime < 250;
+
+ if (isTapPointer && isTapMovement && isTapTouchTime) {
+ return;
+ }
+ }
+
+ if (hasPanX && hasPanY) {
+ // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
+ return;
+ }
+
+ if (hasNone ||
+ (hasPanY && direction & DIRECTION_HORIZONTAL) ||
+ (hasPanX && direction & DIRECTION_VERTICAL)) {
+ return this.preventSrc(srcEvent);
+ }
+ },
+
+ /**
+ * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
+ * @param {Object} srcEvent
+ */
+ preventSrc: function(srcEvent) {
+ this.manager.session.prevented = true;
+ srcEvent.preventDefault();
+ }
+};
+
+/**
+ * when the touchActions are collected they are not a valid value, so we need to clean things up. *
+ * @param {String} actions
+ * @returns {*}
+ */
+function cleanTouchActions(actions) {
+ // none
+ if (inStr(actions, TOUCH_ACTION_NONE)) {
+ return TOUCH_ACTION_NONE;
+ }
+
+ var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
+ var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y);
+
+ // if both pan-x and pan-y are set (different recognizers
+ // for different directions, e.g. horizontal pan but vertical swipe?)
+ // we need none (as otherwise with pan-x pan-y combined none of these
+ // recognizers will work, since the browser would handle all panning
+ if (hasPanX && hasPanY) {
+ return TOUCH_ACTION_NONE;
+ }
+
+ // pan-x OR pan-y
+ if (hasPanX || hasPanY) {
+ return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
+ }
+
+ // manipulation
+ if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
+ return TOUCH_ACTION_MANIPULATION;
+ }
+
+ return TOUCH_ACTION_AUTO;
+}
+
+function getTouchActionProps() {
+ if (!NATIVE_TOUCH_ACTION) {
+ return false;
+ }
+ var touchMap = {};
+ var cssSupports = window.CSS && window.CSS.supports;
+ ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function(val) {
+
+ // If css.supports is not supported but there is native touch-action assume it supports
+ // all values. This is the case for IE 10 and 11.
+ touchMap[val] = cssSupports ? window.CSS.supports('touch-action', val) : true;
+ });
+ return touchMap;
+}
+
+/**
+ * Recognizer flow explained; *
+ * All recognizers have the initial state of POSSIBLE when an input session starts.
+ * The definition of an input session is from the first input until the last input, with all it's movement in it. *
+ * Example session for mouse-input: mousedown -> mousemove -> mouseup
+ *
+ * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
+ * which determines with state it should be.
+ *
+ * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
+ * POSSIBLE to give it another change on the next cycle.
+ *
+ * Possible
+ * |
+ * +-----+---------------+
+ * | |
+ * +-----+-----+ |
+ * | | |
+ * Failed Cancelled |
+ * +-------+------+
+ * | |
+ * Recognized Began
+ * |
+ * Changed
+ * |
+ * Ended/Recognized
+ */
+var STATE_POSSIBLE = 1;
+var STATE_BEGAN = 2;
+var STATE_CHANGED = 4;
+var STATE_ENDED = 8;
+var STATE_RECOGNIZED = STATE_ENDED;
+var STATE_CANCELLED = 16;
+var STATE_FAILED = 32;
+
+/**
+ * Recognizer
+ * Every recognizer needs to extend from this class.
+ * @constructor
+ * @param {Object} options
+ */
+function Recognizer(options) {
+ this.options = assign({}, this.defaults, options || {});
+
+ this.id = uniqueId();
+
+ this.manager = null;
+
+ // default is enable true
+ this.options.enable = ifUndefined(this.options.enable, true);
+
+ this.state = STATE_POSSIBLE;
+
+ this.simultaneous = {};
+ this.requireFail = [];
+}
+
+Recognizer.prototype = {
+ /**
+ * @virtual
+ * @type {Object}
+ */
+ defaults: {},
+
+ /**
+ * set options
+ * @param {Object} options
+ * @return {Recognizer}
+ */
+ set: function(options) {
+ assign(this.options, options);
+
+ // also update the touchAction, in case something changed about the directions/enabled state
+ this.manager && this.manager.touchAction.update();
+ return this;
+ },
+
+ /**
+ * recognize simultaneous with another recognizer.
+ * @param {Recognizer} otherRecognizer
+ * @returns {Recognizer} this
+ */
+ recognizeWith: function(otherRecognizer) {
+ if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
+ return this;
+ }
+
+ var simultaneous = this.simultaneous;
+ otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+ if (!simultaneous[otherRecognizer.id]) {
+ simultaneous[otherRecognizer.id] = otherRecognizer;
+ otherRecognizer.recognizeWith(this);
+ }
+ return this;
+ },
+
+ /**
+ * drop the simultaneous link. It doesn't remove the link on the other recognizer.
+ * @param {Recognizer} otherRecognizer
+ * @returns {Recognizer} this
+ */
+ dropRecognizeWith: function(otherRecognizer) {
+ if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
+ return this;
+ }
+
+ otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+ delete this.simultaneous[otherRecognizer.id];
+ return this;
+ },
+
+ /**
+ * recognizer can only run when another is failing
+ * @param {Recognizer} otherRecognizer
+ * @returns {Recognizer} this
+ */
+ requireFailure: function(otherRecognizer) {
+ if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
+ return this;
+ }
+
+ var requireFail = this.requireFail;
+ otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+ if (inArray(requireFail, otherRecognizer) === -1) {
+ requireFail.push(otherRecognizer);
+ otherRecognizer.requireFailure(this);
+ }
+ return this;
+ },
+
+ /**
+ * drop the requireFailure link. It does not remove the link on the other recognizer.
+ * @param {Recognizer} otherRecognizer
+ * @returns {Recognizer} this
+ */
+ dropRequireFailure: function(otherRecognizer) {
+ if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
+ return this;
+ }
+
+ otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
+ var index = inArray(this.requireFail, otherRecognizer);
+ if (index > -1) {
+ this.requireFail.splice(index, 1);
+ }
+ return this;
+ },
+
+ /**
+ * has require failures boolean
+ * @returns {boolean}
+ */
+ hasRequireFailures: function() {
+ return this.requireFail.length > 0;
+ },
+
+ /**
+ * if the recognizer can recognize simultaneous with another recognizer
+ * @param {Recognizer} otherRecognizer
+ * @returns {Boolean}
+ */
+ canRecognizeWith: function(otherRecognizer) {
+ return !!this.simultaneous[otherRecognizer.id];
+ },
+
+ /**
+ * You should use `tryEmit` instead of `emit` directly to check
+ * that all the needed recognizers has failed before emitting.
+ * @param {Object} input
+ */
+ emit: function(input) {
+ var self = this;
+ var state = this.state;
+
+ function emit(event) {
+ self.manager.emit(event, input);
+ }
+
+ // 'panstart' and 'panmove'
+ if (state < STATE_ENDED) {
+ emit(self.options.event + stateStr(state));
+ }
+
+ emit(self.options.event); // simple 'eventName' events
+
+ if (input.additionalEvent) { // additional event(panleft, panright, pinchin, pinchout...)
+ emit(input.additionalEvent);
+ }
+
+ // panend and pancancel
+ if (state >= STATE_ENDED) {
+ emit(self.options.event + stateStr(state));
+ }
+ },
+
+ /**
+ * Check that all the require failure recognizers has failed,
+ * if true, it emits a gesture event,
+ * otherwise, setup the state to FAILED.
+ * @param {Object} input
+ */
+ tryEmit: function(input) {
+ if (this.canEmit()) {
+ return this.emit(input);
+ }
+ // it's failing anyway
+ this.state = STATE_FAILED;
+ },
+
+ /**
+ * can we emit?
+ * @returns {boolean}
+ */
+ canEmit: function() {
+ var i = 0;
+ while (i < this.requireFail.length) {
+ if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
+ return false;
+ }
+ i++;
+ }
+ return true;
+ },
+
+ /**
+ * update the recognizer
+ * @param {Object} inputData
+ */
+ recognize: function(inputData) {
+ // make a new copy of the inputData
+ // so we can change the inputData without messing up the other recognizers
+ var inputDataClone = assign({}, inputData);
+
+ // is it enabled and allow recognizing?
+ if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
+ this.reset();
+ this.state = STATE_FAILED;
+ return;
+ }
+
+ // reset when we've reached the end
+ if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
+ this.state = STATE_POSSIBLE;
+ }
+
+ this.state = this.process(inputDataClone);
+
+ // the recognizer has recognized a gesture
+ // so trigger an event
+ if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
+ this.tryEmit(inputDataClone);
+ }
+ },
+
+ /**
+ * return the state of the recognizer
+ * the actual recognizing happens in this method
+ * @virtual
+ * @param {Object} inputData
+ * @returns {Const} STATE
+ */
+ process: function(inputData) { }, // jshint ignore:line
+
+ /**
+ * return the preferred touch-action
+ * @virtual
+ * @returns {Array}
+ */
+ getTouchAction: function() { },
+
+ /**
+ * called when the gesture isn't allowed to recognize
+ * like when another is being recognized or it is disabled
+ * @virtual
+ */
+ reset: function() { }
+};
+
+/**
+ * get a usable string, used as event postfix
+ * @param {Const} state
+ * @returns {String} state
+ */
+function stateStr(state) {
+ if (state & STATE_CANCELLED) {
+ return 'cancel';
+ } else if (state & STATE_ENDED) {
+ return 'end';
+ } else if (state & STATE_CHANGED) {
+ return 'move';
+ } else if (state & STATE_BEGAN) {
+ return 'start';
+ }
+ return '';
+}
+
+/**
+ * direction cons to string
+ * @param {Const} direction
+ * @returns {String}
+ */
+function directionStr(direction) {
+ if (direction == DIRECTION_DOWN) {
+ return 'down';
+ } else if (direction == DIRECTION_UP) {
+ return 'up';
+ } else if (direction == DIRECTION_LEFT) {
+ return 'left';
+ } else if (direction == DIRECTION_RIGHT) {
+ return 'right';
+ }
+ return '';
+}
+
+/**
+ * get a recognizer by name if it is bound to a manager
+ * @param {Recognizer|String} otherRecognizer
+ * @param {Recognizer} recognizer
+ * @returns {Recognizer}
+ */
+function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
+ var manager = recognizer.manager;
+ if (manager) {
+ return manager.get(otherRecognizer);
+ }
+ return otherRecognizer;
+}
+
+/**
+ * This recognizer is just used as a base for the simple attribute recognizers.
+ * @constructor
+ * @extends Recognizer
+ */
+function AttrRecognizer() {
+ Recognizer.apply(this, arguments);
+}
+
+inherit(AttrRecognizer, Recognizer, {
+ /**
+ * @namespace
+ * @memberof AttrRecognizer
+ */
+ defaults: {
+ /**
+ * @type {Number}
+ * @default 1
+ */
+ pointers: 1
+ },
+
+ /**
+ * Used to check if it the recognizer receives valid input, like input.distance > 10.
+ * @memberof AttrRecognizer
+ * @param {Object} input
+ * @returns {Boolean} recognized
+ */
+ attrTest: function(input) {
+ var optionPointers = this.options.pointers;
+ return optionPointers === 0 || input.pointers.length === optionPointers;
+ },
+
+ /**
+ * Process the input and return the state for the recognizer
+ * @memberof AttrRecognizer
+ * @param {Object} input
+ * @returns {*} State
+ */
+ process: function(input) {
+ var state = this.state;
+ var eventType = input.eventType;
+
+ var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
+ var isValid = this.attrTest(input);
+
+ // on cancel input and we've recognized before, return STATE_CANCELLED
+ if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
+ return state | STATE_CANCELLED;
+ } else if (isRecognized || isValid) {
+ if (eventType & INPUT_END) {
+ return state | STATE_ENDED;
+ } else if (!(state & STATE_BEGAN)) {
+ return STATE_BEGAN;
+ }
+ return state | STATE_CHANGED;
+ }
+ return STATE_FAILED;
+ }
+});
+
+/**
+ * Pan
+ * Recognized when the pointer is down and moved in the allowed direction.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function PanRecognizer() {
+ AttrRecognizer.apply(this, arguments);
+
+ this.pX = null;
+ this.pY = null;
+}
+
+inherit(PanRecognizer, AttrRecognizer, {
+ /**
+ * @namespace
+ * @memberof PanRecognizer
+ */
+ defaults: {
+ event: 'pan',
+ threshold: 10,
+ pointers: 1,
+ direction: DIRECTION_ALL
+ },
+
+ getTouchAction: function() {
+ var direction = this.options.direction;
+ var actions = [];
+ if (direction & DIRECTION_HORIZONTAL) {
+ actions.push(TOUCH_ACTION_PAN_Y);
+ }
+ if (direction & DIRECTION_VERTICAL) {
+ actions.push(TOUCH_ACTION_PAN_X);
+ }
+ return actions;
+ },
+
+ directionTest: function(input) {
+ var options = this.options;
+ var hasMoved = true;
+ var distance = input.distance;
+ var direction = input.direction;
+ var x = input.deltaX;
+ var y = input.deltaY;
+
+ // lock to axis?
+ if (!(direction & options.direction)) {
+ if (options.direction & DIRECTION_HORIZONTAL) {
+ direction = (x === 0) ? DIRECTION_NONE : (x < 0) ? DIRECTION_LEFT : DIRECTION_RIGHT;
+ hasMoved = x != this.pX;
+ distance = Math.abs(input.deltaX);
+ } else {
+ direction = (y === 0) ? DIRECTION_NONE : (y < 0) ? DIRECTION_UP : DIRECTION_DOWN;
+ hasMoved = y != this.pY;
+ distance = Math.abs(input.deltaY);
+ }
+ }
+ input.direction = direction;
+ return hasMoved && distance > options.threshold && direction & options.direction;
+ },
+
+ attrTest: function(input) {
+ return AttrRecognizer.prototype.attrTest.call(this, input) &&
+ (this.state & STATE_BEGAN || (!(this.state & STATE_BEGAN) && this.directionTest(input)));
+ },
+
+ emit: function(input) {
+
+ this.pX = input.deltaX;
+ this.pY = input.deltaY;
+
+ var direction = directionStr(input.direction);
+
+ if (direction) {
+ input.additionalEvent = this.options.event + direction;
+ }
+ this._super.emit.call(this, input);
+ }
+});
+
+/**
+ * Pinch
+ * Recognized when two or more pointers are moving toward (zoom-in) or away from each other (zoom-out).
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function PinchRecognizer() {
+ AttrRecognizer.apply(this, arguments);
+}
+
+inherit(PinchRecognizer, AttrRecognizer, {
+ /**
+ * @namespace
+ * @memberof PinchRecognizer
+ */
+ defaults: {
+ event: 'pinch',
+ threshold: 0,
+ pointers: 2
+ },
+
+ getTouchAction: function() {
+ return [TOUCH_ACTION_NONE];
+ },
+
+ attrTest: function(input) {
+ return this._super.attrTest.call(this, input) &&
+ (Math.abs(input.scale - 1) > this.options.threshold || this.state & STATE_BEGAN);
+ },
+
+ emit: function(input) {
+ if (input.scale !== 1) {
+ var inOut = input.scale < 1 ? 'in' : 'out';
+ input.additionalEvent = this.options.event + inOut;
+ }
+ this._super.emit.call(this, input);
+ }
+});
+
+/**
+ * Press
+ * Recognized when the pointer is down for x ms without any movement.
+ * @constructor
+ * @extends Recognizer
+ */
+function PressRecognizer() {
+ Recognizer.apply(this, arguments);
+
+ this._timer = null;
+ this._input = null;
+}
+
+inherit(PressRecognizer, Recognizer, {
+ /**
+ * @namespace
+ * @memberof PressRecognizer
+ */
+ defaults: {
+ event: 'press',
+ pointers: 1,
+ time: 251, // minimal time of the pointer to be pressed
+ threshold: 9 // a minimal movement is ok, but keep it low
+ },
+
+ getTouchAction: function() {
+ return [TOUCH_ACTION_AUTO];
+ },
+
+ process: function(input) {
+ var options = this.options;
+ var validPointers = input.pointers.length === options.pointers;
+ var validMovement = input.distance < options.threshold;
+ var validTime = input.deltaTime > options.time;
+
+ this._input = input;
+
+ // we only allow little movement
+ // and we've reached an end event, so a tap is possible
+ if (!validMovement || !validPointers || (input.eventType & (INPUT_END | INPUT_CANCEL) && !validTime)) {
+ this.reset();
+ } else if (input.eventType & INPUT_START) {
+ this.reset();
+ this._timer = setTimeoutContext(function() {
+ this.state = STATE_RECOGNIZED;
+ this.tryEmit();
+ }, options.time, this);
+ } else if (input.eventType & INPUT_END) {
+ return STATE_RECOGNIZED;
+ }
+ return STATE_FAILED;
+ },
+
+ reset: function() {
+ clearTimeout(this._timer);
+ },
+
+ emit: function(input) {
+ if (this.state !== STATE_RECOGNIZED) {
+ return;
+ }
+
+ if (input && (input.eventType & INPUT_END)) {
+ this.manager.emit(this.options.event + 'up', input);
+ } else {
+ this._input.timeStamp = now();
+ this.manager.emit(this.options.event, this._input);
+ }
+ }
+});
+
+/**
+ * Rotate
+ * Recognized when two or more pointer are moving in a circular motion.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function RotateRecognizer() {
+ AttrRecognizer.apply(this, arguments);
+}
+
+inherit(RotateRecognizer, AttrRecognizer, {
+ /**
+ * @namespace
+ * @memberof RotateRecognizer
+ */
+ defaults: {
+ event: 'rotate',
+ threshold: 0,
+ pointers: 2
+ },
+
+ getTouchAction: function() {
+ return [TOUCH_ACTION_NONE];
+ },
+
+ attrTest: function(input) {
+ return this._super.attrTest.call(this, input) &&
+ (Math.abs(input.rotation) > this.options.threshold || this.state & STATE_BEGAN);
+ }
+});
+
+/**
+ * Swipe
+ * Recognized when the pointer is moving fast (velocity), with enough distance in the allowed direction.
+ * @constructor
+ * @extends AttrRecognizer
+ */
+function SwipeRecognizer() {
+ AttrRecognizer.apply(this, arguments);
+}
+
+inherit(SwipeRecognizer, AttrRecognizer, {
+ /**
+ * @namespace
+ * @memberof SwipeRecognizer
+ */
+ defaults: {
+ event: 'swipe',
+ threshold: 10,
+ velocity: 0.3,
+ direction: DIRECTION_HORIZONTAL | DIRECTION_VERTICAL,
+ pointers: 1
+ },
+
+ getTouchAction: function() {
+ return PanRecognizer.prototype.getTouchAction.call(this);
+ },
+
+ attrTest: function(input) {
+ var direction = this.options.direction;
+ var velocity;
+
+ if (direction & (DIRECTION_HORIZONTAL | DIRECTION_VERTICAL)) {
+ velocity = input.overallVelocity;
+ } else if (direction & DIRECTION_HORIZONTAL) {
+ velocity = input.overallVelocityX;
+ } else if (direction & DIRECTION_VERTICAL) {
+ velocity = input.overallVelocityY;
+ }
+
+ return this._super.attrTest.call(this, input) &&
+ direction & input.offsetDirection &&
+ input.distance > this.options.threshold &&
+ input.maxPointers == this.options.pointers &&
+ abs(velocity) > this.options.velocity && input.eventType & INPUT_END;
+ },
+
+ emit: function(input) {
+ var direction = directionStr(input.offsetDirection);
+ if (direction) {
+ this.manager.emit(this.options.event + direction, input);
+ }
+
+ this.manager.emit(this.options.event, input);
+ }
+});
+
+/**
+ * A tap is recognized when the pointer is doing a small tap/click. Multiple taps are recognized if they occur
+ * between the given interval and position. The delay option can be used to recognize multi-taps without firing
+ * a single tap.
+ *
+ * The eventData from the emitted event contains the property `tapCount`, which contains the amount of
+ * multi-taps being recognized.
+ * @constructor
+ * @extends Recognizer
+ */
+function TapRecognizer() {
+ Recognizer.apply(this, arguments);
+
+ // previous time and center,
+ // used for tap counting
+ this.pTime = false;
+ this.pCenter = false;
+
+ this._timer = null;
+ this._input = null;
+ this.count = 0;
+}
+
+inherit(TapRecognizer, Recognizer, {
+ /**
+ * @namespace
+ * @memberof PinchRecognizer
+ */
+ defaults: {
+ event: 'tap',
+ pointers: 1,
+ taps: 1,
+ interval: 300, // max time between the multi-tap taps
+ time: 250, // max time of the pointer to be down (like finger on the screen)
+ threshold: 9, // a minimal movement is ok, but keep it low
+ posThreshold: 10 // a multi-tap can be a bit off the initial position
+ },
+
+ getTouchAction: function() {
+ return [TOUCH_ACTION_MANIPULATION];
+ },
+
+ process: function(input) {
+ var options = this.options;
+
+ var validPointers = input.pointers.length === options.pointers;
+ var validMovement = input.distance < options.threshold;
+ var validTouchTime = input.deltaTime < options.time;
+
+ this.reset();
+
+ if ((input.eventType & INPUT_START) && (this.count === 0)) {
+ return this.failTimeout();
+ }
+
+ // we only allow little movement
+ // and we've reached an end event, so a tap is possible
+ if (validMovement && validTouchTime && validPointers) {
+ if (input.eventType != INPUT_END) {
+ return this.failTimeout();
+ }
+
+ var validInterval = this.pTime ? (input.timeStamp - this.pTime < options.interval) : true;
+ var validMultiTap = !this.pCenter || getDistance(this.pCenter, input.center) < options.posThreshold;
+
+ this.pTime = input.timeStamp;
+ this.pCenter = input.center;
+
+ if (!validMultiTap || !validInterval) {
+ this.count = 1;
+ } else {
+ this.count += 1;
+ }
+
+ this._input = input;
+
+ // if tap count matches we have recognized it,
+ // else it has begun recognizing...
+ var tapCount = this.count % options.taps;
+ if (tapCount === 0) {
+ // no failing requirements, immediately trigger the tap event
+ // or wait as long as the multitap interval to trigger
+ if (!this.hasRequireFailures()) {
+ return STATE_RECOGNIZED;
+ } else {
+ this._timer = setTimeoutContext(function() {
+ this.state = STATE_RECOGNIZED;
+ this.tryEmit();
+ }, options.interval, this);
+ return STATE_BEGAN;
+ }
+ }
+ }
+ return STATE_FAILED;
+ },
+
+ failTimeout: function() {
+ this._timer = setTimeoutContext(function() {
+ this.state = STATE_FAILED;
+ }, this.options.interval, this);
+ return STATE_FAILED;
+ },
+
+ reset: function() {
+ clearTimeout(this._timer);
+ },
+
+ emit: function() {
+ if (this.state == STATE_RECOGNIZED) {
+ this._input.tapCount = this.count;
+ this.manager.emit(this.options.event, this._input);
+ }
+ }
+});
+
+/**
+ * Simple way to create a manager with a default set of recognizers.
+ * @param {HTMLElement} element
+ * @param {Object} [options]
+ * @constructor
+ */
+function Hammer(element, options) {
+ options = options || {};
+ options.recognizers = ifUndefined(options.recognizers, Hammer.defaults.preset);
+ return new Manager(element, options);
+}
+
+/**
+ * @const {string}
+ */
+Hammer.VERSION = '2.0.7';
+
+/**
+ * default settings
+ * @namespace
+ */
+Hammer.defaults = {
+ /**
+ * set if DOM events are being triggered.
+ * But this is slower and unused by simple implementations, so disabled by default.
+ * @type {Boolean}
+ * @default false
+ */
+ domEvents: false,
+
+ /**
+ * The value for the touchAction property/fallback.
+ * When set to `compute` it will magically set the correct value based on the added recognizers.
+ * @type {String}
+ * @default compute
+ */
+ touchAction: TOUCH_ACTION_COMPUTE,
+
+ /**
+ * @type {Boolean}
+ * @default true
+ */
+ enable: true,
+
+ /**
+ * EXPERIMENTAL FEATURE -- can be removed/changed
+ * Change the parent input target element.
+ * If Null, then it is being set the to main element.
+ * @type {Null|EventTarget}
+ * @default null
+ */
+ inputTarget: null,
+
+ /**
+ * force an input class
+ * @type {Null|Function}
+ * @default null
+ */
+ inputClass: null,
+
+ /**
+ * Default recognizer setup when calling `Hammer()`
+ * When creating a new Manager these will be skipped.
+ * @type {Array}
+ */
+ preset: [
+ // RecognizerClass, options, [recognizeWith, ...], [requireFailure, ...]
+ [RotateRecognizer, {enable: false}],
+ [PinchRecognizer, {enable: false}, ['rotate']],
+ [SwipeRecognizer, {direction: DIRECTION_HORIZONTAL}],
+ [PanRecognizer, {direction: DIRECTION_HORIZONTAL}, ['swipe']],
+ [TapRecognizer],
+ [TapRecognizer, {event: 'doubletap', taps: 2}, ['tap']],
+ [PressRecognizer]
+ ],
+
+ /**
+ * Some CSS properties can be used to improve the working of Hammer.
+ * Add them to this method and they will be set when creating a new Manager.
+ * @namespace
+ */
+ cssProps: {
+ /**
+ * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
+ * @type {String}
+ * @default 'none'
+ */
+ userSelect: 'none',
+
+ /**
+ * Disable the Windows Phone grippers when pressing an element.
+ * @type {String}
+ * @default 'none'
+ */
+ touchSelect: 'none',
+
+ /**
+ * Disables the default callout shown when you touch and hold a touch target.
+ * On iOS, when you touch and hold a touch target such as a link, Safari displays
+ * a callout containing information about the link. This property allows you to disable that callout.
+ * @type {String}
+ * @default 'none'
+ */
+ touchCallout: 'none',
+
+ /**
+ * Specifies whether zooming is enabled. Used by IE10>
+ * @type {String}
+ * @default 'none'
+ */
+ contentZooming: 'none',
+
+ /**
+ * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
+ * @type {String}
+ * @default 'none'
+ */
+ userDrag: 'none',
+
+ /**
+ * Overrides the highlight color shown when the user taps a link or a JavaScript
+ * clickable element in iOS. This property obeys the alpha value, if specified.
+ * @type {String}
+ * @default 'rgba(0,0,0,0)'
+ */
+ tapHighlightColor: 'rgba(0,0,0,0)'
+ }
+};
+
+var STOP = 1;
+var FORCED_STOP = 2;
+
+/**
+ * Manager
+ * @param {HTMLElement} element
+ * @param {Object} [options]
+ * @constructor
+ */
+function Manager(element, options) {
+ this.options = assign({}, Hammer.defaults, options || {});
+
+ this.options.inputTarget = this.options.inputTarget || element;
+
+ this.handlers = {};
+ this.session = {};
+ this.recognizers = [];
+ this.oldCssProps = {};
+
+ this.element = element;
+ this.input = createInputInstance(this);
+ this.touchAction = new TouchAction(this, this.options.touchAction);
+
+ toggleCssProps(this, true);
+
+ each(this.options.recognizers, function(item) {
+ var recognizer = this.add(new (item[0])(item[1]));
+ item[2] && recognizer.recognizeWith(item[2]);
+ item[3] && recognizer.requireFailure(item[3]);
+ }, this);
+}
+
+Manager.prototype = {
+ /**
+ * set options
+ * @param {Object} options
+ * @returns {Manager}
+ */
+ set: function(options) {
+ assign(this.options, options);
+
+ // Options that need a little more setup
+ if (options.touchAction) {
+ this.touchAction.update();
+ }
+ if (options.inputTarget) {
+ // Clean up existing event listeners and reinitialize
+ this.input.destroy();
+ this.input.target = options.inputTarget;
+ this.input.init();
+ }
+ return this;
+ },
+
+ /**
+ * stop recognizing for this session.
+ * This session will be discarded, when a new [input]start event is fired.
+ * When forced, the recognizer cycle is stopped immediately.
+ * @param {Boolean} [force]
+ */
+ stop: function(force) {
+ this.session.stopped = force ? FORCED_STOP : STOP;
+ },
+
+ /**
+ * run the recognizers!
+ * called by the inputHandler function on every movement of the pointers (touches)
+ * it walks through all the recognizers and tries to detect the gesture that is being made
+ * @param {Object} inputData
+ */
+ recognize: function(inputData) {
+ var session = this.session;
+ if (session.stopped) {
+ return;
+ }
+
+ // run the touch-action polyfill
+ this.touchAction.preventDefaults(inputData);
+
+ var recognizer;
+ var recognizers = this.recognizers;
+
+ // this holds the recognizer that is being recognized.
+ // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
+ // if no recognizer is detecting a thing, it is set to `null`
+ var curRecognizer = session.curRecognizer;
+
+ // reset when the last recognizer is recognized
+ // or when we're in a new session
+ if (!curRecognizer || (curRecognizer && curRecognizer.state & STATE_RECOGNIZED)) {
+ curRecognizer = session.curRecognizer = null;
+ }
+
+ var i = 0;
+ while (i < recognizers.length) {
+ recognizer = recognizers[i];
+
+ // find out if we are allowed try to recognize the input for this one.
+ // 1. allow if the session is NOT forced stopped (see the .stop() method)
+ // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
+ // that is being recognized.
+ // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
+ // this can be setup with the `recognizeWith()` method on the recognizer.
+ if (session.stopped !== FORCED_STOP && ( // 1
+ !curRecognizer || recognizer == curRecognizer || // 2
+ recognizer.canRecognizeWith(curRecognizer))) { // 3
+ recognizer.recognize(inputData);
+ } else {
+ recognizer.reset();
+ }
+
+ // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
+ // current active recognizer. but only if we don't already have an active recognizer
+ if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
+ curRecognizer = session.curRecognizer = recognizer;
+ }
+ i++;
+ }
+ },
+
+ /**
+ * get a recognizer by its event name.
+ * @param {Recognizer|String} recognizer
+ * @returns {Recognizer|Null}
+ */
+ get: function(recognizer) {
+ if (recognizer instanceof Recognizer) {
+ return recognizer;
+ }
+
+ var recognizers = this.recognizers;
+ for (var i = 0; i < recognizers.length; i++) {
+ if (recognizers[i].options.event == recognizer) {
+ return recognizers[i];
+ }
+ }
+ return null;
+ },
+
+ /**
+ * add a recognizer to the manager
+ * existing recognizers with the same event name will be removed
+ * @param {Recognizer} recognizer
+ * @returns {Recognizer|Manager}
+ */
+ add: function(recognizer) {
+ if (invokeArrayArg(recognizer, 'add', this)) {
+ return this;
+ }
+
+ // remove existing
+ var existing = this.get(recognizer.options.event);
+ if (existing) {
+ this.remove(existing);
+ }
+
+ this.recognizers.push(recognizer);
+ recognizer.manager = this;
+
+ this.touchAction.update();
+ return recognizer;
+ },
+
+ /**
+ * remove a recognizer by name or instance
+ * @param {Recognizer|String} recognizer
+ * @returns {Manager}
+ */
+ remove: function(recognizer) {
+ if (invokeArrayArg(recognizer, 'remove', this)) {
+ return this;
+ }
+
+ recognizer = this.get(recognizer);
+
+ // let's make sure this recognizer exists
+ if (recognizer) {
+ var recognizers = this.recognizers;
+ var index = inArray(recognizers, recognizer);
+
+ if (index !== -1) {
+ recognizers.splice(index, 1);
+ this.touchAction.update();
+ }
+ }
+
+ return this;
+ },
+
+ /**
+ * bind event
+ * @param {String} events
+ * @param {Function} handler
+ * @returns {EventEmitter} this
+ */
+ on: function(events, handler) {
+ if (events === undefined) {
+ return;
+ }
+ if (handler === undefined) {
+ return;
+ }
+
+ var handlers = this.handlers;
+ each(splitStr(events), function(event) {
+ handlers[event] = handlers[event] || [];
+ handlers[event].push(handler);
+ });
+ return this;
+ },
+
+ /**
+ * unbind event, leave emit blank to remove all handlers
+ * @param {String} events
+ * @param {Function} [handler]
+ * @returns {EventEmitter} this
+ */
+ off: function(events, handler) {
+ if (events === undefined) {
+ return;
+ }
+
+ var handlers = this.handlers;
+ each(splitStr(events), function(event) {
+ if (!handler) {
+ delete handlers[event];
+ } else {
+ handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
+ }
+ });
+ return this;
+ },
+
+ /**
+ * emit event to the listeners
+ * @param {String} event
+ * @param {Object} data
+ */
+ emit: function(event, data) {
+ // we also want to trigger dom events
+ if (this.options.domEvents) {
+ triggerDomEvent(event, data);
+ }
+
+ // no handlers, so skip it all
+ var handlers = this.handlers[event] && this.handlers[event].slice();
+ if (!handlers || !handlers.length) {
+ return;
+ }
+
+ data.type = event;
+ data.preventDefault = function() {
+ data.srcEvent.preventDefault();
+ };
+
+ var i = 0;
+ while (i < handlers.length) {
+ handlers[i](data);
+ i++;
+ }
+ },
+
+ /**
+ * destroy the manager and unbinds all events
+ * it doesn't unbind dom events, that is the user own responsibility
+ */
+ destroy: function() {
+ this.element && toggleCssProps(this, false);
+
+ this.handlers = {};
+ this.session = {};
+ this.input.destroy();
+ this.element = null;
+ }
+};
+
+/**
+ * add/remove the css properties as defined in manager.options.cssProps
+ * @param {Manager} manager
+ * @param {Boolean} add
+ */
+function toggleCssProps(manager, add) {
+ var element = manager.element;
+ if (!element.style) {
+ return;
+ }
+ var prop;
+ each(manager.options.cssProps, function(value, name) {
+ prop = prefixed(element.style, name);
+ if (add) {
+ manager.oldCssProps[prop] = element.style[prop];
+ element.style[prop] = value;
+ } else {
+ element.style[prop] = manager.oldCssProps[prop] || '';
+ }
+ });
+ if (!add) {
+ manager.oldCssProps = {};
+ }
+}
+
+/**
+ * trigger dom event
+ * @param {String} event
+ * @param {Object} data
+ */
+function triggerDomEvent(event, data) {
+ var gestureEvent = document.createEvent('Event');
+ gestureEvent.initEvent(event, true, true);
+ gestureEvent.gesture = data;
+ data.target.dispatchEvent(gestureEvent);
+}
+
+assign(Hammer, {
+ INPUT_START: INPUT_START,
+ INPUT_MOVE: INPUT_MOVE,
+ INPUT_END: INPUT_END,
+ INPUT_CANCEL: INPUT_CANCEL,
+
+ STATE_POSSIBLE: STATE_POSSIBLE,
+ STATE_BEGAN: STATE_BEGAN,
+ STATE_CHANGED: STATE_CHANGED,
+ STATE_ENDED: STATE_ENDED,
+ STATE_RECOGNIZED: STATE_RECOGNIZED,
+ STATE_CANCELLED: STATE_CANCELLED,
+ STATE_FAILED: STATE_FAILED,
+
+ DIRECTION_NONE: DIRECTION_NONE,
+ DIRECTION_LEFT: DIRECTION_LEFT,
+ DIRECTION_RIGHT: DIRECTION_RIGHT,
+ DIRECTION_UP: DIRECTION_UP,
+ DIRECTION_DOWN: DIRECTION_DOWN,
+ DIRECTION_HORIZONTAL: DIRECTION_HORIZONTAL,
+ DIRECTION_VERTICAL: DIRECTION_VERTICAL,
+ DIRECTION_ALL: DIRECTION_ALL,
+
+ Manager: Manager,
+ Input: Input,
+ TouchAction: TouchAction,
+
+ TouchInput: TouchInput,
+ MouseInput: MouseInput,
+ PointerEventInput: PointerEventInput,
+ TouchMouseInput: TouchMouseInput,
+ SingleTouchInput: SingleTouchInput,
+
+ Recognizer: Recognizer,
+ AttrRecognizer: AttrRecognizer,
+ Tap: TapRecognizer,
+ Pan: PanRecognizer,
+ Swipe: SwipeRecognizer,
+ Pinch: PinchRecognizer,
+ Rotate: RotateRecognizer,
+ Press: PressRecognizer,
+
+ on: addEventListeners,
+ off: removeEventListeners,
+ each: each,
+ merge: merge,
+ extend: extend,
+ assign: assign,
+ inherit: inherit,
+ bindFn: bindFn,
+ prefixed: prefixed
+});
+
+// this prevents errors when Hammer is loaded in the presence of an AMD
+// style loader but by script tag, not by the loader.
+var freeGlobal = (typeof window !== 'undefined' ? window : (typeof self !== 'undefined' ? self : {})); // jshint ignore:line
+freeGlobal.Hammer = Hammer;
+
+if (typeof define === 'function' && define.amd) {
+ define(function() {
+ return Hammer;
+ });
+} else if (typeof module != 'undefined' && module.exports) {
+ module.exports = Hammer;
+} else {
+ window[exportName] = Hammer;
+}
+
+})(window, document, 'Hammer');
+
+/*****
+ * @licstart
+ *
+ * The following is the license notice for the part of JavaScript code of this
+ * page included between the '@jessyinkstart' and the '@jessyinkend' notes.
+ */
+
+/***** ******************************************************************
+ *
+ * Copyright 2008-2013 Hannes Hochreiner
+ *
+ * The JavaScript code included between the start note '@jessyinkstart'
+ * and the end note '@jessyinkend' 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/.
+ *
+ * Alternatively, you can redistribute and/or that part of this file
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see http://www.gnu.org/licenses/.
+*/
+
+/*****
+ * You can find the complete source code of the JessyInk project at:
+ * @source http://code.google.com/p/jessyink/
+ */
+
+/*****
+ * @licend
+ *
+ * The above is the license notice for the part of JavaScript code of this
+ * page included between the '@jessyinkstart' and the '@jessyinkend' notes.
+ */
+
+
+
+/*****
+ * @jessyinkstart
+ *
+ * The following code is a derivative work of some parts of the JessyInk
+ * project.
+ * @source http://code.google.com/p/jessyink/
+ */
+
+/** Convenience function to get an element depending on whether it has a
+ * property with a particular name.
+ *
+ * @param node element of the document
+ * @param name attribute name
+ *
+ * @returns Array array containing all the elements of the tree with root
+ * 'node' that own the property 'name'
+ */
+function getElementsByProperty( node, name )
+{
+ var elements = [];
+
+ if( node.getAttribute( name ) )
+ elements.push( node );
+
+ for( var counter = 0; counter < node.childNodes.length; ++counter )
+ {
+ if( node.childNodes[counter].nodeType == 1 )
+ {
+ var subElements = getElementsByProperty( node.childNodes[counter], name );
+ elements = elements.concat( subElements );
+ }
+ }
+ return elements;
+}
+
+/** Event handler for key press.
+ *
+ * @param aEvt the event
+ */
+function onKeyDown( aEvt )
+{
+ if ( !aEvt )
+ aEvt = window.event;
+
+ var code = aEvt.keyCode || aEvt.charCode;
+
+ // console.log('===> onKeyDown: ' + code);
+
+ // Handle arrow keys in iOS WebKit (including Mobile Safari)
+ if (code == 0 && aEvt.key != undefined) {
+ switch (aEvt.key) {
+ case 'UIKeyInputLeftArrow':
+ code = LEFT_KEY;
+ break;
+ case 'UIKeyInputUpArrow':
+ code = UP_KEY;
+ break;
+ case 'UIKeyInputRightArrow':
+ code = RIGHT_KEY;
+ break;
+ case 'UIKeyInputDownArrow':
+ code = DOWN_KEY;
+ break;
+ }
+
+ // console.log(' now: ' + code);
+ }
+
+ if( !processingEffect && keyCodeDictionary[currentMode] && keyCodeDictionary[currentMode][code] )
+ {
+ return keyCodeDictionary[currentMode][code]();
+ }
+ else
+ {
+ document.onkeypress = onKeyPress;
+ return null;
+ }
+}
+//Set event handler for key down.
+document.onkeydown = onKeyDown;
+
+/** Event handler for key press.
+ *
+ * @param aEvt the event
+ */
+function onKeyPress( aEvt )
+{
+ document.onkeypress = null;
+
+ if ( !aEvt )
+ aEvt = window.event;
+
+ var str = String.fromCharCode( aEvt.keyCode || aEvt.charCode );
+
+ if ( !processingEffect && charCodeDictionary[currentMode] && charCodeDictionary[currentMode][str] )
+ return charCodeDictionary[currentMode][str]();
+
+ return null;
+}
+
+/** Function to supply the default key code dictionary.
+ *
+ * @returns Object default key code dictionary
+ */
+function getDefaultKeyCodeDictionary()
+{
+ var keyCodeDict = {};
+
+ keyCodeDict[SLIDE_MODE] = {};
+ keyCodeDict[INDEX_MODE] = {};
+
+ // slide mode
+ keyCodeDict[SLIDE_MODE][LEFT_KEY]
+ = function() { return aSlideShow.rewindEffect(); };
+ keyCodeDict[SLIDE_MODE][RIGHT_KEY]
+ = function() { return dispatchEffects(1); };
+ keyCodeDict[SLIDE_MODE][UP_KEY]
+ = function() { return aSlideShow.rewindEffect(); };
+ keyCodeDict[SLIDE_MODE][DOWN_KEY]
+ = function() { return skipEffects(1); };
+ keyCodeDict[SLIDE_MODE][PAGE_UP_KEY]
+ = function() { return aSlideShow.rewindAllEffects(); };
+ keyCodeDict[SLIDE_MODE][PAGE_DOWN_KEY]
+ = function() { return skipAllEffects(); };
+ keyCodeDict[SLIDE_MODE][HOME_KEY]
+ = function() { return aSlideShow.displaySlide( 0, true ); };
+ keyCodeDict[SLIDE_MODE][END_KEY]
+ = function() { return aSlideShow.displaySlide( theMetaDoc.nNumberOfSlides - 1, true ); };
+ keyCodeDict[SLIDE_MODE][SPACE_KEY]
+ = function() { return dispatchEffects(1); };
+ // The ESC key can't actually be handled on iOS, it seems to be hardcoded to work like the home button? But try anyway.
+ keyCodeDict[SLIDE_MODE][ESCAPE_KEY]
+ = function() { return aSlideShow.exitSlideShowInApp(); };
+ keyCodeDict[SLIDE_MODE][Q_KEY]
+ = function() { return aSlideShow.exitSlideShowInApp(); };
+
+ // index mode
+ keyCodeDict[INDEX_MODE][LEFT_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex - 1 ); };
+ keyCodeDict[INDEX_MODE][RIGHT_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex + 1 ); };
+ keyCodeDict[INDEX_MODE][UP_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex - theSlideIndexPage.indexColumns ); };
+ keyCodeDict[INDEX_MODE][DOWN_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex + theSlideIndexPage.indexColumns ); };
+ keyCodeDict[INDEX_MODE][PAGE_UP_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex - theSlideIndexPage.getTotalThumbnails() ); };
+ keyCodeDict[INDEX_MODE][PAGE_DOWN_KEY]
+ = function() { return indexSetPageSlide( theSlideIndexPage.selectedSlideIndex + theSlideIndexPage.getTotalThumbnails() ); };
+ keyCodeDict[INDEX_MODE][HOME_KEY]
+ = function() { return indexSetPageSlide( 0 ); };
+ keyCodeDict[INDEX_MODE][END_KEY]
+ = function() { return indexSetPageSlide( theMetaDoc.nNumberOfSlides - 1 ); };
+ keyCodeDict[INDEX_MODE][ENTER_KEY]
+ = function() { return toggleSlideIndex(); };
+ keyCodeDict[INDEX_MODE][SPACE_KEY]
+ = function() { return toggleSlideIndex(); };
+ keyCodeDict[INDEX_MODE][ESCAPE_KEY]
+ = function() { return abandonIndexMode(); };
+
+ return keyCodeDict;
+}
+
+/** Function to supply the default char code dictionary.
+ *
+ * @returns Object char code dictionary
+ */
+function getDefaultCharCodeDictionary()
+{
+ var charCodeDict = {};
+
+ charCodeDict[SLIDE_MODE] = {};
+ charCodeDict[INDEX_MODE] = {};
+
+ // slide mode
+ charCodeDict[SLIDE_MODE]['i']
+ = function () { return toggleSlideIndex(); };
+
+ // index mode
+ charCodeDict[INDEX_MODE]['i']
+ = function () { return toggleSlideIndex(); };
+ charCodeDict[INDEX_MODE]['-']
+ = function () { return theSlideIndexPage.decreaseNumberOfColumns(); };
+ charCodeDict[INDEX_MODE]['=']
+ = function () { return theSlideIndexPage.increaseNumberOfColumns(); };
+ charCodeDict[INDEX_MODE]['+']
+ = function () { return theSlideIndexPage.increaseNumberOfColumns(); };
+ charCodeDict[INDEX_MODE]['0']
+ = function () { return theSlideIndexPage.resetNumberOfColumns(); };
+
+ return charCodeDict;
+}
+
+
+function slideOnMouseUp( aEvt )
+{
+ if (!aEvt)
+ aEvt = window.event;
+
+ var nOffset = 0;
+
+ if( aEvt.button == 0 )
+ nOffset = 1;
+ else if( aEvt.button == 2 )
+ nOffset = -1;
+
+ if( 0 != nOffset )
+ dispatchEffects( nOffset );
+ return true; // the click has been handled
+}
+
+document.handleClick = slideOnMouseUp;
+
+
+/** Event handler for mouse wheel events in slide mode.
+ * based on http://adomas.org/javascript-mouse-wheel/
+ *
+ * @param aEvt the event
+ */
+function slideOnMouseWheel(aEvt)
+{
+ var delta = 0;
+
+ if (!aEvt)
+ aEvt = window.event;
+
+ if (aEvt.wheelDelta)
+ { // IE Opera
+ delta = aEvt.wheelDelta/120;
+ }
+ else if (aEvt.detail)
+ { // MOZ
+ delta = -aEvt.detail/3;
+ }
+
+ if (delta > 0)
+ skipEffects(-1);
+ else if (delta < 0)
+ skipEffects(1);
+
+ if (aEvt.preventDefault)
+ aEvt.preventDefault();
+
+ aEvt.returnValue = false;
+}
+
+//Mozilla
+if( window.addEventListener )
+{
+ window.addEventListener( 'DOMMouseScroll', function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_WHEEL ); }, false );
+}
+
+//Opera Safari OK - may not work in IE
+window.onmousewheel
+ = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_WHEEL ); };
+
+/** Function to handle all mouse events.
+ *
+ * @param aEvt event
+ * @param anAction type of event (e.g. mouse up, mouse wheel)
+ */
+function mouseHandlerDispatch( aEvt, anAction )
+{
+ if( !aEvt )
+ aEvt = window.event;
+
+ var retVal = true;
+
+ if ( mouseHandlerDictionary[currentMode] && mouseHandlerDictionary[currentMode][anAction] )
+ {
+ var subRetVal = mouseHandlerDictionary[currentMode][anAction]( aEvt );
+
+ if( subRetVal != null && subRetVal != undefined )
+ retVal = subRetVal;
+ }
+
+ if( aEvt.preventDefault && !retVal )
+ aEvt.preventDefault();
+
+ aEvt.returnValue = retVal;
+
+ return retVal;
+}
+
+//Set mouse event handler.
+document.onmouseup = function( aEvt ) { return mouseHandlerDispatch( aEvt, MOUSE_UP ); };
+
+
+/** mouseClickHelper
+ *
+ * @return {Object}
+ * a mouse click handler
+ */
+function mouseClickHelper( aEvt )
+{
+ // In case text is selected we stay on the current slide.
+ // Anyway if we are dealing with Firefox there is an issue:
+ // Firefox supports a naive way of selecting svg text, if you click
+ // on text the current selection is set to the whole text fragment
+ // wrapped by the related <tspan> element.
+ // That means until you click on text you never move to the next slide.
+ // In order to avoid this case we do not test the status of current
+ // selection, when the presentation is running on a mozilla browser.
+ if( !Detect.isMozilla )
+ {
+ var aWindowObject = document.defaultView;
+ if( aWindowObject )
+ {
+ var aTextSelection = aWindowObject.getSelection();
+ var sSelectedText = aTextSelection.toString();
+ if( sSelectedText )
+ {
+ DBGLOG( 'text selection: ' + sSelectedText );
+ if( sLastSelectedText !== sSelectedText )
+ {
+ bTextHasBeenSelected = true;
+ sLastSelectedText = sSelectedText;
+ }
+ else
+ {
+ bTextHasBeenSelected = false;
+ }
+ return null;
+ }
+ else if( bTextHasBeenSelected )
+ {
+ bTextHasBeenSelected = false;
+ sLastSelectedText = '';
+ return null;
+ }
+ }
+ else
+ {
+ log( 'error: HyperlinkElement.handleClick: invalid window object.' );
+ }
+ }
+
+ var aSlideAnimationsHandler = theMetaDoc.aMetaSlideSet[nCurSlide].aSlideAnimationsHandler;
+ if( aSlideAnimationsHandler )
+ {
+ var aCurrentEventMultiplexer = aSlideAnimationsHandler.aEventMultiplexer;
+ if( aCurrentEventMultiplexer )
+ {
+ if( aCurrentEventMultiplexer.hasRegisteredMouseClickHandlers() )
+ {
+ return aCurrentEventMultiplexer.notifyMouseClick( aEvt );
+ }
+ }
+ }
+ return slideOnMouseUp( aEvt );
+}
+
+
+/** Function to supply the default mouse handler dictionary.
+ *
+ * @returns Object default mouse handler dictionary
+ */
+function getDefaultMouseHandlerDictionary()
+{
+ var mouseHandlerDict = {};
+
+ mouseHandlerDict[SLIDE_MODE] = {};
+ mouseHandlerDict[INDEX_MODE] = {};
+
+ // slide mode
+ mouseHandlerDict[SLIDE_MODE][MOUSE_UP]
+ = mouseClickHelper;
+
+ mouseHandlerDict[SLIDE_MODE][MOUSE_WHEEL]
+ = function( aEvt ) { return slideOnMouseWheel( aEvt ); };
+
+ // index mode
+ mouseHandlerDict[INDEX_MODE][MOUSE_UP]
+ = function( ) { return toggleSlideIndex(); };
+
+ return mouseHandlerDict;
+}
+
+/** Function to set the page and active slide in index view.
+ *
+ * @param nIndex index of the active slide
+ *
+ * NOTE: To force a redraw,
+ * set INDEX_OFFSET to -1 before calling indexSetPageSlide().
+ *
+ * This is necessary for zooming (otherwise the index might not
+ * get redrawn) and when switching to index mode.
+ *
+ * INDEX_OFFSET = -1
+ * indexSetPageSlide(activeSlide);
+ */
+function indexSetPageSlide( nIndex )
+{
+ var aMetaSlideSet = theMetaDoc.aMetaSlideSet;
+ nIndex = getSafeIndex( nIndex, 0, aMetaSlideSet.length - 1 );
+
+ //calculate the offset
+ var nSelectedThumbnailIndex = nIndex % theSlideIndexPage.getTotalThumbnails();
+ var offset = nIndex - nSelectedThumbnailIndex;
+
+ if( offset < 0 )
+ offset = 0;
+
+ //if different from kept offset, then record and change the page
+ if( offset != INDEX_OFFSET )
+ {
+ INDEX_OFFSET = offset;
+ displayIndex( INDEX_OFFSET );
+ }
+
+ //set the selected thumbnail and the current slide
+ theSlideIndexPage.setSelection( nSelectedThumbnailIndex );
+}
+
+
+/*****
+ * @jessyinkend
+ *
+ * The above code is a derivative work of some parts of the JessyInk project.
+ * @source http://code.google.com/p/jessyink/
+ */
+
+
+
+
+
+/*****
+ * @licstart
+ *
+ * The following is the license notice for the part of JavaScript code of this
+ * page included between the '@dojostart' and the '@dojoend' notes.
+ */
+
+/***** **********************************************************************
+ *
+ * The 'New' BSD License:
+ * **********************
+ * Copyright (c) 2005-2012, The Dojo Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of the Dojo Foundation nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+
+/*****
+ * @licend
+ *
+ * The above is the license notice for the part of JavaScript code of this
+ * page included between the '@dojostart' and the '@dojoend' notes.
+ */
+
+
+
+/*****
+ * @dojostart
+ *
+ * The following code is a derivative work of some part of the dojox.gfx library.
+ * @source http://svn.dojotoolkit.org/src/dojox/trunk/_base/sniff.js
+ */
+
+function has( name )
+{
+ return has.cache[name];
+}
+
+has.cache = {};
+
+has.add = function( name, test )
+{
+ has.cache[name] = test;
+};
+
+function configureDetectionTools()
+{
+ if( !navigator )
+ {
+ log( 'error: configureDetectionTools: configuration failed' );
+ return null;
+ }
+
+ var n = navigator,
+ dua = n.userAgent,
+ dav = n.appVersion,
+ tv = parseFloat(dav);
+
+ has.add('air', dua.indexOf('AdobeAIR') >= 0);
+ has.add('khtml', dav.indexOf('Konqueror') >= 0 ? tv : undefined);
+ has.add('webkit', parseFloat(dua.split('WebKit/')[1]) || undefined);
+ has.add('chrome', parseFloat(dua.split('Chrome/')[1]) || undefined);
+ has.add('safari', dav.indexOf('Safari')>=0 && !has('chrome') ? parseFloat(dav.split('Version/')[1]) : undefined);
+ has.add('mac', dav.indexOf('Macintosh') >= 0);
+ has.add('quirks', document.compatMode == 'BackCompat');
+ has.add('ios', /iPhone|iPod|iPad/.test(dua));
+ has.add('android', parseFloat(dua.split('Android ')[1]) || undefined);
+
+ if(!has('webkit')){
+ // Opera
+ if(dua.indexOf('Opera') >= 0){
+ // see http://dev.opera.com/articles/view/opera-ua-string-changes and http://www.useragentstring.com/pages/Opera/
+ // 9.8 has both styles; <9.8, 9.9 only old style
+ has.add('opera', tv >= 9.8 ? parseFloat(dua.split('Version/')[1]) || tv : tv);
+ }
+
+ // Mozilla and firefox
+ if(dua.indexOf('Gecko') >= 0 && !has('khtml') && !has('webkit')){
+ has.add('mozilla', tv);
+ }
+ if(has('mozilla')){
+ //We really need to get away from this. Consider a sane isGecko approach for the future.
+ has.add('ff', parseFloat(dua.split('Firefox/')[1] || dua.split('Minefield/')[1]) || undefined);
+ }
+
+ // IE
+ if(document.all && !has('opera')){
+ var isIE = parseFloat(dav.split('MSIE ')[1]) || undefined;
+
+ //In cases where the page has an HTTP header or META tag with
+ //X-UA-Compatible, then it is in emulation mode.
+ //Make sure isIE reflects the desired version.
+ //document.documentMode of 5 means quirks mode.
+ //Only switch the value if documentMode's major version
+ //is different from isIE major version.
+ var mode = document.documentMode;
+ if(mode && mode != 5 && Math.floor(isIE) != mode){
+ isIE = mode;
+ }
+
+ has.add('ie', isIE);
+ }
+
+ // Wii
+ has.add('wii', typeof opera != 'undefined' && opera.wiiremote);
+ }
+
+ var detect =
+ {
+ // isFF: Number|undefined
+ // Version as a Number if client is FireFox. undefined otherwise. Corresponds to
+ // major detected FireFox version (1.5, 2, 3, etc.)
+ isFF: has('ff'),
+
+ // isIE: Number|undefined
+ // Version as a Number if client is MSIE(PC). undefined otherwise. Corresponds to
+ // major detected IE version (6, 7, 8, etc.)
+ isIE: has('ie'),
+
+ // isKhtml: Number|undefined
+ // Version as a Number if client is a KHTML browser. undefined otherwise. Corresponds to major
+ // detected version.
+ isKhtml: has('khtml'),
+
+ // isWebKit: Number|undefined
+ // Version as a Number if client is a WebKit-derived browser (Konqueror,
+ // Safari, Chrome, etc.). undefined otherwise.
+ isWebKit: has('webkit'),
+
+ // isMozilla: Number|undefined
+ // Version as a Number if client is a Mozilla-based browser (Firefox,
+ // SeaMonkey). undefined otherwise. Corresponds to major detected version.
+ isMozilla: has('mozilla'),
+ // isMoz: Number|undefined
+ // Version as a Number if client is a Mozilla-based browser (Firefox,
+ // SeaMonkey). undefined otherwise. Corresponds to major detected version.
+ isMoz: has('mozilla'),
+
+ // isOpera: Number|undefined
+ // Version as a Number if client is Opera. undefined otherwise. Corresponds to
+ // major detected version.
+ isOpera: has('opera'),
+
+ // isSafari: Number|undefined
+ // Version as a Number if client is Safari or iPhone. undefined otherwise.
+ isSafari: has('safari'),
+
+ // isChrome: Number|undefined
+ // Version as a Number if client is Chrome browser. undefined otherwise.
+ isChrome: has('chrome'),
+
+ // isMac: Boolean
+ // True if the client runs on Mac
+ isMac: has('mac'),
+
+ // isIos: Boolean
+ // True if client is iPhone, iPod, or iPad
+ isIos: has('ios'),
+
+ // isAndroid: Number|undefined
+ // Version as a Number if client is android browser. undefined otherwise.
+ isAndroid: has('android'),
+
+ // isWii: Boolean
+ // True if client is Wii
+ isWii: has('wii'),
+
+ // isQuirks: Boolean
+ // Page is in quirks mode.
+ isQuirks: has('quirks'),
+
+ // isAir: Boolean
+ // True if client is Adobe Air
+ isAir: has('air')
+ };
+ return detect;
+}
+
+/*****
+ * @dojoend
+ *
+ * The above code is a derivative work of some part of the dojox.gfx library.
+ * @source http://svn.dojotoolkit.org/src/dojox/trunk/_base/sniff.js
+ */
+
+/*****
+ * @licstart
+ *
+ * The following is the license notice for the part of JavaScript code of this
+ * file included between the '@svgpathstart' and the '@svgpathend' notes.
+ */
+
+/***** **********************************************************************
+ *
+ * Copyright 2015 The Chromium Authors. All rights reserved.
+ *
+ * The Chromium Authors can be found at
+ * http://src.chromium.org/svn/trunk/src/AUTHORS
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * 'AS IS' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/*****
+ * @licend
+ *
+ * The above is the license notice for the part of JavaScript code of this
+ * file included between the '@svgpathstart' and the '@svgpathend' notes.
+ */
+
+
+/*****
+ * @svgpathstart
+ *
+ * The following code is a derivative work of some part of the SVGPathSeg API.
+ *
+ * This API is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
+ * SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
+ * changes which were implemented in Firefox 43 and Chrome 46.
+ *
+ * @source https://github.com/progers/pathseg
+ */
+
+(function() { 'use strict';
+ if (!('SVGPathSeg' in window)) {
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSeg
+ window.SVGPathSeg = function(type, typeAsLetter, owningPathSegList) {
+ this.pathSegType = type;
+ this.pathSegTypeAsLetter = typeAsLetter;
+ this._owningPathSegList = owningPathSegList;
+ }
+
+ window.SVGPathSeg.prototype.classname = 'SVGPathSeg';
+
+ window.SVGPathSeg.PATHSEG_UNKNOWN = 0;
+ window.SVGPathSeg.PATHSEG_CLOSEPATH = 1;
+ window.SVGPathSeg.PATHSEG_MOVETO_ABS = 2;
+ window.SVGPathSeg.PATHSEG_MOVETO_REL = 3;
+ window.SVGPathSeg.PATHSEG_LINETO_ABS = 4;
+ window.SVGPathSeg.PATHSEG_LINETO_REL = 5;
+ window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS = 6;
+ window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL = 7;
+ window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS = 8;
+ window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL = 9;
+ window.SVGPathSeg.PATHSEG_ARC_ABS = 10;
+ window.SVGPathSeg.PATHSEG_ARC_REL = 11;
+ window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS = 12;
+ window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL = 13;
+ window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS = 14;
+ window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL = 15;
+ window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS = 16;
+ window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL = 17;
+ window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS = 18;
+ window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL = 19;
+
+ // Notify owning PathSegList on any changes so they can be synchronized back to the path element.
+ window.SVGPathSeg.prototype._segmentChanged = function() {
+ if (this._owningPathSegList)
+ this._owningPathSegList.segmentChanged(this);
+ }
+
+ window.SVGPathSegClosePath = function(owningPathSegList) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CLOSEPATH, 'z', owningPathSegList);
+ }
+ window.SVGPathSegClosePath.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegClosePath.prototype.toString = function() { return '[object SVGPathSegClosePath]'; }
+ window.SVGPathSegClosePath.prototype._asPathString = function() { return this.pathSegTypeAsLetter; }
+ window.SVGPathSegClosePath.prototype.clone = function() { return new window.SVGPathSegClosePath(undefined); }
+
+ window.SVGPathSegMovetoAbs = function(owningPathSegList, x, y) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_ABS, 'M', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ window.SVGPathSegMovetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegMovetoAbs.prototype.toString = function() { return '[object SVGPathSegMovetoAbs]'; }
+ window.SVGPathSegMovetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegMovetoAbs.prototype.clone = function() { return new window.SVGPathSegMovetoAbs(undefined, this._x, this._y); }
+ Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegMovetoAbs.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegMovetoRel = function(owningPathSegList, x, y) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_MOVETO_REL, 'm', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ window.SVGPathSegMovetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegMovetoRel.prototype.toString = function() { return '[object SVGPathSegMovetoRel]'; }
+ window.SVGPathSegMovetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegMovetoRel.prototype.clone = function() { return new window.SVGPathSegMovetoRel(undefined, this._x, this._y); }
+ Object.defineProperty(window.SVGPathSegMovetoRel.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegMovetoRel.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoAbs = function(owningPathSegList, x, y) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_ABS, 'L', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ window.SVGPathSegLinetoAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegLinetoAbs.prototype.toString = function() { return '[object SVGPathSegLinetoAbs]'; }
+ window.SVGPathSegLinetoAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegLinetoAbs.prototype.clone = function() { return new window.SVGPathSegLinetoAbs(undefined, this._x, this._y); }
+ Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegLinetoAbs.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoRel = function(owningPathSegList, x, y) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_REL, 'l', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ window.SVGPathSegLinetoRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegLinetoRel.prototype.toString = function() { return '[object SVGPathSegLinetoRel]'; }
+ window.SVGPathSegLinetoRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegLinetoRel.prototype.clone = function() { return new window.SVGPathSegLinetoRel(undefined, this._x, this._y); }
+ Object.defineProperty(window.SVGPathSegLinetoRel.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegLinetoRel.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoCubicAbs = function(owningPathSegList, x, y, x1, y1, x2, y2) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS, 'C', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x1 = x1;
+ this._y1 = y1;
+ this._x2 = x2;
+ this._y2 = y2;
+ }
+ window.SVGPathSegCurvetoCubicAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegCurvetoCubicAbs.prototype.toString = function() { return '[object SVGPathSegCurvetoCubicAbs]'; }
+ window.SVGPathSegCurvetoCubicAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegCurvetoCubicAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicAbs(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
+ Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x1', { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y1', { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'x2', { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicAbs.prototype, 'y2', { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoCubicRel = function(owningPathSegList, x, y, x1, y1, x2, y2) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL, 'c', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x1 = x1;
+ this._y1 = y1;
+ this._x2 = x2;
+ this._y2 = y2;
+ }
+ window.SVGPathSegCurvetoCubicRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegCurvetoCubicRel.prototype.toString = function() { return '[object SVGPathSegCurvetoCubicRel]'; }
+ window.SVGPathSegCurvetoCubicRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegCurvetoCubicRel.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicRel(undefined, this._x, this._y, this._x1, this._y1, this._x2, this._y2); }
+ Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x1', { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y1', { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'x2', { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicRel.prototype, 'y2', { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoQuadraticAbs = function(owningPathSegList, x, y, x1, y1) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS, 'Q', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x1 = x1;
+ this._y1 = y1;
+ }
+ window.SVGPathSegCurvetoQuadraticAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegCurvetoQuadraticAbs.prototype.toString = function() { return '[object SVGPathSegCurvetoQuadraticAbs]'; }
+ window.SVGPathSegCurvetoQuadraticAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegCurvetoQuadraticAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticAbs(undefined, this._x, this._y, this._x1, this._y1); }
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'x1', { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticAbs.prototype, 'y1', { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoQuadraticRel = function(owningPathSegList, x, y, x1, y1) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL, 'q', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x1 = x1;
+ this._y1 = y1;
+ }
+ window.SVGPathSegCurvetoQuadraticRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegCurvetoQuadraticRel.prototype.toString = function() { return '[object SVGPathSegCurvetoQuadraticRel]'; }
+ window.SVGPathSegCurvetoQuadraticRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x1 + ' ' + this._y1 + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegCurvetoQuadraticRel.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticRel(undefined, this._x, this._y, this._x1, this._y1); }
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'x1', { get: function() { return this._x1; }, set: function(x1) { this._x1 = x1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticRel.prototype, 'y1', { get: function() { return this._y1; }, set: function(y1) { this._y1 = y1; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegArcAbs = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_ABS, 'A', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._r1 = r1;
+ this._r2 = r2;
+ this._angle = angle;
+ this._largeArcFlag = largeArcFlag;
+ this._sweepFlag = sweepFlag;
+ }
+ window.SVGPathSegArcAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegArcAbs.prototype.toString = function() { return '[object SVGPathSegArcAbs]'; }
+ window.SVGPathSegArcAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegArcAbs.prototype.clone = function() { return new window.SVGPathSegArcAbs(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
+ Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'r1', { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'r2', { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'angle', { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'largeArcFlag', { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcAbs.prototype, 'sweepFlag', { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegArcRel = function(owningPathSegList, x, y, r1, r2, angle, largeArcFlag, sweepFlag) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_ARC_REL, 'a', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._r1 = r1;
+ this._r2 = r2;
+ this._angle = angle;
+ this._largeArcFlag = largeArcFlag;
+ this._sweepFlag = sweepFlag;
+ }
+ window.SVGPathSegArcRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegArcRel.prototype.toString = function() { return '[object SVGPathSegArcRel]'; }
+ window.SVGPathSegArcRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._r1 + ' ' + this._r2 + ' ' + this._angle + ' ' + (this._largeArcFlag ? '1' : '0') + ' ' + (this._sweepFlag ? '1' : '0') + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegArcRel.prototype.clone = function() { return new window.SVGPathSegArcRel(undefined, this._x, this._y, this._r1, this._r2, this._angle, this._largeArcFlag, this._sweepFlag); }
+ Object.defineProperty(window.SVGPathSegArcRel.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcRel.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcRel.prototype, 'r1', { get: function() { return this._r1; }, set: function(r1) { this._r1 = r1; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcRel.prototype, 'r2', { get: function() { return this._r2; }, set: function(r2) { this._r2 = r2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcRel.prototype, 'angle', { get: function() { return this._angle; }, set: function(angle) { this._angle = angle; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcRel.prototype, 'largeArcFlag', { get: function() { return this._largeArcFlag; }, set: function(largeArcFlag) { this._largeArcFlag = largeArcFlag; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegArcRel.prototype, 'sweepFlag', { get: function() { return this._sweepFlag; }, set: function(sweepFlag) { this._sweepFlag = sweepFlag; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoHorizontalAbs = function(owningPathSegList, x) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS, 'H', owningPathSegList);
+ this._x = x;
+ }
+ window.SVGPathSegLinetoHorizontalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegLinetoHorizontalAbs.prototype.toString = function() { return '[object SVGPathSegLinetoHorizontalAbs]'; }
+ window.SVGPathSegLinetoHorizontalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x; }
+ window.SVGPathSegLinetoHorizontalAbs.prototype.clone = function() { return new window.SVGPathSegLinetoHorizontalAbs(undefined, this._x); }
+ Object.defineProperty(window.SVGPathSegLinetoHorizontalAbs.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoHorizontalRel = function(owningPathSegList, x) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL, 'h', owningPathSegList);
+ this._x = x;
+ }
+ window.SVGPathSegLinetoHorizontalRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegLinetoHorizontalRel.prototype.toString = function() { return '[object SVGPathSegLinetoHorizontalRel]'; }
+ window.SVGPathSegLinetoHorizontalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x; }
+ window.SVGPathSegLinetoHorizontalRel.prototype.clone = function() { return new window.SVGPathSegLinetoHorizontalRel(undefined, this._x); }
+ Object.defineProperty(window.SVGPathSegLinetoHorizontalRel.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoVerticalAbs = function(owningPathSegList, y) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS, 'V', owningPathSegList);
+ this._y = y;
+ }
+ window.SVGPathSegLinetoVerticalAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegLinetoVerticalAbs.prototype.toString = function() { return '[object SVGPathSegLinetoVerticalAbs]'; }
+ window.SVGPathSegLinetoVerticalAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._y; }
+ window.SVGPathSegLinetoVerticalAbs.prototype.clone = function() { return new window.SVGPathSegLinetoVerticalAbs(undefined, this._y); }
+ Object.defineProperty(window.SVGPathSegLinetoVerticalAbs.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegLinetoVerticalRel = function(owningPathSegList, y) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL, 'v', owningPathSegList);
+ this._y = y;
+ }
+ window.SVGPathSegLinetoVerticalRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegLinetoVerticalRel.prototype.toString = function() { return '[object SVGPathSegLinetoVerticalRel]'; }
+ window.SVGPathSegLinetoVerticalRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._y; }
+ window.SVGPathSegLinetoVerticalRel.prototype.clone = function() { return new window.SVGPathSegLinetoVerticalRel(undefined, this._y); }
+ Object.defineProperty(window.SVGPathSegLinetoVerticalRel.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoCubicSmoothAbs = function(owningPathSegList, x, y, x2, y2) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS, 'S', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x2 = x2;
+ this._y2 = y2;
+ }
+ window.SVGPathSegCurvetoCubicSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegCurvetoCubicSmoothAbs.prototype.toString = function() { return '[object SVGPathSegCurvetoCubicSmoothAbs]'; }
+ window.SVGPathSegCurvetoCubicSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegCurvetoCubicSmoothAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, this._x, this._y, this._x2, this._y2); }
+ Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'x2', { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothAbs.prototype, 'y2', { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoCubicSmoothRel = function(owningPathSegList, x, y, x2, y2) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL, 's', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ this._x2 = x2;
+ this._y2 = y2;
+ }
+ window.SVGPathSegCurvetoCubicSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegCurvetoCubicSmoothRel.prototype.toString = function() { return '[object SVGPathSegCurvetoCubicSmoothRel]'; }
+ window.SVGPathSegCurvetoCubicSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x2 + ' ' + this._y2 + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegCurvetoCubicSmoothRel.prototype.clone = function() { return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, this._x, this._y, this._x2, this._y2); }
+ Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'x2', { get: function() { return this._x2; }, set: function(x2) { this._x2 = x2; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoCubicSmoothRel.prototype, 'y2', { get: function() { return this._y2; }, set: function(y2) { this._y2 = y2; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoQuadraticSmoothAbs = function(owningPathSegList, x, y) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS, 'T', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.toString = function() { return '[object SVGPathSegCurvetoQuadraticSmoothAbs]'; }
+ window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, this._x, this._y); }
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothAbs.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ window.SVGPathSegCurvetoQuadraticSmoothRel = function(owningPathSegList, x, y) {
+ window.SVGPathSeg.call(this, window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL, 't', owningPathSegList);
+ this._x = x;
+ this._y = y;
+ }
+ window.SVGPathSegCurvetoQuadraticSmoothRel.prototype = Object.create(window.SVGPathSeg.prototype);
+ window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.toString = function() { return '[object SVGPathSegCurvetoQuadraticSmoothRel]'; }
+ window.SVGPathSegCurvetoQuadraticSmoothRel.prototype._asPathString = function() { return this.pathSegTypeAsLetter + ' ' + this._x + ' ' + this._y; }
+ window.SVGPathSegCurvetoQuadraticSmoothRel.prototype.clone = function() { return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, this._x, this._y); }
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, 'x', { get: function() { return this._x; }, set: function(x) { this._x = x; this._segmentChanged(); }, enumerable: true });
+ Object.defineProperty(window.SVGPathSegCurvetoQuadraticSmoothRel.prototype, 'y', { get: function() { return this._y; }, set: function(y) { this._y = y; this._segmentChanged(); }, enumerable: true });
+
+ // Add createSVGPathSeg* functions to window.SVGPathElement.
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-Interfacewindow.SVGPathElement.
+ window.SVGPathElement.prototype.createSVGPathSegClosePath = function() { return new window.SVGPathSegClosePath(undefined); }
+ window.SVGPathElement.prototype.createSVGPathSegMovetoAbs = function(x, y) { return new window.SVGPathSegMovetoAbs(undefined, x, y); }
+ window.SVGPathElement.prototype.createSVGPathSegMovetoRel = function(x, y) { return new window.SVGPathSegMovetoRel(undefined, x, y); }
+ window.SVGPathElement.prototype.createSVGPathSegLinetoAbs = function(x, y) { return new window.SVGPathSegLinetoAbs(undefined, x, y); }
+ window.SVGPathElement.prototype.createSVGPathSegLinetoRel = function(x, y) { return new window.SVGPathSegLinetoRel(undefined, x, y); }
+ window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicAbs = function(x, y, x1, y1, x2, y2) { return new window.SVGPathSegCurvetoCubicAbs(undefined, x, y, x1, y1, x2, y2); }
+ window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicRel = function(x, y, x1, y1, x2, y2) { return new window.SVGPathSegCurvetoCubicRel(undefined, x, y, x1, y1, x2, y2); }
+ window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticAbs = function(x, y, x1, y1) { return new window.SVGPathSegCurvetoQuadraticAbs(undefined, x, y, x1, y1); }
+ window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticRel = function(x, y, x1, y1) { return new window.SVGPathSegCurvetoQuadraticRel(undefined, x, y, x1, y1); }
+ window.SVGPathElement.prototype.createSVGPathSegArcAbs = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new window.SVGPathSegArcAbs(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
+ window.SVGPathElement.prototype.createSVGPathSegArcRel = function(x, y, r1, r2, angle, largeArcFlag, sweepFlag) { return new window.SVGPathSegArcRel(undefined, x, y, r1, r2, angle, largeArcFlag, sweepFlag); }
+ window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalAbs = function(x) { return new window.SVGPathSegLinetoHorizontalAbs(undefined, x); }
+ window.SVGPathElement.prototype.createSVGPathSegLinetoHorizontalRel = function(x) { return new window.SVGPathSegLinetoHorizontalRel(undefined, x); }
+ window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalAbs = function(y) { return new window.SVGPathSegLinetoVerticalAbs(undefined, y); }
+ window.SVGPathElement.prototype.createSVGPathSegLinetoVerticalRel = function(y) { return new window.SVGPathSegLinetoVerticalRel(undefined, y); }
+ window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothAbs = function(x, y, x2, y2) { return new window.SVGPathSegCurvetoCubicSmoothAbs(undefined, x, y, x2, y2); }
+ window.SVGPathElement.prototype.createSVGPathSegCurvetoCubicSmoothRel = function(x, y, x2, y2) { return new window.SVGPathSegCurvetoCubicSmoothRel(undefined, x, y, x2, y2); }
+ window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothAbs = function(x, y) { return new window.SVGPathSegCurvetoQuadraticSmoothAbs(undefined, x, y); }
+ window.SVGPathElement.prototype.createSVGPathSegCurvetoQuadraticSmoothRel = function(x, y) { return new window.SVGPathSegCurvetoQuadraticSmoothRel(undefined, x, y); }
+
+ if (!('getPathSegAtLength' in window.SVGPathElement.prototype)) {
+ // Add getPathSegAtLength to SVGPathElement.
+ // Spec: https://www.w3.org/TR/SVG11/single-page.html#paths-__svg__SVGPathElement__getPathSegAtLength
+ // This polyfill requires SVGPathElement.getTotalLength to implement the distance-along-a-path algorithm.
+ window.SVGPathElement.prototype.getPathSegAtLength = function(distance) {
+ if (distance === undefined || !isFinite(distance))
+ throw 'Invalid arguments.';
+
+ var measurementElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
+ measurementElement.setAttribute('d', this.getAttribute('d'));
+ var lastPathSegment = measurementElement.pathSegList.numberOfItems - 1;
+
+ // If the path is empty, return 0.
+ if (lastPathSegment <= 0)
+ return 0;
+
+ do {
+ measurementElement.pathSegList.removeItem(lastPathSegment);
+ if (distance > measurementElement.getTotalLength())
+ break;
+ lastPathSegment--;
+ } while (lastPathSegment > 0);
+ return lastPathSegment;
+ }
+ }
+ }
+
+ // Checking for SVGPathSegList in window checks for the case of an implementation without the
+ // SVGPathSegList API.
+ // The second check for appendItem is specific to Firefox 59+ which removed only parts of the
+ // SVGPathSegList API (e.g., appendItem). In this case we need to re-implement the entire API
+ // so the polyfill data (i.e., _list) is used throughout.
+ if (!('SVGPathSegList' in window) || !('appendItem' in window.SVGPathSegList.prototype)) {
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGPathSegList
+ window.SVGPathSegList = function(pathElement) {
+ this._pathElement = pathElement;
+ this._list = this._parsePath(this._pathElement.getAttribute('d'));
+
+ // Use a MutationObserver to catch changes to the path's 'd' attribute.
+ this._mutationObserverConfig = { 'attributes': true, 'attributeFilter': ['d'] };
+ this._pathElementMutationObserver = new MutationObserver(this._updateListFromPathMutations.bind(this));
+ this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
+ }
+
+ window.SVGPathSegList.prototype.classname = 'SVGPathSegList';
+
+ Object.defineProperty(window.SVGPathSegList.prototype, 'numberOfItems', {
+ get: function() {
+ this._checkPathSynchronizedToList();
+ return this._list.length;
+ },
+ enumerable: true
+ });
+
+ // The length property was not specified but was in Firefox 58.
+ Object.defineProperty(window.SVGPathSegList.prototype, 'length', {
+ get: function() {
+ this._checkPathSynchronizedToList();
+ return this._list.length;
+ },
+ enumerable: true
+ });
+
+ // Add the pathSegList accessors to window.SVGPathElement.
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-InterfaceSVGAnimatedPathData
+ Object.defineProperty(window.SVGPathElement.prototype, 'pathSegList', {
+ get: function() {
+ if (!this._pathSegList)
+ this._pathSegList = new window.SVGPathSegList(this);
+ return this._pathSegList;
+ },
+ enumerable: true
+ });
+ // FIXME: The following are not implemented and simply return window.SVGPathElement.pathSegList.
+ Object.defineProperty(window.SVGPathElement.prototype, 'normalizedPathSegList', { get: function() { return this.pathSegList; }, enumerable: true });
+ Object.defineProperty(window.SVGPathElement.prototype, 'animatedPathSegList', { get: function() { return this.pathSegList; }, enumerable: true });
+ Object.defineProperty(window.SVGPathElement.prototype, 'animatedNormalizedPathSegList', { get: function() { return this.pathSegList; }, enumerable: true });
+
+ // Process any pending mutations to the path element and update the list as needed.
+ // This should be the first call of all public functions and is needed because
+ // MutationObservers are not synchronous so we can have pending asynchronous mutations.
+ window.SVGPathSegList.prototype._checkPathSynchronizedToList = function() {
+ this._updateListFromPathMutations(this._pathElementMutationObserver.takeRecords());
+ }
+
+ window.SVGPathSegList.prototype._updateListFromPathMutations = function(mutationRecords) {
+ if (!this._pathElement)
+ return;
+ var hasPathMutations = false;
+ mutationRecords.forEach(function(record) {
+ if (record.attributeName == 'd')
+ hasPathMutations = true;
+ });
+ if (hasPathMutations)
+ this._list = this._parsePath(this._pathElement.getAttribute('d'));
+ }
+
+ // Serialize the list and update the path's 'd' attribute.
+ window.SVGPathSegList.prototype._writeListToPath = function() {
+ this._pathElementMutationObserver.disconnect();
+ this._pathElement.setAttribute('d', window.SVGPathSegList._pathSegArrayAsString(this._list));
+ this._pathElementMutationObserver.observe(this._pathElement, this._mutationObserverConfig);
+ }
+
+ // When a path segment changes the list needs to be synchronized back to the path element.
+ window.SVGPathSegList.prototype.segmentChanged = function(pathSeg) {
+ this._writeListToPath();
+ }
+
+ window.SVGPathSegList.prototype.clear = function() {
+ this._checkPathSynchronizedToList();
+
+ this._list.forEach(function(pathSeg) {
+ pathSeg._owningPathSegList = null;
+ });
+ this._list = [];
+ this._writeListToPath();
+ }
+
+ window.SVGPathSegList.prototype.initialize = function(newItem) {
+ this._checkPathSynchronizedToList();
+
+ this._list = [newItem];
+ newItem._owningPathSegList = this;
+ this._writeListToPath();
+ return newItem;
+ }
+
+ window.SVGPathSegList.prototype._checkValidIndex = function(index) {
+ if (isNaN(index) || index < 0 || index >= this.numberOfItems)
+ throw 'INDEX_SIZE_ERR';
+ }
+
+ window.SVGPathSegList.prototype.getItem = function(index) {
+ this._checkPathSynchronizedToList();
+
+ this._checkValidIndex(index);
+ return this._list[index];
+ }
+
+ window.SVGPathSegList.prototype.insertItemBefore = function(newItem, index) {
+ this._checkPathSynchronizedToList();
+
+ // Spec: If the index is greater than or equal to numberOfItems, then the new item is appended to the end of the list.
+ if (index > this.numberOfItems)
+ index = this.numberOfItems;
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+ this._list.splice(index, 0, newItem);
+ newItem._owningPathSegList = this;
+ this._writeListToPath();
+ return newItem;
+ }
+
+ window.SVGPathSegList.prototype.replaceItem = function(newItem, index) {
+ this._checkPathSynchronizedToList();
+
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+ this._checkValidIndex(index);
+ this._list[index] = newItem;
+ newItem._owningPathSegList = this;
+ this._writeListToPath();
+ return newItem;
+ }
+
+ window.SVGPathSegList.prototype.removeItem = function(index) {
+ this._checkPathSynchronizedToList();
+
+ this._checkValidIndex(index);
+ var item = this._list[index];
+ this._list.splice(index, 1);
+ this._writeListToPath();
+ return item;
+ }
+
+ window.SVGPathSegList.prototype.appendItem = function(newItem) {
+ this._checkPathSynchronizedToList();
+
+ if (newItem._owningPathSegList) {
+ // SVG2 spec says to make a copy.
+ newItem = newItem.clone();
+ }
+ this._list.push(newItem);
+ newItem._owningPathSegList = this;
+ // TODO: Optimize this to just append to the existing attribute.
+ this._writeListToPath();
+ return newItem;
+ };
+
+ window.SVGPathSegList.prototype.matrixTransform = function(aSVGMatrix) {
+ this._checkPathSynchronizedToList();
+
+ var nLength = this._list.length;
+ for( var i = 0; i < nLength; ++i )
+ {
+ var nX;
+ var aPathSeg = this._list[i];
+ switch( aPathSeg.pathSegTypeAsLetter )
+ {
+ case 'C':
+ nX = aPathSeg._x2;
+ aPathSeg._x2 = aSVGMatrix.a * nX + aSVGMatrix.c * aPathSeg._y2 + aSVGMatrix.e;
+ aPathSeg._y2 = aSVGMatrix.b * nX + aSVGMatrix.d * aPathSeg._y2 + aSVGMatrix.f;
+ // fall through intended
+ case 'Q':
+ nX = aPathSeg._x1;
+ aPathSeg._x1 = aSVGMatrix.a * nX + aSVGMatrix.c * aPathSeg._y1 + aSVGMatrix.e;
+ aPathSeg._y1 = aSVGMatrix.b * nX + aSVGMatrix.d * aPathSeg._y1 + aSVGMatrix.f;
+ // fall through intended
+ case 'M':
+ case 'L':
+ nX = aPathSeg._x;
+ aPathSeg._x = aSVGMatrix.a * nX + aSVGMatrix.c * aPathSeg._y + aSVGMatrix.e;
+ aPathSeg._y = aSVGMatrix.b * nX + aSVGMatrix.d * aPathSeg._y + aSVGMatrix.f;
+ break;
+ default:
+ log( 'SVGPathSeg.matrixTransform: unexpected path segment type: '
+ + aPathSeg.pathSegTypeAsLetter );
+ }
+ }
+
+ this._writeListToPath();
+ };
+
+ window.SVGPathSegList.prototype.changeOrientation = function() {
+ this._checkPathSynchronizedToList();
+
+ var aPathSegList = this._list;
+ var nLength = aPathSegList.length;
+ if( nLength == 0 ) return;
+
+ var nCurrentX = 0;
+ var nCurrentY = 0;
+
+ var aPathSeg = aPathSegList[0];
+ if( aPathSeg.pathSegTypeAsLetter == 'M' )
+ {
+ nCurrentX = aPathSeg.x;
+ nCurrentY = aPathSeg.y;
+ aPathSegList.shift();
+ --nLength;
+ }
+
+ var i;
+ for( i = 0; i < nLength; ++i )
+ {
+ aPathSeg = aPathSegList[i];
+ switch( aPathSeg.pathSegTypeAsLetter )
+ {
+ case 'C':
+ var nX = aPathSeg._x1;
+ aPathSeg._x1 = aPathSeg._x2;
+ aPathSeg._x2 = nX;
+ var nY = aPathSeg._y1;
+ aPathSeg._y1 = aPathSeg._y2;
+ aPathSeg._y2 = nY;
+ // fall through intended
+ case 'M':
+ case 'L':
+ case 'Q':
+ var aPoint = { x: aPathSeg._x, y: aPathSeg._y };
+ aPathSeg._x = nCurrentX;
+ aPathSeg._y = nCurrentY;
+ nCurrentX = aPoint.x;
+ nCurrentY = aPoint.y;
+ break;
+ default:
+ log( 'SVGPathSegList.changeOrientation: unexpected path segment type: '
+ + aPathSeg.pathSegTypeAsLetter );
+ }
+
+ }
+
+ aPathSegList.reverse();
+
+ var aMovePathSeg = new window.SVGPathSegMovetoAbs( this, nCurrentX, nCurrentY );
+ aPathSegList.unshift( aMovePathSeg );
+
+ this._writeListToPath();
+ };
+
+ window.SVGPathSegList._pathSegArrayAsString = function(pathSegArray) {
+ var string = '';
+ var first = true;
+ pathSegArray.forEach(function(pathSeg) {
+ if (first) {
+ first = false;
+ string += pathSeg._asPathString();
+ } else {
+ string += ' ' + pathSeg._asPathString();
+ }
+ });
+ return string;
+ }
+
+ // This closely follows SVGPathParser::parsePath from Source/core/svg/SVGPathParser.cpp.
+ window.SVGPathSegList.prototype._parsePath = function(string) {
+ if (!string || string.length == 0)
+ return [];
+
+ var owningPathSegList = this;
+
+ var Builder = function() {
+ this.pathSegList = [];
+ }
+
+ Builder.prototype.appendSegment = function(pathSeg) {
+ this.pathSegList.push(pathSeg);
+ }
+
+ var Source = function(string) {
+ this._string = string;
+ this._currentIndex = 0;
+ this._endIndex = this._string.length;
+ this._previousCommand = window.SVGPathSeg.PATHSEG_UNKNOWN;
+
+ this._skipOptionalSpaces();
+ }
+
+ Source.prototype._isCurrentSpace = function() {
+ var character = this._string[this._currentIndex];
+ return character <= ' ' && (character == ' ' || character == '\n' || character == '\t' || character == '\r' || character == '\f');
+ }
+
+ Source.prototype._skipOptionalSpaces = function() {
+ while (this._currentIndex < this._endIndex && this._isCurrentSpace())
+ this._currentIndex++;
+ return this._currentIndex < this._endIndex;
+ }
+
+ Source.prototype._skipOptionalSpacesOrDelimiter = function() {
+ if (this._currentIndex < this._endIndex && !this._isCurrentSpace() && this._string.charAt(this._currentIndex) != ',')
+ return false;
+ if (this._skipOptionalSpaces()) {
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == ',') {
+ this._currentIndex++;
+ this._skipOptionalSpaces();
+ }
+ }
+ return this._currentIndex < this._endIndex;
+ }
+
+ Source.prototype.hasMoreData = function() {
+ return this._currentIndex < this._endIndex;
+ }
+
+ Source.prototype.peekSegmentType = function() {
+ var lookahead = this._string[this._currentIndex];
+ return this._pathSegTypeFromChar(lookahead);
+ }
+
+ Source.prototype._pathSegTypeFromChar = function(lookahead) {
+ switch (lookahead) {
+ case 'Z':
+ case 'z':
+ return window.SVGPathSeg.PATHSEG_CLOSEPATH;
+ case 'M':
+ return window.SVGPathSeg.PATHSEG_MOVETO_ABS;
+ case 'm':
+ return window.SVGPathSeg.PATHSEG_MOVETO_REL;
+ case 'L':
+ return window.SVGPathSeg.PATHSEG_LINETO_ABS;
+ case 'l':
+ return window.SVGPathSeg.PATHSEG_LINETO_REL;
+ case 'C':
+ return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS;
+ case 'c':
+ return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL;
+ case 'Q':
+ return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS;
+ case 'q':
+ return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL;
+ case 'A':
+ return window.SVGPathSeg.PATHSEG_ARC_ABS;
+ case 'a':
+ return window.SVGPathSeg.PATHSEG_ARC_REL;
+ case 'H':
+ return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS;
+ case 'h':
+ return window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL;
+ case 'V':
+ return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS;
+ case 'v':
+ return window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL;
+ case 'S':
+ return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS;
+ case 's':
+ return window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL;
+ case 'T':
+ return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS;
+ case 't':
+ return window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL;
+ default:
+ return window.SVGPathSeg.PATHSEG_UNKNOWN;
+ }
+ }
+
+ Source.prototype._nextCommandHelper = function(lookahead, previousCommand) {
+ // Check for remaining coordinates in the current command.
+ if ((lookahead == '+' || lookahead == '-' || lookahead == '.' || (lookahead >= '0' && lookahead <= '9')) && previousCommand != window.SVGPathSeg.PATHSEG_CLOSEPATH) {
+ if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_ABS)
+ return window.SVGPathSeg.PATHSEG_LINETO_ABS;
+ if (previousCommand == window.SVGPathSeg.PATHSEG_MOVETO_REL)
+ return window.SVGPathSeg.PATHSEG_LINETO_REL;
+ return previousCommand;
+ }
+ return window.SVGPathSeg.PATHSEG_UNKNOWN;
+ }
+
+ Source.prototype.initialCommandIsMoveTo = function() {
+ // If the path is empty it is still valid, so return true.
+ if (!this.hasMoreData())
+ return true;
+ var command = this.peekSegmentType();
+ // Path must start with moveTo.
+ return command == window.SVGPathSeg.PATHSEG_MOVETO_ABS || command == window.SVGPathSeg.PATHSEG_MOVETO_REL;
+ }
+
+ // Parse a number from an SVG path. This very closely follows genericParseNumber(...) from Source/core/svg/SVGParserUtilities.cpp.
+ // Spec: http://www.w3.org/TR/SVG11/single-page.html#paths-PathDataBNF
+ Source.prototype._parseNumber = function() {
+ var exponent = 0;
+ var integer = 0;
+ var frac = 1;
+ var decimal = 0;
+ var sign = 1;
+ var expsign = 1;
+
+ var startIndex = this._currentIndex;
+
+ this._skipOptionalSpaces();
+
+ // Read the sign.
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == '+')
+ this._currentIndex++;
+ else if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == '-') {
+ this._currentIndex++;
+ sign = -1;
+ }
+
+ if (this._currentIndex == this._endIndex || ((this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9') && this._string.charAt(this._currentIndex) != '.'))
+ // The first character of a number must be one of [0-9+-.].
+ return undefined;
+
+ // Read the integer part, build right-to-left.
+ var startIntPartIndex = this._currentIndex;
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9')
+ this._currentIndex++; // Advance to first non-digit.
+
+ if (this._currentIndex != startIntPartIndex) {
+ var scanIntPartIndex = this._currentIndex - 1;
+ var multiplier = 1;
+ while (scanIntPartIndex >= startIntPartIndex) {
+ integer += multiplier * (this._string.charAt(scanIntPartIndex--) - '0');
+ multiplier *= 10;
+ }
+ }
+
+ // Read the decimals.
+ if (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) == '.') {
+ this._currentIndex++;
+
+ // There must be a least one digit following the .
+ if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9')
+ return undefined;
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {
+ frac *= 10;
+ decimal += (this._string.charAt(this._currentIndex) - '0') / frac;
+ this._currentIndex += 1;
+ }
+ }
+
+ // Read the exponent part.
+ if (this._currentIndex != startIndex && this._currentIndex + 1 < this._endIndex && (this._string.charAt(this._currentIndex) == 'e' || this._string.charAt(this._currentIndex) == 'E') && (this._string.charAt(this._currentIndex + 1) != 'x' && this._string.charAt(this._currentIndex + 1) != 'm')) {
+ this._currentIndex++;
+
+ // Read the sign of the exponent.
+ if (this._string.charAt(this._currentIndex) == '+') {
+ this._currentIndex++;
+ } else if (this._string.charAt(this._currentIndex) == '-') {
+ this._currentIndex++;
+ expsign = -1;
+ }
+
+ // There must be an exponent.
+ if (this._currentIndex >= this._endIndex || this._string.charAt(this._currentIndex) < '0' || this._string.charAt(this._currentIndex) > '9')
+ return undefined;
+
+ while (this._currentIndex < this._endIndex && this._string.charAt(this._currentIndex) >= '0' && this._string.charAt(this._currentIndex) <= '9') {
+ exponent *= 10;
+ exponent += (this._string.charAt(this._currentIndex) - '0');
+ this._currentIndex++;
+ }
+ }
+
+ var number = integer + decimal;
+ number *= sign;
+
+ if (exponent)
+ number *= Math.pow(10, expsign * exponent);
+
+ if (startIndex == this._currentIndex)
+ return undefined;
+
+ this._skipOptionalSpacesOrDelimiter();
+
+ return number;
+ }
+
+ Source.prototype._parseArcFlag = function() {
+ if (this._currentIndex >= this._endIndex)
+ return undefined;
+ var flag = false;
+ var flagChar = this._string.charAt(this._currentIndex++);
+ if (flagChar == '0')
+ flag = false;
+ else if (flagChar == '1')
+ flag = true;
+ else
+ return undefined;
+
+ this._skipOptionalSpacesOrDelimiter();
+ return flag;
+ }
+
+ Source.prototype.parseSegment = function() {
+ var lookahead = this._string[this._currentIndex];
+ var command = this._pathSegTypeFromChar(lookahead);
+ if (command == window.SVGPathSeg.PATHSEG_UNKNOWN) {
+ // Possibly an implicit command. Not allowed if this is the first command.
+ if (this._previousCommand == window.SVGPathSeg.PATHSEG_UNKNOWN)
+ return null;
+ command = this._nextCommandHelper(lookahead, this._previousCommand);
+ if (command == window.SVGPathSeg.PATHSEG_UNKNOWN)
+ return null;
+ } else {
+ this._currentIndex++;
+ }
+
+ this._previousCommand = command;
+
+ switch (command) {
+ case window.SVGPathSeg.PATHSEG_MOVETO_REL:
+ return new window.SVGPathSegMovetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_MOVETO_ABS:
+ return new window.SVGPathSegMovetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_LINETO_REL:
+ return new window.SVGPathSegLinetoRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_LINETO_ABS:
+ return new window.SVGPathSegLinetoAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_REL:
+ return new window.SVGPathSegLinetoHorizontalRel(owningPathSegList, this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_LINETO_HORIZONTAL_ABS:
+ return new window.SVGPathSegLinetoHorizontalAbs(owningPathSegList, this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_REL:
+ return new window.SVGPathSegLinetoVerticalRel(owningPathSegList, this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_LINETO_VERTICAL_ABS:
+ return new window.SVGPathSegLinetoVerticalAbs(owningPathSegList, this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_CLOSEPATH:
+ this._skipOptionalSpaces();
+ return new window.SVGPathSegClosePath(owningPathSegList);
+ case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_REL:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new window.SVGPathSegCurvetoCubicRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+ case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_ABS:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new window.SVGPathSegCurvetoCubicAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.x2, points.y2);
+ case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
+ var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new window.SVGPathSegCurvetoCubicSmoothRel(owningPathSegList, points.x, points.y, points.x2, points.y2);
+ case window.SVGPathSeg.PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
+ var points = {x2: this._parseNumber(), y2: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new window.SVGPathSegCurvetoCubicSmoothAbs(owningPathSegList, points.x, points.y, points.x2, points.y2);
+ case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_REL:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new window.SVGPathSegCurvetoQuadraticRel(owningPathSegList, points.x, points.y, points.x1, points.y1);
+ case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_ABS:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), x: this._parseNumber(), y: this._parseNumber()};
+ return new window.SVGPathSegCurvetoQuadraticAbs(owningPathSegList, points.x, points.y, points.x1, points.y1);
+ case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
+ return new window.SVGPathSegCurvetoQuadraticSmoothRel(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
+ return new window.SVGPathSegCurvetoQuadraticSmoothAbs(owningPathSegList, this._parseNumber(), this._parseNumber());
+ case window.SVGPathSeg.PATHSEG_ARC_REL:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
+ return new window.SVGPathSegArcRel(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
+ case window.SVGPathSeg.PATHSEG_ARC_ABS:
+ var points = {x1: this._parseNumber(), y1: this._parseNumber(), arcAngle: this._parseNumber(), arcLarge: this._parseArcFlag(), arcSweep: this._parseArcFlag(), x: this._parseNumber(), y: this._parseNumber()};
+ return new window.SVGPathSegArcAbs(owningPathSegList, points.x, points.y, points.x1, points.y1, points.arcAngle, points.arcLarge, points.arcSweep);
+ default:
+ throw 'Unknown path seg type.'
+ }
+ }
+
+ var builder = new Builder();
+ var source = new Source(string);
+
+ if (!source.initialCommandIsMoveTo())
+ return [];
+ while (source.hasMoreData()) {
+ var pathSeg = source.parseSegment();
+ if (!pathSeg)
+ return [];
+ builder.appendSegment(pathSeg);
+ }
+
+ return builder.pathSegList;
+ }
+ }
+}());
+
+/*****
+ * @svgpathend
+ *
+ * The above code is a derivative work of some part of the SVGPathSeg API.
+ *
+ * This API is a drop-in replacement for the SVGPathSeg and SVGPathSegList APIs that were removed from
+ * SVG2 (https://lists.w3.org/Archives/Public/www-svg/2015Jun/0044.html), including the latest spec
+ * changes which were implemented in Firefox 43 and Chrome 46.
+ *
+ * @source https://github.com/progers/pathseg
+ */
+
+
+/*****
+ * @licstart
+ *
+ * The following is the license notice for the part of JavaScript code of
+ * this page included between the '@libreofficestart' and the '@libreofficeend'
+ * notes.
+ */
+
+/***** ******************************************************************
+ *
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the 'License'); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ *
+ ************************************************************************/
+
+/*****
+ * @licend
+ *
+ * The above is the license notice for the part of JavaScript code of
+ * this page included between the '@libreofficestart' and the '@libreofficeend'
+ * notes.
+ */
+
+
+/*****
+ * @libreofficestart
+ *
+ * Several parts of the following code are the result of the porting,
+ * started on August 2011, of the C++ code included in the source
+ * files placed under the folder '/slideshow/source' and
+ * sub-folders. This got later rebased onto the AL2-licensed versions
+ * of those files in early 2013.
+ * @source https://cgit.freedesktop.org/libreoffice/core/tree/slideshow/source
+ *
+ */
+
+
+window.onload = init;
+
+
+// ooo elements
+var aOOOElemMetaSlides = 'ooo:meta_slides';
+var aOOOElemMetaSlide = 'ooo:meta_slide';
+var aOOOElemTextField = 'ooo:text_field';
+var aPresentationClipPathId = 'presentation_clip_path';
+var aPresentationClipPathShrinkId = 'presentation_clip_path_shrink';
+
+// ooo attributes
+var aOOOAttrNumberOfSlides = 'number-of-slides';
+var aOOOAttrStartSlideNumber= 'start-slide-number';
+var aOOOAttrNumberingType = 'page-numbering-type';
+var aOOOAttrListItemNumberingType= 'numbering-type';
+var aOOOAttrUsePositionedChars = 'use-positioned-chars';
+
+var aOOOAttrSlide = 'slide';
+var aOOOAttrMaster = 'master';
+var aOOOAttrDisplayName = 'display-name';
+var aOOOAttrSlideDuration = 'slide-duration';
+var aOOOAttrHasTransition = 'has-transition';
+var aOOOAttrHasCustomBackground = 'has-custom-background';
+var aOOOAttrBackgroundVisibility = 'background-visibility';
+var aOOOAttrMasterObjectsVisibility = 'master-objects-visibility';
+var aOOOAttrPageNumberVisibility = 'page-number-visibility';
+var aOOOAttrDateTimeVisibility = 'date-time-visibility';
+var aOOOAttrFooterVisibility = 'footer-visibility';
+var aOOOAttrHeaderVisibility = 'header-visibility';
+var aOOOAttrDateTimeField = 'date-time-field';
+var aOOOAttrFooterField = 'footer-field';
+var aOOOAttrHeaderField = 'header-field';
+
+var aOOOAttrDateTimeFormat = 'date-time-format';
+
+var aOOOAttrTextAdjust = 'text-adjust';
+
+// element class names
+var aClipPathGroupClassName = 'ClipPathGroup';
+var aPageClassName = 'Page';
+var aSlideNumberClassName = 'Slide_Number';
+var aDateTimeClassName = 'Date/Time';
+var aFooterClassName = 'Footer';
+var aHeaderClassName = 'Header';
+var aDateClassName = 'Date';
+var aTimeClassName = 'Time';
+var aSlideNameClassName='SlideName';
+
+// Creating a namespace dictionary.
+var NSS = {};
+NSS['svg']='http://www.w3.org/2000/svg';
+NSS['rdf']='http://www.w3.org/1999/02/22-rdf-syntax-ns#';
+NSS['xlink']='http://www.w3.org/1999/xlink';
+NSS['xml']='http://www.w3.org/XML/1998/namespace';
+NSS['ooo'] = 'http://xml.openoffice.org/svg/export';
+NSS['presentation'] = 'http://sun.com/xmlns/staroffice/presentation';
+NSS['smil'] = 'http://www.w3.org/2001/SMIL20/';
+NSS['anim'] = 'urn:oasis:names:tc:opendocument:xmlns:animation:1.0';
+
+// Presentation modes.
+var SLIDE_MODE = 1;
+var INDEX_MODE = 2;
+
+// Mouse handler actions.
+var MOUSE_UP = 1;
+var MOUSE_DOWN = 2; // eslint-disable-line no-unused-vars
+var MOUSE_MOVE = 3; // eslint-disable-line no-unused-vars
+var MOUSE_WHEEL = 4;
+
+// Key-codes.
+var LEFT_KEY = 37; // cursor left keycode
+var UP_KEY = 38; // cursor up keycode
+var RIGHT_KEY = 39; // cursor right keycode
+var DOWN_KEY = 40; // cursor down keycode
+var PAGE_UP_KEY = 33; // page up keycode
+var PAGE_DOWN_KEY = 34; // page down keycode
+var HOME_KEY = 36; // home keycode
+var END_KEY = 35; // end keycode
+var ENTER_KEY = 13;
+var SPACE_KEY = 32;
+var ESCAPE_KEY = 27;
+var Q_KEY = 81;
+
+// Visibility Values
+var HIDDEN = 0;
+var VISIBLE = 1;
+var INHERIT = 2;
+var aVisibilityAttributeValue = [ 'hidden', 'visible', 'inherit' ]; // eslint-disable-line no-unused-vars
+var aVisibilityValue = { 'hidden' : HIDDEN, 'visible' : VISIBLE, 'inherit' : INHERIT };
+
+// Parameters
+var ROOT_NODE = document.getElementsByTagNameNS( NSS['svg'], 'svg' )[0];
+var WIDTH = 0;
+var HEIGHT = 0;
+var INDEX_COLUMNS_DEFAULT = 3;
+var INDEX_OFFSET = 0;
+
+// Initialization.
+var Detect = configureDetectionTools();
+var theMetaDoc;
+var theSlideIndexPage;
+var currentMode = SLIDE_MODE;
+var processingEffect = false;
+var nCurSlide = undefined;
+var bTextHasBeenSelected = false;
+var sLastSelectedText = '';
+
+
+// Initialize char and key code dictionaries.
+var charCodeDictionary = getDefaultCharCodeDictionary();
+var keyCodeDictionary = getDefaultKeyCodeDictionary();
+
+// Initialize mouse handler dictionary.
+var mouseHandlerDictionary = getDefaultMouseHandlerDictionary();
+
+/***************************
+ ** OOP support functions **
+ ***************************/
+
+function object( aObject )
+{
+ var F = function() {};
+ F.prototype = aObject;
+ return new F();
+}
+
+
+function extend( aSubType, aSuperType )
+{
+ if (!aSuperType || !aSubType)
+ {
+ alert('extend failed, verify dependencies');
+ }
+ var OP = Object.prototype;
+ var sp = aSuperType.prototype;
+ var rp = object( sp );
+ aSubType.prototype = rp;
+
+ rp.constructor = aSubType;
+ aSubType.superclass = sp;
+
+ // assign constructor property
+ if (aSuperType != Object && sp.constructor == OP.constructor)
+ {
+ sp.constructor = aSuperType;
+ }
+
+ return aSubType;
+}
+
+
+function instantiate( TemplateClass, BaseType )
+{
+ if( !TemplateClass.instanceSet )
+ TemplateClass.instanceSet = [];
+
+ var nSize = TemplateClass.instanceSet.length;
+
+ for( var i = 0; i < nSize; ++i )
+ {
+ if( TemplateClass.instanceSet[i].base === BaseType )
+ return TemplateClass.instanceSet[i].instance;
+ }
+
+ TemplateClass.instanceSet[ nSize ] = {};
+ TemplateClass.instanceSet[ nSize ].base = BaseType;
+ TemplateClass.instanceSet[ nSize ].instance = TemplateClass( BaseType );
+
+ return TemplateClass.instanceSet[ nSize ].instance;
+}
+
+
+
+/**********************************
+ ** Helper functions and classes **
+ **********************************/
+
+function Rectangle( aSVGRectElem )
+{
+ var x = parseInt( aSVGRectElem.getAttribute( 'x' ) );
+ var y = parseInt( aSVGRectElem.getAttribute( 'y' ) );
+ var width = parseInt( aSVGRectElem.getAttribute( 'width' ) );
+ var height = parseInt( aSVGRectElem.getAttribute( 'height' ) );
+
+ this.left = x;
+ this.right = x + width;
+ this.top = y;
+ this.bottom = y + height;
+}
+
+/*
+ * Returns key corresponding to a value in object, null otherwise.
+ *
+ * @param Object
+ * @param value
+ */
+function getKeyByValue(aObj, value) {
+ for(var key in aObj) {
+ if(aObj[key] == value)
+ return key;
+ }
+ return null;
+}
+
+function log( message )
+{
+ if( typeof console == 'object' )
+ {
+ // eslint-disable-next-line no-console
+ console.log( message );
+ }
+ else if( typeof opera == 'object' )
+ {
+ opera.postError( message );
+ }
+ // eslint-disable-next-line no-undef
+ else if( typeof java == 'object' && typeof java.lang == 'object' )
+ {
+ // eslint-disable-next-line no-undef
+ java.lang.System.out.println( message );
+ }
+}
+
+function getNSAttribute( sNSPrefix, aElem, sAttrName )
+{
+ if( !aElem ) return null;
+ if( 'getAttributeNS' in aElem )
+ {
+ return aElem.getAttributeNS( NSS[sNSPrefix], sAttrName );
+ }
+ else
+ {
+ return aElem.getAttribute( sNSPrefix + ':' + sAttrName );
+ }
+}
+
+function getOOOAttribute( aElem, sAttrName )
+{
+ return getNSAttribute( 'ooo', aElem, sAttrName );
+}
+
+function setNSAttribute( sNSPrefix, aElem, sAttrName, aValue )
+{
+ if( !aElem ) return false;
+ if( 'setAttributeNS' in aElem )
+ {
+ aElem.setAttributeNS( NSS[sNSPrefix], sAttrName, aValue );
+ return true;
+ }
+ else
+ {
+ aElem.setAttribute(sNSPrefix + ':' + sAttrName, aValue );
+ return true;
+ }
+}
+
+function getElementsByClassName( aElem, sClassName )
+{
+
+ var aElementSet = [];
+ // not all browsers support the 'getElementsByClassName' method
+ if( 'getElementsByClassName' in aElem )
+ {
+ aElementSet = aElem.getElementsByClassName( sClassName );
+ }
+ else
+ {
+ var aElementSetByClassProperty = getElementsByProperty( aElem, 'class' );
+ for( var i = 0; i < aElementSetByClassProperty.length; ++i )
+ {
+ var sAttrClassName = aElementSetByClassProperty[i].getAttribute( 'class' );
+ if( sAttrClassName == sClassName )
+ {
+ aElementSet.push( aElementSetByClassProperty[i] );
+ }
+ }
+ }
+ return aElementSet;
+}
+
+function getElementByClassName( aElem, sClassName /*, sTagName */)
+{
+ var aElementSet = getElementsByClassName( aElem, sClassName );
+ if ( aElementSet.length == 1 )
+ return aElementSet[0];
+ else
+ return null;
+}
+
+function getClassAttribute( aElem )
+{
+ if( aElem )
+ return aElem.getAttribute( 'class' );
+ return '';
+}
+
+function createElementGroup( aParentElement, aElementList, nFrom, nCount, sGroupClass, sGroupId )
+{
+ var nTo = nFrom + nCount;
+ if( nCount < 1 || aElementList.length < nTo )
+ {
+ log( 'createElementGroup: not enough elements available.' );
+ return;
+ }
+ var firstElement = aElementList[nFrom];
+ if( !firstElement )
+ {
+ log( 'createElementGroup: element not found.' );
+ return;
+ }
+ var aGroupElement = document.createElementNS( NSS['svg'], 'g' );
+ if( sGroupId )
+ aGroupElement.setAttribute( 'id', sGroupId );
+ if( sGroupClass )
+ aGroupElement.setAttribute( 'class', sGroupClass );
+ aParentElement.insertBefore( aGroupElement, firstElement );
+ var i = nFrom;
+ for( ; i < nTo; ++i )
+ {
+ aParentElement.removeChild( aElementList[i] );
+ aGroupElement.appendChild( aElementList[i] );
+ }
+}
+
+function initVisibilityProperty( aElement )
+{
+ var nVisibility = VISIBLE;
+ var sVisibility = aElement.getAttribute( 'visibility' );
+ if( sVisibility ) nVisibility = aVisibilityValue[ sVisibility ];
+ return nVisibility;
+}
+
+function getSafeIndex( nIndex, nMin, nMax )
+{
+ if( nIndex < nMin )
+ return nMin;
+ else if( nIndex > nMax )
+ return nMax;
+ else
+ return nIndex;
+}
+
+function getUrlParameter(name)
+{
+ name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
+ var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
+ var results = regex.exec(window.location.search);
+ return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
+}
+
+/** getRandomInt
+ *
+ * @param nMax
+ * @returns {number}
+ * an integer in [0,nMax[
+ */
+function getRandomInt( nMax )
+{
+ return Math.floor( Math.random() * nMax );
+}
+
+function isTextFieldElement( aElement ) // eslint-disable-line no-unused-vars
+{
+ var sClassName = aElement.getAttribute( 'class' );
+ return ( sClassName === aSlideNumberClassName ) ||
+ ( sClassName === aFooterClassName ) ||
+ ( sClassName === aHeaderClassName ) ||
+ ( sClassName === aDateTimeClassName );
+}
+
+
+/*********************
+ ** Debug Utilities **
+ *********************/
+
+function DebugPrinter()
+{
+ this.bEnabled = false;
+}
+
+
+DebugPrinter.prototype.on = function()
+{
+ this.bEnabled = true;
+};
+
+DebugPrinter.prototype.off = function()
+{
+ this.bEnabled = false;
+};
+
+DebugPrinter.prototype.isEnabled = function()
+{
+ return this.bEnabled;
+};
+
+DebugPrinter.prototype.print = function( sMessage, nTime )
+{
+ if( this.isEnabled() )
+ {
+ var sInfo = 'DBG: ' + sMessage;
+ if( nTime )
+ sInfo += ' (at: ' + String( nTime / 1000 ) + 's)';
+ log( sInfo );
+ }
+};
+
+
+// - Debug Printers -
+var aGenericDebugPrinter = new DebugPrinter();
+aGenericDebugPrinter.on();
+var DBGLOG = bind2( DebugPrinter.prototype.print, aGenericDebugPrinter );
+
+var NAVDBG = new DebugPrinter();
+NAVDBG.off();
+
+var ANIMDBG = new DebugPrinter();
+ANIMDBG.off();
+
+var aRegisterEventDebugPrinter = new DebugPrinter();
+aRegisterEventDebugPrinter.off();
+
+var aTimerEventQueueDebugPrinter = new DebugPrinter();
+aTimerEventQueueDebugPrinter.off();
+
+var aEventMultiplexerDebugPrinter = new DebugPrinter();
+aEventMultiplexerDebugPrinter.off();
+
+var aNextEffectEventArrayDebugPrinter = new DebugPrinter();
+aNextEffectEventArrayDebugPrinter.off();
+
+var aActivityQueueDebugPrinter = new DebugPrinter();
+aActivityQueueDebugPrinter.off();
+
+var aAnimatedElementDebugPrinter = new DebugPrinter();
+aAnimatedElementDebugPrinter.off();
+
+
+
+
+/************************
+ *** Core Classes ***
+ ************************/
+
+/** Class MetaDocument
+ * This class provides a pool of properties related to the whole presentation.
+ * Moreover it is responsible for:
+ * - initializing the set of MetaSlide objects that handle the meta information
+ * for each slide;
+ * - creating a map with key an id and value the svg element containing
+ * the animations performed on the slide with such an id.
+ *
+ */
+function MetaDocument()
+{
+ // We look for the svg element that provides the following presentation
+ // properties:
+ // - the number of slides in the presentation;
+ // - the type of numbering used in the presentation.
+ // Moreover it wraps svg elements providing meta information on each slide
+ // and svg elements providing content and properties of each text field.
+ var aMetaDocElem = document.getElementById( aOOOElemMetaSlides );
+ assert( aMetaDocElem, 'MetaDocument: the svg element with id:' + aOOOElemMetaSlides + 'is not valid.');
+
+ // We initialize general presentation properties:
+ // - the number of slides in the presentation;
+ this.nNumberOfSlides = parseInt( aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrNumberOfSlides ) );
+ assert( typeof this.nNumberOfSlides == 'number' && this.nNumberOfSlides > 0,
+ 'MetaDocument: number of slides is zero or undefined.' );
+ // - the index of the slide to show when the presentation starts;
+ this.nStartSlideNumber = parseInt( aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrStartSlideNumber ) ) || 0;
+ // - get the parameter StartSlideNumber in the URL for online presentation
+ var aParmStartSlideNumber = getUrlParameter('StartSlideNumber');
+ if (aParmStartSlideNumber !== '')
+ {
+ this.nStartSlideNumber = parseInt(aParmStartSlideNumber);
+ }
+ // - the numbering type used in the presentation, default type is arabic.
+ this.sPageNumberingType = aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrNumberingType ) || 'arabic';
+ // - the way text is exported
+ this.bIsUsePositionedChars = ( aMetaDocElem.getAttributeNS( NSS['ooo'], aOOOAttrUsePositionedChars ) === 'true' );
+
+ // The <defs> element used for wrapping <clipPath>.
+ this.aClipPathGroup = getElementByClassName( ROOT_NODE, aClipPathGroupClassName );
+ assert( this.aClipPathGroup, 'MetaDocument: the clip path group element is not valid.');
+
+ // The <clipPath> element used to clip all slides.
+ this.aPresentationClipPath = document.getElementById( aPresentationClipPathId );
+ assert( this.aPresentationClipPath,
+ 'MetaDocument: the presentation clip path element element is not valid.');
+
+ // The collections for handling properties of each slide, svg elements
+ // related to master pages and content and properties of text fields.
+ this.aMetaSlideSet = [];
+ this.aMasterPageSet = {};
+ this.aTextFieldHandlerSet = {};
+ this.aTextFieldContentProviderSet = [];
+ this.aSlideNumberProvider = new SlideNumberProvider( this.nStartSlideNumber + 1, this.sPageNumberingType );
+ this.aCurrentDateProvider = new CurrentDateTimeProvider( null, '<date>' );
+ this.aCurrentTimeProvider = new CurrentDateTimeProvider( null, '<time>' );
+
+ // We create a map with key an id and value the svg element containing
+ // the animations performed on the slide with such an id.
+ this.bIsAnimated = false;
+ this.aSlideAnimationsMap = {};
+ this.initSlideAnimationsMap();
+
+ // We initialize dummy slide - used as leaving slide for transition on the first slide
+ this.theMetaDummySlide = new MetaSlide( 'ooo:meta_dummy_slide', this );
+
+ // We initialize the set of MetaSlide objects that handle the meta
+ // information for each slide.
+ for( var i = 0; i < this.nNumberOfSlides; ++i )
+ {
+ var sMetaSlideId = aOOOElemMetaSlide + '_' + i;
+ this.aMetaSlideSet.push( new MetaSlide( sMetaSlideId, this ) );
+ }
+ assert( this.aMetaSlideSet.length == this.nNumberOfSlides,
+ 'MetaDocument: aMetaSlideSet.length != nNumberOfSlides.' );
+}
+
+MetaDocument.prototype =
+{
+/*** public methods ***/
+
+/** getCurrentSlide
+ *
+ * @return
+ * The MetaSlide object handling the current slide.
+ */
+getCurrentSlide : function()
+{
+ return this.aMetaSlideSet[nCurSlide];
+},
+
+/** setCurrentSlide
+ *
+ * @param nSlideIndex
+ * The index of the slide to show.
+ */
+setCurrentSlide : function( nSlideIndex )
+{
+ if( nSlideIndex >= 0 && nSlideIndex < this.nNumberOfSlides )
+ {
+ if( nCurSlide !== undefined )
+ this.aMetaSlideSet[nCurSlide].hide();
+ this.aMetaSlideSet[nSlideIndex].show();
+ nCurSlide = nSlideIndex;
+ }
+ else
+ {
+ log('MetaDocument.setCurrentSlide: slide index out of range: ' + nSlideIndex );
+ }
+},
+
+/*** private methods ***/
+
+initSlideAnimationsMap : function()
+{
+ var aAnimationsSection = document.getElementById( 'presentation-animations' );
+ if( aAnimationsSection )
+ {
+ var aAnimationsDefSet = aAnimationsSection.getElementsByTagName( 'defs' );
+
+ // we have at least one slide with animations ?
+ this.bIsAnimated = ( typeof aAnimationsDefSet.length =='number' &&
+ aAnimationsDefSet.length > 0 );
+
+ for( var i = 0; i < aAnimationsDefSet.length; ++i )
+ {
+ var sSlideId = aAnimationsDefSet[i].getAttributeNS( NSS['ooo'], aOOOAttrSlide );
+ var aChildSet = getElementChildren( aAnimationsDefSet[i] );
+ if( sSlideId && ( aChildSet.length === 1 ) )
+ {
+ this.aSlideAnimationsMap[ sSlideId ] = aChildSet[0];
+ }
+ }
+ }
+}
+
+}; // end MetaDocument prototype
+
+/** Class MetaSlide
+ * This class is responsible for:
+ * - parsing and initializing slide properties;
+ * - creating a MasterSlide object that provides direct access to the target
+ * master slide and its sub-elements;
+ * - initializing text field content providers;
+ * - initializing the slide animation handler.
+ *
+ * @param sMetaSlideId
+ * The string representing the id attribute of the meta-slide element.
+ * @param aMetaDoc
+ * The MetaDocument global object.
+ */
+function MetaSlide( sMetaSlideId, aMetaDoc )
+{
+ this.theDocument = document;
+ this.id = sMetaSlideId;
+ this.theMetaDoc = aMetaDoc;
+
+ // We get a reference to the meta-slide element.
+ this.element = this.theDocument.getElementById( this.id );
+ assert( this.element,
+ 'MetaSlide: meta_slide element <' + this.id + '> not found.' );
+
+ // We get a reference to the slide element.
+ this.slideId = this.element.getAttributeNS( NSS['ooo'], aOOOAttrSlide );
+ this.slideElement = this.theDocument.getElementById( this.slideId );
+ assert( this.slideElement,
+ 'MetaSlide: slide element <' + this.slideId + '> not found.' );
+
+ if( this.slideId !== 'dummy_slide' )
+ this.nSlideNumber = parseInt( this.slideId.substr(2) );
+ else
+ this.nSlideNumber= -1;
+
+ this.slideName = this.element.getAttributeNS( NSS['ooo'], aOOOAttrDisplayName );
+
+ // Each slide element is double wrapped by <g> elements.
+ // The outer <g> element is responsible for
+ // the slide element visibility. In fact the visibility attribute has
+ // to be set on the parent of the slide element and not directly on
+ // the slide element. The reason is that in index mode each slide
+ // rendered in a thumbnail view is targeted by a <use> element, however
+ // when the visibility attribute is set directly on the referred slide
+ // element its visibility is not overridden by the visibility attribute
+ // defined by the targeting <use> element. The previous solution was,
+ // when the user switched to index mode, to set up the visibility attribute
+ // of all slides rendered in a thumbnail to 'visible'.
+ // Obviously the slides were not really visible because the grid of
+ // thumbnails was above them, anyway Firefox performance was really bad.
+ // The workaround of setting up the visibility attribute on the slide
+ // parent element let us to make visible a slide in a <use> element
+ // even if the slide parent element visibility is set to 'hidden'.
+ // The inner <g> element is used in order to append some element
+ // before or after the slide, operation that can be needed for some
+ // slide transition (e.g. fade through black). In this way we can
+ // create a view of both the slide and the appended elements that turns out
+ // to be useful for handling transition from the last to the first slide.
+ this.aContainerElement = this.slideElement.parentNode;
+ this.slideContainerId = this.aContainerElement.getAttribute( 'id' );
+ this.aVisibilityStatusElement = this.aContainerElement.parentNode;
+
+ // We get a reference to the draw page element, where all shapes specific
+ // of this slide live.
+ this.pageElement = getElementByClassName( this.slideElement, aPageClassName );
+ assert( this.pageElement,
+ 'MetaSlide: page element <' + this.slideId + '> not found.' );
+
+ // The slide custom background element and its id attribute.
+ this.backgroundElement = getElementByClassName( this.pageElement, 'Background' );
+ if( this.backgroundElement )
+ {
+ this.backgroundId = this.backgroundElement.getAttribute( 'id' );
+ }
+
+ // We initialize text fields
+ this.initPlaceholderElements();
+
+ // We initialize the MasterPage object that provides direct access to
+ // the target master page element.
+ this.masterPage = this.initMasterPage();
+
+ // We check if the slide has a custom background which overrides the one of the targeted master page
+ this.bHasCustomBackground = this.initHasCustomBackground();
+
+ // We initialize visibility properties of the target master page elements.
+ this.nAreMasterObjectsVisible = this.initVisibilityProperty( aOOOAttrMasterObjectsVisibility, VISIBLE );
+ this.nIsBackgroundVisible = this.initVisibilityProperty( aOOOAttrBackgroundVisibility, VISIBLE );
+ this.nIsPageNumberVisible = this.initVisibilityProperty( aOOOAttrPageNumberVisibility, HIDDEN );
+ this.nIsDateTimeVisible = this.initVisibilityProperty( aOOOAttrDateTimeVisibility, VISIBLE );
+ this.nIsFooterVisible = this.initVisibilityProperty( aOOOAttrFooterVisibility, VISIBLE );
+ this.nIsHeaderVisible = this.initVisibilityProperty( aOOOAttrHeaderVisibility, VISIBLE );
+
+ // This property tell us if the date/time field need to be updated
+ // each time the slide is shown. It is initialized in
+ // the initDateTimeFieldContentProvider method.
+ this.bIsDateTimeVariable = undefined;
+
+ // We initialize the objects responsible to provide the content to text field.
+ this.aTextFieldContentProviderSet = {};
+ this.aTextFieldContentProviderSet[aSlideNumberClassName] = this.initSlideNumberFieldContentProvider();
+ this.aTextFieldContentProviderSet[aDateTimeClassName] = this.initDateTimeFieldContentProvider( aOOOAttrDateTimeField );
+ this.aTextFieldContentProviderSet[aFooterClassName] = this.initFixedTextFieldContentProvider( aOOOAttrFooterField );
+ this.aTextFieldContentProviderSet[aHeaderClassName] = this.initFixedTextFieldContentProvider( aOOOAttrHeaderField );
+ this.aTextFieldContentProviderSet[aDateClassName] = this.theMetaDoc.aCurrentDateProvider;
+ this.aTextFieldContentProviderSet[aTimeClassName] = this.theMetaDoc.aCurrentTimeProvider;
+ this.aTextFieldContentProviderSet[aSlideNameClassName] = new FixedTextProvider( this.slideName );
+
+ // We init the slide duration when automatic slide transition is enabled
+ this.fDuration = this.initSlideDuration();
+
+ // We look for slide transition.
+ this.aTransitionHandler = null;
+ this.bHasTransition = this.initHasTransition() || true;
+ if( this.bHasTransition )
+ {
+ this.aTransitionHandler = new SlideTransition( this.getSlideAnimationsRoot(), this.slideId );
+ }
+
+ // We initialize the SlideAnimationsHandler object
+ this.aSlideAnimationsHandler = new SlideAnimations( aSlideShow.getContext() );
+ this.aSlideAnimationsHandler.importAnimations( this.getSlideAnimationsRoot() );
+ this.aSlideAnimationsHandler.parseElements();
+
+ // this statement is used only for debugging
+ // eslint-disable-next-line no-constant-condition
+ if( false && this.aSlideAnimationsHandler.aRootNode )
+ log( this.aSlideAnimationsHandler.aRootNode.info( true ) );
+
+ // We collect text shapes included in this slide .
+ this.aTextShapeSet = this.collectTextShapes();
+
+ // We initialize hyperlinks
+ this.aHyperlinkSet = this.initHyperlinks();
+
+}
+
+MetaSlide.prototype =
+{
+/*** public methods ***/
+
+/** show
+ * Set the visibility property of the slide to 'inherit'
+ * and update the master page view.
+ */
+show : function()
+{
+ this.updateMasterPageView();
+ this.aVisibilityStatusElement.setAttribute( 'visibility', 'inherit' );
+},
+
+/** hide
+ * Set the visibility property of the slide to 'hidden'.
+ */
+hide : function()
+{
+ this.aVisibilityStatusElement.setAttribute( 'visibility', 'hidden' );
+},
+
+/** updateMasterPageView
+ * On first call it creates a master page view element and insert it at
+ * the begin of the slide element. Moreover it updates the text fields
+ * included in the master page view.
+ */
+updateMasterPageView : function()
+{
+ // The master page view element is generated and attached on first time
+ // the slide is shown.
+ if( !this.aMasterPageView )
+ {
+ this.aMasterPageView = new MasterPageView( this );
+ this.aMasterPageView.attachToSlide();
+ }
+ this.aMasterPageView.update();
+},
+
+/*** private methods ***/
+
+// It handles a text field inserted on a slide, not on a master page.
+initPlaceholderElements : function()
+{
+ var aPlaceholderList = getElementsByClassName(this.pageElement , 'PlaceholderText' );
+ var i = 0;
+ for( ; i < aPlaceholderList.length; ++i )
+ {
+ var aPlaceholderElem = aPlaceholderList[i];
+ var sContent = aPlaceholderElem.textContent;
+ if( sContent === '<date>' )
+ aPlaceholderElem.textContent = new Date().toLocaleDateString();
+ else if( sContent === '<time>' )
+ aPlaceholderElem.textContent = new Date().toLocaleTimeString();
+ }
+},
+
+initMasterPage : function()
+{
+ var sMasterPageId = this.element.getAttributeNS( NSS['ooo'], aOOOAttrMaster );
+
+ // Check that the master page handler object has not already been
+ // created by another slide that target the same master page.
+ if( !this.theMetaDoc.aMasterPageSet.hasOwnProperty( sMasterPageId ) )
+ {
+ this.theMetaDoc.aMasterPageSet[ sMasterPageId ] = new MasterPage( sMasterPageId, this );
+
+ // We initialize aTextFieldHandlerSet[ sMasterPageId ] to an empty
+ // collection.
+ this.theMetaDoc.aTextFieldHandlerSet[ sMasterPageId ] = {};
+ }
+ return this.theMetaDoc.aMasterPageSet[ sMasterPageId ];
+},
+
+initSlideDuration : function()
+{
+ var sSlideDuration = this.element.getAttributeNS( NSS['ooo'], aOOOAttrSlideDuration );
+ if( sSlideDuration && sSlideDuration.length > 0 )
+ return parseFloat( sSlideDuration );
+ else
+ return -1;
+},
+
+initHasTransition : function()
+{
+ var sHasTransition = this.element.getAttributeNS( NSS['ooo'], aOOOAttrHasTransition );
+ return ( sHasTransition === 'true' );
+},
+
+initHasCustomBackground : function()
+{
+ var sHasCustomBackground = this.element.getAttributeNS( NSS['ooo'], aOOOAttrHasCustomBackground );
+ return ( sHasCustomBackground === 'true' );
+},
+
+initVisibilityProperty : function( aVisibilityAttribute, nDefaultValue )
+{
+ var nVisibility = nDefaultValue;
+ var sVisibility = getOOOAttribute( this.element, aVisibilityAttribute );
+ if( sVisibility )
+ nVisibility = aVisibilityValue[ sVisibility ];
+ return nVisibility;
+},
+
+initSlideNumberFieldContentProvider : function()
+{
+ return this.theMetaDoc.aSlideNumberProvider;
+},
+
+initDateTimeFieldContentProvider : function( aOOOAttrDateTimeField )
+{
+ var sTextFieldId = getOOOAttribute( this.element, aOOOAttrDateTimeField );
+ if( !sTextFieldId ) return null;
+
+ var nLength = aOOOElemTextField.length + 1;
+ var nIndex = parseInt(sTextFieldId.substring( nLength ) );
+ if( typeof nIndex != 'number') return null;
+
+ if( !this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ] )
+ {
+ var aTextField;
+ var aTextFieldElem = document.getElementById( sTextFieldId );
+ var sClassName = getClassAttribute( aTextFieldElem );
+ if( sClassName == 'FixedDateTimeField' )
+ {
+ aTextField = new FixedTextByElementProvider( aTextFieldElem );
+ this.bIsDateTimeVariable = false;
+ }
+ else if( sClassName == 'VariableDateTimeField' )
+ {
+ aTextField = new CurrentDateTimeProvider( aTextFieldElem );
+ this.bIsDateTimeVariable = true;
+ }
+ else
+ {
+ aTextField = null;
+ }
+ this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ] = aTextField;
+ }
+ return this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ];
+},
+
+initFixedTextFieldContentProvider : function( aOOOAttribute )
+{
+ var sTextFieldId = getOOOAttribute( this.element, aOOOAttribute );
+ if( !sTextFieldId ) return null;
+
+ var nLength = aOOOElemTextField.length + 1;
+ var nIndex = parseInt( sTextFieldId.substring( nLength ) );
+ if( typeof nIndex != 'number') return null;
+
+ if( !this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ] )
+ {
+ var aTextFieldElem = document.getElementById( sTextFieldId );
+ this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ]
+ = new FixedTextByElementProvider( aTextFieldElem );
+ }
+ return this.theMetaDoc.aTextFieldContentProviderSet[ nIndex ];
+},
+
+collectTextShapes : function()
+{
+ var aTextShapeSet = [];
+ var aTextShapeIndexElem = getElementByClassName( document, 'TextShapeIndex' );
+ if( aTextShapeIndexElem )
+ {
+ var aIndexEntryList = getElementChildren( aTextShapeIndexElem );
+ var i;
+ for( i = 0; i < aIndexEntryList.length; ++i )
+ {
+ var sSlideId = getOOOAttribute( aIndexEntryList[i], 'slide' );
+ if( sSlideId === this.slideId )
+ {
+ var sTextShapeIds = getOOOAttribute( aIndexEntryList[i], 'id-list' );
+ if( sTextShapeIds )
+ {
+ var aTextShapeIdSet = sTextShapeIds.split( ' ' );
+ var j;
+ for( j = 0; j < aTextShapeIdSet.length; ++j )
+ {
+ var aTextShapeElem = document.getElementById( aTextShapeIdSet[j] );
+ if( aTextShapeElem )
+ {
+ aTextShapeSet.push( aTextShapeElem );
+ }
+ else
+ {
+ log( 'warning: MetaSlide.collectTextShapes: text shape with id <' + aTextShapeIdSet[j] + '> is not valid.' );
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ return aTextShapeSet;
+},
+
+initHyperlinks : function()
+{
+ var aHyperlinkSet = {};
+ var i;
+ for( i = 0; i < this.aTextShapeSet.length; ++i )
+ {
+ if( this.aTextShapeSet[i] )
+ {
+ var aHyperlinkIdList = getElementByClassName( this.aTextShapeSet[i], 'HyperlinkIdList' );
+ if( aHyperlinkIdList )
+ {
+ var sHyperlinkIds = aHyperlinkIdList.textContent;
+ if( sHyperlinkIds )
+ {
+ var aHyperlinkIdSet = sHyperlinkIds.trim().split( ' ' );
+ var j;
+ for( j = 0; j < aHyperlinkIdSet.length; ++j )
+ {
+ var sId = aHyperlinkIdSet[j];
+ aHyperlinkSet[ sId ] = new HyperlinkElement( sId, this.aSlideAnimationsHandler.aEventMultiplexer );
+ }
+ }
+ }
+ }
+ }
+ return aHyperlinkSet;
+},
+
+getSlideAnimationsRoot : function()
+{
+ return this.theMetaDoc.aSlideAnimationsMap[ this.slideId ];
+}
+
+}; // end MetaSlide prototype
+
+function getTextFieldType ( elem )
+{
+ var sFieldType = null;
+ var sClass = elem.getAttribute('class');
+ if( sClass == 'TextShape' )
+ {
+ var aPlaceholderElement = getElementByClassName( elem, 'PlaceholderText' );
+ if (aPlaceholderElement)
+ {
+ var sContent = aPlaceholderElement.textContent
+ if (sContent === '<number>')
+ sFieldType = aSlideNumberClassName;
+ else if (sContent === '<date>')
+ sFieldType = aDateClassName;
+ else if (sContent === '<time>')
+ sFieldType = aTimeClassName;
+ else if (sContent === '<slide-name>')
+ sFieldType = aSlideNameClassName;
+ }
+ }
+ return sFieldType;
+}
+
+function isTextFieldByClassName ( sClassName )
+{
+ return sClassName === aDateTimeClassName || sClassName === aFooterClassName
+ || sClassName === aHeaderClassName || sClassName.indexOf( aSlideNumberClassName ) == 0
+ || sClassName.indexOf( aDateClassName ) == 0 || sClassName.indexOf( aTimeClassName ) == 0
+ || sClassName.indexOf( aSlideNameClassName ) == 0;
+}
+
+/** Class MasterPage
+ * This class gives direct access to a master page element and to the following
+ * elements included in the master page:
+ * - the background element,
+ * - the background objects group element,
+ * Moreover for each text field element a Placeholder object is created which
+ * manages the text field element itself.
+ *
+ * The master page element structure is the following:
+ * <g class='Master_Slide'>
+ * <g class='Background'>
+ * background image
+ * </g>
+ * <g class='BackgroundObjects'>
+ * <g class='Date/Time'>
+ * date/time placeholder
+ * </g>
+ * <g class='Header'>
+ * header placeholder
+ * </g>
+ * <g class='Footer'>
+ * footer placeholder
+ * </g>
+ * <g class='Slide_Number'>
+ * slide number placeholder
+ * </g>
+ * shapes
+ * </g>
+ * </g>
+ *
+ * @param sMasterPageId
+ * A string representing the value of the id attribute of the master page
+ * element to be handled.
+ * @param aMetaSlide
+ * A meta slide having as master page the one with the passed id.
+ */
+function MasterPage( sMasterPageId, aMetaSlide )
+{
+ this.id = sMasterPageId;
+ this.metaSlide = aMetaSlide;
+
+ // The master page element to be handled.
+ this.element = document.getElementById( this.id );
+ assert( this.element,
+ 'MasterPage: master page element <' + this.id + '> not found.' );
+
+ // The master page background element and its id attribute.
+ this.background = getElementByClassName( this.element, 'Background' );
+ if( this.background )
+ {
+ this.backgroundId = this.background.getAttribute( 'id' );
+ this.backgroundVisibility = initVisibilityProperty( this.background );
+ }
+ else
+ {
+ this.backgroundId = '';
+ log( 'MasterPage: the background element is not valid.' );
+ }
+
+ // The background objects group element that contains every element presents
+ // on the master page except the background element.
+ this.backgroundObjects = getElementByClassName( this.element, 'BackgroundObjects' );
+ this.aBackgroundObjectSubGroupIdList = [];
+ if( this.backgroundObjects )
+ {
+ this.backgroundObjectsId = this.backgroundObjects.getAttribute( 'id' );
+ this.backgroundObjectsVisibility = initVisibilityProperty( this.backgroundObjects );
+
+ if( this.backgroundObjectsVisibility != HIDDEN )
+ {
+ var aBackgroundObjectList = getElementChildren( this.backgroundObjects );
+ var nFrom = 0;
+ var nCount = 0;
+ var nSubGroupId = 1;
+ var sClass;
+ var sId = '';
+ var i = 0;
+ for( ; i < aBackgroundObjectList.length; ++i )
+ {
+ var aObject = aBackgroundObjectList[i];
+ sClass = null;
+ var sFieldType = getTextFieldType( aObject );
+ if( sFieldType && aObject.firstElementChild )
+ {
+ var sObjId = aObject.firstElementChild.getAttribute( 'id' );
+ if( sObjId )
+ {
+ sClass = sFieldType + '.' + sObjId;
+ aObject.setAttribute('class', sClass);
+ }
+ }
+ if( !sClass )
+ {
+ sClass = aBackgroundObjectList[i].getAttribute('class');
+ }
+ if( !sClass || !isTextFieldByClassName( sClass ) )
+ {
+ if( nCount === 0 )
+ {
+ nFrom = i;
+ sId = this.backgroundObjectsId + '.' + nSubGroupId;
+ ++nSubGroupId;
+ this.aBackgroundObjectSubGroupIdList.push( sId );
+ }
+ ++nCount;
+ }
+ else
+ {
+ this.aBackgroundObjectSubGroupIdList.push( sClass );
+ if( nCount !== 0 )
+ {
+ createElementGroup( this.backgroundObjects, aBackgroundObjectList, nFrom, nCount, 'BackgroundObjectSubgroup', sId );
+ nCount = 0;
+ }
+ }
+ }
+ if( nCount !== 0 )
+ {
+ createElementGroup( this.backgroundObjects, aBackgroundObjectList, nFrom, nCount, 'BackgroundObjectSubgroup', sId );
+ }
+ }
+ }
+ else
+ {
+ this.backgroundObjectsId = '';
+ log( 'MasterPage: the background objects element is not valid.' );
+ }
+
+ // We populate the collection of placeholders.
+ this.aPlaceholderShapeSet = {};
+ this.initPlaceholderShapes();
+}
+
+MasterPage.prototype =
+{
+/*** private methods ***/
+
+initPlaceholderShapes : function()
+{
+ var sClassName;
+ var i = 0;
+ for( ; i < this.aBackgroundObjectSubGroupIdList.length; ++i )
+ {
+ sClassName = this.aBackgroundObjectSubGroupIdList[i];
+ if( isTextFieldByClassName( sClassName ) )
+ this.aPlaceholderShapeSet[ sClassName ] = new PlaceholderShape( this, sClassName );
+ }
+}
+
+}; // end MasterPage prototype
+
+/** Class PlaceholderShape
+ * This class provides direct access to a text field element and
+ * to the embedded placeholder element.
+ * Moreover it set up the text adjustment and position for the placeholder
+ * element.
+ * Note: the text field element included in a master page is used only as
+ * a template element, it is cloned for each specific text content
+ * (see the TextFieldContentProvider class and its derived classes).
+ *
+ * @param aMasterPage
+ * The master page object to which the text field to be handled belongs.
+ * @param sClassName
+ * A string representing the value of the class attribute of the text
+ * field element to be handled.
+ */
+function PlaceholderShape( aMasterPage, sClassName )
+{
+ this.masterPage = aMasterPage;
+ this.className = sClassName;
+
+ this.element = null;
+ this.textElement = null;
+ this.init();
+}
+
+/* public methods */
+PlaceholderShape.prototype.isValid = function()
+{
+ return ( this.element && this.textElement );
+};
+
+/* private methods */
+
+/** init
+ * In case a text field element of class type 'className' exists and such
+ * an element embeds a placeholder element, the text adjustment and position
+ * of the placeholder element is set up.
+ */
+PlaceholderShape.prototype.init = function()
+{
+ var aTextFieldElement = getElementByClassName( this.masterPage.backgroundObjects, this.className );
+ if( aTextFieldElement )
+ {
+ var aTextElem = getElementByClassName( aTextFieldElement, 'SVGTextShape' );
+ if( aTextElem )
+ {
+ var aPlaceholderElement = getElementByClassName(aTextElem, 'PlaceholderText');
+ if( aPlaceholderElement )
+ {
+ // SVG 1.1 does not support text wrapping wrt a rectangle.
+ // When a text shape contains a placeholder, setting up the position
+ // of each text line doesn't work since the position is computed
+ // before replacing the placeholder text.
+ // Anyway each text shape has an invisible rectangle that can be
+ // regarded as the text shape bounding box.
+ // We exploit such a feature and the exported text adjust attribute
+ // value in order to set up correctly the position and text
+ // adjustment for the text shape content.
+ // We assume that once the real value has been substituted to
+ // the placeholder the resulting content is no more than a single line.
+ // So we remove from <tspan> elements used for setting up the
+ // position of text lines (class TextPosition) the 'x' and 'y' attribute.
+ // In the general case we would need to implement a function
+ // which is able to compute at which words the text shape content has
+ // to be wrapped.
+ var aSVGRectElem = getElementByClassName( aTextFieldElement, 'BoundingBox' );
+ if( aSVGRectElem )
+ {
+ var aRect = new Rectangle( aSVGRectElem );
+ var sTextAdjust = getOOOAttribute( aTextFieldElement, aOOOAttrTextAdjust );
+ // the bbox of the text shape is indeed a bit larger, there is a bit of internal padding
+ var nMargin = 250; // 1000th mm
+ var sTextAnchor, sX;
+ if( sTextAdjust == 'left' )
+ {
+ sTextAnchor = 'start';
+ sX = String( Math.trunc( aRect.left + nMargin ) );
+ }
+ else if( sTextAdjust == 'right' )
+ {
+ sTextAnchor = 'end';
+ sX = String( Math.trunc( aRect.right - nMargin ) );
+ }
+ else if( sTextAdjust == 'center' )
+ {
+ sTextAnchor = 'middle';
+ var nMiddle = ( aRect.left + aRect.right ) / 2;
+ sX = String( parseInt( String( nMiddle ) ) );
+ }
+ if( sTextAnchor )
+ {
+ aTextElem.setAttribute( 'text-anchor', sTextAnchor );
+ if( sX )
+ aTextElem.setAttribute( 'x', sX );
+
+ var aTSpanElements = getElementsByClassName( aTextElem, 'TextPosition' );
+ if( aTSpanElements )
+ {
+ var i = 0;
+ for( ; i < aTSpanElements.length; ++i )
+ {
+ var aTSpanElem = aTSpanElements[i];
+ aTSpanElem.removeAttribute( 'x' );
+ if( i !== 0 )
+ aTSpanElem.removeAttribute( 'y' );
+ }
+ }
+ }
+ }
+
+ // date/time fields were not exported correctly when positioned chars are used
+ if( this.masterPage.metaSlide.theMetaDoc.bIsUsePositionedChars )
+ {
+ // We remove all text lines but the first one used as placeholder.
+ var aTextLineGroupElem = aPlaceholderElement.parentNode.parentNode;
+ if( aTextLineGroupElem )
+ {
+ // Just to be sure it is the element we are looking for.
+ var sFontFamilyAttr = aTextLineGroupElem.getAttribute( 'font-family' );
+ if( sFontFamilyAttr )
+ {
+ var aChildSet = getElementChildren( aTextLineGroupElem );
+ if( aChildSet.length > 1 )
+ var i = 1;
+ for( ; i < aChildSet.length; ++i )
+ {
+ aTextLineGroupElem.removeChild( aChildSet[i] );
+ }
+ }
+ }
+ }
+ this.textElement = aPlaceholderElement;
+ }
+ }
+ this.element = aTextFieldElement;
+ }
+};
+
+/** Class MasterPageView
+ * This class is used to creates a svg element of class MasterPageView and its
+ * sub-elements.
+ * It is also responsible for updating the content of the included text fields.
+ *
+ * MasterPageView element structure:
+ *
+ * <g class='MasterPageView'>
+ * <use class='Background'> // reference to master page background element
+ * <g class='BackgroundObjects'>
+ * <use class='BackgroundObjectSubGroup'> // reference to the group of shapes on the master page that are below text fields
+ * <g class='Slide_Number'> // a cloned element
+ * ...
+ * </g>
+ * <use class='Date/Time'> // reference to a clone
+ * <use class='Footer'>
+ * <use class='Header'>
+ * <use class='BackgroundObjectSubGroup'> // reference to the group of shapes on the master page that are above text fields
+ * </g>
+ * </g>
+ *
+ * Sub-elements are present only if they are visible.
+ *
+ * @param aMetaSlide
+ * The MetaSlide object managing the slide element that targets
+ * the master page view element created by an instance of MasterPageView.
+ */
+function MasterPageView( aMetaSlide )
+{
+ this.aMetaSlide = aMetaSlide;
+ this.aSlideElement = aMetaSlide.slideElement;
+ this.aPageElement = aMetaSlide.pageElement;
+ this.aMasterPage = aMetaSlide.masterPage;
+ this.aMPVElement = this.createElement();
+ this.bIsAttached = false;
+}
+
+/*** public methods ***/
+
+/** attachToSlide
+ * Prepend the master slide view element to the slide element.
+ */
+MasterPageView.prototype.attachToSlide = function()
+{
+ if( !this.bIsAttached )
+ {
+ var aInsertedElement = this.aSlideElement.insertBefore( this.aMPVElement, this.aPageElement );
+ assert( aInsertedElement === this.aMPVElement,
+ 'MasterPageView.attachToSlide: aInsertedElement != this.aMPVElement' );
+
+ this.bIsAttached = true;
+ }
+};
+
+/** detachFromSlide
+ * Remove the master slide view element from the slide element.
+ */
+MasterPageView.prototype.detachFromSlide = function()
+{
+ if( this.bIsAttached )
+ {
+ this.aSlideElement.removeChild( this.aMPVElement );
+ this.bIsAttached = false;
+ }
+};
+
+/** update
+ * Update the content of text fields placed on the master page.
+ */
+MasterPageView.prototype.update = function()
+{
+ if( this.aDateTimeFieldHandler && this.aMetaSlide.bIsDateTimeVariable )
+ this.aDateTimeFieldHandler.update();
+};
+
+/*** private methods ***/
+
+MasterPageView.prototype.createElement = function()
+{
+ var theDocument = document;
+ var aMasterPageViewElement = theDocument.createElementNS( NSS['svg'], 'g' );
+ assert( aMasterPageViewElement,
+ 'MasterPageView.createElement: failed to create a master page view element.' );
+ aMasterPageViewElement.setAttribute( 'class', 'MasterPageView' );
+
+ // we place a white rect below any else element
+ // that is also a workaround for some kind of slide transition
+ // when the master page is empty
+ var aWhiteRect = theDocument.createElementNS( NSS['svg'], 'rect' );
+ var nWidthExt = WIDTH / 1000;
+ var nHeightExt = HEIGHT / 1000;
+ aWhiteRect.setAttribute( 'x', String( -nWidthExt / 2 ) );
+ aWhiteRect.setAttribute( 'y', String( -nHeightExt / 2 ) );
+ aWhiteRect.setAttribute( 'width', String( WIDTH + nWidthExt ) );
+ aWhiteRect.setAttribute( 'height', String( HEIGHT + nHeightExt ) );
+ aWhiteRect.setAttribute( 'fill', '#FFFFFF' );
+ aMasterPageViewElement.appendChild( aWhiteRect );
+
+ // init the Background element
+ if( this.aMetaSlide.nIsBackgroundVisible )
+ {
+ var nBackgroundId = this.aMetaSlide.bHasCustomBackground ? this.aMetaSlide.backgroundId : this.aMasterPage.backgroundId;
+ this.aBackgroundElement = theDocument.createElementNS( NSS['svg'], 'use' );
+ this.aBackgroundElement.setAttribute( 'class', 'Background' );
+ setNSAttribute( 'xlink', this.aBackgroundElement,
+ 'href', '#' + nBackgroundId );
+
+ // node linking
+ aMasterPageViewElement.appendChild( this.aBackgroundElement );
+ }
+
+ // init the BackgroundObjects element
+ if( this.aMetaSlide.nAreMasterObjectsVisible )
+ {
+ this.aBackgroundObjectsElement = theDocument.createElementNS( NSS['svg'], 'g' );
+ this.aBackgroundObjectsElement.setAttribute( 'class', 'BackgroundObjects' );
+
+ // clone and initialize text field elements
+ var aBackgroundObjectSubGroupIdList = this.aMasterPage.aBackgroundObjectSubGroupIdList;
+ this.aBackgroundSubGroupElementSet = [];
+ var aPlaceholderShapeSet = this.aMasterPage.aPlaceholderShapeSet;
+ var aTextFieldContentProviderSet = this.aMetaSlide.aTextFieldContentProviderSet;
+ // where cloned elements are appended
+ var aDefsElement = this.aMetaSlide.element.parentNode;
+ var aTextFieldHandlerSet = this.aMetaSlide.theMetaDoc.aTextFieldHandlerSet;
+ var sMasterSlideId = this.aMasterPage.id;
+
+ var i = 0;
+ var sId;
+ for( ; i < aBackgroundObjectSubGroupIdList.length; ++i )
+ {
+ sId = aBackgroundObjectSubGroupIdList[i];
+ if( sId.indexOf( aSlideNumberClassName ) == 0 )
+ {
+ // Slide Number Field
+ // The cloned element is appended directly to the field group element
+ // since there is no slide number field content shared between two slide
+ // (because the slide number of two slide is always different).
+ var nIsPageNumberVisible = sId === aSlideNumberClassName ? this.aMetaSlide.nIsPageNumberVisible : true;
+ if( aPlaceholderShapeSet[sId] &&
+ aPlaceholderShapeSet[sId].isValid() &&
+ nIsPageNumberVisible &&
+ aTextFieldContentProviderSet[aSlideNumberClassName] )
+ {
+ var aSlideNumberFieldHandler =
+ new SlideNumberFieldHandler( aPlaceholderShapeSet[sId],
+ aTextFieldContentProviderSet[aSlideNumberClassName] );
+ aSlideNumberFieldHandler.update( this.aMetaSlide.nSlideNumber );
+ aSlideNumberFieldHandler.appendTo( this.aBackgroundObjectsElement );
+ if ( sId === aSlideNumberClassName )
+ this.aSlideNumberFieldHandler = aSlideNumberFieldHandler;
+ }
+ }
+ else if( sId === aDateTimeClassName )
+ {
+ // Date/Time field
+ if( this.aMetaSlide.nIsDateTimeVisible )
+ {
+ this.aDateTimeFieldHandler =
+ this.initTextFieldHandler( aDateTimeClassName, aPlaceholderShapeSet,
+ aTextFieldContentProviderSet, aDefsElement,
+ aTextFieldHandlerSet, sMasterSlideId );
+ }
+ }
+ else if( sId === aFooterClassName )
+ {
+ // Footer Field
+ if( this.aMetaSlide.nIsFooterVisible )
+ {
+ this.aFooterFieldHandler =
+ this.initTextFieldHandler( aFooterClassName, aPlaceholderShapeSet,
+ aTextFieldContentProviderSet, aDefsElement,
+ aTextFieldHandlerSet, sMasterSlideId );
+ }
+ }
+ else if( sId === aHeaderClassName )
+ {
+ // Header Field
+ if( this.aMetaSlide.nIsHeaderVisible )
+ {
+ this.aHeaderFieldHandler =
+ this.initTextFieldHandler( aHeaderClassName, aPlaceholderShapeSet,
+ aTextFieldContentProviderSet, aDefsElement,
+ aTextFieldHandlerSet, sMasterSlideId );
+ }
+ }
+ else if( sId.indexOf( aDateClassName ) == 0
+ || sId.indexOf( aTimeClassName ) == 0
+ || sId.indexOf( aSlideNameClassName ) == 0 )
+ {
+ this.initTextFieldHandler( sId, aPlaceholderShapeSet,
+ aTextFieldContentProviderSet, aDefsElement,
+ aTextFieldHandlerSet, sMasterSlideId );
+ }
+ else
+ {
+ // init BackgroundObjectSubGroup elements
+ var aBackgroundSubGroupElement = theDocument.createElementNS( NSS['svg'], 'use' );
+ aBackgroundSubGroupElement.setAttribute( 'class', 'BackgroundObjectSubGroup' );
+ setNSAttribute( 'xlink', aBackgroundSubGroupElement,
+ 'href', '#' + sId );
+ this.aBackgroundSubGroupElementSet.push( aBackgroundSubGroupElement );
+ // node linking
+ this.aBackgroundObjectsElement.appendChild( aBackgroundSubGroupElement );
+ }
+
+ }
+ // node linking
+ aMasterPageViewElement.appendChild( this.aBackgroundObjectsElement );
+ }
+
+ return aMasterPageViewElement;
+};
+
+MasterPageView.prototype.initTextFieldHandler =
+ function( sId, aPlaceholderShapeSet, aTextFieldContentProviderSet,
+ aDefsElement, aTextFieldHandlerSet, sMasterSlideId )
+{
+ var sRefId = null;
+ var aTextFieldHandler = null;
+ var sClassName = sId.split('.')[0];
+ var aPlaceholderShape = aPlaceholderShapeSet[sId];
+ var aTextFieldContentProvider = aTextFieldContentProviderSet[sClassName];
+ if( aPlaceholderShape && aPlaceholderShape.isValid()
+ && aTextFieldContentProvider )
+ {
+ var sTextFieldContentProviderId = aTextFieldContentProvider.sId;
+ // We create only one single TextFieldHandler object (and so one only
+ // text field clone) per master slide and text content.
+ if ( !aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ] )
+ {
+ aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ] =
+ new TextFieldHandler( aPlaceholderShape,
+ aTextFieldContentProvider );
+ aTextFieldHandler = aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ];
+ aTextFieldHandler.update();
+ aTextFieldHandler.appendTo( aDefsElement );
+ }
+ else
+ {
+ aTextFieldHandler = aTextFieldHandlerSet[ sMasterSlideId ][ sTextFieldContentProviderId ];
+ }
+ sRefId = aTextFieldHandler.sId;
+ }
+ else if( aPlaceholderShape && aPlaceholderShape.element && aPlaceholderShape.element.firstElementChild
+ && !aPlaceholderShape.textElement && !aTextFieldContentProvider )
+ {
+ sRefId = aPlaceholderShape.element.firstElementChild.getAttribute('id');
+ }
+
+ if( sRefId )
+ {
+ // We create a <use> element referring to the cloned text field and
+ // append it to the field group element.
+ var aTextFieldElement = document.createElementNS(NSS['svg'], 'use');
+ aTextFieldElement.setAttribute('class', sClassName);
+ setNSAttribute('xlink', aTextFieldElement,
+ 'href', '#' + sRefId);
+ // node linking
+ this.aBackgroundObjectsElement.appendChild( aTextFieldElement );
+ }
+ return aTextFieldHandler;
+};
+
+/** Class TextFieldHandler
+ * This class clone a text field field of a master page and set up
+ * the content of the cloned element on demand.
+ *
+ * @param aPlaceholderShape
+ * A PlaceholderShape object that provides the text field to be cloned.
+ * @param aTextContentProvider
+ * A TextContentProvider object to which the actual content updating is
+ * demanded.
+ */
+function TextFieldHandler( aPlaceholderShape, aTextContentProvider )
+{
+ this.aPlaceHolderShape = aPlaceholderShape;
+ this.aTextContentProvider = aTextContentProvider;
+ assert( this.aTextContentProvider,
+ 'TextFieldHandler: text content provider not defined.' );
+ this.sId = 'tf' + String( TextFieldHandler.getUniqueId() );
+ // The cloned text field element to be handled.
+ this.aTextFieldElement = null;
+ // The actual <text> element where the field content has to be placed.
+ this.aTextPlaceholderElement = null;
+ this.cloneElement();
+}
+
+/*** private methods ***/
+
+TextFieldHandler.CURR_UNIQUE_ID = 0;
+
+TextFieldHandler.getUniqueId = function()
+{
+ ++TextFieldHandler.CURR_UNIQUE_ID;
+ return TextFieldHandler.CURR_UNIQUE_ID;
+};
+
+TextFieldHandler.prototype.cloneElement = function()
+{
+ assert( this.aPlaceHolderShape && this.aPlaceHolderShape.isValid(),
+ 'TextFieldHandler.cloneElement: placeholder shape is not valid.' );
+ // The cloned text field element.
+ this.aTextFieldElement = this.aPlaceHolderShape.element.cloneNode( true /* deep clone */ );
+ assert( this.aTextFieldElement,
+ 'TextFieldHandler.cloneElement: aTextFieldElement is not defined' );
+ this.aTextFieldElement.setAttribute( 'id', this.sId );
+ // Text field placeholder visibility is always set to 'hidden'.
+ this.aTextFieldElement.removeAttribute( 'visibility' );
+ // The actual <text> element where the field content has to be placed.
+ this.aTextPlaceholderElement = getElementByClassName( this.aTextFieldElement, 'PlaceholderText' );
+ assert( this.aTextPlaceholderElement,
+ 'TextFieldHandler.cloneElement: aTextPlaceholderElement is not defined' );
+};
+
+/*** public methods ***/
+
+/** appendTo
+ * Append the cloned text field element to a svg element.
+ *
+ * @param aParentNode
+ * The svg element to which the cloned text field has to be appended.
+ */
+TextFieldHandler.prototype.appendTo = function( aParentNode )
+{
+ if( !this.aTextFieldElement )
+ {
+ log( 'TextFieldHandler.appendTo: aTextFieldElement is not defined' );
+ return;
+ }
+ if( !aParentNode )
+ {
+ log( 'TextFieldHandler.appendTo: parent node is not defined' );
+ return;
+ }
+
+ aParentNode.appendChild( this.aTextFieldElement );
+};
+
+/** setTextContent
+ * Modify the content of the cloned text field.
+ *
+ * @param sText
+ * A string representing the new content of the cloned text field.
+ */
+TextFieldHandler.prototype.setTextContent = function( sText )
+{
+ if( !this.aTextPlaceholderElement )
+ {
+ log( 'PlaceholderShape.setTextContent: text element is not valid in placeholder of type '
+ + this.className + ' that belongs to master slide ' + this.masterPage.id );
+ return;
+ }
+ this.aTextPlaceholderElement.textContent = sText;
+};
+
+/** update
+ * Update the content of the handled text field. The new content is provided
+ * directly from the TextContentProvider data member.
+ */
+TextFieldHandler.prototype.update = function()
+{
+ if( !this.aTextContentProvider )
+ log('TextFieldHandler.update: text content provider not defined.');
+ else
+ this.aTextContentProvider.update( this );
+};
+
+/** SlideNumberFieldHandler
+ * This class clone the slide number field of a master page and set up
+ * the content of the cloned element on demand.
+ *
+ * @param aPlaceholderShape
+ * A PlaceholderShape object that provides the slide number field
+ * to be cloned.
+ * @param aTextContentProvider
+ * A SlideNumberProvider object to which the actual content updating is
+ * demanded.
+ */
+function SlideNumberFieldHandler( aPlaceholderShape, aTextContentProvider )
+{
+ SlideNumberFieldHandler.superclass.constructor.call( this, aPlaceholderShape, aTextContentProvider );
+}
+extend( SlideNumberFieldHandler, TextFieldHandler );
+
+/*** public methods ***/
+
+/** update
+ * Update the content of the handled slide number field with the passed number.
+ *
+ * @param nPageNumber
+ * The number representing the new content of the slide number field.
+ */
+SlideNumberFieldHandler.prototype.update = function( nPageNumber )
+{
+ // The actual content updating is demanded to the related
+ // SlideNumberProvider instance that have the needed info on
+ // the numbering type.
+ if( !this.aTextContentProvider )
+ log('TextFieldHandler.update: text content provider not defined.');
+ else
+ this.aTextContentProvider.update( this, nPageNumber );
+};
+
+
+/******************************************************************************
+ * Text Field Content Provider Class Hierarchy
+ *
+ * The following classes are responsible to format and set the text content
+ * of text fields.
+ *
+ ******************************************************************************/
+
+/** Class TextFieldContentProvider
+ * This class is the root abstract class of the hierarchy.
+ *
+ * @param aTextFieldContentElement
+ * The svg element that contains the text content for one or more
+ * master slide text field.
+ */
+function TextFieldContentProvider()
+{
+ this.sId = TextFieldContentProvider.getUniqueId();
+}
+
+/*** private methods ***/
+
+TextFieldContentProvider.CURR_UNIQUE_ID = 0;
+
+TextFieldContentProvider.getUniqueId = function()
+{
+ ++TextFieldContentProvider.CURR_UNIQUE_ID;
+ return TextFieldContentProvider.CURR_UNIQUE_ID;
+};
+
+/** Class FixedTextProvider
+ * This class handles text field with a fixed text.
+ * The text content is provided by the 'text' property.
+ *
+ * @param aText
+ * a string containing the text to be substituted.
+ */
+function FixedTextProvider( aText )
+{
+ FixedTextProvider.superclass.constructor.call( this );
+ this.text = aText;
+}
+extend( FixedTextProvider, TextFieldContentProvider );
+
+/*** public methods ***/
+
+/** update
+ * Set up the content of a fixed text field.
+ *
+ * @param aFixedTextField
+ * An object that implement a setTextContent( String ) method in order
+ * to set the content of a given text field.
+ */
+FixedTextProvider.prototype.update = function( aFixedTextField )
+{
+ aFixedTextField.setTextContent( this.text );
+};
+
+/** Class FixedTextByElementProvider
+ * This class handles text field with a fixed text.
+ * The text content is provided by the 'text' property.
+ *
+ * @param aTextFieldContentElement
+ * The svg element that contains the text content for one or more
+ * master slide text field.
+ */
+function FixedTextByElementProvider( aTextFieldContentElement )
+{
+ FixedTextByElementProvider.superclass.constructor.call( this, aTextFieldContentElement.textContent );
+}
+extend( FixedTextByElementProvider, FixedTextProvider );
+
+/** Class CurrentDateTimeProvider
+ * Provide the text content to a date/time field by generating the current
+ * date/time in the format specified by the 'dateTimeFormat' property.
+ *
+ * @param aTextFieldContentElement
+ * The svg element that contains the date/time format for one or more
+ * master slide date/time field.
+ */
+function CurrentDateTimeProvider( aTextFieldContentElement, sDateTimeFormat )
+{
+ CurrentDateTimeProvider.superclass.constructor.call( this, aTextFieldContentElement );
+ if( aTextFieldContentElement )
+ this.dateTimeFormat = getOOOAttribute( aTextFieldContentElement, aOOOAttrDateTimeFormat );
+ else
+ {
+ this.dateTimeFormat = sDateTimeFormat;
+ }
+}
+extend( CurrentDateTimeProvider, TextFieldContentProvider );
+
+/*** public methods ***/
+
+/** update
+ * Set up the content of a variable date/time field.
+ *
+ * @param aDateTimeField
+ * An object that implement a setTextContent( String ) method in order
+ * to set the content of a given text field.
+ */
+CurrentDateTimeProvider.prototype.update = function( aDateTimeField )
+{
+ var sText = this.createDateTimeText();
+ aDateTimeField.setTextContent( sText );
+};
+
+/*** private methods ***/
+
+CurrentDateTimeProvider.prototype.createDateTimeText = function()
+{
+ // TODO handle date/time format
+ var sDate;
+ if( this.dateTimeFormat === '<date>' )
+ sDate = new Date().toLocaleDateString();
+ else if( this.dateTimeFormat === '<time>' )
+ sDate = new Date().toLocaleTimeString();
+ else
+ sDate = new Date().toLocaleDateString();
+ return sDate;
+};
+
+/** Class SlideNumberProvider
+ * Provides the text content to the related text field by generating
+ * the current page number in the given page numbering type.
+ */
+function SlideNumberProvider( nInitialSlideNumber, sPageNumberingType )
+{
+ SlideNumberProvider.superclass.constructor.call( this );
+ this.nInitialSlideNumber = nInitialSlideNumber;
+ this.pageNumberingType = sPageNumberingType;
+
+}
+extend( SlideNumberProvider, TextFieldContentProvider );
+
+/*** public methods ***/
+
+/** getNumberingType
+ *
+ * @return
+ * The page numbering type.
+ */
+SlideNumberProvider.prototype.getNumberingType = function()
+{
+ return this.pageNumberingType;
+};
+
+/** update
+ * Set up the content of a slide number field.
+ *
+ * @param aSlideNumberField
+ * An object that implement a setTextContent( String ) method in order
+ * to set the content of a given text field.
+ * @param nSlideNumber
+ * An integer representing the slide number.
+ */
+
+SlideNumberProvider.prototype.update = function( aSlideNumberField, nSlideNumber )
+{
+ if( nSlideNumber === undefined )
+ {
+ if( nCurSlide === undefined )
+ nSlideNumber = this.nInitialSlideNumber;
+ else
+ nSlideNumber = nCurSlide + 1;
+ }
+ var sText = this.createSlideNumberText( nSlideNumber, this.getNumberingType() );
+ aSlideNumberField.setTextContent( sText );
+};
+
+/*** private methods ***/
+
+SlideNumberProvider.prototype.createSlideNumberText = function( nSlideNumber /*, sNumberingType*/ )
+{
+ // TODO handle page numbering type
+ return String( nSlideNumber );
+};
+
+
+
+
+/********************************
+ ** Slide Index Classes **
+ ********************************/
+
+/** Class SlideIndexPage **
+ * This class is responsible for handling the slide index page
+ */
+function SlideIndexPage()
+{
+ this.pageElementId = 'slide_index';
+ this.pageBgColor = 'rgb(252,252,252)';
+ this.pageElement = this.createPageElement();
+ assert( this.pageElement, 'SlideIndexPage: pageElement is not valid' );
+ this.indexColumns = INDEX_COLUMNS_DEFAULT;
+ this.totalThumbnails = this.indexColumns * this.indexColumns;
+ this.selectedSlideIndex = undefined;
+
+ // set up layout parameters
+ this.xSpacingFactor = 600/28000;
+ this.ySpacingFactor = 450/21000;
+ this.xSpacing = WIDTH * this.xSpacingFactor;
+ this.ySpacing = HEIGHT * this.ySpacingFactor;
+ this.halfBorderWidthFactor = ( 300/28000 ) * ( this.indexColumns / 3 );
+ this.halfBorderWidth = WIDTH * this.halfBorderWidthFactor;
+ this.borderWidth = 2 * this.halfBorderWidth;
+ // the following formula is used to compute the slide shrinking factor:
+ // scaleFactor = ( WIDTH - ( columns + 1 ) * xSpacing ) / ( columns * ( WIDTH + borderWidth ) )
+ // indeed we can divide everything by WIDTH:
+ this.scaleFactor = ( 1 - ( this.indexColumns + 1 ) * this.xSpacingFactor ) /
+ ( this.indexColumns * ( 1 + 2 * this.halfBorderWidthFactor ) );
+
+ // We create a Thumbnail Border and Thumbnail MouseArea rectangle template that will be
+ // used by every Thumbnail. The Mouse Area rectangle is used in order to trigger the
+ // mouseover event properly even when the slide background is hidden.
+ this.thumbnailMouseAreaTemplateId = 'thumbnail_mouse_area';
+ this.thumbnailMouseAreaTemplateElement = null;
+ this.thumbnailBorderTemplateId = 'thumbnail_border';
+ this.thumbnailBorderTemplateElement = null;
+ this.createTemplateElements();
+
+ // Now we create the grid of thumbnails
+ this.aThumbnailSet = new Array( this.totalThumbnails );
+ for( var i = 0; i < this.totalThumbnails; ++i )
+ {
+ this.aThumbnailSet[i] = new Thumbnail( this, i );
+ this.aThumbnailSet[i].updateView();
+ }
+
+ this.curThumbnailIndex = 0;
+}
+
+
+/* public methods */
+SlideIndexPage.prototype.getTotalThumbnails = function()
+{
+ return this.totalThumbnails;
+};
+
+SlideIndexPage.prototype.show = function()
+{
+ this.pageElement.setAttribute( 'display', 'inherit' );
+};
+
+SlideIndexPage.prototype.hide = function()
+{
+ this.pageElement.setAttribute( 'display', 'none' );
+};
+
+/** setSelection
+ *
+ * Change the selected thumbnail from the current one to the thumbnail with index nIndex.
+ *
+ * @param nIndex - the thumbnail index
+ */
+SlideIndexPage.prototype.setSelection = function( nIndex )
+{
+ nIndex = getSafeIndex( nIndex, 0, this.getTotalThumbnails() - 1 );
+ if( this.curThumbnailIndex != nIndex )
+ {
+ this.aThumbnailSet[ this.curThumbnailIndex ].unselect();
+ this.aThumbnailSet[ nIndex ].select();
+ this.curThumbnailIndex = nIndex;
+ }
+ this.selectedSlideIndex = this.aThumbnailSet[ nIndex ].slideIndex;
+};
+
+SlideIndexPage.prototype.createPageElement = function()
+{
+ var aPageElement = document.createElementNS( NSS['svg'], 'g' );
+ aPageElement.setAttribute( 'id', this.pageElementId );
+ aPageElement.setAttribute( 'display', 'none' );
+ aPageElement.setAttribute( 'visibility', 'visible' );
+
+ // the slide index page background
+ var sPageBgColor = this.pageBgColor + ';';
+ var aRectElement = document.createElementNS( NSS['svg'], 'rect' );
+ aRectElement.setAttribute( 'x', 0 );
+ aRectElement.setAttribute( 'y', 0 );
+ aRectElement.setAttribute( 'width', WIDTH );
+ aRectElement.setAttribute( 'height', HEIGHT );
+ aRectElement.setAttribute( 'style', 'stroke:none;fill:' + sPageBgColor );
+
+ aPageElement.appendChild( aRectElement );
+ // The index page is appended after all slide elements
+ // so when it is displayed it covers them all
+ ROOT_NODE.appendChild( aPageElement );
+ return( document.getElementById( this.pageElementId ) );
+};
+
+SlideIndexPage.prototype.createTemplateElements = function()
+{
+ // We define a Rect element as a template of thumbnail border for all slide-thumbnails.
+ // The stroke color is defined individually by each thumbnail according to
+ // its selection status.
+ var aDefsElement = document.createElementNS( NSS['svg'], 'defs' );
+ var aRectElement = document.createElementNS( NSS['svg'], 'rect' );
+ aRectElement.setAttribute( 'id', this.thumbnailBorderTemplateId );
+ aRectElement.setAttribute( 'x', -this.halfBorderWidth );
+ aRectElement.setAttribute( 'y', -this.halfBorderWidth );
+ aRectElement.setAttribute( 'rx', this.halfBorderWidth );
+ aRectElement.setAttribute( 'ry', this.halfBorderWidth );
+ aRectElement.setAttribute( 'width', WIDTH + this.halfBorderWidth );
+ aRectElement.setAttribute( 'height', HEIGHT + this.halfBorderWidth );
+ aRectElement.setAttribute( 'stroke-width', this.borderWidth );
+ aRectElement.setAttribute( 'fill', 'none' );
+ aDefsElement.appendChild( aRectElement );
+
+ // We define a Rect element as a template of mouse area for triggering the mouseover event.
+ // A copy is used by each thumbnail element.
+ aRectElement = document.createElementNS( NSS['svg'], 'rect' );
+ aRectElement.setAttribute( 'id', this.thumbnailMouseAreaTemplateId );
+ aRectElement.setAttribute( 'x', 0 );
+ aRectElement.setAttribute( 'y', 0 );
+ aRectElement.setAttribute( 'width', WIDTH );
+ aRectElement.setAttribute( 'height', HEIGHT );
+ aRectElement.setAttribute( 'fill', this.pageBgColor );
+ aDefsElement.appendChild( aRectElement );
+
+ this.pageElement.appendChild( aDefsElement );
+
+ this.thumbnailMouseAreaTemplateElement = document.getElementById( this.thumbnailMouseAreaTemplateId );
+ this.thumbnailBorderTemplateElement = document.getElementById( this.thumbnailBorderTemplateId );
+};
+
+SlideIndexPage.prototype.decreaseNumberOfColumns = function()
+{
+ this.setNumberOfColumns( this.indexColumns - 1 );
+};
+
+SlideIndexPage.prototype.increaseNumberOfColumns = function()
+{
+ this.setNumberOfColumns( this.indexColumns + 1 );
+};
+
+SlideIndexPage.prototype.resetNumberOfColumns = function()
+{
+ this.setNumberOfColumns( INDEX_COLUMNS_DEFAULT );
+};
+
+/** setNumberOfColumns
+ *
+ * Change the size of the thumbnail grid.
+ *
+ * @param nNumberOfColumns - the new number of columns/rows of the thumbnail grid
+ */
+SlideIndexPage.prototype.setNumberOfColumns = function( nNumberOfColumns )
+{
+ if( this.indexColumns == nNumberOfColumns ) return;
+ if( nNumberOfColumns < 2 || nNumberOfColumns > 6 ) return;
+
+ var suspendHandle = ROOT_NODE.suspendRedraw(500);
+
+ var nOldTotalThumbnails = this.totalThumbnails;
+ this.indexColumns = nNumberOfColumns;
+ this.totalThumbnails = nNumberOfColumns * nNumberOfColumns;
+
+ this.aThumbnailSet[this.curThumbnailIndex].unselect();
+
+ // if we decreased the number of used columns we remove the exceeding thumbnail elements
+ var i;
+ for( i = this.totalThumbnails; i < nOldTotalThumbnails; ++i )
+ {
+ this.aThumbnailSet[i].removeElement();
+ }
+
+ // if we increased the number of used columns we create the needed thumbnail objects
+ for( i = nOldTotalThumbnails; i < this.totalThumbnails; ++i )
+ {
+ this.aThumbnailSet[i] = new Thumbnail( this, i );
+ }
+
+ // we set up layout parameters that depend on the number of columns
+ this.halfBorderWidthFactor = ( 300/28000 ) * ( this.indexColumns / 3 );
+ this.halfBorderWidth = WIDTH * this.halfBorderWidthFactor;
+ this.borderWidth = 2 * this.halfBorderWidth;
+ // scaleFactor = ( WIDTH - ( columns + 1 ) * xSpacing ) / ( columns * ( WIDTH + borderWidth ) )
+ this.scaleFactor = ( 1 - ( this.indexColumns + 1 ) * this.xSpacingFactor ) /
+ ( this.indexColumns * ( 1 + 2 * this.halfBorderWidthFactor ) );
+
+ // update the thumbnail border size
+ var aRectElement = this.thumbnailBorderTemplateElement;
+ aRectElement.setAttribute( 'x', -this.halfBorderWidth );
+ aRectElement.setAttribute( 'y', -this.halfBorderWidth );
+ aRectElement.setAttribute( 'rx', this.halfBorderWidth );
+ aRectElement.setAttribute( 'ry', this.halfBorderWidth );
+ aRectElement.setAttribute( 'width', WIDTH + this.halfBorderWidth );
+ aRectElement.setAttribute( 'height', HEIGHT + this.halfBorderWidth );
+ aRectElement.setAttribute( 'stroke-width', this.borderWidth );
+
+ // now we update the displacement on the index page of each thumbnail (old and new)
+ for( i = 0; i < this.totalThumbnails; ++i )
+ {
+ this.aThumbnailSet[i].updateView();
+ }
+
+ this.curThumbnailIndex = this.selectedSlideIndex % this.totalThumbnails;
+ this.aThumbnailSet[this.curThumbnailIndex].select();
+
+ // needed for forcing the indexSetPageSlide routine to update the INDEX_OFFSET
+ INDEX_OFFSET = -1;
+ indexSetPageSlide( this.selectedSlideIndex );
+
+ ROOT_NODE.unsuspendRedraw( suspendHandle );
+ ROOT_NODE.forceRedraw();
+};
+
+
+/** Class Thumbnail **
+ * This class handles a slide thumbnail.
+ */
+function Thumbnail( aSlideIndexPage, nIndex )
+{
+ this.container = aSlideIndexPage;
+ this.index = nIndex;//= getSafeIndex( nIndex, 0, this.container.getTotalThumbnails() );
+ this.pageElement = this.container.pageElement;
+ this.thumbnailId = 'thumbnail' + this.index;
+ this.thumbnailElement = this.createThumbnailElement();
+ this.slideElement = getElementByClassName( this.thumbnailElement, 'Slide' );
+ this.borderElement = getElementByClassName( this.thumbnailElement, 'Border' );
+ this.mouseAreaElement = getElementByClassName( this.thumbnailElement, 'MouseArea' );
+ this.aTransformSet = new Array( 3 );
+ this.visibility = VISIBLE;
+ this.isSelected = false;
+}
+
+/* static const class member */
+Thumbnail.prototype.sNormalBorderColor = 'rgb(216,216,216)';
+Thumbnail.prototype.sSelectionBorderColor = 'rgb(92,92,255)';
+
+/* public methods */
+Thumbnail.prototype.removeElement = function()
+{
+ if( this.thumbnailElement )
+ this.container.pageElement.removeChild( this.thumbnailElement );
+};
+
+Thumbnail.prototype.show = function()
+{
+ if( this.visibility == HIDDEN )
+ {
+ this.thumbnailElement.setAttribute( 'display', 'inherit' );
+ this.visibility = VISIBLE;
+ }
+};
+
+Thumbnail.prototype.hide = function()
+{
+ if( this.visibility == VISIBLE )
+ {
+ this.thumbnailElement.setAttribute( 'display', 'none' );
+ this.visibility = HIDDEN;
+ }
+};
+
+Thumbnail.prototype.select = function()
+{
+ if( !this.isSelected )
+ {
+ this.borderElement.setAttribute( 'stroke', this.sSelectionBorderColor );
+ this.isSelected = true;
+ }
+};
+
+Thumbnail.prototype.unselect = function()
+{
+ if( this.isSelected )
+ {
+ this.borderElement.setAttribute( 'stroke', this.sNormalBorderColor );
+ this.isSelected = false;
+ }
+};
+
+/** updateView
+ *
+ * This method updates the displacement of the thumbnail on the slide index page,
+ * the value of the row, column coordinates of the thumbnail in the grid, and
+ * the onmouseover property of the thumbnail element.
+ *
+ */
+Thumbnail.prototype.updateView = function()
+{
+ this.column = this.index % this.container.indexColumns;
+ this.row = ( this.index - this.column ) / this.container.indexColumns;
+ this.halfBorderWidth = this.container.halfBorderWidth;
+ this.borderWidth = this.container.borderWidth;
+ this.width = ( WIDTH + this.borderWidth ) * this.container.scaleFactor;
+ this.height = ( HEIGHT + this.borderWidth ) * this.container.scaleFactor;
+ this.aTransformSet[2] = 'translate(' + this.halfBorderWidth + ' ' + this.halfBorderWidth + ')';
+ this.aTransformSet[1] = 'scale(' + this.container.scaleFactor + ')';
+ var sTransformAttrValue = this.computeTransform();
+ this.thumbnailElement.setAttribute( 'transform', sTransformAttrValue );
+ this.mouseAreaElement.setAttribute( 'onmouseover', 'theSlideIndexPage.aThumbnailSet[' + this.index + '].onMouseOver()' );
+};
+
+/** update
+ *
+ * This method update the content of the thumbnail view
+ *
+ * @param nIndex - the index of the slide to be shown in the thumbnail
+ */
+Thumbnail.prototype.update = function( nIndex )
+{
+ if( this.slideIndex == nIndex ) return;
+
+ var aMetaSlide = theMetaDoc.aMetaSlideSet[nIndex];
+ aMetaSlide.updateMasterPageView();
+ setNSAttribute( 'xlink', this.slideElement, 'href', '#' + aMetaSlide.slideId );
+ this.slideIndex = nIndex;
+};
+
+Thumbnail.prototype.clear = function( )
+{
+ setNSAttribute( 'xlink', this.slideElement, 'href', '' );
+};
+
+/* private methods */
+Thumbnail.prototype.createThumbnailElement = function()
+{
+ var aThumbnailElement = document.createElementNS( NSS['svg'], 'g' );
+ aThumbnailElement.setAttribute( 'id', this.thumbnailId );
+ aThumbnailElement.setAttribute( 'display', 'inherit' );
+
+ var aSlideElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aSlideElement, 'href', '' );
+ aSlideElement.setAttribute( 'class', 'Slide' );
+ aThumbnailElement.appendChild( aSlideElement );
+
+ var aMouseAreaElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aMouseAreaElement, 'href', '#' + this.container.thumbnailMouseAreaTemplateId );
+ aMouseAreaElement.setAttribute( 'class', 'MouseArea' );
+ aMouseAreaElement.setAttribute( 'opacity', 0.0 );
+ aThumbnailElement.appendChild( aMouseAreaElement );
+
+ var aBorderElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', aBorderElement, 'href', '#' + this.container.thumbnailBorderTemplateId );
+ aBorderElement.setAttribute( 'stroke', this.sNormalBorderColor );
+ aBorderElement.setAttribute( 'class', 'Border' );
+ aThumbnailElement.appendChild( aBorderElement );
+
+ this.container.pageElement.appendChild( aThumbnailElement );
+ return( document.getElementById( this.thumbnailId ) );
+};
+
+Thumbnail.prototype.computeTransform = function()
+{
+ var nXSpacing = this.container.xSpacing;
+ var nYSpacing = this.container.ySpacing;
+
+ var nXOffset = nXSpacing + ( this.width + nXSpacing ) * this.column;
+ var nYOffset = nYSpacing + ( this.height + nYSpacing ) * this.row;
+
+ this.aTransformSet[0] = 'translate(' + nXOffset + ' ' + nYOffset + ')';
+
+ var sTransform = this.aTransformSet.join( ' ' );
+
+ return sTransform;
+};
+
+Thumbnail.prototype.onMouseOver = function()
+{
+ if( ( currentMode == INDEX_MODE ) && ( this.container.curThumbnailIndex != this.index ) )
+ {
+ this.container.setSelection( this.index );
+ }
+};
+
+
+
+
+
+/** Initialization function.
+ * The whole presentation is set-up in this function.
+ */
+function init()
+{
+ var VIEWBOX = ROOT_NODE.getAttribute('viewBox');
+
+ if( VIEWBOX )
+ {
+ WIDTH = ROOT_NODE.viewBox.animVal.width;
+ HEIGHT = ROOT_NODE.viewBox.animVal.height;
+ }
+
+ aSlideShow = new SlideShow();
+ theMetaDoc = new MetaDocument();
+ aSlideShow.bIsEnabled = theMetaDoc.bIsAnimated;
+ theSlideIndexPage = new SlideIndexPage();
+ aSlideShow.displaySlide( theMetaDoc.nStartSlideNumber, false );
+
+ // Allow slide switching with swipe gestures left
+ // and right. Swiping up or down will exit the slideshow.
+ var hammer = new Hammer(ROOT_NODE);
+ hammer.on('swipeleft', function() {
+ switchSlide(1, false);
+ });
+ hammer.on('swiperight', function() {
+ switchSlide(-1, false);
+ });
+ hammer.get('swipe').set({ direction: Hammer.DIRECTION_ALL });
+ hammer.on('swipeup', function() {
+ aSlideShow.exitSlideShowInApp();
+ });
+ hammer.on('swipedown', function() {
+ aSlideShow.exitSlideShowInApp();
+ });
+}
+
+function presentationEngineStop(message)
+{
+ alert( message + '\nThe presentation engine will be stopped' );
+ document.onkeydown = null;
+ document.onkeypress = null;
+ document.onclick = null;
+ window.onmousewheel = null;
+}
+
+function assert( condition, message )
+{
+ if (!condition)
+ {
+ presentationEngineStop( message );
+ if (typeof console == 'object')
+ // eslint-disable-next-line no-console
+ console.trace();
+ throw new Error( message );
+ }
+}
+
+function dispatchEffects(dir)
+{
+ // TODO to be implemented
+
+ if( dir == 1 )
+ {
+ var bRet = aSlideShow.nextEffect();
+
+ if( !bRet )
+ {
+ switchSlide( 1, false );
+ }
+ }
+ else
+ {
+ switchSlide( dir, false );
+ }
+}
+
+function skipAllEffects()
+{
+ var bRet = aSlideShow.skipAllEffects();
+ if( !bRet )
+ {
+ switchSlide( 1, true );
+ }
+}
+
+function skipEffects(dir)
+{
+ if( dir == 1 )
+ {
+ var bRet = aSlideShow.skipPlayingOrNextEffect();
+
+ if( !bRet )
+ {
+ switchSlide( 1, true );
+ }
+ }
+ else
+ {
+ switchSlide( dir, true );
+ }
+}
+
+function switchSlide( nOffset, bSkipTransition )
+{
+ var nNextSlide = nCurSlide + nOffset;
+ aSlideShow.displaySlide( nNextSlide, bSkipTransition );
+}
+
+/** Function to display the index sheet.
+ *
+ * @param offsetNumber offset number
+ */
+function displayIndex( offsetNumber )
+{
+ var aMetaSlideSet = theMetaDoc.aMetaSlideSet;
+ offsetNumber = getSafeIndex( offsetNumber, 0, aMetaSlideSet.length - 1 );
+
+ var nTotalThumbnails = theSlideIndexPage.getTotalThumbnails();
+ var nEnd = Math.min( offsetNumber + nTotalThumbnails, aMetaSlideSet.length);
+
+ var aThumbnailSet = theSlideIndexPage.aThumbnailSet;
+ var j = 0;
+ for( var i = offsetNumber; i < nEnd; ++i, ++j )
+ {
+ aThumbnailSet[j].update( i );
+ aThumbnailSet[j].show();
+ }
+ for( ; j < nTotalThumbnails; ++j )
+ {
+ aThumbnailSet[j].hide();
+ }
+
+ //do we need to save the current offset?
+ if (INDEX_OFFSET != offsetNumber)
+ INDEX_OFFSET = offsetNumber;
+}
+
+/** Function to toggle between index and slide mode.
+ */
+function toggleSlideIndex()
+{
+ if( currentMode == SLIDE_MODE )
+ {
+
+ theMetaDoc.getCurrentSlide().hide();
+ INDEX_OFFSET = -1;
+ indexSetPageSlide( nCurSlide );
+ theSlideIndexPage.show();
+ currentMode = INDEX_MODE;
+ }
+ else if( currentMode == INDEX_MODE )
+ {
+ theSlideIndexPage.hide();
+ var nNewSlide = theSlideIndexPage.selectedSlideIndex;
+
+ aSlideShow.displaySlide( nNewSlide, true );
+ currentMode = SLIDE_MODE;
+ }
+}
+
+/** Function that exit from the index mode without changing the shown slide
+ *
+ */
+function abandonIndexMode()
+{
+ theSlideIndexPage.selectedSlideIndex = nCurSlide;
+ toggleSlideIndex();
+}
+
+
+
+
+
+/*********************************************************************************************
+ *********************************************************************************************
+ *********************************************************************************************
+
+ ***** ANIMATION ENGINE *****
+
+ *********************************************************************************************
+ *********************************************************************************************
+ *********************************************************************************************/
+
+
+
+
+
+
+// helper functions
+
+
+var CURR_UNIQUE_ID = 0;
+
+function getUniqueId()
+{
+ ++CURR_UNIQUE_ID;
+ return CURR_UNIQUE_ID;
+}
+
+function mem_fn( sMethodName )
+{
+ return function( aObject )
+ {
+ var aMethod = aObject[ sMethodName ];
+ if( aMethod )
+ aMethod.call( aObject );
+ else
+ log( 'method sMethodName not found' );
+ };
+}
+
+function bind( aObject, aMethod )
+{
+ return function()
+ {
+ return aMethod.call( aObject, arguments[0] );
+ };
+}
+
+function bind2( aFunction )
+{
+ if( !aFunction )
+ log( 'bind2: passed function is not valid.' );
+
+ var aBoundArgList = arguments;
+
+ var aResultFunction = null;
+
+ switch( aBoundArgList.length )
+ {
+ case 1: aResultFunction = function()
+ {
+ return aFunction.call( arguments[0], arguments[1],
+ arguments[2], arguments[3],
+ arguments[4] );
+ };
+ break;
+ case 2: aResultFunction = function()
+ {
+ return aFunction.call( aBoundArgList[1], arguments[0],
+ arguments[1], arguments[2],
+ arguments[3] );
+ };
+ break;
+ case 3: aResultFunction = function()
+ {
+ return aFunction.call( aBoundArgList[1], aBoundArgList[2],
+ arguments[0], arguments[1],
+ arguments[2] );
+ };
+ break;
+ case 4: aResultFunction = function()
+ {
+ return aFunction.call( aBoundArgList[1], aBoundArgList[2],
+ aBoundArgList[3], arguments[0],
+ arguments[1] );
+ };
+ break;
+ case 5: aResultFunction = function()
+ {
+ return aFunction.call( aBoundArgList[1], aBoundArgList[2],
+ aBoundArgList[3], aBoundArgList[4],
+ arguments[0] );
+ };
+ break;
+ default:
+ log( 'bind2: arity not handled.' );
+ }
+
+ return aResultFunction;
+}
+
+function getCurrentSystemTime()
+{
+ return ( new Date() ).getTime();
+}
+
+// eslint-disable-next-line no-unused-vars
+function getSlideAnimationsRoot( sSlideId )
+{
+ return theMetaDoc.aSlideAnimationsMap[ sSlideId ];
+}
+
+/** This function return an array populated with all children nodes of the
+ * passed element that are elements
+ *
+ * @param aElement any XML element
+ *
+ * @returns Array
+ * an array that contains all children elements
+ */
+function getElementChildren( aElement )
+{
+ var aChildrenArray = [];
+
+ var nSize = aElement.childNodes.length;
+
+ for( var i = 0; i < nSize; ++i )
+ {
+ if( aElement.childNodes[i].nodeType == 1 )
+ aChildrenArray.push( aElement.childNodes[i] );
+ }
+
+ return aChildrenArray;
+}
+
+function removeWhiteSpaces( str )
+{
+ if( !str )
+ return '';
+
+ var re = / */;
+ var aSplitString = str.split( re );
+ return aSplitString.join('');
+}
+
+function clamp( nValue, nMinimum, nMaximum )
+{
+ if( nValue < nMinimum )
+ {
+ return nMinimum;
+ }
+ else if( nValue > nMaximum )
+ {
+ return nMaximum;
+ }
+ else
+ {
+ return nValue;
+ }
+}
+
+function makeMatrixString( a, b, c, d, e, f )
+{
+ var s = 'matrix(';
+ s += a + ', ';
+ s += b + ', ';
+ s += c + ', ';
+ s += d + ', ';
+ s += e + ', ';
+ s += f + ')';
+
+ return s;
+}
+
+// eslint-disable-next-line no-unused-vars
+function matrixToString( aSVGMatrix )
+{
+ return makeMatrixString( aSVGMatrix.a, aSVGMatrix.b, aSVGMatrix.c,
+ aSVGMatrix.d, aSVGMatrix.e, aSVGMatrix.f );
+}
+
+
+
+
+// Attribute Parsers
+
+// eslint-disable-next-line no-unused-vars
+function numberParser( sValue )
+{
+ if( typeof sValue !== 'string' )
+ return undefined;
+ if( sValue === '.' )
+ return undefined;
+ var reFloatNumber = /^[+-]?[0-9]*[.]?[0-9]*$/;
+
+ if( reFloatNumber.test( sValue ) )
+ return parseFloat( sValue );
+ else
+ return undefined;
+}
+
+function booleanParser( sValue )
+{
+ if( typeof sValue !== 'string' )
+ return undefined;
+
+ sValue = sValue.toLowerCase();
+ if( sValue === 'true' )
+ return true;
+ else if( sValue === 'false' )
+ return false;
+ else
+ return undefined;
+}
+
+function colorParser( sValue )
+{
+ if( typeof sValue !== 'string' )
+ return undefined;
+
+ // The following 3 color functions are used in evaluating sValue string
+ // so don't remove them.
+
+ // eslint-disable-next-line no-unused-vars
+ function hsl( nHue, nSaturation, nLuminance )
+ {
+ return new HSLColor( nHue, nSaturation / 100, nLuminance / 100 );
+ }
+
+ // eslint-disable-next-line no-unused-vars
+ function rgb( nRed, nGreen, nBlue )
+ {
+ return new RGBColor( nRed / 255, nGreen / 255, nBlue / 255 );
+ }
+
+ // eslint-disable-next-line no-unused-vars
+ function prgb( nRed, nGreen, nBlue )
+ {
+ return new RGBColor( nRed / 100, nGreen / 100, nBlue / 100 );
+ }
+
+ var sCommaPattern = ' *[,] *';
+ var sIntegerPattern = '[+-]?[0-9]+';
+ var sHexDigitPattern = '[0-9A-Fa-f]';
+
+ var sHexColorPattern = '#(' + sHexDigitPattern + '{2})('
+ + sHexDigitPattern + '{2})('
+ + sHexDigitPattern + '{2})';
+
+ var sRGBIntegerPattern = 'rgb[(] *' + sIntegerPattern + sCommaPattern
+ + sIntegerPattern + sCommaPattern
+ + sIntegerPattern + ' *[)]';
+
+ var sRGBPercentPattern = 'rgb[(] *' + sIntegerPattern + '%' + sCommaPattern
+ + sIntegerPattern + '%' + sCommaPattern
+ + sIntegerPattern + '%' + ' *[)]';
+
+ var sHSLPercentPattern = 'hsl[(] *' + sIntegerPattern + sCommaPattern
+ + sIntegerPattern + '%' + sCommaPattern
+ + sIntegerPattern + '%' + ' *[)]';
+
+ var reHexColor = new RegExp( sHexColorPattern );
+ var reRGBInteger = new RegExp( sRGBIntegerPattern );
+ var reRGBPercent = new RegExp( sRGBPercentPattern );
+ var reHSLPercent = new RegExp( sHSLPercentPattern );
+
+ if( reHexColor.test( sValue ) )
+ {
+ var aRGBTriple = reHexColor.exec( sValue );
+
+ var nRed = parseInt( aRGBTriple[1], 16 ) / 255;
+ var nGreen = parseInt( aRGBTriple[2], 16 ) / 255;
+ var nBlue = parseInt( aRGBTriple[3], 16 ) / 255;
+
+ return new RGBColor( nRed, nGreen, nBlue );
+ }
+ else if( reHSLPercent.test( sValue ) )
+ {
+ sValue = sValue.replace( '%', '' ).replace( '%', '' );
+ return eval( sValue );
+ }
+ else if( reRGBInteger.test( sValue ) )
+ {
+ return eval( sValue );
+ }
+ else if( reRGBPercent.test( sValue ) )
+ {
+ sValue = 'p' + sValue.replace( '%', '' ).replace( '%', '' ).replace( '%', '' );
+ return eval( sValue );
+ }
+ else
+ {
+ return null;
+ }
+}
+
+
+
+/**********************************************************************************************
+ * RGB and HSL color classes
+ **********************************************************************************************/
+
+
+function RGBColor( nRed, nGreen, nBlue )
+{
+ this.eColorSpace = COLOR_SPACE_RGB;
+ // values in the [0,1] range
+ this.nRed = nRed;
+ this.nGreen = nGreen;
+ this.nBlue = nBlue;
+}
+
+
+RGBColor.prototype.clone = function()
+{
+ return new RGBColor( this.nRed, this.nGreen, this.nBlue );
+};
+
+RGBColor.prototype.equal = function( aRGBColor )
+{
+ return ( this.nRed == aRGBColor.nRed ) &&
+ ( this.nGreen == aRGBColor.nGreen ) &&
+ ( this.nBlue == aRGBColor.nBlue );
+};
+
+RGBColor.prototype.add = function( aRGBColor )
+{
+ this.nRed += aRGBColor.nRed;
+ this.nGreen += aRGBColor.nGreen;
+ this.nBlue += aRGBColor.nBlue;
+ return this;
+};
+
+RGBColor.prototype.scale = function( aT )
+{
+ this.nRed *= aT;
+ this.nGreen *= aT;
+ this.nBlue *= aT;
+ return this;
+};
+
+RGBColor.clamp = function( aRGBColor )
+{
+ var aClampedRGBColor = new RGBColor( 0, 0, 0 );
+
+ aClampedRGBColor.nRed = clamp( aRGBColor.nRed, 0.0, 1.0 );
+ aClampedRGBColor.nGreen = clamp( aRGBColor.nGreen, 0.0, 1.0 );
+ aClampedRGBColor.nBlue = clamp( aRGBColor.nBlue, 0.0, 1.0 );
+
+ return aClampedRGBColor;
+};
+
+RGBColor.prototype.convertToHSL = function()
+{
+ var nRed = clamp( this.nRed, 0.0, 1.0 );
+ var nGreen = clamp( this.nGreen, 0.0, 1.0 );
+ var nBlue = clamp( this.nBlue, 0.0, 1.0 );
+
+ var nMax = Math.max( nRed, nGreen, nBlue );
+ var nMin = Math.min( nRed, nGreen, nBlue );
+ var nDelta = nMax - nMin;
+
+ var nLuminance = ( nMax + nMin ) / 2.0;
+ var nSaturation = 0.0;
+ var nHue = 0.0;
+ if( nDelta !== 0 )
+ {
+ nSaturation = ( nLuminance > 0.5 ) ?
+ ( nDelta / ( 2.0 - nMax - nMin) ) :
+ ( nDelta / ( nMax + nMin ) );
+
+ if( nRed == nMax )
+ nHue = ( nGreen - nBlue ) / nDelta;
+ else if( nGreen == nMax )
+ nHue = 2.0 + ( nBlue - nRed ) / nDelta;
+ else if( nBlue == nMax )
+ nHue = 4.0 + ( nRed - nGreen ) / nDelta;
+
+ nHue *= 60.0;
+
+ if( nHue < 0.0 )
+ nHue += 360.0;
+ }
+
+ return new HSLColor( nHue, nSaturation, nLuminance );
+
+};
+
+RGBColor.prototype.toString = function( bClamped )
+{
+ var aRGBColor;
+ if( bClamped )
+ {
+ aRGBColor = RGBColor.clamp( this );
+ }
+ else
+ {
+ aRGBColor = this;
+ }
+
+ var nRed = Math.round( aRGBColor.nRed * 255 );
+ var nGreen = Math.round( aRGBColor.nGreen * 255 );
+ var nBlue = Math.round( aRGBColor.nBlue * 255 );
+
+ return ( 'rgb(' + nRed + ',' + nGreen + ',' + nBlue + ')' );
+};
+
+RGBColor.interpolate = function( aStartRGB , aEndRGB, nT )
+{
+ var aResult = aStartRGB.clone();
+ var aTEndRGB = aEndRGB.clone();
+ aResult.scale( 1.0 - nT );
+ aTEndRGB.scale( nT );
+ aResult.add( aTEndRGB );
+
+ return aResult;
+};
+
+
+
+
+function HSLColor( nHue, nSaturation, nLuminance )
+{
+ this.eColorSpace = COLOR_SPACE_HSL;
+ // Hue is in the [0,360[ range, Saturation and Luminance are in the [0,1] range
+ this.nHue = nHue;
+ this.nSaturation = nSaturation;
+ this.nLuminance = nLuminance;
+
+ this.normalizeHue();
+}
+
+
+HSLColor.prototype.clone = function()
+{
+ return new HSLColor( this.nHue, this.nSaturation, this.nLuminance );
+};
+
+HSLColor.prototype.equal = function( aHSLColor )
+{
+ return ( this.nHue == aHSLColor.nHue ) &&
+ ( this.nSaturation += aHSLColor.nSaturation ) &&
+ ( this.nLuminance += aHSLColor.nLuminance );
+};
+
+HSLColor.prototype.add = function( aHSLColor )
+{
+ this.nHue += aHSLColor.nHue;
+ this.nSaturation += aHSLColor.nSaturation;
+ this.nLuminance += aHSLColor.nLuminance;
+ this.normalizeHue();
+ return this;
+};
+
+HSLColor.prototype.scale = function( aT )
+{
+ this.nHue *= aT;
+ this.nSaturation *= aT;
+ this.nLuminance *= aT;
+ this.normalizeHue();
+ return this;
+};
+
+HSLColor.clamp = function( aHSLColor )
+{
+ var aClampedHSLColor = new HSLColor( 0, 0, 0 );
+
+ aClampedHSLColor.nHue = aHSLColor.nHue % 360;
+ if( aClampedHSLColor.nHue < 0 )
+ aClampedHSLColor.nHue += 360;
+ aClampedHSLColor.nSaturation = clamp( aHSLColor.nSaturation, 0.0, 1.0 );
+ aClampedHSLColor.nLuminance = clamp( aHSLColor.nLuminance, 0.0, 1.0 );
+};
+
+HSLColor.prototype.normalizeHue = function()
+{
+ this.nHue = this.nHue % 360;
+ if( this.nHue < 0 ) this.nHue += 360;
+};
+
+HSLColor.prototype.toString = function()
+{
+ return 'hsl(' + this.nHue.toFixed( 3 ) + ','
+ + this.nSaturation.toFixed( 3 ) + ','
+ + this.nLuminance.toFixed( 3 ) + ')';
+};
+
+HSLColor.prototype.convertToRGB = function()
+{
+
+ var nHue = this.nHue % 360;
+ if( nHue < 0 ) nHue += 360;
+ var nSaturation = clamp( this.nSaturation, 0.0, 1.0 );
+ var nLuminance = clamp( this.nLuminance, 0.0, 1.0 );
+
+
+ if( nSaturation === 0 )
+ {
+ return new RGBColor( nLuminance, nLuminance, nLuminance );
+ }
+
+ var nVal1 = ( nLuminance <= 0.5 ) ?
+ ( nLuminance * (1.0 + nSaturation) ) :
+ ( nLuminance + nSaturation - nLuminance * nSaturation );
+
+ var nVal2 = 2.0 * nLuminance - nVal1;
+
+ var nRed = HSLColor.hsl2rgbHelper( nVal2, nVal1, nHue + 120 );
+ var nGreen = HSLColor.hsl2rgbHelper( nVal2, nVal1, nHue );
+ var nBlue = HSLColor.hsl2rgbHelper( nVal2, nVal1, nHue - 120 );
+
+ return new RGBColor( nRed, nGreen, nBlue );
+};
+
+HSLColor.hsl2rgbHelper = function( nValue1, nValue2, nHue )
+{
+ nHue = nHue % 360;
+ if( nHue < 0 )
+ nHue += 360;
+
+ if( nHue < 60.0 )
+ return nValue1 + ( nValue2 - nValue1 ) * nHue / 60.0;
+ else if( nHue < 180.0 )
+ return nValue2;
+ else if( nHue < 240.0 )
+ return ( nValue1 + ( nValue2 - nValue1 ) * ( 240.0 - nHue ) / 60.0 );
+ else
+ return nValue1;
+};
+
+HSLColor.interpolate = function( aFrom, aTo, nT, bCCW )
+{
+ var nS = 1.0 - nT;
+
+ var nHue = 0.0;
+ if( aFrom.nHue <= aTo.nHue && !bCCW )
+ {
+ // interpolate hue clockwise. That is, hue starts at
+ // high values and ends at low ones. Therefore, we
+ // must 'cross' the 360 degrees and start at low
+ // values again (imagine the hues to lie on the
+ // circle, where values above 360 degrees are mapped
+ // back to [0,360)).
+ nHue = nS * (aFrom.nHue + 360.0) + nT * aTo.nHue;
+ }
+ else if( aFrom.nHue > aTo.nHue && bCCW )
+ {
+ // interpolate hue counter-clockwise. That is, hue
+ // starts at high values and ends at low
+ // ones. Therefore, we must 'cross' the 360 degrees
+ // and start at low values again (imagine the hues to
+ // lie on the circle, where values above 360 degrees
+ // are mapped back to [0,360)).
+ nHue = nS * aFrom.nHue + nT * (aTo.nHue + 360.0);
+ }
+ else
+ {
+ // interpolate hue counter-clockwise. That is, hue
+ // starts at low values and ends at high ones (imagine
+ // the hue value as degrees on a circle, with
+ // increasing values going counter-clockwise)
+ nHue = nS * aFrom.nHue + nT * aTo.nHue;
+ }
+
+ var nSaturation = nS * aFrom.nSaturation + nT * aTo.nSaturation;
+ var nLuminance = nS * aFrom.nLuminance + nT * aTo.nLuminance;
+
+ return new HSLColor( nHue, nSaturation, nLuminance );
+};
+
+
+
+/**********************************************************************************************
+ * SVGMatrix extensions
+ **********************************************************************************************/
+
+var SVGIdentityMatrix = document.documentElement.createSVGMatrix();
+
+SVGMatrix.prototype.setToIdentity = function()
+{
+ this.a = this.d = 1;
+ this.b = this.c = this.d = this.e = 0;
+};
+
+SVGMatrix.prototype.setToRotationAroundPoint = function( nX, nY, nAngle )
+{
+ // convert to radians
+ nAngle = Math.PI * nAngle / 180;
+ var nSin = Math.sin( nAngle );
+ var nCos = Math.cos( nAngle );
+
+ this.a = nCos; this.c = -nSin; this.e = nX * (1 - nCos) + nY * nSin;
+ this.b = nSin; this.d = nCos; this.f = nY * (1 - nCos) - nX * nSin;
+};
+
+
+
+/**********************************************************************************************
+ * SVGPath extensions
+ **********************************************************************************************/
+
+/** SVGPathElement.prependPath
+ * Merge the two path together by inserting the passed path before this one.
+ *
+ * @param aPath
+ * An object of type SVGPathElement to be prepended.
+ */
+SVGPathElement.prototype.prependPath = function( aPath )
+{
+ var sPathData = aPath.getAttribute( 'd' );
+ sPathData += ( ' ' + this.getAttribute( 'd' ) );
+ this.setAttribute( 'd', sPathData );
+};
+
+/** SVGPathElement.appendPath
+ * Merge the two path together by inserting the passed path after this one.
+ *
+ * @param aPath
+ * An object of type SVGPathElement to be appended.
+ */
+SVGPathElement.prototype.appendPath = function( aPath )
+{
+ var sPathData = this.getAttribute( 'd' );
+ sPathData += ( ' ' + aPath.getAttribute( 'd' ) );
+ this.setAttribute( 'd', sPathData );
+};
+
+/** flipOnYAxis
+ * Flips the SVG Path element along y-axis.
+ *
+ * @param aPath
+ * An object of type SVGPathElement to be flipped.
+ */
+function flipOnYAxis( aPath )
+{
+ var aPolyPath = aPath.cloneNode(true);
+ var aTransform = document.documentElement.createSVGMatrix();
+ aTransform.a = -1;
+ aTransform.e = 1;
+ aPolyPath.matrixTransform(aTransform);
+ return aPolyPath;
+}
+
+/** flipOnXAxis
+ * Flips the SVG Path element along x-axis
+ *
+ * @param aPath
+ * An object of type SVGPathElement to be flipped
+ */
+function flipOnXAxis( aPath )
+{
+ var aPolyPath = aPath.cloneNode(true);
+ var aTransform = document.documentElement.createSVGMatrix();
+ aTransform.d = -1;
+ aTransform.f = 1;
+ aPolyPath.matrixTransform(aTransform);
+ return aPolyPath;
+}
+
+/** SVGPathElement.matrixTransform
+ * Apply the transformation defined by the passed matrix to the referenced
+ * svg <path> element.
+ * After the transformation 'this' element is modified in order to reference
+ * the transformed path.
+ *
+ * @param aSVGMatrix
+ * An SVGMatrix instance.
+ */
+SVGPathElement.prototype.matrixTransform = function( aSVGMatrix )
+{
+ if( SVGPathSegList.prototype.matrixTransform )
+ {
+ this.pathSegList.matrixTransform( aSVGMatrix );
+ return;
+ }
+
+ var aPathSegList = this.pathSegList;
+ var nLength = aPathSegList.numberOfItems;
+ var i;
+ for( i = 0; i < nLength; ++i )
+ {
+ aPathSegList.getItem( i ).matrixTransform( aSVGMatrix );
+ }
+};
+
+/** SVGPathElement.changeOrientation
+ * Invert the path orientation by inverting the path command list.
+ *
+ */
+SVGPathElement.prototype.changeOrientation = function()
+{
+ var aPathSegList = this.pathSegList;
+ var nLength = aPathSegList.numberOfItems;
+ if( nLength == 0 ) return;
+
+ if( SVGPathSegList.prototype.changeOrientation )
+ {
+ aPathSegList.changeOrientation();
+ return;
+ }
+
+ var nCurrentX = 0;
+ var nCurrentY = 0;
+
+ var aPathSeg = aPathSegList.getItem( 0 );
+ if( aPathSeg.pathSegTypeAsLetter == 'M' )
+ {
+ nCurrentX = aPathSeg.x;
+ nCurrentY = aPathSeg.y;
+ aPathSegList.removeItem( 0 );
+ --nLength;
+ }
+
+ var i;
+ for( i = 0; i < nLength; ++i )
+ {
+ aPathSeg = aPathSegList.getItem( i );
+ var aPoint = aPathSeg.changeOrientation( nCurrentX, nCurrentY );
+ nCurrentX = aPoint.x;
+ nCurrentY = aPoint.y;
+ }
+
+
+ for( i = nLength - 2; i >= 0; --i )
+ {
+ aPathSeg = aPathSegList.removeItem( i );
+ aPathSegList.appendItem( aPathSeg );
+ }
+
+ var aMovePathSeg = this.createSVGPathSegMovetoAbs( nCurrentX, nCurrentY );
+ aPathSegList.insertItemBefore( aMovePathSeg, 0 );
+
+};
+
+/** matrixTransform and changeOrientation
+ * We implement these methods for each path segment type still present
+ * after the path normalization (M, L, Q, C).
+ *
+ * Note: Opera doesn't have any SVGPathSeg* class and rises an error.
+ * We exploit this fact for providing a different implementation.
+ */
+
+
+try
+{ // Firefox, Google Chrome, Internet Explorer, Safari.
+
+ SVGPathSegMovetoAbs.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ };
+
+ SVGPathSegLinetoAbs.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ };
+
+ SVGPathSegCurvetoQuadraticAbs.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ var nX = this.x1;
+ this.x1 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y1 + aSVGMatrix.e;
+ this.y1 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y1 + aSVGMatrix.f;
+ };
+
+ SVGPathSegCurvetoCubicAbs.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ var nX = this.x1;
+ this.x1 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y1 + aSVGMatrix.e;
+ this.y1 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y1 + aSVGMatrix.f;
+ nX = this.x2;
+ this.x2 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y2 + aSVGMatrix.e;
+ this.y2 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y2 + aSVGMatrix.f;
+ };
+
+
+ SVGPathSegMovetoAbs.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ return aPoint;
+ };
+
+ SVGPathSegLinetoAbs.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ return aPoint;
+ };
+
+ SVGPathSegCurvetoQuadraticAbs.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ return aPoint;
+ };
+
+ SVGPathSegCurvetoCubicAbs.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ var nX = this.x1;
+ this.x1 = this.x2;
+ this.x2 = nX;
+ var nY = this.y1;
+ this.y1 = this.y2;
+ this.y2 = nY;
+ return aPoint;
+ };
+
+}
+catch( e )
+{ // Opera
+
+ if( e.name == 'ReferenceError' )
+ {
+ SVGPathSeg.prototype.matrixTransform = function( aSVGMatrix )
+ {
+ var nX;
+ switch( this.pathSegTypeAsLetter )
+ {
+ case 'C':
+ nX = this.x2;
+ this.x2 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y2 + aSVGMatrix.e;
+ this.y2 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y2 + aSVGMatrix.f;
+ // fall through intended
+ case 'Q':
+ nX = this.x1;
+ this.x1 = aSVGMatrix.a * nX + aSVGMatrix.c * this.y1 + aSVGMatrix.e;
+ this.y1 = aSVGMatrix.b * nX + aSVGMatrix.d * this.y1 + aSVGMatrix.f;
+ // fall through intended
+ case 'M':
+ case 'L':
+ SVGPathMatrixTransform( this, aSVGMatrix );
+ break;
+ default:
+ log( 'SVGPathSeg.matrixTransform: unexpected path segment type: '
+ + this.pathSegTypeAsLetter );
+ }
+ };
+
+ SVGPathSeg.prototype.changeOrientation = function( nCurrentX, nCurrentY )
+ {
+ switch( this.pathSegTypeAsLetter )
+ {
+ case 'C':
+ var nX = this.x1;
+ this.x1 = this.x2;
+ this.x2 = nX;
+ var nY = this.y1;
+ this.y1 = this.y2;
+ this.y2 = nY;
+ // fall through intended
+ case 'M':
+ case 'L':
+ case 'Q':
+ var aPoint = { x: this.x, y: this.y };
+ this.x = nCurrentX;
+ this.y = nCurrentY;
+ return aPoint;
+ default:
+ log( 'SVGPathSeg.changeOrientation: unexpected path segment type: '
+ + this.pathSegTypeAsLetter );
+ return null;
+ }
+ }
+ }
+ else throw e;
+}
+
+function SVGPathMatrixTransform( aPath, aSVGMatrix )
+{
+ var nX = aPath.x;
+ aPath.x = aSVGMatrix.a * nX + aSVGMatrix.c * aPath.y + aSVGMatrix.e;
+ aPath.y = aSVGMatrix.b * nX + aSVGMatrix.d * aPath.y + aSVGMatrix.f;
+}
+
+
+/**********************************************************************************************
+ * simple PriorityQueue
+ **********************************************************************************************/
+
+function PriorityQueue( aCompareFunc )
+{
+ this.aSequence = [];
+ this.aCompareFunc = aCompareFunc;
+}
+
+PriorityQueue.prototype.clone = function()
+{
+ var aCopy = new PriorityQueue( this.aCompareFunc );
+ var src = this.aSequence;
+ var dest = [];
+ var i, l;
+ for( i = 0, l = src.length; i < l; ++i )
+ {
+ if( i in src )
+ {
+ dest.push( src[i] );
+ }
+ }
+ aCopy.aSequence = dest;
+ return aCopy;
+};
+
+PriorityQueue.prototype.top = function()
+{
+ return this.aSequence[this.aSequence.length - 1];
+};
+
+PriorityQueue.prototype.isEmpty = function()
+{
+ return ( this.aSequence.length === 0 );
+};
+
+PriorityQueue.prototype.push = function( aValue )
+{
+ this.aSequence.unshift( aValue );
+ this.aSequence.sort(this.aCompareFunc);
+};
+
+PriorityQueue.prototype.clear = function()
+{
+ this.aSequence = [];
+};
+
+PriorityQueue.prototype.pop = function()
+{
+ return this.aSequence.pop();
+};
+
+
+
+
+/**********************************************************************************************
+ * AnimationNode Class Hierarchy
+ **********************************************************************************************/
+
+
+
+// Node Types
+var ANIMATION_NODE_CUSTOM = 0;
+var ANIMATION_NODE_PAR = 1;
+var ANIMATION_NODE_SEQ = 2;
+var ANIMATION_NODE_ITERATE = 3;
+var ANIMATION_NODE_ANIMATE = 4;
+var ANIMATION_NODE_SET = 5;
+var ANIMATION_NODE_ANIMATEMOTION = 6;
+var ANIMATION_NODE_ANIMATECOLOR = 7;
+var ANIMATION_NODE_ANIMATETRANSFORM = 8;
+var ANIMATION_NODE_TRANSITIONFILTER = 9;
+var ANIMATION_NODE_AUDIO = 10;
+var ANIMATION_NODE_COMMAND = 11;
+
+var aAnimationNodeTypeInMap = {
+ 'par' : ANIMATION_NODE_PAR,
+ 'seq' : ANIMATION_NODE_SEQ,
+ 'iterate' : ANIMATION_NODE_ITERATE,
+ 'animate' : ANIMATION_NODE_ANIMATE,
+ 'set' : ANIMATION_NODE_SET,
+ 'animatemotion' : ANIMATION_NODE_ANIMATEMOTION,
+ 'animatecolor' : ANIMATION_NODE_ANIMATECOLOR,
+ 'animatetransform' : ANIMATION_NODE_ANIMATETRANSFORM,
+ 'transitionfilter' : ANIMATION_NODE_TRANSITIONFILTER,
+ 'audio' : ANIMATION_NODE_AUDIO,
+ 'command' : ANIMATION_NODE_COMMAND
+};
+
+
+
+
+function getAnimationElementType( aElement )
+{
+ var sName = aElement.localName.toLowerCase();
+
+ if( sName && aAnimationNodeTypeInMap[ sName ] )
+ return aAnimationNodeTypeInMap[ sName ];
+ else
+ return ANIMATION_NODE_CUSTOM;
+}
+
+
+
+
+
+// Node States
+var INVALID_NODE = 0;
+var UNRESOLVED_NODE = 1;
+var RESOLVED_NODE = 2;
+var ACTIVE_NODE = 4;
+var FROZEN_NODE = 8;
+var ENDED_NODE = 16;
+
+function getNodeStateName( eNodeState )
+{
+ switch( eNodeState )
+ {
+ case INVALID_NODE:
+ return 'INVALID';
+ case UNRESOLVED_NODE:
+ return 'UNRESOLVED';
+ case RESOLVED_NODE:
+ return 'RESOLVED';
+ case ACTIVE_NODE:
+ return 'ACTIVE';
+ case FROZEN_NODE:
+ return 'FROZEN';
+ case ENDED_NODE:
+ return 'ENDED';
+ default:
+ return 'UNKNOWN';
+ }
+}
+
+
+// Impress Node Types
+var IMPRESS_DEFAULT_NODE = 0;
+var IMPRESS_ON_CLICK_NODE = 1;
+var IMPRESS_WITH_PREVIOUS_NODE = 2;
+var IMPRESS_AFTER_PREVIOUS_NODE = 3;
+var IMPRESS_MAIN_SEQUENCE_NODE = 4;
+var IMPRESS_TIMING_ROOT_NODE = 5;
+var IMPRESS_INTERACTIVE_SEQUENCE_NODE = 6;
+
+var aImpressNodeTypeInMap = {
+ 'on-click' : IMPRESS_ON_CLICK_NODE,
+ 'with-previous' : IMPRESS_WITH_PREVIOUS_NODE,
+ 'after-previous' : IMPRESS_AFTER_PREVIOUS_NODE,
+ 'main-sequence' : IMPRESS_MAIN_SEQUENCE_NODE,
+ 'timing-root' : IMPRESS_TIMING_ROOT_NODE,
+ 'interactive-sequence' : IMPRESS_INTERACTIVE_SEQUENCE_NODE
+};
+
+var aImpressNodeTypeOutMap = [ 'default', 'on-click', 'with-previous', 'after-previous',
+ 'main-sequence', 'timing-root', 'interactive-sequence' ];
+
+
+// Preset Classes
+var aPresetClassInMap = {};
+
+
+// Preset Ids
+var aPresetIdInMap = {};
+
+
+// Restart Modes
+var RESTART_MODE_DEFAULT = 0;
+var RESTART_MODE_INHERIT = 0; // eslint-disable-line no-unused-vars
+var RESTART_MODE_ALWAYS = 1;
+var RESTART_MODE_WHEN_NOT_ACTIVE = 2;
+var RESTART_MODE_NEVER = 3;
+
+var aRestartModeInMap = {
+ 'inherit' : RESTART_MODE_DEFAULT,
+ 'always' : RESTART_MODE_ALWAYS,
+ 'whenNotActive' : RESTART_MODE_WHEN_NOT_ACTIVE,
+ 'never' : RESTART_MODE_NEVER
+};
+
+var aRestartModeOutMap = [ 'inherit','always', 'whenNotActive', 'never' ];
+
+
+// Fill Modes
+var FILL_MODE_DEFAULT = 0;
+var FILL_MODE_INHERIT = 0; // eslint-disable-line no-unused-vars
+var FILL_MODE_REMOVE = 1;
+var FILL_MODE_FREEZE = 2;
+var FILL_MODE_HOLD = 3;
+var FILL_MODE_TRANSITION = 4;
+var FILL_MODE_AUTO = 5;
+
+var aFillModeInMap = {
+ 'inherit' : FILL_MODE_DEFAULT,
+ 'remove' : FILL_MODE_REMOVE,
+ 'freeze' : FILL_MODE_FREEZE,
+ 'hold' : FILL_MODE_HOLD,
+ 'transition' : FILL_MODE_TRANSITION,
+ 'auto' : FILL_MODE_AUTO
+};
+
+var aFillModeOutMap = [ 'inherit', 'remove', 'freeze', 'hold', 'transition', 'auto' ];
+
+
+// Additive Modes
+var ADDITIVE_MODE_UNKNOWN = 0; // eslint-disable-line no-unused-vars
+var ADDITIVE_MODE_BASE = 1;
+var ADDITIVE_MODE_SUM = 2;
+var ADDITIVE_MODE_REPLACE = 3;
+var ADDITIVE_MODE_MULTIPLY = 4;
+var ADDITIVE_MODE_NONE = 5;
+
+var aAddittiveModeInMap = {
+ 'base' : ADDITIVE_MODE_BASE,
+ 'sum' : ADDITIVE_MODE_SUM,
+ 'replace' : ADDITIVE_MODE_REPLACE,
+ 'multiply' : ADDITIVE_MODE_MULTIPLY,
+ 'none' : ADDITIVE_MODE_NONE
+};
+
+var aAddittiveModeOutMap = [ 'unknown', 'base', 'sum', 'replace', 'multiply', 'none' ];
+
+
+// Accumulate Modes
+var ACCUMULATE_MODE_NONE = 0;
+var ACCUMULATE_MODE_SUM = 1;
+
+var aAccumulateModeOutMap = [ 'none', 'sum' ];
+
+// Calculation Modes
+var CALC_MODE_DISCRETE = 1;
+var CALC_MODE_LINEAR = 2;
+var CALC_MODE_PACED = 3;
+var CALC_MODE_SPLINE = 4;
+
+var aCalcModeInMap = {
+ 'discrete' : CALC_MODE_DISCRETE,
+ 'linear' : CALC_MODE_LINEAR,
+ 'paced' : CALC_MODE_PACED,
+ 'spline' : CALC_MODE_SPLINE
+};
+
+var aCalcModeOutMap = [ 'unknown', 'discrete', 'linear', 'paced', 'spline' ];
+
+
+// Color Spaces
+var COLOR_SPACE_RGB = 0;
+var COLOR_SPACE_HSL = 1;
+
+var aColorSpaceInMap = { 'rgb': COLOR_SPACE_RGB, 'hsl': COLOR_SPACE_HSL };
+
+var aColorSpaceOutMap = [ 'rgb', 'hsl' ];
+
+
+// Clock Directions
+var CLOCKWISE = 0;
+var COUNTERCLOCKWISE = 1;
+
+var aClockDirectionInMap = { 'clockwise': CLOCKWISE, 'counter-clockwise': COUNTERCLOCKWISE };
+
+var aClockDirectionOutMap = [ 'clockwise', 'counter-clockwise' ];
+
+
+// Attribute Value Types
+var UNKNOWN_PROPERTY = 0; // eslint-disable-line no-unused-vars
+var NUMBER_PROPERTY = 1;
+var ENUM_PROPERTY = 2;
+var COLOR_PROPERTY = 3;
+var STRING_PROPERTY = 4;
+var BOOL_PROPERTY = 5;
+var TUPLE_NUMBER_PROPERTY = 6;
+
+var aValueTypeOutMap = [ 'unknown', 'number', 'enum', 'color', 'string', 'boolean' ];
+
+
+// Attribute Map
+var aAttributeMap =
+{
+ 'height': { 'type': NUMBER_PROPERTY,
+ 'get': 'getHeight',
+ 'set': 'setHeight',
+ 'getmod': 'makeScaler( 1/nHeight )',
+ 'setmod': 'makeScaler( nHeight)' },
+
+ 'opacity': { 'type': NUMBER_PROPERTY,
+ 'get': 'getOpacity',
+ 'set': 'setOpacity' },
+
+ 'scale': { 'type': TUPLE_NUMBER_PROPERTY,
+ 'get': 'getSize',
+ 'set': 'setSize' },
+
+ 'translate': { 'type': TUPLE_NUMBER_PROPERTY,
+ 'get': 'getPos',
+ 'set': 'setPos' },
+
+ 'rotate': { 'type': NUMBER_PROPERTY,
+ 'get': 'getRotationAngle',
+ 'set': 'setRotationAngle' },
+
+ 'width': { 'type': NUMBER_PROPERTY,
+ 'get': 'getWidth',
+ 'set': 'setWidth',
+ 'getmod': 'makeScaler( 1/nWidth )',
+ 'setmod': 'makeScaler( nWidth)' },
+
+ 'x': { 'type': NUMBER_PROPERTY,
+ 'get': 'getX',
+ 'set': 'setX',
+ 'getmod': 'makeScaler( 1/nWidth )',
+ 'setmod': 'makeScaler( nWidth)' },
+
+ 'y': { 'type': NUMBER_PROPERTY,
+ 'get': 'getY',
+ 'set': 'setY',
+ 'getmod': 'makeScaler( 1/nHeight )',
+ 'setmod': 'makeScaler( nHeight)' },
+
+ 'fill': { 'type': ENUM_PROPERTY,
+ 'get': 'getFillStyle',
+ 'set': 'setFillStyle' },
+
+ 'stroke': { 'type': ENUM_PROPERTY,
+ 'get': 'getStrokeStyle',
+ 'set': 'setStrokeStyle' },
+
+ 'visibility': { 'type': ENUM_PROPERTY,
+ 'get': 'getVisibility',
+ 'set': 'setVisibility' },
+
+ 'fill-color': { 'type': COLOR_PROPERTY,
+ 'get': 'getFillColor',
+ 'set': 'setFillColor' },
+
+ 'stroke-color': { 'type': COLOR_PROPERTY,
+ 'get': 'getStrokeColor',
+ 'set': 'setStrokeColor' },
+
+ 'color': { 'type': COLOR_PROPERTY,
+ 'get': 'getFontColor',
+ 'set': 'setFontColor' }
+
+};
+
+
+// Transition Classes
+var TRANSITION_INVALID = 0; // Invalid type
+var TRANSITION_CLIP_POLYPOLYGON = 1; // Transition expressed by parametric clip polygon
+var TRANSITION_SPECIAL = 2; // Transition expressed by hand-crafted function
+
+/*
+ * All Transition types should be in sync with aTransitionTypeInMap:
+ * Comments '//' followed by integers represent the transition values in their
+ * C++ implementations.
+ */
+
+// Transition Types
+var BARWIPE_TRANSITION = 1;
+var BOXWIPE_TRANSITION = 2;
+var FOURBOXWIPE_TRANSITION = 3;
+var ELLIPSEWIPE_TRANSITION = 4; // 17
+var CLOCKWIPE_TRANSITION = 5; // 22
+var PINWHEELWIPE_TRANSITION = 6; // 23
+var PUSHWIPE_TRANSITION = 7; // 35
+var SLIDEWIPE_TRANSITION = 8; // 36
+var FADE_TRANSITION = 9; // 37
+var RANDOMBARWIPE_TRANSITION = 10; // 38
+var CHECKERBOARDWIPE_TRANSITION = 11; // 39
+var DISSOLVE_TRANSITION = 12; // 40
+var SNAKEWIPE_TRANSITION = 13; // 30
+var PARALLELSNAKESWIPE_TRANSITION = 14; // 32
+var IRISWIPE_TRANSITION = 15; // 12
+var BARNDOORWIPE_TRANSITION = 16; // 4
+var VEEWIPE_TRANSITION = 17; // 8
+var ZIGZAGWIPE_TRANSITION = 18; // 10
+var BARNZIGZAGWIPE_TRANSITION = 19; // 11
+var FANWIPE_TRANSITION = 20; // 25
+var SINGLESWEEPWIPE_TRANSITION = 21; // 24
+var WATERFALLWIPE_TRANSITION = 22; // 34
+var SPIRALWIPE_TRANSITION = 23; // 31
+var MISCDIAGONALWIPE_TRANSITION = 24; // 7
+var BOXSNAKESWIPE_TRANSITION = 25; // 33
+
+var aTransitionTypeInMap = {
+ 'barWipe' : BARWIPE_TRANSITION,
+ 'boxWipe' : BOXWIPE_TRANSITION,
+ 'barnDoorWipe' : BARNDOORWIPE_TRANSITION,
+ 'fourBoxWipe' : FOURBOXWIPE_TRANSITION,
+ 'ellipseWipe' : ELLIPSEWIPE_TRANSITION,
+ 'clockWipe' : CLOCKWIPE_TRANSITION,
+ 'pinWheelWipe' : PINWHEELWIPE_TRANSITION,
+ 'miscDiagonalWipe' : MISCDIAGONALWIPE_TRANSITION,
+ 'pushWipe' : PUSHWIPE_TRANSITION,
+ 'slideWipe' : SLIDEWIPE_TRANSITION,
+ 'fade' : FADE_TRANSITION,
+ 'fanWipe' : FANWIPE_TRANSITION,
+ 'randomBarWipe' : RANDOMBARWIPE_TRANSITION,
+ 'checkerBoardWipe' : CHECKERBOARDWIPE_TRANSITION,
+ 'dissolve' : DISSOLVE_TRANSITION,
+ 'singleSweepWipe' : SINGLESWEEPWIPE_TRANSITION,
+ 'snakeWipe' : SNAKEWIPE_TRANSITION,
+ 'parallelSnakesWipe': PARALLELSNAKESWIPE_TRANSITION,
+ 'spiralWipe' : SPIRALWIPE_TRANSITION,
+ 'boxSnakesWipe' : BOXSNAKESWIPE_TRANSITION,
+ 'irisWipe' : IRISWIPE_TRANSITION,
+ 'veeWipe' : VEEWIPE_TRANSITION,
+ 'zigZagWipe' : ZIGZAGWIPE_TRANSITION,
+ 'barnZigZagWipe' : BARNZIGZAGWIPE_TRANSITION,
+ 'waterfallWipe' : WATERFALLWIPE_TRANSITION
+};
+
+/*
+ * All Transition subtypes should be in sync with aTransitionSubtypeInMap:
+ * Comments '//' followed by integers represent the transition values in their
+ * C++ implementations.
+ */
+// Transition Subtypes
+var DEFAULT_TRANS_SUBTYPE = 0;
+var LEFTTORIGHT_TRANS_SUBTYPE = 1;
+var TOPTOBOTTOM_TRANS_SUBTYPE = 2;
+var CORNERSIN_TRANS_SUBTYPE = 3; // 11
+var CORNERSOUT_TRANS_SUBTYPE = 4;
+var VERTICAL_TRANS_SUBTYPE = 5;
+var HORIZONTAL_TRANS_SUBTYPE = 6; // 14
+var DOWN_TRANS_SUBTYPE = 7; // 19
+var CIRCLE_TRANS_SUBTYPE = 8; // 27
+var CLOCKWISETWELVE_TRANS_SUBTYPE = 9; // 33
+var CLOCKWISETHREE_TRANS_SUBTYPE = 10;
+var CLOCKWISESIX_TRANS_SUBTYPE = 11;
+var CLOCKWISENINE_TRANS_SUBTYPE = 12;
+var TWOBLADEVERTICAL_TRANS_SUBTYPE = 13;
+var TWOBLADEHORIZONTAL_TRANS_SUBTYPE = 14;
+var FOURBLADE_TRANS_SUBTYPE = 15; // 39
+var FROMLEFT_TRANS_SUBTYPE = 16; // 97
+var FROMTOP_TRANS_SUBTYPE = 17;
+var FROMRIGHT_TRANS_SUBTYPE = 18;
+var FROMBOTTOM_TRANS_SUBTYPE = 19;
+var CROSSFADE_TRANS_SUBTYPE = 20;
+var FADETOCOLOR_TRANS_SUBTYPE = 21;
+var FADEFROMCOLOR_TRANS_SUBTYPE = 22;
+var FADEOVERCOLOR_TRANS_SUBTYPE = 23;
+var THREEBLADE_TRANS_SUBTYPE = 24;
+var EIGHTBLADE_TRANS_SUBTYPE = 25;
+var ONEBLADE_TRANS_SUBTYPE = 26; // 107
+var ACROSS_TRANS_SUBTYPE = 27;
+var TOPLEFTVERTICAL_TRANS_SUBTYPE = 28; // 109
+var TOPLEFTHORIZONTAL_TRANS_SUBTYPE = 29; // 64
+var TOPLEFTDIAGONAL_TRANS_SUBTYPE = 30; // 65
+var TOPRIGHTDIAGONAL_TRANS_SUBTYPE = 31; // 66
+var BOTTOMRIGHTDIAGONAL_TRANS_SUBTYPE = 32; // 67
+var BOTTOMLEFTDIAGONAL_TRANS_SUBTYPE = 33; // 68
+var RECTANGLE_TRANS_SUBTYPE = 34; // 101
+var DIAMOND_TRANS_SUBTYPE = 35; // 102
+var TOPLEFT_TRANS_SUBTYPE = 36; // 3
+var TOPRIGHT_TRANS_SUBTYPE = 37; // 4
+var BOTTOMRIGHT_TRANS_SUBTYPE = 38; // 5
+var BOTTOMLEFT_TRANS_SUBTYPE = 39; // 6
+var TOPCENTER_TRANS_SUBTYPE = 40; // 7
+var RIGHTCENTER_TRANS_SUBTYPE = 41; // 8
+var BOTTOMCENTER_TRANS_SUBTYPE = 42; // 9
+var LEFTCENTER_TRANS_SUBTYPE = 43; // 10
+var LEFT_TRANS_SUBTYPE = 44; // 20
+var UP_TRANS_SUBTYPE = 45; // 21
+var RIGHT_TRANS_SUBTYPE = 46; // 22
+var DIAGONALBOTTOMLEFT_TRANS_SUBTYPE = 47; // 15
+var DIAGONALTOPLEFT_TRANS_SUBTYPE = 48; // 16
+var CENTERTOP_TRANS_SUBTYPE = 49; // 48
+var CENTERRIGHT_TRANS_SUBTYPE = 50; // 49
+var TOP_TRANS_SUBTYPE = 51; // 50
+var BOTTOM_TRANS_SUBTYPE = 52; // 52
+var CLOCKWISETOP_TRANS_SUBTYPE = 53; // 40
+var CLOCKWISERIGHT_TRANS_SUBTYPE = 54; // 41
+var CLOCKWISEBOTTOM_TRANS_SUBTYPE = 55; // 42
+var CLOCKWISELEFT_TRANS_SUBTYPE = 56; // 43
+var CLOCKWISETOPLEFT_TRANS_SUBTYPE = 57; // 44
+var COUNTERCLOCKWISEBOTTOMLEFT_TRANS_SUBTYPE = 58; // 45
+var CLOCKWISEBOTTOMRIGHT_TRANS_SUBTYPE = 59; // 46
+var COUNTERCLOCKWISETOPRIGHT_TRANS_SUBTYPE = 60; // 47
+var VERTICALLEFT_TRANS_SUBTYPE = 61; // 93
+var VERTICALRIGHT_TRANS_SUBTYPE = 62; // 94
+var HORIZONTALLEFT_TRANS_SUBTYPE = 63; // 95
+var HORIZONTALRIGHT_TRANS_SUBTYPE = 64; // 96
+var TOPLEFTCLOCKWISE_TRANS_SUBTYPE = 65; // 69
+var TOPRIGHTCLOCKWISE_TRANS_SUBTYPE = 66; // 70
+var BOTTOMRIGHTCLOCKWISE_TRANS_SUBTYPE = 67; // 71
+var BOTTOMLEFTCLOCKWISE_TRANS_SUBTYPE = 68; // 72
+var TOPLEFTCOUNTERCLOCKWISE_TRANS_SUBTYPE = 69; // 73
+var TOPRIGHTCOUNTERCLOCKWISE_TRANS_SUBTYPE = 70; // 74
+var BOTTOMRIGHTCOUNTERCLOCKWISE_TRANS_SUBTYPE = 71; // 75
+var BOTTOMLEFTCOUNTERCLOCKWISE_TRANS_SUBTYPE = 72; // 76
+var DOUBLEBARNDOOR_TRANS_SUBTYPE = 73; // 17
+var DOUBLEDIAMOND_TRANS_SUBTYPE = 74; // 18
+var VERTICALTOPSAME_TRANS_SUBTYPE = 75; // 77
+var VERTICALBOTTOMSAME_TRANS_SUBTYPE = 76; // 78
+var VERTICALTOPLEFTOPPOSITE_TRANS_SUBTYPE = 77; // 79
+var VERTICALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE = 78; // 80
+var HORIZONTALLEFTSAME_TRANS_SUBTYPE = 79; // 81
+var HORIZONTALRIGHTSAME_TRANS_SUBTYPE = 80; // 82
+var HORIZONTALTOPLEFTOPPOSITE_TRANS_SUBTYPE = 81; // 83
+var HORIZONTALTOPRIGHTOPPOSITE_TRANS_SUBTYPE = 82; // 84
+var DIAGONALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE = 83; // 85
+var DIAGONALTOPLEFTOPPOSITE_TRANS_SUBTYPE = 84; // 86
+var TWOBOXTOP_TRANS_SUBTYPE = 85; // 87
+var TWOBOXBOTTOM_TRANS_SUBTYPE = 86; // 88
+var TWOBOXLEFT_TRANS_SUBTYPE = 87; // 89
+var TWOBOXRIGHT_TRANS_SUBTYPE = 88; // 90
+var FOURBOXVERTICAL_TRANS_SUBTYPE = 89; // 91
+var FOURBOXHORIZONTAL_TRANS_SUBTYPE = 90; // 92
+
+var aTransitionSubtypeInMap = {
+ 'default' : DEFAULT_TRANS_SUBTYPE,
+ 'leftToRight' : LEFTTORIGHT_TRANS_SUBTYPE,
+ 'topToBottom' : TOPTOBOTTOM_TRANS_SUBTYPE,
+ 'cornersIn' : CORNERSIN_TRANS_SUBTYPE,
+ 'cornersOut' : CORNERSOUT_TRANS_SUBTYPE,
+ 'vertical' : VERTICAL_TRANS_SUBTYPE,
+ 'centerTop' : CENTERTOP_TRANS_SUBTYPE,
+ 'centerRight' : CENTERRIGHT_TRANS_SUBTYPE,
+ 'top' : TOP_TRANS_SUBTYPE,
+ 'right' : RIGHT_TRANS_SUBTYPE,
+ 'bottom' : BOTTOM_TRANS_SUBTYPE,
+ 'left' : LEFT_TRANS_SUBTYPE,
+ 'horizontal' : HORIZONTAL_TRANS_SUBTYPE,
+ 'down' : DOWN_TRANS_SUBTYPE,
+ 'circle' : CIRCLE_TRANS_SUBTYPE,
+ 'clockwiseTwelve' : CLOCKWISETWELVE_TRANS_SUBTYPE,
+ 'clockwiseThree' : CLOCKWISETHREE_TRANS_SUBTYPE,
+ 'clockwiseSix' : CLOCKWISESIX_TRANS_SUBTYPE,
+ 'clockwiseNine' : CLOCKWISENINE_TRANS_SUBTYPE,
+ 'clockwiseRight' : CLOCKWISERIGHT_TRANS_SUBTYPE,
+ 'clockwiseTop' : CLOCKWISETOP_TRANS_SUBTYPE,
+ 'clockwiseBottom' : CLOCKWISEBOTTOM_TRANS_SUBTYPE,
+ 'clockwiseLeft' : CLOCKWISELEFT_TRANS_SUBTYPE,
+ 'clockwiseTopLeft' : CLOCKWISETOPLEFT_TRANS_SUBTYPE,
+ 'counterClockwiseBottomLeft' : COUNTERCLOCKWISEBOTTOMLEFT_TRANS_SUBTYPE,
+ 'clockwiseBottomRight' : CLOCKWISEBOTTOMRIGHT_TRANS_SUBTYPE,
+ 'counterClockwiseTopRight' : COUNTERCLOCKWISETOPRIGHT_TRANS_SUBTYPE,
+ 'twoBladeVertical' : TWOBLADEVERTICAL_TRANS_SUBTYPE,
+ 'twoBladeHorizontal' : TWOBLADEHORIZONTAL_TRANS_SUBTYPE,
+ 'fourBlade' : FOURBLADE_TRANS_SUBTYPE,
+ 'fromLeft' : FROMLEFT_TRANS_SUBTYPE,
+ 'fromTop' : FROMTOP_TRANS_SUBTYPE,
+ 'fromRight' : FROMRIGHT_TRANS_SUBTYPE,
+ 'fromBottom' : FROMBOTTOM_TRANS_SUBTYPE,
+ 'crossfade' : CROSSFADE_TRANS_SUBTYPE,
+ 'fadeToColor' : FADETOCOLOR_TRANS_SUBTYPE,
+ 'fadeFromColor' : FADEFROMCOLOR_TRANS_SUBTYPE,
+ 'fadeOverColor' : FADEOVERCOLOR_TRANS_SUBTYPE,
+ 'threeBlade' : THREEBLADE_TRANS_SUBTYPE,
+ 'eightBlade' : EIGHTBLADE_TRANS_SUBTYPE,
+ 'oneBlade' : ONEBLADE_TRANS_SUBTYPE,
+ 'across' : ACROSS_TRANS_SUBTYPE,
+ 'topLeftVertical' : TOPLEFTVERTICAL_TRANS_SUBTYPE,
+ 'topLeftHorizontal' : TOPLEFTHORIZONTAL_TRANS_SUBTYPE,
+ 'topLeftDiagonal' : TOPLEFTDIAGONAL_TRANS_SUBTYPE,
+ 'topRightDiagonal' : TOPRIGHTDIAGONAL_TRANS_SUBTYPE,
+ 'bottomRightDiagonal' : BOTTOMRIGHTDIAGONAL_TRANS_SUBTYPE,
+ 'topLeftClockwise' : TOPLEFTCLOCKWISE_TRANS_SUBTYPE,
+ 'topRightClockwise' : TOPRIGHTCLOCKWISE_TRANS_SUBTYPE,
+ 'bottomRightClockwise' : BOTTOMRIGHTCLOCKWISE_TRANS_SUBTYPE,
+ 'bottomLeftClockwise' : BOTTOMLEFTCLOCKWISE_TRANS_SUBTYPE,
+ 'topLeftCounterClockwise' : TOPLEFTCOUNTERCLOCKWISE_TRANS_SUBTYPE,
+ 'topRightCounterClockwise' : TOPRIGHTCOUNTERCLOCKWISE_TRANS_SUBTYPE,
+ 'bottomRightCounterClockwise' : BOTTOMRIGHTCOUNTERCLOCKWISE_TRANS_SUBTYPE,
+ 'bottomLeftCounterClockwise' : BOTTOMLEFTCOUNTERCLOCKWISE_TRANS_SUBTYPE,
+ 'bottomLeftDiagonal' : BOTTOMLEFTDIAGONAL_TRANS_SUBTYPE,
+ 'rectangle' : RECTANGLE_TRANS_SUBTYPE,
+ 'diamond' : DIAMOND_TRANS_SUBTYPE,
+ 'topLeft' : TOPLEFT_TRANS_SUBTYPE,
+ 'topRight' : TOPRIGHT_TRANS_SUBTYPE,
+ 'bottomRight' : BOTTOMRIGHT_TRANS_SUBTYPE,
+ 'bottomLeft' : BOTTOMLEFT_TRANS_SUBTYPE,
+ 'topCenter' : TOPCENTER_TRANS_SUBTYPE,
+ 'rightCenter' : RIGHTCENTER_TRANS_SUBTYPE,
+ 'bottomCenter' : BOTTOMCENTER_TRANS_SUBTYPE,
+ 'leftCenter' : LEFTCENTER_TRANS_SUBTYPE,
+ 'up' : UP_TRANS_SUBTYPE,
+ 'diagonalBottomLeft' : DIAGONALBOTTOMLEFT_TRANS_SUBTYPE,
+ 'diagonalTopLeft' : DIAGONALTOPLEFT_TRANS_SUBTYPE,
+ 'verticalLeft' : VERTICALLEFT_TRANS_SUBTYPE,
+ 'verticalRight' : VERTICALRIGHT_TRANS_SUBTYPE,
+ 'horizontalLeft' : HORIZONTALLEFT_TRANS_SUBTYPE,
+ 'horizontalRight' : HORIZONTALRIGHT_TRANS_SUBTYPE,
+ 'doubleBarnDoor' : DOUBLEBARNDOOR_TRANS_SUBTYPE,
+ 'doubleDiamond' : DOUBLEDIAMOND_TRANS_SUBTYPE,
+ 'verticalTopSame' : VERTICALTOPSAME_TRANS_SUBTYPE,
+ 'verticalBottomSame' : VERTICALBOTTOMSAME_TRANS_SUBTYPE,
+ 'verticalTopLeftOpposite' : VERTICALTOPLEFTOPPOSITE_TRANS_SUBTYPE,
+ 'verticalBottomLeftOpposite' : VERTICALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE,
+ 'horizontalLeftSame' : HORIZONTALLEFTSAME_TRANS_SUBTYPE,
+ 'horizontalRightSame' : HORIZONTALRIGHTSAME_TRANS_SUBTYPE,
+ 'horizontalTopLeftOpposite' : HORIZONTALTOPLEFTOPPOSITE_TRANS_SUBTYPE,
+ 'horizontalTopRightOpposite' : HORIZONTALTOPRIGHTOPPOSITE_TRANS_SUBTYPE,
+ 'diagonalBottomLeftOpposite' : DIAGONALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE,
+ 'diagonalTopLeftOpposite' : DIAGONALTOPLEFTOPPOSITE_TRANS_SUBTYPE,
+ 'twoBoxTop' : TWOBOXTOP_TRANS_SUBTYPE,
+ 'twoBoxBottom' : TWOBOXBOTTOM_TRANS_SUBTYPE,
+ 'twoBoxLeft' : TWOBOXLEFT_TRANS_SUBTYPE,
+ 'twoBoxRight' : TWOBOXRIGHT_TRANS_SUBTYPE,
+ 'fourBoxVertical' : FOURBOXVERTICAL_TRANS_SUBTYPE,
+ 'fourBoxHorizontal' : FOURBOXHORIZONTAL_TRANS_SUBTYPE
+};
+
+// Transition Modes
+var TRANSITION_MODE_IN = 1;
+var TRANSITION_MODE_OUT = 0;
+
+var aTransitionModeOutMap = [ 'out', 'in' ];
+
+
+// Transition Reverse Methods
+
+// Ignore direction attribute altogether.
+// (If it has no sensible meaning for this transition.)
+var REVERSEMETHOD_IGNORE = 0;
+// Revert by changing the direction of the parameter sweep.
+// (From 1->0 instead of 0->1)
+var REVERSEMETHOD_INVERT_SWEEP = 1;
+// Revert by subtracting the generated polygon from the target bound rect.
+var REVERSEMETHOD_SUBTRACT_POLYGON = 2;
+// Combination of REVERSEMETHOD_INVERT_SWEEP and REVERSEMETHOD_SUBTRACT_POLYGON.
+var REVERSEMETHOD_SUBTRACT_AND_INVERT = 3;
+// Reverse by rotating polygon 180 degrees.
+var REVERSEMETHOD_ROTATE_180 = 4;
+// Reverse by flipping polygon at the y axis.
+var REVERSEMETHOD_FLIP_X = 5;
+// Reverse by flipping polygon at the x axis.
+var REVERSEMETHOD_FLIP_Y = 6;
+
+// eslint-disable-next-line no-unused-vars
+var aReverseMethodOutMap = ['ignore', 'invert sweep', 'subtract polygon',
+ 'subtract and invert', 'rotate 180', 'flip x', 'flip y'];
+
+
+// Transition filter info table
+
+var aTransitionInfoTable = {};
+
+// type: fake transition
+aTransitionInfoTable[0] = {};
+// subtype: default
+aTransitionInfoTable[0][0] =
+{
+ 'class' : TRANSITION_INVALID,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 0.0,
+ 'scaleY' : 0.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : false,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[SNAKEWIPE_TRANSITION] = {};
+aTransitionInfoTable[SNAKEWIPE_TRANSITION][TOPLEFTVERTICAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SNAKEWIPE_TRANSITION][TOPLEFTHORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SNAKEWIPE_TRANSITION][TOPLEFTDIAGONAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SNAKEWIPE_TRANSITION][TOPRIGHTDIAGONAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SNAKEWIPE_TRANSITION][BOTTOMRIGHTDIAGONAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SNAKEWIPE_TRANSITION][BOTTOMLEFTDIAGONAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+}
+
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION] = {};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][VERTICALTOPSAME_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][VERTICALBOTTOMSAME_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][VERTICALTOPLEFTOPPOSITE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][VERTICALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][HORIZONTALLEFTSAME_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][HORIZONTALRIGHTSAME_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][HORIZONTALTOPLEFTOPPOSITE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][HORIZONTALTOPRIGHTOPPOSITE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][DIAGONALTOPLEFTOPPOSITE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[PARALLELSNAKESWIPE_TRANSITION][DIAGONALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[SPIRALWIPE_TRANSITION] = {};
+aTransitionInfoTable[SPIRALWIPE_TRANSITION][TOPLEFTCLOCKWISE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SPIRALWIPE_TRANSITION][TOPRIGHTCLOCKWISE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SPIRALWIPE_TRANSITION][BOTTOMRIGHTCLOCKWISE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SPIRALWIPE_TRANSITION][BOTTOMLEFTCLOCKWISE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 270.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SPIRALWIPE_TRANSITION][TOPLEFTCOUNTERCLOCKWISE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SPIRALWIPE_TRANSITION][TOPRIGHTCOUNTERCLOCKWISE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SPIRALWIPE_TRANSITION][BOTTOMRIGHTCOUNTERCLOCKWISE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 270.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SPIRALWIPE_TRANSITION][BOTTOMLEFTCOUNTERCLOCKWISE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[BOXSNAKESWIPE_TRANSITION] = {};
+aTransitionInfoTable[BOXSNAKESWIPE_TRANSITION][TWOBOXTOP_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXSNAKESWIPE_TRANSITION][TWOBOXBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXSNAKESWIPE_TRANSITION][TWOBOXLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXSNAKESWIPE_TRANSITION][TWOBOXRIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXSNAKESWIPE_TRANSITION][FOURBOXVERTICAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXSNAKESWIPE_TRANSITION][FOURBOXHORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[BARNDOORWIPE_TRANSITION] = {};
+aTransitionInfoTable[BARNDOORWIPE_TRANSITION][VERTICAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle': 0.0,
+ 'scaleX': 1.0,
+ 'scaleY': 1.0,
+ 'reverseMethod': REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep': true,
+ 'scaleIsotropically': false
+};
+aTransitionInfoTable[BARNDOORWIPE_TRANSITION][HORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle': 90.0,
+ 'scaleX': 1.0,
+ 'scaleY': 1.0,
+ 'reverseMethod': REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep': true,
+ 'scaleIsotropically': false
+};
+aTransitionInfoTable[BARNDOORWIPE_TRANSITION][DIAGONALBOTTOMLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle': 45.0,
+ 'scaleX': Math.SQRT2,
+ 'scaleY': Math.SQRT2,
+ 'reverseMethod': REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep': true,
+ 'scaleIsotropically': false
+};
+aTransitionInfoTable[BARNDOORWIPE_TRANSITION][DIAGONALTOPLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle': -45.0,
+ 'scaleX': Math.SQRT2,
+ 'scaleY': Math.SQRT2,
+ 'reverseMethod': REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep': true,
+ 'scaleIsotropically': false
+};
+
+aTransitionInfoTable[MISCDIAGONALWIPE_TRANSITION] = {};
+aTransitionInfoTable[MISCDIAGONALWIPE_TRANSITION][DOUBLEBARNDOOR_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle': 45.0,
+ 'scaleX': Math.SQRT2,
+ 'scaleY': Math.SQRT2,
+ 'reverseMethod': REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep': true,
+ 'scaleIsotropically': false
+};
+aTransitionInfoTable[MISCDIAGONALWIPE_TRANSITION][DOUBLEDIAMOND_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle': 0.0,
+ 'scaleX': 1,
+ 'scaleY': 1,
+ 'reverseMethod': REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep': true,
+ 'scaleIsotropically': false
+};
+
+aTransitionInfoTable[IRISWIPE_TRANSITION] = {};
+aTransitionInfoTable[IRISWIPE_TRANSITION][RECTANGLE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle': 0.0,
+ 'scaleX': 1.0,
+ 'scaleY': 1.0,
+ 'reverseMethod': REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep': true,
+ 'scaleIsotropically': false
+};
+
+aTransitionInfoTable[IRISWIPE_TRANSITION][DIAMOND_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle': 45.0,
+ 'scaleX': Math.SQRT2,
+ 'scaleY': Math.SQRT2,
+ 'reverseMethod': REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep': true,
+ 'scaleIsotropically': false
+};
+
+aTransitionInfoTable[ZIGZAGWIPE_TRANSITION] = {};
+aTransitionInfoTable[ZIGZAGWIPE_TRANSITION][LEFTTORIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[ZIGZAGWIPE_TRANSITION][TOPTOBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[BARNZIGZAGWIPE_TRANSITION] = {};
+aTransitionInfoTable[BARNZIGZAGWIPE_TRANSITION][VERTICAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BARNZIGZAGWIPE_TRANSITION][HORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[BARWIPE_TRANSITION] = {};
+aTransitionInfoTable[BARWIPE_TRANSITION][LEFTTORIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : false,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BARWIPE_TRANSITION][TOPTOBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : false,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[WATERFALLWIPE_TRANSITION] = {};
+aTransitionInfoTable[WATERFALLWIPE_TRANSITION][VERTICALLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[WATERFALLWIPE_TRANSITION][VERTICALRIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[WATERFALLWIPE_TRANSITION][HORIZONTALLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[WATERFALLWIPE_TRANSITION][HORIZONTALRIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_ROTATE_180,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[BOXWIPE_TRANSITION] = {};
+aTransitionInfoTable[BOXWIPE_TRANSITION][TOPLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXWIPE_TRANSITION][TOPRIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXWIPE_TRANSITION][BOTTOMRIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXWIPE_TRANSITION][BOTTOMLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXWIPE_TRANSITION][TOPCENTER_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXWIPE_TRANSITION][RIGHTCENTER_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXWIPE_TRANSITION][BOTTOMCENTER_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[BOXWIPE_TRANSITION][LEFTCENTER_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[FOURBOXWIPE_TRANSITION] = {};
+aTransitionInfoTable[FOURBOXWIPE_TRANSITION][CORNERSIN_TRANS_SUBTYPE] =
+aTransitionInfoTable[FOURBOXWIPE_TRANSITION][CORNERSOUT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[ELLIPSEWIPE_TRANSITION] = {};
+aTransitionInfoTable[ELLIPSEWIPE_TRANSITION][CIRCLE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : true
+};
+aTransitionInfoTable[ELLIPSEWIPE_TRANSITION][HORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[ELLIPSEWIPE_TRANSITION][VERTICAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[CLOCKWIPE_TRANSITION] = {};
+aTransitionInfoTable[CLOCKWIPE_TRANSITION][CLOCKWISETWELVE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[CLOCKWIPE_TRANSITION][CLOCKWISETHREE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[CLOCKWIPE_TRANSITION][CLOCKWISESIX_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[CLOCKWIPE_TRANSITION][CLOCKWISENINE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 270.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[VEEWIPE_TRANSITION] = {};
+aTransitionInfoTable[VEEWIPE_TRANSITION][DOWN_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[VEEWIPE_TRANSITION][LEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[VEEWIPE_TRANSITION][UP_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[VEEWIPE_TRANSITION][RIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[FANWIPE_TRANSITION] = {};
+aTransitionInfoTable[FANWIPE_TRANSITION][CENTERTOP_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[FANWIPE_TRANSITION][CENTERRIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[FANWIPE_TRANSITION][TOP_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[FANWIPE_TRANSITION][RIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[FANWIPE_TRANSITION][BOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[FANWIPE_TRANSITION][LEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION] = {};
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][ONEBLADE_TRANS_SUBTYPE] =
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][TWOBLADEVERTICAL_TRANS_SUBTYPE] =
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][THREEBLADE_TRANS_SUBTYPE] =
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][FOURBLADE_TRANS_SUBTYPE] =
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][EIGHTBLADE_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : true
+};
+aTransitionInfoTable[PINWHEELWIPE_TRANSITION][TWOBLADEHORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : -90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : true
+};
+
+aTransitionInfoTable[PUSHWIPE_TRANSITION] = {};
+aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMLEFT_TRANS_SUBTYPE] =
+aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMTOP_TRANS_SUBTYPE] =
+aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMRIGHT_TRANS_SUBTYPE] =
+aTransitionInfoTable[PUSHWIPE_TRANSITION][FROMBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_SPECIAL,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION] = {};
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION][CLOCKWISETOP_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION][CLOCKWISERIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION][CLOCKWISEBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION][CLOCKWISELEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 270.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION][CLOCKWISETOPLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION][COUNTERCLOCKWISEBOTTOMLEFT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION][CLOCKWISEBOTTOMRIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 180.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[SINGLESWEEPWIPE_TRANSITION][COUNTERCLOCKWISETOPRIGHT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_SUBTRACT_AND_INVERT,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[SLIDEWIPE_TRANSITION] = {};
+aTransitionInfoTable[SLIDEWIPE_TRANSITION][FROMLEFT_TRANS_SUBTYPE] =
+aTransitionInfoTable[SLIDEWIPE_TRANSITION][FROMTOP_TRANS_SUBTYPE] =
+aTransitionInfoTable[SLIDEWIPE_TRANSITION][FROMRIGHT_TRANS_SUBTYPE] =
+aTransitionInfoTable[SLIDEWIPE_TRANSITION][FROMBOTTOM_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_SPECIAL,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[FADE_TRANSITION] = {};
+aTransitionInfoTable[FADE_TRANSITION][CROSSFADE_TRANS_SUBTYPE] =
+aTransitionInfoTable[FADE_TRANSITION][FADETOCOLOR_TRANS_SUBTYPE] =
+aTransitionInfoTable[FADE_TRANSITION][FADEFROMCOLOR_TRANS_SUBTYPE] =
+aTransitionInfoTable[FADE_TRANSITION][FADEOVERCOLOR_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_SPECIAL,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+
+aTransitionInfoTable[RANDOMBARWIPE_TRANSITION] = {};
+aTransitionInfoTable[RANDOMBARWIPE_TRANSITION][VERTICAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[RANDOMBARWIPE_TRANSITION][HORIZONTAL_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[CHECKERBOARDWIPE_TRANSITION] = {};
+aTransitionInfoTable[CHECKERBOARDWIPE_TRANSITION][DOWN_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 90.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_Y,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+aTransitionInfoTable[CHECKERBOARDWIPE_TRANSITION][ACROSS_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_FLIP_X,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : false
+};
+
+aTransitionInfoTable[DISSOLVE_TRANSITION] = {};
+aTransitionInfoTable[DISSOLVE_TRANSITION][DEFAULT_TRANS_SUBTYPE] =
+{
+ 'class' : TRANSITION_CLIP_POLYPOLYGON,
+ 'rotationAngle' : 0.0,
+ 'scaleX' : 1.0,
+ 'scaleY' : 1.0,
+ 'reverseMethod' : REVERSEMETHOD_IGNORE,
+ 'outInvertsSweep' : true,
+ 'scaleIsotropically' : true
+};
+
+
+// Transition tables
+
+function createStateTransitionTable()
+{
+ var aSTT = {};
+
+ aSTT[RESTART_MODE_NEVER] = {};
+ aSTT[RESTART_MODE_WHEN_NOT_ACTIVE] = {};
+ aSTT[RESTART_MODE_ALWAYS] = {};
+
+ // transition table for restart=NEVER, fill=REMOVE
+ var aTable =
+ aSTT[RESTART_MODE_NEVER][FILL_MODE_REMOVE] = {};
+ aTable[INVALID_NODE] = INVALID_NODE;
+ aTable[UNRESOLVED_NODE] = RESOLVED_NODE | ENDED_NODE;
+ aTable[RESOLVED_NODE] = ACTIVE_NODE | ENDED_NODE;
+ aTable[ACTIVE_NODE] = ENDED_NODE;
+ aTable[FROZEN_NODE] = INVALID_NODE; // this state is unreachable here
+ aTable[ENDED_NODE] = ENDED_NODE; // this state is a sink here (cannot restart)
+
+ // transition table for restart=NEVER, fill=FREEZE
+ aTable =
+ aSTT[RESTART_MODE_NEVER][FILL_MODE_FREEZE] =
+ aSTT[RESTART_MODE_NEVER][FILL_MODE_HOLD] =
+ aSTT[RESTART_MODE_NEVER][FILL_MODE_TRANSITION] = {};
+ aTable[INVALID_NODE] = INVALID_NODE;
+ aTable[UNRESOLVED_NODE] = RESOLVED_NODE | ENDED_NODE;
+ aTable[RESOLVED_NODE] = ACTIVE_NODE | ENDED_NODE;
+ aTable[ACTIVE_NODE] = FROZEN_NODE | ENDED_NODE;
+ aTable[FROZEN_NODE] = ENDED_NODE;
+ aTable[ENDED_NODE] = ENDED_NODE; // this state is a sink here (cannot restart)
+
+ // transition table for restart=WHEN_NOT_ACTIVE, fill=REMOVE
+ aTable =
+ aSTT[RESTART_MODE_WHEN_NOT_ACTIVE][FILL_MODE_REMOVE] = {};
+ aTable[INVALID_NODE] = INVALID_NODE;
+ aTable[UNRESOLVED_NODE] = RESOLVED_NODE | ENDED_NODE;
+ aTable[RESOLVED_NODE] = ACTIVE_NODE | ENDED_NODE;
+ aTable[ACTIVE_NODE] = ENDED_NODE;
+ aTable[FROZEN_NODE] = INVALID_NODE; // this state is unreachable here
+ aTable[ENDED_NODE] = RESOLVED_NODE | ACTIVE_NODE | ENDED_NODE; // restart is possible
+
+ // transition table for restart=WHEN_NOT_ACTIVE, fill=FREEZE
+ aTable =
+ aSTT[RESTART_MODE_WHEN_NOT_ACTIVE][FILL_MODE_FREEZE] =
+ aSTT[RESTART_MODE_WHEN_NOT_ACTIVE][FILL_MODE_HOLD] =
+ aSTT[RESTART_MODE_WHEN_NOT_ACTIVE][FILL_MODE_TRANSITION] = {};
+ aTable[INVALID_NODE] = INVALID_NODE;
+ aTable[UNRESOLVED_NODE] = RESOLVED_NODE | ENDED_NODE;
+ aTable[RESOLVED_NODE] = ACTIVE_NODE | ENDED_NODE;
+ aTable[ACTIVE_NODE] = FROZEN_NODE | ENDED_NODE;
+ aTable[FROZEN_NODE] = RESOLVED_NODE | ACTIVE_NODE | ENDED_NODE; // restart is possible
+ aTable[ENDED_NODE] = RESOLVED_NODE | ACTIVE_NODE | ENDED_NODE; // restart is possible
+
+ // transition table for restart=ALWAYS, fill=REMOVE
+ aTable =
+ aSTT[RESTART_MODE_ALWAYS][FILL_MODE_REMOVE] = {};
+ aTable[INVALID_NODE] = INVALID_NODE;
+ aTable[UNRESOLVED_NODE] = RESOLVED_NODE | ENDED_NODE;
+ aTable[RESOLVED_NODE] = ACTIVE_NODE | ENDED_NODE;
+ aTable[ACTIVE_NODE] = RESOLVED_NODE | ACTIVE_NODE | ENDED_NODE; // restart is possible
+ aTable[FROZEN_NODE] = INVALID_NODE; // this state is unreachable here
+ aTable[ENDED_NODE] = RESOLVED_NODE | ACTIVE_NODE | ENDED_NODE; // restart is possible
+
+ // transition table for restart=ALWAYS, fill=FREEZE
+ aTable =
+ aSTT[RESTART_MODE_ALWAYS][FILL_MODE_FREEZE] =
+ aSTT[RESTART_MODE_ALWAYS][FILL_MODE_HOLD] =
+ aSTT[RESTART_MODE_ALWAYS][FILL_MODE_TRANSITION] = {};
+ aTable[INVALID_NODE] = INVALID_NODE;
+ aTable[UNRESOLVED_NODE] = RESOLVED_NODE | ENDED_NODE;
+ aTable[RESOLVED_NODE] = ACTIVE_NODE | ENDED_NODE;
+ aTable[ACTIVE_NODE] = RESOLVED_NODE | ACTIVE_NODE | FROZEN_NODE | ENDED_NODE;
+ aTable[FROZEN_NODE] = RESOLVED_NODE | ACTIVE_NODE | ENDED_NODE; // restart is possible
+ aTable[ENDED_NODE] = RESOLVED_NODE | ACTIVE_NODE | ENDED_NODE; // restart is possible
+
+ return aSTT;
+}
+
+var aStateTransitionTable = createStateTransitionTable();
+
+
+
+function getTransitionTable( eRestartMode, eFillMode )
+{
+ // If restart mode has not been resolved we use 'never'.
+ // Note: RESTART_MODE_DEFAULT == RESTART_MODE_INHERIT.
+ if( eRestartMode == RESTART_MODE_DEFAULT )
+ {
+ log( 'getTransitionTable: unexpected restart mode: ' + eRestartMode
+ + '. Used NEVER instead.');
+ eRestartMode = RESTART_MODE_NEVER;
+ }
+
+ // If fill mode has not been resolved we use 'remove'.
+ // Note: FILL_MODE_DEFAULT == FILL_MODE_INHERIT
+ if( eFillMode == FILL_MODE_DEFAULT ||
+ eFillMode == FILL_MODE_AUTO )
+ {
+ eFillMode = FILL_MODE_REMOVE;
+ }
+
+ return aStateTransitionTable[eRestartMode][eFillMode];
+}
+
+
+
+
+
+// Event Triggers
+var EVENT_TRIGGER_UNKNOWN = 0;
+var EVENT_TRIGGER_ON_SLIDE_BEGIN = 1; // eslint-disable-line no-unused-vars
+var EVENT_TRIGGER_ON_SLIDE_END = 2; // eslint-disable-line no-unused-vars
+var EVENT_TRIGGER_BEGIN_EVENT = 3;
+var EVENT_TRIGGER_END_EVENT = 4;
+var EVENT_TRIGGER_ON_CLICK = 5;
+var EVENT_TRIGGER_ON_DBL_CLICK = 6; // eslint-disable-line no-unused-vars
+var EVENT_TRIGGER_ON_MOUSE_ENTER = 7; // eslint-disable-line no-unused-vars
+var EVENT_TRIGGER_ON_MOUSE_LEAVE = 8; // eslint-disable-line no-unused-vars
+var EVENT_TRIGGER_ON_NEXT_EFFECT = 9;
+var EVENT_TRIGGER_ON_PREV_EFFECT = 10;
+var EVENT_TRIGGER_REPEAT = 11; // eslint-disable-line no-unused-vars
+
+var aEventTriggerOutMap = [ 'unknown', 'slideBegin', 'slideEnd', 'begin', 'end', 'click',
+ 'doubleClick', 'mouseEnter', 'mouseLeave', 'next', 'previous', 'repeat' ];
+
+
+function getEventTriggerType( sEventTrigger )
+{
+ if( sEventTrigger == 'begin' )
+ return EVENT_TRIGGER_BEGIN_EVENT;
+ else if( sEventTrigger == 'end' )
+ return EVENT_TRIGGER_END_EVENT;
+ else if( sEventTrigger == 'next' )
+ return EVENT_TRIGGER_ON_NEXT_EFFECT;
+ else if( sEventTrigger == 'prev' )
+ return EVENT_TRIGGER_ON_PREV_EFFECT;
+ else if( sEventTrigger == 'click' )
+ return EVENT_TRIGGER_ON_CLICK;
+ else
+ return EVENT_TRIGGER_UNKNOWN;
+}
+
+
+
+
+
+// Timing Types
+var UNKNOWN_TIMING = 0;
+var OFFSET_TIMING = 1;
+var WALLCLOCK_TIMING = 2; // eslint-disable-line no-unused-vars
+var INDEFINITE_TIMING = 3;
+var EVENT_TIMING = 4;
+var SYNCBASE_TIMING = 5;
+var MEDIA_TIMING = 6; // eslint-disable-line no-unused-vars
+
+var aTimingTypeOutMap = [ 'unknown', 'offset', 'wallclock', 'indefinite', 'event', 'syncbase', 'media' ];
+
+
+// Char Codes
+var CHARCODE_PLUS = '+'.charCodeAt(0);
+var CHARCODE_MINUS = '-'.charCodeAt(0);
+var CHARCODE_0 = '0'.charCodeAt(0);
+var CHARCODE_9 = '9'.charCodeAt(0);
+
+
+
+function Timing( aAnimationNode, sTimingAttribute )
+{
+ this.aAnimationNode = aAnimationNode; // the node, the timing attribute belongs to
+ this.sTimingDescription = removeWhiteSpaces( sTimingAttribute );
+ this.eTimingType = UNKNOWN_TIMING;
+ this.nOffset = 0.0; // in seconds
+ this.sEventBaseElementId = ''; // the element id for event based timing
+ this.eEventType = EVENT_TRIGGER_UNKNOWN; // the event type
+}
+
+Timing.prototype.getAnimationNode = function()
+{
+ return this.aAnimationNode;
+};
+
+Timing.prototype.getType = function()
+{
+ return this.eTimingType;
+};
+
+Timing.prototype.getOffset = function()
+{
+ return this.nOffset;
+};
+
+Timing.prototype.getEventBaseElementId = function()
+{
+ return this.sEventBaseElementId;
+};
+
+Timing.prototype.getEventType = function()
+{
+ return this.eEventType;
+};
+
+Timing.prototype.parse = function()
+{
+ if( !this.sTimingDescription )
+ {
+ this.eTimingType = OFFSET_TIMING;
+ return;
+ }
+
+ if( this.sTimingDescription == 'indefinite' )
+ this.eTimingType = INDEFINITE_TIMING;
+ else
+ {
+ var nFirstCharCode = this.sTimingDescription.charCodeAt(0);
+ var bPositiveOffset = !( nFirstCharCode == CHARCODE_MINUS );
+ if ( ( nFirstCharCode == CHARCODE_PLUS ) ||
+ ( nFirstCharCode == CHARCODE_MINUS ) ||
+ ( ( nFirstCharCode >= CHARCODE_0 ) && ( nFirstCharCode <= CHARCODE_9 ) ) )
+ {
+ var sClockValue
+ = ( ( nFirstCharCode == CHARCODE_PLUS ) || ( nFirstCharCode == CHARCODE_MINUS ) )
+ ? this.sTimingDescription.substr( 1 )
+ : this.sTimingDescription;
+
+ var TimeInSec = Timing.parseClockValue( sClockValue );
+ if( TimeInSec != undefined )
+ {
+ this.eTimingType = OFFSET_TIMING;
+ this.nOffset = bPositiveOffset ? TimeInSec : -TimeInSec;
+ }
+ }
+ else
+ {
+ var aTimingSplit = [];
+ bPositiveOffset = true;
+ if( this.sTimingDescription.indexOf( '+' ) != -1 )
+ {
+ aTimingSplit = this.sTimingDescription.split( '+' );
+ }
+ else if( this.sTimingDescription.indexOf( '-' ) != -1 )
+ {
+ aTimingSplit = this.sTimingDescription.split( '-' );
+ bPositiveOffset = false;
+ }
+ else
+ {
+ aTimingSplit[0] = this.sTimingDescription;
+ aTimingSplit[1] = '';
+ }
+
+ if( aTimingSplit[0].indexOf( '.' ) != -1 )
+ {
+ var aEventSplit = aTimingSplit[0].split( '.' );
+ this.sEventBaseElementId = aEventSplit[0];
+ this.eEventType = getEventTriggerType( aEventSplit[1] );
+ }
+ else
+ {
+ this.eEventType = getEventTriggerType( aTimingSplit[0] );
+ }
+
+ if( this.eEventType == EVENT_TRIGGER_UNKNOWN )
+ return;
+
+ if( ( this.eEventType == EVENT_TRIGGER_BEGIN_EVENT ) ||
+ ( this.eEventType == EVENT_TRIGGER_END_EVENT ) )
+ {
+ this.eTimingType = SYNCBASE_TIMING;
+ }
+ else
+ {
+ this.eTimingType = EVENT_TIMING;
+ }
+
+ if( aTimingSplit[1] )
+ {
+ sClockValue = aTimingSplit[1];
+ TimeInSec = Timing.parseClockValue( sClockValue );
+ if( TimeInSec != undefined )
+ {
+ this.nOffset = ( bPositiveOffset ) ? TimeInSec : -TimeInSec;
+ }
+ else
+ {
+ this.eTimingType = UNKNOWN_TIMING;
+ }
+
+ }
+ }
+ }
+
+};
+
+Timing.parseClockValue = function( sClockValue )
+{
+ if( !sClockValue )
+ return 0.0;
+
+ var nTimeInSec = undefined;
+
+ var reFullClockValue = /^([0-9]+):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?$/;
+ var rePartialClockValue = /^([0-5][0-9]):([0-5][0-9])(.[0-9]+)?$/;
+ var reTimeCountValue = /^([0-9]+)(.[0-9]+)?(h|min|s|ms)?$/;
+
+ if( reFullClockValue.test( sClockValue ) )
+ {
+ var aClockTimeParts = reFullClockValue.exec( sClockValue );
+
+ var nHours = parseInt( aClockTimeParts[1] );
+ var nMinutes = parseInt( aClockTimeParts[2] );
+ var nSeconds = parseInt( aClockTimeParts[3] );
+ if( aClockTimeParts[4] )
+ nSeconds += parseFloat( aClockTimeParts[4] );
+
+ nTimeInSec = ( ( nHours * 60 ) + nMinutes ) * 60 + nSeconds;
+
+ }
+ else if( rePartialClockValue.test( sClockValue ) )
+ {
+ aClockTimeParts = rePartialClockValue.exec( sClockValue );
+
+ nMinutes = parseInt( aClockTimeParts[1] );
+ nSeconds = parseInt( aClockTimeParts[2] );
+ if( aClockTimeParts[3] )
+ nSeconds += parseFloat( aClockTimeParts[3] );
+
+ nTimeInSec = nMinutes * 60 + nSeconds;
+ }
+ else if( reTimeCountValue.test( sClockValue ) )
+ {
+ aClockTimeParts = reTimeCountValue.exec( sClockValue );
+
+ var nTimeCount = parseInt( aClockTimeParts[1] );
+ if( aClockTimeParts[2] )
+ nTimeCount += parseFloat( aClockTimeParts[2] );
+
+ if( aClockTimeParts[3] )
+ {
+ if( aClockTimeParts[3] == 'h' )
+ {
+ nTimeInSec = nTimeCount * 3600;
+ }
+ else if( aClockTimeParts[3] == 'min' )
+ {
+ nTimeInSec = nTimeCount * 60;
+ }
+ else if( aClockTimeParts[3] == 's' )
+ {
+ nTimeInSec = nTimeCount;
+ }
+ else if( aClockTimeParts[3] == 'ms' )
+ {
+ nTimeInSec = nTimeCount / 1000;
+ }
+ }
+ else
+ {
+ nTimeInSec = nTimeCount;
+ }
+
+ }
+
+ if( nTimeInSec )
+ nTimeInSec = parseFloat( nTimeInSec.toFixed( 3 ) );
+ return nTimeInSec;
+};
+
+Timing.prototype.info = function( bVerbose )
+{
+
+ var sInfo = '';
+
+ if( bVerbose )
+ {
+ sInfo = 'description: ' + this.sTimingDescription + ', ';
+
+ sInfo += ', type: ' + aTimingTypeOutMap[ this.getType() ];
+ sInfo += ', offset: ' + this.getOffset();
+ sInfo += ', event base element id: ' + this.getEventBaseElementId();
+ sInfo += ', timing event type: ' + aEventTriggerOutMap[ this.getEventType() ];
+ }
+ else
+ {
+ switch( this.getType() )
+ {
+ case INDEFINITE_TIMING:
+ sInfo += 'indefinite';
+ break;
+ case OFFSET_TIMING:
+ sInfo += this.getOffset();
+ break;
+ case EVENT_TIMING:
+ case SYNCBASE_TIMING:
+ if( this.getEventBaseElementId() )
+ sInfo += this.getEventBaseElementId() + '.';
+ sInfo += aEventTriggerOutMap[ this.getEventType() ];
+ if( this.getOffset() )
+ {
+ if( this.getOffset() > 0 )
+ sInfo += '+';
+ sInfo += this.getOffset();
+ }
+ }
+ }
+
+ return sInfo;
+};
+
+
+
+
+function Duration( sDurationAttribute )
+{
+ this.bIndefinite = false;
+ this.bMedia = false;
+ this.nValue = undefined;
+ this.bDefined = false;
+
+ if( !sDurationAttribute )
+ return;
+
+ if( sDurationAttribute == 'indefinite' )
+ this.bIndefinite = true;
+ else if( sDurationAttribute == 'media' )
+ this.bMedia = true;
+ else
+ {
+ this.nValue = Timing.parseClockValue( sDurationAttribute );
+ if( this.nValue <= 0.0 )
+ this.nValue = 0.001; // duration must be always greater than 0
+ }
+ this.bDefined = true;
+}
+
+
+Duration.prototype.isSet = function()
+{
+ return this.bDefined;
+};
+
+Duration.prototype.isIndefinite = function()
+{
+ return this.bIndefinite;
+};
+
+Duration.prototype.isMedia = function()
+{
+ return this.bMedia;
+};
+
+Duration.prototype.isValue = function()
+{
+ return this.nValue != undefined;
+};
+
+Duration.prototype.getValue= function()
+{
+ return this.nValue;
+};
+
+Duration.prototype.info= function()
+{
+ var sInfo;
+
+ if( this.isIndefinite() )
+ sInfo = 'indefinite';
+ else if( this.isMedia() )
+ sInfo = 'media';
+ else if( this.getValue() )
+ sInfo = this.getValue();
+
+ return sInfo;
+};
+
+
+
+
+function AnimationNode()
+{
+}
+
+AnimationNode.prototype.init = function() {};
+AnimationNode.prototype.resolve = function() {};
+AnimationNode.prototype.activate = function() {};
+AnimationNode.prototype.deactivate = function() {};
+AnimationNode.prototype.end = function() {};
+AnimationNode.prototype.getState = function() {};
+AnimationNode.prototype.registerDeactivatingListener = function() {};
+AnimationNode.prototype.notifyDeactivating = function() {};
+
+
+
+
+function NodeContext( aSlideShowContext )
+{
+ this.aContext = aSlideShowContext;
+ this.aAnimationNodeMap = null;
+ this.aAnimatedElementMap = null;
+ this.aSourceEventElementMap = null;
+ this.nStartDelay = 0.0;
+ this.bFirstRun = undefined;
+ this.bIsInvalid = false;
+ this.aSlideHeight = HEIGHT;
+ this.aSlideWidth = WIDTH;
+}
+
+
+NodeContext.prototype.makeSourceEventElement = function( sId, aEventBaseElem )
+{
+ if( !aEventBaseElem )
+ {
+ log( 'NodeContext.makeSourceEventElement: event base element is not valid' );
+ return null;
+ }
+
+ if( !this.aContext.aEventMultiplexer )
+ {
+ log( 'NodeContext.makeSourceEventElement: event multiplexer not initialized' );
+ return null;
+ }
+
+ if( !this.aSourceEventElementMap[ sId ] )
+ {
+ this.aSourceEventElementMap[ sId ] = new SourceEventElement( sId, aEventBaseElem, this.aContext.aEventMultiplexer );
+ }
+ return this.aSourceEventElementMap[ sId ];
+};
+
+
+
+
+function StateTransition( aBaseNode )
+{
+ this.aNode = aBaseNode;
+ this.eToState = INVALID_NODE;
+}
+
+StateTransition.prototype.enter = function( eNodeState, bForce )
+{
+ if( !bForce ) bForce = false;
+
+ if( this.eToState != INVALID_NODE )
+ {
+ log( 'StateTransition.enter: commit() before enter()ing again!' );
+ return false;
+ }
+ if( !bForce && !this.aNode.isTransition( this.aNode.getState(), eNodeState ) )
+ return false;
+
+ // recursion detection:
+ if( ( this.aNode.nCurrentStateTransition & eNodeState ) != 0 )
+ return false; // already in wanted transition
+
+ // mark transition:
+ this.aNode.nCurrentStateTransition |= eNodeState;
+ this.eToState = eNodeState;
+ return true;
+};
+
+StateTransition.prototype.commit = function()
+{
+ if( this.eToState != INVALID_NODE )
+ {
+ this.aNode.eCurrentState = this.eToState;
+ this.clear();
+ }
+};
+
+StateTransition.prototype.clear = function()
+{
+ if( this.eToState != INVALID_NODE )
+ {
+ this.aNode.nCurrentStateTransition &= ~this.eToState;
+ this.eToState = INVALID_NODE;
+ }
+};
+
+
+
+
+function BaseNode( aAnimElem, aParentNode, aNodeContext )
+{
+ this.nId = getUniqueId();
+ this.sClassName = 'BaseNode';
+
+ if( !aAnimElem )
+ log( 'BaseNode(id:' + this.nId + ') constructor: aAnimElem is not valid' );
+
+ if( !aNodeContext )
+ log( 'BaseNode(id:' + this.nId + ') constructor: aNodeContext is not valid' );
+
+ if( !aNodeContext.aContext )
+ log( 'BaseNode(id:' + this.nId + ') constructor: aNodeContext.aContext is not valid' );
+
+
+ this.bIsContainer = false;
+ this.aElement = aAnimElem;
+ this.aParentNode = aParentNode;
+ this.aNodeContext = aNodeContext;
+ this.aContext = aNodeContext.aContext;
+ this.nStartDelay = aNodeContext.nStartDelay;
+ this.eCurrentState = UNRESOLVED_NODE;
+ this.nCurrentStateTransition = 0;
+ this.aDeactivatingListenerArray = [];
+ this.aActivationEvent = null;
+ this.aDeactivationEvent = null;
+
+ this.aBegin = null;
+ this.aDuration = null;
+ this.aEnd = null;
+ this.bMainSequenceRootNode = false;
+ this.bInteractiveSequenceRootNode = false;
+ this.eFillMode = FILL_MODE_FREEZE;
+ this.eRestartMode = RESTART_MODE_NEVER;
+ this.nRepeatCount = undefined;
+ this.nAccelerate = 0.0;
+ this.nDecelerate = 0.0;
+ this.bAutoReverse = false;
+
+}
+extend( BaseNode, AnimationNode );
+
+
+BaseNode.prototype.getId = function()
+{
+ return this.nId;
+};
+
+BaseNode.prototype.parseElement = function()
+{
+ var aAnimElem = this.aElement;
+
+ // id attribute
+ var sIdAttr = aAnimElem.getAttributeNS( NSS['xml'], 'id' );
+ // we append the animation node to the Animation Node Map so that it can be retrieved
+ // by the registerEvent routine for resolving begin values of type 'id.begin', 'id.end'
+ if( sIdAttr )
+ this.aNodeContext.aAnimationNodeMap[ sIdAttr ] = this;
+
+ // begin attribute
+ this.aBegin = null;
+ var sBeginAttr = aAnimElem.getAttributeNS( NSS['smil'], 'begin' );
+ this.aBegin = new Timing( this, sBeginAttr );
+ this.aBegin.parse();
+
+ // end attribute
+ this.aEnd = null;
+ var sEndAttr = aAnimElem.getAttributeNS( NSS['smil'], 'end' );
+ if( sEndAttr )
+ {
+ this.aEnd = new Timing( this, sEndAttr );
+ this.aEnd.parse();
+ }
+
+ // dur attribute
+ this.aDuration = null;
+ var sDurAttr = aAnimElem.getAttributeNS( NSS['smil'], 'dur' );
+ this.aDuration = new Duration( sDurAttr );
+ if( !this.aDuration.isSet() )
+ {
+ if( this.isContainer() )
+ this.aDuration = null;
+ else
+ this.aDuration = new Duration( 'indefinite' );
+ }
+
+ // fill attribute
+ var sFillAttr = aAnimElem.getAttributeNS( NSS['smil'], 'fill' );
+ if( sFillAttr && aFillModeInMap[ sFillAttr ])
+ this.eFillMode = aFillModeInMap[ sFillAttr ];
+ else
+ this.eFillMode = FILL_MODE_DEFAULT;
+
+ // restart attribute
+ var sRestartAttr = aAnimElem.getAttributeNS( NSS['smil'], 'restart' );
+ if( sRestartAttr && aRestartModeInMap[ sRestartAttr ] )
+ this.eRestartMode = aRestartModeInMap[ sRestartAttr ];
+ else
+ this.eRestartMode = RESTART_MODE_DEFAULT;
+
+ // repeatCount attribute
+ var sRepeatCount = aAnimElem.getAttributeNS( NSS['smil'], 'repeatCount' );
+ if( !sRepeatCount )
+ this.nRepeatCount = 1;
+ else
+ this.nRepeatCount = parseFloat( sRepeatCount );
+ if( ( isNaN(this.nRepeatCount) ) && ( sRepeatCount != 'indefinite' ) )
+ this.nRepeatCount = 1;
+
+ // accelerate attribute
+ this.nAccelerate = 0.0;
+ var sAccelerateAttr = aAnimElem.getAttributeNS( NSS['smil'], 'accelerate' );
+ if( sAccelerateAttr )
+ this.nAccelerate = parseFloat( sAccelerateAttr );
+ if( isNaN(this.nAccelerate) )
+ this.nAccelerate = 0.0;
+
+ // decelerate attribute
+ this.nDecelerate = 0.0;
+ var sDecelerateAttr = aAnimElem.getAttributeNS( NSS['smil'], 'decelerate' );
+ if( sDecelerateAttr )
+ this.nDecelerate = parseFloat( sDecelerateAttr );
+ if( isNaN(this.nDecelerate) )
+ this.nDecelerate = 0.0;
+
+ // autoReverse attribute
+ this.bAutoreverse = false;
+ var sAutoReverseAttr = aAnimElem.getAttributeNS( NSS['smil'], 'autoReverse' );
+ if( sAutoReverseAttr == 'true' )
+ this.bAutoreverse = true;
+
+
+ // resolve fill value
+ if( this.eFillMode == FILL_MODE_DEFAULT )
+ if( this.getParentNode() )
+ this.eFillMode = this.getParentNode().getFillMode();
+ else
+ this.eFillMode = FILL_MODE_AUTO;
+
+ if( this.eFillMode == FILL_MODE_AUTO ) // see SMIL recommendation document
+ {
+ this.eFillMode = ( this.aEnd ||
+ ( this.nRepeatCount != 1) ||
+ ( this.aDuration && !this.aDuration.isIndefinite() ) )
+ ? FILL_MODE_REMOVE
+ : FILL_MODE_FREEZE;
+ }
+
+ // resolve restart value
+ if( this.eRestartMode == RESTART_MODE_DEFAULT )
+ if( this.getParentNode() )
+ this.eRestartMode = this.getParentNode().getRestartMode();
+ else
+ // SMIL recommendation document says to set it to 'always'
+ this.eRestartMode = RESTART_MODE_ALWAYS;
+
+ // resolve accelerate and decelerate attributes
+ // from the SMIL recommendation document: if the individual values of the accelerate
+ // and decelerate attributes are between 0 and 1 and the sum is greater than 1,
+ // then both the accelerate and decelerate attributes will be ignored and the timed
+ // element will behave as if neither attribute was specified.
+ if( ( this.nAccelerate + this.nDecelerate ) > 1.0 )
+ {
+ this.nAccelerate = 0.0;
+ this.nDecelerate = 0.0;
+ }
+
+ this.aStateTransTable = getTransitionTable( this.getRestartMode(), this.getFillMode() );
+
+ return true;
+};
+
+BaseNode.prototype.getParentNode = function()
+{
+ return this.aParentNode;
+};
+
+BaseNode.prototype.init = function()
+{
+ this.DBG( this.callInfo( 'init' ) );
+ if( ! this.checkValidNode() )
+ return false;
+ if( this.aActivationEvent )
+ this.aActivationEvent.dispose();
+ if( this.aDeactivationEvent )
+ this.aDeactivationEvent.dispose();
+
+ this.eCurrentState = UNRESOLVED_NODE;
+
+ return this.init_st();
+};
+
+BaseNode.prototype.resolve = function()
+{
+ if( this.aNodeContext.bIsInvalid || ! this.checkValidNode() )
+ return false;
+
+ this.DBG( this.callInfo( 'resolve' ) );
+
+ if( this.eCurrentState == RESOLVED_NODE )
+ log( 'BaseNode.resolve: already in RESOLVED state' );
+
+ var aStateTrans = new StateTransition( this );
+
+ if( aStateTrans.enter( RESOLVED_NODE ) &&
+ this.isTransition( RESOLVED_NODE, ACTIVE_NODE ) &&
+ this.resolve_st() )
+ {
+ aStateTrans.commit();
+
+ if( this.aActivationEvent )
+ {
+ this.aActivationEvent.charge();
+ }
+ else
+ {
+ this.aActivationEvent = makeDelay( bind( this, this.activate ), this.getBegin().getOffset() + this.nStartDelay );
+ }
+ registerEvent( this.getId(), this.getBegin(), this.aActivationEvent, this.aNodeContext );
+
+ return true;
+ }
+
+ return false;
+};
+
+BaseNode.prototype.activate = function()
+{
+ if( ! this.checkValidNode() )
+ return false;
+
+ if( this.eCurrentState == ACTIVE_NODE )
+ log( 'BaseNode.activate: already in ACTIVE state' );
+
+ this.DBG( this.callInfo( 'activate' ), getCurrentSystemTime() );
+
+ var aStateTrans = new StateTransition( this );
+
+ if( aStateTrans.enter( ACTIVE_NODE ) )
+ {
+ this.activate_st();
+ aStateTrans.commit();
+ if( !this.aContext.aEventMultiplexer )
+ log( 'BaseNode.activate: this.aContext.aEventMultiplexer is not valid' );
+ this.aContext.aEventMultiplexer.notifyEvent( EVENT_TRIGGER_BEGIN_EVENT, this.getId() );
+ return true;
+ }
+ return false;
+};
+
+BaseNode.prototype.deactivate = function()
+{
+ if( this.inStateOrTransition( ENDED_NODE | FROZEN_NODE ) || !this.checkValidNode() )
+ return;
+
+ if( this.isTransition( this.eCurrentState, FROZEN_NODE ) )
+ {
+ this.DBG( this.callInfo( 'deactivate' ), getCurrentSystemTime() );
+
+ var aStateTrans = new StateTransition( this );
+ if( aStateTrans.enter( FROZEN_NODE, true /* FORCE */ ) )
+ {
+ this.deactivate_st( FROZEN_NODE );
+ aStateTrans.commit();
+
+ this.notifyEndListeners();
+
+ if( this.aActivationEvent )
+ this.aActivationEvent.dispose();
+ if( this.aDeactivationEvent )
+ this.aDeactivationEvent.dispose();
+ }
+ }
+ else
+ {
+ this.end();
+ }
+ // state has changed either to FROZEN or ENDED
+};
+
+BaseNode.prototype.end = function()
+{
+ var bIsFrozenOrInTransitionToFrozen = this.inStateOrTransition( FROZEN_NODE );
+ if( this.inStateOrTransition( ENDED_NODE ) || !this.checkValidNode() )
+ return;
+
+ if( !(this.isTransition( this.eCurrentState, ENDED_NODE ) ) )
+ log( 'BaseNode.end: end state not reachable in transition table' );
+
+ this.DBG( this.callInfo( 'end' ), getCurrentSystemTime() );
+
+ var aStateTrans = new StateTransition( this );
+ if( aStateTrans.enter( ENDED_NODE, true /* FORCE */ ) )
+ {
+ this.deactivate_st( ENDED_NODE );
+ aStateTrans.commit();
+
+ // if is FROZEN or is to be FROZEN, then
+ // will/already notified deactivating listeners
+ if( !bIsFrozenOrInTransitionToFrozen )
+ this.notifyEndListeners();
+
+ if( this.aActivationEvent )
+ this.aActivationEvent.dispose();
+ if( this.aDeactivationEvent )
+ this.aDeactivationEvent.dispose();
+ }
+};
+
+BaseNode.prototype.dispose = function()
+{
+ if( this.aActivationEvent )
+ this.aActivationEvent.dispose();
+ if( this.aDeactivationEvent )
+ this.aDeactivationEvent.dispose();
+ this.aDeactivatingListenerArray = [];
+};
+
+BaseNode.prototype.getState = function()
+{
+ return this.eCurrentState;
+};
+
+BaseNode.prototype.registerDeactivatingListener = function( aNotifiee )
+{
+ if (! this.checkValidNode())
+ return false;
+
+ if( !aNotifiee )
+ {
+ log( 'BaseNode.registerDeactivatingListener(): invalid notifiee' );
+ return false;
+ }
+ this.aDeactivatingListenerArray.push( aNotifiee );
+
+ return true;
+};
+
+BaseNode.prototype.notifyDeactivating = function( aNotifier )
+{
+ assert( ( aNotifier.getState() == FROZEN_NODE ) || ( aNotifier.getState() == ENDED_NODE ),
+ 'BaseNode.notifyDeactivating: Notifier node is neither in FROZEN nor in ENDED state' );
+};
+
+BaseNode.prototype.isMainSequenceRootNode = function()
+{
+ return this.bMainSequenceRootNode;
+};
+
+BaseNode.prototype.isInteractiveSequenceRootNode = function()
+{
+ return this.bInteractiveSequenceRootNode;
+};
+
+BaseNode.prototype.makeDeactivationEvent = function( nDelay )
+{
+ if( this.aDeactivationEvent )
+ {
+ this.aDeactivationEvent.charge();
+ }
+ else
+ {
+ if( typeof( nDelay ) == typeof(0) )
+ this.aDeactivationEvent = makeDelay( bind( this, this.deactivate ), nDelay );
+ else
+ this.aDeactivationEvent = null;
+ }
+ return this.aDeactivationEvent;
+};
+
+BaseNode.prototype.scheduleDeactivationEvent = function( aEvent )
+{
+ this.DBG( this.callInfo( 'scheduleDeactivationEvent' ) );
+
+ if( !aEvent )
+ {
+ if( this.getDuration() && this.getDuration().isValue() )
+ aEvent = this.makeDeactivationEvent( this.getDuration().getValue() );
+ }
+ if( aEvent )
+ {
+ this.aContext.aTimerEventQueue.addEvent( aEvent );
+ }
+};
+
+BaseNode.prototype.checkValidNode = function()
+{
+ return ( this.eCurrentState != INVALID_NODE );
+};
+
+BaseNode.prototype.init_st = function()
+{
+ return true;
+};
+
+BaseNode.prototype.resolve_st = function()
+{
+ return true;
+};
+
+BaseNode.prototype.activate_st = function()
+{
+ this.scheduleDeactivationEvent();
+};
+
+BaseNode.prototype.deactivate_st = function( /*aNodeState*/ )
+{
+ // empty body
+};
+
+BaseNode.prototype.notifyEndListeners = function()
+{
+ var nDeactivatingListenerCount = this.aDeactivatingListenerArray.length;
+
+ for( var i = 0; i < nDeactivatingListenerCount; ++i )
+ {
+ this.aDeactivatingListenerArray[i].notifyDeactivating( this );
+ }
+
+ this.aContext.aEventMultiplexer.notifyEvent( EVENT_TRIGGER_END_EVENT, this.getId() );
+ if( this.getParentNode() && this.getParentNode().isMainSequenceRootNode() )
+ this.aContext.aEventMultiplexer.notifyNextEffectEndEvent();
+
+ if( this.isMainSequenceRootNode() )
+ this.aContext.aEventMultiplexer.notifyAnimationsEndEvent();
+};
+
+BaseNode.prototype.getContext = function()
+{
+ return this.aContext;
+};
+
+BaseNode.prototype.isTransition = function( eFromState, eToState )
+{
+ return ( ( this.aStateTransTable[ eFromState ] & eToState ) != 0 );
+};
+
+BaseNode.prototype.inStateOrTransition = function( nMask )
+{
+ return ( ( ( this.eCurrentState & nMask ) != 0 ) || ( ( this.nCurrentStateTransition & nMask ) != 0 ) );
+};
+
+BaseNode.prototype.isContainer = function()
+{
+ return this.bIsContainer;
+};
+
+BaseNode.prototype.getBegin = function()
+{
+ return this.aBegin;
+};
+
+BaseNode.prototype.getDuration = function()
+{
+ return this.aDuration;
+};
+
+BaseNode.prototype.getEnd = function()
+{
+ return this.aEnd;
+};
+
+BaseNode.prototype.getFillMode = function()
+{
+ return this.eFillMode;
+};
+
+BaseNode.prototype.getRestartMode = function()
+{
+ return this.eRestartMode;
+};
+
+BaseNode.prototype.getRepeatCount = function()
+{
+ return this.nRepeatCount;
+};
+
+BaseNode.prototype.getAccelerateValue = function()
+{
+ return this.nAccelerate;
+};
+
+BaseNode.prototype.getDecelerateValue = function()
+{
+ return this.nDecelerate;
+};
+
+BaseNode.prototype.isAutoReverseEnabled = function()
+{
+ return this.bAutoreverse;
+};
+
+BaseNode.prototype.info = function( bVerbose )
+{
+ var sInfo = 'class name: ' + this.sClassName;
+ sInfo += '; element name: ' + this.aElement.localName;
+ sInfo += '; id: ' + this.getId();
+ sInfo += '; state: ' + getNodeStateName( this.getState() );
+
+ if( bVerbose )
+ {
+ // is container
+ sInfo += '; is container: ' + this.isContainer();
+
+ // begin
+ if( this.getBegin() )
+ sInfo += '; begin: ' + this.getBegin().info();
+
+ // duration
+ if( this.getDuration() )
+ sInfo += '; dur: ' + this.getDuration().info();
+
+ // end
+ if( this.getEnd() )
+ sInfo += '; end: ' + this.getEnd().info();
+
+ // fill mode
+ if( this.getFillMode() )
+ sInfo += '; fill: ' + aFillModeOutMap[ this.getFillMode() ];
+
+ // restart mode
+ if( this.getRestartMode() )
+ sInfo += '; restart: ' + aRestartModeOutMap[ this.getRestartMode() ];
+
+ // repeatCount
+ if( this.getRepeatCount() && ( this.getRepeatCount() != 1.0 ) )
+ sInfo += '; repeatCount: ' + this.getRepeatCount();
+
+ // accelerate
+ if( this.getAccelerateValue() )
+ sInfo += '; accelerate: ' + this.getAccelerateValue();
+
+ // decelerate
+ if( this.getDecelerateValue() )
+ sInfo += '; decelerate: ' + this.getDecelerateValue();
+
+ // auto reverse
+ if( this.isAutoReverseEnabled() )
+ sInfo += '; autoReverse: true';
+
+ }
+
+ return sInfo;
+};
+
+BaseNode.prototype.callInfo = function( sMethodName )
+{
+ var sInfo = this.sClassName +
+ '( ' + this.getId() +
+ ', ' + getNodeStateName( this.getState() ) +
+ ' ).' + sMethodName;
+ return sInfo;
+};
+
+BaseNode.prototype.DBG = function( sMessage, nTime )
+{
+ ANIMDBG.print( sMessage, nTime );
+};
+
+
+
+
+function AnimationBaseNode( aAnimElem, aParentNode, aNodeContext )
+{
+ AnimationBaseNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'AnimationBaseNode';
+ this.bIsContainer = false;
+ this.aTargetElement = null;
+ this.bIsTargetTextElement = false;
+ this.aAnimatedElement = null;
+ this.aActivity = null;
+
+ this.nMinFrameCount = undefined;
+ this.eAdditiveMode = undefined;
+
+}
+extend( AnimationBaseNode, BaseNode );
+
+
+AnimationBaseNode.prototype.parseElement = function()
+{
+ var bRet = AnimationBaseNode.superclass.parseElement.call( this );
+
+ var aAnimElem = this.aElement;
+
+ // targetElement attribute
+ this.aTargetElement = null;
+ var sTargetElementAttr = aAnimElem.getAttributeNS( NSS['smil'], 'targetElement' );
+ if( sTargetElementAttr )
+ this.aTargetElement = document.getElementById( sTargetElementAttr );
+
+ if( !this.aTargetElement )
+ {
+ this.eCurrentState = INVALID_NODE;
+ log( 'AnimationBaseNode.parseElement: target element not found: ' + sTargetElementAttr );
+ }
+
+ // sub-item attribute for text animated element
+ var sSubItemAttr = aAnimElem.getAttributeNS( NSS['anim'], 'sub-item' );
+ this.bIsTargetTextElement = ( sSubItemAttr && ( sSubItemAttr === 'text' ) );
+
+ // additive attribute
+ var sAdditiveAttr = aAnimElem.getAttributeNS( NSS['smil'], 'additive' );
+ if( sAdditiveAttr && aAddittiveModeInMap[sAdditiveAttr] )
+ this.eAdditiveMode = aAddittiveModeInMap[sAdditiveAttr];
+ else
+ this.eAdditiveMode = ADDITIVE_MODE_REPLACE;
+
+ // set up min frame count value;
+ this.nMinFrameCount = ( this.getDuration().isValue() )
+ ? ( this.getDuration().getValue() * MINIMUM_FRAMES_PER_SECONDS )
+ : MINIMUM_FRAMES_PER_SECONDS;
+ if( this.nMinFrameCount < 1.0 )
+ this.nMinFrameCount = 1;
+ else if( this.nMinFrameCount > MINIMUM_FRAMES_PER_SECONDS )
+ this.nMinFrameCount = MINIMUM_FRAMES_PER_SECONDS;
+
+
+ if( this.aTargetElement )
+ {
+ // set up target element initial visibility
+ if( aAnimElem.getAttributeNS( NSS['smil'], 'attributeName' ) === 'visibility' )
+ {
+ if( aAnimElem.getAttributeNS( NSS['smil'], 'to' ) === 'visible' )
+ this.aTargetElement.setAttribute( 'visibility', 'hidden' );
+ }
+
+ // create animated element
+ if( !this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ] )
+ {
+ if( this.bIsTargetTextElement )
+ {
+ this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ]
+ = new AnimatedTextElement( this.aTargetElement );
+ }
+ else
+ {
+ this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ]
+ = new AnimatedElement( this.aTargetElement );
+ }
+ }
+ this.aAnimatedElement = this.aNodeContext.aAnimatedElementMap[ sTargetElementAttr ];
+
+ // set additive mode
+ this.aAnimatedElement.setAdditiveMode( this.eAdditiveMode );
+ }
+
+
+ return bRet;
+};
+
+AnimationBaseNode.prototype.init_st = function()
+{
+ if( this.aActivity )
+ this.aActivity.activate( makeEvent( bind( this, this.deactivate ) ) );
+ else
+ this.aActivity = this.createActivity();
+ return true;
+};
+
+AnimationBaseNode.prototype.resolve_st = function()
+{
+ return true;
+};
+
+AnimationBaseNode.prototype.activate_st = function()
+{
+ if( this.aActivity )
+ {
+ this.saveStateOfAnimatedElement();
+ this.aActivity.setTargets( this.getAnimatedElement() );
+ if( this.getContext().bIsSkipping )
+ {
+ this.aActivity.end();
+ }
+ else
+ {
+ this.getContext().aActivityQueue.addActivity( this.aActivity );
+ }
+ }
+ else
+ {
+ AnimationBaseNode.superclass.scheduleDeactivationEvent.call( this );
+ }
+};
+
+AnimationBaseNode.prototype.deactivate_st = function( eDestState )
+{
+ if( eDestState == FROZEN_NODE )
+ {
+ if( this.aActivity )
+ this.aActivity.end();
+ }
+ if( eDestState == ENDED_NODE )
+ {
+ if( this.aActivity )
+ this.aActivity.dispose();
+ if( ( this.getFillMode() == FILL_MODE_REMOVE ) && this.getAnimatedElement() )
+ this.removeEffect();
+ }
+};
+
+AnimationBaseNode.prototype.createActivity = function()
+{
+ log( 'AnimationBaseNode.createActivity: abstract method called' );
+};
+
+AnimationBaseNode.prototype.fillActivityParams = function()
+{
+
+ // compute duration
+ var nDuration = 0.001;
+ if( this.getDuration().isValue() )
+ {
+ nDuration = this.getDuration().getValue();
+ }
+ else
+ {
+ log( 'AnimationBaseNode.fillActivityParams: duration is not a number' );
+ }
+
+ // create and set up activity params
+ var aActivityParamSet = new ActivityParamSet();
+
+ aActivityParamSet.aEndEvent = makeEvent( bind( this, this.deactivate ) );
+ aActivityParamSet.aTimerEventQueue = this.aContext.aTimerEventQueue;
+ aActivityParamSet.aActivityQueue = this.aContext.aActivityQueue;
+ aActivityParamSet.nMinDuration = nDuration;
+ aActivityParamSet.nMinNumberOfFrames = this.getMinFrameCount();
+ aActivityParamSet.bAutoReverse = this.isAutoReverseEnabled();
+ aActivityParamSet.nRepeatCount = this.getRepeatCount();
+ aActivityParamSet.nAccelerationFraction = this.getAccelerateValue();
+ aActivityParamSet.nDecelerationFraction = this.getDecelerateValue();
+ aActivityParamSet.nSlideWidth = this.aNodeContext.aSlideWidth;
+ aActivityParamSet.nSlideHeight = this.aNodeContext.aSlideHeight;
+
+ return aActivityParamSet;
+};
+
+AnimationBaseNode.prototype.hasPendingAnimation = function()
+{
+ return true;
+};
+
+AnimationBaseNode.prototype.saveStateOfAnimatedElement = function()
+{
+ this.getAnimatedElement().saveState( this.getId() );
+};
+
+AnimationBaseNode.prototype.removeEffect = function()
+{
+ this.getAnimatedElement().restoreState( this.getId() );
+};
+
+AnimationBaseNode.prototype.getTargetElement = function()
+{
+ return this.aTargetElement;
+};
+
+AnimationBaseNode.prototype.getAnimatedElement = function()
+{
+ return this.aAnimatedElement;
+};
+
+AnimationBaseNode.prototype.dispose= function()
+{
+ if( this.aActivity )
+ this.aActivity.dispose();
+
+ AnimationBaseNode.superclass.dispose.call( this );
+};
+
+AnimationBaseNode.prototype.getMinFrameCount = function()
+{
+ return this.nMinFrameCount;
+};
+
+AnimationBaseNode.prototype.getAdditiveMode = function()
+{
+ return this.eAdditiveMode;
+};
+
+AnimationBaseNode.prototype.info = function( bVerbose )
+{
+ var sInfo = AnimationBaseNode.superclass.info.call( this, bVerbose );
+
+ if( bVerbose )
+ {
+ // min frame count
+ if( this.getMinFrameCount() )
+ sInfo += '; min frame count: ' + this.getMinFrameCount();
+
+ // additive mode
+ sInfo += '; additive: ' + aAddittiveModeOutMap[ this.getAdditiveMode() ];
+
+ // target element
+ if( this.getTargetElement() )
+ {
+ var sElemId = this.getTargetElement().getAttribute( 'id' );
+ sInfo += '; targetElement: ' + sElemId;
+ }
+ }
+
+ return sInfo;
+};
+
+
+
+function AnimationBaseNode2( aAnimElem, aParentNode, aNodeContext )
+{
+ AnimationBaseNode2.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sAttributeName = '';
+ this.aToValue = null;
+
+}
+extend( AnimationBaseNode2, AnimationBaseNode );
+
+
+AnimationBaseNode2.prototype.parseElement = function()
+{
+ var bRet = AnimationBaseNode2.superclass.parseElement.call( this );
+
+ var aAnimElem = this.aElement;
+
+ // attributeName attribute
+ this.sAttributeName = aAnimElem.getAttributeNS( NSS['smil'], 'attributeName' );
+ if( !this.sAttributeName )
+ {
+ this.eCurrentState = INVALID_NODE;
+ log( 'AnimationBaseNode2.parseElement: target attribute name not found: ' + this.sAttributeName );
+ }
+
+ // to attribute
+ this.aToValue = aAnimElem.getAttributeNS( NSS['smil'], 'to' );
+
+ return bRet;
+};
+
+AnimationBaseNode2.prototype.getAttributeName = function()
+{
+ return this.sAttributeName;
+};
+
+AnimationBaseNode2.prototype.getToValue = function()
+{
+ return this.aToValue;
+};
+
+AnimationBaseNode2.prototype.info = function( bVerbose )
+{
+ var sInfo = AnimationBaseNode2.superclass.info.call( this, bVerbose );
+
+ if( bVerbose )
+ {
+ // attribute name
+ if( this.getAttributeName() )
+ sInfo += '; attributeName: ' + this.getAttributeName();
+
+ // To
+ if( this.getToValue() )
+ sInfo += '; to: ' + this.getToValue();
+ }
+
+ return sInfo;
+};
+
+
+
+
+function AnimationBaseNode3( aAnimElem, aParentNode, aNodeContext )
+{
+ AnimationBaseNode3.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.eAccumulate = undefined;
+ this.eCalcMode = undefined;
+ this.aFromValue = null;
+ this.aByValue = null;
+ this.aKeyTimes = null;
+ this.aValues = null;
+ this.aFormula= null;
+}
+extend( AnimationBaseNode3, AnimationBaseNode2 );
+
+
+AnimationBaseNode3.prototype.parseElement = function()
+{
+ var bRet = AnimationBaseNode3.superclass.parseElement.call( this );
+
+ var aAnimElem = this.aElement;
+
+ // accumulate attribute
+ this.eAccumulate = ACCUMULATE_MODE_NONE;
+ var sAccumulateAttr = aAnimElem.getAttributeNS( NSS['smil'], 'accumulate' );
+ if( sAccumulateAttr == 'sum' )
+ this.eAccumulate = ACCUMULATE_MODE_SUM;
+
+ // calcMode attribute
+ this.eCalcMode = CALC_MODE_LINEAR;
+ var sCalcModeAttr = aAnimElem.getAttributeNS( NSS['smil'], 'calcMode' );
+ if( sCalcModeAttr && aCalcModeInMap[ sCalcModeAttr ] )
+ this.eCalcMode = aCalcModeInMap[ sCalcModeAttr ];
+
+ // from attribute
+ this.aFromValue = aAnimElem.getAttributeNS( NSS['smil'], 'from' );
+
+ // by attribute
+ this.aByValue = aAnimElem.getAttributeNS( NSS['smil'], 'by' );
+
+ // keyTimes attribute
+ this.aKeyTimes = [];
+ var sKeyTimesAttr = aAnimElem.getAttributeNS( NSS['smil'], 'keyTimes' );
+ sKeyTimesAttr = removeWhiteSpaces( sKeyTimesAttr );
+ if( sKeyTimesAttr )
+ {
+ var aKeyTimes = sKeyTimesAttr.split( ';' );
+ for( var i = 0; i < aKeyTimes.length; ++i )
+ this.aKeyTimes.push( parseFloat( aKeyTimes[i] ) );
+ }
+
+ // values attribute
+ var sValuesAttr = aAnimElem.getAttributeNS( NSS['smil'], 'values' );
+ if( sValuesAttr )
+ {
+ this.aValues = sValuesAttr.split( ';' );
+ }
+ else
+ {
+ this.aValues = [];
+ }
+
+ // formula attribute
+ this.aFormula = aAnimElem.getAttributeNS( NSS['anim'], 'formula' );
+
+ return bRet;
+};
+
+AnimationBaseNode3.prototype.getAccumulate = function()
+{
+ return this.eAccumulate;
+};
+
+AnimationBaseNode3.prototype.getCalcMode = function()
+{
+ return this.eCalcMode;
+};
+
+AnimationBaseNode3.prototype.getFromValue = function()
+{
+ return this.aFromValue;
+};
+
+AnimationBaseNode3.prototype.getByValue = function()
+{
+ return this.aByValue;
+};
+
+AnimationBaseNode3.prototype.getKeyTimes = function()
+{
+ return this.aKeyTimes;
+};
+
+AnimationBaseNode3.prototype.getValues = function()
+{
+ return this.aValues;
+};
+
+AnimationBaseNode3.prototype.getFormula = function()
+{
+ return this.aFormula;
+};
+
+AnimationBaseNode3.prototype.info = function( bVerbose )
+{
+ var sInfo = AnimationBaseNode3.superclass.info.call( this, bVerbose );
+
+ if( bVerbose )
+ {
+ // accumulate mode
+ if( this.getAccumulate() )
+ sInfo += '; accumulate: ' + aAccumulateModeOutMap[ this.getAccumulate() ];
+
+ // calcMode
+ sInfo += '; calcMode: ' + aCalcModeOutMap[ this.getCalcMode() ];
+
+ // from
+ if( this.getFromValue() )
+ sInfo += '; from: ' + this.getFromValue();
+
+ // by
+ if( this.getByValue() )
+ sInfo += '; by: ' + this.getByValue();
+
+ // keyTimes
+ if( this.getKeyTimes().length )
+ sInfo += '; keyTimes: ' + this.getKeyTimes().join( ',' );
+
+ // values
+ if( this.getValues().length )
+ sInfo += '; values: ' + this.getValues().join( ',' );
+
+ // formula
+ if( this.getFormula() )
+ sInfo += '; formula: ' + this.getFormula();
+ }
+
+ return sInfo;
+};
+
+
+
+
+function BaseContainerNode( aAnimElem, aParentNode, aNodeContext )
+{
+ BaseContainerNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'BaseContainerNode';
+ this.bIsContainer = true;
+ this.aChildrenArray = [];
+ this.nFinishedChildren = 0;
+ this.bDurationIndefinite = false;
+ this.nLeftIterations = 1;
+
+ this.eImpressNodeType = undefined;
+ this.ePresetClass = undefined;
+ this.ePresetId = undefined;
+}
+extend( BaseContainerNode, BaseNode );
+
+
+BaseContainerNode.prototype.parseElement= function()
+{
+ var bRet = BaseContainerNode.superclass.parseElement.call( this );
+
+ var aAnimElem = this.aElement;
+
+ // node-type attribute
+ this.eImpressNodeType = IMPRESS_DEFAULT_NODE;
+ var sNodeTypeAttr = aAnimElem.getAttributeNS( NSS['presentation'], 'node-type' );
+ if( sNodeTypeAttr && aImpressNodeTypeInMap[ sNodeTypeAttr ] )
+ this.eImpressNodeType = aImpressNodeTypeInMap[ sNodeTypeAttr ];
+ this.bMainSequenceRootNode = ( this.eImpressNodeType == IMPRESS_MAIN_SEQUENCE_NODE );
+ this.bInteractiveSequenceRootNode = ( this.eImpressNodeType == IMPRESS_INTERACTIVE_SEQUENCE_NODE );
+
+ // preset-class attribute
+ this.ePresetClass = undefined;
+ var sPresetClassAttr = aAnimElem.getAttributeNS( NSS['presentation'], 'preset-class' );
+ if( sPresetClassAttr && aPresetClassInMap[ sPresetClassAttr ] )
+ this.ePresetClass = aPresetClassInMap[ sPresetClassAttr ];
+
+ // preset-id attribute
+ this.ePresetId = undefined;
+ var sPresetIdAttr = aAnimElem.getAttributeNS( NSS['presentation'], 'preset-id' );
+ if( sPresetIdAttr && aPresetIdInMap[ sPresetIdAttr ] )
+ this.ePresetId = aPresetIdInMap[ sPresetIdAttr ];
+
+
+ // parse children elements
+ var nChildrenCount = this.aChildrenArray.length;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ this.aChildrenArray[i].parseElement();
+ }
+
+
+ // resolve duration
+ this.bDurationIndefinite
+ = ( !this.getDuration() || this.getDuration().isIndefinite() ) &&
+ ( !this.getEnd() || ( this.getEnd().getType() != OFFSET_TIMING ) );
+
+ return bRet;
+};
+
+BaseContainerNode.prototype.appendChildNode = function( aAnimationNode )
+{
+ if( ! this.checkValidNode() )
+ return ;
+
+ if( aAnimationNode.registerDeactivatingListener( this ) )
+ this.aChildrenArray.push( aAnimationNode );
+};
+
+BaseContainerNode.prototype.removeAllChildrenNodes = function()
+{
+ this.aChildrenArray = [];
+};
+
+BaseContainerNode.prototype.init_st = function()
+{
+ this.nLeftIterations = this.getRepeatCount();
+
+ return this.init_children();
+};
+
+BaseContainerNode.prototype.init_children = function()
+{
+ this.nFinishedChildren = 0;
+ var nChildrenCount = this.aChildrenArray.length;
+ var nInitChildren = 0;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ if( this.aChildrenArray[i].init() )
+ {
+ ++nInitChildren;
+ }
+ }
+ return ( nChildrenCount == nInitChildren );
+};
+
+
+BaseContainerNode.prototype.deactivate_st = function( eDestState )
+{
+ this.nLeftIterations = 0;
+ if( eDestState == FROZEN_NODE )
+ {
+ // deactivate all children that are not FROZEN or ENDED:
+ this.forEachChildNode( mem_fn( 'deactivate' ), ~( FROZEN_NODE | ENDED_NODE ) );
+ }
+ else
+ {
+ // end all children that are not ENDED:
+ this.forEachChildNode( mem_fn( 'end' ), ~ENDED_NODE );
+ if( this.getFillMode() == FILL_MODE_REMOVE )
+ this.removeEffect();
+ }
+};
+
+BaseContainerNode.prototype.hasPendingAnimation = function()
+{
+ var nChildrenCount = this.aChildrenArray.length;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ if( this.aChildrenArray[i].hasPendingAnimation() )
+ return true;
+ }
+ return false;
+};
+
+BaseContainerNode.prototype.activate_st = function()
+{
+ log( 'BaseContainerNode.activate_st: abstract method called' );
+};
+
+BaseContainerNode.prototype.notifyDeactivating = function( /*aAnimationNode*/ )
+{
+ log( 'BaseContainerNode.notifyDeactivating: abstract method called' );
+};
+
+BaseContainerNode.prototype.isDurationIndefinite = function()
+{
+ return this.bDurationIndefinite;
+};
+
+BaseContainerNode.prototype.isChildNode = function( aAnimationNode )
+{
+ var nChildrenCount = this.aChildrenArray.length;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ if( this.aChildrenArray[i].getId() == aAnimationNode.getId() )
+ return true;
+ }
+ return false;
+};
+
+BaseContainerNode.prototype.notifyDeactivatedChild = function( aChildNode )
+{
+ assert( ( aChildNode.getState() == FROZEN_NODE ) || ( aChildNode.getState() == ENDED_NODE ),
+ 'BaseContainerNode.notifyDeactivatedChild: passed child node is neither in FROZEN nor in ENDED state' );
+
+ assert( this.getState() != INVALID_NODE,
+ 'BaseContainerNode.notifyDeactivatedChild: this node is invalid' );
+
+ if( !this.isChildNode( aChildNode ) )
+ {
+ log( 'BaseContainerNode.notifyDeactivatedChild: unknown child notifier!' );
+ return false;
+ }
+
+ var nChildrenCount = this.aChildrenArray.length;
+
+ assert( ( this.nFinishedChildren < nChildrenCount ),
+ 'BaseContainerNode.notifyDeactivatedChild: assert(this.nFinishedChildren < nChildrenCount) failed' );
+
+ ++this.nFinishedChildren;
+ var bFinished = ( this.nFinishedChildren >= nChildrenCount );
+
+ if( bFinished && this.isDurationIndefinite() )
+ {
+ if( this.nLeftIterations >= 1.0 )
+ {
+ this.nLeftIterations -= 1.0;
+ }
+ if( this.nLeftIterations >= 1.0 )
+ {
+ bFinished = false;
+ var aRepetitionEvent = makeDelay( bind( this, this.repeat ), 0.0 );
+ this.aContext.aTimerEventQueue.addEvent( aRepetitionEvent );
+ }
+ else
+ {
+ this.deactivate();
+ }
+ }
+
+ return bFinished;
+};
+
+BaseContainerNode.prototype.repeat = function()
+{
+ // end all children that are not ENDED:
+ this.forEachChildNode( mem_fn( 'end' ), ~ENDED_NODE );
+ this.removeEffect();
+ var bInitialized = this.init_children();
+ if( bInitialized )
+ this.activate_st();
+ return bInitialized;
+};
+
+BaseContainerNode.prototype.removeEffect = function()
+{
+ var nChildrenCount = this.aChildrenArray.length;
+ if( nChildrenCount == 0 )
+ return;
+ // We remove effect in reverse order.
+ for( var i = nChildrenCount - 1; i >= 0; --i )
+ {
+ if( ( this.aChildrenArray[i].getState() & ( FROZEN_NODE | ENDED_NODE ) ) == 0 )
+ {
+ log( 'BaseContainerNode.removeEffect: child(id:'
+ + this.aChildrenArray[i].getId() + ') is neither frozen nor ended;'
+ + ' state: '
+ + aTransitionModeOutMap[ this.aChildrenArray[i].getState() ] );
+ continue;
+ }
+ this.aChildrenArray[i].removeEffect();
+ }
+};
+
+BaseContainerNode.prototype.saveStateOfAnimatedElement = function()
+{
+ var nChildrenCount = this.aChildrenArray.length;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ this.aChildrenArray[i].saveStateOfAnimatedElement();
+ }
+};
+
+BaseContainerNode.prototype.forEachChildNode = function( aFunction, eNodeStateMask )
+{
+ if( !eNodeStateMask )
+ eNodeStateMask = -1;
+
+ var nChildrenCount = this.aChildrenArray.length;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ if( ( eNodeStateMask != -1 ) && ( ( this.aChildrenArray[i].getState() & eNodeStateMask ) == 0 ) )
+ continue;
+ aFunction( this.aChildrenArray[i] );
+ }
+};
+
+BaseContainerNode.prototype.dispose = function()
+{
+ var nChildrenCount = this.aChildrenArray.length;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ this.aChildrenArray[i].dispose();
+ }
+
+ BaseContainerNode.superclass.dispose.call( this );
+};
+
+BaseContainerNode.prototype.getImpressNodeType = function()
+{
+ return this.eImpressNodeType;
+};
+
+BaseContainerNode.prototype.info = function( bVerbose )
+{
+ var sInfo = BaseContainerNode.superclass.info.call( this, bVerbose );
+
+ if( bVerbose )
+ {
+ // impress node type
+ if( this.getImpressNodeType() )
+ sInfo += '; node-type: ' + aImpressNodeTypeOutMap[ this.getImpressNodeType() ];
+ }
+
+ var nChildrenCount = this.aChildrenArray.length;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ sInfo += '\n';
+ sInfo += this.aChildrenArray[i].info( bVerbose );
+ }
+
+ return sInfo;
+};
+
+
+function ParallelTimeContainer( aAnimElem, aParentNode, aNodeContext )
+{
+ ParallelTimeContainer.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'ParallelTimeContainer';
+}
+extend( ParallelTimeContainer, BaseContainerNode );
+
+
+ParallelTimeContainer.prototype.activate_st = function()
+{
+ var nChildrenCount = this.aChildrenArray.length;
+ var nResolvedChildren = 0;
+ for( var i = 0; i < nChildrenCount; ++i )
+ {
+ if( this.aChildrenArray[i].resolve() )
+ {
+ ++nResolvedChildren;
+ }
+ }
+
+ if( nChildrenCount != nResolvedChildren )
+ {
+ log( 'ParallelTimeContainer.activate_st: resolving all children failed' );
+ return;
+ }
+
+
+ if( this.isDurationIndefinite() && ( nChildrenCount == 0 ) )
+ {
+ this.scheduleDeactivationEvent( this.makeDeactivationEvent( 0.0 ) );
+ }
+ else
+ {
+ this.scheduleDeactivationEvent();
+ }
+};
+
+ParallelTimeContainer.prototype.notifyDeactivating = function( aAnimationNode )
+{
+ this.notifyDeactivatedChild( aAnimationNode );
+};
+
+
+
+
+function SequentialTimeContainer( aAnimElem, aParentNode, aNodeContext )
+{
+ SequentialTimeContainer.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'SequentialTimeContainer';
+ this.bIsRewinding = false;
+ this.aCurrentSkipEvent = null;
+ this.aRewindCurrentEffectEvent = null;
+ this.aRewindLastEffectEvent = null;
+}
+extend( SequentialTimeContainer, BaseContainerNode );
+
+
+SequentialTimeContainer.prototype.activate_st = function()
+{
+ var nChildrenCount = this.aChildrenArray.length;
+ for( ; this.nFinishedChildren < nChildrenCount; ++this.nFinishedChildren )
+ {
+ if( this.resolveChild( this.aChildrenArray[ this.nFinishedChildren ] ) )
+ break;
+ else
+ log( 'SequentialTimeContainer.activate_st: resolving child failed!' );
+ }
+
+ if( this.isDurationIndefinite() && ( ( nChildrenCount == 0 ) || ( this.nFinishedChildren >= nChildrenCount ) ) )
+ {
+ // deactivate ASAP:
+ this.scheduleDeactivationEvent( this.makeDeactivationEvent( 0.0 ) );
+ }
+ else
+ {
+ this.scheduleDeactivationEvent();
+ }
+};
+
+SequentialTimeContainer.prototype.notifyDeactivating = function( aNotifier )
+{
+ // If we are rewinding we have not to resolve the next child.
+ if( this.bIsRewinding )
+ return;
+
+ if( this.notifyDeactivatedChild( aNotifier ) )
+ return;
+
+ assert( this.nFinishedChildren < this.aChildrenArray.length,
+ 'SequentialTimeContainer.notifyDeactivating: assertion (this.nFinishedChildren < this.aChildrenArray.length) failed' );
+
+ var aNextChild = this.aChildrenArray[ this.nFinishedChildren ];
+
+ assert( aNextChild.getState() == UNRESOLVED_NODE,
+ 'SequentialTimeContainer.notifyDeactivating: assertion (aNextChild.getState == UNRESOLVED_NODE) failed' );
+
+ if( !this.resolveChild( aNextChild ) )
+ {
+ // could not resolve child - since we risk to
+ // stall the chain of events here, play it safe
+ // and deactivate this node (only if we have
+ // indefinite duration - otherwise, we'll get a
+ // deactivation event, anyways).
+ this.deactivate();
+ }
+};
+
+/** skipEffect
+ * Skip the current playing shape effect.
+ * Requires: the current node is the main sequence root node.
+ *
+ * @param aChildNode
+ * An animation node representing the root node of the shape effect being
+ * played.
+ */
+SequentialTimeContainer.prototype.skipEffect = function( aChildNode )
+{
+ if( this.isChildNode( aChildNode ) )
+ {
+ // First off we end all queued activities.
+ this.getContext().aActivityQueue.endAll();
+ // We signal that we are going to skip all subsequent animations by
+ // setting the bIsSkipping flag to 'true', then all queued events are
+ // fired immediately. In such a way the correct order of the various
+ // events that belong to the animation time-line is preserved.
+ this.getContext().bIsSkipping = true;
+ this.getContext().aTimerEventQueue.forceEmpty();
+ this.getContext().bIsSkipping = false;
+ var aEvent = makeEvent( bind2( aChildNode.deactivate, aChildNode ) );
+ this.getContext().aTimerEventQueue.addEvent( aEvent );
+ }
+ else
+ {
+ log( 'SequentialTimeContainer.skipEffect: unknown child: '
+ + aChildNode.getId() );
+ }
+};
+
+/** rewindCurrentEffect
+ * Rewind a playing shape effect.
+ * Requires: the current node is the main sequence root node.
+ *
+ * @param aChildNode
+ * An animation node representing the root node of the shape effect being
+ * played
+ */
+SequentialTimeContainer.prototype.rewindCurrentEffect = function( aChildNode )
+{
+ if( this.isChildNode( aChildNode ) )
+ {
+ assert( !this.bIsRewinding,
+ 'SequentialTimeContainer.rewindCurrentEffect: is already rewinding.' );
+
+ // We signal we are rewinding so the notifyDeactivating method returns
+ // immediately without increment the finished children counter and
+ // resolve the next child.
+ this.bIsRewinding = true;
+ // First off we end all queued activities.
+ this.getContext().aActivityQueue.endAll();
+ // We signal that we are going to skip all subsequent animations by
+ // setting the bIsSkipping flag to 'true', then all queued events are
+ // fired immediately. In such a way the correct order of the various
+ // events that belong to the animation time-line is preserved.
+ this.getContext().bIsSkipping = true;
+ this.getContext().aTimerEventQueue.forceEmpty();
+ this.getContext().bIsSkipping = false;
+ // We end all new activities appended to the activity queue by
+ // the fired events.
+ this.getContext().aActivityQueue.endAll();
+
+ // Now we perform a final 'end' and restore the animated shape to
+ // the state it was before the current effect was applied.
+ aChildNode.end();
+ aChildNode.removeEffect();
+ // Finally we place the child node to the 'unresolved' state and
+ // resolve it again.
+ aChildNode.init();
+ this.resolveChild( aChildNode );
+ this.notifyRewindedEvent( aChildNode );
+ this.bIsRewinding = false;
+ }
+ else
+ {
+ log( 'SequentialTimeContainer.rewindCurrentEffect: unknown child: '
+ + aChildNode.getId() );
+ }
+};
+
+/** rewindLastEffect
+ * Rewind the last ended effect.
+ * Requires: the current node is the main sequence root node.
+ *
+ * @param aChildNode
+ * An animation node representing the root node of the next shape effect
+ * to be played.
+ */
+SequentialTimeContainer.prototype.rewindLastEffect = function( aChildNode )
+{
+ if( this.isChildNode( aChildNode ) )
+ {
+ assert( !this.bIsRewinding,
+ 'SequentialTimeContainer.rewindLastEffect: is already rewinding.' );
+
+ // We signal we are rewinding so the notifyDeactivating method returns
+ // immediately without increment the finished children counter and
+ // resolve the next child.
+ this.bIsRewinding = true;
+ // We end the current effect.
+ this.getContext().aTimerEventQueue.forceEmpty();
+ this.getContext().aActivityQueue.clear();
+ aChildNode.end();
+ // Invoking the end method on the current child node that has not yet
+ // been activated should not lead to any change on the animated shape.
+ // However for safety we used to call the removeEffect method but
+ // lately we noticed that when interactive animation sequences are
+ // involved into the shape effect invoking such a method causes
+ // some issue.
+ //aChildNode.removeEffect();
+
+ // As we rewind the previous effect we need to decrease the finished
+ // children counter.
+ --this.nFinishedChildren;
+ var aPreviousChildNode = this.aChildrenArray[ this.nFinishedChildren ];
+ // No need to invoke the end method for the previous child as it is
+ // already in the ENDED state.
+
+ aPreviousChildNode.removeEffect();
+ // We place the child node to the 'unresolved' state.
+ aPreviousChildNode.init();
+ // We need to re-initialize the old current child too, because it is
+ // in ENDED state now, On the contrary it cannot be resolved again later.
+ aChildNode.init();
+ this.resolveChild( aPreviousChildNode );
+ this.notifyRewindedEvent( aChildNode );
+ this.bIsRewinding = false;
+ }
+ else
+ {
+ log( 'SequentialTimeContainer.rewindLastEffect: unknown child: '
+ + aChildNode.getId() );
+ }
+};
+
+/** resolveChild
+ * Resolve the passed child.
+ * In case this node is a main sequence root node events for skipping and
+ * rewinding the effect related to the passed child node are created and
+ * registered.
+ *
+ * @param aChildNode
+ * An animation node representing the root node of the next shape effect
+ * to be played.
+ * @return
+ * It returns true if the passed child has been resolved successfully,
+ * false otherwise.
+ */
+SequentialTimeContainer.prototype.resolveChild = function( aChildNode )
+{
+ var bResolved = aChildNode.resolve();
+
+ if( bResolved && ( this.isMainSequenceRootNode() || this.isInteractiveSequenceRootNode() ) )
+ {
+ if( this.aCurrentSkipEvent )
+ this.aCurrentSkipEvent.dispose();
+ this.aCurrentSkipEvent = makeEvent( bind2( SequentialTimeContainer.prototype.skipEffect, this, aChildNode ) );
+
+ if( this.aRewindCurrentEffectEvent )
+ this.aRewindCurrentEffectEvent.dispose();
+ this.aRewindCurrentEffectEvent = makeEvent( bind2( SequentialTimeContainer.prototype.rewindCurrentEffect, this, aChildNode ) );
+
+ if( this.aRewindLastEffectEvent )
+ this.aRewindLastEffectEvent.dispose();
+ this.aRewindLastEffectEvent = makeEvent( bind2( SequentialTimeContainer.prototype.rewindLastEffect, this, aChildNode ) );
+
+ if( this.isMainSequenceRootNode() )
+ {
+ this.aContext.aEventMultiplexer.registerSkipEffectEvent( this.aCurrentSkipEvent );
+ this.aContext.aEventMultiplexer.registerRewindCurrentEffectEvent( this.aRewindCurrentEffectEvent );
+ this.aContext.aEventMultiplexer.registerRewindLastEffectEvent( this.aRewindLastEffectEvent );
+ }
+ else if( this.isInteractiveSequenceRootNode() )
+ {
+ this.aContext.aEventMultiplexer.registerSkipInteractiveEffectEvent( aChildNode.getId(), this.aCurrentSkipEvent );
+ this.aContext.aEventMultiplexer.registerRewindRunningInteractiveEffectEvent( aChildNode.getId(), this.aRewindCurrentEffectEvent );
+ this.aContext.aEventMultiplexer.registerRewindEndedInteractiveEffectEvent( aChildNode.getId(), this.aRewindLastEffectEvent );
+ }
+ }
+ return bResolved;
+};
+
+SequentialTimeContainer.prototype.notifyRewindedEvent = function( aChildNode )
+{
+ if( this.isInteractiveSequenceRootNode() )
+ {
+ this.aContext.aEventMultiplexer.notifyRewindedEffectEvent( aChildNode.getId() );
+
+ var sId = aChildNode.getBegin().getEventBaseElementId();
+ if( sId )
+ {
+ this.aContext.aEventMultiplexer.notifyRewindedEffectEvent( sId );
+ }
+ }
+};
+
+SequentialTimeContainer.prototype.dispose = function()
+{
+ if( this.aCurrentSkipEvent )
+ this.aCurrentSkipEvent.dispose();
+
+ SequentialTimeContainer.superclass.dispose.call( this );
+};
+
+
+
+
+function PropertyAnimationNode( aAnimElem, aParentNode, aNodeContext )
+{
+ PropertyAnimationNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'PropertyAnimationNode';
+}
+extend( PropertyAnimationNode, AnimationBaseNode3 );
+
+
+PropertyAnimationNode.prototype.createActivity = function()
+{
+ var aActivityParamSet = this.fillActivityParams();
+
+ var aAnimation = createPropertyAnimation( this.getAttributeName(),
+ this.getAnimatedElement(),
+ this.aNodeContext.aSlideWidth,
+ this.aNodeContext.aSlideHeight );
+
+ var aInterpolator = null; // createActivity will compute it;
+ return createActivity( aActivityParamSet, this, aAnimation, aInterpolator );
+};
+
+
+
+
+function isValidTransformation( sType )
+{
+ return ( sType === 'translate' || sType === 'scale' || sType === 'rotate'
+ || sType === 'skewX' || sType === 'skewY' );
+}
+
+function AnimationTransformNode( aAnimElem, aParentNode, aNodeContext )
+{
+ AnimationTransformNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'AnimationTransformNode';
+}
+extend( AnimationTransformNode, AnimationBaseNode3 );
+
+
+AnimationTransformNode.prototype.parseElement = function()
+{
+ var bRet = AnimationTransformNode.superclass.parseElement.call(this);
+
+ var aAnimElem = this.aElement;
+
+ // transformation type
+ var sTransformType = aAnimElem.getAttribute( 'svg:type' );
+ if( !isValidTransformation( sTransformType ) )
+ {
+ this.eCurrentState = INVALID_NODE;
+ log( 'AnimationTransformNode.parseElement: transformation type not found: ' + sTransformType );
+ }
+ else
+ {
+ this.sAttributeName = sTransformType;
+ }
+
+ return bRet;
+}
+
+AnimationTransformNode.prototype.createActivity = function()
+{
+ var aActivityParamSet = this.fillActivityParams();
+ var aAnimation;
+
+ if( this.getAttributeName() === 'scale' || this.getAttributeName() === 'translate' )
+ {
+ aAnimation = createPairPropertyAnimation( this.getAttributeName(),
+ this.getAnimatedElement(),
+ this.aNodeContext.aSlideWidth,
+ this.aNodeContext.aSlideHeight );
+
+ }
+ else
+ {
+ aAnimation = createPropertyAnimation( this.getAttributeName(),
+ this.getAnimatedElement(),
+ this.aNodeContext.aSlideWidth,
+ this.aNodeContext.aSlideHeight );
+ }
+
+ var aInterpolator = null; // createActivity will compute it;
+ return createActivity( aActivityParamSet, this, aAnimation, aInterpolator );
+};
+
+
+
+
+function AnimationSetNode( aAnimElem, aParentNode, aNodeContext )
+{
+ AnimationSetNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'AnimationSetNode';
+}
+extend( AnimationSetNode, AnimationBaseNode2 );
+
+
+AnimationSetNode.prototype.createActivity = function()
+{
+ var aAnimation = createPropertyAnimation( this.getAttributeName(),
+ this.getAnimatedElement(),
+ this.aNodeContext.aSlideWidth,
+ this.aNodeContext.aSlideHeight );
+
+ var aActivityParamSet = this.fillActivityParams();
+
+ return new SetActivity( aActivityParamSet, aAnimation, this.getToValue() );
+};
+
+
+
+
+function AnimationColorNode( aAnimElem, aParentNode, aNodeContext )
+{
+ AnimationColorNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'AnimationColorNode';
+
+ this.eColorInterpolation = undefined;
+ this.eColorInterpolationDirection = undefined;
+}
+extend( AnimationColorNode, AnimationBaseNode3 );
+
+
+AnimationColorNode.prototype.parseElement = function()
+{
+ var bRet = AnimationColorNode.superclass.parseElement.call( this );
+
+ var aAnimElem = this.aElement;
+
+ // color-interpolation attribute
+ this.eColorInterpolation = COLOR_SPACE_RGB;
+ var sColorInterpolationAttr = aAnimElem.getAttributeNS( NSS['anim'], 'color-interpolation' );
+ if( sColorInterpolationAttr && aColorSpaceInMap[ sColorInterpolationAttr ] )
+ this.eColorInterpolation = aColorSpaceInMap[ sColorInterpolationAttr ];
+
+ // color-interpolation-direction attribute
+ this.eColorInterpolationDirection = CLOCKWISE;
+ var sColorInterpolationDirectionAttr = aAnimElem.getAttributeNS( NSS['anim'], 'color-interpolation-direction' );
+ if( sColorInterpolationDirectionAttr && aClockDirectionInMap[ sColorInterpolationDirectionAttr ] )
+ this.eColorInterpolationDirection = aClockDirectionInMap[ sColorInterpolationDirectionAttr ];
+
+ return bRet;
+};
+
+AnimationColorNode.prototype.createActivity = function()
+{
+ var aActivityParamSet = this.fillActivityParams();
+
+ var aAnimation = createPropertyAnimation( this.getAttributeName(),
+ this.getAnimatedElement(),
+ this.aNodeContext.aSlideWidth,
+ this.aNodeContext.aSlideHeight );
+
+ var aColorAnimation;
+ var aInterpolator;
+ if( this.getColorInterpolation() === COLOR_SPACE_HSL )
+ {
+ ANIMDBG.print( 'AnimationColorNode.createActivity: color space hsl' );
+ aColorAnimation = new HSLAnimationWrapper( aAnimation );
+ var aInterpolatorMaker = aInterpolatorHandler.getInterpolator( this.getCalcMode(),
+ COLOR_PROPERTY,
+ COLOR_SPACE_HSL );
+ aInterpolator = aInterpolatorMaker( this.getColorInterpolationDirection() );
+ }
+ else
+ {
+ ANIMDBG.print( 'AnimationColorNode.createActivity: color space rgb' );
+ aColorAnimation = aAnimation;
+ aInterpolator = aInterpolatorHandler.getInterpolator( this.getCalcMode(),
+ COLOR_PROPERTY,
+ COLOR_SPACE_RGB );
+ }
+
+ return createActivity( aActivityParamSet, this, aColorAnimation, aInterpolator );
+};
+
+AnimationColorNode.prototype.getColorInterpolation = function()
+{
+ return this.eColorInterpolation;
+};
+
+AnimationColorNode.prototype.getColorInterpolationDirection = function()
+{
+ return this.eColorInterpolationDirection;
+};
+
+AnimationColorNode.prototype.info = function( bVerbose )
+{
+ var sInfo = AnimationColorNode.superclass.info.call( this, bVerbose );
+
+ if( bVerbose )
+ {
+ // color interpolation
+ sInfo += '; color-interpolation: ' + aColorSpaceOutMap[ this.getColorInterpolation() ];
+
+ // color interpolation direction
+ sInfo += '; color-interpolation-direction: ' + aClockDirectionOutMap[ this.getColorInterpolationDirection() ];
+ }
+ return sInfo;
+};
+
+
+
+
+function AnimationTransitionFilterNode( aAnimElem, aParentNode, aNodeContext )
+{
+ AnimationTransitionFilterNode.superclass.constructor.call( this, aAnimElem, aParentNode, aNodeContext );
+
+ this.sClassName = 'AnimationTransitionFilterNode';
+
+ this.eTransitionType = undefined;
+ this.eTransitionSubType = undefined;
+ this.bReverseDirection = undefined;
+ this.eTransitionMode = undefined;
+}
+extend( AnimationTransitionFilterNode, AnimationBaseNode );
+
+
+AnimationTransitionFilterNode.prototype.createActivity = function()
+{
+ var aActivityParamSet = this.fillActivityParams();
+
+ return createShapeTransition( aActivityParamSet,
+ this.getAnimatedElement(),
+ this.aNodeContext.aSlideWidth,
+ this.aNodeContext.aSlideHeight,
+ this );
+};
+
+AnimationTransitionFilterNode.prototype.parseElement = function()
+{
+ var bRet = AnimationTransitionFilterNode.superclass.parseElement.call( this );
+ var bIsValidTransition = true;
+
+ var aAnimElem = this.aElement;
+
+ // type attribute
+ this.eTransitionType = undefined;
+ var sTypeAttr = aAnimElem.getAttributeNS( NSS['smil'], 'type' );
+ if( sTypeAttr && aTransitionTypeInMap[ sTypeAttr ] )
+ {
+ this.eTransitionType = aTransitionTypeInMap[ sTypeAttr ];
+ }
+ else
+ {
+ bIsValidTransition = false;
+ log( 'AnimationTransitionFilterNode.parseElement: transition type not valid: ' + sTypeAttr );
+ }
+
+ // subtype attribute
+ this.eTransitionSubType = undefined;
+ var sSubTypeAttr = aAnimElem.getAttributeNS( NSS['smil'], 'subtype' );
+ if( sSubTypeAttr === null )
+ sSubTypeAttr = 'default';
+ if( sSubTypeAttr && ( aTransitionSubtypeInMap[ sSubTypeAttr ] !== undefined ) )
+ {
+ this.eTransitionSubType = aTransitionSubtypeInMap[ sSubTypeAttr ];
+ }
+ else
+ {
+ bIsValidTransition = false;
+ log( 'AnimationTransitionFilterNode.parseElement: transition subtype not valid: ' + sSubTypeAttr );
+ }
+
+ // if we do not support the requested transition type we fall back to crossfade transition;
+ // note: if we do not provide an alternative transition and we set the state of the animation node to 'invalid'
+ // the animation engine stops itself;
+ if( !bIsValidTransition )
+ {
+ this.eTransitionType = FADE_TRANSITION;
+ this.eTransitionSubType = CROSSFADE_TRANS_SUBTYPE;
+ log( 'AnimationTransitionFilterNode.parseElement: in place of the invalid transition a crossfade transition is used' );
+ }
+
+ // direction attribute
+ this.bReverseDirection = false;
+ var sDirectionAttr = aAnimElem.getAttributeNS( NSS['smil'], 'direction' );
+ if( sDirectionAttr == 'reverse' )
+ this.bReverseDirection = true;
+
+ // mode attribute:
+ this.eTransitionMode = TRANSITION_MODE_IN;
+ var sModeAttr = aAnimElem.getAttributeNS( NSS['smil'], 'mode' );
+ if( sModeAttr === 'out' )
+ this.eTransitionMode = TRANSITION_MODE_OUT;
+
+ return bRet;
+};
+
+AnimationTransitionFilterNode.prototype.getTransitionType = function()
+{
+ return this.eTransitionType;
+};
+
+AnimationTransitionFilterNode.prototype.getTransitionSubType = function()
+{
+ return this.eTransitionSubType;
+};
+
+AnimationTransitionFilterNode.prototype.getTransitionMode = function()
+{
+ return this.eTransitionMode;
+};
+
+AnimationTransitionFilterNode.prototype.getReverseDirection = function()
+{
+ return this.bReverseDirection;
+};
+
+AnimationTransitionFilterNode.prototype.info = function( bVerbose )
+{
+ var sInfo = AnimationTransitionFilterNode.superclass.info.call( this, bVerbose );
+
+ if( bVerbose )
+ {
+ // transition type
+ sInfo += '; type: ' + getKeyByValue(aTransitionTypeInMap, this.getTransitionType());
+
+ // transition subtype
+ sInfo += '; subtype: ' + getKeyByValue(aTransitionSubtypeInMap, this.getTransitionSubType());
+
+ // transition direction
+ if( this.getReverseDirection() )
+ sInfo += '; direction: reverse';
+ }
+
+ return sInfo;
+};
+
+
+
+/**********************************************************************************************
+ * Animation Node Factory
+ **********************************************************************************************/
+
+
+function createAnimationTree( aRootElement, aNodeContext )
+{
+ return createAnimationNode( aRootElement, null, aNodeContext );
+}
+
+
+
+
+function createAnimationNode( aElement, aParentNode, aNodeContext )
+{
+ assert( aElement, 'createAnimationNode: invalid animation element' );
+
+ var eAnimationNodeType = getAnimationElementType( aElement );
+
+ var aCreatedNode = null;
+ var aCreatedContainer = null;
+
+ switch( eAnimationNodeType )
+ {
+ case ANIMATION_NODE_PAR:
+ aCreatedNode = aCreatedContainer =
+ new ParallelTimeContainer( aElement, aParentNode, aNodeContext );
+ break;
+ case ANIMATION_NODE_ITERATE:
+ // map iterate container to ParallelTimeContainer.
+ // the iterating functionality is to be found
+ // below, (see method implCreateIteratedNodes)
+ aCreatedNode = aCreatedContainer =
+ new ParallelTimeContainer( aElement, aParentNode, aNodeContext );
+ break;
+ case ANIMATION_NODE_SEQ:
+ aCreatedNode = aCreatedContainer =
+ new SequentialTimeContainer( aElement, aParentNode, aNodeContext );
+ break;
+ case ANIMATION_NODE_ANIMATE:
+ aCreatedNode = new PropertyAnimationNode( aElement, aParentNode, aNodeContext );
+ break;
+ case ANIMATION_NODE_SET:
+ aCreatedNode = new AnimationSetNode( aElement, aParentNode, aNodeContext );
+ break;
+ case ANIMATION_NODE_ANIMATEMOTION:
+ //aCreatedNode = new AnimationPathMotionNode( aElement, aParentNode, aNodeContext );
+ //break;
+ log( 'createAnimationNode: ANIMATEMOTION not implemented' );
+ return null;
+ case ANIMATION_NODE_ANIMATECOLOR:
+ aCreatedNode = new AnimationColorNode( aElement, aParentNode, aNodeContext );
+ break;
+ case ANIMATION_NODE_ANIMATETRANSFORM:
+ aCreatedNode = new AnimationTransformNode( aElement, aParentNode, aNodeContext );
+ break;
+ case ANIMATION_NODE_TRANSITIONFILTER:
+ aCreatedNode = new AnimationTransitionFilterNode( aElement, aParentNode, aNodeContext );
+ break;
+ case ANIMATION_NODE_AUDIO:
+ log( 'createAnimationNode: AUDIO not implemented' );
+ return null;
+ case ANIMATION_NODE_COMMAND:
+ log( 'createAnimationNode: COMMAND not implemented' );
+ return null;
+ default:
+ log( 'createAnimationNode: invalid Animation Node Type: ' + eAnimationNodeType );
+ return null;
+ }
+
+ if( aCreatedContainer )
+ {
+ if( eAnimationNodeType == ANIMATION_NODE_ITERATE )
+ {
+ createIteratedNodes( aElement, aCreatedContainer, aNodeContext );
+ }
+ else
+ {
+ var aChildrenArray = getElementChildren( aElement );
+ for( var i = 0; i < aChildrenArray.length; ++i )
+ {
+ if( !createChildNode( aChildrenArray[i], aCreatedContainer, aNodeContext ) )
+ {
+ aCreatedContainer.removeAllChildrenNodes();
+ break;
+ }
+ }
+ }
+ }
+
+ return aCreatedNode;
+}
+
+
+
+
+function createChildNode( aElement, aParentNode, aNodeContext )
+{
+ var aChildNode = createAnimationNode( aElement, aParentNode, aNodeContext );
+
+ if( !aChildNode )
+ {
+ log( 'createChildNode: child node creation failed' );
+ return false;
+ }
+ else
+ {
+ aParentNode.appendChildNode( aChildNode );
+ return true;
+ }
+}
+
+
+
+
+function createIteratedNodes( /*aElement, aContainerNode, aNodeContext*/ )
+{
+ // not implemented
+}
+
+
+
+/**********************************************************************************************
+ * Animation Factory
+ **********************************************************************************************/
+
+// makeScaler is used in aAttributeMap:
+// eslint-disable-next-line no-unused-vars
+function makeScaler( nScale )
+{
+ if( ( typeof( nScale ) !== typeof( 0 ) ) || !isFinite( nScale ) )
+ {
+ log( 'makeScaler: not valid param passed: ' + nScale );
+ return null;
+ }
+
+ return function( nValue )
+ {
+ return ( nScale * nValue );
+ };
+}
+
+
+
+// eslint-disable-next-line no-unused-vars
+function createPropertyAnimation( sAttrName, aAnimatedElement, nWidth, nHeight )
+{
+ if( !aAttributeMap[ sAttrName ] )
+ {
+ log( 'createPropertyAnimation: attribute is unknown' );
+ return null;
+ }
+
+
+ var aFunctorSet = aAttributeMap[ sAttrName ];
+
+ var sGetValueMethod = aFunctorSet.get;
+ var sSetValueMethod = aFunctorSet.set;
+
+ if( !sGetValueMethod || !sSetValueMethod )
+ {
+ log( 'createPropertyAnimation: attribute is not handled' );
+ return null;
+ }
+
+ var aGetModifier = eval( aFunctorSet.getmod );
+ var aSetModifier = eval( aFunctorSet.setmod );
+
+
+ return new GenericAnimation( bind( aAnimatedElement, aAnimatedElement[ sGetValueMethod ] ),
+ bind( aAnimatedElement, aAnimatedElement[ sSetValueMethod ] ),
+ aGetModifier,
+ aSetModifier);
+}
+
+
+
+
+function createPairPropertyAnimation( sTransformType, aAnimatedElement, nWidth, nHeight )
+{
+ var aFunctorSet = aAttributeMap[ sTransformType ];
+ var sGetValueMethod = aFunctorSet.get;
+ var sSetValueMethod = aFunctorSet.set;
+
+ var aDefaultValue = [];
+ var aSizeReference = [];
+ if( sTransformType === 'scale' )
+ {
+ aDefaultValue[0] = aSizeReference[0] = aAnimatedElement.getBaseBBox().width;
+ aDefaultValue[1] = aSizeReference[1] = aAnimatedElement.getBaseBBox().height;
+ }
+ else if( sTransformType === 'translate' )
+ {
+ aDefaultValue[0] = aAnimatedElement.getBaseCenterX();
+ aDefaultValue[1] = aAnimatedElement.getBaseCenterY();
+ aSizeReference[0] = nWidth;
+ aSizeReference[1] = nHeight;
+ }
+ else
+ {
+ log( 'createPairPropertyAnimation: transform type is not handled' );
+ return null;
+ }
+
+ return new TupleAnimation( bind( aAnimatedElement, aAnimatedElement[ sGetValueMethod ] ),
+ bind( aAnimatedElement, aAnimatedElement[ sSetValueMethod ] ),
+ aDefaultValue,
+ aSizeReference );
+}
+
+
+
+
+/** createShapeTransition
+ *
+ * @param aActivityParamSet
+ * The set of property for the activity to be created.
+ * @param aAnimatedElement
+ * The element to be animated.
+ * @param nSlideWidth
+ * The width of a slide.
+ * @param nSlideHeight
+ * The height of a slide.
+ * @param aAnimatedTransitionFilterNode
+ * An instance of the AnimationFilterNode that invoked this function.
+ * @return {SimpleActivity}
+ * A simple activity handling a shape transition.
+ */
+function createShapeTransition( aActivityParamSet, aAnimatedElement,
+ nSlideWidth, nSlideHeight,
+ aAnimatedTransitionFilterNode )
+{
+ if( !aAnimatedTransitionFilterNode )
+ {
+ log( 'createShapeTransition: the animated transition filter node is not valid.' );
+ return null;
+ }
+ var eTransitionType = aAnimatedTransitionFilterNode.getTransitionType();
+ var eTransitionSubType = aAnimatedTransitionFilterNode.getTransitionSubType();
+ var bDirectionForward = ! aAnimatedTransitionFilterNode.getReverseDirection();
+ var bModeIn = ( aAnimatedTransitionFilterNode.getTransitionMode() == FORWARD );
+
+ var aTransitionInfo = aTransitionInfoTable[eTransitionType][eTransitionSubType];
+ var eTransitionClass = aTransitionInfo['class'];
+
+ switch( eTransitionClass )
+ {
+ default:
+ case TRANSITION_INVALID:
+ log( 'createShapeTransition: transition class: TRANSITION_INVALID' );
+ return null;
+
+ case TRANSITION_CLIP_POLYPOLYGON:
+ var aParametricPolyPolygon
+ = createClipPolyPolygon( eTransitionType, eTransitionSubType );
+ var aClippingAnimation
+ = new ClippingAnimation( aParametricPolyPolygon, aTransitionInfo,
+ bDirectionForward, bModeIn );
+ return new SimpleActivity( aActivityParamSet, aClippingAnimation, true );
+
+ case TRANSITION_SPECIAL:
+ switch( eTransitionType )
+ {
+ // no special transition filter provided
+ // we map everything to crossfade
+ default:
+ var aAnimation
+ = createPropertyAnimation( 'opacity',
+ aAnimatedElement,
+ nSlideWidth,
+ nSlideHeight );
+ return new SimpleActivity( aActivityParamSet, aAnimation, bModeIn );
+ }
+ }
+
+}
+
+
+
+
+/** Class ClippingAnimation
+ * This class performs a shape transition where the effect is achieved by
+ * clipping the shape to be animated with a parametric path.
+ *
+ * @param aParametricPolyPolygon
+ * An object handling a <path> element that depends on a parameter.
+ * @param aTransitionInfo
+ * The set of parameters defining the shape transition to be performed.
+ * @param bDirectionForward
+ * The direction the shape transition has to be performed.
+ * @param bModeIn
+ * If true the element to be animated becomes more visible as the transition
+ * progress else it becomes less visible.
+ */
+function ClippingAnimation( aParametricPolyPolygon, aTransitionInfo,
+ bDirectionForward, bModeIn )
+{
+ this.aClippingFunctor = new ClippingFunctor( aParametricPolyPolygon,
+ aTransitionInfo,
+ bDirectionForward, bModeIn );
+ this.bAnimationStarted = false;
+}
+
+/** start
+ * This method notifies to the element involved in the transition that
+ * the animation is starting and creates the <clipPath> element used for
+ * the transition.
+ *
+ * @param aAnimatableElement
+ * The element to be animated.
+ */
+ClippingAnimation.prototype.start = function( aAnimatableElement )
+{
+ assert( aAnimatableElement,
+ 'ClippingAnimation.start: animatable element is not valid' );
+ this.aAnimatableElement = aAnimatableElement;
+ this.aAnimatableElement.initClipPath();
+ this.aAnimatableElement.notifyAnimationStart();
+
+ if( !this.bAnimationStarted )
+ this.bAnimationStarted = true;
+
+};
+
+/** end
+ * The transition clean up is performed here.
+ */
+ClippingAnimation.prototype.end = function()
+{
+ if( this.bAnimationStarted )
+ {
+ this.aAnimatableElement.cleanClipPath();
+ this.bAnimationStarted = false;
+ this.aAnimatableElement.notifyAnimationEnd();
+ }
+};
+
+/** perform
+ * This method set the position of the element to be animated according to
+ * the passed time value.
+ *
+ * @param nValue
+ * The time parameter.
+ */
+ClippingAnimation.prototype.perform = function( nValue )
+{
+ var nWidth = this.aAnimatableElement.aClippingBBox.width;
+ var nHeight = this.aAnimatableElement.aClippingBBox.height;
+ var aPolyPolygonElement = this.aClippingFunctor.perform( nValue, nWidth, nHeight );
+ this.aAnimatableElement.setClipPath( aPolyPolygonElement );
+};
+
+ClippingAnimation.prototype.getUnderlyingValue = function()
+{
+ return 0.0;
+};
+
+
+
+
+function GenericAnimation( aGetValueFunc, aSetValueFunc, aGetModifier, aSetModifier )
+{
+ assert( aGetValueFunc && aSetValueFunc,
+ 'GenericAnimation constructor: get value functor and/or set value functor are not valid' );
+
+ this.aGetValueFunc = aGetValueFunc;
+ this.aSetValueFunc = aSetValueFunc;
+ this.aGetModifier = aGetModifier;
+ this.aSetModifier = aSetModifier;
+ this.aAnimatableElement = null;
+ this.bAnimationStarted = false;
+}
+
+
+GenericAnimation.prototype.start = function( aAnimatableElement )
+{
+ assert( aAnimatableElement, 'GenericAnimation.start: animatable element is not valid' );
+
+ this.aAnimatableElement = aAnimatableElement;
+ this.aAnimatableElement.notifyAnimationStart();
+
+ if( !this.bAnimationStarted )
+ this.bAnimationStarted = true;
+};
+
+GenericAnimation.prototype.end = function()
+{
+ if( this.bAnimationStarted )
+ {
+ this.bAnimationStarted = false;
+ this.aAnimatableElement.notifyAnimationEnd();
+ }
+};
+
+GenericAnimation.prototype.perform = function( aValue )
+{
+ if( this.aSetModifier )
+ aValue = this.aSetModifier( aValue );
+
+ this.aSetValueFunc( aValue );
+};
+
+GenericAnimation.prototype.getUnderlyingValue = function()
+{
+ var aValue = this.aGetValueFunc();
+ if( this.aGetModifier )
+ aValue = this.aGetModifier( aValue );
+ return aValue;
+};
+
+
+
+function TupleAnimation( aGetValueFunc, aSetValueFunc, aDefaultValue, aReferenceSize )
+{
+ TupleAnimation.superclass.constructor.call( this, aGetValueFunc, aSetValueFunc );
+ assert( aDefaultValue && aReferenceSize,
+ 'TupleAnimation constructor: default value functor and/or reference size are not valid' );
+
+ this.aDefaultValue = aDefaultValue;
+ this.aReferenceSize = aReferenceSize;
+}
+extend( TupleAnimation, GenericAnimation );
+
+TupleAnimation.prototype.perform = function( aNormValue )
+{
+ assert(aNormValue.length === this.aReferenceSize.length);
+
+ var aValue = [];
+ for( var i = 0; i < aNormValue.length; ++i )
+ {
+ aValue.push( aNormValue[i] * this.aReferenceSize[i] );
+ }
+
+ this.aSetValueFunc( aValue );
+};
+
+TupleAnimation.prototype.getUnderlyingValue = function()
+{
+ var aValue = this.aGetValueFunc();
+ assert(aValue.length === this.aReferenceSize.length);
+
+ var aNormValue = [];
+ for( var i = 0; i < aValue.length; ++i )
+ {
+ aNormValue.push( aValue[i] / this.aReferenceSize[i] );
+ }
+
+ return aNormValue;
+};
+
+
+
+function HSLAnimationWrapper( aColorAnimation )
+{
+ assert( aColorAnimation,
+ 'HSLAnimationWrapper constructor: invalid color animation delegate' );
+
+ this.aAnimation = aColorAnimation;
+}
+
+
+HSLAnimationWrapper.prototype.start = function( aAnimatableElement )
+{
+ this.aAnimation.start( aAnimatableElement );
+};
+
+HSLAnimationWrapper.prototype.end = function()
+{
+ this.aAnimation.end();
+};
+HSLAnimationWrapper.prototype.perform = function( aHSLValue )
+{
+ this.aAnimation.perform( aHSLValue.convertToRGB() );
+};
+
+HSLAnimationWrapper.prototype.getUnderlyingValue = function()
+{
+ return this.aAnimation.getUnderlyingValue().convertToHSL();
+};
+
+
+
+
+/** Class SlideChangeBase
+ * The base abstract class of classes performing slide transitions.
+ *
+ * @param aLeavingSlide
+ * An object of type AnimatedSlide handling the leaving slide.
+ * @param aEnteringSlide
+ * An object of type AnimatedSlide handling the entering slide.
+ */
+function SlideChangeBase(aLeavingSlide, aEnteringSlide)
+{
+ this.aLeavingSlide = aLeavingSlide;
+ this.aEnteringSlide = aEnteringSlide;
+ this.bIsFinished = false;
+}
+
+/** start
+ * The transition initialization is performed here.
+ */
+SlideChangeBase.prototype.start = function()
+{
+};
+
+/** end
+ * The transition clean up is performed here.
+ */
+SlideChangeBase.prototype.end = function()
+{
+ if( this.bIsFinished )
+ return;
+
+ this.aLeavingSlide.hide();
+ this.aEnteringSlide.reset();
+ this.aLeavingSlide.reset();
+
+ this.bIsFinished = true;
+};
+
+/** perform
+ * This method is responsible for performing the slide transition.
+ *
+ * @param nValue
+ * The time parameter.
+ * @return {Boolean}
+ * If the transition is performed returns tue else returns false.
+ */
+SlideChangeBase.prototype.perform = function( nValue )
+{
+ if( this.bIsFinished ) return false;
+
+ if( this.aLeavingSlide )
+ this.performOut( nValue );
+
+ if( this.aEnteringSlide )
+ this.performIn( nValue );
+
+ return true;
+};
+
+SlideChangeBase.prototype.getUnderlyingValue = function()
+{
+ return 0.0;
+};
+
+SlideChangeBase.prototype.performIn = function( )
+{
+ log( 'SlideChangeBase.performIn: abstract method called' );
+};
+
+SlideChangeBase.prototype.performOut = function( )
+{
+ log( 'SlideChangeBase.performOut: abstract method called' );
+};
+
+
+
+
+/** Class FadingSlideChange
+ * This class performs a slide transition by fading out the leaving slide and
+ * fading in the entering slide.
+ *
+ * @param aLeavingSlide
+ * An object of type AnimatedSlide handling the leaving slide.
+ * @param aEnteringSlide
+ * An object of type AnimatedSlide handling the entering slide.
+ */
+function FadingSlideChange( aLeavingSlide, aEnteringSlide )
+{
+ FadingSlideChange.superclass.constructor.call( this, aLeavingSlide, aEnteringSlide );
+ this.bFirstRun = true;
+}
+extend( FadingSlideChange, SlideChangeBase );
+
+/** start
+ * This method notifies to the slides involved in the transition the attributes
+ * appended to the slide elements for performing the animation.
+ * Moreover it sets the entering slide in the initial state and makes the slide
+ * visible.
+ */
+FadingSlideChange.prototype.start = function()
+{
+ FadingSlideChange.superclass.start.call( this );
+ this.aEnteringSlide.notifyUsedAttribute( 'opacity' );
+ this.aLeavingSlide.notifyUsedAttribute( 'opacity' );
+ this.aEnteringSlide.setOpacity( 0.0 );
+ this.aEnteringSlide.show();
+};
+
+/** performIn
+ * This method set the opacity of the entering slide according to the passed
+ * time value.
+ *
+ * @param nT
+ * The time parameter.
+ */
+FadingSlideChange.prototype.performIn = function( nT )
+{
+ this.aEnteringSlide.setOpacity( nT );
+};
+
+/** performOut
+ * This method set the opacity of the leaving slide according to the passed
+ * time value.
+ *
+ * @param nT
+ * The time parameter.
+ */
+FadingSlideChange.prototype.performOut = function( nT )
+{
+
+ this.aLeavingSlide.setOpacity( 1 - nT );
+};
+
+
+
+
+/** Class FadingOverColorSlideChange
+ * This class performs a slide transition by fading out the leaving slide to
+ * a given color and fading in the entering slide from the same color.
+ *
+ * @param aLeavingSlide
+ * An object of type AnimatedSlide handling the leaving slide.
+ * @param aEnteringSlide
+ * An object of type AnimatedSlide handling the entering slide.
+ * @param sFadeColor
+ * A string representing the color the leaving slide fades out to and
+ * the entering slide fade in from.
+ */
+function FadingOverColorSlideChange( aLeavingSlide, aEnteringSlide, sFadeColor )
+{
+ FadingSlideChange.superclass.constructor.call( this, aLeavingSlide, aEnteringSlide );
+ this.sFadeColor = sFadeColor;
+ if( !this.sFadeColor )
+ {
+ log( 'FadingOverColorSlideChange: sFadeColor not valid.' );
+ this.sFadeColor = '#000000';
+ }
+ this.aColorPlaneElement = this.createColorPlaneElement();
+}
+extend( FadingOverColorSlideChange, SlideChangeBase );
+
+/** start
+ * This method notifies to the slides involved in the transition the attributes
+ * appended to the slide elements for performing the animation.
+ * Moreover it inserts the color plane element below the leaving slide.
+ * Finally it sets the entering slide in the initial state and makes
+ * the slide visible.
+ */
+FadingOverColorSlideChange.prototype.start = function()
+{
+ FadingOverColorSlideChange.superclass.start.call( this );
+ this.aEnteringSlide.notifyUsedAttribute( 'opacity' );
+ this.aLeavingSlide.notifyUsedAttribute( 'opacity' );
+ this.aLeavingSlide.insertBefore( this.aColorPlaneElement );
+ this.aEnteringSlide.setOpacity( 0.0 );
+ this.aEnteringSlide.show();
+};
+
+/** end
+ * This method removes the color plane element.
+ */
+FadingOverColorSlideChange.prototype.end = function()
+{
+ FadingOverColorSlideChange.superclass.end.call( this );
+ this.aLeavingSlide.removeElement( this.aColorPlaneElement );
+};
+
+/** performIn
+ * This method set the opacity of the entering slide according to the passed
+ * time value.
+ *
+ * @param nT
+ * The time parameter.
+ */
+FadingOverColorSlideChange.prototype.performIn = function( nT )
+{
+ this.aEnteringSlide.setOpacity( (nT > 0.55) ? 2.0*(nT-0.55) : 0.0 );
+};
+
+/** performOut
+ * This method set the opacity of the leaving slide according to the passed
+ * time value.
+ *
+ * @param nT
+ * The time parameter.
+ */
+FadingOverColorSlideChange.prototype.performOut = function( nT )
+{
+ this.aLeavingSlide.setOpacity( (nT > 0.45) ? 0.0 : 2.0*(0.45-nT) );
+};
+
+FadingOverColorSlideChange.prototype.createColorPlaneElement = function()
+{
+ var aColorPlaneElement = document.createElementNS( NSS['svg'], 'rect' );
+ aColorPlaneElement.setAttribute( 'width', String( this.aLeavingSlide.getWidth() ) );
+ aColorPlaneElement.setAttribute( 'height', String( this.aLeavingSlide.getHeight() ) );
+ aColorPlaneElement.setAttribute( 'fill', this.sFadeColor );
+ return aColorPlaneElement;
+};
+
+
+
+
+/** Class MovingSlideChange
+ * This class performs a slide transition that involves translating the leaving
+ * slide and/or the entering one in a given direction.
+ *
+ * @param aLeavingSlide
+ * An object of type AnimatedSlide handling the leaving slide.
+ * @param aEnteringSlide
+ * An object of type AnimatedSlide handling the entering slide.
+ * @param aLeavingDirection
+ * A 2D vector object {x, y}.
+ * @param aEnteringDirection
+ * A 2D vector object {x, y}.
+ */
+function MovingSlideChange( aLeavingSlide, aEnteringSlide,
+ aLeavingDirection, aEnteringDirection )
+{
+ MovingSlideChange.superclass.constructor.call( this, aLeavingSlide, aEnteringSlide );
+ this.aLeavingDirection = aLeavingDirection;
+ this.aEnteringDirection = aEnteringDirection;
+}
+extend( MovingSlideChange, SlideChangeBase );
+
+/** start
+ * This method notifies to the slides involved in the transition the attributes
+ * appended to the slide elements for performing the animation.
+ * Moreover it sets the entering slide in the initial state and makes the slide
+ * visible.
+ */
+MovingSlideChange.prototype.start = function()
+{
+ MovingSlideChange.superclass.start.call( this );
+ this.aEnteringSlide.notifyUsedAttribute( 'transform' );
+ this.aLeavingSlide.notifyUsedAttribute( 'transform' );
+ // Before setting the 'visibility' attribute of the entering slide to 'visible'
+ // we translate it to the initial position so that it is not really visible
+ // because it is clipped out.
+ this.performIn( 0 );
+ this.aEnteringSlide.show();
+};
+
+/** performIn
+ * This method set the position of the entering slide according to the passed
+ * time value.
+ *
+ * @param nT
+ * The time parameter.
+ */
+MovingSlideChange.prototype.performIn = function( nT )
+{
+ var nS = nT - 1;
+ var dx = nS * this.aEnteringDirection.x * this.aEnteringSlide.getWidth();
+ var dy = nS * this.aEnteringDirection.y * this.aEnteringSlide.getHeight();
+ this.aEnteringSlide.translate( dx, dy );
+};
+
+/** performOut
+ * This method set the position of the leaving slide according to the passed
+ * time value.
+ *
+ * @param nT
+ * The time parameter.
+ */
+MovingSlideChange.prototype.performOut = function( nT )
+{
+ var dx = nT * this.aLeavingDirection.x * this.aLeavingSlide.getWidth();
+ var dy = nT * this.aLeavingDirection.y * this.aLeavingSlide.getHeight();
+ this.aLeavingSlide.translate( dx, dy );
+};
+
+
+
+
+/** Class ClippedSlideChange
+ * This class performs a slide transition where the entering slide wipes
+ * the leaving one out. The wipe effect is achieved by clipping the entering
+ * slide with a parametric path.
+ *
+ * @param aLeavingSlide
+ * An object of type AnimatedSlide handling the leaving slide.
+ * @param aEnteringSlide
+ * An object of type AnimatedSlide handling the entering slide.
+ * @param aParametricPolyPolygon
+ * An object handling a <path> element that depends on a parameter.
+ * @param aTransitionInfo
+ * The set of parameters defining the slide transition to be performed.
+ * @param bIsDirectionForward
+ * The direction the slide transition has to be performed.
+ */
+function ClippedSlideChange( aLeavingSlide, aEnteringSlide, aParametricPolyPolygon,
+ aTransitionInfo, bIsDirectionForward )
+{
+ ClippedSlideChange.superclass.constructor.call( this, aLeavingSlide, aEnteringSlide );
+
+ var bIsModeIn = true;
+ this.aClippingFunctor= new ClippingFunctor( aParametricPolyPolygon, aTransitionInfo,
+ bIsDirectionForward, bIsModeIn );
+}
+extend( ClippedSlideChange, SlideChangeBase );
+
+/** start
+ * This method notifies to the slides involved in the transition the attributes
+ * appended to the slide elements for performing the animation.
+ * Moreover it sets the entering slide in the initial state and makes the slide
+ * visible.
+ */
+ClippedSlideChange.prototype.start = function()
+{
+ ClippedSlideChange.superclass.start.call( this );
+ this.aEnteringSlide.notifyUsedAttribute( 'clip-path' );
+ this.performIn( 0 );
+ this.aEnteringSlide.show();
+};
+
+/** performIn
+ * This method set the position of the entering slide according to the passed
+ * time value.
+ *
+ * @param nT
+ * The time parameter.
+ */
+ClippedSlideChange.prototype.performIn = function( nT )
+{
+ var nWidth = this.aEnteringSlide.getWidth();
+ var nHeight = this.aEnteringSlide.getHeight();
+ var aPolyPolygonElement = this.aClippingFunctor.perform( nT, nWidth, nHeight );
+ this.aEnteringSlide.setClipPath( aPolyPolygonElement );
+};
+
+ClippedSlideChange.prototype.performOut = function( )
+{
+ // empty body
+};
+
+
+
+
+/** Class ClippingFunctor
+ * This class is responsible for computing the <path> used for clipping
+ * the entering slide in a polypolygon clipping slide transition or the
+ * animated shape in a transition filter effect.
+ *
+ * @param aParametricPolyPolygon
+ * An object that handle a <path> element defined in the [0,1]x[0,1]
+ * unit square and that depends on a parameter.
+ * @param aTransitionInfo
+ * The set of parameters defining the slide transition to be performed.
+ * @param bIsDirectionForward
+ * The direction the slide transition has to be performed.
+ * @param bIsModeIn
+ * The direction the filter effect has to be performed
+ */
+function ClippingFunctor( aParametricPolyPolygon, aTransitionInfo,
+ bIsDirectionForward, bIsModeIn)
+{
+ this.aParametricPolyPolygon = aParametricPolyPolygon;
+ this.aStaticTransformation = null;
+ this.bForwardParameterSweep = true;
+ this.bSubtractPolygon = false;
+ this.bScaleIsotropically = aTransitionInfo.scaleIsotropically;
+ this.bFlip = false;
+
+ assert( this.aParametricPolyPolygon,
+ 'ClippingFunctor: parametric polygon is not valid' );
+
+ if( aTransitionInfo.rotationAngle != 0.0 ||
+ aTransitionInfo.scaleX != 1.0 || aTransitionInfo.scaleY != 1.0 )
+ {
+ // note: operations must be defined in reverse order.
+ this.aStaticTransformation = SVGIdentityMatrix.translate( 0.5, 0.5 );
+ if( aTransitionInfo.scaleX != 1.0 || aTransitionInfo.scaleY != 1.0 )
+ this.aStaticTransformation
+ = this.aStaticTransformation.scaleNonUniform( aTransitionInfo.scaleX,
+ aTransitionInfo.scaleY );
+ if( aTransitionInfo.rotationAngle != 0.0 )
+ this.aStaticTransformation
+ = this.aStaticTransformation.rotate( aTransitionInfo.rotationAngle );
+ this.aStaticTransformation = this.aStaticTransformation.translate( -0.5, -0.5 );
+ }
+ else
+ {
+ this.aStaticTransformation = document.documentElement.createSVGMatrix();
+ }
+
+ if( !bIsDirectionForward )
+ {
+ var aMatrix = null;
+ switch( aTransitionInfo.reverseMethod )
+ {
+ default:
+ log( 'ClippingFunctor: unexpected reverse method.' );
+ break;
+ case REVERSEMETHOD_IGNORE:
+ break;
+ case REVERSEMETHOD_INVERT_SWEEP:
+ this.bForwardParameterSweep = !this.bForwardParameterSweep;
+ break;
+ case REVERSEMETHOD_SUBTRACT_POLYGON:
+ this.bSubtractPolygon = !this.bSubtractPolygon;
+ break;
+ case REVERSEMETHOD_SUBTRACT_AND_INVERT:
+ this.bForwardParameterSweep = !this.bForwardParameterSweep;
+ this.bSubtractPolygon = !this.bSubtractPolygon;
+ break;
+ case REVERSEMETHOD_ROTATE_180:
+ aMatrix = document.documentElement.createSVGMatrix();
+ aMatrix.setToRotationAroundPoint( 0.5, 0.5, 180 );
+ this.aStaticTransformation = aMatrix.multiply( this.aStaticTransformation );
+ break;
+ case REVERSEMETHOD_FLIP_X:
+ aMatrix = document.documentElement.createSVGMatrix();
+ // |-1 0 1 |
+ // | 0 1 0 |
+ aMatrix.a = -1; aMatrix.e = 1.0;
+ this.aStaticTransformation = aMatrix.multiply( this.aStaticTransformation );
+ this.bFlip = true;
+ break;
+ case REVERSEMETHOD_FLIP_Y:
+ aMatrix = document.documentElement.createSVGMatrix();
+ // | 1 0 0 |
+ // | 0 -1 1 |
+ aMatrix.d = -1; aMatrix.f = 1.0;
+ this.aStaticTransformation = aMatrix.multiply( this.aStaticTransformation );
+ this.bFlip = true;
+ break;
+ }
+ }
+
+ if( !bIsModeIn )
+ {
+ if( aTransitionInfo.outInvertsSweep )
+ {
+ this.bForwardParameterSweep = !this.bForwardParameterSweep;
+ }
+ else
+ {
+ this.bSubtractPolygon = !this.bSubtractPolygon;
+ }
+ }
+}
+
+// This path is used when the direction is the reverse one and
+// the reverse method type is the subtraction type.
+ClippingFunctor.aBoundingPath = document.createElementNS( NSS['svg'], 'path' );
+ClippingFunctor.aBoundingPath.setAttribute( 'd', 'M -1 -1 L 2 -1 L 2 2 L -1 2 L -1 -1' );
+
+/** perform
+ *
+ * @param nT
+ * A parameter in [0,1] representing normalized time.
+ * @param nWidth
+ * The width of the bounding box of the slide/shape to be clipped.
+ * @param nHeight
+ * The height of the bounding box of the slide/shape to be clipped.
+ * @return SVGPathElement
+ * A svg <path> element representing the path to be used for the clipping
+ * operation.
+ */
+ClippingFunctor.prototype.perform = function( nT, nWidth, nHeight )
+{
+ var aClipPoly = this.aParametricPolyPolygon.perform( this.bForwardParameterSweep ? nT : (1 - nT) );
+
+ // Note: even if the reverse method involves flipping we don't need to
+ // change the clip-poly orientation because we utilize the 'nonzero'
+ // clip-rule.
+ // See: http://www.w3.org/TR/SVG11/painting.html#FillRuleProperty
+
+ if( this.bSubtractPolygon )
+ {
+ aClipPoly.changeOrientation();
+ aClipPoly.prependPath( ClippingFunctor.aBoundingPath );
+ }
+
+ var aMatrix;
+ if( this.bScaleIsotropically )
+ {
+ var nScaleFactor = Math.max( nWidth, nHeight );
+ // note: operations must be defined in reverse order.
+ aMatrix = SVGIdentityMatrix.translate( -( nScaleFactor - nWidth ) / 2.0,
+ -( nScaleFactor - nHeight ) / 2.0 );
+ aMatrix = aMatrix.scale( nScaleFactor );
+ aMatrix = aMatrix.multiply( this.aStaticTransformation );
+ }
+ else
+ {
+ aMatrix = SVGIdentityMatrix.scaleNonUniform( nWidth, nHeight );
+ aMatrix = aMatrix.multiply( this.aStaticTransformation );
+ }
+
+ aClipPoly.matrixTransform( aMatrix );
+
+ return aClipPoly;
+};
+
+
+
+
+/** createClipPolyPolygon
+ *
+ * @param nType
+ * An enumerator representing the transition type.
+ * @param nSubtype
+ * An enumerator representing the transition subtype.
+ * @return
+ * An object that handles a parametric <path> element.
+ */
+function createClipPolyPolygon( nType, nSubtype )
+{
+ switch( nType )
+ {
+ default:
+ log( 'createClipPolyPolygon: unknown transition type: ' + nType );
+ return null;
+ case BARWIPE_TRANSITION:
+ return new BarWipePath( 1 );
+ case FOURBOXWIPE_TRANSITION:
+ return new FourBoxWipePath( nSubtype === CORNERSOUT_TRANS_SUBTYPE );
+ case BOXWIPE_TRANSITION:
+ return new BoxWipePath( nSubtype == LEFTCENTER_TRANS_SUBTYPE ||
+ nSubtype == TOPCENTER_TRANS_SUBTYPE ||
+ nSubtype == RIGHTCENTER_TRANS_SUBTYPE ||
+ nSubtype == BOTTOMCENTER_TRANS_SUBTYPE );
+ case ELLIPSEWIPE_TRANSITION:
+ return new EllipseWipePath( nSubtype );
+ case FANWIPE_TRANSITION:
+ return new FanWipePath(nSubtype == CENTERTOP_TRANS_SUBTYPE ||
+ nSubtype == CENTERRIGHT_TRANS_SUBTYPE, true, false);
+ case PINWHEELWIPE_TRANSITION:
+ var nBlades;
+ switch( nSubtype )
+ {
+ case ONEBLADE_TRANS_SUBTYPE:
+ nBlades = 1;
+ break;
+ case DEFAULT_TRANS_SUBTYPE:
+ case TWOBLADEVERTICAL_TRANS_SUBTYPE:
+ nBlades = 2;
+ break;
+ case TWOBLADEHORIZONTAL_TRANS_SUBTYPE:
+ nBlades = 2;
+ break;
+ case THREEBLADE_TRANS_SUBTYPE:
+ nBlades = 3;
+ break;
+ case FOURBLADE_TRANS_SUBTYPE:
+ nBlades = 4;
+ break;
+ case EIGHTBLADE_TRANS_SUBTYPE:
+ nBlades = 8;
+ break;
+ default:
+ log( 'createClipPolyPolygon: unknown subtype: ' + nSubtype );
+ return null;
+ }
+ return new PinWheelWipePath( nBlades );
+ case CLOCKWIPE_TRANSITION:
+ return new ClockWipePath();
+ case RANDOMBARWIPE_TRANSITION:
+ return new RandomWipePath( 128, true /* bars */ );
+ case CHECKERBOARDWIPE_TRANSITION:
+ return new CheckerBoardWipePath( 10 );
+ case ZIGZAGWIPE_TRANSITION:
+ return new ZigZagWipePath( 5 );
+ case BARNZIGZAGWIPE_TRANSITION:
+ return new BarnZigZagWipePath( 5 );
+ case IRISWIPE_TRANSITION:
+ switch(nSubtype)
+ {
+ case RECTANGLE_TRANS_SUBTYPE:
+ return new IrisWipePath(0);
+ case DIAMOND_TRANS_SUBTYPE:
+ return new IrisWipePath(1);
+ default:
+ log( 'createClipPolyPolygon: unknown subtype: ' + nSubtype );
+ return null;
+ }
+ case BARNDOORWIPE_TRANSITION:
+ return new BarnDoorWipePath(false);
+ case SINGLESWEEPWIPE_TRANSITION:
+ return new SweepWipePath(
+ // center
+ nSubtype == CLOCKWISETOP_TRANS_SUBTYPE ||
+ nSubtype == CLOCKWISERIGHT_TRANS_SUBTYPE ||
+ nSubtype == CLOCKWISEBOTTOM_TRANS_SUBTYPE ||
+ nSubtype == CLOCKWISELEFT_TRANS_SUBTYPE,
+ // single
+ true,
+ // oppositeVertical
+ false,
+ // flipOnYAxis
+ nSubtype == COUNTERCLOCKWISEBOTTOMLEFT_TRANS_SUBTYPE ||
+ nSubtype == COUNTERCLOCKWISETOPRIGHT_TRANS_SUBTYPE );
+ case WATERFALLWIPE_TRANSITION:
+ return new WaterfallWipePath(128, // flipOnYAxis
+ nSubtype == VERTICALRIGHT_TRANS_SUBTYPE ||
+ nSubtype == HORIZONTALLEFT_TRANS_SUBTYPE);
+ case MISCDIAGONALWIPE_TRANSITION:
+ switch(nSubtype) {
+ case DOUBLEBARNDOOR_TRANS_SUBTYPE:
+ return new BarnDoorWipePath(true /* Doubled */);
+ case DOUBLEDIAMOND_TRANS_SUBTYPE:
+ return new DoubleDiamondWipePath();
+ default:
+ log( 'createClipPolyPolygon: unhandled subtype: ' + nSubtype );
+ return null;
+ }
+ case DISSOLVE_TRANSITION:
+ return new RandomWipePath( 16 * 16, false /* dissolve */ );
+ case VEEWIPE_TRANSITION:
+ return new VeeWipePath();
+ case SNAKEWIPE_TRANSITION:
+ return new SnakeWipePath( 8 * 8, // diagonal
+ nSubtype == TOPLEFTDIAGONAL_TRANS_SUBTYPE ||
+ nSubtype == TOPRIGHTDIAGONAL_TRANS_SUBTYPE ||
+ nSubtype == BOTTOMRIGHTDIAGONAL_TRANS_SUBTYPE ||
+ nSubtype == BOTTOMLEFTDIAGONAL_TRANS_SUBTYPE ,
+ // flipOnYAxis
+ nSubtype == TOPLEFTVERTICAL_TRANS_SUBTYPE ||
+ nSubtype == TOPRIGHTDIAGONAL_TRANS_SUBTYPE ||
+ nSubtype == BOTTOMLEFTDIAGONAL_TRANS_SUBTYPE
+ );
+ case PARALLELSNAKESWIPE_TRANSITION:
+ return new ParallelSnakesWipePath(
+ 8 * 8, // elements
+ // diagonal
+ nSubtype == DIAGONALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE ||
+ nSubtype == DIAGONALTOPLEFTOPPOSITE_TRANS_SUBTYPE,
+ // flipOnYAxis
+ nSubtype == VERTICALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE ||
+ nSubtype == HORIZONTALTOPLEFTOPPOSITE_TRANS_SUBTYPE ||
+ nSubtype == DIAGONALTOPLEFTOPPOSITE_TRANS_SUBTYPE,
+ // opposite
+ nSubtype == VERTICALTOPLEFTOPPOSITE_TRANS_SUBTYPE ||
+ nSubtype == VERTICALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE ||
+ nSubtype == HORIZONTALTOPLEFTOPPOSITE_TRANS_SUBTYPE ||
+ nSubtype == HORIZONTALTOPRIGHTOPPOSITE_TRANS_SUBTYPE ||
+ nSubtype == DIAGONALBOTTOMLEFTOPPOSITE_TRANS_SUBTYPE ||
+ nSubtype == DIAGONALTOPLEFTOPPOSITE_TRANS_SUBTYPE
+ );
+
+ case SPIRALWIPE_TRANSITION:
+ return new SpiralWipePath(
+ 8 * 8, // elements
+ nSubtype == TOPLEFTCOUNTERCLOCKWISE_TRANS_SUBTYPE ||
+ nSubtype == TOPRIGHTCOUNTERCLOCKWISE_TRANS_SUBTYPE ||
+ nSubtype == BOTTOMRIGHTCOUNTERCLOCKWISE_TRANS_SUBTYPE ||
+ nSubtype == BOTTOMLEFTCOUNTERCLOCKWISE_TRANS_SUBTYPE );
+
+ case BOXSNAKESWIPE_TRANSITION:
+ return new BoxSnakesWipePath(
+ // elements
+ 8 * 8,
+ // fourBox
+ nSubtype == FOURBOXVERTICAL_TRANS_SUBTYPE ||
+ nSubtype == FOURBOXHORIZONTAL_TRANS_SUBTYPE );
+ }
+}
+
+
+
+
+function createUnitSquarePath()
+{
+ var aPath = document.createElementNS( NSS['svg'], 'path' );
+ var sD = 'M 0 0 L 1 0 L 1 1 L 0 1 L 0 0';
+ aPath.setAttribute( 'd', sD );
+ return aPath;
+}
+
+function createEmptyPath()
+{
+ var aPath = document.createElementNS( NSS['svg'], 'path' );
+ var sD = 'M 0 0 L 0 0';
+ aPath.setAttribute( 'd', sD );
+ return aPath;
+}
+
+function pruneScaleValue( nVal )
+{
+ if( nVal < 0.0 )
+ return (nVal < -0.00001 ? nVal : -0.00001);
+ else
+ return (nVal > 0.00001 ? nVal : 0.00001);
+}
+
+
+/** Class BarWipePath
+ * This class handles a <path> element that defines a unit square and
+ * transforms it accordingly to a parameter in the [0,1] range for performing
+ * a left to right barWipe transition.
+ *
+ * @param nBars
+ * The number of bars to be generated.
+ */
+function BarWipePath( nBars /* nBars > 1: blinds effect */ )
+{
+ this.nBars = nBars;
+ if( this.nBars === undefined || this.nBars < 1 )
+ this.nBars = 1;
+ this.aBasePath = createUnitSquarePath();
+}
+
+/** perform
+ *
+ * @param nT
+ * A parameter in [0,1] representing the width of the generated bars.
+ * @return SVGPathElement
+ * A svg <path> element representing a multi-bars.
+ */
+BarWipePath.prototype.perform = function( nT )
+{
+
+ var aMatrix = SVGIdentityMatrix.scaleNonUniform( pruneScaleValue( nT / this.nBars ), 1.0 );
+
+ var aPolyPath = this.aBasePath.cloneNode( true );
+ aPolyPath.matrixTransform( aMatrix );
+
+ if( this.nBars > 1 )
+ {
+ var i;
+ var aTransform;
+ var aPath;
+ for( i = this.nBars - 1; i > 0; --i )
+ {
+ aTransform = SVGIdentityMatrix.translate( i / this.nBars, 0.0 );
+ aTransform = aTransform.multiply( aMatrix );
+ aPath = this.aBasePath.cloneNode( true );
+ aPath.matrixTransform( aTransform );
+ aPolyPath.appendPath( aPath );
+ }
+ }
+ return aPolyPath;
+};
+
+
+/** Class BoxWipePath
+ * This class handles a path made up by one square and is utilized for
+ * performing BoxWipe transitions.
+ *
+ * @param bIsTopCentered
+ * if true the transition subtype is top centered else not.
+ */
+function BoxWipePath(bIsTopCentered) {
+ this.bIsTopCentered = bIsTopCentered;
+ this.aBasePath = createUnitSquarePath();
+}
+
+BoxWipePath.prototype.perform = function( nT ) {
+ var d = pruneScaleValue(nT);
+ var aTransform = SVGIdentityMatrix;
+ if(this.bIsTopCentered) {
+ aTransform = aTransform.translate(-0.5, 0.0).scale(d, d).translate(0.5, 0.0);
+ }
+ else {
+ aTransform = aTransform.scale(d, d);
+ }
+ var aPath = this.aBasePath.cloneNode(true);
+ aPath.matrixTransform(aTransform);
+ return aPath;
+}
+
+/* Class SweepWipePath
+ *
+ *
+ */
+function SweepWipePath(bCenter, bSingle, bOppositeVertical, bFlipOnYAxis) {
+ this.bCenter = bCenter;
+ this.bSingle = bSingle;
+ this.bOppositeVertical = bOppositeVertical;
+ this.bFlipOnYAxis = bFlipOnYAxis;
+ this.aBasePath = createUnitSquarePath();
+}
+
+SweepWipePath.prototype.perform = function( nT ) {
+ nT /= 2.0;
+ if(!this.bCenter)
+ nT /= 2.0;
+ if(!this.bSingle && !this.bOppositeVertical)
+ nT /= 2.0;
+
+ var poly = PinWheelWipePath.calcCenteredClock( nT + 0.25, 1.0 );
+ var aTransform;
+
+ if(this.bCenter) {
+ aTransform = SVGIdentityMatrix.translate(0.5, 0.0);
+ poly.matrixTransform(aTransform);
+ }
+ var res = poly;
+
+ if(!this.bSingle) {
+ if(this.bOppositeVertical) {
+ aTransform = SVGIdentityMatrix.scale(1.0, -1.0);
+ aTransform.translate(0.0, 1.0);
+ poly.matrixTransform(aTransform);
+ poly.changeOrientation();
+ }
+ else {
+ aTransform = SVGIdentityMatrix.translate(-0.5, -0.5);
+ aTransform.rotate(Math.PI);
+ aTransform.translate(0.5, 0.5);
+ poly.matrixTransform(aTransform);
+ }
+ res.appendPath(poly);
+ }
+ return this.bFlipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+/** Class FourBoxWipePath
+ * This class handles a path made up by four squares and is utilized for
+ * performing fourBoxWipe transitions.
+ *
+ * @param bCornersOut
+ * If true the transition subtype is cornersOut else is cornersIn.
+ */
+function FourBoxWipePath( bCornersOut )
+{
+ this.bCornersOut = bCornersOut;
+ this.aBasePath = createUnitSquarePath();
+}
+
+FourBoxWipePath.prototype.perform = function( nT )
+{
+ var aMatrix;
+ var d = pruneScaleValue( nT / 2.0 );
+
+ if( this.bCornersOut )
+ {
+ aMatrix = SVGIdentityMatrix.translate( -0.25, -0.25 ).scale( d ).translate( -0.5, -0.5 );
+ }
+ else
+ {
+ aMatrix = SVGIdentityMatrix.translate( -0.5, -0.5 ).scale( d );
+ }
+
+
+ var aTransform = aMatrix;
+ // top left
+ var aSquare = this.aBasePath.cloneNode( true );
+ aSquare.matrixTransform( aTransform );
+ var aPolyPath = aSquare;
+ // bottom left, flip on x-axis:
+ aMatrix = SVGIdentityMatrix.flipY();
+ aTransform = aMatrix.multiply( aTransform );
+ aSquare = this.aBasePath.cloneNode( true );
+ aSquare.matrixTransform( aTransform );
+ aSquare.changeOrientation();
+ aPolyPath.appendPath( aSquare );
+ // bottom right, flip on y-axis:
+ aMatrix = SVGIdentityMatrix.flipX();
+ aTransform = aMatrix.multiply( aTransform );
+ aSquare = this.aBasePath.cloneNode( true );
+ aSquare.matrixTransform( aTransform );
+ aPolyPath.appendPath( aSquare );
+ // top right, flip on x-axis:
+ aMatrix = SVGIdentityMatrix.flipY();
+ aTransform = aMatrix.multiply( aTransform );
+ aSquare = this.aBasePath.cloneNode( true );
+ aSquare.matrixTransform( aTransform );
+ aSquare.changeOrientation();
+ aPolyPath.appendPath( aSquare );
+
+ // Remind: operations are applied in inverse order
+ aMatrix = SVGIdentityMatrix.translate( 0.5, 0.5 );
+ // We enlarge a bit the clip path so we avoid that in reverse direction
+ // some thin line of the border stroke is visible.
+ aMatrix = aMatrix.scale( 1.1 );
+ aPolyPath.matrixTransform( aMatrix );
+
+ return aPolyPath;
+};
+
+
+
+
+/** Class EllipseWipePath
+ * This class handles a parametric ellipse represented by a path made up of
+ * cubic Bezier curve segments that helps in performing the ellipseWipe
+ * transition.
+ *
+ * @param eSubtype
+ * The transition subtype.
+ */
+function EllipseWipePath( eSubtype )
+{
+ this.eSubtype = eSubtype;
+
+ // precomputed circle( 0.5, 0.5, SQRT2 / 2 )
+ var sPathData = 'M 0.5 -0.207107 ' +
+ 'C 0.687536 -0.207107 0.867392 -0.132608 1 0 ' +
+ 'C 1.13261 0.132608 1.20711 0.312464 1.20711 0.5 ' +
+ 'C 1.20711 0.687536 1.13261 0.867392 1 1 ' +
+ 'C 0.867392 1.13261 0.687536 1.20711 0.5 1.20711 ' +
+ 'C 0.312464 1.20711 0.132608 1.13261 0 1 ' +
+ 'C -0.132608 0.867392 -0.207107 0.687536 -0.207107 0.5 ' +
+ 'C -0.207107 0.312464 -0.132608 0.132608 0 0 ' +
+ 'C 0.132608 -0.132608 0.312464 -0.207107 0.5 -0.207107';
+
+ this.aBasePath = document.createElementNS( NSS['svg'], 'path' );
+ this.aBasePath.setAttribute( 'd', sPathData );
+}
+
+EllipseWipePath.prototype.perform = function( nT )
+{
+
+ var aTransform = SVGIdentityMatrix.translate( 0.5, 0.5 ).scale( nT ).translate( -0.5, -0.5 );
+ var aEllipse = this.aBasePath.cloneNode( true );
+ aEllipse.matrixTransform( aTransform );
+
+ return aEllipse;
+};
+
+/*
+ * Class FanWipePath
+ *
+ */
+function FanWipePath(bIsCenter, bIsSingle, bIsFanIn) {
+ this.bCenter = bIsCenter;
+ this.bSingle = bIsSingle;
+ this.bFanIn = bIsFanIn;
+ this.aBasePath = createUnitSquarePath();
+}
+
+FanWipePath.prototype.perform = function( nT ) {
+ var res = this.aBasePath.cloneNode(true);
+ var poly = PinWheelWipePath.calcCenteredClock(
+ nT / ((this.bCenter && this.bSingle) ? 2.0 : 4.0), 1.0);
+ res.appendPath(poly);
+ // flip on y-axis
+ var aTransform = SVGIdentityMatrix.flipY();
+ aTransform = aTransform.scaleNonUniform(-1.0, 1.0);
+ poly.matrixTransform(aTransform);
+ res.appendPath(poly);
+
+ if(this.bCenter) {
+ aTransform = SVGIdentityMatrix.scaleNonUniform(0.5, 0.5).translate(0.5, 0.5);
+ res.matrixTransform(aTransform);
+
+ if(!this.bSingle)
+ res.appendPath(flipOnXAxis(res));
+ }
+ else {
+ aTransform = SVGIdentityMatrix.scaleNonUniform(0.5, 1.0).translate(0.5, 1.0);
+ res.matrixTransform(aTransform);
+ }
+ return res;
+}
+
+/**
+ * Class ClockWipePath
+ *
+ */
+function ClockWipePath() { }
+
+ClockWipePath.prototype.perform = function( nT ) {
+ const aTransform = SVGIdentityMatrix.scaleNonUniform(0.5, 0.5).translate(0.5, 0.5);
+ var aPolyPath = PinWheelWipePath.calcCenteredClock(nT, 1.0);
+ aPolyPath.matrixTransform( aTransform );
+
+ return aPolyPath;
+}
+
+/** Class PinWheelWipePath
+ * This class handles a parametric poly-path that is used for performing
+ * a spinWheelWipe transition.
+ *
+ * @param nBlades
+ * Number of blades generated by the transition.
+ */
+function PinWheelWipePath( nBlades )
+{
+ this.nBlades = nBlades;
+ if( !this.nBlades || this.nBlades < 1 )
+ this.nBlades = 1;
+}
+
+PinWheelWipePath.calcCenteredClock = function( nT, nE )
+{
+ var nMAX_EDGE = 2;
+
+ var aTransform = SVGIdentityMatrix.rotate( nT * 360 );
+
+ var aPoint = document.documentElement.createSVGPoint();
+ aPoint.y = -nMAX_EDGE;
+ aPoint = aPoint.matrixTransform( aTransform );
+
+ var sPathData = 'M ' + aPoint.x + ' ' + aPoint.y + ' ';
+ if( nT >= 0.875 )
+ // L -e -e
+ sPathData += 'L ' + '-' + nE + ' -' + nE + ' ';
+ if( nT >= 0.625 )
+ // L -e e
+ sPathData += 'L ' + '-' + nE + ' ' + nE + ' ';
+ if( nT >= 0.375 )
+ // L e e
+ sPathData += 'L ' + nE + ' ' + nE + ' ';
+ if( nT >= 0.125 )
+ // L e -e
+ sPathData += 'L ' + nE + ' -' + nE + ' ';
+
+ // L 0 -e
+ sPathData += 'L 0 -' + nE + ' ';
+ sPathData += 'L 0 0 ';
+ // Z
+ sPathData += 'L ' + aPoint.x + ' ' + aPoint.y;
+
+ var aPath = document.createElementNS( NSS['svg'], 'path' );
+ aPath.setAttribute( 'd', sPathData );
+ return aPath;
+};
+
+PinWheelWipePath.prototype.perform = function( nT )
+{
+ var aBasePath = PinWheelWipePath.calcCenteredClock( nT / this.nBlades,
+ 2.0 /* max edge when rotating */ );
+
+ var aPolyPath = aBasePath.cloneNode( true );
+ var aPath;
+ var aRotation;
+ var i;
+ for( i = this.nBlades - 1; i > 0; --i )
+ {
+ aRotation = SVGIdentityMatrix.rotate( (i * 360) / this.nBlades );
+ aPath = aBasePath.cloneNode( true );
+ aPath.matrixTransform( aRotation );
+ aPolyPath.appendPath( aPath );
+ }
+
+ var aTransform = SVGIdentityMatrix.translate( 0.5, 0.5 ).scale( 0.5 );
+ aPolyPath.matrixTransform( aTransform );
+
+ return aPolyPath;
+};
+
+/** Class BarnDoorWipe
+ *
+ * @param doubled
+ */
+function BarnDoorWipePath(doubled) {
+ this.aBasePath = createUnitSquarePath();
+ this.doubled = doubled;
+}
+
+BarnDoorWipePath.prototype.perform = function( nT ) {
+ if(this.doubled)
+ nT /= 2.0;
+ var aTransform = SVGIdentityMatrix.translate(-0.5, -0.5);
+ aTransform = aTransform.scaleNonUniform(pruneScaleValue(nT), 1.0).translate(0.5, 0.5);
+ var aPath = this.aBasePath.cloneNode(true);
+ aPath.matrixTransform(aTransform);
+ var res = aPath;
+
+ if(this.doubled) {
+ aTransform = SVGIdentityMatrix.translate(-0.5, -0.5);
+ aTransform = aTransform.rotate(Math.PI / 2).translate(0.5, 0.5);
+ aPath.matrixTransform(aTransform);
+ res.appendPath(aPath);
+ }
+ return res;
+}
+
+/** Class WaterfallWipe
+ *
+ * @param nElements
+ * Number of cells to be used
+ * @param bFlipOnYAxis
+ * Whether to flip on y-axis or not.
+ */
+function WaterfallWipePath(nElements, bFlipOnYAxis) {
+ this.bFlipOnYAxis = bFlipOnYAxis;
+
+ var sqrtElements = Math.floor(Math.sqrt(nElements));
+ var elementEdge = 1.0/sqrtElements;
+
+ var aPath = 'M '+ 0.0 + ' ' + -1.0 + ' ';
+ for(var pos = sqrtElements; pos--; ) {
+ var xPos = sqrtElements - pos - 1;
+ var yPos = pruneScaleValue( ((pos+1) * elementEdge) - 1.0);
+
+ aPath += 'L ' + pruneScaleValue(xPos * elementEdge) + ' ' + yPos + ' ';
+ aPath += 'L ' + pruneScaleValue((xPos+1)*elementEdge) + ' ' + yPos + ' ';
+ }
+ aPath += 'L ' + 1.0 + ' ' + -1.0 + ' ';
+ aPath += 'L ' + 0.0 + ' ' + -1.0 + ' ';
+ this.aBasePath = document.createElementNS( NSS['svg'], 'path');
+ this.aBasePath.setAttribute('d', aPath);
+}
+
+WaterfallWipePath.prototype.perform = function( nT ) {
+ var poly = this.aBasePath.cloneNode(true);
+ var aTransform = SVGIdentityMatrix.translate(0.0, pruneScaleValue(2.0 * nT));
+ poly.matrixTransform(aTransform);
+ var aHead = 'M ' + 0.0 + ' ' + -1.0 + ' ';
+ var aHeadPath= document.createElementNS( NSS['svg'], 'path');
+ aHeadPath.setAttribute('d', aHead);
+
+ var aTail = 'M ' + 1.0 + ' ' + -1.0 + ' ';
+ var aTailPath = document.createElementNS( NSS['svg'], 'path');
+ aTailPath.setAttribute('d', aTail);
+
+ poly.prependPath(aHeadPath);
+ poly.appendPath(aTailPath);
+
+ return this.bFlipOnYAxis ? flipOnYAxis(poly) : poly;
+}
+
+/** Class DoubleDiamondWipePath
+ *
+ */
+function DoubleDiamondWipePath() { }
+
+DoubleDiamondWipePath.prototype.perform = function( nT ) {
+ var a = pruneScaleValue(0.25 + (nT * 0.75));
+ var aPath = 'M ' + (0.5 + a) + ' ' + 0.5 + ' ';
+ aPath += 'L ' + 0.5 + ' ' + (0.5 - a) + ' ';
+ aPath += 'L ' + (0.5 - a) + ' ' + 0.5 + ' ';
+ aPath += 'L ' + 0.5 + ' ' + (0.5 + a) + ' ';
+ aPath += 'L ' + (0.5 + a) + ' ' + 0.5 + ' ';
+ var poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', aPath);
+ var res = poly.cloneNode(true);
+
+ var b = pruneScaleValue( (1.0 - nT) * 0.25);
+ aPath = 'M ' + (0.5 + b) + ' ' + 0.5 + ' ';
+ aPath += 'L ' + 0.5 + ' ' + (0.5 + b) + ' ';
+ aPath += 'L ' + (0.5 - b) + ' ' + 0.5 + ' ';
+ aPath += 'L ' + 0.5 + ' ' + (0.5 - b) + ' ';
+ aPath += 'L ' + (0.5 + b) + ' ' + 0.5 + ' ';
+ poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', aPath);
+ res.appendPath(poly);
+
+ return res;
+}
+
+/** Class Iriswipe
+ *
+ * @param unitRect
+ *
+ */
+function IrisWipePath(unitRect) {
+ this.unitRect = unitRect;
+ this.aBasePath = createUnitSquarePath();
+}
+
+
+/** perform
+ *
+ * @param nT
+ * A parameter in [0,1] representing the diamond or rectangle.
+ * @return SVGPathElement
+ * A svg <path> element representing a transition.
+ */
+IrisWipePath.prototype.perform = function( nT ) {
+ var d = pruneScaleValue(nT);
+ var aTransform = SVGIdentityMatrix.translate(-0.5, -0.5);
+ aTransform = aTransform.multiply(SVGIdentityMatrix.scaleNonUniform(d, d).translate(0.5, 0.5));
+ var aPath = this.aBasePath.cloneNode(true);
+ aPath.matrixTransform(aTransform);
+ return aPath;
+}
+
+/**
+ * Class ZigZagWipePath
+ *
+ * @param nZigs
+ *
+ */
+function ZigZagWipePath(nZigs) {
+ this.zigEdge = 1.0/nZigs;
+ const d = this.zigEdge;
+ const d2 = (d / 2.0);
+ this.aBasePath = 'M ' + (-1.0 - d) + ' ' + -d + ' ';
+ this.aBasePath += 'L ' + (-1.0 - d) + ' ' + (1.0 + d) + ' ';
+ this.aBasePath += 'L ' + -d + ' ' + (1.0 + d) + ' ';
+
+ for(var pos = (nZigs + 2); pos--; ) {
+ this.aBasePath += 'L ' + 0.0 + ' ' + ((pos - 1) * d + d2) + ' ';
+ this.aBasePath += 'L ' + -d + ' ' + (pos - 1) * d + ' ';
+ }
+ this.aBasePath += 'L ' + (-1.0 - d) + ' ' + -d + ' ';
+}
+
+ZigZagWipePath.prototype.perform = function( nT ) {
+ var res = document.createElementNS( NSS['svg'], 'path');
+ res.setAttribute('d', this.aBasePath);
+ res.matrixTransform(SVGIdentityMatrix.translate((1.0 + this.zigEdge) * nT, 0.0));
+ return res;
+}
+
+/*
+ * Class BarnZigZagWipePath
+ *
+ * @param nZigs
+ *
+ */
+function BarnZigZagWipePath( nZigs ) { ZigZagWipePath.call(this, nZigs); }
+
+BarnZigZagWipePath.prototype = Object.create(ZigZagWipePath);
+
+BarnZigZagWipePath.prototype.perform = function( nT ) {
+ var res = createEmptyPath();
+ var poly = document.createElementNS( NSS['svg'], 'path');
+ var aTransform = SVGIdentityMatrix.translate(
+ ((1.0 + this.zigEdge) * (1.0 - nT)) / 2.0, 0.0);
+ poly.setAttribute('d', this.aBasePath);
+ poly.changeOrientation();
+ poly.matrixTransform(aTransform);
+ res.appendPath(poly);
+
+ aTransform = SVGIdentityMatrix.scale(-1.0, 1.0);
+ aTransform.translate(1.0, this.zigEdge / 2.0);
+ poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', this.aBasePath);
+ poly.matrixTransform(aTransform);
+ res.appendPath(poly);
+
+ return res;
+}
+
+/** Class CheckerBoardWipePath
+ *
+ * @param unitsPerEdge
+ * The number of cells (per line and column) in the checker board.
+ */
+function CheckerBoardWipePath( unitsPerEdge )
+{
+ this.unitsPerEdge = unitsPerEdge;
+ if( this.unitsPerEdge === undefined || this.unitsPerEdge < 1 )
+ this.unitsPerEdge = 10;
+ this.aBasePath = createUnitSquarePath();
+}
+
+/** perform
+ *
+ * @param nT
+ * A parameter in [0,1] representing the width of the generated bars.
+ * @return SVGPathElement
+ * A svg <path> element representing a multi-bars.
+ */
+CheckerBoardWipePath.prototype.perform = function( nT )
+{
+ var d = pruneScaleValue(1.0 / this.unitsPerEdge);
+ var aMatrix = SVGIdentityMatrix.scaleNonUniform(pruneScaleValue( d*2.0*nT ),
+ pruneScaleValue( d ) );
+
+ var aPolyPath = null;
+ var i, j;
+ var aTransform;
+ var aPath;
+ for ( i = this.unitsPerEdge; i--; )
+ {
+ aTransform = SVGIdentityMatrix;
+
+ if ((i % 2) == 1) // odd line
+ aTransform = aTransform.translate( -d, 0.0 );
+
+ aTransform = aTransform.multiply( aMatrix );
+
+ for ( j = (this.unitsPerEdge / 2) + 1; j--;)
+ {
+ aPath = this.aBasePath.cloneNode( true );
+ aPath.matrixTransform( aTransform );
+ if (aPolyPath == null) aPolyPath = aPath;
+ else aPolyPath.appendPath( aPath );
+ aTransform = SVGIdentityMatrix.translate( d*2.0, 0.0 ).multiply( aTransform );
+ }
+
+ aMatrix = SVGIdentityMatrix.translate( 0.0, d ).multiply( aMatrix ); // next line
+ }
+
+ return aPolyPath;
+};
+
+
+
+/** Class RandomWipePath
+ *
+ * @param nElements
+ * The number of bars or cells to be used.
+ * @param bRandomBars
+ * true: generates a horizontal random bar wipe
+ * false: generates a dissolve wipe
+ */
+function RandomWipePath( nElements, bRandomBars )
+{
+ this.nElements = nElements;
+ this.aBasePath = createUnitSquarePath();
+ this.aPositionArray = new Array( nElements );
+ this.aClipPath = createEmptyPath();
+ this.nAlreadyAppendedElements = 0;
+
+ var fEdgeLength, nPos, aTransform;
+
+ if( bRandomBars ) // random bar wipe
+ {
+ fEdgeLength = 1.0 / nElements;
+ for( nPos = 0; nPos < nElements; ++nPos )
+ {
+ this.aPositionArray[nPos] = { x: 0.0, y: pruneScaleValue( nPos * fEdgeLength ) }
+ }
+ aTransform = SVGIdentityMatrix.scaleNonUniform( 1.0, pruneScaleValue( fEdgeLength ) );
+ }
+ else // dissolve wipe
+ {
+ var nSqrtElements = Math.round( Math.sqrt( nElements ) );
+ fEdgeLength = 1.0 / nSqrtElements;
+ for( nPos = 0; nPos < nElements; ++nPos )
+ {
+ this.aPositionArray[nPos] = {
+ x: pruneScaleValue( ( nPos % nSqrtElements ) * fEdgeLength ),
+ y: pruneScaleValue( ( nPos / nSqrtElements ) * fEdgeLength ) }
+ }
+ aTransform = SVGIdentityMatrix.scale( pruneScaleValue( fEdgeLength ) );
+ }
+ this.aBasePath.matrixTransform( aTransform );
+
+ var nPos1, nPos2;
+ var tmp;
+ for( nPos1 = nElements - 1; nPos1 > 0; --nPos1 )
+ {
+ nPos2 = getRandomInt( nPos1 + 1 );
+ tmp = this.aPositionArray[nPos1];
+ this.aPositionArray[nPos1] = this.aPositionArray[nPos2];
+ this.aPositionArray[nPos2] = tmp;
+ }
+}
+
+/** perform
+ *
+ * @param nT
+ * A parameter in [0,1] representing the width of the generated bars or squares.
+ * @return SVGPathElement
+ * A svg <path> element representing a multi bars or a multi squared cells.
+ */
+RandomWipePath.prototype.perform = function( nT )
+{
+ var aPolyPath = createEmptyPath();
+ var aPoint;
+ var aPath;
+ var aTransform;
+ var nElements = Math.round( nT * this.nElements );
+ if( nElements === 0 )
+ {
+ return aPolyPath;
+ }
+ // check if we need to reset the clip path
+ if( this.nAlreadyAppendedElements >= nElements )
+ {
+ this.nAlreadyAppendedElements = 0;
+ this.aClipPath = createEmptyPath();
+ }
+ var nPos;
+ for( nPos = this.nAlreadyAppendedElements; nPos < nElements; ++nPos )
+ {
+ aPoint = this.aPositionArray[nPos];
+ aPath = this.aBasePath.cloneNode( true );
+ aTransform = SVGIdentityMatrix.translate( aPoint.x, aPoint.y );
+ aPath.matrixTransform( aTransform );
+ aPolyPath.appendPath( aPath );
+ }
+
+ this.nAlreadyAppendedElements = nElements;
+ this.aClipPath.appendPath( aPolyPath );
+
+ return this.aClipPath.cloneNode( true );
+};
+
+/** Class SnakeWipeSlide
+ *
+ * @param nElements
+ * @param bDiagonal
+ * @param bFlipOnYaxis
+ */
+function SnakeWipePath(nElements, bDiagonal, bflipOnYAxis)
+{
+ this.sqrtElements = Math.floor(Math.sqrt(nElements));
+ this.elementEdge = (1.0 / this.sqrtElements);
+ this.diagonal = bDiagonal;
+ this.flipOnYAxis = bflipOnYAxis;
+ this.aBasePath = createUnitSquarePath();
+}
+
+SnakeWipePath.prototype.calcSnake = function(t)
+{
+ var aPolyPath = createEmptyPath();
+ const area = (t * this.sqrtElements * this.sqrtElements);
+ const line_ = Math.floor(area) / this.sqrtElements;
+ const line = pruneScaleValue(line_ / this.sqrtElements);
+ const col = pruneScaleValue((area - (line_ * this.sqrtElements)) / this.sqrtElements);
+
+ if(line != 0) {
+ let aPath = 'M '+ 0.0 + ' ' + 0.0 + ' ';
+ aPath += 'L ' + 0.0 + ' ' + line + ' ';
+ aPath += 'L ' + 1.0 + ' ' + line + ' ';
+ aPath += 'L ' + 1.0 + ' ' + 0.0 + ' ';
+ aPath += 'L 0 0 ';
+ let poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', aPath);
+ aPolyPath.appendPath(poly);
+ }
+ if(col != 0) {
+ var offset = 0.0;
+ if((line_ & 1) == 1) {
+ // odd line: => right to left
+ offset = (1.0 - col);
+ }
+ let aPath = 'M ' + offset + ' ' + line + ' ';
+ aPath += 'L '+ offset + ' ' + (line + this.elementEdge) + ' ';
+ aPath += 'L ' + (offset+col) + ' ' + (line + this.elementEdge) + ' ';
+ aPath += 'L ' + (offset+col) + ' ' + line + ' ';
+ aPath += 'L ' + offset + ' ' + line + ' ';
+ let poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', aPath);
+ aPolyPath.appendPath(poly);
+ }
+
+ return aPolyPath;
+}
+
+SnakeWipePath.prototype.calcHalfDiagonalSnake = function(nT, bIn) {
+ var res = createEmptyPath();
+
+ if(bIn) {
+ const sqrtArea2 = Math.sqrt(nT * this.sqrtElements * this.sqrtElements);
+ const edge = pruneScaleValue(sqrtArea2 / this.sqrtElements);
+
+ var aPath, aPoint = document.documentElement.createSVGPoint();
+ if(edge) {
+ aPath = 'M ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.y = edge;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = edge;
+ aPoint.y = 0.0;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = 0.0;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ const poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', aPath);
+ res.appendPath(poly);
+ }
+ const a = (Math.SQRT1_2 / this.sqrtElements);
+ const d = (sqrtArea2 - Math.floor(sqrtArea2));
+ const len = (nT * Math.SQRT1_2 * d);
+ const height = pruneScaleValue(Math.SQRT1_2 / this.sqrtElements);
+ aPath = 'M ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.y = height;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = len + a;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.y = 0.0;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = 0.0;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ const poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', aPath);
+ let aTransform;
+
+ if((Math.floor(sqrtArea2) & 1) == 1) {
+ // odd line
+ aTransform = SVGIdentityMatrix.rotate((Math.PI)/2 + (Math.PI)/4);
+ aTransform.translate(edge + this.elementEdge, 0.0);
+ }
+ else {
+ aTransform = SVGIdentityMatrix.translate(-a, 0.0);
+ aTransform.rotate(-(Math.PI/4));
+ aTransform.translate(0.0, edge);
+ }
+
+ poly.matrixTransform(aTransform);
+ res.appendPath(poly);
+ }
+ else { //out
+ const sqrtArea2 = Math.sqrt(nT * this.sqrtElements * this.sqrtElements);
+ const edge = pruneScaleValue(Math.floor(sqrtArea2)/this.sqrtElements);
+
+ let aPath, aPoint = document.documentElement.createSVGPoint();
+ if(edge != 0) {
+ aPoint.y = 1.0;
+ aPath = 'M ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = edge;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = 1.0;
+ aPoint.y = edge;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.y = 0.0;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = 0.0;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ const poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', aPath);
+ res.appendPath(poly);
+ }
+ const a = (Math.SQRT1_2 / this.sqrtElements);
+ const d = (sqrtArea2 - Math.floor(sqrtArea2));
+ const len = ((1.0 - nT) * Math.SQRT2 * d);
+ const height = pruneScaleValue(Math.SQRT1_2 / this.sqrtElements);
+ aPath = 'M ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.y = height;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = len + a;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.y = 0.0;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ aPoint.x = 0.0;
+ aPath += 'L ' + aPoint.x + ' ' + aPoint.y + ' ';
+ const poly = document.createElementNS( NSS['svg'], 'path');
+ poly.setAttribute('d', aPath);
+ let aTransform;
+
+ if((Math.floor(sqrtArea2) & 1) == 1) {
+ // odd line
+ aTransform = SVGIdentityMatrix.translate(0.0, -height);
+ aTransform.rotate(Math.PI/2 + Math.PI/4);
+ aTransform.translate(1.0, edge);
+ }
+ else {
+ aTransform = SVGIdentityMatrix.rotate(-(Math.PI/4));
+ aTransform = aTransform.translate(edge, 1.0);
+ }
+ poly.matrixTransform(aTransform);
+ res.appendPath(poly);
+ }
+ return res;
+}
+
+SnakeWipePath.prototype.perform = function(nT) {
+ var res = createEmptyPath();
+ if(this.diagonal) {
+ if(nT >= 0.5) {
+ res.appendPath(this.calcHalfDiagonalSnake(1.0, true));
+ res.appendPath(this.calcHalfDiagonalSnake(2.0*(nT-0.5), false));
+ }
+ else
+ res.appendPath(this.calcHalfDiagonalSnake(2.0*nT, true));
+ }
+ else
+ res = this.calcSnake(nT);
+
+ return this.flipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+/** Class ParallelSnakesWipePath
+ * Generates a parallel snakes wipe:
+ *
+ * @param nElements
+ * @param bDiagonal
+ * @param bFlipOnYAxis
+ * @param bOpposite
+ */
+function ParallelSnakesWipePath(nElements, bDiagonal, bFlipOnYAxis, bOpposite) {
+ SnakeWipePath.call(this, nElements, bDiagonal, bFlipOnYAxis);
+ this.bOpposite = bOpposite;
+}
+
+ParallelSnakesWipePath.prototype = Object.create(SnakeWipePath);
+
+ParallelSnakesWipePath.prototype.perform = function( nT ) {
+ var res = createEmptyPath(), half, aTransform;
+ if(this.diagonal) {
+ assert(this.bOpposite);
+ half = SnakeWipePath.prototype.calcHalfDiagonalSnake.call(this, nT, false);
+ // flip on x axis and rotate 90 degrees:
+ aTransform = SVGIdentityMatrix.scale(1, -1);
+ aTransform.translate(-0.5, 0.5);
+ aTransform.rotate(Math.PI/2);
+ aTransform.translate(0.5, 0.5);
+ half.matrixTransform(aTransform);
+ half.changeOrientation();
+ res.appendPath(half);
+
+ // rotate 180 degrees:
+ aTransform = SVGIdentityMatrix.translate(-0.5, -0.5);
+ aTransform.rotate(Math.PI);
+ aTransform.translate(0.5, 0.5);
+ half.matrixTransform(aTransform);
+ res.appendPath(half);
+ }
+ else {
+ half = SnakeWipePath.prototype.calcSnake.call(this, nT / 2.0 );
+ // rotate 90 degrees
+ aTransform = SVGIdentityMatrix.translate(-0.5, -0.5);
+ aTransform = aTransform.rotate(Math.PI/2);
+ aTransform = aTransform.translate(0.5, 0.5);
+ half.matrixTransform(aTransform);
+ res.appendPath(flipOnYAxis(half));
+ res.appendPath(this.bOpposite ? flipOnXAxis(half) : half);
+ }
+
+ return this.flipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+/** SpiralWipePath
+ *
+ * @param nElements
+ * number of elements in the spiral animation
+ * @param bFlipOnYAxis
+ * boolean value indicating whether to flip on y-axis or not.
+ */
+function SpiralWipePath(nElements, bFlipOnYAxis) {
+ this.nElements = nElements;
+ this.sqrtElements = Math.floor(Math.sqrt(nElements));
+ this.bFlipOnYAxis = bFlipOnYAxis;
+}
+
+SpiralWipePath.prototype.calcNegSpiral = function( nT ) {
+ var area = nT * this.nElements;
+ var e = (Math.sqrt(area) / 2.0);
+ var edge = Math.floor(e) * 2;
+
+ var aTransform = SVGIdentityMatrix.translate(-0.5, -0.5);
+ var edge_ = pruneScaleValue(edge / this.sqrtElements);
+
+ aTransform = aTransform.scale(edge_, edge_);
+ aTransform = aTransform.translate(0.5, 0.5);
+ var poly = createUnitSquarePath();
+ poly.matrixTransform(aTransform);
+ var res = poly.cloneNode(true);
+
+ if(1.0 - nT != 0) {
+ var edge1 = edge + 1;
+ var len = Math.floor( (e - edge/2) * edge1 * 4);
+ var w = Math.PI / 2;
+
+ while(len > 0) {
+ var alen = Math.min(len, edge1);
+ len -= alen;
+ poly = createUnitSquarePath();
+ aTransform = SVGIdentityMatrix.scale(
+ pruneScaleValue( alen / this.sqrtElements ),
+ pruneScaleValue( 1.0 / this.sqrtElements ));
+ aTransform = aTransform.translate(
+ - pruneScaleValue( (edge / 2) / this.sqrtElements ),
+ pruneScaleValue( (edge / 2) / this.sqrtElements ));
+ aTransform = aTransform.rotate( w );
+ w -= Math.PI / 2;
+ aTransform = aTransform.translate(0.5, 0.5);
+ poly.matrixTransform(aTransform);
+ res.appendPath(poly);
+ }
+ }
+
+ return res;
+}
+
+SpiralWipePath.prototype.perform = function( nT ) {
+ var res = createUnitSquarePath();
+ var innerSpiral = this.calcNegSpiral( 1.0 - nT );
+ innerSpiral.changeOrientation();
+ res.appendPath(innerSpiral);
+
+ return this.bFlipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+/** Class BoxSnakesWipePath
+ * Generates a twoBoxLeft or fourBoxHorizontal wipe:
+ *
+ */
+function BoxSnakesWipePath(nElements, bFourBox) {
+ SpiralWipePath.call(this, nElements);
+ this.bFourBox = bFourBox;
+}
+
+BoxSnakesWipePath.prototype = Object.create(SpiralWipePath);
+
+BoxSnakesWipePath.prototype.perform = function( nT ) {
+ var res = createUnitSquarePath(), aTransform;
+ var innerSpiral = SpiralWipePath.prototype.calcNegSpiral.call(this, 1.0 - nT);
+ innerSpiral.changeOrientation();
+
+ if(this.bFourBox) {
+ aTransform = SVGIdentityMatrix.scale(0.5, 0.5);
+ innerSpiral.matrixTransform(aTransform);
+ res.appendPath(innerSpiral);
+ res.appendPath(flipOnXAxis(innerSpiral));
+ innerSpiral = flipOnYAxis(innerSpiral);
+ res.appendPath(innerSpiral);
+ res.appendPath(flipOnXAxis(innerSpiral));
+ }
+ else {
+ aTransform = SVGIdentityMatrix.scale(1.0, 0.5);
+ innerSpiral.matrixTransform(aTransform);
+ res.appendPath(innerSpiral);
+ res.appendPath(flipOnXAxis(innerSpiral));
+ }
+ return this.bFlipOnYAxis ? flipOnYAxis(res) : res;
+}
+
+/** Class VeeWipePath
+ *
+ */
+function VeeWipePath() { }
+
+VeeWipePath.prototype.perform = function( nT ) {
+ const d = pruneScaleValue(2.0 * nT);
+ var polyPath = 'M ' + 0.0 + ' ' + -1.0 + ' ';
+ polyPath += 'L ' + 0.0 + ' ' + (d - 1.0) + ' ';
+ polyPath += 'L ' + 0.5 + ' ' + d + ' ';
+ polyPath += 'L ' + 1.0 + ' ' + (d - 1.0) + ' ';
+ polyPath += 'L ' + 1.0 + ' ' + -1.0 + ' ';
+ polyPath += 'L ' + 0.0 + ' ' + -1.0 + ' ';
+
+ var aPolyPolyPath = document.createElementNS( NSS['svg'], 'path');
+ aPolyPolyPath.setAttribute('d', polyPath);
+ return aPolyPolyPath;
+}
+
+
+/** Class AnimatedSlide
+ * This class handle a slide element during a slide transition.
+ *
+ * @param aMetaSlide
+ * The MetaSlide object related to the slide element to be handled.
+ */
+function AnimatedSlide( aMetaSlide )
+{
+ if( !aMetaSlide )
+ {
+ log( 'AnimatedSlide constructor: meta slide is not valid' );
+ }
+
+ this.aMetaSlide = aMetaSlide;
+ this.aSlideElement = this.aMetaSlide.slideElement;
+ this.sSlideId = this.aMetaSlide.slideId;
+
+ this.aUsedAttributeSet = [];
+
+ this.aClipPathElement = null;
+ this.aClipPathContent = null;
+ this.bIsClipped = false;
+}
+
+/** show
+ * Set the visibility property of the slide to 'inherit'
+ * and update the master page view.
+ */
+AnimatedSlide.prototype.show = function()
+{
+ this.aMetaSlide.show();
+};
+
+/** hide
+ * Set the visibility property of the slide to 'hidden'.
+ */
+AnimatedSlide.prototype.hide = function()
+{
+ this.aMetaSlide.hide();
+};
+
+/** notifyUsedAttribute
+ * Populate the set of attribute used for the transition.
+ *
+ * @param sName
+ * A string representing an attribute name.
+ */
+AnimatedSlide.prototype.notifyUsedAttribute = function( sName )
+{
+ if( sName == 'clip-path' )
+ {
+ this.initClipPath();
+ this.bIsClipped = true;
+ }
+ else
+ {
+ this.aUsedAttributeSet.push( sName );
+ }
+};
+
+/** reset
+ * Remove from the handled slide element any attribute that was appended for
+ * performing the transition.
+ */
+AnimatedSlide.prototype.reset = function()
+{
+ if( this.bIsClipped )
+ {
+ this.cleanClipPath();
+ this.bIsClipped = false;
+ }
+
+ var i;
+ for( i = 0; i < this.aUsedAttributeSet.length; ++i )
+ {
+ var sAttrName = this.aUsedAttributeSet[i];
+ this.aSlideElement.removeAttribute( sAttrName );
+ }
+ this.aUsedAttributeSet = [];
+};
+
+/** initClipPath
+ * Create a new clip path element and append it to the clip path def group.
+ * Moreover the created <clipPath> element is referenced by the handled slide
+ * element.
+ */
+AnimatedSlide.prototype.initClipPath = function()
+{
+ // We create the clip path element.
+ this.aClipPathElement = document.createElementNS( NSS['svg'], 'clipPath' );
+
+ var sId = 'clip-path-' + this.sSlideId;
+ this.aClipPathElement.setAttribute( 'id', sId );
+ this.aClipPathElement.setAttribute( 'clipPathUnits', 'userSpaceOnUse' );
+
+ // We create and append a placeholder content.
+ this.aClipPathContent = document.createElementNS( NSS['svg'], 'path' );
+ var sPathData = 'M 0 0 h ' + WIDTH + ' v ' + HEIGHT + ' h -' + WIDTH + ' z';
+ this.aClipPathContent.setAttribute( 'd', sPathData );
+ this.aClipPathElement.appendChild( this.aClipPathContent );
+
+ // We insert it into the svg document.
+ var aClipPathGroup = theMetaDoc.aClipPathGroup;
+ aClipPathGroup.appendChild( this.aClipPathElement );
+
+ // Finally we set the reference to the created clip path.
+ // We set it on the parent element because a slide element already
+ // owns a clip path attribute.
+ var sRef = 'url(#' + sId + ')';
+ this.aSlideElement.parentNode.setAttribute( 'clip-path', sRef );
+};
+
+/** cleanClipPath
+ * Removes the related <clipPath> element from the <defs> group,
+ * and remove the 'clip-path' attribute from the slide element.
+ *
+ */
+AnimatedSlide.prototype.cleanClipPath = function()
+{
+ this.aSlideElement.parentNode.removeAttribute( 'clip-path' );
+
+ if( this.aClipPathElement )
+ {
+ var aClipPathGroup = theMetaDoc.aClipPathGroup;
+ aClipPathGroup.removeChild( this.aClipPathElement );
+ this.aClipPathElement = null;
+ this.aClipPathContent = null;
+ }
+};
+
+/** insertBefore
+ * Insert an svg element before the handled slide element.
+ *
+ * @param aElement
+ * A svg element.
+ */
+AnimatedSlide.prototype.insertBefore = function( aElement )
+{
+ if( aElement )
+ {
+ this.aSlideElement.parentNode.insertBefore( aElement, this.aSlideElement );
+ }
+};
+
+/** appendElement
+ * Insert an svg element after the handled slide element.
+ *
+ * @param aElement
+ * A svg element.
+ */
+AnimatedSlide.prototype.appendElement = function( aElement )
+{
+ if( aElement )
+ {
+ this.aSlideElement.parentNode.appendChild( aElement );
+ }
+};
+
+/** removeElement
+ * Remove an svg element.
+ *
+ * @param aElement
+ * A svg element.
+ */
+AnimatedSlide.prototype.removeElement = function( aElement )
+{
+ if( aElement )
+ {
+ this.aSlideElement.parentNode.removeChild( aElement );
+ }
+};
+
+/** getWidth
+ *
+ * @return {Number}
+ * The slide width.
+ */
+AnimatedSlide.prototype.getWidth = function()
+{
+ return WIDTH;
+};
+
+/** getHeight
+ *
+ * @return {Number}
+ * The slide height.
+ */
+AnimatedSlide.prototype.getHeight = function()
+{
+ return HEIGHT;
+};
+
+/** setOpacity
+ *
+ * @param nValue
+ * A number in the [0,1] range representing the slide opacity.
+ */
+AnimatedSlide.prototype.setOpacity = function( nValue )
+{
+ this.aSlideElement.setAttribute( 'opacity', nValue );
+};
+
+/** translate
+ * Translate the handled slide.
+ *
+ * @param nDx
+ * A number representing the translation that occurs in the x direction.
+ * @param nDy
+ * A number representing the translation that occurs in the y direction.
+ */
+AnimatedSlide.prototype.translate = function( nDx, nDy )
+{
+ var sTransformAttr = 'translate(' + nDx + ',' + nDy + ')';
+ this.aSlideElement.setAttribute( 'transform', sTransformAttr );
+};
+
+/** setClipPath
+ * Replace the current content of the <clipPath> element with the one
+ * passed through the parameter.
+ *
+ * @param aClipPathContent
+ * A <g> element representing a <path> element used for clipping.
+ */
+AnimatedSlide.prototype.setClipPath = function( aClipPathContent )
+{
+ // Earlier we used to replace the current <path> element with the passed one,
+ // anyway that does not work in IE9, so we replace the 'd' attribute, only.
+ if( this.aClipPathContent )
+ {
+ var sPathData = aClipPathContent.getAttribute( 'd' );
+ this.aClipPathContent.setAttribute( 'd', sPathData );
+ }
+};
+
+
+
+function AnimatedElement( aElement )
+{
+ if( !aElement )
+ {
+ log( 'AnimatedElement constructor: element is not valid' );
+ }
+
+ this.aSlideShowContext = null;
+
+ this.aBaseElement = aElement.cloneNode( true );
+ this.aActiveElement = aElement;
+ this.sElementId = this.aActiveElement.getAttribute( 'id' );
+
+ this.aBaseBBox = this.aActiveElement.getBBox();
+ this.nBaseCenterX = this.aBaseBBox.x + this.aBaseBBox.width / 2;
+ this.nBaseCenterY = this.aBaseBBox.y + this.aBaseBBox.height / 2;
+
+
+ this.aClipPathElement = null;
+ this.aClipPathContent = null;
+
+ this.aPreviousElement = null;
+ this.aStateSet = {};
+
+ this.eAdditiveMode = ADDITIVE_MODE_REPLACE;
+ this.bIsUpdated = true;
+
+ this.aTMatrix = document.documentElement.createSVGMatrix();
+ this.aCTM = document.documentElement.createSVGMatrix();
+ this.aICTM = document.documentElement.createSVGMatrix();
+
+ this.initElement();
+}
+
+AnimatedElement.prototype.initElement = function()
+{
+ this.nCenterX = this.nBaseCenterX;
+ this.nCenterY = this.nBaseCenterY;
+ this.nScaleFactorX = 1.0;
+ this.nScaleFactorY = 1.0;
+ this.nRotationAngle = 0.0;
+
+ // add a transform attribute of type matrix
+ this.aActiveElement.setAttribute( 'transform', makeMatrixString( 1, 0, 0, 1, 0, 0 ) );
+};
+
+/** initClipPath
+ * Create a new clip path element and append it to the clip path def group.
+ * Moreover the created <clipPath> element is referenced by the handled
+ * animated element.
+ *
+ */
+AnimatedElement.prototype.initClipPath = function()
+{
+ // We create the clip path element.
+ this.aClipPathElement = document.createElementNS( NSS['svg'], 'clipPath' );
+
+ var sId = 'clip-path-' + this.sElementId;
+ this.aClipPathElement.setAttribute( 'id', sId );
+ this.aClipPathElement.setAttribute( 'clipPathUnits', 'userSpaceOnUse' );
+
+ // We create and append a placeholder content.
+ this.aClipPathContent = document.createElementNS( NSS['svg'], 'path' );
+ this.aClippingBBox = this.getBBoxWithStroke();
+ var nWidth = this.aClippingBBox.width;
+ var nHeight = this.aClippingBBox.height;
+ var sPathData = 'M ' + this.aClippingBBox.x + ' ' + this.aClippingBBox.y +
+ ' h ' + nWidth + ' v ' + nHeight + ' h -' + nWidth + ' z';
+ this.aClipPathContent.setAttribute( 'd', sPathData );
+ this.aClipPathElement.appendChild( this.aClipPathContent );
+
+ // We insert it into the svg document.
+ var aClipPathGroup = theMetaDoc.aClipPathGroup;
+ aClipPathGroup.appendChild( this.aClipPathElement );
+
+ // Finally we set the reference to the created clip path.
+ var sRef = 'url(#' + sId + ')';
+ this.aActiveElement.setAttribute( 'clip-path', sRef );
+};
+
+/** cleanClipPath
+ * Removes the related <clipPath> element from the <defs> group,
+ * and remove the 'clip-path' attribute from the animated element.
+ *
+ */
+AnimatedElement.prototype.cleanClipPath = function()
+{
+ this.aActiveElement.removeAttribute( 'clip-path' );
+
+ if( this.aClipPathElement )
+ {
+ var aClipPathGroup = theMetaDoc.aClipPathGroup;
+ aClipPathGroup.removeChild( this.aClipPathElement );
+ this.aClipPathElement = null;
+ this.aClipPathContent = null;
+ }
+};
+
+AnimatedElement.prototype.getId = function()
+{
+ return this.aActiveElement.getAttribute( 'id' );
+};
+
+AnimatedElement.prototype.getAdditiveMode = function()
+{
+ return this.eAdditiveMode;
+};
+
+AnimatedElement.prototype.setAdditiveMode = function( eAdditiveMode )
+{
+ this.eAdditiveMode = eAdditiveMode;
+};
+
+AnimatedElement.prototype.setToElement = function( aElement )
+{
+ if( !aElement )
+ {
+ log( 'AnimatedElement(' + this.getId() + ').setToElement: element is not valid' );
+ return false;
+ }
+
+ var aClone = aElement.cloneNode( true );
+ this.aPreviousElement = this.aActiveElement.parentNode.replaceChild( aClone, this.aActiveElement );
+ this.aActiveElement = aClone;
+
+ return true;
+};
+
+AnimatedElement.prototype.notifySlideStart = function( aSlideShowContext )
+{
+ if( !aSlideShowContext )
+ {
+ log( 'AnimatedElement.notifySlideStart: slideshow context is not valid' );
+ }
+ this.aSlideShowContext = aSlideShowContext;
+
+ var aClone = this.aBaseElement.cloneNode( true );
+ this.aActiveElement.parentNode.replaceChild( aClone, this.aActiveElement );
+ this.aActiveElement = aClone;
+
+ this.initElement();
+ this.DBG( '.notifySlideStart invoked' );
+};
+
+AnimatedElement.prototype.notifySlideEnd = function()
+{
+ // empty body
+};
+
+AnimatedElement.prototype.notifyAnimationStart = function()
+{
+ // empty body
+};
+
+AnimatedElement.prototype.notifyAnimationEnd = function()
+{
+ // empty body
+};
+
+AnimatedElement.prototype.notifyNextEffectStart = function( /*nEffectIndex*/ )
+{
+ // empty body
+};
+
+/** saveState
+ * Save the state of the managed animated element and append it to aStateSet
+ * using the passed animation node id as key.
+ *
+ * @param nAnimationNodeId
+ * A non negative integer representing the unique id of an animation node.
+ */
+AnimatedElement.prototype.saveState = function( nAnimationNodeId )
+{
+ ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').saveState(' + nAnimationNodeId +')' );
+ if( !this.aStateSet[ nAnimationNodeId ] )
+ {
+ this.aStateSet[ nAnimationNodeId ] = {};
+ }
+ var aState = this.aStateSet[ nAnimationNodeId ];
+ aState.aElement = this.aActiveElement.cloneNode( true );
+ aState.nCenterX = this.nCenterX;
+ aState.nCenterY = this.nCenterY;
+ aState.nScaleFactorX = this.nScaleFactorX;
+ aState.nScaleFactorY = this.nScaleFactorY;
+ aState.nRotationAngle = this.nRotationAngle;
+
+};
+
+/** restoreState
+ * Restore the state of the managed animated element to the state with key
+ * the passed animation node id.
+ *
+ * @param nAnimationNodeId
+ * A non negative integer representing the unique id of an animation node.
+ *
+ * @return
+ * True if the restoring operation is successful, false otherwise.
+ */
+AnimatedElement.prototype.restoreState = function( nAnimationNodeId )
+{
+ if( !this.aStateSet[ nAnimationNodeId ] )
+ {
+ log( 'AnimatedElement(' + this.getId() + ').restoreState: state '
+ +nAnimationNodeId + ' is not valid' );
+ return false;
+ }
+
+ ANIMDBG.print( 'AnimatedElement(' + this.getId() + ').restoreState(' + nAnimationNodeId +')' );
+ var aState = this.aStateSet[ nAnimationNodeId ];
+ var bRet = this.setToElement( aState.aElement );
+ if( bRet )
+ {
+ this.nCenterX = aState.nCenterX;
+ this.nCenterY = aState.nCenterY;
+ this.nScaleFactorX = aState.nScaleFactorX;
+ this.nScaleFactorY = aState.nScaleFactorY;
+ this.nRotationAngle = aState.nRotationAngle;
+ }
+ return bRet;
+};
+
+AnimatedElement.prototype.getBaseBBox = function()
+{
+ return this.aBaseBBox;
+};
+
+AnimatedElement.prototype.getBaseCenterX = function()
+{
+ return this.nBaseCenterX;
+};
+
+AnimatedElement.prototype.getBaseCenterY = function()
+{
+ return this.nBaseCenterY;
+};
+
+AnimatedElement.prototype.getBBox = function()
+{
+ return this.aActiveElement.parentNode.getBBox();
+};
+
+AnimatedElement.prototype.getBBoxWithStroke = function()
+{
+ var aBBox = this.aActiveElement.parentNode.getBBox();
+
+ var aChildrenSet = this.aActiveElement.childNodes;
+
+ var sStroke, sStrokeWidth;
+ var nStrokeWidth = 0;
+ var i;
+ for( i = 0; i < aChildrenSet.length; ++i )
+ {
+ if( ! aChildrenSet[i].getAttribute )
+ continue;
+
+ sStroke = aChildrenSet[i].getAttribute( 'stroke' );
+ if( sStroke && sStroke != 'none' )
+ {
+ sStrokeWidth = aChildrenSet[i].getAttribute( 'stroke-width' );
+ var nSW = parseFloat( sStrokeWidth );
+ if( nSW > nStrokeWidth )
+ nStrokeWidth = nSW;
+ }
+ }
+
+ if( nStrokeWidth == 0 )
+ {
+ sStrokeWidth = ROOT_NODE.getAttribute( 'stroke-width' );
+ nStrokeWidth = parseFloat( sStrokeWidth );
+ }
+ if( nStrokeWidth != 0 )
+ {
+ // It is hard to clip properly the stroke so we try to enlarge
+ // the resulting bounding box even more.
+ nStrokeWidth *= 1.1;
+ var nHalfStrokeWidth = nStrokeWidth / 2;
+ var nDoubleStrokeWidth = nStrokeWidth * 2;
+
+ // Note: IE10 don't let modify the values of an element BBox.
+ var aEBBox = document.documentElement.createSVGRect();
+ aEBBox.x = aBBox.x - nHalfStrokeWidth;
+ aEBBox.y = aBBox.y - nHalfStrokeWidth;
+ aEBBox.width = aBBox.width + nDoubleStrokeWidth;
+ aEBBox.height = aBBox.height + nDoubleStrokeWidth;
+ aBBox = aEBBox;
+ }
+ return aBBox;
+};
+
+/** setClipPath
+ * Replace the current content of the <clipPath> element with the one
+ * passed through the parameter.
+ *
+ * @param aClipPathContent
+ * A <g> element representing a <path> element used for clipping.
+ */
+AnimatedElement.prototype.setClipPath = function( aClipPathContent )
+{
+ if( this.aClipPathContent )
+ {
+ // We need to translate the clip path to the top left corner of
+ // the element bounding box.
+ var aTranslation = SVGIdentityMatrix.translate( this.aClippingBBox.x,
+ this.aClippingBBox.y);
+ aClipPathContent.matrixTransform( aTranslation );
+ var sPathData = aClipPathContent.getAttribute( 'd' );
+ this.aClipPathContent.setAttribute( 'd', sPathData );
+ }
+};
+
+
+AnimatedElement.prototype.getX = function()
+{
+ return this.nCenterX;
+};
+
+AnimatedElement.prototype.getY = function()
+{
+ return this.nCenterY;
+};
+
+AnimatedElement.prototype.getPos = function()
+{
+ return [this.getX(), this.getY()];
+};
+
+AnimatedElement.prototype.getWidth = function()
+{
+ return this.nScaleFactorX * this.getBaseBBox().width;
+};
+
+AnimatedElement.prototype.getHeight = function()
+{
+ return this.nScaleFactorY * this.getBaseBBox().height;
+};
+
+AnimatedElement.prototype.getSize = function()
+{
+ return [this.getWidth(), this.getHeight()];
+};
+
+AnimatedElement.prototype.updateTransformAttribute = function()
+{
+ this.aTransformAttrList = this.aActiveElement.transform.baseVal;
+ this.aTransformAttr = this.aTransformAttrList.getItem( 0 );
+ this.aTransformAttr.setMatrix( this.aTMatrix );
+};
+
+AnimatedElement.prototype.setX = function( nNewCenterX )
+{
+ if( nNewCenterX === this.nCenterX ) return;
+
+ this.aTransformAttrList = this.aActiveElement.transform.baseVal;
+ this.aTransformAttr = this.aTransformAttrList.getItem( 0 );
+ this.aTMatrix = this.aTransformAttr.matrix.translate( nNewCenterX - this.nCenterX, 0 );
+ this.aTransformAttr.setMatrix( this.aTMatrix );
+ this.nCenterX = nNewCenterX;
+};
+
+AnimatedElement.prototype.setY = function( nNewCenterY )
+{
+ if( nNewCenterY === this.nCenterY ) return;
+
+ this.aTransformAttrList = this.aActiveElement.transform.baseVal;
+ this.aTransformAttr = this.aTransformAttrList.getItem( 0 );
+ this.aTMatrix = this.aTransformAttr.matrix.translate( 0, nNewCenterY - this.nCenterY );
+ this.aTransformAttr.setMatrix( this.aTMatrix );
+ this.nCenterY = nNewCenterY;
+};
+
+AnimatedElement.prototype.setPos = function( aNewPos )
+{
+ var nNewCenterX = aNewPos[0];
+ var nNewCenterY = aNewPos[1];
+
+ if( nNewCenterX === this.nCenterX && nNewCenterY === this.nCenterY ) return;
+
+ this.aTransformAttrList = this.aActiveElement.transform.baseVal;
+ this.aTransformAttr = this.aTransformAttrList.getItem( 0 );
+ this.aTMatrix = this.aTransformAttr.matrix.translate( nNewCenterX - this.nCenterX, nNewCenterY - this.nCenterY );
+ this.aTransformAttr.setMatrix( this.aTMatrix );
+ this.nCenterX = nNewCenterX;
+ this.nCenterY = nNewCenterY;
+};
+
+AnimatedElement.prototype.setWidth = function( nNewWidth )
+{
+ ANIMDBG.print( 'AnimatedElement.setWidth: nNewWidth = ' + nNewWidth );
+ if( nNewWidth < 0 )
+ {
+ log('AnimatedElement(' + this.getId() + ').setWidth: negative width!');
+ nNewWidth = 0;
+ }
+
+ var nBaseWidth = this.getBaseBBox().width;
+ var nScaleFactorX = nNewWidth / nBaseWidth;
+
+ if( nScaleFactorX < 1e-5 ) nScaleFactorX = 1e-5;
+ if( nScaleFactorX == this.nScaleFactorX ) return;
+
+ this.aTMatrix = document.documentElement.createSVGMatrix()
+ .translate( this.nCenterX, this.nCenterY )
+ .rotate(this.nRotationAngle)
+ .scaleNonUniform( nScaleFactorX, this.nScaleFactorY )
+ .translate( -this.nBaseCenterX, -this.nBaseCenterY );
+ this.updateTransformAttribute();
+
+ this.nScaleFactorX = nScaleFactorX;
+};
+
+AnimatedElement.prototype.setHeight = function( nNewHeight )
+{
+ ANIMDBG.print( 'AnimatedElement.setWidth: nNewHeight = ' + nNewHeight );
+ if( nNewHeight < 0 )
+ {
+ log('AnimatedElement(' + this.getId() + ').setWidth: negative height!');
+ nNewHeight = 0;
+ }
+
+ var nBaseHeight = this.getBaseBBox().height;
+ var nScaleFactorY = nNewHeight / nBaseHeight;
+
+ if( nScaleFactorY < 1e-5 ) nScaleFactorY = 1e-5;
+ if( nScaleFactorY == this.nScaleFactorY ) return;
+
+ this.aTMatrix = document.documentElement.createSVGMatrix()
+ .translate( this.nCenterX, this.nCenterY )
+ .rotate(this.nRotationAngle)
+ .scaleNonUniform( this.nScaleFactorX, nScaleFactorY )
+ .translate( -this.nBaseCenterX, -this.nBaseCenterY );
+ this.updateTransformAttribute();
+
+ this.nScaleFactorY = nScaleFactorY;
+};
+
+AnimatedElement.prototype.setSize= function( aNewSize )
+{
+ var nNewWidth = aNewSize[0];
+ var nNewHeight = aNewSize[1];
+ ANIMDBG.print( 'AnimatedElement.setSize: = [' + nNewWidth + ',' + nNewHeight + ']');
+ if( nNewWidth < 0 )
+ {
+ log('AnimatedElement(' + this.getId() + ').setSize: negative width!');
+ nNewWidth = 0;
+ }
+ if( nNewHeight < 0 )
+ {
+ log('AnimatedElement(' + this.getId() + ').setSize: negative height!');
+ nNewHeight = 0;
+ }
+
+ var nBaseWidth = this.getBaseBBox().width;
+ var nScaleFactorX = nNewWidth / nBaseWidth;
+ if( nScaleFactorX < 1e-5 ) nScaleFactorX = 1e-5;
+
+ var nBaseHeight = this.getBaseBBox().height;
+ var nScaleFactorY = nNewHeight / nBaseHeight;
+ if( nScaleFactorY < 1e-5 ) nScaleFactorY = 1e-5;
+
+ if( nScaleFactorX == this.nScaleFactorX && nScaleFactorY == this.nScaleFactorY ) return;
+
+ this.aTMatrix = document.documentElement.createSVGMatrix()
+ .translate( this.nCenterX, this.nCenterY )
+ .rotate(this.nRotationAngle)
+ .scaleNonUniform( nScaleFactorX, nScaleFactorY )
+ .translate( -this.nBaseCenterX, -this.nBaseCenterY );
+ this.updateTransformAttribute();
+
+ this.nScaleFactorX = nScaleFactorX;
+ this.nScaleFactorY = nScaleFactorY;
+};
+
+AnimatedElement.prototype.getOpacity = function()
+{
+ return this.aActiveElement.getAttribute( 'opacity' );
+};
+
+AnimatedElement.prototype.setOpacity = function( nValue )
+{
+ this.aActiveElement.setAttribute( 'opacity', nValue );
+};
+
+AnimatedElement.prototype.getRotationAngle = function()
+{
+ return this.nRotationAngle;
+};
+
+AnimatedElement.prototype.setRotationAngle = function( nNewRotAngle )
+{
+ this.aTMatrix = document.documentElement.createSVGMatrix()
+ .translate( this.nCenterX, this.nCenterY )
+ .rotate(nNewRotAngle)
+ .scaleNonUniform( this.nScaleFactorX, this.nScaleFactorY )
+ .translate( -this.nBaseCenterX, -this.nBaseCenterY );
+ this.updateTransformAttribute();
+
+ this.nRotationAngle = nNewRotAngle;
+};
+
+AnimatedElement.prototype.getVisibility = function()
+{
+
+ var sVisibilityValue = this.aActiveElement.getAttribute( 'visibility' );
+ if( !sVisibilityValue || ( sVisibilityValue === 'inherit' ) )
+ return 'visible'; // TODO: look for parent visibility!
+ else
+ return sVisibilityValue;
+};
+
+AnimatedElement.prototype.setVisibility = function( sValue )
+{
+ if( sValue == 'visible' )
+ sValue = 'inherit';
+ this.aActiveElement.setAttribute( 'visibility', sValue );
+};
+
+AnimatedElement.prototype.getStrokeStyle = function()
+{
+ // TODO: getStrokeStyle: implement it
+ return 'solid';
+};
+
+AnimatedElement.prototype.setStrokeStyle = function( sValue )
+{
+ ANIMDBG.print( 'AnimatedElement.setStrokeStyle(' + sValue + ')' );
+};
+
+AnimatedElement.prototype.getFillStyle = function()
+{
+ // TODO: getFillStyle: implement it
+ return 'solid';
+};
+
+AnimatedElement.prototype.setFillStyle = function( sValue )
+{
+ ANIMDBG.print( 'AnimatedElement.setFillStyle(' + sValue + ')' );
+};
+
+AnimatedElement.prototype.getFillColor = function()
+{
+ var aChildSet = getElementChildren( this.aActiveElement );
+ var sFillColorValue = '';
+ for( var i = 0; i < aChildSet.length; ++i )
+ {
+ sFillColorValue = aChildSet[i].getAttribute( 'fill' );
+ if( sFillColorValue && ( sFillColorValue !== 'none' ) )
+ break;
+ }
+
+ return colorParser( sFillColorValue );
+};
+
+AnimatedElement.prototype.setFillColor = function( aRGBValue )
+{
+ assert( aRGBValue instanceof RGBColor,
+ 'AnimatedElement.setFillColor: value argument is not an instance of RGBColor' );
+
+ var sValue = aRGBValue.toString( true /* clamped values */ );
+ var aChildSet = getElementChildren( this.aActiveElement );
+
+ var sFillColorValue = '';
+ for( var i = 0; i < aChildSet.length; ++i )
+ {
+ sFillColorValue = aChildSet[i].getAttribute( 'fill' );
+ if( sFillColorValue && ( sFillColorValue !== 'none' ) )
+ {
+ aChildSet[i].setAttribute( 'fill', sValue );
+ }
+ }
+};
+
+AnimatedElement.prototype.getStrokeColor = function()
+{
+ var aChildSet = getElementChildren( this.aActiveElement );
+ var sStrokeColorValue = '';
+ for( var i = 0; i < aChildSet.length; ++i )
+ {
+ sStrokeColorValue = aChildSet[i].getAttribute( 'stroke' );
+ if( sStrokeColorValue && ( sStrokeColorValue !== 'none' ) )
+ break;
+ }
+
+ return colorParser( sStrokeColorValue );
+};
+
+AnimatedElement.prototype.setStrokeColor = function( aRGBValue )
+{
+ assert( aRGBValue instanceof RGBColor,
+ 'AnimatedElement.setFillColor: value argument is not an instance of RGBColor' );
+
+ var sValue = aRGBValue.toString( true /* clamped values */ );
+ var aChildSet = getElementChildren( this.aActiveElement );
+
+ var sStrokeColorValue = '';
+ for( var i = 0; i < aChildSet.length; ++i )
+ {
+ sStrokeColorValue = aChildSet[i].getAttribute( 'stroke' );
+ if( sStrokeColorValue && ( sStrokeColorValue !== 'none' ) )
+ {
+ aChildSet[i].setAttribute( 'stroke', sValue );
+ }
+ }
+};
+
+AnimatedElement.prototype.getFontColor = function()
+{
+ // TODO: getFontColor implement it
+ return new RGBColor( 0, 0, 0 );
+};
+
+AnimatedElement.prototype.setFontColor = function( sValue )
+{
+ ANIMDBG.print( 'AnimatedElement.setFontColor(' + sValue + ')' );
+};
+
+AnimatedElement.prototype.DBG = function( sMessage, nTime )
+{
+ aAnimatedElementDebugPrinter.print( 'AnimatedElement(' + this.getId() + ')' + sMessage, nTime );
+};
+
+
+function AnimatedTextElement( aElement, aEventMultiplexer )
+{
+ var theDocument = document;
+
+ var sTextType = aElement.getAttribute( 'class' );
+ var bIsListItem = ( sTextType === 'ListItem' );
+ if( ( sTextType !== 'TextParagraph' ) && !bIsListItem )
+ {
+ log( 'AnimatedTextElement: passed element is not a paragraph.' );
+ return;
+ }
+ var aTextShapeElement = aElement.parentNode;
+ sTextType = aTextShapeElement.getAttribute( 'class' );
+ if( sTextType !== 'SVGTextShape' )
+ {
+ log( 'AnimatedTextElement: element parent is not a text shape.' );
+ return;
+ }
+ var aTextShapeGroup = aTextShapeElement.parentNode;
+ // We search for the helper group element used for inserting
+ // the element copy to be animated; if it doesn't exist we create it.
+ var aAnimatedElementGroup = getElementByClassName( aTextShapeGroup, 'AnimatedElements' );
+ if( !aAnimatedElementGroup )
+ {
+ aAnimatedElementGroup = theDocument.createElementNS( NSS['svg'], 'g' );
+ aAnimatedElementGroup.setAttribute( 'class', 'AnimatedElements' );
+ aTextShapeGroup.appendChild( aAnimatedElementGroup );
+ }
+
+ // Create element used on animating
+ var aAnimatableElement = theDocument.createElementNS( NSS['svg'], 'g' );
+ var aTextElement = theDocument.createElementNS( NSS['svg'], 'text' );
+ // Clone paragraph element <tspan>
+ var aParagraphElement = aElement.cloneNode( true );
+
+ // We create a group element for wrapping bullets, bitmaps
+ // and text decoration
+ this.aGraphicGroupElement = theDocument.createElementNS( NSS['svg'], 'g' );
+ this.aGraphicGroupElement.setAttribute( 'class', 'GraphicGroup' );
+
+ // In case we are dealing with a list item that utilizes a bullet char
+ // we need to clone the related bullet char too.
+ var aBulletCharClone = null;
+ var aBulletCharElem = null;
+ var bIsBulletCharStyle =
+ ( aElement.getAttributeNS( NSS['ooo'], aOOOAttrListItemNumberingType ) === 'bullet-style' );
+ if( bIsBulletCharStyle )
+ {
+ var aBulletCharGroupElem = getElementByClassName( aTextShapeGroup, 'BulletChars' );
+ if( aBulletCharGroupElem )
+ {
+ var aBulletPlaceholderElem = getElementByClassName( aElement, 'BulletPlaceholder' );
+ if( aBulletPlaceholderElem )
+ {
+ var sId = aBulletPlaceholderElem.getAttribute( 'id' );
+ sId = 'bullet-char(' + sId + ')';
+ aBulletCharElem = theDocument.getElementById( sId );
+ if( aBulletCharElem )
+ {
+ aBulletCharClone = aBulletCharElem.cloneNode( true );
+ }
+ else
+ {
+ log( 'AnimatedTextElement: ' + sId + ' not found.' );
+ }
+ }
+ else
+ {
+ log( 'AnimatedTextElement: no bullet placeholder found' );
+ }
+ }
+ else
+ {
+ log( 'AnimatedTextElement: no bullet char group found' );
+ }
+ }
+
+ // In case there are embedded bitmaps we need to clone them
+ var aBitmapElemSet = [];
+ var aBitmapCloneSet = [];
+ var aBitmapPlaceholderSet = getElementsByClassName( aElement, 'BitmapPlaceholder' );
+ var i;
+ if( aBitmapPlaceholderSet )
+ {
+ for( i = 0; i < aBitmapPlaceholderSet.length; ++i )
+ {
+ sId = aBitmapPlaceholderSet[i].getAttribute( 'id' );
+ var sBitmapChecksum = sId.substring( 'bitmap-placeholder'.length + 1, sId.length - 1 );
+ sId = 'embedded-bitmap(' + sBitmapChecksum + ')';
+ aBitmapElemSet[i] = theDocument.getElementById( sId );
+ if( aBitmapElemSet[i] )
+ {
+ aBitmapCloneSet[i] = aBitmapElemSet[i].cloneNode( true );
+ }
+ else
+ {
+ log( 'AnimatedTextElement: ' + sId + ' not found.' );
+ }
+ }
+ }
+
+
+ // Change clone element id.
+ this.sParagraphId = sId = aParagraphElement.getAttribute( 'id' );
+ aParagraphElement.removeAttribute( 'id' );
+ aAnimatableElement.setAttribute( 'id', sId +'.a' );
+ if( aBulletCharClone )
+ aBulletCharClone.removeAttribute( 'id' );
+ for( i = 0; i < aBitmapCloneSet.length; ++i )
+ {
+ if( aBitmapCloneSet[i] )
+ aBitmapCloneSet[i].removeAttribute( 'id' );
+ }
+
+ // Set up visibility
+ var sVisibilityAttr = aElement.getAttribute( 'visibility' );
+ if( !sVisibilityAttr )
+ sVisibilityAttr = 'inherit';
+ aAnimatableElement.setAttribute( 'visibility', sVisibilityAttr );
+ aParagraphElement.setAttribute( 'visibility', 'inherit' );
+ this.aGraphicGroupElement.setAttribute( 'visibility', 'inherit' );
+ if( aBulletCharElem )
+ aBulletCharElem.setAttribute( 'visibility', 'hidden' );
+ for( i = 0; i < aBitmapCloneSet.length; ++i )
+ {
+ if( aBitmapElemSet[i] )
+ aBitmapElemSet[i].setAttribute( 'visibility', 'hidden' );
+ }
+
+ // Append each element to its parent.
+ // <g class='AnimatedElements'>
+ // <g>
+ // <text>
+ // <tspan class='TextParagraph'> ... </tspan>
+ // </text>
+ // <g class='GraphicGroup'>
+ // [<g class='BulletChar'>...</g>]
+ // [<g class='EmbeddedBitmap'>...</g>]
+ // .
+ // .
+ // [<g class='EmbeddedBitmap'>...</g>]
+ // </g>
+ // </g>
+ // </g>
+
+ aTextElement.appendChild( aParagraphElement );
+ aAnimatableElement.appendChild( aTextElement );
+
+ if( aBulletCharClone )
+ this.aGraphicGroupElement.appendChild( aBulletCharClone );
+ for( i = 0; i < aBitmapCloneSet.length; ++i )
+ {
+ if( aBitmapCloneSet[i] )
+ this.aGraphicGroupElement.appendChild( aBitmapCloneSet[i] );
+ }
+ aAnimatableElement.appendChild( this.aGraphicGroupElement );
+ aAnimatedElementGroup.appendChild( aAnimatableElement );
+
+ this.aParentTextElement = aElement.parentNode;
+ this.aParagraphElement = aElement;
+ this.aAnimatedElementGroup = aAnimatedElementGroup;
+ this.nRunningAnimations = 0;
+
+ // we collect all hyperlink ids
+ this.aHyperlinkIdSet = [];
+ var aHyperlinkElementSet = getElementsByClassName( this.aParagraphElement, 'UrlField' );
+ var sHyperlinkId;
+ for( i = 0; i < aHyperlinkElementSet.length; ++i )
+ {
+ sHyperlinkId = aHyperlinkElementSet[i].getAttribute( 'id' );
+ if( sHyperlinkId )
+ this.aHyperlinkIdSet.push( sHyperlinkId );
+ else
+ log( 'error: AnimatedTextElement constructor: hyperlink element has no id' );
+ }
+
+ AnimatedTextElement.superclass.constructor.call( this, aAnimatableElement, aEventMultiplexer );
+
+}
+extend( AnimatedTextElement, AnimatedElement );
+
+
+AnimatedTextElement.prototype.setToElement = function( aElement )
+{
+ var bRet = AnimatedTextElement.superclass.setToElement.call( this, aElement );
+ if( bRet )
+ {
+ this.aGraphicGroupElement = getElementByClassName( this.aActiveElement, 'GraphicGroup' );
+ }
+ return ( bRet && this.aGraphicGroupElement );
+};
+
+AnimatedTextElement.prototype.notifySlideStart = function( aSlideShowContext )
+{
+ DBGLOG( 'AnimatedTextElement.notifySlideStart' );
+ AnimatedTextElement.superclass.notifySlideStart.call( this, aSlideShowContext );
+ this.aGraphicGroupElement = getElementByClassName( this.aActiveElement, 'GraphicGroup' );
+ this.restoreBaseTextParagraph();
+};
+
+AnimatedTextElement.prototype.notifySlideEnd = function()
+{
+ DBGLOG( 'AnimatedTextElement.notifySlideEnd' );
+ this.aGraphicGroupElement.setAttribute( 'visibility', 'inherit' );
+};
+
+AnimatedTextElement.prototype.restoreBaseTextParagraph = function()
+{
+ var aActiveParagraphElement = this.aActiveElement.firstElementChild.firstElementChild;
+ if( aActiveParagraphElement )
+ {
+ var sVisibilityAttr = this.aActiveElement.getAttribute( 'visibility' );
+ if( !sVisibilityAttr || ( sVisibilityAttr === 'visible' ) )
+ sVisibilityAttr = 'inherit';
+ if( sVisibilityAttr === 'inherit' )
+ this.aGraphicGroupElement.setAttribute( 'visibility', 'visible' );
+ else
+ this.aGraphicGroupElement.setAttribute( 'visibility', 'hidden' );
+
+ var aParagraphClone = aActiveParagraphElement.cloneNode( true );
+ aParagraphClone.setAttribute( 'id', this.sParagraphId );
+ aParagraphClone.setAttribute( 'visibility', sVisibilityAttr );
+ this.aParentTextElement.replaceChild( aParagraphClone, this.aParagraphElement );
+ this.aParagraphElement = aParagraphClone;
+
+
+ var aEventMultiplexer = this.aSlideShowContext.aEventMultiplexer;
+ var aHyperlinkIdSet = this.aHyperlinkIdSet;
+ var aHyperlinkElementSet = getElementsByClassName( this.aParagraphElement, 'UrlField' );
+ var i = 0;
+ for( ; i < aHyperlinkIdSet.length; ++i )
+ {
+ aEventMultiplexer.notifyElementChangedEvent( aHyperlinkIdSet[i], aHyperlinkElementSet[i] );
+ }
+ }
+ this.aActiveElement.setAttribute( 'visibility', 'hidden' );
+};
+
+AnimatedTextElement.prototype.notifyAnimationStart = function()
+{
+ DBGLOG( 'AnimatedTextElement.notifyAnimationStart' );
+ if( this.nRunningAnimations === 0 )
+ {
+ var sVisibilityAttr = this.aParagraphElement.getAttribute( 'visibility' );
+ if( !sVisibilityAttr )
+ sVisibilityAttr = 'inherit';
+ this.aActiveElement.setAttribute( 'visibility', sVisibilityAttr );
+ this.aGraphicGroupElement.setAttribute( 'visibility', 'inherit' );
+ this.aParagraphElement.setAttribute( 'visibility', 'hidden' );
+ }
+ ++this.nRunningAnimations;
+};
+
+AnimatedTextElement.prototype.notifyAnimationEnd = function()
+{
+ DBGLOG( 'AnimatedTextElement.notifyAnimationEnd' );
+ --this.nRunningAnimations;
+ if( this.nRunningAnimations === 0 )
+ {
+ this.restoreBaseTextParagraph();
+ }
+};
+
+AnimatedTextElement.prototype.saveState = function( nAnimationNodeId )
+{
+ if( this.nRunningAnimations === 0 )
+ {
+ var sVisibilityAttr = this.aParagraphElement.getAttribute( 'visibility' );
+ this.aActiveElement.setAttribute( 'visibility', sVisibilityAttr );
+ this.aGraphicGroupElement.setAttribute( 'visibility', 'inherit' );
+ }
+ AnimatedTextElement.superclass.saveState.call( this, nAnimationNodeId );
+};
+
+AnimatedTextElement.prototype.restoreState = function( nAnimationNodeId )
+{
+ var bRet = AnimatedTextElement.superclass.restoreState.call( this, nAnimationNodeId );
+ if( bRet )
+ this.restoreBaseTextParagraph();
+ return bRet;
+};
+
+
+
+
+/** Class SlideTransition
+ * This class is responsible for initializing the properties of a slide
+ * transition and create the object that actually will perform the transition.
+ *
+ * @param aAnimationsRootElement
+ * The <defs> element wrapping all animations for the related slide.
+ * @param aSlideId
+ * A string representing a slide id.
+ */
+function SlideTransition( aAnimationsRootElement, aSlideId )
+{
+ this.sSlideId = aSlideId;
+ this.bIsValid = false;
+ this.eTransitionType = undefined;
+ this.eTransitionSubType = undefined;
+ this.bReverseDirection = false;
+ this.eTransitionMode = TRANSITION_MODE_IN;
+ this.sFadeColor = null;
+ this.aDuration = null;
+ this.nMinFrameCount = undefined;
+
+ if( aAnimationsRootElement )
+ {
+ if( aAnimationsRootElement.firstElementChild &&
+ ( aAnimationsRootElement.firstElementChild.getAttributeNS( NSS['smil'], 'begin' ) === (this.sSlideId + '.begin') ) )
+ {
+ var aTransitionFilterElement = aAnimationsRootElement.firstElementChild.firstElementChild;
+ if( aTransitionFilterElement && ( aTransitionFilterElement.localName === 'transitionFilter' ) )
+ {
+ this.aElement = aTransitionFilterElement;
+ this.parseElement();
+ }
+ aAnimationsRootElement.removeChild( aAnimationsRootElement.firstElementChild );
+ }
+ }
+}
+
+SlideTransition.prototype.createSlideTransition = function( aLeavingSlide, aEnteringSlide )
+{
+ if( !this.isValid() )
+ return null;
+ if( this.eTransitionType == 0 )
+ return null;
+
+ if( !aEnteringSlide )
+ {
+ log( 'SlideTransition.createSlideTransition: invalid entering slide.' );
+ return null;
+ }
+
+ var aTransitionInfo = aTransitionInfoTable[this.eTransitionType][this.eTransitionSubType];
+ var eTransitionClass = aTransitionInfo['class'];
+
+ switch( eTransitionClass )
+ {
+ default:
+ case TRANSITION_INVALID:
+ log( 'SlideTransition.createSlideTransition: transition class: TRANSITION_INVALID' );
+ return null;
+
+ case TRANSITION_CLIP_POLYPOLYGON:
+ var aParametricPolyPolygon
+ = createClipPolyPolygon( this.eTransitionType, this.eTransitionSubType );
+ return new ClippedSlideChange( aLeavingSlide, aEnteringSlide, aParametricPolyPolygon,
+ aTransitionInfo, this.isDirectionForward() );
+
+ case TRANSITION_SPECIAL:
+ switch( this.eTransitionType )
+ {
+ default:
+ log( 'SlideTransition.createSlideTransition: ' +
+ 'transition class: TRANSITION_SPECIAL, ' +
+ 'unknown transition type: ' + this.eTransitionType );
+ return null;
+
+ case PUSHWIPE_TRANSITION:
+ {
+ var aDirection = null;
+ switch( this.eTransitionSubType )
+ {
+ default:
+ log( 'SlideTransition.createSlideTransition: ' +
+ 'transition type: PUSHWIPE_TRANSITION, ' +
+ 'unknown transition subtype: ' + this.eTransitionSubType );
+ return null;
+ case FROMTOP_TRANS_SUBTYPE:
+ aDirection = { x: 0.0, y: 1.0 };
+ break;
+ case FROMBOTTOM_TRANS_SUBTYPE:
+ aDirection = { x: 0.0, y: -1.0 };
+ break;
+ case FROMLEFT_TRANS_SUBTYPE:
+ aDirection = { x: 1.0, y: 0.0 };
+ break;
+ case FROMRIGHT_TRANS_SUBTYPE:
+ aDirection = { x: -1.0, y: 0.0 };
+ break;
+ }
+ return new MovingSlideChange( aLeavingSlide, aEnteringSlide, aDirection, aDirection );
+ }
+
+ case SLIDEWIPE_TRANSITION:
+ {
+ var aInDirection = null;
+ switch( this.eTransitionSubType )
+ {
+ default:
+ log( 'SlideTransition.createSlideTransition: ' +
+ 'transition type: SLIDEWIPE_TRANSITION, ' +
+ 'unknown transition subtype: ' + this.eTransitionSubType );
+ return null;
+ case FROMTOP_TRANS_SUBTYPE:
+ aInDirection = { x: 0.0, y: 1.0 };
+ break;
+ case FROMBOTTOM_TRANS_SUBTYPE:
+ aInDirection = { x: 0.0, y: -1.0 };
+ break;
+ case FROMLEFT_TRANS_SUBTYPE:
+ aInDirection = { x: 1.0, y: 0.0 };
+ break;
+ case FROMRIGHT_TRANS_SUBTYPE:
+ aInDirection = { x: -1.0, y: 0.0 };
+ break;
+ }
+ var aNoDirection = { x: 0.0, y: 0.0 };
+ if( !this.bReverseDirection )
+ {
+ return new MovingSlideChange( aLeavingSlide, aEnteringSlide, aNoDirection, aInDirection );
+ }
+ else
+ {
+ return new MovingSlideChange( aLeavingSlide, aEnteringSlide, aInDirection, aNoDirection );
+ }
+ }
+
+ case FADE_TRANSITION:
+ switch( this.eTransitionSubType )
+ {
+ default:
+ log( 'SlideTransition.createSlideTransition: ' +
+ 'transition type: FADE_TRANSITION, ' +
+ 'unknown transition subtype: ' + this.eTransitionSubType );
+ return null;
+ case CROSSFADE_TRANS_SUBTYPE:
+ return new FadingSlideChange( aLeavingSlide, aEnteringSlide );
+ case FADEOVERCOLOR_TRANS_SUBTYPE:
+ return new FadingOverColorSlideChange( aLeavingSlide, aEnteringSlide, this.getFadeColor() );
+ }
+ }
+ }
+};
+
+SlideTransition.prototype.parseElement = function()
+{
+ this.bIsValid = true;
+ var aAnimElem = this.aElement;
+
+ // type attribute
+ this.eTransitionType = undefined;
+ var sTypeAttr = aAnimElem.getAttributeNS( NSS['smil'], 'type' );
+ if( sTypeAttr && aTransitionTypeInMap[ sTypeAttr ] )
+ {
+ this.eTransitionType = aTransitionTypeInMap[ sTypeAttr ];
+ }
+ else
+ {
+ this.bIsValid = false;
+ log( 'SlideTransition.parseElement: transition type not valid: ' + sTypeAttr );
+ }
+
+ // subtype attribute
+ this.eTransitionSubType = undefined;
+ var sSubTypeAttr = aAnimElem.getAttributeNS( NSS['smil'], 'subtype' );
+ if( sSubTypeAttr === null )
+ sSubTypeAttr = 'default';
+ if( sSubTypeAttr && ( aTransitionSubtypeInMap[ sSubTypeAttr ] !== undefined ) )
+ {
+ this.eTransitionSubType = aTransitionSubtypeInMap[ sSubTypeAttr ];
+ }
+ else
+ {
+ this.bIsValid = false;
+ log( 'SlideTransition.parseElement: transition subtype not valid: ' + sSubTypeAttr );
+ }
+
+ if( this.bIsValid && aTransitionInfoTable[this.eTransitionType][this.eTransitionSubType] === undefined )
+ {
+ this.bIsValid = false;
+ log( 'SlideTransition.parseElement: transition not valid: type: ' + sTypeAttr + ' subtype: ' + sSubTypeAttr );
+ }
+
+ // direction attribute
+ this.bReverseDirection = false;
+ var sDirectionAttr = aAnimElem.getAttributeNS( NSS['smil'], 'direction' );
+ if( sDirectionAttr == 'reverse' )
+ this.bReverseDirection = true;
+
+ // fade color
+ this.sFadeColor = null;
+ if( this.eTransitionType == FADE_TRANSITION &&
+ ( this.eTransitionSubType == FADEFROMCOLOR_TRANS_SUBTYPE ||
+ this.eTransitionSubType == FADEOVERCOLOR_TRANS_SUBTYPE ||
+ this.eTransitionSubType == FADETOCOLOR_TRANS_SUBTYPE ) )
+ {
+ var sColorAttr = aAnimElem.getAttributeNS( NSS['smil'], 'fadeColor' );
+ if( sColorAttr )
+ this.sFadeColor = sColorAttr;
+ else
+ this.sFadeColor='#000000';
+ }
+
+
+ // dur attribute
+ this.aDuration = null;
+ var sDurAttr = aAnimElem.getAttributeNS( NSS['smil'], 'dur' );
+ this.aDuration = new Duration( sDurAttr );
+ if( !this.aDuration.isSet() )
+ {
+ this.aDuration = new Duration( null ); // duration == 0.0
+ }
+
+ // set up min frame count value;
+ this.nMinFrameCount = ( this.getDuration().isValue() )
+ ? ( this.getDuration().getValue() * MINIMUM_FRAMES_PER_SECONDS )
+ : MINIMUM_FRAMES_PER_SECONDS;
+ if( this.nMinFrameCount < 1.0 )
+ this.nMinFrameCount = 1;
+ else if( this.nMinFrameCount > MINIMUM_FRAMES_PER_SECONDS )
+ this.nMinFrameCount = MINIMUM_FRAMES_PER_SECONDS;
+
+};
+
+SlideTransition.prototype.isValid = function()
+{
+ return this.bIsValid;
+};
+
+SlideTransition.prototype.getTransitionType = function()
+{
+ return this.eTransitionType;
+};
+
+SlideTransition.prototype.getTransitionSubType = function()
+{
+ return this.eTransitionSubType;
+};
+
+SlideTransition.prototype.getTransitionMode = function()
+{
+ return this.eTransitionMode;
+};
+
+SlideTransition.prototype.getFadeColor = function()
+{
+ return this.sFadeColor;
+};
+
+SlideTransition.prototype.isDirectionForward = function()
+{
+ return !this.bReverseDirection;
+};
+
+SlideTransition.prototype.getDuration = function()
+{
+ return this.aDuration;
+};
+
+SlideTransition.prototype.getMinFrameCount = function()
+{
+ return this.nMinFrameCount;
+};
+
+SlideTransition.prototype.info = function()
+{
+
+ var sInfo ='slide transition <' + this.sSlideId + '>: ';
+ // transition type
+ sInfo += '; type: ' + getKeyByValue(aTransitionTypeInMap, this.getTransitionType());
+
+ // transition subtype
+ sInfo += '; subtype: ' + getKeyByValue(aTransitionSubtypeInMap, this.getTransitionSubType());
+
+ // transition direction
+ if( !this.isDirectionForward() )
+ sInfo += '; direction: reverse';
+
+ // transition mode
+ sInfo += '; mode: ' + aTransitionModeOutMap[ this.getTransitionMode() ];
+
+ // duration
+ if( this.getDuration() )
+ sInfo += '; duration: ' + this.getDuration().info();
+
+ return sInfo;
+};
+
+
+
+
+// SlideAnimations
+
+function SlideAnimations( aSlideShowContext )
+{
+ this.aContext = new NodeContext( aSlideShowContext );
+ this.aAnimationNodeMap = {};
+ this.aAnimatedElementMap = {};
+ this.aSourceEventElementMap = {};
+ this.aNextEffectEventArray = new NextEffectEventArray();
+ this.aInteractiveAnimationSequenceMap = {};
+ this.aEventMultiplexer = new EventMultiplexer( aSlideShowContext.aTimerEventQueue );
+ this.aRootNode = null;
+ this.bElementsParsed = false;
+
+ this.aContext.aAnimationNodeMap = this.aAnimationNodeMap;
+ this.aContext.aAnimatedElementMap = this.aAnimatedElementMap;
+ this.aContext.aSourceEventElementMap = this.aSourceEventElementMap;
+
+ // We set up a low priority for the invocation of document.handleClick
+ // in order to make clicks on shapes, that start interactive animation
+ // sequence (on click), have an higher priority.
+ this.aEventMultiplexer.registerMouseClickHandler( document, 100 );
+}
+
+
+SlideAnimations.prototype.importAnimations = function( aAnimationRootElement )
+{
+ if( !aAnimationRootElement )
+ return false;
+
+ this.aRootNode = createAnimationTree( aAnimationRootElement, this.aContext );
+
+ return ( this.aRootNode ? true : false );
+};
+
+SlideAnimations.prototype.parseElements = function()
+{
+ if( !this.aRootNode )
+ return false;
+
+ // parse all nodes
+ if( !this.aRootNode.parseElement() )
+ return false;
+ else
+ this.bElementsParsed = true;
+};
+
+SlideAnimations.prototype.elementsParsed = function()
+{
+ return this.bElementsParsed;
+};
+
+SlideAnimations.prototype.isFirstRun = function()
+{
+ return this.aContext.bFirstRun;
+};
+
+SlideAnimations.prototype.isAnimated = function()
+{
+ if( !this.bElementsParsed )
+ return false;
+
+ return this.aRootNode.hasPendingAnimation();
+};
+
+SlideAnimations.prototype.start = function()
+{
+ if( !this.bElementsParsed )
+ return false;
+
+ this.chargeSourceEvents();
+ this.chargeInterAnimEvents();
+
+ aSlideShow.setSlideEvents( this.aNextEffectEventArray,
+ this.aInteractiveAnimationSequenceMap,
+ this.aEventMultiplexer );
+
+ if( this.aContext.bFirstRun == undefined )
+ this.aContext.bFirstRun = true;
+ else if( this.aContext.bFirstRun )
+ this.aContext.bFirstRun = false;
+
+ // init all nodes
+ this.aContext.bIsInvalid = !this.aRootNode.init();
+ if( this.aContext.bIsInvalid )
+ return false;
+
+ // resolve root node
+ return this.aRootNode.resolve();
+};
+
+SlideAnimations.prototype.end = function( bLeftEffectsSkipped )
+{
+ if( !this.bElementsParsed )
+ return; // no animations there
+
+ // end root node
+ this.aRootNode.deactivate();
+ this.aRootNode.end();
+
+ if( bLeftEffectsSkipped && this.isFirstRun() )
+ {
+ // in case this is the first run and left events have been skipped
+ // some next effect events for the slide could not be collected
+ // so the next time we should behave as it was the first run again
+ this.aContext.bFirstRun = undefined;
+ }
+ else if( this.isFirstRun() )
+ {
+ this.aContext.bFirstRun = false;
+ }
+
+ this.aContext.bIsInvalid = false;
+};
+
+SlideAnimations.prototype.dispose = function()
+{
+ if( this.aRootNode )
+ {
+ this.aRootNode.dispose();
+ }
+};
+
+SlideAnimations.prototype.clearNextEffectEvents = function()
+{
+ ANIMDBG.print( 'SlideAnimations.clearNextEffectEvents: current slide: ' + nCurSlide );
+ this.aNextEffectEventArray.clear();
+ this.aContext.bFirstRun = undefined;
+};
+
+SlideAnimations.prototype.chargeSourceEvents = function()
+{
+ for( var id in this.aSourceEventElementMap )
+ {
+ this.aSourceEventElementMap[id].charge();
+ }
+};
+
+SlideAnimations.prototype.chargeInterAnimEvents = function()
+{
+ for( var id in this.aInteractiveAnimationSequenceMap )
+ {
+ this.aInteractiveAnimationSequenceMap[id].chargeEvents();
+ }
+};
+
+/**********************************************************************************************
+ * Event classes and helper functions
+ **********************************************************************************************/
+
+
+function Event()
+{
+ this.nId = Event.getUniqueId();
+}
+
+
+Event.CURR_UNIQUE_ID = 0;
+
+Event.getUniqueId = function()
+{
+ ++Event.CURR_UNIQUE_ID;
+ return Event.CURR_UNIQUE_ID;
+};
+
+Event.prototype.getId = function()
+{
+ return this.nId;
+};
+
+
+
+function DelayEvent( aFunctor, nTimeout )
+{
+ DelayEvent.superclass.constructor.call( this );
+
+ this.aFunctor = aFunctor;
+ this.nTimeout = nTimeout;
+ this.bWasFired = false;
+}
+extend( DelayEvent, Event );
+
+
+DelayEvent.prototype.fire = function()
+{
+ assert( this.isCharged(), 'DelayEvent.fire: assertion isCharged failed' );
+
+ this.bWasFired = true;
+ this.aFunctor();
+ return true;
+};
+
+DelayEvent.prototype.isCharged = function()
+{
+ return !this.bWasFired;
+};
+
+DelayEvent.prototype.getActivationTime = function( nCurrentTime )
+{
+ return ( this.nTimeout + nCurrentTime );
+};
+
+DelayEvent.prototype.dispose = function()
+{
+ // don't clear unconditionally, because it may currently be executed:
+ if( this.isCharged() )
+ this.bWasFired = true;
+};
+
+DelayEvent.prototype.charge = function()
+{
+ if( !this.isCharged() )
+ this.bWasFired = false;
+};
+
+
+
+function WakeupEvent( aTimer, aActivityQueue )
+{
+ WakeupEvent.superclass.constructor.call( this );
+
+ this.aTimer = new ElapsedTime( aTimer );
+ this.nNextTime = 0.0;
+ this.aActivity = null;
+ this.aActivityQueue = aActivityQueue;
+}
+extend( WakeupEvent, Event );
+
+
+WakeupEvent.prototype.clone = function()
+{
+ var aWakeupEvent = new WakeupEvent( this.aTimer.getTimeBase(), this.aActivityQueue );
+ aWakeupEvent.nNextTime = this.nNextTime;
+ aWakeupEvent.aActivity = this.aActivity;
+ return aWakeupEvent;
+};
+
+WakeupEvent.prototype.dispose = function()
+{
+ this.aActivity = null;
+};
+
+WakeupEvent.prototype.fire = function()
+{
+ if( !this.aActivity )
+ return false;
+
+ return this.aActivityQueue.addActivity( this.aActivity );
+};
+
+WakeupEvent.prototype.isCharged = function()
+{
+ // this event won't expire, we fire every time we're
+ // re-inserted into the event queue.
+ return true;
+};
+
+WakeupEvent.prototype.getActivationTime = function( nCurrentTime )
+{
+ var nElapsedTime = this.aTimer.getElapsedTime();
+
+ return Math.max( nCurrentTime, nCurrentTime - nElapsedTime + this.nNextTime );
+};
+
+WakeupEvent.prototype.start = function()
+{
+ this.aTimer.reset();
+};
+
+WakeupEvent.prototype.setNextTimeout = function( nNextTime )
+{
+ this.nNextTime = nNextTime;
+};
+
+WakeupEvent.prototype.setActivity = function( aActivity )
+{
+ this.aActivity = aActivity;
+};
+
+
+
+function makeEvent( aFunctor )
+{
+ return new DelayEvent( aFunctor, 0.0 );
+}
+
+
+
+
+function makeDelay( aFunctor, nTimeout )
+{
+ return new DelayEvent( aFunctor, nTimeout );
+}
+
+
+
+
+function registerEvent( nNodeId, aTiming, aEvent, aNodeContext )
+{
+ var aSlideShowContext = aNodeContext.aContext;
+ var eTimingType = aTiming.getType();
+
+ registerEvent.DBG( aTiming );
+
+ if( eTimingType == OFFSET_TIMING )
+ {
+ aSlideShowContext.aTimerEventQueue.addEvent( aEvent );
+ }
+ else if ( aNodeContext.bFirstRun )
+ {
+ var aEventMultiplexer = aSlideShowContext.aEventMultiplexer;
+ if( !aEventMultiplexer )
+ {
+ log( 'registerEvent: event multiplexer not initialized' );
+ return;
+ }
+ var aNextEffectEventArray = aSlideShowContext.aNextEffectEventArray;
+ if( !aNextEffectEventArray )
+ {
+ log( 'registerEvent: next effect event array not initialized' );
+ return;
+ }
+ var aInteractiveAnimationSequenceMap =
+ aSlideShowContext.aInteractiveAnimationSequenceMap;
+ if( !aInteractiveAnimationSequenceMap )
+ {
+ log( 'registerEvent: interactive animation sequence map not initialized' );
+ return;
+ }
+
+ switch( eTimingType )
+ {
+ case EVENT_TIMING:
+ var eEventType = aTiming.getEventType();
+ var sEventBaseElemId = aTiming.getEventBaseElementId();
+ if( sEventBaseElemId )
+ {
+ var aEventBaseElem = document.getElementById( sEventBaseElemId );
+ if( !aEventBaseElem )
+ {
+ log( 'generateEvent: EVENT_TIMING: event base element not found: ' + sEventBaseElemId );
+ return;
+ }
+ var aSourceEventElement = aNodeContext.makeSourceEventElement( sEventBaseElemId, aEventBaseElem );
+
+ if( !aInteractiveAnimationSequenceMap[ nNodeId ] )
+ {
+ aInteractiveAnimationSequenceMap[ nNodeId ] = new InteractiveAnimationSequence(nNodeId);
+ }
+
+ var bEventRegistered = false;
+ switch( eEventType )
+ {
+ case EVENT_TRIGGER_ON_CLICK:
+ aEventMultiplexer.registerEvent( eEventType, aSourceEventElement.getId(), aEvent );
+ aEventMultiplexer.registerRewindedEffectHandler( aSourceEventElement.getId(),
+ bind2( aSourceEventElement.charge, aSourceEventElement ) );
+ bEventRegistered = true;
+ break;
+ default:
+ log( 'generateEvent: not handled event type: ' + eEventType );
+ }
+ if( bEventRegistered )
+ {
+ var aStartEvent = aInteractiveAnimationSequenceMap[ nNodeId ].getStartEvent();
+ var aEndEvent = aInteractiveAnimationSequenceMap[ nNodeId ].getEndEvent();
+ aEventMultiplexer.registerEvent( eEventType, aSourceEventElement.getId(), aStartEvent );
+ aEventMultiplexer.registerEvent( EVENT_TRIGGER_END_EVENT, nNodeId, aEndEvent );
+ aEventMultiplexer.registerRewindedEffectHandler(
+ nNodeId,
+ bind2( InteractiveAnimationSequence.prototype.chargeEvents,
+ aInteractiveAnimationSequenceMap[ nNodeId ] )
+ );
+ }
+ }
+ else // no base event element present
+ {
+ switch( eEventType )
+ {
+ case EVENT_TRIGGER_ON_NEXT_EFFECT:
+ aNextEffectEventArray.appendEvent( aEvent );
+ break;
+ default:
+ log( 'generateEvent: not handled event type: ' + eEventType );
+ }
+ }
+ break;
+ case SYNCBASE_TIMING:
+ eEventType = aTiming.getEventType();
+ sEventBaseElemId = aTiming.getEventBaseElementId();
+ if( sEventBaseElemId )
+ {
+ var aAnimationNode = aNodeContext.aAnimationNodeMap[ sEventBaseElemId ];
+ if( !aAnimationNode )
+ {
+ log( 'generateEvent: SYNCBASE_TIMING: event base element not found: ' + sEventBaseElemId );
+ return;
+ }
+ aEventMultiplexer.registerEvent( eEventType, aAnimationNode.getId(), aEvent );
+ }
+ else
+ {
+ log( 'generateEvent: SYNCBASE_TIMING: event base element not specified' );
+ }
+ break;
+ default:
+ log( 'generateEvent: not handled timing type: ' + eTimingType );
+ }
+ }
+}
+
+registerEvent.DEBUG = aRegisterEventDebugPrinter.isEnabled();
+
+registerEvent.DBG = function( aTiming, nTime )
+{
+ if( registerEvent.DEBUG )
+ {
+ aRegisterEventDebugPrinter.print( 'registerEvent( timing: ' + aTiming.info() + ' )', nTime );
+ }
+};
+
+
+
+
+function SourceEventElement( sId, aElement, aEventMultiplexer )
+{
+ this.sId = sId;
+ this.aElement = aElement;
+ this.aEventMultiplexer = aEventMultiplexer;
+
+ this.aEventMultiplexer.registerMouseClickHandler( this, 1000 );
+
+ this.bClickHandled = false;
+ this.bIsPointerOver = false;
+ this.aElement.addEventListener( 'mouseover', bind2( SourceEventElement.prototype.onMouseEnter, this), false );
+ this.aElement.addEventListener( 'mouseout', bind2( SourceEventElement.prototype.onMouseLeave, this), false );
+}
+
+SourceEventElement.prototype.getId = function()
+{
+ return this.sId;
+};
+
+SourceEventElement.prototype.onMouseEnter = function()
+{
+ this.bIsPointerOver = true;
+ this.setPointerCursor();
+};
+
+SourceEventElement.prototype.onMouseLeave = function()
+{
+ this.bIsPointerOver = false;
+ this.setDefaultCursor();
+};
+
+SourceEventElement.prototype.charge = function()
+{
+ this.bClickHandled = false;
+ this.setPointerCursor();
+};
+
+SourceEventElement.prototype.handleClick = function( /*aMouseEvent*/ )
+{
+ if( !this.bIsPointerOver ) return false;
+
+ if( this.bClickHandled )
+ return false;
+
+ this.aEventMultiplexer.notifyEvent( EVENT_TRIGGER_ON_CLICK, this.getId() );
+ aSlideShow.update();
+ this.bClickHandled = true;
+ this.setDefaultCursor();
+ return true;
+};
+
+SourceEventElement.prototype.setPointerCursor = function()
+{
+ if( this.bClickHandled )
+ return;
+
+ this.aElement.setAttribute( 'style', 'cursor: pointer' );
+};
+
+SourceEventElement.prototype.setDefaultCursor = function()
+{
+ this.aElement.setAttribute( 'style', 'cursor: default' );
+};
+
+
+
+function HyperlinkElement( sId, aEventMultiplexer )
+{
+ var aElement = document.getElementById( sId );
+ if( !aElement )
+ {
+ log( 'error: HyperlinkElement: no element with id: <' + sId + '> found' );
+ return;
+ }
+ if( !aEventMultiplexer )
+ {
+ log( 'AnimatedElement constructor: event multiplexer is not valid' );
+ }
+
+ this.sId = sId;
+ this.aElement = aElement;
+ this.aEventMultiplexer = aEventMultiplexer;
+ this.nTargetSlideIndex = undefined;
+
+ this.sURL = getNSAttribute( 'xlink', this.aElement, 'href' );
+ if( this.sURL )
+ {
+ if( this.sURL[0] === '#' )
+ {
+ if( this.sURL.substr(1, 5) === 'Slide' )
+ {
+ var sSlideIndex = this.sURL.split( ' ' )[1];
+ this.nTargetSlideIndex = parseInt( sSlideIndex ) - 1;
+ }
+ }
+
+ this.aEventMultiplexer.registerElementChangedHandler( this.sId, bind2( HyperlinkElement.prototype.onElementChanged, this) );
+ this.aEventMultiplexer.registerMouseClickHandler( this, 1100 );
+
+ this.bIsPointerOver = false;
+ this.mouseEnterHandler = bind2( HyperlinkElement.prototype.onMouseEnter, this);
+ this.mouseLeaveHandler = bind2( HyperlinkElement.prototype.onMouseLeave, this);
+ this.aElement.addEventListener( 'mouseover', this.mouseEnterHandler, false );
+ this.aElement.addEventListener( 'mouseout', this.mouseLeaveHandler, false );
+ }
+ else
+ {
+ log( 'warning: HyperlinkElement(' + this.sId + '): url is empty' );
+ }
+}
+
+HyperlinkElement.prototype.onElementChanged = function( aElement )
+{
+ if( !aElement )
+ {
+ log( 'error: HyperlinkElement: passed element is not valid' );
+ return;
+ }
+
+ if( this.sURL )
+ {
+ this.aElement.removeEventListener( 'mouseover', this.mouseEnterHandler, false );
+ this.aElement.removeEventListener( 'mouseout', this.mouseLeaveHandler, false );
+ this.aElement = aElement;
+ this.aElement.addEventListener( 'mouseover', this.mouseEnterHandler, false );
+ this.aElement.addEventListener( 'mouseout', this.mouseLeaveHandler, false );
+ }
+};
+
+HyperlinkElement.prototype.onMouseEnter = function()
+{
+ this.bIsPointerOver = true;
+ this.setPointerCursor();
+};
+
+HyperlinkElement.prototype.onMouseLeave = function()
+{
+ this.bIsPointerOver = false;
+ this.setDefaultCursor();
+};
+
+HyperlinkElement.prototype.handleClick = function( )
+{
+ if( !this.bIsPointerOver ) return false;
+
+ if( this.nTargetSlideIndex !== undefined )
+ {
+ aSlideShow.displaySlide( this.nTargetSlideIndex, true );
+ }
+ else
+ {
+ var aWindowObject = document.defaultView;
+ if( aWindowObject )
+ {
+ aWindowObject.open( this.sURL, this.sId );
+ }
+ else
+ {
+ log( 'error: HyperlinkElement.handleClick: invalid window object.' );
+ }
+ }
+
+ return true;
+};
+
+HyperlinkElement.prototype.setPointerCursor = function()
+{
+ if( this.bClickHandled )
+ return;
+
+ this.aElement.setAttribute( 'style', 'cursor: pointer' );
+};
+
+HyperlinkElement.prototype.setDefaultCursor = function()
+{
+ this.aElement.setAttribute( 'style', 'cursor: default' );
+};
+
+
+
+function InteractiveAnimationSequence( nId )
+{
+ this.nId = nId;
+ this.bIsRunning = false;
+ this.aStartEvent = null;
+ this.aEndEvent = null;
+}
+
+InteractiveAnimationSequence.prototype.getId = function()
+{
+ return this.nId;
+};
+
+InteractiveAnimationSequence.prototype.getStartEvent = function()
+{
+ if( !this.aStartEvent )
+ {
+ this.aStartEvent =
+ makeEvent( bind2( InteractiveAnimationSequence.prototype.start, this ) );
+ }
+ return this.aStartEvent;
+};
+
+InteractiveAnimationSequence.prototype.getEndEvent = function()
+{
+ if( !this.aEndEvent )
+ {
+ this.aEndEvent =
+ makeEvent( bind2( InteractiveAnimationSequence.prototype.end, this ) );
+ }
+ return this.aEndEvent;
+};
+
+InteractiveAnimationSequence.prototype.chargeEvents = function()
+{
+ if( this.aStartEvent ) this.aStartEvent.charge();
+ if( this.aEndEvent ) this.aEndEvent.charge();
+};
+
+InteractiveAnimationSequence.prototype.isRunning = function()
+{
+ return this.bIsRunning;
+};
+
+InteractiveAnimationSequence.prototype.start = function()
+{
+ aSlideShow.notifyInteractiveAnimationSequenceStart( this.getId() );
+ this.bIsRunning = true;
+};
+
+InteractiveAnimationSequence.prototype.end = function()
+{
+ aSlideShow.notifyInteractiveAnimationSequenceEnd( this.getId() );
+ this.bIsRunning = false;
+};
+
+
+/** class PriorityEntry
+ * It provides an entry type for priority queues.
+ * Higher is the value of nPriority higher is the priority of the created entry.
+ *
+ * @param aValue
+ * The object to be prioritized.
+ * @param nPriority
+ * An integral number representing the object priority.
+ *
+ */
+function PriorityEntry( aValue, nPriority )
+{
+ this.aValue = aValue;
+ this.nPriority = nPriority;
+}
+
+/** EventEntry.compare
+ * Compare priority of two entries.
+ *
+ * @param aLhsEntry
+ * An instance of type PriorityEntry.
+ * @param aRhsEntry
+ * An instance of type PriorityEntry.
+ * @return Integer
+ * -1 if the left entry has lower priority of the right entry,
+ * 1 if the left entry has higher priority of the right entry,
+ * 0 if the two entry have the same priority
+ */
+PriorityEntry.compare = function( aLhsEntry, aRhsEntry )
+{
+ if ( aLhsEntry.nPriority < aRhsEntry.nPriority )
+ {
+ return -1;
+ }
+ else if (aLhsEntry.nPriority > aRhsEntry.nPriority)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+};
+
+
+
+
+function EventMultiplexer( aTimerEventQueue )
+{
+ this.nId = EventMultiplexer.getUniqueId();
+ this.aTimerEventQueue = aTimerEventQueue;
+ this.aEventMap = {};
+ this.aAnimationsEndHandler = null;
+ this.aSkipEffectEndHandlerSet = [];
+ this.aMouseClickHandlerSet = new PriorityQueue( PriorityEntry.compare );
+ this.aSkipEffectEvent = null;
+ this.aRewindCurrentEffectEvent = null;
+ this.aRewindLastEffectEvent = null;
+ this.aSkipInteractiveEffectEventSet = {};
+ this.aRewindRunningInteractiveEffectEventSet = {};
+ this.aRewindEndedInteractiveEffectEventSet = {};
+ this.aRewindedEffectHandlerSet = {};
+ this.aElementChangedHandlerSet = {};
+}
+
+EventMultiplexer.CURR_UNIQUE_ID = 0;
+
+EventMultiplexer.getUniqueId = function()
+{
+ ++EventMultiplexer.CURR_UNIQUE_ID;
+ return EventMultiplexer.CURR_UNIQUE_ID;
+};
+
+EventMultiplexer.prototype.getId = function()
+{
+ return this.nId;
+};
+
+EventMultiplexer.prototype.hasRegisteredMouseClickHandlers = function()
+{
+ return !this.aMouseClickHandlerSet.isEmpty();
+};
+
+EventMultiplexer.prototype.registerMouseClickHandler = function( aHandler, nPriority )
+{
+ var aHandlerEntry = new PriorityEntry( aHandler, nPriority );
+ this.aMouseClickHandlerSet.push( aHandlerEntry );
+};
+
+EventMultiplexer.prototype.notifyMouseClick = function( aMouseEvent )
+{
+ var aMouseClickHandlerSet = this.aMouseClickHandlerSet.clone();
+ while( !aMouseClickHandlerSet.isEmpty() )
+ {
+ var aHandlerEntry = aMouseClickHandlerSet.top();
+ aMouseClickHandlerSet.pop();
+ if( aHandlerEntry.aValue.handleClick( aMouseEvent ) )
+ break;
+ }
+};
+
+EventMultiplexer.prototype.registerEvent = function( eEventType, aNotifierId, aEvent )
+{
+ this.DBG( 'registerEvent', eEventType, aNotifierId );
+ if( !this.aEventMap[ eEventType ] )
+ {
+ this.aEventMap[ eEventType ] = {};
+ }
+ if( !this.aEventMap[ eEventType ][ aNotifierId ] )
+ {
+ this.aEventMap[ eEventType ][ aNotifierId ] = [];
+ }
+ this.aEventMap[ eEventType ][ aNotifierId ].push( aEvent );
+};
+
+
+EventMultiplexer.prototype.notifyEvent = function( eEventType, aNotifierId )
+{
+ this.DBG( 'notifyEvent', eEventType, aNotifierId );
+ if( this.aEventMap[ eEventType ] )
+ {
+ if( this.aEventMap[ eEventType ][ aNotifierId ] )
+ {
+ var aEventArray = this.aEventMap[ eEventType ][ aNotifierId ];
+ var nSize = aEventArray.length;
+ for( var i = 0; i < nSize; ++i )
+ {
+ this.aTimerEventQueue.addEvent( aEventArray[i] );
+ }
+ }
+ }
+};
+
+EventMultiplexer.prototype.registerAnimationsEndHandler = function( aHandler )
+{
+ this.aAnimationsEndHandler = aHandler;
+};
+
+EventMultiplexer.prototype.notifyAnimationsEndEvent = function()
+{
+ if( this.aAnimationsEndHandler )
+ this.aAnimationsEndHandler();
+};
+
+EventMultiplexer.prototype.registerNextEffectEndHandler = function( aHandler )
+{
+ this.aSkipEffectEndHandlerSet.push( aHandler );
+};
+
+EventMultiplexer.prototype.notifyNextEffectEndEvent = function()
+{
+ var nSize = this.aSkipEffectEndHandlerSet.length;
+ for( var i = 0; i < nSize; ++i )
+ {
+ (this.aSkipEffectEndHandlerSet[i])();
+ }
+ this.aSkipEffectEndHandlerSet = [];
+};
+
+EventMultiplexer.prototype.registerSkipEffectEvent = function( aEvent )
+{
+ this.aSkipEffectEvent = aEvent;
+};
+
+EventMultiplexer.prototype.notifySkipEffectEvent = function()
+{
+ if( this.aSkipEffectEvent )
+ {
+ this.aTimerEventQueue.addEvent( this.aSkipEffectEvent );
+ this.aSkipEffectEvent = null;
+ }
+};
+
+EventMultiplexer.prototype.registerRewindCurrentEffectEvent = function( aEvent )
+{
+ this.aRewindCurrentEffectEvent = aEvent;
+};
+
+EventMultiplexer.prototype.notifyRewindCurrentEffectEvent = function()
+{
+ if( this.aRewindCurrentEffectEvent )
+ {
+ this.aTimerEventQueue.addEvent( this.aRewindCurrentEffectEvent );
+ this.aRewindCurrentEffectEvent = null;
+ }
+};
+
+EventMultiplexer.prototype.registerRewindLastEffectEvent = function( aEvent )
+{
+ this.aRewindLastEffectEvent = aEvent;
+};
+
+EventMultiplexer.prototype.notifyRewindLastEffectEvent = function()
+{
+ if( this.aRewindLastEffectEvent )
+ {
+ this.aTimerEventQueue.addEvent( this.aRewindLastEffectEvent );
+ this.aRewindLastEffectEvent = null;
+ }
+};
+
+EventMultiplexer.prototype.registerSkipInteractiveEffectEvent = function( nNotifierId, aEvent )
+{
+ this.aSkipInteractiveEffectEventSet[ nNotifierId ] = aEvent;
+};
+
+EventMultiplexer.prototype.notifySkipInteractiveEffectEvent = function( nNotifierId )
+{
+ if( this.aSkipInteractiveEffectEventSet[ nNotifierId ] )
+ {
+ this.aTimerEventQueue.addEvent( this.aSkipInteractiveEffectEventSet[ nNotifierId ] );
+ }
+};
+
+EventMultiplexer.prototype.registerRewindRunningInteractiveEffectEvent = function( nNotifierId, aEvent )
+{
+ this.aRewindRunningInteractiveEffectEventSet[ nNotifierId ] = aEvent;
+};
+
+EventMultiplexer.prototype.notifyRewindRunningInteractiveEffectEvent = function( nNotifierId )
+{
+ if( this.aRewindRunningInteractiveEffectEventSet[ nNotifierId ] )
+ {
+ this.aTimerEventQueue.addEvent( this.aRewindRunningInteractiveEffectEventSet[ nNotifierId ] );
+ }
+};
+
+EventMultiplexer.prototype.registerRewindEndedInteractiveEffectEvent = function( nNotifierId, aEvent )
+{
+ this.aRewindEndedInteractiveEffectEventSet[ nNotifierId ] = aEvent;
+};
+
+EventMultiplexer.prototype.notifyRewindEndedInteractiveEffectEvent = function( nNotifierId )
+{
+ if( this.aRewindEndedInteractiveEffectEventSet[ nNotifierId ] )
+ {
+ this.aTimerEventQueue.addEvent( this.aRewindEndedInteractiveEffectEventSet[ nNotifierId ] );
+ }
+};
+
+EventMultiplexer.prototype.registerRewindedEffectHandler = function( aNotifierId, aHandler )
+{
+ this.aRewindedEffectHandlerSet[ aNotifierId ] = aHandler;
+};
+
+EventMultiplexer.prototype.notifyRewindedEffectEvent = function( aNotifierId )
+{
+ if( this.aRewindedEffectHandlerSet[ aNotifierId ] )
+ {
+ (this.aRewindedEffectHandlerSet[ aNotifierId ])();
+ }
+};
+
+EventMultiplexer.prototype.registerElementChangedHandler = function( aNotifierId, aHandler )
+{
+ this.aElementChangedHandlerSet[ aNotifierId ] = aHandler;
+};
+
+EventMultiplexer.prototype.notifyElementChangedEvent = function( aNotifierId, aElement )
+{
+ if( this.aElementChangedHandlerSet[ aNotifierId ] )
+ {
+ (this.aElementChangedHandlerSet[ aNotifierId ])( aElement );
+ }
+};
+
+EventMultiplexer.DEBUG = aEventMultiplexerDebugPrinter.isEnabled();
+
+EventMultiplexer.prototype.DBG = function( sMethodName, eEventType, aNotifierId, nTime )
+{
+ if( EventMultiplexer.DEBUG )
+ {
+ var sInfo = 'EventMultiplexer.' + sMethodName;
+ sInfo += '( type: ' + aEventTriggerOutMap[ eEventType ];
+ sInfo += ', notifier: ' + aNotifierId + ' )';
+ aEventMultiplexerDebugPrinter.print( sInfo, nTime );
+ }
+};
+
+
+
+/**********************************************************************************************
+ * Interpolator Handler and KeyStopLerp
+ **********************************************************************************************/
+
+var aInterpolatorHandler = {};
+
+aInterpolatorHandler.getInterpolator = function( eCalcMode, eValueType, eValueSubtype )
+{
+ var bHasSubtype = ( typeof( eValueSubtype ) === typeof( 0 ) );
+
+ if( !bHasSubtype && aInterpolatorHandler.aLerpFunctorMap[ eCalcMode ][ eValueType ] )
+ {
+ return aInterpolatorHandler.aLerpFunctorMap[ eCalcMode ][ eValueType ];
+ }
+ else if( bHasSubtype && aInterpolatorHandler.aLerpFunctorMap[ eCalcMode ][ eValueType ][ eValueSubtype ] )
+ {
+ return aInterpolatorHandler.aLerpFunctorMap[ eCalcMode ][ eValueType ][ eValueSubtype ];
+ }
+ else
+ {
+ log( 'aInterpolatorHandler.getInterpolator: not found any valid interpolator for calc mode '
+ + aCalcModeOutMap[eCalcMode] + ' and value type ' + aValueTypeOutMap[eValueType] );
+ return null;
+ }
+};
+
+aInterpolatorHandler.aLerpFunctorMap = [];
+aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_DISCRETE ] = [];
+aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ] = [];
+
+
+// interpolators for linear calculation
+
+aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ NUMBER_PROPERTY ] =
+ function ( nFrom, nTo, nT )
+ {
+ return ( ( 1.0 - nT )* nFrom + nT * nTo );
+ };
+
+aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ COLOR_PROPERTY ] = [];
+
+aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ COLOR_PROPERTY ][ COLOR_SPACE_RGB ] =
+ function ( nFrom, nTo, nT )
+ {
+ return RGBColor.interpolate( nFrom, nTo, nT );
+ };
+
+// For HSLColor we do not return the interpolator but a function
+// that generate the interpolator. The AnimationColorNode is 'aware' of that.
+aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ COLOR_PROPERTY ][ COLOR_SPACE_HSL ] =
+ function ( bCCW )
+ {
+ return function ( nFrom, nTo, nT )
+ {
+ return HSLColor.interpolate( nFrom, nTo, nT, bCCW );
+ };
+ };
+
+aInterpolatorHandler.aLerpFunctorMap[ CALC_MODE_LINEAR ][ TUPLE_NUMBER_PROPERTY ] =
+ function ( aFrom, aTo, nT )
+ {
+ var aRes = [];
+ for( var i = 0; i < aFrom.length; ++i )
+ {
+ aRes.push( ( 1.0 - nT )* aFrom[i] + nT * aTo[i] );
+ }
+ return aRes;
+ };
+
+
+
+
+function KeyStopLerp( aValueList )
+{
+ KeyStopLerp.validateInput( aValueList );
+
+ this.aKeyStopList = [];
+ this.nLastIndex = 0;
+ this.nKeyStopDistance = aValueList[1] - aValueList[0];
+ if( this.nKeyStopDistance <= 0 )
+ this.nKeyStopDistance = 0.001;
+
+ for( var i = 0; i < aValueList.length; ++i )
+ this.aKeyStopList.push( aValueList[i] );
+
+ this.nUpperBoundIndex = this.aKeyStopList.length - 2;
+}
+
+
+KeyStopLerp.validateInput = function( aValueList )
+{
+ var nSize = aValueList.length;
+ assert( nSize > 1, 'KeyStopLerp.validateInput: key stop vector must have two entries or more' );
+
+ for( var i = 1; i < nSize; ++i )
+ {
+ if( aValueList[i-1] > aValueList[i] )
+ log( 'KeyStopLerp.validateInput: time vector is not sorted in ascending order!' );
+ }
+};
+
+KeyStopLerp.prototype.reset = function()
+{
+ KeyStopLerp.validateInput( this.aKeyStopList );
+ this.nLastIndex = 0;
+ this.nKeyStopDistance = this.aKeyStopList[1] - this.aKeyStopList[0];
+ if( this.nKeyStopDistance <= 0 )
+ this.nKeyStopDistance = 0.001;
+
+};
+
+KeyStopLerp.prototype.lerp = function( nAlpha )
+{
+ if( nAlpha > this.aKeyStopList[ this.nLastIndex + 1 ] )
+ {
+ do
+ {
+ var nIndex = this.nLastIndex + 1;
+ this.nLastIndex = clamp( nIndex, 0, this.nUpperBoundIndex );
+ this.nKeyStopDistance = this.aKeyStopList[ this.nLastIndex + 1 ] - this.aKeyStopList[ this.nLastIndex ];
+ }
+ while( ( this.nKeyStopDistance <= 0 ) && ( this.nLastIndex < this.nUpperBoundIndex ) );
+ }
+
+ var nRawLerp = ( nAlpha - this.aKeyStopList[ this.nLastIndex ] ) / this.nKeyStopDistance;
+
+ nRawLerp = clamp( nRawLerp, 0.0, 1.0 );
+
+ var aResult = {};
+ aResult.nIndex = this.nLastIndex;
+ aResult.nLerp = nRawLerp;
+
+ return aResult;
+};
+
+KeyStopLerp.prototype.lerp_ported = function( nAlpha )
+{
+ if( ( this.aKeyStopList[ this.nLastIndex ] < nAlpha ) ||
+ ( this.aKeyStopList[ this.nLastIndex + 1 ] >= nAlpha ) )
+ {
+ var i = 0;
+ for( ; i < this.aKeyStopList.length; ++i )
+ {
+ if( this.aKeyStopList[i] >= nAlpha )
+ break;
+ }
+ if( this.aKeyStopList[i] > nAlpha )
+ --i;
+ var nIndex = i - 1;
+ this.nLastIndex = clamp( nIndex, 0, this.aKeyStopList.length - 2 );
+ }
+
+ var nRawLerp = ( nAlpha - this.aKeyStopList[ this.nLastIndex ] ) /
+ ( this.aKeyStopList[ this.nLastIndex+1 ] - this.aKeyStopList[ this.nLastIndex ] );
+
+ nRawLerp = clamp( nRawLerp, 0.0, 1.0 );
+
+ var aResult = {};
+ aResult.nIndex = this.nLastIndex;
+ aResult.nLerp = nRawLerp;
+
+ return aResult;
+};
+
+
+
+/**********************************************************************************************
+ * Operators
+ **********************************************************************************************/
+
+var aOperatorSetMap = [];
+
+// number operators
+aOperatorSetMap[ NUMBER_PROPERTY ] = {};
+
+aOperatorSetMap[ NUMBER_PROPERTY ].equal = function( a, b )
+{
+ return ( a === b );
+};
+
+aOperatorSetMap[ NUMBER_PROPERTY ].add = function( a, b )
+{
+ return ( a + b );
+};
+
+aOperatorSetMap[ NUMBER_PROPERTY ].scale = function( k, v )
+{
+ return ( k * v );
+};
+
+// color operators
+aOperatorSetMap[ COLOR_PROPERTY ] = {};
+
+aOperatorSetMap[ COLOR_PROPERTY ].equal = function( a, b )
+{
+ return a.equal( b );
+};
+
+aOperatorSetMap[ COLOR_PROPERTY ].add = function( a, b )
+{
+ var c = a.clone();
+ c.add( b );
+ return c;
+};
+
+aOperatorSetMap[ COLOR_PROPERTY ].scale = function( k, v )
+{
+ var r = v.clone();
+ r.scale( k );
+ return r;
+};
+
+// enum operators
+aOperatorSetMap[ ENUM_PROPERTY ] = {};
+
+aOperatorSetMap[ ENUM_PROPERTY ].equal = function( a, b )
+{
+ return ( a === b );
+};
+
+aOperatorSetMap[ ENUM_PROPERTY ].add = function( a )
+{
+ return a;
+};
+
+aOperatorSetMap[ ENUM_PROPERTY ].scale = function( k, v )
+{
+ return v;
+};
+
+// string operators
+aOperatorSetMap[ STRING_PROPERTY ] = aOperatorSetMap[ ENUM_PROPERTY ];
+
+// bool operators
+aOperatorSetMap[ BOOL_PROPERTY ] = aOperatorSetMap[ ENUM_PROPERTY ];
+
+// tuple number operators
+aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ] = {};
+
+aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].equal = function( a, b )
+{
+ assert( a.length === b.length, 'Tuples length mismatch.' );
+ return ( a.toString() === b.toString() );
+};
+
+aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].add = function( a, b )
+{
+ assert( a.length === b.length, 'Tuples length mismatch.' );
+ var r = [];
+ for( var i = 0; i < a.length; ++i )
+ {
+ r.push(a[i] + b[i]);
+ }
+ return r;
+};
+
+aOperatorSetMap[ TUPLE_NUMBER_PROPERTY ].scale = function( k, v )
+{
+ var r = [];
+ for( var i = 0; i < v.length; ++i )
+ {
+ r.push(k * v[i]);
+ }
+ return r;
+};
+
+
+
+
+/**********************************************************************************************
+ * Activity Class Hierarchy
+ **********************************************************************************************/
+
+
+function ActivityParamSet()
+{
+ this.aEndEvent = null;
+ this.aWakeupEvent = null;
+ this.aTimerEventQueue = null;
+ this.aActivityQueue = null;
+ this.nMinDuration = undefined;
+ this.nMinNumberOfFrames = MINIMUM_FRAMES_PER_SECONDS;
+ this.bAutoReverse = false;
+ this.nRepeatCount = 1.0;
+ this.nAccelerationFraction = 0.0;
+ this.nDecelerationFraction = 0.0;
+ this.nSlideWidth = undefined;
+ this.nSlideHeight = undefined;
+ this.aFormula = null;
+ this.aDiscreteTimes = [];
+}
+
+
+function AnimationActivity()
+{
+ this.nId = AnimationActivity.getUniqueId();
+}
+
+
+AnimationActivity.CURR_UNIQUE_ID = 0;
+
+AnimationActivity.getUniqueId = function()
+{
+ ++AnimationActivity.CURR_UNIQUE_ID;
+ return AnimationActivity.CURR_UNIQUE_ID;
+};
+
+AnimationActivity.prototype.getId = function()
+{
+ return this.nId;
+};
+
+
+
+
+function SetActivity( aCommonParamSet, aAnimation, aToAttr )
+{
+ SetActivity.superclass.constructor.call( this );
+
+ this.aAnimation = aAnimation;
+ this.aTargetElement = null;
+ this.aEndEvent = aCommonParamSet.aEndEvent;
+ this.aTimerEventQueue = aCommonParamSet.aTimerEventQueue;
+ this.aToAttr = aToAttr;
+ this.bIsActive = true;
+}
+extend( SetActivity, AnimationActivity );
+
+
+SetActivity.prototype.activate = function( aEndEvent )
+{
+ this.aEndEvent = aEndEvent;
+ this.bIsActive = true;
+};
+
+SetActivity.prototype.dispose = function()
+{
+ this.bIsActive = false;
+ if( this.aEndEvent && this.aEndEvent.isCharged() )
+ this.aEndEvent.dispose();
+};
+
+SetActivity.prototype.calcTimeLag = function()
+{
+ return 0.0;
+};
+
+SetActivity.prototype.perform = function()
+{
+ if( !this.isActive() )
+ return false;
+
+ // we're going inactive immediately:
+ this.bIsActive = false;
+
+ if( this.aAnimation && this.aTargetElement )
+ {
+ this.aAnimation.start( this.aTargetElement );
+ this.aAnimation.perform( this.aToAttr );
+ this.aAnimation.end();
+ }
+
+ if( this.aEndEvent )
+ this.aTimerEventQueue.addEvent( this.aEndEvent );
+
+};
+
+SetActivity.prototype.isActive = function()
+{
+ return this.bIsActive;
+};
+
+SetActivity.prototype.dequeued = function()
+{
+ // empty body
+};
+
+SetActivity.prototype.end = function()
+{
+ this.perform();
+};
+
+SetActivity.prototype.setTargets = function( aTargetElement )
+{
+ assert( aTargetElement, 'SetActivity.setTargets: target element is not valid' );
+ this.aTargetElement = aTargetElement;
+};
+
+
+
+
+function ActivityBase( aCommonParamSet )
+{
+ ActivityBase.superclass.constructor.call( this );
+
+ this.aTargetElement = null;
+ this.aEndEvent = aCommonParamSet.aEndEvent;
+ this.aTimerEventQueue = aCommonParamSet.aTimerEventQueue;
+ this.nRepeats = aCommonParamSet.nRepeatCount;
+ this.nAccelerationFraction = aCommonParamSet.nAccelerationFraction;
+ this.nDecelerationFraction = aCommonParamSet.nDecelerationFraction;
+ this.bAutoReverse = aCommonParamSet.bAutoReverse;
+
+ this.bFirstPerformCall = true;
+ this.bIsActive = true;
+
+}
+extend( ActivityBase, AnimationActivity );
+
+
+ActivityBase.prototype.activate = function( aEndEvent )
+{
+ this.aEndEvent = aEndEvent;
+ this.bFirstPerformCall = true;
+ this.bIsActive = true;
+};
+
+ActivityBase.prototype.dispose = function()
+{
+ // deactivate
+ this.bIsActive = false;
+
+ // dispose event
+ if( this.aEndEvent )
+ this.aEndEvent.dispose();
+
+ this.aEndEvent = null;
+};
+
+ActivityBase.prototype.perform = function()
+{
+ // still active?
+ if( !this.isActive() )
+ return false; // no, early exit.
+
+ assert( !this.bFirstPerformCall, 'ActivityBase.perform: assertion (!this.FirstPerformCall) failed' );
+
+ return true;
+};
+
+ActivityBase.prototype.calcTimeLag = function()
+{
+ // TODO(Q1): implement different init process!
+ if( this.isActive() && this.bFirstPerformCall )
+ {
+ this.bFirstPerformCall = false;
+
+ // notify derived classes that we're
+ // starting now
+ this.startAnimation();
+ }
+ return 0.0;
+};
+
+ActivityBase.prototype.isActive = function()
+{
+ return this.bIsActive;
+};
+
+ActivityBase.prototype.isDisposed = function()
+{
+ return ( !this.bIsActive && !this.aEndEvent );
+};
+
+ActivityBase.prototype.dequeued = function()
+{
+ if( !this.isActive() )
+ this.endAnimation();
+};
+
+ActivityBase.prototype.setTargets = function( aTargetElement )
+{
+ assert( aTargetElement, 'ActivityBase.setTargets: target element is not valid' );
+
+ this.aTargetElement = aTargetElement;
+};
+
+ActivityBase.prototype.startAnimation = function()
+{
+ throw ( 'ActivityBase.startAnimation: abstract method invoked' );
+};
+
+ActivityBase.prototype.endAnimation = function()
+{
+ throw ( 'ActivityBase.endAnimation: abstract method invoked' );
+};
+
+ActivityBase.prototype.endActivity = function()
+{
+ // this is a regular activity end
+ this.bIsActive = false;
+
+ // Activity is ending, queue event, then
+ if( this.aEndEvent )
+ this.aTimerEventQueue.addEvent( this.aEndEvent );
+
+ this.aEndEvent = null;
+
+};
+
+ActivityBase.prototype.calcAcceleratedTime = function( nT )
+{
+ // Handle acceleration/deceleration
+
+
+ // clamp nT to permissible [0,1] range
+ nT = clamp( nT, 0.0, 1.0 );
+
+ // take acceleration/deceleration into account. if the sum
+ // of nAccelerationFraction and nDecelerationFraction
+ // exceeds 1.0, ignore both (that's according to SMIL spec)
+ if( ( this.nAccelerationFraction > 0.0 || this.nDecelerationFraction > 0.0 ) &&
+ ( this.nAccelerationFraction + this.nDecelerationFraction <= 1.0 ) )
+ {
+ var nC = 1.0 - 0.5*this.nAccelerationFraction - 0.5*this.nDecelerationFraction;
+
+ // this variable accumulates the new time value
+ var nTPrime = 0.0;
+
+ if( nT < this.nAccelerationFraction )
+ {
+ nTPrime += 0.5 * nT * nT / this.nAccelerationFraction; // partial first interval
+ }
+ else
+ {
+ nTPrime += 0.5 * this.nAccelerationFraction; // full first interval
+
+ if( nT <= ( 1.0 - this.nDecelerationFraction ) )
+ {
+ nTPrime += nT - this.nAccelerationFraction; // partial second interval
+ }
+ else
+ {
+ nTPrime += 1.0 - this.nAccelerationFraction - this.nDecelerationFraction; // full second interval
+
+ var nTRelative = nT - 1.0 + this.nDecelerationFraction;
+
+ nTPrime += nTRelative - 0.5*nTRelative*nTRelative / this.nDecelerationFraction;
+ }
+ }
+
+ // normalize, and assign to work variable
+ nT = nTPrime / nC;
+
+ }
+ return nT;
+};
+
+ActivityBase.prototype.getEventQueue = function()
+{
+ return this.aTimerEventQueue;
+};
+
+ActivityBase.prototype.getTargetElement = function()
+{
+ return this.aTargetElement;
+};
+
+ActivityBase.prototype.isRepeatCountValid = function()
+{
+ return !!this.nRepeats; // first ! convert to bool
+};
+
+ActivityBase.prototype.getRepeatCount = function()
+{
+ return this.nRepeats;
+};
+
+ActivityBase.prototype.isAutoReverse = function()
+{
+ return this.bAutoReverse;
+};
+
+ActivityBase.prototype.end = function()
+{
+ if( !this.isActive() || this.isDisposed() )
+ return;
+
+ // assure animation is started:
+ if( this.bFirstPerformCall )
+ {
+ this.bFirstPerformCall = false;
+ // notify derived classes that we're starting now
+ this.startAnimation();
+ }
+
+ this.performEnd();
+ this.endAnimation();
+ this.endActivity();
+};
+
+ActivityBase.prototype.performEnd = function()
+{
+ throw ( 'ActivityBase.performEnd: abstract method invoked' );
+};
+
+
+
+
+function DiscreteActivityBase( aCommonParamSet )
+{
+ DiscreteActivityBase.superclass.constructor.call( this, aCommonParamSet );
+
+ this.aOriginalWakeupEvent = aCommonParamSet.aWakeupEvent;
+ this.aOriginalWakeupEvent.setActivity( this );
+ this.aWakeupEvent = this.aOriginalWakeupEvent;
+ this.aWakeupEvent = aCommonParamSet.aWakeupEvent;
+ this.aDiscreteTimes = aCommonParamSet.aDiscreteTimes;
+ // Simple duration of activity
+ this.nMinSimpleDuration = aCommonParamSet.nMinDuration;
+ // Actual number of frames shown until now.
+ this.nCurrPerformCalls = 0;
+}
+extend( DiscreteActivityBase, ActivityBase );
+
+
+DiscreteActivityBase.prototype.activate = function( aEndElement )
+{
+ DiscreteActivityBase.superclass.activate.call( this, aEndElement );
+
+ this.aWakeupEvent = this.aOriginalWakeupEvent;
+ this.aWakeupEvent.setNextTimeout( 0 );
+ this.nCurrPerformCalls = 0;
+};
+
+DiscreteActivityBase.prototype.startAnimation = function()
+{
+ this.aWakeupEvent.start();
+};
+
+DiscreteActivityBase.prototype.calcFrameIndex = function( nCurrCalls, nVectorSize )
+{
+ if( this.isAutoReverse() )
+ {
+ // every full repeat run consists of one
+ // forward and one backward traversal.
+ var nFrameIndex = nCurrCalls % (2 * nVectorSize);
+
+ // nFrameIndex values >= nVectorSize belong to
+ // the backward traversal
+ if( nFrameIndex >= nVectorSize )
+ nFrameIndex = 2*nVectorSize - nFrameIndex; // invert sweep
+
+ return nFrameIndex;
+ }
+ else
+ {
+ return nCurrCalls % nVectorSize;
+ }
+};
+
+DiscreteActivityBase.prototype.calcRepeatCount = function( nCurrCalls, nVectorSize )
+{
+ if( this.isAutoReverse() )
+ {
+ return Math.floor( nCurrCalls / (2*nVectorSize) ); // we've got 2 cycles per repeat
+ }
+ else
+ {
+ return Math.floor( nCurrCalls / nVectorSize );
+ }
+};
+
+DiscreteActivityBase.prototype.performDiscreteHook = function( /*nFrame, nRepeatCount*/ )
+{
+ throw ( 'DiscreteActivityBase.performDiscreteHook: abstract method invoked' );
+};
+
+DiscreteActivityBase.prototype.perform = function()
+{
+ // call base class, for start() calls and end handling
+ if( !SimpleContinuousActivityBase.superclass.perform.call( this ) )
+ return false; // done, we're ended
+
+ var nVectorSize = this.aDiscreteTimes.length;
+
+ var nFrameIndex = this.calcFrameIndex(this.nCurrPerformCalls, nVectorSize);
+ var nRepeatCount = this.calcRepeatCount( this.nCurrPerformCalls, nVectorSize );
+ this.performDiscreteHook( nFrameIndex, nRepeatCount );
+
+ // one more frame successfully performed
+ ++this.nCurrPerformCalls;
+
+ // calc currently reached repeat count
+ var nCurrRepeat = this.nCurrPerformCalls / nVectorSize;
+
+ // if auto-reverse is specified, halve the
+ // effective repeat count, since we pass every
+ // repeat run twice: once forward, once backward.
+ if( this.isAutoReverse() )
+ nCurrRepeat /= 2;
+
+ // schedule next frame, if either repeat is indefinite
+ // (repeat forever), or we've not yet reached the requested
+ // repeat count
+ if( !this.isRepeatCountValid() || nCurrRepeat < this.getRepeatCount() )
+ {
+ // add wake-up event to queue (modulo vector size, to cope with repeats).
+
+ // repeat is handled locally, only apply acceleration/deceleration.
+ // Scale time vector with simple duration, offset with full repeat
+ // times.
+
+ // Note that calcAcceleratedTime() is only applied to the current repeat's value,
+ // not to the total resulting time. This is in accordance with the SMIL spec.
+
+ nFrameIndex = this.calcFrameIndex(this.nCurrPerformCalls, nVectorSize);
+ var nCurrentRepeatTime = this.aDiscreteTimes[nFrameIndex];
+ nRepeatCount = this.calcRepeatCount( this.nCurrPerformCalls, nVectorSize );
+ var nNextTimeout = this.nMinSimpleDuration * ( nRepeatCount + this.calcAcceleratedTime( nCurrentRepeatTime ) );
+ this.aWakeupEvent.setNextTimeout( nNextTimeout );
+
+ this.getEventQueue().addEvent( this.aWakeupEvent );
+ }
+ else
+ {
+ // release event reference (relation to wake up event is circular!)
+ this.aWakeupEvent = null;
+
+ // done with this activity
+ this.endActivity();
+ }
+
+ return false; // remove from queue, will be added back by the wakeup event.
+};
+
+DiscreteActivityBase.prototype.dispose = function()
+{
+ // dispose event
+ if( this.aWakeupEvent )
+ this.aWakeupEvent.dispose();
+
+ // release references
+ this.aWakeupEvent = null;
+
+ DiscreteActivityBase.superclass.dispose.call(this);
+};
+
+
+
+
+function SimpleContinuousActivityBase( aCommonParamSet )
+{
+ SimpleContinuousActivityBase.superclass.constructor.call( this, aCommonParamSet );
+
+ // Time elapsed since activity started
+ this.aTimer = new ElapsedTime( aCommonParamSet.aActivityQueue.getTimer() );
+ // Simple duration of activity
+ this.nMinSimpleDuration = aCommonParamSet.nMinDuration;
+ // Minimal number of frames to show
+ this.nMinNumberOfFrames = aCommonParamSet.nMinNumberOfFrames;
+ // Actual number of frames shown until now.
+ this.nCurrPerformCalls = 0;
+
+}
+extend( SimpleContinuousActivityBase, ActivityBase );
+
+
+SimpleContinuousActivityBase.prototype.startAnimation = function()
+{
+ // init timer. We measure animation time only when we're
+ // actually started.
+ this.aTimer.reset();
+};
+
+SimpleContinuousActivityBase.prototype.calcTimeLag = function()
+{
+ SimpleContinuousActivityBase.superclass.calcTimeLag.call( this );
+
+ if( !this.isActive() )
+ return 0.0;
+
+ // retrieve locally elapsed time
+ var nCurrElapsedTime = this.aTimer.getElapsedTime();
+
+ // go to great length to ensure a proper animation
+ // run. Since we don't know how often we will be called
+ // here, try to spread the animator calls uniquely over
+ // the [0,1] parameter range. Be aware of the fact that
+ // perform will be called at least mnMinNumberOfTurns
+ // times.
+
+ // fraction of time elapsed
+ var nFractionElapsedTime = nCurrElapsedTime / this.nMinSimpleDuration;
+
+ // fraction of minimum calls performed
+ var nFractionRequiredCalls = this.nCurrPerformCalls / this.nMinNumberOfFrames;
+
+ // okay, so now, the decision is easy:
+ //
+ // If the fraction of time elapsed is smaller than the
+ // number of calls required to be performed, then we calc
+ // the position on the animation range according to
+ // elapsed time. That is, we're so to say ahead of time.
+ //
+ // In contrary, if the fraction of time elapsed is larger,
+ // then we're lagging, and we thus calc the position on
+ // the animation time line according to the fraction of
+ // calls performed. Thus, the animation is forced to slow
+ // down, and take the required minimal number of steps,
+ // sufficiently equally distributed across the animation
+ // time line.
+
+ if( nFractionElapsedTime < nFractionRequiredCalls )
+ {
+ return 0.0;
+ }
+ else
+ {
+ // lag global time, so all other animations lag, too:
+ return ( ( nFractionElapsedTime - nFractionRequiredCalls ) * this.nMinSimpleDuration );
+ }
+};
+
+SimpleContinuousActivityBase.prototype.perform = function()
+{
+ // call base class, for start() calls and end handling
+ if( !SimpleContinuousActivityBase.superclass.perform.call( this ) )
+ return false; // done, we're ended
+
+ // get relative animation position
+ var nCurrElapsedTime = this.aTimer.getElapsedTime();
+ var nT = nCurrElapsedTime / this.nMinSimpleDuration;
+
+
+ // one of the stop criteria reached?
+
+ // will be set to true below, if one of the termination criteria matched.
+ var bActivityEnding = false;
+
+ if( this.isRepeatCountValid() )
+ {
+ // Finite duration case
+
+ // When we've autoreverse on, the repeat count doubles
+ var nRepeatCount = this.getRepeatCount();
+ var nEffectiveRepeat = this.isAutoReverse() ? 2.0 * nRepeatCount : nRepeatCount;
+
+ // time (or frame count) elapsed?
+ if( nEffectiveRepeat <= nT )
+ {
+ // Ok done for now. Will not exit right here,
+ // to give animation the chance to render the last
+ // frame below
+ bActivityEnding = true;
+
+ // clamp animation to max permissible value
+ nT = nEffectiveRepeat;
+ }
+ }
+
+
+ // need to do auto-reverse?
+
+ var nRepeats;
+ var nRelativeSimpleTime;
+ // TODO(Q3): Refactor this mess
+ if( this.isAutoReverse() )
+ {
+ // divert active duration into repeat and
+ // fractional part.
+ nRepeats = Math.floor( nT );
+ var nFractionalActiveDuration = nT - nRepeats;
+
+ // for auto-reverse, map ranges [1,2), [3,4), ...
+ // to ranges [0,1), [1,2), etc.
+ if( nRepeats % 2 )
+ {
+ // we're in an odd range, reverse sweep
+ nRelativeSimpleTime = 1.0 - nFractionalActiveDuration;
+ }
+ else
+ {
+ // we're in an even range, pass on as is
+ nRelativeSimpleTime = nFractionalActiveDuration;
+ }
+
+ // effective repeat count for autoreverse is half of
+ // the input time's value (each run of an autoreverse
+ // cycle is half of a repeat)
+ nRepeats /= 2;
+ }
+ else
+ {
+ // determine repeat
+
+ // calc simple time and number of repeats from nT
+ // Now, that's easy, since the fractional part of
+ // nT gives the relative simple time, and the
+ // integer part the number of full repeats:
+ nRepeats = Math.floor( nT );
+ nRelativeSimpleTime = nT - nRepeats;
+
+ // clamp repeats to max permissible value (maRepeats.getValue() - 1.0)
+ if( this.isRepeatCountValid() && ( nRepeats >= this.getRepeatCount() ) )
+ {
+ // Note that this code here only gets
+ // triggered if this.nRepeats is an
+ // _integer_. Otherwise, nRepeats will never
+ // reach nor exceed
+ // maRepeats.getValue(). Thus, the code below
+ // does not need to handle cases of fractional
+ // repeats, and can always assume that a full
+ // animation run has ended (with
+ // nRelativeSimpleTime = 1.0 for
+ // non-autoreversed activities).
+
+ // with modf, nRelativeSimpleTime will never
+ // become 1.0, since nRepeats is incremented and
+ // nRelativeSimpleTime set to 0.0 then.
+ //
+ // For the animation to reach its final value,
+ // nRepeats must although become this.nRepeats - 1.0,
+ // and nRelativeSimpleTime = 1.0.
+ nRelativeSimpleTime = 1.0;
+ nRepeats -= 1.0;
+ }
+ }
+
+
+ // actually perform something
+
+ this.simplePerform( nRelativeSimpleTime, nRepeats );
+
+ // delayed endActivity() call from end condition check
+ // below. Issued after the simplePerform() call above, to
+ // give animations the chance to correctly reach the
+ // animation end value, without spurious bail-outs because
+ // of isActive() returning false.
+ if( bActivityEnding )
+ this.endActivity();
+
+ // one more frame successfully performed
+ ++this.nCurrPerformCalls;
+
+ return this.isActive();
+};
+
+SimpleContinuousActivityBase.prototype.simplePerform = function( /*nSimpleTime, nRepeatCount*/ )
+{
+ throw ( 'SimpleContinuousActivityBase.simplePerform: abstract method invoked' );
+};
+
+
+
+
+function ContinuousKeyTimeActivityBase( aCommonParamSet )
+{
+ var nSize = aCommonParamSet.aDiscreteTimes.length;
+ assert( nSize > 1,
+ 'ContinuousKeyTimeActivityBase constructor: assertion (aDiscreteTimes.length > 1) failed' );
+
+ assert( aCommonParamSet.aDiscreteTimes[0] == 0.0,
+ 'ContinuousKeyTimeActivityBase constructor: assertion (aDiscreteTimes.front() == 0.0) failed' );
+
+ assert( aCommonParamSet.aDiscreteTimes[ nSize - 1 ] <= 1.0,
+ 'ContinuousKeyTimeActivityBase constructor: assertion (aDiscreteTimes.back() <= 1.0) failed' );
+
+ ContinuousKeyTimeActivityBase.superclass.constructor.call( this, aCommonParamSet );
+
+ this.aLerper = new KeyStopLerp( aCommonParamSet.aDiscreteTimes );
+}
+extend( ContinuousKeyTimeActivityBase, SimpleContinuousActivityBase );
+
+
+ContinuousKeyTimeActivityBase.prototype.activate = function( aEndElement )
+{
+ ContinuousKeyTimeActivityBase.superclass.activate.call( this, aEndElement );
+
+ this.aLerper.reset();
+};
+
+ContinuousKeyTimeActivityBase.prototype.performContinuousHook = function( /*nIndex, nFractionalIndex, nRepeatCount*/ )
+{
+ throw ( 'ContinuousKeyTimeActivityBase.performContinuousHook: abstract method invoked' );
+};
+
+ContinuousKeyTimeActivityBase.prototype.simplePerform = function( nSimpleTime, nRepeatCount )
+{
+ var nAlpha = this.calcAcceleratedTime( nSimpleTime );
+
+ var aLerpResult = this.aLerper.lerp( nAlpha );
+
+ this.performContinuousHook( aLerpResult.nIndex, aLerpResult.nLerp, nRepeatCount );
+};
+
+
+
+
+function ContinuousActivityBase( aCommonParamSet )
+{
+ ContinuousActivityBase.superclass.constructor.call( this, aCommonParamSet );
+
+}
+extend( ContinuousActivityBase, SimpleContinuousActivityBase );
+
+
+ContinuousActivityBase.prototype.performContinuousHook = function( /*nModifiedTime, nRepeatCount*/ )
+{
+ throw ( 'ContinuousActivityBase.performContinuousHook: abstract method invoked' );
+};
+
+ContinuousActivityBase.prototype.simplePerform = function( nSimpleTime, nRepeatCount )
+{
+ this.performContinuousHook( this.calcAcceleratedTime( nSimpleTime ), nRepeatCount );
+};
+
+
+
+
+function SimpleActivity( aCommonParamSet, aNumberAnimation, eDirection )
+{
+ assert( ( eDirection == BACKWARD ) || ( eDirection == FORWARD ),
+ 'SimpleActivity constructor: animation direction is not valid' );
+
+ assert( aNumberAnimation, 'SimpleActivity constructor: animation object is not valid' );
+
+ SimpleActivity.superclass.constructor.call( this, aCommonParamSet );
+
+ this.aAnimation = aNumberAnimation;
+ this.nDirection = ( eDirection == FORWARD ) ? 1.0 : 0.0;
+}
+extend( SimpleActivity, ContinuousActivityBase );
+
+
+SimpleActivity.prototype.startAnimation = function()
+{
+ if( this.isDisposed() || !this.aAnimation )
+ return;
+
+ ANIMDBG.print( 'SimpleActivity.startAnimation invoked' );
+ SimpleActivity.superclass.startAnimation.call( this );
+
+ // start animation
+ this.aAnimation.start( this.getTargetElement() );
+};
+
+SimpleActivity.prototype.endAnimation = function()
+{
+ if( this.aAnimation )
+ this.aAnimation.end();
+
+};
+
+SimpleActivity.prototype.performContinuousHook = function( nModifiedTime /*, nRepeatCount*/ )
+{
+ // nRepeatCount is not used
+
+ if( this.isDisposed() || !this.aAnimation )
+ return;
+
+ var nT = 1.0 - this.nDirection + nModifiedTime * ( 2.0*this.nDirection - 1.0 );
+ this.aAnimation.perform( nT );
+};
+
+SimpleActivity.prototype.performEnd = function()
+{
+ if( this.aAnimation )
+ this.aAnimation.perform( this.nDirection );
+};
+
+
+
+
+// FromToByActivity< BaseType > template class
+
+
+function FromToByActivityTemplate( BaseType ) // template parameter
+{
+
+ function FromToByActivity( aFromValue, aToValue, aByValue,
+ aActivityParamSet, aAnimation,
+ aInterpolator, aOperatorSet, bAccumulate )
+ {
+ assert( aAnimation, 'FromToByActivity constructor: invalid animation object' );
+ assert( ( aToValue != undefined ) || ( aByValue != undefined ),
+ 'FromToByActivity constructor: one of aToValue or aByValue must be valid' );
+
+ FromToByActivity.superclass.constructor.call( this, aActivityParamSet );
+
+ this.aFrom = aFromValue;
+ this.aTo = aToValue;
+ this.aBy = aByValue;
+ this.aStartValue = null;
+ this.aEndValue = null;
+ this.aPreviousValue = null;
+ this.aStartInterpolationValue = null;
+ this.aAnimation = aAnimation;
+ this.aInterpolator = aInterpolator;
+ this.equal = aOperatorSet.equal;
+ this.add = aOperatorSet.add;
+ this.scale = aOperatorSet.scale;
+ this.bDynamicStartValue = false;
+ this.nIteration = 0;
+ this.bCumulative = bAccumulate;
+ this.aFormula = aActivityParamSet.aFormula;
+ }
+ extend( FromToByActivity, BaseType );
+
+ FromToByActivity.prototype.initAnimatedElement = function()
+ {
+ if( this.aAnimation && this.aFrom )
+ {
+ var aValue = this.aFormula ? this.aFormula( this.aFrom ) : this.aFrom;
+ this.aAnimation.perform(aValue);
+ }
+ };
+
+ FromToByActivity.prototype.startAnimation = function()
+ {
+ if( this.isDisposed() || !this.aAnimation )
+ {
+ log( 'FromToByActivity.startAnimation: activity disposed or not valid animation' );
+ return;
+ }
+
+ FromToByActivity.superclass.startAnimation.call( this );
+
+ this.aAnimation.start( this.getTargetElement() );
+
+
+ var aAnimationStartValue = this.aAnimation.getUnderlyingValue();
+
+ // first of all, determine general type of
+ // animation, by inspecting which of the FromToBy values
+ // are actually valid.
+ // See http://www.w3.org/TR/smil20/animation.html#AnimationNS-FromToBy
+ // for a definition
+ if( this.aFrom )
+ {
+ // From-to or From-by animation. According to
+ // SMIL spec, the To value takes precedence
+ // over the By value, if both are specified
+ if( this.aTo )
+ {
+ // From-To animation
+ this.aStartValue = this.aFrom;
+ this.aEndValue = this.aTo;
+ }
+ else if( this.aBy )
+ {
+ // From-By animation
+ this.aStartValue = this.aFrom;
+
+ this.aEndValue = this.add( this.aStartValue, this.aBy );
+ }
+ }
+ else
+ {
+ this.aStartValue = aAnimationStartValue;
+ this.aStartInterpolationValue = this.aStartValue;
+
+ // By or To animation. According to SMIL spec,
+ // the To value takes precedence over the By
+ // value, if both are specified
+ if( this.aTo )
+ {
+ // To animation
+
+ // According to the SMIL spec
+ // (http://www.w3.org/TR/smil20/animation.html#animationNS-ToAnimation),
+ // the to animation interpolates between
+ // the _running_ underlying value and the to value (as the end value)
+ this.bDynamicStartValue = true;
+ this.aPreviousValue = this.aStartValue;
+ this.aEndValue = this.aTo;
+ }
+ else if( this.aBy )
+ {
+ // By animation
+ this.aStartValue = aAnimationStartValue;
+
+ this.aEndValue = this.add( this.aStartValue, this.aBy );
+ }
+ }
+
+ ANIMDBG.print( 'FromToByActivity.startAnimation: aStartValue = ' + this.aStartValue + ', aEndValue = ' + this.aEndValue );
+ };
+
+ FromToByActivity.prototype.endAnimation = function()
+ {
+ if( this.aAnimation )
+ this.aAnimation.end();
+ };
+
+ // perform hook override for ContinuousActivityBase
+ FromToByActivity.prototype.performContinuousHook = function( nModifiedTime, nRepeatCount )
+ {
+ if( this.isDisposed() || !this.aAnimation )
+ {
+ log( 'FromToByActivity.performContinuousHook: activity disposed or not valid animation' );
+ return;
+ }
+
+
+ // According to SMIL 3.0 spec 'to' animation if no other (lower priority)
+ // animations are active or frozen then a simple interpolation is performed.
+ // That is, the start interpolation value is constant while the animation
+ // is running, and is equal to the underlying value retrieved when
+ // the animation start.
+ // However if another animation is manipulating the underlying value,
+ // the 'to' animation will initially add to the effect of the lower priority
+ // animation, and increasingly dominate it as it nears the end of the
+ // simple duration, eventually overriding it completely.
+ // That is, each time the underlying value is changed between two
+ // computations of the animation function the new underlying value is used
+ // as start value for the interpolation.
+ // See:
+ // http://www.w3.org/TR/SMIL3/smil-animation.html#animationNS-ToAnimation
+ // (Figure 6 - Effect of Additive to animation example)
+ // Moreover when a 'to' animation is repeated, at each new iteration
+ // the start interpolation value is reset to the underlying value
+ // of the animated property when the animation started,
+ // as it is shown in the example provided by the SMIL 3.0 spec.
+ // This is exactly as Firefox performs SVG 'to' animations.
+ if( this.bDynamicStartValue )
+ {
+ if( this.nIteration != nRepeatCount )
+ {
+ this.nIteration = nRepeatCount;
+ this.aStartInterpolationValue = this.aStartValue;
+ }
+ else
+ {
+ var aActualValue = this.aAnimation.getUnderlyingValue();
+ if( !this.equal( aActualValue, this.aPreviousValue ) )
+ this.aStartInterpolationValue = aActualValue;
+ }
+ }
+
+ var aValue = this.aInterpolator( this.aStartInterpolationValue,
+ this.aEndValue, nModifiedTime );
+
+ // According to the SMIL spec:
+ // Because 'to' animation is defined in terms of absolute values of
+ // the target attribute, cumulative animation is not defined.
+ if( this.bCumulative && !this.bDynamicStartValue )
+ {
+ // aValue = this.aEndValue * nRepeatCount + aValue;
+ aValue = this.add( this.scale( nRepeatCount, this.aEndValue ), aValue );
+ }
+
+ aValue = this.aFormula ? this.aFormula( aValue ) : aValue;
+ this.aAnimation.perform( aValue );
+
+ if( this.bDynamicStartValue )
+ {
+ this.aPreviousValue = this.aAnimation.getUnderlyingValue();
+ }
+
+ };
+
+ // perform hook override for DiscreteActivityBase
+ FromToByActivity.prototype.performDiscreteHook = function( /*nFrame, nRepeatCount*/ )
+ {
+ if (this.isDisposed() || !this.aAnimation) {
+ log('FromToByActivity.performDiscreteHook: activity disposed or not valid animation');
+ return;
+ }
+ };
+
+ FromToByActivity.prototype.performEnd = function()
+ {
+ if( this.aAnimation )
+ {
+ var aValue = this.isAutoReverse() ? this.aStartValue : this.aEndValue;
+ aValue = this.aFormula ? this.aFormula( aValue ) : aValue;
+ this.aAnimation.perform( aValue );
+ }
+ };
+
+ FromToByActivity.prototype.dispose = function()
+ {
+ FromToByActivity.superclass.dispose.call( this );
+ };
+
+
+ return FromToByActivity;
+}
+
+
+// FromToByActivity< ContinuousActivityBase > instantiation
+var LinearFromToByActivity = instantiate( FromToByActivityTemplate, ContinuousActivityBase );
+// FromToByActivity< DiscreteActivityBase > instantiation
+var DiscreteFromToByActivity = instantiate( FromToByActivityTemplate, DiscreteActivityBase );
+
+
+
+
+// ValueListActivity< BaseType > template class
+
+
+function ValueListActivityTemplate( BaseType ) // template parameter
+{
+
+ function ValueListActivity( aValueList, aActivityParamSet,
+ aAnimation, aInterpolator,
+ aOperatorSet, bAccumulate )
+ {
+ assert( aAnimation, 'ValueListActivity constructor: invalid animation object' );
+ assert( aValueList.length != 0, 'ValueListActivity: value list is empty' );
+
+ ValueListActivity.superclass.constructor.call( this, aActivityParamSet );
+
+ this.aValueList = aValueList;
+ this.aAnimation = aAnimation;
+ this.aInterpolator = aInterpolator;
+ this.add = aOperatorSet.add;
+ this.scale = aOperatorSet.scale;
+ this.bCumulative = bAccumulate;
+ this.aLastValue = this.aValueList[ this.aValueList.length - 1 ];
+ this.aFormula = aActivityParamSet.aFormula;
+ }
+ extend( ValueListActivity, BaseType );
+
+ ValueListActivity.prototype.activate = function( aEndEvent )
+ {
+ ValueListActivity.superclass.activate.call( this, aEndEvent );
+ for( var i = 0; i < this.aValueList.length; ++i )
+ {
+ ANIMDBG.print( 'createValueListActivity: value[' + i + '] = ' + this.aValueList[i] );
+ }
+ };
+
+ ValueListActivity.prototype.initAnimatedElement = function()
+ {
+ if( this.aAnimation )
+ {
+ var aValue = this.aValueList[0];
+ aValue = this.aFormula ? this.aFormula( aValue ) : aValue;
+ this.aAnimation.perform(aValue);
+ }
+ };
+
+ ValueListActivity.prototype.startAnimation = function()
+ {
+ if( this.isDisposed() || !this.aAnimation )
+ {
+ log( 'ValueListActivity.startAnimation: activity disposed or not valid animation' );
+ return;
+ }
+
+ ValueListActivity.superclass.startAnimation.call( this );
+
+ this.aAnimation.start( this.getTargetElement() );
+ };
+
+ ValueListActivity.prototype.endAnimation = function()
+ {
+ if( this.aAnimation )
+ this.aAnimation.end();
+ };
+
+ // perform hook override for ContinuousKeyTimeActivityBase base
+ ValueListActivity.prototype.performContinuousHook = function( nIndex, nFractionalIndex, nRepeatCount )
+ {
+ if( this.isDisposed() || !this.aAnimation )
+ {
+ log( 'ValueListActivity.performContinuousHook: activity disposed or not valid animation' );
+ return;
+ }
+
+ assert( ( nIndex + 1 ) < this.aValueList.length,
+ 'ValueListActivity.performContinuousHook: assertion (nIndex + 1 < this.aValueList.length) failed' );
+
+ // interpolate between nIndex and nIndex+1 values
+
+ var aValue = this.aInterpolator( this.aValueList[ nIndex ],
+ this.aValueList[ nIndex+1 ],
+ nFractionalIndex );
+
+ if( this.bCumulative )
+ {
+ //aValue = aValue + nRepeatCount * this.aLastValue;
+ aValue = this.add( aValue, this.scale( nRepeatCount, this.aLastValue ) );
+ }
+
+ aValue = this.aFormula ? this.aFormula( aValue ) : aValue;
+ this.aAnimation.perform( aValue );
+ };
+
+ // perform hook override for DiscreteActivityBase base
+ ValueListActivity.prototype.performDiscreteHook = function( nFrame, nRepeatCount )
+ {
+ if( this.isDisposed() || !this.aAnimation )
+ {
+ log( 'ValueListActivity.performDiscreteHook: activity disposed or not valid animation' );
+ return;
+ }
+
+ assert( nFrame < this.aValueList.length,
+ 'ValueListActivity.performDiscreteHook: assertion ( nFrame < this.aValueList.length) failed' );
+
+ // this is discrete, thus no lerp here.
+ var aValue = this.aValueList[nFrame];
+
+ if( this.bCumulative )
+ {
+ aValue = this.add( aValue, this.scale( nRepeatCount, this.aLastValue ) );
+ // for numbers: aValue = aValue + nRepeatCount * this.aLastValue;
+ // for enums, bools or strings: aValue = aValue;
+ }
+
+ aValue = this.aFormula ? this.aFormula( aValue ) : aValue;
+ this.aAnimation.perform( aValue );
+ };
+
+ ValueListActivity.prototype.performEnd = function()
+ {
+ if( this.aAnimation )
+ {
+ var aValue = this.aFormula ? this.aFormula( this.aLastValue ) : this.aLastValue;
+ this.aAnimation.perform( aValue );
+ }
+ };
+
+ ValueListActivity.prototype.dispose = function()
+ {
+ ValueListActivity.superclass.dispose.call( this );
+ };
+
+
+ return ValueListActivity;
+}
+
+
+// ValueListActivity< ContinuousKeyTimeActivityBase > instantiation
+var LinearValueListActivity = instantiate( ValueListActivityTemplate, ContinuousKeyTimeActivityBase );
+// ValueListActivity< DiscreteActivityBase > instantiation
+var DiscreteValueListActivity = instantiate( ValueListActivityTemplate, DiscreteActivityBase );
+
+
+
+/**********************************************************************************************
+ * Activity Factory
+ **********************************************************************************************/
+
+
+function createActivity( aActivityParamSet, aAnimationNode, aAnimation, aInterpolator )
+{
+ var eCalcMode = aAnimationNode.getCalcMode();
+
+ var sAttributeName = aAnimationNode.getAttributeName();
+ var aAttributeProp = aAttributeMap[ sAttributeName ];
+
+ var eValueType = aAttributeProp[ 'type' ];
+ var eValueSubtype = aAttributeProp[ 'subtype' ];
+
+ // do we need to get an interpolator ?
+ if( ! aInterpolator )
+ {
+ aInterpolator = aInterpolatorHandler.getInterpolator( eCalcMode,
+ eValueType,
+ eValueSubtype );
+ }
+
+ // is it cumulative ?
+ var bAccumulate = ( aAnimationNode.getAccumulate() === ACCUMULATE_MODE_SUM )
+ && !( eValueType === BOOL_PROPERTY ||
+ eValueType === STRING_PROPERTY ||
+ eValueType === ENUM_PROPERTY );
+
+ if( aAnimationNode.getFormula() )
+ {
+ var sFormula = aAnimationNode.getFormula();
+ var reMath = /abs|sqrt|asin|acos|atan|sin|cos|tan|exp|log|min|max/g;
+ sFormula = sFormula.replace(reMath, 'Math.$&');
+ sFormula = sFormula.replace(/pi(?!\w)/g, 'Math.PI');
+ sFormula = sFormula.replace(/e(?!\w)/g, 'Math.E');
+ sFormula = sFormula.replace(/\$/g, '__PARAM0__');
+
+ var aAnimatedElement = aAnimationNode.getAnimatedElement();
+ var aBBox = aAnimatedElement.getBaseBBox();
+
+ // the following variable are used for evaluating sFormula
+ /* eslint-disable no-unused-vars */
+ var width = aBBox.width / aActivityParamSet.nSlideWidth;
+ var height = aBBox.height / aActivityParamSet.nSlideHeight;
+ var x = ( aBBox.x + aBBox.width / 2 ) / aActivityParamSet.nSlideWidth;
+ var y = ( aBBox.y + aBBox.height / 2 ) / aActivityParamSet.nSlideHeight;
+
+ aActivityParamSet.aFormula = function( __PARAM0__ ) {
+
+ return eval(sFormula);
+ };
+ /* eslint-enable no-unused-vars */
+ }
+
+ aActivityParamSet.aDiscreteTimes = aAnimationNode.getKeyTimes();
+
+ // do we have a value list ?
+ var aValueSet = aAnimationNode.getValues();
+ var nValueSetSize = aValueSet.length;
+
+ if( nValueSetSize != 0 )
+ {
+ // Value list activity
+
+ if( aActivityParamSet.aDiscreteTimes.length == 0 )
+ {
+ for( var i = 0; i < nValueSetSize; ++i )
+ aActivityParamSet.aDiscreteTimes[i].push( i / nValueSetSize );
+ }
+
+ switch( eCalcMode )
+ {
+ case CALC_MODE_DISCRETE:
+ aActivityParamSet.aWakeupEvent =
+ new WakeupEvent( aActivityParamSet.aTimerEventQueue.getTimer(),
+ aActivityParamSet.aActivityQueue );
+
+ return createValueListActivity( aActivityParamSet,
+ aAnimationNode,
+ aAnimation,
+ aInterpolator,
+ DiscreteValueListActivity,
+ bAccumulate,
+ eValueType );
+
+ default:
+ log( 'createActivity: unexpected calculation mode: ' + eCalcMode );
+ // FALLTHROUGH intended
+ case CALC_MODE_PACED :
+ case CALC_MODE_SPLINE :
+ case CALC_MODE_LINEAR:
+ return createValueListActivity( aActivityParamSet,
+ aAnimationNode,
+ aAnimation,
+ aInterpolator,
+ LinearValueListActivity,
+ bAccumulate,
+ eValueType );
+ }
+ }
+ else
+ {
+ // FromToBy activity
+ switch( eCalcMode )
+ {
+ case CALC_MODE_DISCRETE:
+ log( 'createActivity: discrete calculation case not yet implemented' );
+ aActivityParamSet.aWakeupEvent =
+ new WakeupEvent( aActivityParamSet.aTimerEventQueue.getTimer(),
+ aActivityParamSet.aActivityQueue );
+ return createFromToByActivity( aActivityParamSet,
+ aAnimationNode,
+ aAnimation,
+ aInterpolator,
+ DiscreteFromToByActivity,
+ bAccumulate,
+ eValueType );
+
+ default:
+ log( 'createActivity: unexpected calculation mode: ' + eCalcMode );
+ // FALLTHROUGH intended
+ case CALC_MODE_PACED :
+ case CALC_MODE_SPLINE :
+ case CALC_MODE_LINEAR:
+ return createFromToByActivity( aActivityParamSet,
+ aAnimationNode,
+ aAnimation,
+ aInterpolator,
+ LinearFromToByActivity,
+ bAccumulate,
+ eValueType );
+ }
+ }
+}
+
+
+
+
+function createValueListActivity( aActivityParamSet, aAnimationNode, aAnimation,
+ aInterpolator, ClassTemplateInstance, bAccumulate, eValueType )
+{
+ var aAnimatedElement = aAnimationNode.getAnimatedElement();
+ var aOperatorSet = aOperatorSetMap[ eValueType ];
+ assert( aOperatorSet, 'createValueListActivity: no operator set found' );
+
+ var aValueSet = aAnimationNode.getValues();
+
+ var aValueList = [];
+
+ extractAttributeValues( eValueType,
+ aValueList,
+ aValueSet,
+ aAnimatedElement.getBaseBBox(),
+ aActivityParamSet.nSlideWidth,
+ aActivityParamSet.nSlideHeight );
+
+ for( var i = 0; i < aValueList.length; ++i )
+ {
+ ANIMDBG.print( 'createValueListActivity: value[' + i + '] = ' + aValueList[i] );
+ }
+
+ return new ClassTemplateInstance( aValueList, aActivityParamSet, aAnimation,
+ aInterpolator, aOperatorSet, bAccumulate );
+}
+
+
+
+
+function createFromToByActivity( aActivityParamSet, aAnimationNode, aAnimation,
+ aInterpolator, ClassTemplateInstance, bAccumulate, eValueType )
+{
+
+ var aAnimatedElement = aAnimationNode.getAnimatedElement();
+ var aOperatorSet = aOperatorSetMap[ eValueType ];
+ assert( aOperatorSet, 'createFromToByActivity: no operator set found' );
+
+ var aValueSet = [];
+ aValueSet[0] = aAnimationNode.getFromValue();
+ aValueSet[1] = aAnimationNode.getToValue();
+ aValueSet[2] = aAnimationNode.getByValue();
+
+ ANIMDBG.print( 'createFromToByActivity: value type: ' + aValueTypeOutMap[eValueType] +
+ ', aFrom = ' + aValueSet[0] +
+ ', aTo = ' + aValueSet[1] +
+ ', aBy = ' + aValueSet[2] );
+
+ var aValueList = [];
+
+ extractAttributeValues( eValueType,
+ aValueList,
+ aValueSet,
+ aAnimatedElement.getBaseBBox(),
+ aActivityParamSet.nSlideWidth,
+ aActivityParamSet.nSlideHeight );
+
+ ANIMDBG.print( 'createFromToByActivity: ' +
+ ', aFrom = ' + aValueList[0] +
+ ', aTo = ' + aValueList[1] +
+ ', aBy = ' + aValueList[2] );
+
+ return new ClassTemplateInstance( aValueList[0], aValueList[1], aValueList[2],
+ aActivityParamSet, aAnimation,
+ aInterpolator, aOperatorSet, bAccumulate );
+}
+
+
+
+function extractAttributeValues( eValueType, aValueList, aValueSet, aBBox, nSlideWidth, nSlideHeight )
+{
+ var i;
+ switch( eValueType )
+ {
+ case NUMBER_PROPERTY :
+ evalValuesAttribute( aValueList, aValueSet, aBBox, nSlideWidth, nSlideHeight );
+ break;
+ case BOOL_PROPERTY :
+ for( i = 0; i < aValueSet.length; ++i )
+ {
+ var aValue = booleanParser( aValueSet[i] );
+ aValueList.push( aValue );
+ }
+ break;
+ case STRING_PROPERTY :
+ for( i = 0; i < aValueSet.length; ++i )
+ {
+ aValueList.push( aValueSet[i] );
+ }
+ break;
+ case ENUM_PROPERTY :
+ for( i = 0; i < aValueSet.length; ++i )
+ {
+ aValueList.push( aValueSet[i] );
+ }
+ break;
+ case COLOR_PROPERTY :
+ for( i = 0; i < aValueSet.length; ++i )
+ {
+ aValue = colorParser( aValueSet[i] );
+ aValueList.push( aValue );
+ }
+ break;
+ case TUPLE_NUMBER_PROPERTY :
+ for( i = 0; i < aValueSet.length; ++i )
+ {
+ if( typeof aValueSet[i] === 'string' )
+ {
+ var aTuple = aValueSet[i].split(',');
+ aValue = [];
+ evalValuesAttribute(aValue, aTuple, aBBox, nSlideWidth, nSlideHeight);
+ aValueList.push(aValue);
+ }
+ else
+ {
+ aValueList.push( undefined );
+ }
+ }
+ break;
+ default:
+ log( 'createValueListActivity: unexpected value type: ' + eValueType );
+ }
+
+}
+
+
+function evalValuesAttribute( aValueList, aValueSet, aBBox, nSlideWidth, nSlideHeight )
+{
+ // the following variables are used for evaluating sValue later
+ /* eslint-disable no-unused-vars */
+ var width = aBBox.width / nSlideWidth;
+ var height = aBBox.height / nSlideHeight;
+ var x = ( aBBox.x + aBBox.width / 2 ) / nSlideWidth;
+ var y = ( aBBox.y + aBBox.height / 2 ) / nSlideHeight;
+ /* eslint-enable no-unused-vars */
+
+ var reMath = /abs|sqrt|asin|acos|atan|sin|cos|tan|exp|log|min|max/g;
+
+ for( var i = 0; i < aValueSet.length; ++i )
+ {
+ var sValue = aValueSet[i];
+ if(sValue)
+ {
+ sValue = sValue.replace(reMath, 'Math.$&');
+ sValue = sValue.replace(/pi(?!\w)/g, 'Math.PI');
+ sValue = sValue.replace(/e(?!\w)/g, 'Math.E');
+ }
+ var aValue = eval( sValue );
+ aValueList.push( aValue );
+ }
+}
+
+
+
+/**********************************************************************************************
+ * SlideShow, SlideShowContext and FrameSynchronization
+ **********************************************************************************************/
+
+
+
+// direction of animation, important: not change the values!
+var BACKWARD = 0;
+var FORWARD = 1;
+
+var MAXIMUM_FRAME_COUNT = 60;
+var MINIMUM_TIMEOUT = 1.0 / MAXIMUM_FRAME_COUNT;
+var MAXIMUM_TIMEOUT = 4.0;
+var MINIMUM_FRAMES_PER_SECONDS = 10;
+var PREFERRED_FRAMES_PER_SECONDS = 50;
+var PREFERRED_FRAME_RATE = 1.0 / PREFERRED_FRAMES_PER_SECONDS;
+
+
+function Effect( nId )
+{
+ this.nId = ( typeof( nId ) === typeof( 1 ) ) ? nId : -1;
+ this.eState = Effect.NOT_STARTED;
+}
+Effect.NOT_STARTED = 0;
+Effect.PLAYING = 1;
+Effect.ENDED = 2;
+
+Effect.prototype.getId = function()
+{
+ return this.nId;
+};
+
+Effect.prototype.isMainEffect = function()
+{
+ return ( this.nId === -1 );
+};
+
+Effect.prototype.isPlaying = function()
+{
+ return ( this.eState === Effect.PLAYING );
+};
+
+Effect.prototype.isEnded = function()
+{
+ return ( this.eState === Effect.ENDED );
+};
+
+Effect.prototype.start = function()
+{
+ assert( this.eState === Effect.NOT_STARTED, 'Effect.start: wrong state.' );
+ this.eState = Effect.PLAYING;
+};
+
+Effect.prototype.end = function()
+{
+ assert( this.eState === Effect.PLAYING, 'Effect.end: wrong state.' );
+ this.eState = Effect.ENDED;
+};
+
+
+
+function SlideShow()
+{
+ this.aTimer = new ElapsedTime();
+ this.aFrameSynchronization = new FrameSynchronization( PREFERRED_FRAME_RATE );
+ this.aTimerEventQueue = new TimerEventQueue( this.aTimer );
+ this.aActivityQueue = new ActivityQueue( this.aTimer );
+ this.aNextEffectEventArray = null;
+ this.aInteractiveAnimationSequenceMap = null;
+ this.aEventMultiplexer = null;
+
+ this.aContext = new SlideShowContext( this.aTimerEventQueue,
+ this.aEventMultiplexer,
+ this.aNextEffectEventArray,
+ this.aInteractiveAnimationSequenceMap,
+ this.aActivityQueue );
+ this.bIsIdle = true;
+ this.bIsEnabled = true;
+ this.bNoSlideTransition = false;
+ this.bIsTransitionRunning = false;
+
+ this.nCurrentEffect = 0;
+ this.bIsNextEffectRunning = false;
+ this.bIsRewinding = false;
+ this.bIsSkipping = false;
+ this.bIsSkippingAll = false;
+ this.nTotalInteractivePlayingEffects = 0;
+ this.aStartedEffectList = [];
+ this.aStartedEffectIndexMap = {};
+ this.aStartedEffectIndexMap[ -1 ] = undefined;
+ this.automaticAdvanceTimeout = null;
+}
+
+SlideShow.prototype.setSlideEvents = function( aNextEffectEventArray,
+ aInteractiveAnimationSequenceMap,
+ aEventMultiplexer )
+{
+ if( !aNextEffectEventArray )
+ log( 'SlideShow.setSlideEvents: aNextEffectEventArray is not valid' );
+
+ if( !aInteractiveAnimationSequenceMap )
+ log( 'SlideShow.setSlideEvents:aInteractiveAnimationSequenceMap is not valid' );
+
+ if( !aEventMultiplexer )
+ log( 'SlideShow.setSlideEvents: aEventMultiplexer is not valid' );
+
+ this.aContext.aNextEffectEventArray = aNextEffectEventArray;
+ this.aNextEffectEventArray = aNextEffectEventArray;
+ this.aContext.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap;
+ this.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap;
+ this.aContext.aEventMultiplexer = aEventMultiplexer;
+ this.aEventMultiplexer = aEventMultiplexer;
+ this.nCurrentEffect = 0;
+};
+
+SlideShow.prototype.createSlideTransition = function( aSlideTransitionHandler, aLeavingSlide, aEnteringSlide, aTransitionEndEvent )
+{
+ if( !aEnteringSlide )
+ {
+ log( 'SlideShow.createSlideTransition: entering slide element is not valid.' );
+ return null;
+ }
+
+ if( this.bNoSlideTransition ) return null;
+
+ var aAnimatedLeavingSlide = null;
+ if( aLeavingSlide )
+ aAnimatedLeavingSlide = new AnimatedSlide( aLeavingSlide );
+ var aAnimatedEnteringSlide = new AnimatedSlide( aEnteringSlide );
+
+ var aSlideTransition = aSlideTransitionHandler.createSlideTransition( aAnimatedLeavingSlide, aAnimatedEnteringSlide );
+ if( !aSlideTransition ) return null;
+
+ // compute duration
+ var nDuration = 0.001;
+ if( aSlideTransitionHandler.getDuration().isValue() )
+ {
+ nDuration = aSlideTransitionHandler.getDuration().getValue();
+ }
+ else
+ {
+ log( 'SlideShow.createSlideTransition: duration is not a number' );
+ }
+
+ var aCommonParameterSet = new ActivityParamSet();
+ aCommonParameterSet.aEndEvent = aTransitionEndEvent;
+ aCommonParameterSet.aTimerEventQueue = this.aTimerEventQueue;
+ aCommonParameterSet.aActivityQueue = this.aActivityQueue;
+ aCommonParameterSet.nMinDuration = nDuration;
+ aCommonParameterSet.nMinNumberOfFrames = aSlideTransitionHandler.getMinFrameCount();
+ aCommonParameterSet.nSlideWidth = WIDTH;
+ aCommonParameterSet.nSlideHeight = HEIGHT;
+
+ return new SimpleActivity( aCommonParameterSet, aSlideTransition, FORWARD );
+
+};
+
+SlideShow.prototype.isEnabled = function()
+{
+ return this.bIsEnabled;
+};
+
+SlideShow.prototype.isRunning = function()
+{
+ return !this.bIsIdle;
+};
+
+SlideShow.prototype.isTransitionPlaying = function()
+{
+ return this.bIsTransitionRunning;
+};
+
+SlideShow.prototype.isMainEffectPlaying = function()
+{
+ return this.bIsNextEffectRunning;
+};
+
+SlideShow.prototype.isInteractiveEffectPlaying = function()
+{
+ return ( this.nTotalInteractivePlayingEffects > 0 );
+};
+
+SlideShow.prototype.isAnyEffectPlaying = function()
+{
+ return ( this.isMainEffectPlaying() || this.isInteractiveEffectPlaying() );
+};
+
+SlideShow.prototype.hasAnyEffectStarted = function()
+{
+ return ( this.aStartedEffectList.length > 0 );
+};
+
+SlideShow.prototype.notifyNextEffectStart = function()
+{
+ assert( !this.bIsNextEffectRunning,
+ 'SlideShow.notifyNextEffectStart: an effect is already started.' );
+ this.bIsNextEffectRunning = true;
+ this.aEventMultiplexer.registerNextEffectEndHandler( bind2( SlideShow.prototype.notifyNextEffectEnd, this ) );
+ var aEffect = new Effect();
+ aEffect.start();
+ this.aStartedEffectIndexMap[ -1 ] = this.aStartedEffectList.length;
+ this.aStartedEffectList.push( aEffect );
+
+ var aAnimatedElementMap = theMetaDoc.aMetaSlideSet[nCurSlide].aSlideAnimationsHandler.aAnimatedElementMap;
+ for( var sId in aAnimatedElementMap )
+ aAnimatedElementMap[ sId ].notifyNextEffectStart( this.nCurrentEffect );
+};
+
+SlideShow.prototype.notifyNextEffectEnd = function()
+{
+ assert( this.bIsNextEffectRunning,
+ 'SlideShow.notifyNextEffectEnd: effect already ended.' );
+ this.bIsNextEffectRunning = false;
+
+ this.aStartedEffectList[ this.aStartedEffectIndexMap[ -1 ] ].end();
+ if( this.automaticAdvanceTimeout !== null )
+ {
+ if( this.automaticAdvanceTimeout['rewindedEffect'] === this.nCurrentEffect )
+ {
+ this.automaticAdvanceTimeout = null;
+ this.notifyAnimationsEnd();
+ }
+ }
+};
+
+SlideShow.prototype.notifyAnimationsEnd = function()
+{
+ if( nCurSlide + 1 === theMetaDoc.nNumberOfSlides )
+ return;
+
+ assert (this.automaticAdvanceTimeout === null,
+ 'SlideShow.notifyAnimationsEnd: Timeout already set.')
+
+ var nTimeout = Math.ceil(theMetaDoc.aMetaSlideSet[nCurSlide].fDuration * 1000);
+ if( nTimeout < 0 )
+ return;
+
+ this.automaticAdvanceTimeout = window.setTimeout('switchSlide(1, false)', nTimeout);
+};
+
+SlideShow.prototype.notifySlideStart = function( nNewSlideIndex, nOldSlideIndex )
+{
+ this.nCurrentEffect = 0;
+ this.bIsRewinding = false;
+ this.bIsSkipping = false;
+ this.bIsSkippingAll = false;
+ this.nTotalInteractivePlayingEffects = 0;
+ this.aStartedEffectList = [];
+ this.aStartedEffectIndexMap = {};
+ this.aStartedEffectIndexMap[ -1 ] = undefined;
+
+ var aAnimatedElementMap;
+ var sId;
+ if( nOldSlideIndex !== undefined )
+ {
+ aAnimatedElementMap = theMetaDoc.aMetaSlideSet[nOldSlideIndex].aSlideAnimationsHandler.aAnimatedElementMap;
+ for( sId in aAnimatedElementMap )
+ aAnimatedElementMap[ sId ].notifySlideEnd();
+ }
+
+ aAnimatedElementMap = theMetaDoc.aMetaSlideSet[nNewSlideIndex].aSlideAnimationsHandler.aAnimatedElementMap;
+ for( sId in aAnimatedElementMap )
+ aAnimatedElementMap[ sId ].notifySlideStart( this.aContext );
+};
+
+SlideShow.prototype.notifyTransitionEnd = function( nSlideIndex )
+{
+ // reset the presentation clip path on the leaving slide
+ // to the standard one when transition ends
+ if( theMetaDoc.getCurrentSlide() )
+ {
+ var sRef = 'url(#' + aPresentationClipPathId + ')';
+ theMetaDoc.getCurrentSlide().slideElement.setAttribute('clip-path', sRef);
+ }
+
+ this.bIsTransitionRunning = false;
+ if( this.bIsRewinding )
+ {
+ theMetaDoc.aMetaSlideSet[nSlideIndex].hide();
+ var nIndex = nCurSlide !== undefined ? nCurSlide : -1;
+ this.displaySlide( nIndex, true );
+ this.skipAllEffects();
+ this.bIsRewinding = false;
+ return;
+ }
+
+ theMetaDoc.setCurrentSlide(nSlideIndex);
+
+ if( this.aSlideViewElement )
+ {
+ theMetaDoc.getCurrentSlide().aVisibilityStatusElement.parentNode.removeChild( this.aSlideViewElement );
+ this.aSlideViewElement = null;
+ }
+ if( this.isEnabled() )
+ {
+ // clear all queues
+ this.dispose();
+
+ var aCurrentSlide = theMetaDoc.getCurrentSlide();
+ if( aCurrentSlide.aSlideAnimationsHandler.elementsParsed() )
+ {
+ aCurrentSlide.aSlideAnimationsHandler.start();
+ this.aEventMultiplexer.registerAnimationsEndHandler( bind2( SlideShow.prototype.notifyAnimationsEnd, this ) );
+ }
+ else
+ this.notifyAnimationsEnd();
+
+ this.update();
+ }
+ else
+ this.notifyAnimationsEnd();
+};
+
+SlideShow.prototype.notifyInteractiveAnimationSequenceStart = function( nNodeId )
+{
+ ++this.nTotalInteractivePlayingEffects;
+ var aEffect = new Effect( nNodeId );
+ aEffect.start();
+ this.aStartedEffectIndexMap[ nNodeId ] = this.aStartedEffectList.length;
+ this.aStartedEffectList.push( aEffect );
+};
+
+SlideShow.prototype.notifyInteractiveAnimationSequenceEnd = function( nNodeId )
+{
+ assert( this.isInteractiveEffectPlaying(),
+ 'SlideShow.notifyInteractiveAnimationSequenceEnd: no interactive effect playing.' );
+
+ this.aStartedEffectList[ this.aStartedEffectIndexMap[ nNodeId ] ].end();
+ --this.nTotalInteractivePlayingEffects;
+};
+
+/** nextEffect
+ * Start the next effect belonging to the main animation sequence if any.
+ * If there is an already playing effect belonging to any animation sequence
+ * it is skipped.
+ *
+ * @return {Boolean}
+ * False if there is no more effect to start, true otherwise.
+ */
+SlideShow.prototype.nextEffect = function()
+{
+ if( !this.isEnabled() )
+ return false;
+
+ if( this.isTransitionPlaying() )
+ {
+ this.skipTransition();
+ return true;
+ }
+
+ if( this.isAnyEffectPlaying() )
+ {
+ this.skipAllPlayingEffects();
+ return true;
+ }
+
+ if( !this.aNextEffectEventArray )
+ return false;
+
+ if( this.nCurrentEffect >= this.aNextEffectEventArray.size() )
+ return false;
+
+ this.notifyNextEffectStart();
+
+ this.aNextEffectEventArray.at( this.nCurrentEffect ).fire();
+ ++this.nCurrentEffect;
+ this.update();
+ return true;
+};
+
+/** skipTransition
+ * Skip the current playing slide transition.
+ */
+SlideShow.prototype.skipTransition = function()
+{
+ if( this.bIsSkipping || this.bIsRewinding )
+ return;
+
+ this.bIsSkipping = true;
+
+ this.aActivityQueue.endAll();
+ this.aTimerEventQueue.forceEmpty();
+ this.aActivityQueue.endAll();
+ this.update();
+ this.bIsSkipping = false;
+};
+
+/** skipAllPlayingEffects
+ * Skip all playing effect, independently to which animation sequence they
+ * belong.
+ *
+ */
+SlideShow.prototype.skipAllPlayingEffects = function()
+{
+ if( this.bIsSkipping || this.bIsRewinding )
+ return true;
+
+ this.bIsSkipping = true;
+ // TODO: The correct order should be based on the left playing time.
+ for( var i = 0; i < this.aStartedEffectList.length; ++i )
+ {
+ var aEffect = this.aStartedEffectList[i];
+ if( aEffect.isPlaying() )
+ {
+ if( aEffect.isMainEffect() )
+ this.aEventMultiplexer.notifySkipEffectEvent();
+ else
+ this.aEventMultiplexer.notifySkipInteractiveEffectEvent( aEffect.getId() );
+ }
+ }
+ this.update();
+ this.bIsSkipping = false;
+ return true;
+};
+
+/** skipNextEffect
+ * Skip the next effect to be played (if any) that belongs to the main
+ * animation sequence.
+ * Require: no effect is playing.
+ *
+ * @return {Boolean}
+ * False if there is no more effect to skip, true otherwise.
+ */
+SlideShow.prototype.skipNextEffect = function()
+{
+ if( this.bIsSkipping || this.bIsRewinding )
+ return true;
+
+ assert( !this.isAnyEffectPlaying(),
+ 'SlideShow.skipNextEffect' );
+
+ if( !this.aNextEffectEventArray )
+ return false;
+
+ if( this.nCurrentEffect >= this.aNextEffectEventArray.size() )
+ return false;
+
+ this.notifyNextEffectStart();
+
+ this.bIsSkipping = true;
+ this.aNextEffectEventArray.at( this.nCurrentEffect ).fire();
+ this.aEventMultiplexer.notifySkipEffectEvent();
+ ++this.nCurrentEffect;
+ this.update();
+ this.bIsSkipping = false;
+ return true;
+};
+
+/** skipPlayingOrNextEffect
+ * Skip the next effect to be played that belongs to the main animation
+ * sequence or all playing effects.
+ *
+ * @return {Boolean}
+ * False if there is no more effect to skip, true otherwise.
+ */
+SlideShow.prototype.skipPlayingOrNextEffect = function()
+{
+ if( this.isTransitionPlaying() )
+ {
+ this.skipTransition();
+ return true;
+ }
+
+ if( this.isAnyEffectPlaying() )
+ return this.skipAllPlayingEffects();
+ else
+ return this.skipNextEffect();
+};
+
+
+/** skipAllEffects
+ * Skip all left effects that belongs to the main animation sequence and all
+ * playing effects on the current slide.
+ *
+ * @return {Boolean}
+ * True if it already skipping or when it has ended skipping,
+ * false if the next slide needs to be displayed.
+ */
+SlideShow.prototype.skipAllEffects = function()
+{
+ if( this.bIsSkippingAll )
+ return true;
+
+ this.bIsSkippingAll = true;
+
+ if( this.isTransitionPlaying() )
+ {
+ this.skipTransition();
+ }
+
+ if( this.isAnyEffectPlaying() )
+ {
+ this.skipAllPlayingEffects();
+ }
+ else if( !this.aNextEffectEventArray
+ || ( this.nCurrentEffect >= this.aNextEffectEventArray.size() ) )
+ {
+ this.bIsSkippingAll = false;
+ return false;
+ }
+
+ // Pay attention here: a new next effect event is appended to
+ // aNextEffectEventArray only after the related animation node has been
+ // resolved, that is only after the animation node related to the previous
+ // effect has notified to be deactivated to the main sequence time container.
+ // So you should avoid any optimization here because the size of
+ // aNextEffectEventArray will going on increasing after every skip action.
+ while( this.nCurrentEffect < this.aNextEffectEventArray.size() )
+ {
+ this.skipNextEffect();
+ }
+ this.bIsSkippingAll = false;
+ return true;
+};
+
+/** rewindTransition
+ * Rewind the current playing slide transition.
+ */
+SlideShow.prototype.rewindTransition = function()
+{
+ if( this.bIsSkipping || this.bIsRewinding )
+ return;
+
+ this.bIsRewinding = true;
+ this.aActivityQueue.endAll();
+ this.update();
+ this.bIsRewinding = false;
+};
+
+/** rewindEffect
+ * Rewind all the effects started after at least one of the current playing
+ * effects. If there is no playing effect, it rewinds the last played one,
+ * both in case it belongs to the main or to an interactive animation sequence.
+ *
+ */
+SlideShow.prototype.rewindEffect = function()
+{
+ if( this.bIsSkipping || this.bIsRewinding )
+ return;
+
+ if( this.automaticAdvanceTimeout !== null && !this.automaticAdvanceTimeout['rewindedEffect'] )
+ {
+ window.clearTimeout( this.automaticAdvanceTimeout );
+ this.automaticAdvanceTimeout = { 'rewindedEffect': this.nCurrentEffect };
+ }
+
+ if( !this.hasAnyEffectStarted() )
+ {
+ this.rewindToPreviousSlide();
+ return;
+ }
+
+ this.bIsRewinding = true;
+
+ var nFirstPlayingEffectIndex = undefined;
+
+ var i = 0;
+ for( ; i < this.aStartedEffectList.length; ++i )
+ {
+ var aEffect = this.aStartedEffectList[i];
+ if( aEffect.isPlaying() )
+ {
+ nFirstPlayingEffectIndex = i;
+ break;
+ }
+ }
+
+ // There is at least one playing effect.
+ if( nFirstPlayingEffectIndex !== undefined )
+ {
+ i = this.aStartedEffectList.length - 1;
+ for( ; i >= nFirstPlayingEffectIndex; --i )
+ {
+ aEffect = this.aStartedEffectList[i];
+ if( aEffect.isPlaying() )
+ {
+ if( aEffect.isMainEffect() )
+ {
+ this.aEventMultiplexer.notifyRewindCurrentEffectEvent();
+ if( this.nCurrentEffect > 0 )
+ --this.nCurrentEffect;
+ }
+ else
+ {
+ this.aEventMultiplexer.notifyRewindRunningInteractiveEffectEvent( aEffect.getId() );
+ }
+ }
+ else if( aEffect.isEnded() )
+ {
+ if( aEffect.isMainEffect() )
+ {
+ this.aEventMultiplexer.notifyRewindLastEffectEvent();
+ if( this.nCurrentEffect > 0 )
+ --this.nCurrentEffect;
+ }
+ else
+ {
+ this.aEventMultiplexer.notifyRewindEndedInteractiveEffectEvent( aEffect.getId() );
+ }
+ }
+ }
+ this.update();
+
+ // Pay attention here: we need to remove all rewinded effects from
+ // the started effect list only after updating.
+ i = this.aStartedEffectList.length - 1;
+ for( ; i >= nFirstPlayingEffectIndex; --i )
+ {
+ aEffect = this.aStartedEffectList.pop();
+ if( !aEffect.isMainEffect() )
+ delete this.aStartedEffectIndexMap[ aEffect.getId() ];
+ }
+ }
+ else // there is no playing effect
+ {
+ aEffect = this.aStartedEffectList.pop();
+ if( !aEffect.isMainEffect() )
+ delete this.aStartedEffectIndexMap[ aEffect.getId() ];
+ if( aEffect.isEnded() ) // Well that is almost an assertion.
+ {
+ if( aEffect.isMainEffect() )
+ {
+ this.aEventMultiplexer.notifyRewindLastEffectEvent();
+ if( this.nCurrentEffect > 0 )
+ --this.nCurrentEffect;
+ }
+ else
+ {
+ this.aEventMultiplexer.notifyRewindEndedInteractiveEffectEvent( aEffect.getId() );
+ }
+ }
+ this.update();
+ }
+
+ this.bIsRewinding = false;
+};
+
+/** rewindToPreviousSlide
+ * Displays the previous slide with all effects, that belong to the main
+ * animation sequence, played.
+ *
+ */
+SlideShow.prototype.rewindToPreviousSlide = function()
+{
+ if( this.isTransitionPlaying() )
+ {
+ this.rewindTransition();
+ return;
+ }
+ if( this.isAnyEffectPlaying() )
+ return;
+ var nNewSlide = nCurSlide - 1;
+ this.displaySlide( nNewSlide, true );
+ this.skipAllEffects();
+};
+
+/** rewindAllEffects
+ * Rewind all effects already played on the current slide.
+ *
+ */
+SlideShow.prototype.rewindAllEffects = function()
+{
+ if( !this.hasAnyEffectStarted() )
+ {
+ this.rewindToPreviousSlide();
+ return;
+ }
+
+ while( this.hasAnyEffectStarted() )
+ {
+ this.rewindEffect();
+ }
+};
+
+SlideShow.prototype.exitSlideShowInApp = function()
+{
+ if (window.webkit !== undefined &&
+ window.webkit.messageHandlers !== undefined &&
+ window.webkit.messageHandlers.cool !== undefined)
+ window.webkit.messageHandlers.cool.postMessage('EXITSLIDESHOW', '*');
+}
+
+SlideShow.prototype.displaySlide = function( nNewSlide, bSkipSlideTransition )
+{
+ var aMetaDoc = theMetaDoc;
+ var nSlides = aMetaDoc.nNumberOfSlides;
+ if( nNewSlide < 0 && nSlides > 0 )
+ nNewSlide = nSlides - 1;
+ else if( nNewSlide >= nSlides ) {
+ nNewSlide = 0;
+ // In the iOS app, exit the slideshow when going past the end.
+ this.exitSlideShowInApp();
+ }
+
+ if( ( currentMode === INDEX_MODE ) && ( nNewSlide === nCurSlide ) )
+ {
+ aMetaDoc.getCurrentSlide().show();
+ return;
+ }
+
+ if( this.isTransitionPlaying() )
+ {
+ this.skipTransition();
+ }
+
+ // handle current slide
+ var nOldSlide = nCurSlide;
+ if( nOldSlide !== undefined )
+ {
+ var oldMetaSlide = aMetaDoc.aMetaSlideSet[nOldSlide];
+ if( this.isEnabled() )
+ {
+ if( oldMetaSlide.aSlideAnimationsHandler.isAnimated() )
+ {
+ // force end animations
+ oldMetaSlide.aSlideAnimationsHandler.end( bSkipSlideTransition );
+
+ // clear all queues
+ this.dispose();
+ }
+ }
+
+ if( this.automaticAdvanceTimeout !== null )
+ {
+ window.clearTimeout( this.automaticAdvanceTimeout );
+ this.automaticAdvanceTimeout = null;
+ }
+ }
+
+ this.notifySlideStart( nNewSlide, nOldSlide );
+
+ if( this.isEnabled() && !bSkipSlideTransition )
+ {
+ // create slide transition and add to activity queue
+ if ( ( ( nOldSlide !== undefined ) &&
+ ( ( nNewSlide > nOldSlide ) ||
+ ( ( nNewSlide == 0) && ( nOldSlide == (aMetaDoc.nNumberOfSlides - 1) ) ) ) ) ||
+ ( ( nOldSlide === undefined ) && ( nNewSlide == 0) ) // for transition on first slide
+ )
+ {
+
+ var aOldMetaSlide = null;
+ if( nOldSlide === undefined ) // for transition on first slide
+ {
+ aOldMetaSlide = aMetaDoc.theMetaDummySlide;
+ }
+ else
+ {
+ aOldMetaSlide = aMetaDoc.aMetaSlideSet[nOldSlide];
+ }
+ var aNewMetaSlide = aMetaDoc.aMetaSlideSet[nNewSlide];
+
+ var aSlideTransitionHandler = aNewMetaSlide.aTransitionHandler;
+ if( aSlideTransitionHandler && aSlideTransitionHandler.isValid() )
+ {
+ // clipPath element used for the leaving slide in order
+ // to avoid that slide borders are visible during transition
+ var sRef = 'url(#' + aPresentationClipPathShrinkId + ')';
+ aOldMetaSlide.slideElement.setAttribute( 'clip-path', sRef );
+
+ // when we switch from the last to the first slide we need to hide the last slide
+ // or nobody will see the transition, hence we create a view of the last slide and
+ // we place it before the first slide
+ if( nOldSlide > nNewSlide )
+ {
+ this.aSlideViewElement = document.createElementNS( NSS['svg'], 'use' );
+ setNSAttribute( 'xlink', this.aSlideViewElement, 'href', '#' + aOldMetaSlide.slideContainerId );
+ aNewMetaSlide.aVisibilityStatusElement.parentNode.insertBefore( this.aSlideViewElement, aNewMetaSlide.aVisibilityStatusElement );
+ aOldMetaSlide.hide();
+ }
+
+ var aLeavingSlide = aOldMetaSlide;
+ var aEnteringSlide = aNewMetaSlide;
+ var aTransitionEndEvent = makeEvent( bind2( this.notifyTransitionEnd, this, nNewSlide ) );
+
+ var aTransitionActivity =
+ this.createSlideTransition( aSlideTransitionHandler, aLeavingSlide,
+ aEnteringSlide, aTransitionEndEvent );
+
+ if( aTransitionActivity )
+ {
+ this.bIsTransitionRunning = true;
+ this.aActivityQueue.addActivity( aTransitionActivity );
+ this.update();
+ }
+ else
+ {
+ this.notifyTransitionEnd( nNewSlide );
+ }
+ }
+ else
+ {
+ this.notifyTransitionEnd( nNewSlide );
+ }
+ }
+ else
+ {
+ this.notifyTransitionEnd( nNewSlide );
+ }
+ }
+ else
+ {
+ this.notifyTransitionEnd( nNewSlide );
+ }
+
+};
+
+SlideShow.prototype.update = function()
+{
+ this.aTimer.holdTimer();
+
+ // process queues
+ this.aTimerEventQueue.process();
+ this.aActivityQueue.process();
+
+ this.aFrameSynchronization.synchronize();
+
+ this.aActivityQueue.processDequeued();
+
+ this.aTimer.releaseTimer();
+
+ var bActivitiesLeft = ( ! this.aActivityQueue.isEmpty() );
+ var bTimerEventsLeft = ( ! this.aTimerEventQueue.isEmpty() );
+ var bEventsLeft = ( bActivitiesLeft || bTimerEventsLeft );
+
+
+ if( bEventsLeft )
+ {
+ var nNextTimeout;
+ if( bActivitiesLeft )
+ {
+ nNextTimeout = MINIMUM_TIMEOUT;
+ this.aFrameSynchronization.activate();
+ }
+ else
+ {
+ nNextTimeout = this.aTimerEventQueue.nextTimeout();
+ if( nNextTimeout < MINIMUM_TIMEOUT )
+ nNextTimeout = MINIMUM_TIMEOUT;
+ else if( nNextTimeout > MAXIMUM_TIMEOUT )
+ nNextTimeout = MAXIMUM_TIMEOUT;
+ this.aFrameSynchronization.deactivate();
+ }
+
+ this.bIsIdle = false;
+ window.setTimeout( 'aSlideShow.update()', nNextTimeout * 1000 );
+ }
+ else
+ {
+ this.bIsIdle = true;
+ }
+};
+
+SlideShow.prototype.dispose = function()
+{
+ // clear all queues
+ this.aTimerEventQueue.clear();
+ this.aActivityQueue.clear();
+ this.aNextEffectEventArray = null;
+ this.aEventMultiplexer = null;
+};
+
+SlideShow.prototype.getContext = function()
+{
+ return this.aContext;
+};
+
+// the SlideShow global instance
+var aSlideShow = null;
+
+
+
+
+function SlideShowContext( aTimerEventQueue, aEventMultiplexer, aNextEffectEventArray, aInteractiveAnimationSequenceMap, aActivityQueue)
+{
+ this.aTimerEventQueue = aTimerEventQueue;
+ this.aEventMultiplexer = aEventMultiplexer;
+ this.aNextEffectEventArray = aNextEffectEventArray;
+ this.aInteractiveAnimationSequenceMap = aInteractiveAnimationSequenceMap;
+ this.aActivityQueue = aActivityQueue;
+ this.bIsSkipping = false;
+}
+
+
+
+
+function FrameSynchronization( nFrameDuration )
+{
+ this.nFrameDuration = nFrameDuration;
+ this.aTimer = new ElapsedTime();
+ this.nNextFrameTargetTime = 0.0;
+ this.bIsActive = false;
+
+ this.markCurrentFrame();
+}
+
+
+FrameSynchronization.prototype.markCurrentFrame = function()
+{
+ this.nNextFrameTargetTime = this.aTimer.getElapsedTime() + this.nFrameDuration;
+};
+
+FrameSynchronization.prototype.synchronize = function()
+{
+ if( this.bIsActive )
+ {
+ // Do busy waiting for now.
+ while( this.aTimer.getElapsedTime() < this.nNextFrameTargetTime )
+ ;
+ }
+
+ this.markCurrentFrame();
+
+};
+
+FrameSynchronization.prototype.activate = function()
+{
+ this.bIsActive = true;
+};
+
+FrameSynchronization.prototype.deactivate = function()
+{
+ this.bIsActive = false;
+};
+
+
+
+/**********************************************************************************************
+ * TimerEventQueue, ActivityQueue and ElapsedTime
+ **********************************************************************************************/
+
+
+function NextEffectEventArray()
+{
+ this.aEventArray = [];
+}
+
+
+NextEffectEventArray.prototype.size = function()
+{
+ return this.aEventArray.length;
+};
+
+NextEffectEventArray.prototype.at = function( nIndex )
+{
+ return this.aEventArray[ nIndex ];
+};
+
+NextEffectEventArray.prototype.appendEvent = function( aEvent )
+{
+ var nSize = this.size();
+ for( var i = 0; i < nSize; ++i )
+ {
+ if( this.aEventArray[i].getId() == aEvent.getId() )
+ {
+ aNextEffectEventArrayDebugPrinter.print( 'NextEffectEventArray.appendEvent: event(' + aEvent.getId() + ') already present' );
+ return false;
+ }
+ }
+ this.aEventArray.push( aEvent );
+ aNextEffectEventArrayDebugPrinter.print( 'NextEffectEventArray.appendEvent: event(' + aEvent.getId() + ') appended' );
+ return true;
+};
+
+NextEffectEventArray.prototype.clear = function( )
+{
+ this.aEventArray = [];
+};
+
+
+
+
+function TimerEventQueue( aTimer )
+{
+ this.aTimer = aTimer;
+ this.aEventSet = new PriorityQueue( EventEntry.compare );
+}
+
+
+TimerEventQueue.prototype.addEvent = function( aEvent )
+{
+ this.DBG( 'TimerEventQueue.addEvent event(' + aEvent.getId() + ') appended.' );
+ if( !aEvent )
+ {
+ log( 'TimerEventQueue.addEvent: null event' );
+ return false;
+ }
+
+ var nTime = aEvent.getActivationTime( this.aTimer.getElapsedTime() );
+ var aEventEntry = new EventEntry( aEvent, nTime );
+ this.aEventSet.push( aEventEntry );
+
+ return true;
+};
+
+TimerEventQueue.prototype.forceEmpty = function()
+{
+ this.process_(true);
+};
+
+
+TimerEventQueue.prototype.process = function()
+{
+ this.process_(false);
+};
+
+TimerEventQueue.prototype.process_ = function( bFireAllEvents )
+{
+ var nCurrentTime = this.aTimer.getElapsedTime();
+
+ while( !this.isEmpty() && ( bFireAllEvents || ( this.aEventSet.top().nActivationTime <= nCurrentTime ) ) )
+ {
+ var aEventEntry = this.aEventSet.top();
+ this.aEventSet.pop();
+
+ var aEvent = aEventEntry.aEvent;
+ if( aEvent.isCharged() )
+ aEvent.fire();
+ }
+};
+
+TimerEventQueue.prototype.isEmpty = function()
+{
+ return this.aEventSet.isEmpty();
+};
+
+TimerEventQueue.prototype.nextTimeout = function()
+{
+ var nTimeout = Number.MAX_VALUE;
+ var nCurrentTime = this.aTimer.getElapsedTime();
+ if( !this.isEmpty() )
+ nTimeout = this.aEventSet.top().nActivationTime - nCurrentTime;
+ return nTimeout;
+};
+
+TimerEventQueue.prototype.clear = function()
+{
+ this.DBG( 'TimerEventQueue.clear invoked' );
+ this.aEventSet.clear();
+};
+
+TimerEventQueue.prototype.getTimer = function()
+{
+ return this.aTimer;
+};
+
+TimerEventQueue.prototype.DBG = function( sMessage, nTime )
+{
+ aTimerEventQueueDebugPrinter.print( sMessage, nTime );
+};
+
+
+TimerEventQueue.prototype.insert = function( aEventEntry )
+{
+ var nHoleIndex = this.aEventSet.length;
+ var nParent = Math.floor( ( nHoleIndex - 1 ) / 2 );
+
+ while( ( nHoleIndex > 0 ) && this.aEventSet[ nParent ].compare( aEventEntry ) )
+ {
+ this.aEventSet[ nHoleIndex ] = this.aEventSet[ nParent ];
+ nHoleIndex = nParent;
+ nParent = Math.floor( ( nHoleIndex - 1 ) / 2 );
+ }
+ this.aEventSet[ nHoleIndex ] = aEventEntry;
+};
+
+
+
+
+function EventEntry( aEvent, nTime )
+{
+ this.aEvent = aEvent;
+ this.nActivationTime = nTime;
+}
+
+
+EventEntry.compare = function( aLhsEventEntry, aRhsEventEntry )
+{
+ if ( aLhsEventEntry.nActivationTime > aRhsEventEntry.nActivationTime )
+ {
+ return -1;
+ }
+ else if ( aLhsEventEntry.nActivationTime < aRhsEventEntry.nActivationTime )
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+};
+
+
+
+
+function ActivityQueue( aTimer )
+{
+ this.aTimer = aTimer;
+ this.aCurrentActivityWaitingSet = [];
+ this.aCurrentActivityReinsertSet = [];
+ this.aDequeuedActivitySet = [];
+}
+
+
+ActivityQueue.prototype.dispose = function()
+{
+ var nSize = this.aCurrentActivityWaitingSet.length;
+ var i;
+ for( i = 0; i < nSize; ++i )
+ this.aCurrentActivityWaitingSet[i].dispose();
+
+ nSize = this.aCurrentActivityReinsertSet.length;
+ for( i = 0; i < nSize; ++i )
+ this.aCurrentActivityReinsertSet[i].dispose();
+};
+
+ActivityQueue.prototype.addActivity = function( aActivity )
+{
+ if( !aActivity )
+ {
+ log( 'ActivityQueue.addActivity: activity is not valid' );
+ return false;
+ }
+
+ this.aCurrentActivityWaitingSet.push( aActivity );
+ aActivityQueueDebugPrinter.print( 'ActivityQueue.addActivity: activity appended' );
+ return true;
+};
+
+ActivityQueue.prototype.process = function()
+{
+ var nSize = this.aCurrentActivityWaitingSet.length;
+ var nLag = 0.0;
+ for( var i = 0; i < nSize; ++i )
+ {
+ nLag = Math.max( nLag,this.aCurrentActivityWaitingSet[i].calcTimeLag() );
+ }
+
+ if( nLag > 0.0 )
+ this.aTimer.adjustTimer( -nLag, true );
+
+
+ while( this.aCurrentActivityWaitingSet.length != 0 )
+ {
+ var aActivity = this.aCurrentActivityWaitingSet.shift();
+ var bReinsert = false;
+
+ bReinsert = aActivity.perform();
+
+ if( bReinsert )
+ {
+ this.aCurrentActivityReinsertSet.push( aActivity );
+ }
+ else
+ {
+ this.aDequeuedActivitySet.push( aActivity );
+ }
+ }
+
+ if( this.aCurrentActivityReinsertSet.length != 0 )
+ {
+ // TODO: optimization, try to swap reference here
+ this.aCurrentActivityWaitingSet = this.aCurrentActivityReinsertSet;
+ this.aCurrentActivityReinsertSet = [];
+ }
+};
+
+ActivityQueue.prototype.processDequeued = function()
+{
+ // notify all dequeued activities from last round
+ var nSize = this.aDequeuedActivitySet.length;
+ for( var i = 0; i < nSize; ++i )
+ this.aDequeuedActivitySet[i].dequeued();
+
+ this.aDequeuedActivitySet = [];
+};
+
+ActivityQueue.prototype.isEmpty = function()
+{
+ return ( ( this.aCurrentActivityWaitingSet.length == 0 ) &&
+ ( this.aCurrentActivityReinsertSet.length == 0 ) );
+};
+
+ActivityQueue.prototype.clear = function()
+{
+ aActivityQueueDebugPrinter.print( 'ActivityQueue.clear invoked' );
+ var nSize = this.aCurrentActivityWaitingSet.length;
+ var i;
+ for( i = 0; i < nSize; ++i )
+ this.aCurrentActivityWaitingSet[i].dequeued();
+ this.aCurrentActivityWaitingSet = [];
+
+ nSize = this.aCurrentActivityReinsertSet.length;
+ for( i = 0; i < nSize; ++i )
+ this.aCurrentActivityReinsertSet[i].dequeued();
+ this.aCurrentActivityReinsertSet = [];
+};
+
+ActivityQueue.prototype.endAll = function()
+{
+ aActivityQueueDebugPrinter.print( 'ActivityQueue.endAll invoked' );
+ var nSize = this.aCurrentActivityWaitingSet.length;
+ var i;
+ for( i = 0; i < nSize; ++i )
+ this.aCurrentActivityWaitingSet[i].end();
+ this.aCurrentActivityWaitingSet = [];
+
+ nSize = this.aCurrentActivityReinsertSet.length;
+ for( i = 0; i < nSize; ++i )
+ this.aCurrentActivityReinsertSet[i].end();
+ this.aCurrentActivityReinsertSet = [];
+};
+
+ActivityQueue.prototype.getTimer = function()
+{
+ return this.aTimer;
+};
+
+ActivityQueue.prototype.size = function()
+{
+ return ( this.aCurrentActivityWaitingSet.length +
+ this.aCurrentActivityReinsertSet.length +
+ this.aDequeuedActivitySet.length );
+};
+
+
+
+
+function ElapsedTime( aTimeBase )
+{
+ this.aTimeBase = aTimeBase;
+ this.nLastQueriedTime = 0.0;
+ this.nStartTime = this.getCurrentTime();
+ this.nFrozenTime = 0.0;
+ this.bInPauseMode = false;
+ this.bInHoldMode = false;
+}
+
+
+ElapsedTime.prototype.getTimeBase = function()
+{
+ return this.aTimeBase;
+};
+
+ElapsedTime.prototype.reset = function()
+{
+ this.nLastQueriedTime = 0.0;
+ this.nStartTime = this.getCurrentTime();
+ this.nFrozenTime = 0.0;
+ this.bInPauseMode = false;
+ this.bInHoldMode = false;
+};
+
+ElapsedTime.prototype.getElapsedTime = function()
+{
+ this.nLastQueriedTime = this.getElapsedTimeImpl();
+ return this.nLastQueriedTime;
+};
+
+ElapsedTime.prototype.pauseTimer = function()
+{
+ this.nFrozenTime = this.getElapsedTimeImpl();
+ this.bInPauseMode = true;
+};
+
+ElapsedTime.prototype.continueTimer = function()
+{
+ this.bInPauseMode = false;
+
+ // stop pausing, time runs again. Note that
+ // getElapsedTimeImpl() honors hold mode, i.e. a
+ // continueTimer() in hold mode will preserve the latter
+ var nPauseDuration = this.getElapsedTimeImpl() - this.nFrozenTime;
+
+ // adjust start time, such that subsequent getElapsedTime() calls
+ // will virtually start from m_fFrozenTime.
+ this.nStartTime += nPauseDuration;
+};
+
+ElapsedTime.prototype.adjustTimer = function( nOffset, bLimitToLastQueriedTime )
+{
+ if( bLimitToLastQueriedTime == undefined )
+ bLimitToLastQueriedTime = true;
+
+ // to make getElapsedTime() become _larger_, have to reduce nStartTime.
+ this.nStartTime -= nOffset;
+
+ // also adjust frozen time, this method must _always_ affect the
+ // value returned by getElapsedTime()!
+ if( this.bInHoldMode || this.bInPauseMode )
+ this.nFrozenTime += nOffset;
+};
+
+ElapsedTime.prototype.holdTimer = function()
+{
+ // when called during hold mode (e.g. more than once per time
+ // object), the original hold time will be maintained.
+ this.nFrozenTime = this.getElapsedTimeImpl();
+ this.bInHoldMode = true;
+};
+
+ElapsedTime.prototype.releaseTimer = function()
+{
+ this.bInHoldMode = false;
+};
+
+ElapsedTime.prototype.getSystemTime = function()
+{
+ return ( getCurrentSystemTime() / 1000.0 );
+};
+
+ElapsedTime.prototype.getCurrentTime = function()
+{
+ var nCurrentTime;
+ if ( !this.aTimeBase )
+ {
+ nCurrentTime = this.getSystemTime();
+ }
+ else
+ {
+ nCurrentTime = this.aTimeBase.getElapsedTimeImpl();
+ }
+
+ assert( ( typeof( nCurrentTime ) === typeof( 0 ) ) && isFinite( nCurrentTime ),
+ 'ElapsedTime.getCurrentTime: assertion failed: nCurrentTime == ' + nCurrentTime );
+
+
+ return nCurrentTime;
+};
+
+ElapsedTime.prototype.getElapsedTimeImpl = function()
+{
+ if( this.bInHoldMode || this.bInPauseMode )
+ {
+ return this.nFrozenTime;
+ }
+
+ var nCurTime = this.getCurrentTime();
+ return ( nCurTime - this.nStartTime );
+};
+
+
+
+/*****
+ * @libreofficeend
+ *
+ * Several parts of the above code are the result of the porting,
+ * started on August 2011, of the C++ code included in the source files
+ * placed under the folder '/slideshow/source' and subfolders.
+ * @source https://cgit.freedesktop.org/libreoffice/core/tree/slideshow/source
+ *
+ */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgexport.cxx b/filter/source/svg/svgexport.cxx
new file mode 100644
index 000000000..c21b041b1
--- /dev/null
+++ b/filter/source/svg/svgexport.cxx
@@ -0,0 +1,2877 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "svgwriter.hxx"
+#include "svgfontexport.hxx"
+#include "svgfilter.hxx"
+#include <svgscript.hxx>
+
+#include <com/sun/star/awt/Rectangle.hpp>
+#include <com/sun/star/animations/XAnimationNodeSupplier.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/drawing/FillStyle.hpp>
+#include <com/sun/star/drawing/XMasterPageTarget.hpp>
+#include <com/sun/star/drawing/GraphicExportFilter.hpp>
+#include <com/sun/star/presentation/XPresentationSupplier.hpp>
+#include <com/sun/star/style/ParagraphAdjust.hpp>
+#include <com/sun/star/text/textfield/Type.hpp>
+#include <com/sun/star/util/MeasureUnit.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/ShapeCollection.hpp>
+
+#include <rtl/bootstrap.hxx>
+#include <svx/unopage.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdoutl.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/flditem.hxx>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <i18nlangtag/lang.h>
+#include <svl/numformat.hxx>
+#include <tools/debug.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unotools/tempfile.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <vcl/filter/SvmReader.hxx>
+#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/animationexport.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdxcgv.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <memory>
+#include <string_view>
+
+using namespace css::animations;
+using namespace css::presentation;
+using namespace ::com::sun::star::graphic;
+using namespace ::com::sun::star::geometry;
+using namespace ::com::sun::star;
+using namespace ::xmloff::token;
+
+// - ooo elements and attributes -
+
+#define NSPREFIX u"ooo:"
+
+constexpr OUStringLiteral SVG_PROP_TINYPROFILE = u"TinyMode";
+constexpr OUStringLiteral SVG_PROP_DTDSTRING = u"DTDString";
+constexpr OUStringLiteral SVG_PROP_EMBEDFONTS = u"EmbedFonts";
+constexpr OUStringLiteral SVG_PROP_NATIVEDECORATION = u"UseNativeTextDecoration";
+constexpr OUStringLiteral SVG_PROP_OPACITY = u"Opacity";
+constexpr OUStringLiteral SVG_PROP_POSITIONED_CHARACTERS = u"UsePositionedCharacters";
+
+// ooo xml elements
+constexpr OUStringLiteral aOOOElemTextField = NSPREFIX "text_field";
+
+
+// ooo xml attributes for meta_slide
+constexpr OUStringLiteral aOOOAttrSlide = NSPREFIX "slide";
+constexpr OUStringLiteral aOOOAttrMaster = NSPREFIX "master";
+constexpr OUStringLiteral aOOOAttrHasCustomBackground = NSPREFIX "has-custom-background";
+constexpr OUStringLiteral aOOOAttrDisplayName = NSPREFIX "display-name";
+constexpr OUStringLiteral aOOOAttrBackgroundVisibility = NSPREFIX "background-visibility";
+constexpr OUStringLiteral aOOOAttrMasterObjectsVisibility = NSPREFIX "master-objects-visibility";
+constexpr OUStringLiteral aOOOAttrSlideDuration = NSPREFIX "slide-duration";
+constexpr OUStringLiteral aOOOAttrDateTimeField = NSPREFIX "date-time-field";
+constexpr OUStringLiteral aOOOAttrFooterField = NSPREFIX "footer-field";
+constexpr OUStringLiteral aOOOAttrHasTransition = NSPREFIX "has-transition";
+
+// ooo xml attributes for pages and shapes
+constexpr OUStringLiteral aOOOAttrName = NSPREFIX "name";
+
+constexpr OUStringLiteral constSvgNamespace = u"http://www.w3.org/2000/svg";
+
+
+/** Text Field Class Hierarchy
+ This is a set of classes for exporting text field meta info.
+ */
+
+namespace {
+
+class TextField
+{
+protected:
+ SVGFilter::ObjectSet mMasterPageSet;
+public:
+ TextField() = default;
+ TextField(TextField const &) = default;
+ TextField(TextField &&) = default;
+ TextField & operator =(TextField const &) = default;
+ TextField & operator =(TextField &&) = default;
+
+ virtual OUString getClassName() const
+ {
+ return "TextField";
+ }
+ virtual bool equalTo( const TextField & aTextField ) const = 0;
+ virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const = 0;
+ virtual void elementExport( SVGExport* pSVGExport ) const
+ {
+ pSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", getClassName() );
+ }
+ void insertMasterPage( const Reference< css::drawing::XDrawPage>& xMasterPage )
+ {
+ mMasterPageSet.insert( xMasterPage );
+ }
+ virtual ~TextField() {}
+protected:
+ void implGrowCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets, const OUString& sText, const OUString& sTextFieldId ) const
+ {
+ const sal_Unicode * ustr = sText.getStr();
+ sal_Int32 nLength = sText.getLength();
+ for (auto const& masterPage : mMasterPageSet)
+ {
+ const Reference< XInterface > & xMasterPage = masterPage;
+ for( sal_Int32 i = 0; i < nLength; ++i )
+ {
+ aTextFieldCharSets[ xMasterPage ][ sTextFieldId ].insert( ustr[i] );
+ }
+ }
+ }
+};
+
+
+class FixedTextField : public TextField
+{
+public:
+ OUString text;
+
+ virtual OUString getClassName() const override
+ {
+ return "FixedTextField";
+ }
+ virtual bool equalTo( const TextField & aTextField ) const override
+ {
+ if( const FixedTextField* aFixedTextField = dynamic_cast< const FixedTextField* >( &aTextField ) )
+ {
+ return ( text == aFixedTextField->text );
+ }
+ return false;
+ }
+ virtual void elementExport( SVGExport* pSVGExport ) const override
+ {
+ TextField::elementExport( pSVGExport );
+ SvXMLElementExport aExp( *pSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ pSVGExport->GetDocHandler()->characters( text );
+ }
+};
+
+
+class FixedDateTimeField : public FixedTextField
+{
+public:
+ FixedDateTimeField() {}
+ virtual OUString getClassName() const override
+ {
+ return "FixedDateTimeField";
+ }
+ virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const override
+ {
+ implGrowCharSet( aTextFieldCharSets, text, aOOOAttrDateTimeField );
+ }
+};
+
+
+class FooterField : public FixedTextField
+{
+public:
+ FooterField() {}
+ virtual OUString getClassName() const override
+ {
+ return "FooterField";
+ }
+ virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const override
+ {
+ static constexpr OUStringLiteral sFieldId = aOOOAttrFooterField;
+ implGrowCharSet( aTextFieldCharSets, text, sFieldId );
+ }
+};
+
+
+class VariableTextField : public TextField
+{
+public:
+ virtual OUString getClassName() const override
+ {
+ return "VariableTextField";
+ }
+};
+
+
+class VariableDateTimeField : public VariableTextField
+{
+public:
+ sal_Int32 format;
+
+ VariableDateTimeField()
+ : format(0)
+ {
+ }
+ virtual OUString getClassName() const override
+ {
+ return "VariableDateTimeField";
+ }
+ virtual bool equalTo( const TextField & aTextField ) const override
+ {
+ if( const VariableDateTimeField* aField = dynamic_cast< const VariableDateTimeField* >( &aTextField ) )
+ {
+ return ( format == aField->format );
+ }
+ return false;
+ }
+ virtual void elementExport( SVGExport* pSVGExport ) const override
+ {
+ VariableTextField::elementExport( pSVGExport );
+ OUString sDateFormat, sTimeFormat;
+ SvxDateFormat eDateFormat = static_cast<SvxDateFormat>( format & 0x0f );
+ if( eDateFormat != SvxDateFormat::AppDefault )
+ {
+ switch( eDateFormat )
+ {
+ case SvxDateFormat::StdSmall:
+ case SvxDateFormat::A: // 13.02.96
+ sDateFormat.clear();
+ break;
+ case SvxDateFormat::C: // 13.Feb 1996
+ sDateFormat.clear();
+ break;
+ case SvxDateFormat::D: // 13.February 1996
+ sDateFormat.clear();
+ break;
+ case SvxDateFormat::E: // Tue, 13.February 1996
+ sDateFormat.clear();
+ break;
+ case SvxDateFormat::StdBig:
+ case SvxDateFormat::F: // Tuesday, 13.February 1996
+ sDateFormat.clear();
+ break;
+ // default case
+ case SvxDateFormat::B: // 13.02.1996
+ default:
+ sDateFormat.clear();
+ break;
+ }
+ }
+
+ SvxTimeFormat eTimeFormat = static_cast<SvxTimeFormat>( ( format >> 4 ) & 0x0f );
+ if( eTimeFormat != SvxTimeFormat::AppDefault )
+ {
+ switch( eTimeFormat )
+ {
+ case SvxTimeFormat::HH24_MM_SS: // 13:49:38
+ sTimeFormat.clear();
+ break;
+ case SvxTimeFormat::HH12_MM_AMPM: // 01:49 PM
+ case SvxTimeFormat::HH12_MM:
+ sTimeFormat.clear();
+ break;
+ case SvxTimeFormat::HH12_MM_SS_AMPM: // 01:49:38 PM
+ case SvxTimeFormat::HH12_MM_SS:
+ sTimeFormat.clear();
+ break;
+ // default case
+ case SvxTimeFormat::HH24_MM: // 13:49
+ default:
+ sTimeFormat.clear();
+ break;
+ }
+ }
+
+ OUString sDateTimeFormat = sDateFormat + " " + sTimeFormat;
+
+ pSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "date-time-format", sDateTimeFormat );
+ SvXMLElementExport aExp( *pSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ }
+ virtual void growCharSet( SVGFilter::UCharSetMapMap & aTextFieldCharSets ) const override
+ {
+ // we use the unicode char set in an improper way: we put in the date/time format
+ // in order to pass it to the CalcFieldValue method
+ static const OUString sFieldId = aOOOAttrDateTimeField + "-variable";
+ for (auto const& masterPage : mMasterPageSet)
+ {
+ aTextFieldCharSets[ masterPage ][ sFieldId ].insert( static_cast<sal_Unicode>( format ) );
+ }
+ }
+};
+
+
+bool operator==( const TextField & aLhsTextField, const TextField & aRhsTextField )
+{
+ return aLhsTextField.equalTo( aRhsTextField );
+}
+
+}
+
+SVGExport::SVGExport(
+ const css::uno::Reference< css::uno::XComponentContext >& rContext,
+ const Reference< XDocumentHandler >& rxHandler,
+ const Sequence< PropertyValue >& rFilterData )
+ : SvXMLExport( rContext, "",
+ util::MeasureUnit::MM_100TH,
+ xmloff::token::XML_TOKEN_INVALID,
+ SvXMLExportFlags::META|SvXMLExportFlags::PRETTY )
+{
+ SetDocHandler( rxHandler );
+ GetDocHandler()->startDocument();
+
+ // initializing filter settings from filter data
+ comphelper::SequenceAsHashMap aFilterDataHashMap = rFilterData;
+
+ // TinyProfile
+ mbIsUseTinyProfile = aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_TINYPROFILE, false);
+
+ // DTD string
+ mbIsUseDTDString = aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_DTDSTRING, true);
+
+ // Font Embedding
+ comphelper::SequenceAsHashMap::const_iterator iter = aFilterDataHashMap.find(SVG_PROP_EMBEDFONTS);
+ if(iter==aFilterDataHashMap.end())
+ {
+ OUString v;
+ mbIsEmbedFonts = !rtl::Bootstrap::get("SVG_DISABLE_FONT_EMBEDDING", v);
+ }
+ else
+ {
+ if(!(iter->second >>= mbIsEmbedFonts))
+ mbIsEmbedFonts = false;
+ }
+
+ // Native Decoration
+ mbIsUseNativeTextDecoration = !mbIsUseTinyProfile && aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_NATIVEDECORATION, true);
+
+ // Tiny Opacity (supported from SVG Tiny 1.2)
+ mbIsUseOpacity = aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_OPACITY, true);
+
+ // Positioned Characters (The old method)
+ mbIsUsePositionedCharacters = aFilterDataHashMap.getUnpackedValueOrDefault(SVG_PROP_POSITIONED_CHARACTERS, false);
+
+ // add namespaces
+ GetNamespaceMap_().Add(
+ GetXMLToken(XML_NP_PRESENTATION),
+ GetXMLToken(XML_N_PRESENTATION),
+ XML_NAMESPACE_PRESENTATION);
+
+ GetNamespaceMap_().Add(
+ GetXMLToken(XML_NP_SMIL),
+ GetXMLToken(XML_N_SMIL_COMPAT),
+ XML_NAMESPACE_SMIL);
+
+ GetNamespaceMap_().Add(
+ GetXMLToken(XML_NP_ANIMATION),
+ GetXMLToken(XML_N_ANIMATION),
+ XML_NAMESPACE_ANIMATION);
+}
+
+SVGExport::~SVGExport()
+{
+ GetDocHandler()->endDocument();
+}
+
+ObjectRepresentation::ObjectRepresentation()
+{
+}
+
+ObjectRepresentation::ObjectRepresentation( const Reference< XInterface >& rxObject,
+ const GDIMetaFile& rMtf ) :
+ mxObject( rxObject ),
+ mxMtf( new GDIMetaFile( rMtf ) )
+{
+}
+
+ObjectRepresentation::ObjectRepresentation( const ObjectRepresentation& rPresentation ) :
+ mxObject( rPresentation.mxObject ),
+ mxMtf( rPresentation.mxMtf ? new GDIMetaFile( *rPresentation.mxMtf ) : nullptr )
+{
+}
+
+ObjectRepresentation& ObjectRepresentation::operator=( const ObjectRepresentation& rPresentation )
+{
+ // Check for self-assignment
+ if (this == &rPresentation)
+ return *this;
+
+ mxObject = rPresentation.mxObject;
+ mxMtf.reset(rPresentation.mxMtf ? new GDIMetaFile(*rPresentation.mxMtf) : nullptr);
+
+ return *this;
+}
+
+
+namespace
+{
+
+BitmapChecksum GetBitmapChecksum( const MetaAction* pAction )
+{
+ if( !pAction )
+ {
+ OSL_FAIL( "GetBitmapChecksum: passed MetaAction pointer is null." );
+ return 0;
+ }
+
+ BitmapChecksum nChecksum = 0;
+ const MetaActionType nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ // The conversion to BitmapEx is needed since a Bitmap object is
+ // converted to BitmapEx before passing it to SVGActionWriter::ImplWriteBmp
+ // where the checksum is checked for matching.
+ nChecksum = BitmapEx( pA->GetBitmap() ).GetChecksum();
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ nChecksum = pA->GetBitmapEx().GetChecksum();
+ }
+ break;
+ default: break;
+ }
+ return nChecksum;
+}
+
+MetaAction* CreateMetaBitmapAction( const MetaAction* pAction, const Point& rPt, const Size& rSz )
+{
+ if( !pAction )
+ {
+ OSL_FAIL( "CreateMetaBitmapAction: passed MetaAction pointer is null." );
+ return nullptr;
+ }
+
+ MetaAction* pResAction = nullptr;
+ const MetaActionType nType = pAction->GetType();
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ pResAction = new MetaBmpScaleAction( rPt, rSz, pA->GetBitmap() );
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ pResAction = new MetaBmpExScaleAction( rPt, rSz, pA->GetBitmapEx() );
+ }
+ break;
+ default: break;
+ }
+ return pResAction;
+}
+
+void MetaBitmapActionGetPoint( const MetaAction* pAction, Point& rPt )
+{
+ if( !pAction )
+ {
+ OSL_FAIL( "MetaBitmapActionGetPoint: passed MetaAction pointer is null." );
+ return;
+ }
+ const MetaActionType nType = pAction->GetType();
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ rPt = pA->GetPoint();
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ rPt = pA->GetPoint();
+ }
+ break;
+ default: break;
+ }
+}
+
+void MetaBitmapActionGetSize( const MetaAction* pAction, Size& rSz )
+{
+ if( !pAction )
+ {
+ OSL_FAIL( "MetaBitmapActionGetSize: passed MetaAction pointer is null." );
+ return;
+ }
+ const MetaActionType nType = pAction->GetType();
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ rSz = pA->GetSize();
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ rSz = pA->GetSize();
+ }
+ break;
+ default: break;
+ }
+}
+
+void MetaBitmapActionGetOrigSize( const MetaAction* pAction, Size& rSz )
+{
+ if( !pAction )
+ {
+ OSL_FAIL( "MetaBitmapActionGetOrigSize: passed MetaAction pointer is null." );
+ return;
+ }
+
+ const MetaActionType nType = pAction->GetType();
+ MapMode aSourceMode( MapUnit::MapPixel );
+ MapMode aTargetMode( MapUnit::Map100thMM );
+
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ const Bitmap& rBitmap = pA->GetBitmap();
+ rSz = rBitmap.GetSizePixel();
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ const BitmapEx& rBitmap = pA->GetBitmapEx();
+ rSz = rBitmap.GetSizePixel();
+ }
+ break;
+ default: break;
+ }
+ rSz = OutputDevice::LogicToLogic( rSz, aSourceMode, aTargetMode );
+}
+
+OUString getPatternIdForTiledBackground( std::u16string_view sSlideId, BitmapChecksum nChecksum )
+{
+ return OUString::Concat("bg-pattern.") + sSlideId + "." + OUString::number( nChecksum );
+}
+
+OUString getIdForTiledBackground( std::u16string_view sSlideId, BitmapChecksum nChecksum )
+{
+ return OUString::Concat("bg-") + sSlideId + "." + OUString::number( nChecksum );
+}
+
+} // end anonymous namespace
+
+size_t HashBitmap::operator()( const ObjectRepresentation& rObjRep ) const
+{
+ const GDIMetaFile& aMtf = rObjRep.GetRepresentation();
+ if( aMtf.GetActionSize() == 1 )
+ {
+ return static_cast< size_t >( GetBitmapChecksum( aMtf.GetAction( 0 ) ) );
+ }
+ else
+ {
+ OSL_FAIL( "HashBitmap: metafile should have a single action." );
+ return 0;
+ }
+}
+
+
+bool EqualityBitmap::operator()( const ObjectRepresentation& rObjRep1,
+ const ObjectRepresentation& rObjRep2 ) const
+{
+ const GDIMetaFile& aMtf1 = rObjRep1.GetRepresentation();
+ const GDIMetaFile& aMtf2 = rObjRep2.GetRepresentation();
+ if( aMtf1.GetActionSize() == 1 && aMtf2.GetActionSize() == 1 )
+ {
+ BitmapChecksum nChecksum1 = GetBitmapChecksum( aMtf1.GetAction( 0 ) );
+ BitmapChecksum nChecksum2 = GetBitmapChecksum( aMtf2.GetAction( 0 ) );
+ return ( nChecksum1 == nChecksum2 );
+ }
+ else
+ {
+ OSL_FAIL( "EqualityBitmap: metafile should have a single action." );
+ return false;
+ }
+}
+
+
+bool SVGFilter::implExport( const Sequence< PropertyValue >& rDescriptor )
+{
+ Reference< XOutputStream > xOStm;
+ std::unique_ptr<SvStream> pOStm;
+ sal_Int32 nLength = rDescriptor.getLength();
+ const PropertyValue* pValue = rDescriptor.getConstArray();
+
+ maFilterData.realloc( 0 );
+
+ for ( sal_Int32 i = 0 ; i < nLength; ++i)
+ {
+ if ( pValue[ i ].Name == "OutputStream" )
+ pValue[ i ].Value >>= xOStm;
+ else if ( pValue[ i ].Name == "FileName" )
+ {
+ OUString aFileName;
+
+ pValue[ i ].Value >>= aFileName;
+ pOStm = ::utl::UcbStreamHelper::CreateStream( aFileName, StreamMode::WRITE | StreamMode::TRUNC );
+
+ if( pOStm )
+ xOStm.set( new ::utl::OOutputStreamWrapper ( *pOStm ) );
+ }
+ else if ( pValue[ i ].Name == "FilterData" )
+ {
+ pValue[ i ].Value >>= maFilterData;
+ }
+ }
+
+ if(mbWriterFilter || mbCalcFilter)
+ return implExportWriterOrCalc(xOStm);
+
+ return implExportImpressOrDraw(xOStm);
+}
+
+bool SVGFilter::implExportImpressOrDraw( const Reference< XOutputStream >& rxOStm)
+{
+ Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ) ;
+ bool bRet = false;
+
+ if( rxOStm.is() )
+ {
+ if( !mSelectedPages.empty() && !mMasterPageTargets.empty() )
+ {
+ Reference< XDocumentHandler > xDocHandler = implCreateExportDocumentHandler( rxOStm );
+
+ if( xDocHandler.is() )
+ {
+ mbPresentation = Reference< XPresentationSupplier >( mxSrcDoc, UNO_QUERY ).is();
+ mpObjects = new ObjectMap;
+
+ // mpSVGExport = new SVGExport( xDocHandler );
+ mpSVGExport = new SVGExport( xContext, xDocHandler, maFilterData );
+
+ // create an id for each draw page
+ for( const auto& rPage : mSelectedPages )
+ implRegisterInterface( rPage );
+
+ // create an id for each master page
+ for(const uno::Reference<drawing::XDrawPage> & mMasterPageTarget : mMasterPageTargets)
+ implRegisterInterface( mMasterPageTarget );
+
+ SdrModel* pSdrModel(nullptr);
+
+ try
+ {
+ mxDefaultPage = mSelectedPages[0];
+
+ if( mxDefaultPage.is() )
+ {
+ SvxDrawPage* pSvxDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>( mxDefaultPage );
+
+ if( pSvxDrawPage )
+ {
+ mpDefaultSdrPage = pSvxDrawPage->GetSdrPage();
+ pSdrModel = &mpDefaultSdrPage->getSdrModelFromSdrPage();
+ SdrOutliner& rOutl = pSdrModel->GetDrawOutliner();
+
+ maOldFieldHdl = rOutl.GetCalcFieldValueHdl();
+ maNewFieldHdl = LINK(this, SVGFilter, CalcFieldHdl);
+ rOutl.SetCalcFieldValueHdl(maNewFieldHdl);
+ }
+
+ bRet = implExportDocument();
+ }
+ }
+ catch( ... )
+ {
+ delete mpSVGDoc;
+ mpSVGDoc = nullptr;
+ SAL_WARN("filter.svg", "Exception caught");
+ }
+
+ if( nullptr != pSdrModel )
+ {
+ // fdo#62682 The maNewFieldHdl can end up getting copied
+ // into various other outliners which live past this
+ // method, so get the full list of outliners and restore
+ // the maOldFieldHdl for all that have ended up using
+ // maNewFieldHdl
+ std::vector<SdrOutliner*> aOutliners(pSdrModel->GetActiveOutliners());
+ for (auto const& outliner : aOutliners)
+ {
+ if (maNewFieldHdl == outliner->GetCalcFieldValueHdl())
+ outliner->SetCalcFieldValueHdl(maOldFieldHdl);
+ }
+ }
+
+ delete mpSVGWriter;
+ mpSVGWriter = nullptr;
+ mpSVGExport = nullptr; // pointed object is released by xSVGExport dtor at the end of this scope
+ delete mpSVGFontExport;
+ mpSVGFontExport = nullptr;
+ delete mpObjects;
+ mpObjects = nullptr;
+ mbPresentation = false;
+ }
+ }
+ }
+ return bRet;
+}
+
+
+bool SVGFilter::implExportWriterOrCalc( const Reference< XOutputStream >& rxOStm )
+{
+ Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() ) ;
+ bool bRet = false;
+
+ if( rxOStm.is() )
+ {
+ Reference< XDocumentHandler > xDocHandler = implCreateExportDocumentHandler( rxOStm );
+
+ if( xDocHandler.is() )
+ {
+ mpObjects = new ObjectMap;
+
+ // mpSVGExport = new SVGExport( xDocHandler );
+ mpSVGExport = new SVGExport( xContext, xDocHandler, maFilterData );
+
+ try
+ {
+ mxDefaultPage = mSelectedPages[0];
+ bRet = implExportDocument();
+ }
+ catch( ... )
+ {
+ TOOLS_WARN_EXCEPTION( "filter.svg", "" );
+ delete mpSVGDoc;
+ mpSVGDoc = nullptr;
+ }
+
+ delete mpSVGWriter;
+ mpSVGWriter = nullptr;
+ mpSVGExport = nullptr; // pointed object is released by xSVGExport dtor at the end of this scope
+ delete mpSVGFontExport;
+ mpSVGFontExport = nullptr;
+ delete mpObjects;
+ mpObjects = nullptr;
+ }
+ }
+ return bRet;
+}
+
+bool SVGFilter::implExportWriterTextGraphic( const Reference< view::XSelectionSupplier >& xSelectionSupplier )
+{
+ Any selection = xSelectionSupplier->getSelection();
+ uno::Reference<lang::XServiceInfo> xSelection;
+ selection >>= xSelection;
+ if (!xSelection || !xSelection->supportsService("com.sun.star.text.TextGraphicObject"))
+ return true;
+
+ uno::Reference<beans::XPropertySet> xPropertySet(xSelection, uno::UNO_QUERY);
+
+ uno::Reference<graphic::XGraphic> xOriginalGraphic;
+ xPropertySet->getPropertyValue("Graphic") >>= xOriginalGraphic;
+ const Graphic aOriginalGraphic(xOriginalGraphic);
+
+ uno::Reference<graphic::XGraphic> xTransformedGraphic;
+ xPropertySet->getPropertyValue(
+ mbIsPreview ? OUString("GraphicPreview") : OUString("TransformedGraphic"))
+ >>= xTransformedGraphic;
+
+ if (!xTransformedGraphic.is())
+ return false;
+ const Graphic aTransformedGraphic(xTransformedGraphic);
+ bool bSameGraphic = aTransformedGraphic == aOriginalGraphic ||
+ aOriginalGraphic.GetChecksum() == aTransformedGraphic.GetChecksum();
+ const Graphic aGraphic = bSameGraphic ? aOriginalGraphic : aTransformedGraphic;
+ uno::Reference<graphic::XGraphic> xGraphic = bSameGraphic ? xOriginalGraphic : xTransformedGraphic;
+
+ // Calculate size from Graphic
+ Point aPos( OutputDevice::LogicToLogic(aGraphic.GetPrefMapMode().GetOrigin(), aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
+ Size aSize( OutputDevice::LogicToLogic(aGraphic.GetPrefSize(), aGraphic.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
+
+ assert(mSelectedPages.size() == 1);
+ SvxDrawPage* pSvxDrawPage(comphelper::getFromUnoTunnel<SvxDrawPage>(mSelectedPages[0]));
+ if(pSvxDrawPage == nullptr || pSvxDrawPage->GetSdrPage() == nullptr)
+ return false;
+
+ SdrGrafObj* pGraphicObj = new SdrGrafObj(pSvxDrawPage->GetSdrPage()->getSdrModelFromSdrPage(), aGraphic, tools::Rectangle( aPos, aSize ));
+ uno::Reference< drawing::XShape > xShape = GetXShapeForSdrObject(pGraphicObj);
+ uno::Reference< XPropertySet > xShapePropSet(xShape, uno::UNO_QUERY);
+ xShapePropSet->setPropertyValue("Graphic", uno::Any(xGraphic));
+
+ maShapeSelection = drawing::ShapeCollection::create(comphelper::getProcessComponentContext());
+ maShapeSelection->add(xShape);
+
+ return true;
+}
+
+
+Reference< XWriter > SVGFilter::implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm )
+{
+ Reference< XWriter > xSaxWriter;
+
+ if( rxOStm.is() )
+ {
+ xSaxWriter = Writer::create( ::comphelper::getProcessComponentContext() );
+ xSaxWriter->setOutputStream( rxOStm );
+ }
+
+ return xSaxWriter;
+}
+
+
+bool SVGFilter::implLookForFirstVisiblePage()
+{
+ sal_Int32 nCurPage = 0, nLastPage = mSelectedPages.size() - 1;
+
+ if(!mbPresentation || mbSinglePage)
+ {
+ mnVisiblePage = nCurPage;
+ }
+
+ while( ( nCurPage <= nLastPage ) && ( -1 == mnVisiblePage ) )
+ {
+ const Reference< css::drawing::XDrawPage > & xDrawPage = mSelectedPages[nCurPage];
+
+ if( xDrawPage.is() )
+ {
+ Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
+
+ if( xPropSet.is() )
+ {
+ bool bVisible = false;
+
+ if( ( xPropSet->getPropertyValue( "Visible" ) >>= bVisible ) && bVisible )
+ {
+ mnVisiblePage = nCurPage;
+ }
+ }
+ }
+ ++nCurPage;
+ }
+
+ return ( mnVisiblePage != -1 );
+}
+
+
+bool SVGFilter::implExportDocument()
+{
+ sal_Int32 nDocX = 0, nDocY = 0; // #i124608#
+ sal_Int32 nDocWidth = 0, nDocHeight = 0;
+ bool bRet = false;
+ sal_Int32 nLastPage = mSelectedPages.size() - 1;
+
+ mbSinglePage = (nLastPage == 0);
+ mnVisiblePage = -1;
+
+ const Reference< XPropertySet > xDefaultPagePropertySet( mxDefaultPage, UNO_QUERY );
+
+ // #i124608#
+ mbExportShapeSelection = mbSinglePage && maShapeSelection.is() && maShapeSelection->getCount();
+
+ if(xDefaultPagePropertySet.is())
+ {
+ xDefaultPagePropertySet->getPropertyValue( "Width" ) >>= nDocWidth;
+ xDefaultPagePropertySet->getPropertyValue( "Height" ) >>= nDocHeight;
+ }
+
+ if(mbExportShapeSelection)
+ {
+ // #i124608# create BoundRange and set nDocX, nDocY, nDocWidth and nDocHeight
+ basegfx::B2DRange aShapeRange;
+
+ for(sal_Int32 a(0); a < maShapeSelection->getCount(); a++)
+ {
+ Reference< css::drawing::XShape > xShapeCandidate;
+ if((maShapeSelection->getByIndex(a) >>= xShapeCandidate) && xShapeCandidate.is())
+ {
+ Reference< XPropertySet > xShapePropSet( xShapeCandidate, UNO_QUERY );
+ css::awt::Rectangle aBoundRect;
+ if( xShapePropSet.is() && ( xShapePropSet->getPropertyValue( "BoundRect" ) >>= aBoundRect ))
+ {
+ aShapeRange.expand(basegfx::B2DTuple(aBoundRect.X, aBoundRect.Y));
+ aShapeRange.expand(basegfx::B2DTuple(aBoundRect.X + aBoundRect.Width,
+ aBoundRect.Y + aBoundRect.Height));
+ }
+ }
+ }
+
+ if(!aShapeRange.isEmpty())
+ {
+ nDocX = basegfx::fround(aShapeRange.getMinX());
+ nDocY = basegfx::fround(aShapeRange.getMinY());
+ nDocWidth = basegfx::fround(aShapeRange.getWidth());
+ nDocHeight = basegfx::fround(aShapeRange.getHeight());
+ }
+ }
+
+ if(mbWriterFilter || mbCalcFilter)
+ implExportDocumentHeaderWriterOrCalc(nDocX, nDocY, nDocWidth, nDocHeight);
+ else
+ implExportDocumentHeaderImpressOrDraw(nDocX, nDocY, nDocWidth, nDocHeight);
+
+
+ if( implLookForFirstVisiblePage() ) // OK! We found at least one visible page.
+ {
+ if( mbPresentation && !mbExportShapeSelection )
+ {
+ implGenerateMetaData();
+ implExportAnimations();
+ }
+ else
+ {
+ implGetPagePropSet( mSelectedPages[0] );
+ }
+
+ // Create the (Shape, GDIMetaFile) map
+ if( implCreateObjects() )
+ {
+ ::std::vector< ObjectRepresentation > aObjects( mpObjects->size() );
+ sal_uInt32 nPos = 0;
+
+ for (auto const& elem : *mpObjects)
+ {
+ aObjects[ nPos++ ] = elem.second;
+ }
+
+ mpSVGFontExport = new SVGFontExport( *mpSVGExport, std::move(aObjects) );
+ mpSVGWriter = new SVGActionWriter( *mpSVGExport, *mpSVGFontExport );
+
+ if( mpSVGExport->IsEmbedFonts() )
+ {
+ mpSVGFontExport->EmbedFonts();
+ }
+ if( !mpSVGExport->IsUsePositionedCharacters() )
+ {
+ implExportTextShapeIndex();
+ implEmbedBulletGlyphs();
+ implExportTextEmbeddedBitmaps();
+ implExportBackgroundBitmaps();
+ mpSVGWriter->SetEmbeddedBitmapRefs( &maBitmapActionMap );
+ implExportTiledBackground();
+ }
+ if( mbIsPreview )
+ mpSVGWriter->SetPreviewMode();
+
+ // #i124608# export a given object selection, so no MasterPage export at all
+ if (!mbExportShapeSelection)
+ implExportMasterPages( mMasterPageTargets, 0, mMasterPageTargets.size() - 1 );
+ implExportDrawPages( mSelectedPages, 0, nLastPage );
+
+ if( mbPresentation && !mbExportShapeSelection )
+ {
+ implGenerateScript();
+ }
+
+ delete mpSVGDoc;
+ mpSVGDoc = nullptr;
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+void SVGFilter::implExportDocumentHeaderImpressOrDraw(sal_Int32 nDocX, sal_Int32 nDocY,
+ sal_Int32 nDocWidth, sal_Int32 nDocHeight)
+{
+ const Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
+ if( xExtDocHandler.is() && !mpSVGExport->IsUseTinyProfile() )
+ {
+ xExtDocHandler->unknown( SVG_DTD_STRING );
+ }
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "version", "1.2" );
+
+ if( mpSVGExport->IsUseTinyProfile() )
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "baseProfile", "tiny" );
+
+ // The following if block means that the slide size is not adapted
+ // to the size of the browser window, moreover the slide is top left aligned
+ // instead of centered:
+ OUString aAttr;
+ if( !mbPresentation )
+ {
+ aAttr = OUString::number( nDocWidth * 0.01 ) + "mm";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", aAttr );
+
+ aAttr = OUString::number( nDocHeight * 0.01 ) + "mm";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", aAttr );
+ }
+
+ // #i124608# set viewBox explicitly to the exported content
+ if (mbExportShapeSelection)
+ {
+ aAttr = OUString::number(nDocX) + " " + OUString::number(nDocY) + " ";
+ }
+ else
+ {
+ aAttr = "0 0 ";
+ }
+
+ aAttr += OUString::number(nDocWidth) + " " + OUString::number(nDocHeight);
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", "xMidYMid" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill-rule", "evenodd" );
+
+ // standard line width is based on 1 pixel on a 90 DPI device (0.28222mmm)
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-width", OUString::number( 28.222 ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-linejoin", "round" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns", constSvgNamespace );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:ooo", "http://xml.openoffice.org/svg/export" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:xlink", "http://www.w3.org/1999/xlink" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:presentation", "http://sun.com/xmlns/staroffice/presentation" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:smil", "http://www.w3.org/2001/SMIL20/" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:anim", "urn:oasis:names:tc:opendocument:xmlns:animation:1.0" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xml:space", "preserve" );
+
+ mpSVGDoc = new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "svg", true, true );
+
+ // Create a ClipPath element that will be used for cutting bitmaps and other elements that could exceed the page margins.
+ if(mbExportShapeSelection)
+ return;
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "ClipPathGroup" );
+ SvXMLElementExport aDefsElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+ {
+ msClipPathId = "presentation_clip_path";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", msClipPathId );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clipPathUnits", "userSpaceOnUse" );
+ SvXMLElementExport aClipPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "clipPath", true, true );
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", OUString::number( nDocX ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", OUString::number( nDocY ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::number( nDocWidth ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::number( nDocHeight ) );
+ SvXMLElementExport aRectElem( *mpSVGExport, XML_NAMESPACE_NONE, "rect", true, true );
+ }
+ }
+ // Create a ClipPath element applied to the leaving slide in order
+ // to avoid that slide borders are visible during transition
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "presentation_clip_path_shrink" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clipPathUnits", "userSpaceOnUse" );
+ SvXMLElementExport aClipPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "clipPath", true, true );
+ {
+ sal_Int32 nDocWidthExt = nDocWidth / 500;
+ sal_Int32 nDocHeightExt = nDocHeight / 500;
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", OUString::number( nDocX + nDocWidthExt / 2 ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", OUString::number( nDocY + nDocHeightExt / 2) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::number( nDocWidth - nDocWidthExt ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::number( nDocHeight - nDocHeightExt ) );
+ SvXMLElementExport aRectElem( *mpSVGExport, XML_NAMESPACE_NONE, "rect", true, true );
+ }
+ }
+}
+
+void SVGFilter::implExportDocumentHeaderWriterOrCalc(sal_Int32 nDocX, sal_Int32 nDocY,
+ sal_Int32 nDocWidth, sal_Int32 nDocHeight)
+{
+ OUString aAttr;
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "version", "1.2" );
+
+ aAttr = OUString::number( nDocWidth * 0.01 ) + "mm";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", aAttr );
+
+ aAttr = OUString::number( nDocHeight * 0.01 ) + "mm";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", aAttr );
+
+ aAttr = OUString::number(nDocX) + " " + OUString::number(nDocY) + " " +
+ OUString::number(nDocWidth) + " " + OUString::number(nDocHeight);
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", "xMidYMid" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill-rule", "evenodd" );
+
+ // standard line width is based on 1 pixel on a 90 DPI device (0.28222mmm)
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-width", OUString::number( 28.222 ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke-linejoin", "round" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns", constSvgNamespace );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:ooo", "http://xml.openoffice.org/svg/export" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:xlink", "http://www.w3.org/1999/xlink" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:office", "urn:oasis:names:tc:opendocument:xmlns:office:1.0" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xmlns:smil", "urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xml:space", "preserve" );
+
+ mpSVGDoc = new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "svg", true, true );
+}
+
+/// Append aField to aFieldSet if it is not already present in the set and create the field id sFieldId
+template< typename TextFieldType >
+static OUString implGenerateFieldId( std::vector< std::unique_ptr<TextField> > & aFieldSet,
+ const TextFieldType & aField,
+ std::u16string_view sOOOElemField,
+ const Reference< css::drawing::XDrawPage >& xMasterPage )
+{
+ bool bFound = false;
+ sal_Int32 i;
+ sal_Int32 nSize = aFieldSet.size();
+ for( i = 0; i < nSize; ++i )
+ {
+ if( *(aFieldSet[i]) == aField )
+ {
+ bFound = true;
+ break;
+ }
+ }
+ OUString sFieldId(OUString::Concat(sOOOElemField) + "_");
+ if( !bFound )
+ {
+ aFieldSet.emplace_back( new TextFieldType( aField ) );
+ }
+ aFieldSet[i]->insertMasterPage( xMasterPage );
+ sFieldId += OUString::number( i );
+ return sFieldId;
+}
+
+
+void SVGFilter::implGenerateMetaData()
+{
+ sal_Int32 nCount = mSelectedPages.size();
+ if( nCount == 0 )
+ return;
+
+ // we wrap all meta presentation info into a svg:defs element
+ SvXMLElementExport aDefsElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", NSPREFIX "meta_slides" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "number-of-slides", OUString::number( nCount ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "start-slide-number", OUString::number( mnVisiblePage ) );
+
+ if( mpSVGExport->IsUsePositionedCharacters() )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "use-positioned-chars", "true" );
+ }
+
+ // Add a (global) Page Numbering Type attribute for the document
+ // NOTE: at present pSdrModel->GetPageNumType() returns always css::style::NumberingType::ARABIC
+ // so the following code fragment is pretty useless
+ sal_Int32 nPageNumberingType = css::style::NumberingType::ARABIC;
+ SvxDrawPage* pSvxDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>( mSelectedPages[0] );
+ if( pSvxDrawPage )
+ {
+ SdrPage* pSdrPage = pSvxDrawPage->GetSdrPage();
+ SdrModel& rSdrModel(pSdrPage->getSdrModelFromSdrPage());
+ nPageNumberingType = rSdrModel.GetPageNumType();
+
+ // That is used by CalcFieldHdl method.
+ mVisiblePagePropSet.nPageNumberingType = nPageNumberingType;
+ }
+ if( nPageNumberingType != css::style::NumberingType::NUMBER_NONE )
+ {
+ OUString sNumberingType;
+ switch( nPageNumberingType )
+ {
+ case css::style::NumberingType::CHARS_UPPER_LETTER:
+ sNumberingType = "alpha-upper";
+ break;
+ case css::style::NumberingType::CHARS_LOWER_LETTER:
+ sNumberingType = "alpha-lower";
+ break;
+ case css::style::NumberingType::ROMAN_UPPER:
+ sNumberingType = "roman-upper";
+ break;
+ case css::style::NumberingType::ROMAN_LOWER:
+ sNumberingType = "roman-lower";
+ break;
+ case css::style::NumberingType::ARABIC:
+ // arabic numbering type is the default, so we do not append any attribute for it
+ default:
+ // in case the numbering type is not handled we fall back on arabic numbering
+ break;
+ }
+ if( !sNumberingType.isEmpty() )
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "page-numbering-type", sNumberingType );
+ }
+
+
+ {
+ SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ const OUString aId( NSPREFIX "meta_slide" );
+ const OUString aElemTextFieldId( aOOOElemTextField );
+ std::vector< std::unique_ptr<TextField> > aFieldSet;
+
+ // dummy slide - used as leaving slide for transition on the first slide
+ if( mbPresentation )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", NSPREFIX "meta_dummy_slide" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, "dummy-slide" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMaster, "dummy-master-page" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrBackgroundVisibility, "hidden" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMasterObjectsVisibility, "hidden" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrHasTransition, "false" );
+ SvXMLElementExport aMetaDummySlideElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ }
+
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ const Reference< css::drawing::XDrawPage > & xDrawPage = mSelectedPages[i];
+ Reference< css::drawing::XMasterPageTarget > xMasterPageTarget( xDrawPage, UNO_QUERY );
+ if (!xMasterPageTarget.is())
+ continue;
+ Reference< css::drawing::XDrawPage > xMasterPage = xMasterPageTarget->getMasterPage();
+ OUString aSlideId(aId + "_" + OUString::number( i ));
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", aSlideId );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, implGetValidIDFromInterface( xDrawPage ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMaster, implGetValidIDFromInterface( xMasterPage ) );
+
+
+ if( mbPresentation )
+ {
+ Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
+
+ if( xPropSet.is() )
+ {
+ OUString sDisplayName;
+ if (xPropSet->getPropertyValue("LinkDisplayName") >>= sDisplayName)
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDisplayName, sDisplayName);
+ }
+
+ bool bBackgroundVisibility = true; // default: visible
+ bool bBackgroundObjectsVisibility = true; // default: visible
+
+ FixedDateTimeField aFixedDateTimeField;
+ VariableDateTimeField aVariableDateTimeField;
+ FooterField aFooterField;
+
+ // check if the slide has a custom background which overlaps the master page background
+ Reference< XPropertySet > xBackground;
+ xPropSet->getPropertyValue( "Background" ) >>= xBackground;
+ if( xBackground.is() )
+ {
+ drawing::FillStyle aFillStyle;
+ bool assigned = ( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle );
+ // has a custom background ?
+ if( assigned && aFillStyle != drawing::FillStyle_NONE )
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrHasCustomBackground, "true" );
+ }
+
+ xPropSet->getPropertyValue( "IsBackgroundVisible" ) >>= bBackgroundVisibility;
+ // in case the attribute is set to its default value it is not appended to the meta-slide element
+ if( !bBackgroundVisibility ) // visibility default value: 'visible'
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrBackgroundVisibility, "hidden" );
+
+ // Page Number, Date/Time, Footer and Header Fields are regarded as background objects.
+ // So bBackgroundObjectsVisibility overrides visibility of master page text fields.
+ xPropSet->getPropertyValue( "IsBackgroundObjectsVisible" ) >>= bBackgroundObjectsVisibility;
+ if( bBackgroundObjectsVisibility ) // visibility default value: 'visible'
+ {
+ bool bPageNumberVisibility = false; // default: hidden
+ bool bDateTimeVisibility = true; // default: visible
+ bool bFooterVisibility = true; // default: visible
+
+ // Page Number Field
+ xPropSet->getPropertyValue( "IsPageNumberVisible" ) >>= bPageNumberVisibility;
+ bPageNumberVisibility = bPageNumberVisibility && ( nPageNumberingType != css::style::NumberingType::NUMBER_NONE );
+ if( bPageNumberVisibility ) // visibility default value: 'hidden'
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "page-number-visibility", "visible" );
+ }
+
+ // Date/Time Field
+ xPropSet->getPropertyValue( "IsDateTimeVisible" ) >>= bDateTimeVisibility;
+ if( bDateTimeVisibility ) // visibility default value: 'visible'
+ {
+ bool bDateTimeFixed = true; // default: fixed
+ xPropSet->getPropertyValue( "IsDateTimeFixed" ) >>= bDateTimeFixed;
+ if( bDateTimeFixed ) // we are interested only in the field text not in the date/time format
+ {
+ xPropSet->getPropertyValue( "DateTimeText" ) >>= aFixedDateTimeField.text;
+ if( !aFixedDateTimeField.text.isEmpty() )
+ {
+ OUString sFieldId = implGenerateFieldId( aFieldSet, aFixedDateTimeField, aElemTextFieldId, xMasterPage );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeField, sFieldId );
+ }
+ }
+ else // the inverse applies: we are interested only in the date/time format not in the field text
+ {
+ xPropSet->getPropertyValue( "DateTimeFormat" ) >>= aVariableDateTimeField.format;
+ OUString sFieldId = implGenerateFieldId( aFieldSet, aVariableDateTimeField, aElemTextFieldId, xMasterPage );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrDateTimeField, sFieldId );
+ }
+ }
+ else
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "date-time-visibility", "hidden" );
+ }
+
+ // Footer Field
+ xPropSet->getPropertyValue( "IsFooterVisible" ) >>= bFooterVisibility;
+ if( bFooterVisibility ) // visibility default value: 'visible'
+ {
+ xPropSet->getPropertyValue( "FooterText" ) >>= aFooterField.text;
+ if( !aFooterField.text.isEmpty() )
+ {
+ OUString sFieldId = implGenerateFieldId( aFieldSet, aFooterField, aElemTextFieldId, xMasterPage );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrFooterField, sFieldId );
+ }
+ }
+ else
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "footer-visibility", "hidden" );
+ }
+ }
+ else
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrMasterObjectsVisibility, "hidden" );
+ }
+
+ sal_Int32 nChange(0);
+
+ if( xPropSet->getPropertySetInfo()->hasPropertyByName( "Change" ) &&
+ (xPropSet->getPropertyValue( "Change" ) >>= nChange ) && nChange == 1 )
+ {
+ double fSlideDuration(0);
+ if( xPropSet->getPropertySetInfo()->hasPropertyByName( "HighResDuration" ) &&
+ (xPropSet->getPropertyValue( "HighResDuration" ) >>= fSlideDuration) )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlideDuration, OUString::number(fSlideDuration) );
+ }
+ }
+ // We look for a slide transition.
+ // Transition properties are exported together with animations.
+ sal_Int16 nTransitionType(0);
+ if( xPropSet->getPropertySetInfo()->hasPropertyByName( "TransitionType" ) &&
+ (xPropSet->getPropertyValue( "TransitionType" ) >>= nTransitionType) )
+ {
+ sal_Int16 nTransitionSubType(0);
+ if( xPropSet->getPropertyValue( "TransitionSubtype" ) >>= nTransitionSubType )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrHasTransition, "true" );
+ }
+ }
+
+ }
+ }
+
+ {
+ SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ } // when the aExp2 destructor is called the </g> tag is appended to the output file
+ }
+
+ // export text field elements
+ if( mbPresentation )
+ {
+ for( sal_Int32 i = 0, nSize = aFieldSet.size(); i < nSize; ++i )
+ {
+ OUString sElemId = OUString::Concat(aOOOElemTextField) + "_" + OUString::number( i );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sElemId );
+ aFieldSet[i]->elementExport( mpSVGExport.get() );
+ }
+ if( mpSVGExport->IsEmbedFonts() && mpSVGExport->IsUsePositionedCharacters() )
+ {
+ for(const std::unique_ptr<TextField>& i : aFieldSet)
+ {
+ i->growCharSet( mTextFieldCharSets );
+ }
+ }
+ }
+
+ // text fields are used only for generating meta info so we don't need them anymore
+ aFieldSet.clear();
+ }
+}
+
+
+void SVGFilter::implExportAnimations()
+{
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "presentation-animations" );
+ SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ for(const uno::Reference<drawing::XDrawPage> & mSelectedPage : mSelectedPages)
+ {
+ Reference< XPropertySet > xProps( mSelectedPage, UNO_QUERY );
+
+ if( xProps.is() && xProps->getPropertySetInfo()->hasPropertyByName( "TransitionType" ) )
+ {
+ sal_Int16 nTransition = 0;
+ xProps->getPropertyValue( "TransitionType" ) >>= nTransition;
+ // we have a slide transition ?
+ bool bHasEffects = ( nTransition != 0 );
+
+ Reference< XAnimationNodeSupplier > xAnimNodeSupplier( mSelectedPage, UNO_QUERY );
+ if( xAnimNodeSupplier.is() )
+ {
+ Reference< XAnimationNode > xRootNode = xAnimNodeSupplier->getAnimationNode();
+ if( xRootNode.is() )
+ {
+ if( !bHasEffects )
+ {
+ // first check if there are no animations
+ Reference< XEnumerationAccess > xEnumerationAccess( xRootNode, UNO_QUERY_THROW );
+ Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_SET_THROW );
+ if( xEnumeration->hasMoreElements() )
+ {
+ // first child node may be an empty main sequence, check this
+ Reference< XAnimationNode > xMainNode( xEnumeration->nextElement(), UNO_QUERY_THROW );
+ Reference< XEnumerationAccess > xMainEnumerationAccess( xMainNode, UNO_QUERY_THROW );
+ Reference< XEnumeration > xMainEnumeration( xMainEnumerationAccess->createEnumeration(), UNO_SET_THROW );
+
+ // only export if the main sequence is not empty or if there are additional
+ // trigger sequences
+ bHasEffects = xMainEnumeration->hasMoreElements() || xEnumeration->hasMoreElements();
+ }
+ }
+ if( bHasEffects )
+ {
+ OUString sId = implGetValidIDFromInterface( mSelectedPage );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, sId );
+ sId += "-animations";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Animations" );
+ SvXMLElementExport aDefsElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ rtl::Reference< xmloff::AnimationsExporter > xAnimationsExporter = new xmloff::AnimationsExporter( *mpSVGExport, xProps );
+ xAnimationsExporter->prepare( xRootNode );
+ xAnimationsExporter->exportAnimations( xRootNode );
+ }
+ }
+ }
+ }
+ }
+}
+
+
+void SVGFilter::implExportTextShapeIndex()
+{
+ if(mbExportShapeSelection)
+ return;
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "TextShapeIndex" );
+ SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ sal_Int32 nCount = mSelectedPages.size();
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ const Reference< css::drawing::XDrawPage > & xDrawPage = mSelectedPages[i];
+ if( mTextShapeIdListMap.find( xDrawPage ) != mTextShapeIdListMap.end() )
+ {
+ OUString sTextShapeIdList = mTextShapeIdListMap[xDrawPage].trim();
+
+ const OUString& rPageId = implGetValidIDFromInterface( Reference<XInterface>(xDrawPage, UNO_QUERY) );
+ if( !rPageId.isEmpty() && !sTextShapeIdList.isEmpty() )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrSlide, rPageId );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "id-list", sTextShapeIdList );
+ SvXMLElementExport aGElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ }
+ }
+ }
+}
+
+
+void SVGFilter::implEmbedBulletGlyphs()
+{
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "EmbeddedBulletChars" );
+ SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ OUString sPathData = "M 580,1141 L 1163,571 580,0 -4,571 580,1141 Z";
+ implEmbedBulletGlyph( 57356, sPathData );
+ sPathData = "M 8,1128 L 1137,1128 1137,0 8,0 8,1128 Z";
+ implEmbedBulletGlyph( 57354, sPathData );
+ sPathData = "M 174,0 L 602,739 174,1481 1456,739 174,0 Z M 1358,739 L 309,1346 659,739 1358,739 Z";
+ implEmbedBulletGlyph( 10146, sPathData );
+ sPathData = "M 2015,739 L 1276,0 717,0 1260,543 174,543 174,936 1260,936 717,1481 1274,1481 2015,739 Z";
+ implEmbedBulletGlyph( 10132, sPathData );
+ sPathData = "M 0,-2 C -7,14 -16,27 -25,37 L 356,567 C 262,823 215,952 215,954 215,979 228,992 255,992 264,992 276,990 289,987 310,991 331,999 354,1012 L 381,999 492,748 772,1049 836,1024 860,1049 C 881,1039 901,1025 922,1006 886,937 835,863 770,784 769,783 710,716 594,584 L 774,223 C 774,196 753,168 711,139 L 727,119 C 717,90 699,76 672,76 641,76 570,178 457,381 L 164,-76 C 142,-110 111,-127 72,-127 30,-127 9,-110 8,-76 1,-67 -2,-52 -2,-32 -2,-23 -1,-13 0,-2 Z";
+ implEmbedBulletGlyph( 10007, sPathData );
+ sPathData = "M 285,-33 C 182,-33 111,30 74,156 52,228 41,333 41,471 41,549 55,616 82,672 116,743 169,778 240,778 293,778 328,747 346,684 L 369,508 C 377,444 397,411 428,410 L 1163,1116 C 1174,1127 1196,1133 1229,1133 1271,1133 1292,1118 1292,1087 L 1292,965 C 1292,929 1282,901 1262,881 L 442,47 C 390,-6 338,-33 285,-33 Z";
+ implEmbedBulletGlyph( 10004, sPathData );
+ sPathData = "M 813,0 C 632,0 489,54 383,161 276,268 223,411 223,592 223,773 276,916 383,1023 489,1130 632,1184 813,1184 992,1184 1136,1130 1245,1023 1353,916 1407,772 1407,592 1407,412 1353,268 1245,161 1136,54 992,0 813,0 Z";
+ implEmbedBulletGlyph( 9679, sPathData );
+ sPathData = "M 346,457 C 273,457 209,483 155,535 101,586 74,649 74,723 74,796 101,859 155,911 209,963 273,989 346,989 419,989 480,963 531,910 582,859 608,796 608,723 608,648 583,586 532,535 482,483 420,457 346,457 Z";
+ implEmbedBulletGlyph( 8226, sPathData );
+ sPathData = "M -4,459 L 1135,459 1135,606 -4,606 -4,459 Z";
+ implEmbedBulletGlyph( 8211, sPathData );
+ sPathData = "M 173,740 C 173,903 231,1043 346,1159 462,1274 601,1332 765,1332 928,1332 1067,1274 1183,1159 1299,1043 1357,903 1357,740 1357,577 1299,437 1183,322 1067,206 928,148 765,148 601,148 462,206 346,322 231,437 173,577 173,740 Z";
+ implEmbedBulletGlyph( 61548, sPathData );
+}
+
+
+void SVGFilter::implEmbedBulletGlyph( sal_Unicode cBullet, const OUString & sPathData )
+{
+ OUString sId = "bullet-char-template-" + OUString::number( static_cast<sal_Int32>(cBullet) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+
+ OUString sFactor = OUString::number( 1.0 / 2048 );
+ OUString sTransform = "scale(" + sFactor + ",-" + sFactor + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "transform", sTransform );
+
+ SvXMLElementExport aGElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "d", sPathData );
+ SvXMLElementExport aPathElem( *mpSVGExport, XML_NAMESPACE_NONE, "path", true, true );
+
+ mpSVGExport->SetEmbeddedBulletGlyph(cBullet);
+}
+
+void SVGFilter::implExportBackgroundBitmaps()
+{
+ if (maBitmapActionMap.empty())
+ return;
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BackgroundBitmaps" );
+ SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ OUString sId;
+ for( const auto& rItem : maBitmapActionMap )
+ {
+ BitmapChecksum nChecksum = rItem.first;
+ const GDIMetaFile& aEmbeddedBitmapMtf = *(rItem.second);
+ MetaAction* pBitmapAction = aEmbeddedBitmapMtf.GetAction( 0 );
+ if( pBitmapAction )
+ {
+ sId = "bitmap(" + OUString::number( nChecksum ) + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+
+ const Point aPos; // (0, 0)
+ const Size aSize = aEmbeddedBitmapMtf.GetPrefSize();
+ mpSVGWriter->WriteMetaFile( aPos, aSize, aEmbeddedBitmapMtf, 0xffffffff );
+ }
+ }
+}
+
+void SVGFilter::implExportTiledBackground()
+{
+ if( maPatterProps.empty() )
+ return;
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BackgroundPatterns" );
+ SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ for( const auto& [ rSlideId, rData ] : maPatterProps )
+ {
+ auto aBitmapActionIt = maBitmapActionMap.find( rData.aBitmapChecksum );
+ if( aBitmapActionIt != maBitmapActionMap.end() )
+ {
+ // pattern element attributes
+ const OUString sPatternId = getPatternIdForTiledBackground( rSlideId, rData.aBitmapChecksum );
+ // <pattern> <use>
+ {
+ // pattern element attributes
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sPatternId );
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", OUString::number( rData.aPos.X() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", OUString::number( rData.aPos.Y() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::number( rData.aSize.Width() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::number( rData.aSize.Height() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "patternUnits", "userSpaceOnUse" );
+
+ SvXMLElementExport aPatternElem( *mpSVGExport, XML_NAMESPACE_NONE, "pattern", true, true );
+
+ // use element attributes
+ const Size& aOrigSize = aBitmapActionIt->second->GetPrefSize();
+ OUString sTransform;
+ Fraction aFractionX( rData.aSize.Width(), aOrigSize.Width() );
+ Fraction aFractionY( rData.aSize.Height(), aOrigSize.Height() );
+ double scaleX = rtl_math_round( double(aFractionX), 3, rtl_math_RoundingMode::rtl_math_RoundingMode_Corrected );
+ double scaleY = rtl_math_round( double(aFractionY), 3, rtl_math_RoundingMode::rtl_math_RoundingMode_Corrected );
+ if( !rtl_math_approxEqual( scaleX, 1.0 ) || !rtl_math_approxEqual( scaleY, 1.0 ) )
+ sTransform += " scale(" + OUString::number( double(aFractionX) ) + ", " + OUString::number( double(aFractionY) ) + ")";
+
+ if( !sTransform.isEmpty() )
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "transform", sTransform );
+
+ // referenced bitmap
+ OUString sRefId = "#bitmap(" + OUString::number( rData.aBitmapChecksum ) + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xlink:href", sRefId );
+
+ SvXMLElementExport aUseElem( *mpSVGExport, XML_NAMESPACE_NONE, "use", true, true );
+ } // </use> </pattern>
+
+ // <g> <rect>
+ {
+ // group
+ const OUString sBgId = getIdForTiledBackground( rSlideId, rData.aBitmapChecksum );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sBgId );
+
+ SvXMLElementExport aGroupElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ // rectangle
+ const OUString sUrl = "url(#" + sPatternId + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", "0" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", "0" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::number( rData.aSlideSize.Width() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::number( rData.aSlideSize.Height() ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke", "none" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill", sUrl );
+
+ SvXMLElementExport aRectElem( *mpSVGExport, XML_NAMESPACE_NONE, "rect", true, true );
+ } // </g> </rect>
+ }
+ }
+}
+
+/** SVGFilter::implExportTextEmbeddedBitmaps
+ We export bitmaps embedded into text shapes, such as those used by list
+ items with image style, only once in a specific defs element.
+ */
+void SVGFilter::implExportTextEmbeddedBitmaps()
+{
+ if (mEmbeddedBitmapActionSet.empty())
+ return;
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "TextEmbeddedBitmaps" );
+ SvXMLElementExport aDefsContainerElem( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true );
+
+ OUString sId;
+
+ for (auto const& embeddedBitmapAction : mEmbeddedBitmapActionSet)
+ {
+ const GDIMetaFile& aMtf = embeddedBitmapAction.GetRepresentation();
+
+ if( aMtf.GetActionSize() == 1 )
+ {
+ MetaAction* pAction = aMtf.GetAction( 0 );
+ if( pAction )
+ {
+ BitmapChecksum nId = GetBitmapChecksum( pAction );
+ sId = "bitmap(" + OUString::number( nId ) + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+
+ const Reference< XInterface >& rxShape = embeddedBitmapAction.GetObject();
+ Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY );
+ css::awt::Rectangle aBoundRect;
+ if( xShapePropSet.is() && ( xShapePropSet->getPropertyValue( "BoundRect" ) >>= aBoundRect ) )
+ {
+ // Origin of the coordinate device must be (0,0).
+ const Point aTopLeft;
+ const Size aSize( aBoundRect.Width, aBoundRect.Height );
+
+ Point aPt;
+ MetaBitmapActionGetPoint( pAction, aPt );
+ // The image must be exported with x, y attribute set to 0,
+ // on the contrary when referenced by a <use> element,
+ // specifying the wanted position, they will result
+ // misplaced.
+ pAction->Move( -aPt.X(), -aPt.Y() );
+ mpSVGWriter->WriteMetaFile( aTopLeft, aSize, aMtf, 0xffffffff );
+ // We reset to the original values so that when the <use>
+ // element is created the x, y attributes are correct.
+ pAction->Move( aPt.X(), aPt.Y() );
+ }
+ else
+ {
+ OSL_FAIL( "implExportTextEmbeddedBitmaps: no shape bounding box." );
+ return;
+ }
+ }
+ else
+ {
+ OSL_FAIL( "implExportTextEmbeddedBitmaps: metafile should have MetaBmpExScaleAction only." );
+ return;
+ }
+ }
+ else
+ {
+ OSL_FAIL( "implExportTextEmbeddedBitmaps: metafile should have a single action." );
+ return;
+ }
+ }
+}
+
+void SVGFilter::implGenerateScript()
+{
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "type", "text/ecmascript" );
+
+ {
+ SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "script", true, true );
+ Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
+
+ if( xExtDocHandler.is() )
+ {
+ for (size_t i = 0; i < N_SVGSCRIPT_FRAGMENTS; ++i)
+ {
+ xExtDocHandler->unknown(OUString::createFromAscii(g_SVGScripts[i]));
+ }
+ }
+ }
+}
+
+
+Any SVGFilter::implSafeGetPagePropSet( const OUString & sPropertyName,
+ const Reference< XPropertySet > & rxPropSet,
+ const Reference< XPropertySetInfo > & rxPropSetInfo )
+{
+ Any result;
+ if( rxPropSetInfo->hasPropertyByName( sPropertyName ) )
+ {
+ result = rxPropSet->getPropertyValue( sPropertyName );
+ }
+ return result;
+}
+
+
+/** We collect info on master page elements visibility, and placeholder text shape content.
+ This method is used when exporting a single page as implGenerateMetaData is not invoked.
+ */
+void SVGFilter::implGetPagePropSet( const Reference< css::drawing::XDrawPage > & rxPage )
+{
+ mVisiblePagePropSet.bIsBackgroundVisible = true;
+ mVisiblePagePropSet.bAreBackgroundObjectsVisible = true;
+ mVisiblePagePropSet.bIsPageNumberFieldVisible = false;
+ mVisiblePagePropSet.bIsHeaderFieldVisible = false;
+ mVisiblePagePropSet.bIsFooterFieldVisible = true;
+ mVisiblePagePropSet.bIsDateTimeFieldVisible = true;
+ mVisiblePagePropSet.bIsDateTimeFieldFixed = true;
+ mVisiblePagePropSet.nDateTimeFormat = SvxDateFormat::B;
+ mVisiblePagePropSet.nPageNumberingType = css::style::NumberingType::ARABIC;
+
+ // We collect info on master page elements visibility, and placeholder text shape content.
+ Reference< XPropertySet > xPropSet( rxPage, UNO_QUERY );
+ if( !xPropSet.is() )
+ return;
+
+ Reference< XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
+ if( !xPropSetInfo.is() )
+ return;
+
+ implSafeGetPagePropSet( "IsBackgroundVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsBackgroundVisible;
+ implSafeGetPagePropSet( "IsBackgroundObjectsVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bAreBackgroundObjectsVisible;
+ implSafeGetPagePropSet( "IsPageNumberVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsPageNumberFieldVisible;
+ implSafeGetPagePropSet( "IsHeaderVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsHeaderFieldVisible;
+ implSafeGetPagePropSet( "IsFooterVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsFooterFieldVisible;
+ implSafeGetPagePropSet( "IsDateTimeVisible", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsDateTimeFieldVisible;
+
+ implSafeGetPagePropSet( "IsDateTimeFixed", xPropSet, xPropSetInfo ) >>= mVisiblePagePropSet.bIsDateTimeFieldFixed;
+ sal_Int32 nTmp;
+ if (implSafeGetPagePropSet( "DateTimeFormat", xPropSet, xPropSetInfo ) >>= nTmp)
+ mVisiblePagePropSet.nDateTimeFormat = static_cast<SvxDateFormat>(nTmp);
+
+ if( mVisiblePagePropSet.bIsPageNumberFieldVisible )
+ {
+ SvxDrawPage* pSvxDrawPage = comphelper::getFromUnoTunnel<SvxDrawPage>( rxPage );
+ if( pSvxDrawPage )
+ {
+ SdrPage* pSdrPage = pSvxDrawPage->GetSdrPage();
+ SdrModel& rSdrModel(pSdrPage->getSdrModelFromSdrPage());
+ mVisiblePagePropSet.nPageNumberingType = rSdrModel.GetPageNumType();
+ }
+ }
+}
+
+
+bool SVGFilter::implExportMasterPages( const std::vector< Reference< css::drawing::XDrawPage > > & rxPages,
+ sal_Int32 nFirstPage, sal_Int32 nLastPage )
+{
+ DBG_ASSERT( nFirstPage <= nLastPage,
+ "SVGFilter::implExportMasterPages: nFirstPage > nLastPage" );
+
+ // When the exported slides are more than one we wrap master page elements
+ // with a svg <defs> element.
+ OUString aContainerTag = (!mbPresentation) ? OUString( "g" ) : OUString( "defs" );
+ SvXMLElementExport aContainerElement( *mpSVGExport, XML_NAMESPACE_NONE, aContainerTag, true, true );
+
+ // dummy slide - used as leaving slide for transition on the first slide
+ if( mbPresentation )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "dummy-master-page" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrName, "dummy-master-page" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Master_Slide" );
+ SvXMLElementExport aMasterSlideElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "bg-dummy-master-page" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Background" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ SvXMLElementExport aBackgroundElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ }
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "bo-dummy-master-page" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BackgroundObjects" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ SvXMLElementExport aBackgroundObjectElem( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ }
+ }
+
+ bool bRet = false;
+ for( sal_Int32 i = nFirstPage; i <= nLastPage; ++i )
+ {
+ if( rxPages[i].is() )
+ {
+ // add id attribute
+ const OUString & sPageId = implGetValidIDFromInterface( rxPages[i] );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sPageId );
+
+ bRet = implExportPage( sPageId, rxPages[i], rxPages[i], true /* is a master page */ ) || bRet;
+ }
+ }
+ return bRet;
+}
+
+
+void SVGFilter::implExportDrawPages( const std::vector< Reference< css::drawing::XDrawPage > > & rxPages,
+ sal_Int32 nFirstPage, sal_Int32 nLastPage )
+{
+ DBG_ASSERT( nFirstPage <= nLastPage,
+ "SVGFilter::implExportDrawPages: nFirstPage > nLastPage" );
+
+ // dummy slide - used as leaving slide for transition on the first slide
+ if( mbPresentation && !mbExportShapeSelection)
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "DummySlide" );
+ SvXMLElementExport aDummySlideElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ {
+ SvXMLElementExport aGElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", "dummy-slide" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Slide" );
+ OUString sClipPathAttrValue = "url(#" + msClipPathId + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clip-path", sClipPathAttrValue );
+ SvXMLElementExport aSlideElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrName, "dummy-page" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Page" );
+ SvXMLElementExport aPageElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+ }
+ }
+ }
+ }
+
+ if(!mbExportShapeSelection)
+ {
+ // We wrap all slide in a group element with class name "SlideGroup".
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "SlideGroup" );
+ SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ for( sal_Int32 i = nFirstPage; i <= nLastPage; ++i )
+ {
+ Reference< css::drawing::XShapes > xShapes;
+
+ if (mbExportShapeSelection)
+ {
+ // #i124608# export a given object selection
+ xShapes = maShapeSelection;
+ }
+ else
+ {
+ xShapes = rxPages[i];
+ }
+
+ if( xShapes.is() )
+ {
+ // Insert the <g> open tag related to the svg element for
+ // handling a slide visibility.
+ // In case the exported slides are more than one the initial
+ // visibility of each slide is set to 'hidden'.
+ if( mbPresentation )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ }
+ SvXMLElementExport aGElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+
+ {
+ // Insert a further inner the <g> open tag for handling elements
+ // inserted before or after a slide: that is used for some
+ // when switching from the last to the first slide.
+ const OUString & sPageId = implGetValidIDFromInterface( rxPages[i] );
+ OUString sContainerId = "container-" + sPageId;
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sContainerId );
+ SvXMLElementExport aContainerExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ {
+ // add id attribute
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sPageId );
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Slide" );
+
+ // Adding a clip path to each exported slide , so in case
+ // bitmaps or other elements exceed the slide margins, they are
+ // trimmed, even when they are shown inside a thumbnail view.
+ OUString sClipPathAttrValue = "url(#" + msClipPathId + ")";
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "clip-path", sClipPathAttrValue );
+
+ SvXMLElementExport aSlideElement( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ implExportPage( sPageId, rxPages[i], xShapes, false /* is not a master page */ );
+ }
+ } // append the </g> closing tag related to inserted elements
+ } // append the </g> closing tag related to the svg element handling the slide visibility
+ }
+ }
+ else
+ {
+ assert(maShapeSelection.is());
+ assert(rxPages.size() == 1);
+
+ const OUString & sPageId = implGetValidIDFromInterface( rxPages[0] );
+ implExportPage( sPageId, rxPages[0], maShapeSelection, false /* is not a master page */ );
+ }
+}
+
+
+bool SVGFilter::implExportPage( std::u16string_view sPageId,
+ const Reference< css::drawing::XDrawPage > & rxPage,
+ const Reference< css::drawing::XShapes > & xShapes,
+ bool bMaster )
+{
+ bool bRet = false;
+
+ {
+ OUString sPageName = implGetInterfaceName( rxPage );
+ if( mbPresentation && !sPageName.isEmpty() )
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, aOOOAttrName, sPageName );
+
+ {
+ Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
+
+ if( xExtDocHandler.is() )
+ {
+ OUString aDesc;
+
+ if( bMaster )
+ aDesc = "Master_Slide";
+ else
+ aDesc = "Page";
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", aDesc );
+ }
+ }
+
+ // insert the <g> open tag related to the DrawPage/MasterPage
+ SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ // In case the page has a background object we append it .
+ if( mpObjects->find( rxPage ) != mpObjects->end() )
+ {
+ const GDIMetaFile& rMtf = (*mpObjects)[ rxPage ].GetRepresentation();
+ if( rMtf.GetActionSize() )
+ {
+ // If this is not a master page wrap the slide custom background
+ // by a <defs> element.
+ // Slide custom background, if any, is referenced at a different position
+ // in order to not overlap background objects.
+ std::unique_ptr<SvXMLElementExport> xDefsExp;
+ if (!bMaster) // insert the <defs> open tag related to the slide background
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "SlideBackground" );
+ xDefsExp.reset( new SvXMLElementExport( *mpSVGExport, XML_NAMESPACE_NONE, "defs", true, true ) );
+ }
+ {
+ // background id = "bg-" + page id
+ OUString sBackgroundId = OUString::Concat("bg-") + sPageId;
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sBackgroundId );
+
+ // At present (LibreOffice 3.4.0) the 'IsBackgroundVisible' property is not handled
+ // by Impress; anyway we handle this property as referring only to the visibility
+ // of the master page background. So if a slide has its own background object,
+ // the visibility of such a background object is always inherited from the visibility
+ // of the parent slide regardless of the value of the 'IsBackgroundVisible' property.
+ // This means that we need to set up the visibility attribute only for the background
+ // element of a master page.
+ if( !mbPresentation && bMaster )
+ {
+ if( !mVisiblePagePropSet.bIsBackgroundVisible )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ }
+ }
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Background" );
+
+ // insert the <g> open tag related to the Background
+ SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ // append all elements that make up the Background
+ const Point aNullPt;
+ mpSVGWriter->WriteMetaFile( aNullPt, rMtf.GetPrefSize(), rMtf, SVGWRITER_WRITE_FILL );
+ } // insert the </g> closing tag related to the Background
+
+ } // insert the </defs> closing tag related to the slide background
+ }
+
+ // In case we are dealing with a master page we need to group all its shapes
+ // into a group element, this group will make up the so named "background objects"
+ if( bMaster )
+ {
+ // background objects id = "bo-" + page id
+ OUString sBackgroundObjectsId = OUString::Concat("bo-") + sPageId;
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", sBackgroundObjectsId );
+ if( !mbPresentation )
+ {
+ if( !mVisiblePagePropSet.bAreBackgroundObjectsVisible )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ }
+ }
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BackgroundObjects" );
+
+ // insert the <g> open tag related to the Background Objects
+ SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ // append all shapes that make up the Master Slide
+ bRet = implExportShapes( xShapes, true ) || bRet;
+ } // append the </g> closing tag related to the Background Objects
+ else
+ {
+ // append all shapes that make up the Slide
+ bRet = implExportShapes( xShapes, false ) || bRet;
+ }
+ } // append the </g> closing tag related to the Slide/Master_Slide
+
+ return bRet;
+}
+
+
+bool SVGFilter::implExportShapes( const Reference< css::drawing::XShapes >& rxShapes, bool bMaster )
+{
+ Reference< css::drawing::XShape > xShape;
+ bool bRet = false;
+
+ for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i )
+ {
+ if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() )
+ bRet = implExportShape( xShape, bMaster ) || bRet;
+
+ xShape = nullptr;
+ }
+
+ return bRet;
+}
+
+
+bool SVGFilter::implExportShape( const Reference< css::drawing::XShape >& rxShape, bool bMaster )
+{
+ Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY );
+ bool bRet = false;
+
+ if( xShapePropSet.is() )
+ {
+ const OUString aShapeType( rxShape->getShapeType() );
+ bool bHideObj = false;
+
+ if( mbPresentation )
+ {
+ xShapePropSet->getPropertyValue( "IsEmptyPresentationObject" ) >>= bHideObj;
+ }
+
+ OUString aShapeClass = implGetClassFromShape( rxShape );
+ if( bMaster )
+ {
+ if( aShapeClass == "TitleText" || aShapeClass == "Outline" )
+ bHideObj = true;
+ }
+
+ if( !bHideObj )
+ {
+ if( aShapeType.lastIndexOf( "drawing.GroupShape" ) != -1 )
+ {
+ Reference< css::drawing::XShapes > xShapes( rxShape, UNO_QUERY );
+
+ if( xShapes.is() )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "Group" );
+ const OUString& rShapeId = implGetValidIDFromInterface( Reference<XInterface>(rxShape, UNO_QUERY) );
+ if( !rShapeId.isEmpty() )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", rShapeId );
+ }
+ SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ bRet = implExportShapes( xShapes, bMaster );
+ }
+ }
+
+ if( !bRet && mpObjects->find( rxShape ) != mpObjects->end() )
+ {
+ css::awt::Rectangle aBoundRect;
+ const GDIMetaFile& rMtf = (*mpObjects)[ rxShape ].GetRepresentation();
+
+ xShapePropSet->getPropertyValue( "BoundRect" ) >>= aBoundRect;
+
+ const Point aTopLeft( aBoundRect.X, aBoundRect.Y );
+ const Size aSize( aBoundRect.Width, aBoundRect.Height );
+
+ if( rMtf.GetActionSize() )
+ { // for text field shapes we set up text-adjust attributes
+ // and set visibility to hidden
+ OUString aElementId;
+
+ if( mbPresentation )
+ {
+ bool bIsPageNumber = ( aShapeClass == "Slide_Number" );
+ bool bIsFooter = ( aShapeClass == "Footer" );
+ bool bIsDateTime = ( aShapeClass == "Date/Time" );
+ bool bTextField = bIsPageNumber || bIsFooter || bIsDateTime;
+ if( bTextField )
+ {
+ // to notify to the SVGActionWriter::ImplWriteActions method
+ // that we are dealing with a placeholder shape
+ aElementId = sPlaceholderTag;
+
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "visibility", "hidden" );
+ }
+
+ if( bTextField || ( aShapeClass == "TextShape" ) )
+ {
+ sal_uInt16 nTextAdjust = sal_uInt16(ParagraphAdjust_LEFT);
+ OUString sTextAdjust;
+ xShapePropSet->getPropertyValue( "ParaAdjust" ) >>= nTextAdjust;
+
+ switch( static_cast<ParagraphAdjust>(nTextAdjust) )
+ {
+ case ParagraphAdjust_LEFT:
+ sTextAdjust = "left";
+ break;
+ case ParagraphAdjust_CENTER:
+ sTextAdjust = "center";
+ break;
+ case ParagraphAdjust_RIGHT:
+ sTextAdjust = "right";
+ break;
+ default:
+ break;
+ }
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, NSPREFIX "text-adjust", sTextAdjust );
+ }
+ }
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", aShapeClass );
+ SvXMLElementExport aExp( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ Reference< XExtendedDocumentHandler > xExtDocHandler( mpSVGExport->GetDocHandler(), UNO_QUERY );
+
+ OUString aTitle;
+ xShapePropSet->getPropertyValue( "Title" ) >>= aTitle;
+ if( !aTitle.isEmpty() )
+ {
+ SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "title", true, true );
+ xExtDocHandler->characters( aTitle );
+ }
+
+ OUString aDescription;
+ xShapePropSet->getPropertyValue( "Description" ) >>= aDescription;
+ if( !aDescription.isEmpty() )
+ {
+ SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "desc", true, true );
+ xExtDocHandler->characters( aDescription );
+ }
+
+
+ const OUString& rShapeId = implGetValidIDFromInterface( Reference<XInterface>(rxShape, UNO_QUERY) );
+ if( !rShapeId.isEmpty() )
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "id", rShapeId );
+ }
+
+ const GDIMetaFile* pEmbeddedBitmapsMtf = nullptr;
+ if( mEmbeddedBitmapActionMap.find( rxShape ) != mEmbeddedBitmapActionMap.end() )
+ {
+ pEmbeddedBitmapsMtf = &( mEmbeddedBitmapActionMap[ rxShape ].GetRepresentation() );
+ }
+
+ {
+ OUString aBookmark;
+ Reference<XPropertySetInfo> xShapePropSetInfo = xShapePropSet->getPropertySetInfo();
+ if(xShapePropSetInfo->hasPropertyByName("Bookmark"))
+ {
+ xShapePropSet->getPropertyValue( "Bookmark" ) >>= aBookmark;
+ }
+
+ SvXMLElementExport aExp2( *mpSVGExport, XML_NAMESPACE_NONE, "g", true, true );
+
+ // export the shape bounding box
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "class", "BoundingBox" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "stroke", "none" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "fill", "none" );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "x", OUString::number( aBoundRect.X ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "y", OUString::number( aBoundRect.Y ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "width", OUString::number( aBoundRect.Width ) );
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "height", OUString::number( aBoundRect.Height ) );
+ SvXMLElementExport aBB( *mpSVGExport, XML_NAMESPACE_NONE, "rect", true, true );
+ }
+
+ if( !aBookmark.isEmpty() )
+ {
+ INetURLObject aINetURLObject(aBookmark);
+ if (!aINetURLObject.HasError()
+ && aINetURLObject.GetProtocol() != INetProtocol::Javascript)
+ {
+ mpSVGExport->AddAttribute( XML_NAMESPACE_NONE, "xlink:href", aBookmark);
+ SvXMLElementExport alinkA( *mpSVGExport, XML_NAMESPACE_NONE, "a", true, true );
+ mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf,
+ 0xffffffff,
+ aElementId,
+ &rxShape,
+ pEmbeddedBitmapsMtf );
+ }
+ }
+ else
+ {
+ mpSVGWriter->WriteMetaFile( aTopLeft, aSize, rMtf,
+ 0xffffffff,
+ aElementId,
+ &rxShape,
+ pEmbeddedBitmapsMtf );
+ }
+ }
+ }
+
+ bRet = true;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+
+bool SVGFilter::implCreateObjects()
+{
+ if (mbExportShapeSelection)
+ {
+ // #i124608# export a given object selection
+ if (!mSelectedPages.empty() && mSelectedPages[0].is())
+ {
+ implCreateObjectsFromShapes(mSelectedPages[0], maShapeSelection);
+ return true;
+ }
+ return false;
+ }
+
+ sal_Int32 i, nCount;
+
+ for( i = 0, nCount = mMasterPageTargets.size(); i < nCount; ++i )
+ {
+ const Reference< css::drawing::XDrawPage > & xMasterPage = mMasterPageTargets[i];
+
+ if( xMasterPage.is() )
+ {
+ mCreateOjectsCurrentMasterPage = xMasterPage;
+ implCreateObjectsFromBackground( xMasterPage );
+
+ if( xMasterPage.is() )
+ implCreateObjectsFromShapes( xMasterPage, xMasterPage );
+ }
+ }
+
+ for( i = 0, nCount = mSelectedPages.size(); i < nCount; ++i )
+ {
+ const Reference< css::drawing::XDrawPage > & xDrawPage = mSelectedPages[i];
+
+ if( xDrawPage.is() )
+ {
+ // TODO complete the implementation for exporting custom background for each slide
+ // implementation status:
+ // - hatch stroke color is set to 'none' so the hatch is not visible, why?
+ // - gradient look is not really awesome, too few colors are used;
+ // - gradient and hatch are not exported only once
+ // and then referenced in case more than one slide uses them.
+ Reference< XPropertySet > xPropSet( xDrawPage, UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ Reference< XPropertySet > xBackground;
+ xPropSet->getPropertyValue( "Background" ) >>= xBackground;
+ if( xBackground.is() )
+ {
+ drawing::FillStyle aFillStyle;
+ bool assigned = ( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle );
+ if( assigned && aFillStyle != drawing::FillStyle_NONE )
+ {
+ implCreateObjectsFromBackground( xDrawPage );
+ }
+ }
+ }
+ implCreateObjectsFromShapes( xDrawPage, xDrawPage );
+ }
+ }
+ return true;
+}
+
+
+bool SVGFilter::implCreateObjectsFromShapes( const Reference< css::drawing::XDrawPage > & rxPage, const Reference< css::drawing::XShapes >& rxShapes )
+{
+ Reference< css::drawing::XShape > xShape;
+ bool bRet = false;
+
+ for( sal_Int32 i = 0, nCount = rxShapes->getCount(); i < nCount; ++i )
+ {
+ if( ( rxShapes->getByIndex( i ) >>= xShape ) && xShape.is() )
+ bRet = implCreateObjectsFromShape( rxPage, xShape ) || bRet;
+
+ xShape = nullptr;
+ }
+
+ return bRet;
+}
+
+
+bool SVGFilter::implCreateObjectsFromShape( const Reference< css::drawing::XDrawPage > & rxPage, const Reference< css::drawing::XShape >& rxShape )
+{
+ bool bRet = false;
+ if( rxShape->getShapeType().lastIndexOf( "drawing.GroupShape" ) != -1 )
+ {
+ Reference< css::drawing::XShapes > xShapes( rxShape, UNO_QUERY );
+
+ if( xShapes.is() )
+ bRet = implCreateObjectsFromShapes( rxPage, xShapes );
+ }
+ else
+ {
+ SdrObject* pObj = SdrObject::getSdrObjectFromXShape(rxShape);
+
+ if( pObj )
+ {
+ Graphic aGraphic(SdrExchangeView::GetObjGraphic(*pObj));
+
+ // Writer graphic shapes are handled differently
+ if( mbWriterFilter && aGraphic.GetType() == GraphicType::NONE )
+ {
+ if (rxShape->getShapeType() == "com.sun.star.drawing.GraphicObjectShape")
+ {
+ uno::Reference<beans::XPropertySet> xPropertySet(rxShape, uno::UNO_QUERY);
+ uno::Reference<graphic::XGraphic> xGraphic;
+ xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
+
+ if (!xGraphic.is())
+ return false;
+
+ aGraphic = Graphic(xGraphic);
+ }
+ }
+
+ if( aGraphic.GetType() != GraphicType::NONE )
+ {
+ if( aGraphic.GetType() == GraphicType::Bitmap )
+ {
+ GDIMetaFile aMtf;
+ const Point aNullPt;
+ const Size aSize( pObj->GetCurrentBoundRect().GetSize() );
+
+ aMtf.AddAction( new MetaBmpExScaleAction( aNullPt, aSize, aGraphic.GetBitmapEx() ) );
+ aMtf.SetPrefSize( aSize );
+ aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+
+ (*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
+ }
+ else
+ {
+ if( aGraphic.GetGDIMetaFile().GetActionSize() )
+ {
+ Reference< XText > xText( rxShape, UNO_QUERY );
+ bool bIsTextShape = xText.is();
+
+ if( !mpSVGExport->IsUsePositionedCharacters() && bIsTextShape )
+ {
+ Reference< XPropertySet > xShapePropSet( rxShape, UNO_QUERY );
+
+ if( xShapePropSet.is() )
+ {
+ bool bHideObj = false;
+
+ if( mbPresentation )
+ {
+ xShapePropSet->getPropertyValue( "IsEmptyPresentationObject" ) >>= bHideObj;
+ }
+
+ if( !bHideObj )
+ {
+ // We create a map of text shape ids.
+ implRegisterInterface( rxShape );
+ const OUString& rShapeId = implGetValidIDFromInterface( Reference<XInterface>(rxShape, UNO_QUERY) );
+ if( !rShapeId.isEmpty() )
+ {
+ mTextShapeIdListMap[rxPage] += rShapeId;
+ mTextShapeIdListMap[rxPage] += " ";
+ }
+
+ // We create a set of bitmaps embedded into text shape.
+ GDIMetaFile aMtf;
+ const Size aSize( pObj->GetCurrentBoundRect().GetSize() );
+ MetaAction* pAction;
+ bool bIsTextShapeStarted = false;
+ const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
+ size_t nCount = rMtf.GetActionSize();
+ for( size_t nCurAction = 0; nCurAction < nCount; ++nCurAction )
+ {
+ pAction = rMtf.GetAction( nCurAction );
+ const MetaActionType nType = pAction->GetType();
+
+ if( nType == MetaActionType::COMMENT )
+ {
+ const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
+ if( pA->GetComment().equalsIgnoreAsciiCase("XTEXT_PAINTSHAPE_BEGIN") )
+ {
+ bIsTextShapeStarted = true;
+ }
+ else if( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_PAINTSHAPE_END" ) )
+ {
+ bIsTextShapeStarted = false;
+ }
+ }
+ if( bIsTextShapeStarted && ( nType == MetaActionType::BMPSCALE || nType == MetaActionType::BMPEXSCALE ) )
+ {
+ GDIMetaFile aEmbeddedBitmapMtf;
+ aEmbeddedBitmapMtf.AddAction( pAction );
+ aEmbeddedBitmapMtf.SetPrefSize( aSize );
+ aEmbeddedBitmapMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ mEmbeddedBitmapActionSet.insert( ObjectRepresentation( rxShape, aEmbeddedBitmapMtf ) );
+ aMtf.AddAction( pAction );
+ }
+ }
+ aMtf.SetPrefSize( aSize );
+ aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+ mEmbeddedBitmapActionMap[ rxShape ] = ObjectRepresentation( rxShape, aMtf );
+ }
+ }
+ }
+ }
+ (*mpObjects)[ rxShape ] = ObjectRepresentation( rxShape, aGraphic.GetGDIMetaFile() );
+ }
+ bRet = true;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+
+void SVGFilter::implCreateObjectsFromBackground( const Reference< css::drawing::XDrawPage >& rxDrawPage )
+{
+ Reference< css::drawing::XGraphicExportFilter > xExporter = drawing::GraphicExportFilter::create( mxContext );
+
+ GDIMetaFile aMtf;
+
+ utl::TempFile aFile;
+ aFile.EnableKillingFile();
+
+ Sequence< PropertyValue > aDescriptor{
+ comphelper::makePropertyValue("FilterName", OUString( "SVM" )),
+ comphelper::makePropertyValue("URL", aFile.GetURL()),
+ comphelper::makePropertyValue("ExportOnlyBackground", true)
+ };
+
+ xExporter->setSourceDocument( Reference< XComponent >( rxDrawPage, UNO_QUERY ) );
+ xExporter->filter( aDescriptor );
+ SvmReader aReader( *aFile.GetStream( StreamMode::READ ) );
+ aReader.Read( aMtf );
+
+ bool bIsBitmap = false;
+ bool bIsTiled = false;
+
+ // look for background type
+ Reference< XPropertySet > xPropSet( rxDrawPage, UNO_QUERY );
+ if( xPropSet.is() )
+ {
+ Reference< XPropertySet > xBackground;
+ xPropSet->getPropertyValue( "Background" ) >>= xBackground;
+ if( xBackground.is() )
+ {
+ drawing::FillStyle aFillStyle;
+ if( xBackground->getPropertyValue( "FillStyle" ) >>= aFillStyle )
+ {
+ if( aFillStyle == drawing::FillStyle::FillStyle_BITMAP )
+ {
+ bIsBitmap = true;
+ xBackground->getPropertyValue( "FillBitmapTile" ) >>= bIsTiled;
+
+ // we do not handle tiled background with a row or column offset
+ sal_Int32 nFillBitmapOffsetX = 0, nFillBitmapOffsetY = 0;
+ xBackground->getPropertyValue( "FillBitmapOffsetX" ) >>= nFillBitmapOffsetX;
+ xBackground->getPropertyValue( "FillBitmapOffsetY" ) >>= nFillBitmapOffsetY;
+ bIsTiled = bIsTiled && ( nFillBitmapOffsetX == 0 && nFillBitmapOffsetY == 0 );
+ }
+ }
+ }
+ }
+
+ if( !bIsBitmap )
+ {
+ (*mpObjects)[ rxDrawPage ] = ObjectRepresentation( rxDrawPage, aMtf );
+ return;
+ }
+
+ GDIMetaFile aTiledMtf;
+ bool bBitmapFound = false;
+ MetaAction* pAction;
+ size_t nCount = aMtf.GetActionSize();
+ for( size_t nCurAction = 0; nCurAction < nCount; ++nCurAction )
+ {
+ pAction = aMtf.GetAction( nCurAction );
+ const MetaActionType nType = pAction->GetType();
+
+ // collect bitmap
+ if( nType == MetaActionType::BMPSCALE || nType == MetaActionType::BMPEXSCALE )
+ {
+ if( bBitmapFound )
+ continue;
+ bBitmapFound = true; // the subsequent bitmaps are still the same just translated
+
+ BitmapChecksum nChecksum = GetBitmapChecksum( pAction );
+ if( maBitmapActionMap.find( nChecksum ) == maBitmapActionMap.end() )
+ {
+ Point aPos; // (0, 0)
+ Size aSize;
+ MetaBitmapActionGetOrigSize( pAction, aSize );
+ MetaAction* pBitmapAction = CreateMetaBitmapAction( pAction, aPos, aSize );
+ if( pBitmapAction )
+ {
+ GDIMetaFile* pEmbeddedBitmapMtf = new GDIMetaFile();
+ pEmbeddedBitmapMtf->AddAction( pBitmapAction );
+ pEmbeddedBitmapMtf->SetPrefSize( aSize );
+ pEmbeddedBitmapMtf->SetPrefMapMode( MapMode(MapUnit::Map100thMM) );
+
+ maBitmapActionMap[ nChecksum ].reset( pEmbeddedBitmapMtf );
+ }
+ }
+
+ if( bIsTiled )
+ {
+ // collect data for <pattern> and <rect>
+ const OUString & sPageId = implGetValidIDFromInterface( rxDrawPage );
+ Point aPos;
+ MetaBitmapActionGetPoint( pAction, aPos );
+ Size aSize;
+ MetaBitmapActionGetSize( pAction, aSize );
+
+ sal_Int32 nSlideWidth = 0, nSlideHeight = 0;
+ xPropSet->getPropertyValue( "Width" ) >>= nSlideWidth;
+ xPropSet->getPropertyValue( "Height" ) >>= nSlideHeight;
+
+ maPatterProps[ sPageId ] = { nChecksum, aPos, aSize, { nSlideWidth, nSlideHeight } };
+
+ // create meta comment action that is used to exporting
+ // a <use> element which points to the group element representing the background
+ const OUString sBgId = getIdForTiledBackground( sPageId, nChecksum );
+ OString sComment = sTiledBackgroundTag + " " + sBgId.toUtf8();
+ MetaCommentAction* pCommentAction = new MetaCommentAction( sComment );
+ if( pCommentAction )
+ aTiledMtf.AddAction( pCommentAction );
+ }
+ }
+ else if( bIsTiled && nType != MetaActionType::CLIPREGION )
+ {
+ aTiledMtf.AddAction( pAction );
+ }
+ }
+
+ (*mpObjects)[ rxDrawPage ] = ObjectRepresentation( rxDrawPage, bIsTiled ? aTiledMtf : aMtf );
+}
+
+OUString SVGFilter::implGetClassFromShape( const Reference< css::drawing::XShape >& rxShape )
+{
+ OUString aRet;
+ const OUString aShapeType( rxShape->getShapeType() );
+
+ if( aShapeType.lastIndexOf( "drawing.GroupShape" ) != -1 )
+ aRet = "Group";
+ else if( aShapeType.lastIndexOf( "drawing.GraphicObjectShape" ) != -1 )
+ aRet = "Graphic";
+ else if( aShapeType.lastIndexOf( "drawing.OLE2Shape" ) != -1 )
+ aRet = "OLE2";
+ else if( aShapeType.lastIndexOf( "drawing.TextShape" ) != -1 )
+ aRet = "TextShape";
+ else if( aShapeType.lastIndexOf( "presentation.HeaderShape" ) != -1 )
+ aRet = "Header";
+ else if( aShapeType.lastIndexOf( "presentation.FooterShape" ) != -1 )
+ aRet = "Footer";
+ else if( aShapeType.lastIndexOf( "presentation.DateTimeShape" ) != -1 )
+ aRet = "Date/Time";
+ else if( aShapeType.lastIndexOf( "presentation.SlideNumberShape" ) != -1 )
+ aRet = "Slide_Number";
+ else if( aShapeType.lastIndexOf( "presentation.TitleTextShape" ) != -1 )
+ aRet = "TitleText";
+ else if( aShapeType.lastIndexOf( "presentation.OutlinerShape" ) != -1 )
+ aRet = "Outline";
+ else
+ aRet = aShapeType;
+
+ return aRet;
+}
+
+
+void SVGFilter::implRegisterInterface( const Reference< XInterface >& rxIf )
+{
+ if( rxIf.is() )
+ mpSVGExport->getInterfaceToIdentifierMapper().registerReference( rxIf );
+}
+
+
+const OUString & SVGFilter::implGetValidIDFromInterface( const Reference< XInterface >& rxIf )
+{
+ return mpSVGExport->getInterfaceToIdentifierMapper().getIdentifier( rxIf );
+}
+
+
+OUString SVGFilter::implGetInterfaceName( const Reference< XInterface >& rxIf )
+{
+ Reference< XNamed > xNamed( rxIf, UNO_QUERY );
+ OUString aRet;
+ if( xNamed.is() )
+ {
+ aRet = xNamed->getName().replace( ' ', '_' );
+ }
+ return aRet;
+}
+
+
+IMPL_LINK( SVGFilter, CalcFieldHdl, EditFieldInfo*, pInfo, void )
+{
+ bool bFieldProcessed = false;
+ if( pInfo && mbPresentation )
+ {
+ bFieldProcessed = true;
+ if( mpSVGExport->IsEmbedFonts() && mpSVGExport->IsUsePositionedCharacters() )
+ {
+ // to notify to the SVGActionWriter::ImplWriteText method
+ // that we are dealing with a placeholder shape
+ OUStringBuffer aRepresentation(sPlaceholderTag);
+
+ if( !mCreateOjectsCurrentMasterPage.is() )
+ {
+ OSL_FAIL( "error: !mCreateOjectsCurrentMasterPage.is()" );
+ return;
+ }
+ bool bHasCharSetMap = mTextFieldCharSets.find( mCreateOjectsCurrentMasterPage ) != mTextFieldCharSets.end();
+
+ static constexpr OUStringLiteral aHeaderId( NSPREFIX "header-field" );
+ static constexpr OUStringLiteral aFooterId( aOOOAttrFooterField );
+ static constexpr OUStringLiteral aDateTimeId( aOOOAttrDateTimeField );
+ static const OUString aVariableDateTimeId( aOOOAttrDateTimeField + "-variable" );
+
+ const UCharSet * pCharSet = nullptr;
+ UCharSetMap * pCharSetMap = nullptr;
+ if( bHasCharSetMap )
+ {
+ pCharSetMap = &( mTextFieldCharSets[ mCreateOjectsCurrentMasterPage ] );
+ }
+ const SvxFieldData* pField = pInfo->GetField().GetField();
+ if( bHasCharSetMap && ( pField->GetClassId() == text::textfield::Type::PRESENTATION_HEADER ) && ( pCharSetMap->find( aHeaderId ) != pCharSetMap->end() ) )
+ {
+ pCharSet = &( (*pCharSetMap)[ aHeaderId ] );
+ }
+ else if( bHasCharSetMap && ( pField->GetClassId() == text::textfield::Type::PRESENTATION_FOOTER ) && ( pCharSetMap->find( aFooterId ) != pCharSetMap->end() ) )
+ {
+ pCharSet = &( (*pCharSetMap)[ aFooterId ] );
+ }
+ else if( pField->GetClassId() == text::textfield::Type::PRESENTATION_DATE_TIME )
+ {
+ if( bHasCharSetMap && ( pCharSetMap->find( aDateTimeId ) != pCharSetMap->end() ) )
+ {
+ pCharSet = &( (*pCharSetMap)[ aDateTimeId ] );
+ }
+ if( bHasCharSetMap && ( pCharSetMap->find( aVariableDateTimeId ) != pCharSetMap->end() ) && !(*pCharSetMap)[ aVariableDateTimeId ].empty() )
+ {
+ SvxDateFormat eDateFormat = SvxDateFormat::B, eCurDateFormat;
+ const UCharSet & aCharSet = (*pCharSetMap)[ aVariableDateTimeId ];
+ // we look for the most verbose date format
+ for (auto const& elem : aCharSet)
+ {
+ eCurDateFormat = static_cast<SvxDateFormat>( static_cast<int>(elem) & 0x0f );
+ switch( eDateFormat )
+ {
+ case SvxDateFormat::StdSmall:
+ case SvxDateFormat::A: // 13.02.96
+ case SvxDateFormat::B: // 13.02.1996
+ switch( eCurDateFormat )
+ {
+ case SvxDateFormat::C: // 13.Feb 1996
+ case SvxDateFormat::D: // 13.February 1996
+ case SvxDateFormat::E: // Tue, 13.February 1996
+ case SvxDateFormat::StdBig:
+ case SvxDateFormat::F: // Tuesday, 13.February 1996
+ eDateFormat = eCurDateFormat;
+ break;
+ default:
+ break;
+ }
+ break;
+ case SvxDateFormat::C: // 13.Feb 1996
+ case SvxDateFormat::D: // 13.February 1996
+ switch( eCurDateFormat )
+ {
+ case SvxDateFormat::E: // Tue, 13.February 1996
+ case SvxDateFormat::StdBig:
+ case SvxDateFormat::F: // Tuesday, 13.February 1996
+ eDateFormat = eCurDateFormat;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ // Independently of the date format, we always put all these characters by default.
+ // They should be enough to cover every time format.
+ aRepresentation.append( "0123456789.:/-APM" );
+
+ if( eDateFormat != SvxDateFormat::AppDefault )
+ {
+ OUStringBuffer sDate;
+ LanguageType eLang = pInfo->GetOutliner()->GetLanguage( pInfo->GetPara(), pInfo->GetPos() );
+ SvNumberFormatter * pNumberFormatter = new SvNumberFormatter( ::comphelper::getProcessComponentContext(), LANGUAGE_SYSTEM );
+ // We always collect the characters obtained by using the SvxDateFormat::B (as: 13.02.1996)
+ // so we are sure to include any unusual day|month|year separator.
+ Date aDate( 1, 1, 1996 );
+ sDate.append( SvxDateField::GetFormatted( aDate, SvxDateFormat::B, *pNumberFormatter, eLang ) );
+ switch( eDateFormat )
+ {
+ case SvxDateFormat::E: // Tue, 13.February 1996
+ case SvxDateFormat::StdBig:
+ case SvxDateFormat::F: // Tuesday, 13.February 1996
+ for( sal_uInt16 i = 1; i <= 7; ++i ) // we get all days in a week
+ {
+ aDate.SetDay( i );
+ sDate.append( SvxDateField::GetFormatted( aDate, eDateFormat, *pNumberFormatter, eLang ) );
+ }
+ [[fallthrough]]; // We need months too!
+ case SvxDateFormat::C: // 13.Feb 1996
+ case SvxDateFormat::D: // 13.February 1996
+ for( sal_uInt16 i = 1; i <= 12; ++i ) // we get all months in a year
+ {
+ aDate.SetMonth( i );
+ sDate.append( SvxDateField::GetFormatted( aDate, eDateFormat, *pNumberFormatter, eLang ) );
+ }
+ break;
+ // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
+ case SvxDateFormat::StdSmall:
+ case SvxDateFormat::A: // 13.02.96
+ case SvxDateFormat::B: // 13.02.1996
+ default:
+ // nothing to do here, we always collect the characters needed for these cases.
+ break;
+ }
+ aRepresentation.append( sDate );
+ }
+ }
+ }
+ else if( pField->GetClassId() == text::textfield::Type::PAGE )
+ {
+ switch( mVisiblePagePropSet.nPageNumberingType )
+ {
+ case css::style::NumberingType::CHARS_UPPER_LETTER:
+ aRepresentation.append( "QWERTYUIOPASDFGHJKLZXCVBNM" );
+ break;
+ case css::style::NumberingType::CHARS_LOWER_LETTER:
+ aRepresentation.append( "qwertyuiopasdfghjklzxcvbnm" );
+ break;
+ case css::style::NumberingType::ROMAN_UPPER:
+ aRepresentation.append( "IVXLCDM" );
+ break;
+ case css::style::NumberingType::ROMAN_LOWER:
+ aRepresentation.append( "ivxlcdm" );
+ break;
+ // arabic numbering type is the default
+ case css::style::NumberingType::ARABIC:
+ // in case the numbering type is not handled we fall back on arabic numbering
+ default:
+ aRepresentation.append( "0123456789" );
+ break;
+ }
+ }
+ else
+ {
+ bFieldProcessed = false;
+ }
+ if( bFieldProcessed )
+ {
+ if( pCharSet != nullptr )
+ {
+ for (auto const& elem : *pCharSet)
+ {
+ aRepresentation.append(elem);
+ }
+ }
+ pInfo->SetRepresentation( aRepresentation.makeStringAndClear() );
+ }
+ }
+ else
+ {
+ bFieldProcessed = false;
+ }
+
+ }
+ if (!bFieldProcessed)
+ maOldFieldHdl.Call( pInfo );
+}
+
+
+void SVGExport::writeMtf( const GDIMetaFile& rMtf )
+{
+ const Size aSize( OutputDevice::LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MapMode(MapUnit::MapMM)) );
+ OUString aAttr;
+ Reference< XExtendedDocumentHandler> xExtDocHandler( GetDocHandler(), UNO_QUERY );
+
+ if( xExtDocHandler.is() && IsUseDTDString() )
+ xExtDocHandler->unknown( SVG_DTD_STRING );
+
+ aAttr = OUString::number( aSize.Width() ) + "mm";
+ AddAttribute( XML_NAMESPACE_NONE, "width", aAttr );
+
+ aAttr = OUString::number( aSize.Height() ) + "mm";
+ AddAttribute( XML_NAMESPACE_NONE, "height", aAttr );
+
+ aAttr = "0 0 " + OUString::number( aSize.Width() * 100 ) + " " +
+ OUString::number( aSize.Height() * 100 );
+ AddAttribute( XML_NAMESPACE_NONE, "viewBox", aAttr );
+
+ AddAttribute( XML_NAMESPACE_NONE, "version", "1.1" );
+
+ if( IsUseTinyProfile() )
+ AddAttribute( XML_NAMESPACE_NONE, "baseProfile", "tiny" );
+
+ AddAttribute( XML_NAMESPACE_NONE, "xmlns", constSvgNamespace );
+ // For <image xlink:href="...">.
+ AddAttribute(XML_NAMESPACE_XMLNS, "xlink", "http://www.w3.org/1999/xlink");
+ AddAttribute( XML_NAMESPACE_NONE, "stroke-width", OUString::number( 28.222 ) );
+ AddAttribute( XML_NAMESPACE_NONE, "stroke-linejoin", "round" );
+ AddAttribute( XML_NAMESPACE_NONE, "xml:space", "preserve" );
+
+ {
+ SvXMLElementExport aSVG( *this, XML_NAMESPACE_NONE, "svg", true, true );
+
+ std::vector< ObjectRepresentation > aObjects;
+
+ aObjects.emplace_back( Reference< XInterface >(), rMtf );
+ SVGFontExport aSVGFontExport( *this, std::move(aObjects) );
+
+ Point aPoint100thmm( OutputDevice::LogicToLogic(rMtf.GetPrefMapMode().GetOrigin(), rMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
+ Size aSize100thmm( OutputDevice::LogicToLogic(rMtf.GetPrefSize(), rMtf.GetPrefMapMode(), MapMode(MapUnit::Map100thMM)) );
+
+ SVGActionWriter aWriter( *this, aSVGFontExport );
+ aWriter.WriteMetaFile( aPoint100thmm, aSize100thmm, rMtf,
+ SVGWRITER_WRITE_FILL | SVGWRITER_WRITE_TEXT );
+ }
+}
+
+void SVGExport::SetEmbeddedBulletGlyph(sal_Unicode cBullet)
+{
+ maEmbeddedBulletGlyphs.insert(cBullet);
+}
+
+bool SVGExport::IsEmbeddedBulletGlyph(sal_Unicode cBullet) const
+{
+ auto it = maEmbeddedBulletGlyphs.find(cBullet);
+ return it != maEmbeddedBulletGlyphs.end();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgfilter.component b/filter/source/svg/svgfilter.component
new file mode 100644
index 000000000..479748f38
--- /dev/null
+++ b/filter/source/svg/svgfilter.component
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.Draw.SVGFilter"
+ constructor="filter_SVGFilter_get_implementation">
+ <service name="com.sun.star.document.ImportFilter"/>
+ <service name="com.sun.star.document.ExportFilter"/>
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Draw.SVGWriter"
+ constructor="filter_SVGWriter_get_implementation">
+ <service name="com.sun.star.svg.SVGWriter"/>
+ </implementation>
+</component>
diff --git a/filter/source/svg/svgfilter.cxx b/filter/source/svg/svgfilter.cxx
new file mode 100644
index 000000000..4538e5021
--- /dev/null
+++ b/filter/source/svg/svgfilter.cxx
@@ -0,0 +1,847 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <cstdio>
+
+#include <comphelper/lok.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/drawing/XDrawView.hpp>
+#include <com/sun/star/drawing/XMasterPagesSupplier.hpp>
+#include <com/sun/star/drawing/XMasterPageTarget.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XController.hpp>
+#include <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+#include <com/sun/star/drawing/framework/XControllerManager.hpp>
+#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
+#include <com/sun/star/drawing/framework/XConfiguration.hpp>
+#include <com/sun/star/drawing/framework/AnchorBindingMode.hpp>
+#include <com/sun/star/drawing/framework/XResourceId.hpp>
+#include <com/sun/star/drawing/framework/XResource.hpp>
+
+#include <unotools/mediadescriptor.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <tools/debug.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/zcodec.hxx>
+
+#include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <drawinglayer/primitive2d/Primitive2DContainer.hxx>
+#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
+
+#include "svgfilter.hxx"
+
+#include <svx/unopage.hxx>
+#include <vcl/graphicfilter.hxx>
+#include <vcl/window.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdograf.hxx>
+#include <svl/itempool.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+namespace
+{
+ constexpr OUStringLiteral constFilterNameDraw = u"svg_Scalable_Vector_Graphics_Draw";
+ constexpr OUStringLiteral constFilterName = u"svg_Scalable_Vector_Graphics";
+}
+
+SVGFilter::SVGFilter( const Reference< XComponentContext >& rxCtx ) :
+ mxContext( rxCtx ),
+ mpSVGDoc( nullptr ),
+ mpSVGFontExport( nullptr ),
+ mpSVGWriter( nullptr ),
+ mbSinglePage( false ),
+ mnVisiblePage( -1 ),
+ mpObjects( nullptr ),
+ mbExportShapeSelection(false),
+ mbIsPreview(false),
+ mbWriterFilter(false),
+ mbCalcFilter(false),
+ mbImpressFilter(false),
+ mpDefaultSdrPage( nullptr ),
+ mbPresentation( false )
+{
+}
+
+SVGFilter::~SVGFilter()
+{
+ DBG_ASSERT( mpSVGDoc == nullptr, "mpSVGDoc not destroyed" );
+ DBG_ASSERT( mpSVGExport == nullptr, "mpSVGExport not destroyed" );
+ DBG_ASSERT( mpSVGFontExport == nullptr, "mpSVGFontExport not destroyed" );
+ DBG_ASSERT( mpSVGWriter == nullptr, "mpSVGWriter not destroyed" );
+ DBG_ASSERT( mpObjects == nullptr, "mpObjects not destroyed" );
+}
+
+sal_Bool SAL_CALL SVGFilter::filter( const Sequence< PropertyValue >& rDescriptor )
+{
+ mbWriterFilter = false;
+ mbCalcFilter = false;
+ mbImpressFilter = false;
+
+ if(mxDstDoc.is()) // Import works for Impress / draw only
+ return filterImpressOrDraw(rDescriptor);
+
+ if(!mxSrcDoc)
+ return false;
+
+ for (const PropertyValue& rProp : rDescriptor)
+ {
+ if (rProp.Name == "IsPreview")
+ {
+ rProp.Value >>= mbIsPreview;
+ break;
+ }
+ }
+
+ for (const PropertyValue& rProp : rDescriptor)
+ {
+ if (rProp.Name == "FilterName")
+ {
+ OUString sFilterName;
+ rProp.Value >>= sFilterName;
+ if(sFilterName == "impress_svg_Export")
+ {
+ mbImpressFilter = true;
+ return filterImpressOrDraw(rDescriptor);
+ }
+ else if(sFilterName == "writer_svg_Export")
+ {
+ mbWriterFilter = true;
+ return filterWriterOrCalc(rDescriptor);
+ }
+ else if(sFilterName == "calc_svg_Export")
+ {
+ mbCalcFilter = true;
+ return filterWriterOrCalc(rDescriptor);
+ }
+ break;
+ }
+ }
+ return filterImpressOrDraw(rDescriptor);
+}
+
+bool SVGFilter::filterImpressOrDraw( const Sequence< PropertyValue >& rDescriptor )
+{
+ SolarMutexGuard aGuard;
+ vcl::Window* pFocusWindow(Application::GetFocusWindow());
+ bool bRet(false);
+
+ if(pFocusWindow)
+ {
+ pFocusWindow->EnterWait();
+ }
+
+ if(mxDstDoc.is())
+ {
+ // Import. Use an endless loop to have easy exits for error handling
+ while(true)
+ {
+ // use MediaDescriptor to get needed data out of Sequence< PropertyValue >
+ utl::MediaDescriptor aMediaDescriptor(rDescriptor);
+ uno::Reference<io::XInputStream> xInputStream;
+
+ xInputStream.set(aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM], UNO_QUERY);
+
+ if(!xInputStream.is())
+ {
+ // we need the InputStream
+ break;
+ }
+
+ // get the DrawPagesSupplier
+ uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSupplier( mxDstDoc, uno::UNO_QUERY );
+
+ if(!xDrawPagesSupplier.is())
+ {
+ // we need the DrawPagesSupplier
+ break;
+ }
+
+ // get the DrawPages
+ uno::Reference< drawing::XDrawPages > xDrawPages = xDrawPagesSupplier->getDrawPages();
+
+ if(!xDrawPages.is())
+ {
+ // we need the DrawPages
+ break;
+ }
+
+ // check DrawPageCount (there should be one by default)
+ sal_Int32 nDrawPageCount(xDrawPages->getCount());
+
+ if(0 == nDrawPageCount)
+ {
+ // at least one DrawPage should be there - we need that
+ break;
+ }
+
+ // get that DrawPage
+ uno::Reference< drawing::XDrawPage > xDrawPage( xDrawPages->getByIndex(0), uno::UNO_QUERY );
+
+ if(!xDrawPage.is())
+ {
+ // we need that DrawPage
+ break;
+ }
+
+ // get that DrawPage's UNO API implementation
+ SvxDrawPage* pSvxDrawPage(comphelper::getFromUnoTunnel<SvxDrawPage>(xDrawPage));
+
+ if(nullptr == pSvxDrawPage || nullptr == pSvxDrawPage->GetSdrPage())
+ {
+ // we need a SvxDrawPage
+ break;
+ }
+
+ // get the SvStream to work with
+ std::unique_ptr< SvStream > aStream(utl::UcbStreamHelper::CreateStream(xInputStream, true));
+
+ if (!aStream)
+ {
+ // we need the SvStream
+ break;
+ }
+
+ // create a GraphicFilter and load the SVG (format already known, thus *could*
+ // be handed over to ImportGraphic - but detection is fast).
+ // As a bonus, zipped data is already detected and handled there
+ GraphicFilter aGraphicFilter;
+ Graphic aGraphic;
+ const ErrCode nGraphicFilterErrorCode(
+ aGraphicFilter.ImportGraphic(aGraphic, u"", *aStream));
+
+ if(ERRCODE_NONE != nGraphicFilterErrorCode)
+ {
+ // SVG import error, cannot continue
+ break;
+ }
+
+ // get the GraphicPrefSize early to check if we have any content
+ // (the SVG may contain nothing and/or just <g visibility="hidden"> stuff...)
+ const Size aGraphicPrefSize(aGraphic.GetPrefSize());
+
+ if(0 == aGraphicPrefSize.Width() || 0 == aGraphicPrefSize.Height())
+ {
+ // SVG has no displayable content, stop import.
+ // Also possible would be to get the sequence< Primitives >
+ // from aGraphic and check if it is empty.
+ // Possibility to set some error message here to tell
+ // the user what/why loading went wrong, but I do not
+ // know how this could be done here
+ break;
+ }
+
+ // tdf#118232 Get the sequence of primitives and check if geometry is completely
+ // hidden. If so, there is no need to add a SdrObject at all
+ auto const & rVectorGraphicData(aGraphic.getVectorGraphicData());
+ bool bContainsNoGeometry(false);
+
+ if(bool(rVectorGraphicData) && VectorGraphicDataType::Svg == rVectorGraphicData->getType())
+ {
+ const drawinglayer::primitive2d::Primitive2DContainer aContainer(rVectorGraphicData->getPrimitive2DSequence());
+
+ if(!aContainer.empty())
+ {
+ bool bAllAreHiddenGeometry(true);
+
+ for(const auto& rCandidate : aContainer)
+ {
+ if(rCandidate && PRIMITIVE2D_ID_HIDDENGEOMETRYPRIMITIVE2D != rCandidate->getPrimitive2DID())
+ {
+ bAllAreHiddenGeometry = false;
+ break;
+ }
+ }
+
+ if(bAllAreHiddenGeometry)
+ {
+ bContainsNoGeometry = true;
+ }
+ }
+ }
+
+ // create a SdrModel-GraphicObject to insert to page
+ SdrPage* pTargetSdrPage(pSvxDrawPage->GetSdrPage());
+ std::unique_ptr< SdrGrafObj, SdrObjectFreeOp > aNewSdrGrafObj;
+
+ // tdf#118232 only add an SdrGrafObj when we have Geometry
+ if(!bContainsNoGeometry)
+ {
+ aNewSdrGrafObj.reset(
+ new SdrGrafObj(
+ pTargetSdrPage->getSdrModelFromSdrPage(),
+ aGraphic));
+ }
+
+ // Evtl. adapt the GraphicPrefSize to target-MapMode of target-Model
+ // (should be 100thmm here, but just stay safe by doing the conversion)
+ const MapMode aGraphicPrefMapMode(aGraphic.GetPrefMapMode());
+ const MapUnit eDestUnit(pTargetSdrPage->getSdrModelFromSdrPage().GetItemPool().GetMetric(0));
+ const MapUnit eSrcUnit(aGraphicPrefMapMode.GetMapUnit());
+ Size aGraphicSize(aGraphicPrefSize);
+
+ if (eDestUnit != eSrcUnit)
+ {
+ aGraphicSize = Size(
+ OutputDevice::LogicToLogic(aGraphicSize.Width(), eSrcUnit, eDestUnit),
+ OutputDevice::LogicToLogic(aGraphicSize.Height(), eSrcUnit, eDestUnit));
+ }
+
+ // Based on GraphicSize, set size of Page. Do not forget to adapt PageBorders,
+ // but interpret them relative to PageSize so that they do not 'explode/shrink'
+ // in comparison. Use a common scaling factor for hor/ver to not get
+ // asynchronous border distances, though. All in all this will adapt borders
+ // nicely and is based on office-defaults for standard-page-border-sizes.
+ const Size aPageSize(pTargetSdrPage->GetSize());
+ const double fBorderRelation((
+ static_cast< double >(pTargetSdrPage->GetLeftBorder()) / aPageSize.Width() +
+ static_cast< double >(pTargetSdrPage->GetRightBorder()) / aPageSize.Width() +
+ static_cast< double >(pTargetSdrPage->GetUpperBorder()) / aPageSize.Height() +
+ static_cast< double >(pTargetSdrPage->GetLowerBorder()) / aPageSize.Height()) / 4.0);
+ const tools::Long nAllBorder(basegfx::fround((aGraphicSize.Width() + aGraphicSize.Height()) * fBorderRelation * 0.5));
+
+ // Adapt PageSize and Border stuff. To get all MasterPages and PresObjs
+ // correctly adapted, do not just use
+ // pTargetSdrPage->SetBorder(...) and
+ // pTargetSdrPage->SetSize(...),
+ // but ::adaptSizeAndBorderForAllPages
+ // Do use original Size and borders to get as close to original
+ // as possible for better turn-arounds.
+ pTargetSdrPage->getSdrModelFromSdrPage().adaptSizeAndBorderForAllPages(
+ Size(
+ aGraphicSize.Width(),
+ aGraphicSize.Height()),
+ nAllBorder,
+ nAllBorder,
+ nAllBorder,
+ nAllBorder);
+
+ // tdf#118232 set pos/size at SdrGraphicObj - use zero position for
+ // better turn-around results
+ if(!bContainsNoGeometry)
+ {
+ aNewSdrGrafObj->SetSnapRect(
+ tools::Rectangle(
+ Point(0, 0),
+ aGraphicSize));
+
+ // insert to page (owner change of SdrGrafObj)
+ pTargetSdrPage->InsertObject(aNewSdrGrafObj.release());
+ }
+
+ // done - set positive result now
+ bRet = true;
+
+ // always leave helper endless loop
+ break;
+ }
+ }
+ else if( mxSrcDoc.is() )
+ {
+ // #i124608# detect selection
+ bool bSelectionOnly = false;
+ bool bGotSelection = false;
+
+ // when using LibreOfficeKit, default to exporting everything (-1)
+ bool bPageProvided = comphelper::LibreOfficeKit::isActive();
+ sal_Int32 nPageToExport = -1;
+
+ for( const PropertyValue& rProp : rDescriptor )
+ {
+ if (rProp.Name == "SelectionOnly")
+ {
+ // #i124608# extract single selection wanted from dialog return values
+ rProp.Value >>= bSelectionOnly;
+ bPageProvided = false;
+ }
+ else if (rProp.Name == "PagePos")
+ {
+ rProp.Value >>= nPageToExport;
+ bPageProvided = true;
+ }
+ }
+
+ uno::Reference<frame::XDesktop2> xDesktop(frame::Desktop::create(mxContext));
+ uno::Reference<frame::XController > xController;
+ if (xDesktop->getCurrentFrame().is() && !bPageProvided) // Manage headless case
+ {
+ uno::Reference<frame::XFrame> xFrame(xDesktop->getCurrentFrame(), uno::UNO_SET_THROW);
+ xController.set(xFrame->getController(), uno::UNO_SET_THROW);
+ uno::Reference<drawing::XDrawView> xDrawView(xController, uno::UNO_QUERY_THROW);
+ uno::Reference<drawing::framework::XControllerManager> xManager(xController, uno::UNO_QUERY_THROW);
+ uno::Reference<drawing::framework::XConfigurationController> xConfigController(xManager->getConfigurationController());
+
+ // which view configuration are we in?
+ //
+ // * traverse Impress resources to find slide preview pane, grab selection from there
+ // * otherwise, fallback to current slide
+ //
+ const uno::Sequence<uno::Reference<drawing::framework::XResourceId> > aResIds(
+ xConfigController->getCurrentConfiguration()->getResources(
+ uno::Reference<drawing::framework::XResourceId>(),
+ "",
+ drawing::framework::AnchorBindingMode_INDIRECT));
+
+ for( const uno::Reference<drawing::framework::XResourceId>& rResId : aResIds )
+ {
+ // can we somehow obtain the slidesorter from the Impress framework?
+ if( rResId->getResourceURL() == "private:resource/view/SlideSorter" )
+ {
+ // got it, grab current selection from there
+ uno::Reference<drawing::framework::XResource> xRes(
+ xConfigController->getResource(rResId));
+
+ uno::Reference< view::XSelectionSupplier > xSelectionSupplier(
+ xRes,
+ uno::UNO_QUERY );
+ if( xSelectionSupplier.is() )
+ {
+ uno::Any aSelection = xSelectionSupplier->getSelection();
+ if( aSelection.hasValue() )
+ {
+ Sequence< Reference< XInterface > > aSelectedPageSequence;
+ aSelection >>= aSelectedPageSequence;
+ mSelectedPages.resize( aSelectedPageSequence.getLength() );
+ for( size_t j=0; j<mSelectedPages.size(); ++j )
+ {
+ uno::Reference< drawing::XDrawPage > xDrawPage( aSelectedPageSequence[j],
+ uno::UNO_QUERY );
+ mSelectedPages[j] = xDrawPage;
+ }
+
+ // and stop looping. It is likely not getting better
+ break;
+ }
+ }
+ }
+ }
+
+ if( mSelectedPages.empty() )
+ {
+ // apparently failed to clean selection - fallback to current page
+ mSelectedPages.resize( 1 );
+ mSelectedPages[0] = xDrawView->getCurrentPage();
+ }
+ }
+
+ /*
+ * Export all slides, or requested "PagePos"
+ */
+ if( mSelectedPages.empty() )
+ {
+ uno::Reference< drawing::XMasterPagesSupplier > xMasterPagesSupplier( mxSrcDoc, uno::UNO_QUERY );
+ uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSupplier( mxSrcDoc, uno::UNO_QUERY );
+
+ if( xMasterPagesSupplier.is() && xDrawPagesSupplier.is() )
+ {
+ uno::Reference< drawing::XDrawPages > xMasterPages = xMasterPagesSupplier->getMasterPages();
+ uno::Reference< drawing::XDrawPages > xDrawPages = xDrawPagesSupplier->getDrawPages();
+ if( xMasterPages.is() && xMasterPages->getCount() &&
+ xDrawPages.is() && xDrawPages->getCount() )
+ {
+ sal_Int32 nDPCount = xDrawPages->getCount();
+
+ mSelectedPages.resize( nPageToExport != -1 ? 1 : nDPCount );
+ sal_Int32 i;
+ for( i = 0; i < nDPCount; ++i )
+ {
+ if( nPageToExport != -1 && nPageToExport == i )
+ {
+ uno::Reference< drawing::XDrawPage > xDrawPage( xDrawPages->getByIndex( i ), uno::UNO_QUERY );
+ mSelectedPages[0] = xDrawPage;
+ }
+ else
+ {
+ uno::Reference< drawing::XDrawPage > xDrawPage( xDrawPages->getByIndex( i ), uno::UNO_QUERY );
+ mSelectedPages[i] = xDrawPage;
+ }
+ }
+ }
+ }
+ }
+
+ if (bSelectionOnly)
+ {
+ // #i124608# when selection only is wanted, get the current object selection
+ // from the DrawView
+ Reference< view::XSelectionSupplier > xSelection (xController, UNO_QUERY);
+
+ if (xSelection.is())
+ {
+ bGotSelection
+ = ( xSelection->getSelection() >>= maShapeSelection );
+ }
+ }
+
+ if(bSelectionOnly && bGotSelection && 0 == maShapeSelection->getCount())
+ {
+ // #i124608# export selection, got maShapeSelection but no shape selected -> nothing
+ // to export, we are done (maybe return true, but a hint that nothing was done
+ // may be useful; it may have happened by error)
+ bRet = false;
+ }
+ else
+ {
+ /*
+ * We get all master page that are targeted by at least one draw page.
+ * The master page are put in an unordered set.
+ */
+ ObjectSet aMasterPageTargetSet;
+ for(const uno::Reference<drawing::XDrawPage> & mSelectedPage : mSelectedPages)
+ {
+ uno::Reference< drawing::XMasterPageTarget > xMasterPageTarget( mSelectedPage, uno::UNO_QUERY );
+ if( xMasterPageTarget.is() )
+ {
+ aMasterPageTargetSet.insert( xMasterPageTarget->getMasterPage() );
+ }
+ }
+ // Later we move them to an uno::Sequence so we can get them by index
+ mMasterPageTargets.resize( aMasterPageTargetSet.size() );
+ sal_Int32 i = 0;
+ for (auto const& masterPageTarget : aMasterPageTargetSet)
+ {
+ uno::Reference< drawing::XDrawPage > xMasterPage( masterPageTarget, uno::UNO_QUERY );
+ mMasterPageTargets[i++] = xMasterPage;
+ }
+
+ bRet = implExport( rDescriptor );
+ }
+ }
+ else
+ bRet = false;
+
+ if( pFocusWindow )
+ pFocusWindow->LeaveWait();
+
+ return bRet;
+}
+
+bool SVGFilter::filterWriterOrCalc( const Sequence< PropertyValue >& rDescriptor )
+{
+ bool bSelectionOnly = false;
+
+ for (const PropertyValue& rProp : rDescriptor)
+ {
+ if (rProp.Name == "SelectionOnly")
+ {
+ rProp.Value >>= bSelectionOnly;
+ break;
+ }
+ }
+
+ if(!bSelectionOnly) // For Writer only the selection-only mode is supported
+ return false;
+
+ uno::Reference<frame::XDesktop2> xDesktop(frame::Desktop::create(mxContext));
+ uno::Reference<frame::XController > xController;
+ if (xDesktop->getCurrentFrame().is())
+ {
+ uno::Reference<frame::XFrame> xFrame(xDesktop->getCurrentFrame(), uno::UNO_SET_THROW);
+ xController.set(xFrame->getController(), uno::UNO_SET_THROW);
+ }
+
+ Reference< view::XSelectionSupplier > xSelection (xController, UNO_QUERY);
+ if (!xSelection.is())
+ return false;
+
+ // Select only one draw page
+ uno::Reference< drawing::XDrawPagesSupplier > xDrawPagesSupplier( mxSrcDoc, uno::UNO_QUERY );
+ uno::Reference<drawing::XDrawPages> xDrawPages = xDrawPagesSupplier->getDrawPages();
+ uno::Reference< drawing::XDrawPage > xDrawPage( xDrawPages->getByIndex(0), uno::UNO_QUERY );
+ mSelectedPages.resize( 1 );
+ mSelectedPages[0] = xDrawPage;
+
+ bool bGotSelection = xSelection->getSelection() >>= maShapeSelection;
+
+ if (!bGotSelection)
+ {
+ if (mbWriterFilter)
+ {
+ // For Writer we might have a non-shape graphic
+ bGotSelection = implExportWriterTextGraphic(xSelection);
+ }
+ if (!bGotSelection)
+ return false;
+ }
+
+ return implExport( rDescriptor );
+}
+
+void SAL_CALL SVGFilter::cancel( )
+{
+}
+
+void SAL_CALL SVGFilter::setSourceDocument( const Reference< XComponent >& xDoc )
+{
+ mxSrcDoc = xDoc;
+}
+
+void SAL_CALL SVGFilter::setTargetDocument( const Reference< XComponent >& xDoc )
+{
+ mxDstDoc = xDoc;
+}
+
+namespace {
+
+// There is already another SVG-Type_Detector, see
+// vcl/source/filter/graphicfilter.cxx ("DOCTYPE svg"),
+// but since these start from different preconditions it is not
+// easy to unify these. For now, use this local helper.
+class SVGFileInfo
+{
+private:
+ const uno::Reference<io::XInputStream>& mxInput;
+ uno::Sequence< sal_Int8 > mnFirstBytes;
+ sal_Int32 mnFirstBytesSize;
+ sal_Int32 mnFirstRead;
+ bool mbProcessed;
+ bool mbIsSVG;
+
+ bool impCheckForMagic(
+ const sal_Int8* pMagic,
+ const sal_Int32 nMagicSize)
+ {
+ const sal_Int8* pBuffer(mnFirstBytes.getConstArray());
+ return std::search(
+ pBuffer,
+ pBuffer + mnFirstRead,
+ pMagic,
+ pMagic + nMagicSize) != pBuffer + mnFirstRead;
+ }
+
+ void impEnsureProcessed()
+ {
+ if(mbProcessed)
+ {
+ return;
+ }
+
+ mbProcessed = true;
+
+ if(!mxInput.is())
+ {
+ return;
+ }
+
+ if(0 == mnFirstBytesSize)
+ {
+ return;
+ }
+
+ mnFirstBytes.realloc(mnFirstBytesSize);
+
+ if(mnFirstBytesSize != mnFirstBytes.getLength())
+ {
+ return;
+ }
+
+ std::unique_ptr< SvStream > aStream(utl::UcbStreamHelper::CreateStream(mxInput, true));
+
+ if (!aStream)
+ {
+ return;
+ }
+
+ const sal_uInt64 nStreamLen(aStream->remainingSize());
+
+ if(aStream->GetError())
+ {
+ return;
+ }
+
+ mnFirstRead = aStream->ReadBytes(
+ &mnFirstBytes.getArray()[0],
+ std::min(nStreamLen, static_cast<sal_uInt64>(mnFirstBytesSize)));
+
+ if(aStream->GetError())
+ {
+ return;
+ }
+
+ // check if it is gzipped -> svgz
+ if (mnFirstBytes[0] == 0x1F && static_cast<sal_uInt8>(mnFirstBytes[1]) == 0x8B)
+ {
+ ZCodec aCodec;
+
+ aCodec.BeginCompression(ZCODEC_DEFAULT_COMPRESSION, /*gzLib*/true);
+ mnFirstRead = aCodec.Read(
+ *aStream,
+ reinterpret_cast< sal_uInt8* >(mnFirstBytes.getArray()),
+ mnFirstBytesSize);
+ aCodec.EndCompression();
+
+ if (mnFirstRead < 0)
+ return;
+ }
+
+ if(!mbIsSVG)
+ {
+ const sal_Int8 aMagic[] = {'<', 's', 'v', 'g'};
+ const sal_Int32 nMagicSize(SAL_N_ELEMENTS(aMagic));
+
+ mbIsSVG = impCheckForMagic(aMagic, nMagicSize);
+ }
+
+ if(!mbIsSVG)
+ {
+ const sal_Int8 aMagic[] = {'D', 'O', 'C', 'T', 'Y', 'P', 'E', ' ', 's', 'v', 'g'};
+ const sal_Int32 nMagicSize(SAL_N_ELEMENTS(aMagic));
+
+ mbIsSVG = impCheckForMagic(aMagic, nMagicSize);
+ }
+
+ return;
+ }
+
+public:
+ SVGFileInfo(
+ const uno::Reference<io::XInputStream>& xInput)
+ : mxInput(xInput),
+ mnFirstBytesSize(2048),
+ mnFirstRead(0),
+ mbProcessed(false),
+ mbIsSVG(false)
+ {
+ // For the default buffer size: Use not too big
+ // (not more than 16K), but also not too small
+ // (not less than 1/2K), see comments at
+ // ImpPeekGraphicFormat, SVG section.
+ // I remember these cases and it *can* happen
+ // that SVGs have quite massive comments in their
+ // headings (!)
+ // Limit to plausible sizes, also for security reasons
+ mnFirstBytesSize = std::min(sal_Int32(512), mnFirstBytesSize);
+ mnFirstBytesSize = std::max(sal_Int32(16384), mnFirstBytesSize);
+ }
+
+ bool isSVG()
+ {
+ impEnsureProcessed();
+
+ return mbIsSVG;
+ }
+
+ bool isOwnFormat()
+ {
+ impEnsureProcessed();
+
+ if(mbIsSVG)
+ {
+ // xmlns:ooo
+ const sal_Int8 aMagic[] = {'x', 'm', 'l', 'n', 's', ':', 'o', 'o', 'o'};
+ const sal_Int32 nMagicSize(SAL_N_ELEMENTS(aMagic));
+
+ return impCheckForMagic(aMagic, nMagicSize);
+ }
+
+ return false;
+ }
+
+ bool isImpress()
+ {
+ impEnsureProcessed();
+
+ if(mbIsSVG)
+ {
+ // ooo:meta_slides
+ const sal_Int8 aMagic[] = {'o', 'o', 'o', ':', 'm', 'e', 't', 'a', '_', 's', 'l', 'i', 'd', 'e', 's'};
+ const sal_Int32 nMagicSize(SAL_N_ELEMENTS(aMagic));
+
+ return impCheckForMagic(aMagic, nMagicSize);
+ }
+
+ return false;
+ }
+};
+
+}
+
+OUString SAL_CALL SVGFilter::detect(Sequence<PropertyValue>& rDescriptor)
+{
+ utl::MediaDescriptor aMediaDescriptor(rDescriptor);
+ uno::Reference<io::XInputStream> xInput(aMediaDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM], UNO_QUERY);
+ OUString aRetval;
+
+ if (!xInput.is())
+ {
+ return aRetval;
+ }
+
+ try
+ {
+ SVGFileInfo aSVGFileInfo(xInput);
+
+ if(aSVGFileInfo.isSVG())
+ {
+ // We have SVG - set default document format to Draw
+ aRetval = OUString(constFilterNameDraw);
+
+ if(aSVGFileInfo.isOwnFormat())
+ {
+ // it's a file that was written/exported by LO
+ if(aSVGFileInfo.isImpress())
+ {
+ // it was written by Impress export. Set document
+ // format for import to Impress
+ aRetval = OUString(constFilterName);
+ }
+ }
+ }
+ }
+ catch (css::io::IOException &)
+ {
+ TOOLS_WARN_EXCEPTION("filter.svg", "");
+ }
+
+ return aRetval;
+}
+
+// XServiceInfo
+sal_Bool SVGFilter::supportsService(const OUString& sServiceName)
+{
+ return cppu::supportsService(this, sServiceName);
+}
+OUString SVGFilter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.SVGFilter";
+}
+css::uno::Sequence< OUString > SVGFilter::getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ImportFilter",
+ "com.sun.star.document.ExportFilter",
+ "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_SVGFilter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new SVGFilter(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgfilter.hxx b/filter/source/svg/svgfilter.hxx
new file mode 100644
index 000000000..93e14ec41
--- /dev/null
+++ b/filter/source/svg/svgfilter.hxx
@@ -0,0 +1,321 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/xml/sax/XWriter.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
+
+#include <editeng/flditem.hxx>
+#include <vcl/gdimtf.hxx>
+#include <vcl/svapp.hxx>
+#include <svx/unoapi.hxx>
+#include <xmloff/xmlexp.hxx>
+#include <cstdio>
+#include <string_view>
+#include <unordered_set>
+#include <unordered_map>
+
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::document;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::xml::sax;
+
+#define SVG_EXPORT_ALLPAGES ((sal_Int32)-1)
+
+
+// Placeholder tag used into the ImplWriteActions method to filter text placeholder fields
+inline constexpr OUStringLiteral sPlaceholderTag = u"<[:isPlaceholder:]>";
+// This tag is used for exporting a slide background made of tiled bitmaps
+inline constexpr OStringLiteral sTiledBackgroundTag = "SLIDE_BACKGROUND";
+
+class SVGExport : public SvXMLExport
+{
+ bool mbIsUseTinyProfile;
+ bool mbIsUseDTDString;
+ bool mbIsEmbedFonts;
+ bool mbIsUseOpacity;
+ bool mbIsUseNativeTextDecoration;
+ bool mbIsUsePositionedCharacters;
+ std::set<sal_Unicode> maEmbeddedBulletGlyphs;
+
+public:
+
+ SVGExport( const css::uno::Reference< css::uno::XComponentContext >& rContext,
+ const Reference< XDocumentHandler >& rxHandler,
+ const Sequence< PropertyValue >& rFilterData );
+
+ virtual ~SVGExport() override;
+
+ bool IsUseTinyProfile() const { return mbIsUseTinyProfile; };
+ bool IsUseDTDString() const { return mbIsUseDTDString; };
+ bool IsEmbedFonts() const { return mbIsEmbedFonts; };
+ bool IsUseOpacity() const { return mbIsUseOpacity; };
+ bool IsUseNativeTextDecoration() const { return mbIsUseNativeTextDecoration; };
+ bool IsUsePositionedCharacters() const { return mbIsUsePositionedCharacters; };
+
+ void writeMtf( const GDIMetaFile& rMtf );
+
+ void SetEmbeddedBulletGlyph(sal_Unicode cBullet);
+ bool IsEmbeddedBulletGlyph(sal_Unicode cBullet) const;
+
+protected:
+
+ virtual void ExportStyles_( bool /* bUsed */ ) override {}
+ virtual void ExportAutoStyles_() override {}
+ virtual void ExportContent_() override {}
+ virtual void ExportMasterStyles_() override {}
+ virtual ErrCode exportDoc( enum ::xmloff::token::XMLTokenEnum /* eClass */ ) override { return ERRCODE_NONE; }
+};
+
+class ObjectRepresentation
+{
+private:
+
+ Reference< XInterface > mxObject;
+ std::unique_ptr<GDIMetaFile> mxMtf;
+
+public:
+ ObjectRepresentation();
+ ObjectRepresentation(const Reference< XInterface >& rxIf,
+ const GDIMetaFile& rMtf);
+ ObjectRepresentation(const ObjectRepresentation& rPresentation);
+
+ ObjectRepresentation& operator=(const ObjectRepresentation& rPresentation);
+
+ const Reference< XInterface >& GetObject() const { return mxObject; }
+ bool HasRepresentation() const { return static_cast<bool>(mxMtf); }
+ const GDIMetaFile& GetRepresentation() const { return *mxMtf; }
+};
+
+struct PagePropertySet
+{
+ bool bIsBackgroundVisible;
+ bool bAreBackgroundObjectsVisible;
+ bool bIsPageNumberFieldVisible;
+ bool bIsDateTimeFieldVisible;
+ bool bIsFooterFieldVisible;
+ bool bIsHeaderFieldVisible;
+ sal_Int32 nPageNumberingType;
+ bool bIsDateTimeFieldFixed;
+ SvxDateFormat nDateTimeFormat;
+ PagePropertySet()
+ : bIsBackgroundVisible(false)
+ , bAreBackgroundObjectsVisible(false)
+ , bIsPageNumberFieldVisible(false)
+ , bIsDateTimeFieldVisible(false)
+ , bIsFooterFieldVisible(false)
+ , bIsHeaderFieldVisible(false)
+ , nPageNumberingType(0)
+ , bIsDateTimeFieldFixed(false)
+ , nDateTimeFormat(SvxDateFormat::AppDefault)
+ {
+ }
+};
+
+struct HashUChar
+{
+ size_t operator()( const sal_Unicode uchar ) const { return static_cast< size_t >( uchar ); }
+};
+
+struct HashBitmap
+{
+ size_t operator()( const ObjectRepresentation& rObjRep ) const;
+};
+
+struct EqualityBitmap
+{
+ bool operator()( const ObjectRepresentation& rObjRep1,
+ const ObjectRepresentation& rObjRep2 ) const;
+};
+
+// This must match the same type definition in svgwriter.hxx
+typedef std::unordered_map< BitmapChecksum, std::unique_ptr< GDIMetaFile > > MetaBitmapActionMap;
+
+struct PatternData
+{
+ BitmapChecksum aBitmapChecksum;
+ Point aPos;
+ Size aSize;
+ Size aSlideSize;
+};
+typedef std::map<OUString, PatternData> PatternPropertySet;
+
+class SVGFontExport;
+class SVGActionWriter;
+class EditFieldInfo;
+
+class SVGFilter : public cppu::WeakImplHelper < XFilter,
+ XImporter,
+ XExporter,
+ XExtendedFilterDetection, XServiceInfo >
+{
+public:
+ typedef std::unordered_map< Reference< XInterface >, ObjectRepresentation > ObjectMap;
+ typedef std::unordered_set< Reference< XInterface > > ObjectSet;
+
+ typedef std::unordered_set< sal_Unicode, HashUChar > UCharSet;
+ typedef std::unordered_map< OUString, UCharSet > UCharSetMap;
+ typedef std::unordered_map< Reference< XInterface >, UCharSetMap > UCharSetMapMap;
+
+ typedef std::unordered_set< ObjectRepresentation, HashBitmap, EqualityBitmap > MetaBitmapActionSet;
+
+private:
+
+ /// Generally use members
+
+ Reference< XComponentContext > mxContext;
+ SvXMLElementExport* mpSVGDoc;
+ rtl::Reference<SVGExport> mpSVGExport;
+ SVGFontExport* mpSVGFontExport;
+ SVGActionWriter* mpSVGWriter;
+ bool mbSinglePage;
+ sal_Int32 mnVisiblePage;
+ ObjectMap* mpObjects;
+ Reference< XComponent > mxSrcDoc;
+ Reference< XComponent > mxDstDoc;
+ // #i124608# explicit ShapeSelection for export when export of the selection is wanted
+ Reference< css::drawing::XShapes > maShapeSelection;
+ bool mbExportShapeSelection;
+ Sequence< PropertyValue > maFilterData;
+ Reference< css::drawing::XDrawPage > mxDefaultPage;
+ std::vector< Reference< css::drawing::XDrawPage > > mSelectedPages;
+ bool mbIsPreview;
+
+ bool mbWriterFilter;
+ bool mbCalcFilter;
+ bool mbImpressFilter;
+
+
+ /// Impress / draw only members
+
+ SdrPage* mpDefaultSdrPage;
+ bool mbPresentation;
+ PagePropertySet mVisiblePagePropSet;
+ OUString msClipPathId;
+ UCharSetMapMap mTextFieldCharSets;
+ Reference< XInterface > mCreateOjectsCurrentMasterPage;
+ std::unordered_map< Reference< XInterface >, OUString >
+ mTextShapeIdListMap;
+ MetaBitmapActionSet mEmbeddedBitmapActionSet;
+ ObjectMap mEmbeddedBitmapActionMap;
+ MetaBitmapActionMap maBitmapActionMap;
+ PatternPropertySet maPatterProps;
+ std::vector< Reference< css::drawing::XDrawPage > > mMasterPageTargets;
+
+ Link<EditFieldInfo*,void> maOldFieldHdl;
+ Link<EditFieldInfo*,void> maNewFieldHdl;
+
+ /// @throws css::uno::RuntimeException
+ bool implExport( const Sequence< PropertyValue >& rDescriptor );
+ bool implExportImpressOrDraw( const Reference< XOutputStream >& rxOStm );
+ bool implExportWriterOrCalc( const Reference< XOutputStream >& rxOStm );
+ bool implExportWriterTextGraphic( const Reference< view::XSelectionSupplier >& xSelectionSupplier );
+
+ static Reference< XWriter > implCreateExportDocumentHandler( const Reference< XOutputStream >& rxOStm );
+
+ void implGetPagePropSet( const Reference< css::drawing::XDrawPage > & rxPage );
+ void implGenerateMetaData();
+ void implExportTextShapeIndex();
+ void implEmbedBulletGlyphs();
+ void implEmbedBulletGlyph( sal_Unicode cBullet, const OUString & sPathData );
+ void implExportTextEmbeddedBitmaps();
+ void implExportBackgroundBitmaps();
+ void implExportTiledBackground();
+ void implGenerateScript();
+
+ bool implExportDocument();
+ void implExportDocumentHeaderImpressOrDraw(sal_Int32 nDocX, sal_Int32 nDocY,
+ sal_Int32 nDocWidth, sal_Int32 nDocHeight);
+ void implExportDocumentHeaderWriterOrCalc(sal_Int32 nDocX, sal_Int32 nDocY,
+ sal_Int32 nDocWidth, sal_Int32 nDocHeight);
+ void implExportAnimations();
+
+ bool implExportMasterPages( const std::vector< Reference< css::drawing::XDrawPage > >& rxPages,
+ sal_Int32 nFirstPage, sal_Int32 nLastPage );
+ void implExportDrawPages( const std::vector< Reference< css::drawing::XDrawPage > >& rxPages,
+ sal_Int32 nFirstPage, sal_Int32 nLastPage );
+ bool implExportPage( std::u16string_view sPageId,
+ const Reference< css::drawing::XDrawPage > & rxPage,
+ const Reference< css::drawing::XShapes > & xShapes,
+ bool bMaster );
+
+ bool implExportShapes( const Reference< css::drawing::XShapes >& rxShapes,
+ bool bMaster );
+ bool implExportShape( const Reference< css::drawing::XShape >& rxShape,
+ bool bMaster );
+
+ bool implCreateObjects();
+ bool implCreateObjectsFromShapes( const Reference< css::drawing::XDrawPage > & rxPage, const Reference< css::drawing::XShapes >& rxShapes );
+ bool implCreateObjectsFromShape( const Reference< css::drawing::XDrawPage > & rxPage, const Reference< css::drawing::XShape >& rxShape );
+ void implCreateObjectsFromBackground( const Reference< css::drawing::XDrawPage >& rxMasterPage );
+
+ static OUString implGetClassFromShape( const Reference< css::drawing::XShape >& rxShape );
+ void implRegisterInterface( const Reference< XInterface >& rxIf );
+ const OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf );
+ static OUString implGetInterfaceName( const Reference< XInterface >& rxIf );
+ bool implLookForFirstVisiblePage();
+ static Any implSafeGetPagePropSet( const OUString & sPropertyName,
+ const Reference< XPropertySet > & rxPropSet,
+ const Reference< XPropertySetInfo > & rxPropSetInfo );
+ DECL_LINK( CalcFieldHdl, EditFieldInfo*, void );
+
+ bool filterImpressOrDraw( const Sequence< PropertyValue >& rDescriptor );
+ bool filterWriterOrCalc( const Sequence< PropertyValue >& rDescriptor );
+
+protected:
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& rDescriptor ) override;
+ virtual void SAL_CALL cancel( ) override;
+
+ // XImporter
+ virtual void SAL_CALL setTargetDocument( const Reference< XComponent >& xDoc ) override;
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const Reference< XComponent >& xDoc ) override;
+
+ // XExtendedFilterDetection
+ virtual OUString SAL_CALL detect( Sequence< PropertyValue >& io_rDescriptor ) override;
+
+public:
+
+ explicit SVGFilter( const Reference< XComponentContext >& rxCtx );
+ virtual ~SVGFilter() override;
+
+ // XServiceInfo
+ virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override;
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgfontexport.cxx b/filter/source/svg/svgfontexport.cxx
new file mode 100644
index 000000000..7e75d65e6
--- /dev/null
+++ b/filter/source/svg/svgfontexport.cxx
@@ -0,0 +1,321 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "svgfontexport.hxx"
+#include "svgfilter.hxx"
+#include "svgwriter.hxx"
+
+#include <vcl/unohelp.hxx>
+#include <vcl/font.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/settings.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+
+const sal_Int32 nFontEM = 2048;
+
+
+SVGFontExport::SVGFontExport( SVGExport& rExport, ::std::vector< ObjectRepresentation >&& rObjects ) :
+ mrExport( rExport ),
+ maObjects( std::move(rObjects) ),
+ mnCurFontId( 0 )
+{
+}
+
+
+SVGFontExport::~SVGFontExport()
+{
+}
+
+
+SVGFontExport::GlyphSet& SVGFontExport::implGetGlyphSet( const vcl::Font& rFont )
+{
+ FontWeight eWeight( WEIGHT_NORMAL );
+ FontItalic eItalic( ITALIC_NONE );
+ const OUString& aFontName( rFont.GetFamilyName() );
+
+ switch( rFont.GetWeight() )
+ {
+ case WEIGHT_BOLD:
+ case WEIGHT_ULTRABOLD:
+ case WEIGHT_BLACK:
+ eWeight = WEIGHT_BOLD;
+ break;
+
+ default:
+ break;
+ }
+
+ if( rFont.GetItalic() != ITALIC_NONE )
+ eItalic = ITALIC_NORMAL;
+
+ return( maGlyphTree[ aFontName.getToken( 0, ';' ) ][ eWeight ][ eItalic ] );
+}
+
+
+void SVGFontExport::implCollectGlyphs()
+{
+ ScopedVclPtrInstance< VirtualDevice > pVDev;
+
+ pVDev->EnableOutput( false );
+
+ for (auto const& elem : maObjects)
+ {
+ if( elem.HasRepresentation() )
+ {
+ const GDIMetaFile& rMtf = elem.GetRepresentation();
+
+ pVDev->Push();
+
+ for( size_t i = 0, nCount = rMtf.GetActionSize(); i < nCount; ++i )
+ {
+ OUString aText;
+ MetaAction* pAction = rMtf.GetAction( i );
+ const MetaActionType nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case MetaActionType::TEXT:
+ {
+ const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
+ sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
+ aText = pA->GetText().copy( pA->GetIndex(), aLength );
+ }
+ break;
+
+ case MetaActionType::TEXTRECT:
+ {
+ const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
+ aText = pA->GetText();
+ }
+ break;
+
+ case MetaActionType::TEXTARRAY:
+ {
+ const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
+ sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
+ aText = pA->GetText().copy( pA->GetIndex(), aLength );
+ }
+ break;
+
+ case MetaActionType::STRETCHTEXT:
+ {
+ const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
+ sal_Int32 aLength=std::min( pA->GetText().getLength(), pA->GetLen() );
+ aText = pA->GetText().copy( pA->GetIndex(), aLength );
+ }
+ break;
+
+ default:
+ pAction->Execute( pVDev );
+ break;
+ }
+
+ if( !aText.isEmpty() )
+ {
+ GlyphSet& rGlyphSet = implGetGlyphSet( pVDev->GetFont() );
+ css::uno::Reference< css::i18n::XBreakIterator > xBI(
+ vcl::unohelper::CreateBreakIterator() );
+
+ if( xBI.is() )
+ {
+ const css::lang::Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
+ sal_Int32 nCurPos = 0, nLastPos = -1;
+
+ while( ( nCurPos < aText.getLength() ) && ( nCurPos > nLastPos ) )
+ {
+ sal_Int32 nCount2 = 1;
+
+ nLastPos = nCurPos;
+ nCurPos = xBI->nextCharacters( aText, nCurPos, rLocale,
+ css::i18n::CharacterIteratorMode::SKIPCELL,
+ nCount2, nCount2 );
+
+ rGlyphSet.insert( aText.copy( nLastPos, nCurPos - nLastPos ) );
+ }
+ }
+ else
+ {
+ const sal_Unicode* pStr = aText.getStr();
+
+ for( sal_uInt32 k = 0, nLen = aText.getLength(); k < nLen; ++k )
+ rGlyphSet.insert( OUString( pStr[ k ] ) );
+ }
+ }
+ }
+
+ pVDev->Pop();
+ }
+ }
+}
+
+
+void SVGFontExport::implEmbedFont( const vcl::Font& rFont )
+{
+ if( !mrExport.IsEmbedFonts() )
+ return;
+
+ GlyphSet& rGlyphSet = implGetGlyphSet( rFont );
+
+ if( rGlyphSet.empty() )
+ return;
+
+ {
+ SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "defs", true, true );
+ OUString aCurIdStr( "EmbeddedFont_" );
+ OUString aUnitsPerEM( OUString::number( nFontEM ) );
+ ScopedVclPtrInstance< VirtualDevice > pVDev;
+ vcl::Font aFont( rFont );
+
+ aFont.SetFontSize( Size( 0, nFontEM ) );
+ aFont.SetAlignment( ALIGN_BASELINE );
+
+ pVDev->SetMapMode(MapMode(MapUnit::Map100thMM));
+ pVDev->SetFont( aFont );
+
+ aCurIdStr += OUString::number( ++mnCurFontId );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", aCurIdStr );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", aUnitsPerEM );
+
+ {
+ SvXMLElementExport aExp2( mrExport, XML_NAMESPACE_NONE, "font", true, true );
+ OUString aFontWeight;
+ OUString aFontStyle;
+ const Size aSize( nFontEM, nFontEM );
+
+ // Font Weight
+ if( aFont.GetWeight() != WEIGHT_NORMAL )
+ aFontWeight = "bold";
+ else
+ aFontWeight = "normal";
+
+ // Font Italic
+ if( aFont.GetItalic() != ITALIC_NONE )
+ aFontStyle = "italic";
+ else
+ aFontStyle = "normal";
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-family", GetMappedFontName( rFont.GetFamilyName() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "units-per-em", aUnitsPerEM );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-weight", aFontWeight );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "font-style", aFontStyle );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "ascent", OUString::number( pVDev->GetFontMetric().GetAscent() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "descent", OUString::number( pVDev->GetFontMetric().GetDescent() ) );
+
+ {
+ SvXMLElementExport aExp3( mrExport, XML_NAMESPACE_NONE, "font-face", true, true );
+ }
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", OUString::number( aSize.Width() ) );
+
+ {
+ const Point aPos;
+ const tools::PolyPolygon aMissingGlyphPolyPoly( tools::Rectangle( aPos, aSize ) );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", SVGActionWriter::GetPathString( aMissingGlyphPolyPoly, false ) );
+
+ {
+ SvXMLElementExport aExp4( mrExport, XML_NAMESPACE_NONE, "missing-glyph", true, true );
+ }
+ }
+ for (auto const& glyph : rGlyphSet)
+ {
+ implEmbedGlyph( *pVDev, glyph);
+ }
+ }
+ }
+}
+
+
+void SVGFontExport::implEmbedGlyph( OutputDevice const & rOut, const OUString& rCellStr )
+{
+ tools::PolyPolygon aPolyPoly;
+ const sal_Unicode nSpace = ' ';
+
+ if( !rOut.GetTextOutline( aPolyPoly, rCellStr ) )
+ return;
+
+ tools::Rectangle aBoundRect;
+
+ aPolyPoly.Scale( 1.0, -1.0 );
+
+ if( !rOut.GetTextBoundRect( aBoundRect, rCellStr ) )
+ aBoundRect = tools::Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( rCellStr ), 0 ) );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "unicode", rCellStr );
+
+ if( rCellStr[ 0 ] == nSpace && rCellStr.getLength() == 1 )
+ aBoundRect = tools::Rectangle( Point( 0, 0 ), Size( rOut.GetTextWidth( OUString(' ') ), 0 ) );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "horiz-adv-x", OUString::number( aBoundRect.GetWidth() ) );
+
+ const OUString aPathString( SVGActionWriter::GetPathString( aPolyPoly, false ) );
+ if( !aPathString.isEmpty() )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", aPathString );
+ }
+
+ {
+ SvXMLElementExport aExp( mrExport, XML_NAMESPACE_NONE, "glyph", true, true );
+ }
+}
+
+
+void SVGFontExport::EmbedFonts()
+{
+ implCollectGlyphs();
+
+ for (auto const& glyph : maGlyphTree)
+ {
+ const FontWeightMap& rFontWeightMap = glyph.second;
+ for (auto const& fontWeight : rFontWeightMap)
+ {
+ const FontItalicMap& rFontItalicMap = fontWeight.second;
+ for (auto const& fontItalic : rFontItalicMap)
+ {
+ vcl::Font aFont;
+
+ aFont.SetFamilyName( glyph.first );
+ aFont.SetWeight( fontWeight.first );
+ aFont.SetItalic( fontItalic.first );
+
+ implEmbedFont( aFont );
+ }
+ }
+ }
+}
+
+
+OUString SVGFontExport::GetMappedFontName( std::u16string_view rFontName ) const
+{
+ OUString aRet( o3tl::getToken(rFontName, 0, ';' ) );
+
+ if( mnCurFontId )
+ aRet += " embedded";
+
+ return aRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgfontexport.hxx b/filter/source/svg/svgfontexport.hxx
new file mode 100644
index 000000000..259196f9e
--- /dev/null
+++ b/filter/source/svg/svgfontexport.hxx
@@ -0,0 +1,72 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <sal/config.h>
+
+#include <functional>
+#include <map>
+#include <set>
+#include <vector>
+
+#include <rtl/ustring.hxx>
+#include <tools/fontenum.hxx>
+
+
+class ObjectRepresentation;
+class SVGExport;
+namespace vcl { class Font; }
+class OutputDevice;
+
+#ifdef _MSC_VER
+#pragma warning (disable : 4503) // FontNameMap gives decorated name length exceeded
+#endif
+
+class SVGFontExport
+{
+ typedef ::std::vector< ObjectRepresentation > ObjectVector;
+ typedef ::std::set< OUString, ::std::greater< OUString > > GlyphSet;
+ typedef ::std::map< FontItalic, GlyphSet > FontItalicMap;
+ typedef ::std::map< FontWeight, FontItalicMap > FontWeightMap;
+ typedef ::std::map< OUString, FontWeightMap > FontNameMap;
+ typedef FontNameMap GlyphTree;
+
+private:
+
+ SVGExport& mrExport;
+ GlyphTree maGlyphTree;
+ ObjectVector maObjects;
+ sal_Int32 mnCurFontId;
+
+ GlyphSet& implGetGlyphSet( const vcl::Font& rFont );
+ void implCollectGlyphs();
+ void implEmbedFont( const vcl::Font& rFont );
+ void implEmbedGlyph( OutputDevice const & rOut, const OUString& rCellStr );
+
+public:
+
+ SVGFontExport( SVGExport& rExport, ::std::vector< ObjectRepresentation >&& rObjects );
+ ~SVGFontExport();
+
+ void EmbedFonts();
+ OUString GetMappedFontName( std::u16string_view rFontName ) const;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgwriter.cxx b/filter/source/svg/svgwriter.cxx
new file mode 100644
index 000000000..3a3fc8a5c
--- /dev/null
+++ b/filter/source/svg/svgwriter.cxx
@@ -0,0 +1,4096 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "svgfilter.hxx"
+#include "svgfontexport.hxx"
+#include "svgwriter.hxx"
+
+#include <comphelper/base64.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <sal/log.hxx>
+#include <vcl/unohelp.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/filter/SvmReader.hxx>
+#include <vcl/filter/SvmWriter.hxx>
+#include <tools/fract.hxx>
+#include <tools/helpers.hxx>
+#include <tools/stream.hxx>
+#include <xmloff/namespacemap.hxx>
+#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <o3tl/string_view.hxx>
+
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XIndexReplace.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
+#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/style/NumberingType.hpp>
+#include <com/sun/star/text/XTextField.hpp>
+
+#include <memory>
+
+
+constexpr OUStringLiteral aPrefixClipPathId = u"clip_path_";
+
+constexpr OUStringLiteral aXMLElemG = u"g";
+constexpr OUStringLiteral aXMLElemDefs = u"defs";
+constexpr OUStringLiteral aXMLElemText = u"text";
+constexpr OUStringLiteral aXMLElemTspan = u"tspan";
+constexpr OUStringLiteral aXMLElemLinearGradient = u"linearGradient";
+constexpr OUStringLiteral aXMLElemStop = u"stop";
+
+constexpr OUStringLiteral aXMLAttrTransform = u"transform";
+constexpr OUStringLiteral aXMLAttrStyle = u"style";
+constexpr OUStringLiteral aXMLAttrId = u"id";
+constexpr OUStringLiteral aXMLAttrX = u"x";
+constexpr OUStringLiteral aXMLAttrY = u"y";
+constexpr OUStringLiteral aXMLAttrX1 = u"x1";
+constexpr OUStringLiteral aXMLAttrY1 = u"y1";
+constexpr OUStringLiteral aXMLAttrX2 = u"x2";
+constexpr OUStringLiteral aXMLAttrY2 = u"y2";
+constexpr OUStringLiteral aXMLAttrCX = u"cx";
+constexpr OUStringLiteral aXMLAttrCY = u"cy";
+constexpr OUStringLiteral aXMLAttrRX = u"rx";
+constexpr OUStringLiteral aXMLAttrRY = u"ry";
+constexpr OUStringLiteral aXMLAttrWidth = u"width";
+constexpr OUStringLiteral aXMLAttrHeight = u"height";
+constexpr OUStringLiteral aXMLAttrStrokeWidth = u"stroke-width";
+constexpr OUStringLiteral aXMLAttrFill = u"fill";
+constexpr OUStringLiteral aXMLAttrFontFamily = u"font-family";
+constexpr OUStringLiteral aXMLAttrFontSize = u"font-size";
+constexpr OUStringLiteral aXMLAttrFontStyle = u"font-style";
+constexpr OUStringLiteral aXMLAttrFontWeight = u"font-weight";
+constexpr OUStringLiteral aXMLAttrTextDecoration = u"text-decoration";
+constexpr OUStringLiteral aXMLAttrXLinkHRef = u"xlink:href";
+constexpr OUStringLiteral aXMLAttrGradientUnits = u"gradientUnits";
+constexpr OUStringLiteral aXMLAttrOffset = u"offset";
+constexpr OUStringLiteral aXMLAttrStopColor = u"stop-color";
+constexpr OUStringLiteral aXMLAttrStrokeLinejoin = u"stroke-linejoin";
+constexpr OUStringLiteral aXMLAttrStrokeLinecap = u"stroke-linecap";
+
+
+vcl::PushFlags SVGContextHandler::getPushFlags() const
+{
+ if (maStateStack.empty())
+ return vcl::PushFlags::NONE;
+
+ const PartialState& rPartialState = maStateStack.top();
+ return rPartialState.meFlags;
+}
+
+SVGState& SVGContextHandler::getCurrentState()
+{
+ return maCurrentState;
+}
+
+void SVGContextHandler::pushState( vcl::PushFlags eFlags )
+{
+ PartialState aPartialState;
+ aPartialState.meFlags = eFlags;
+
+ if (eFlags & vcl::PushFlags::FONT)
+ {
+ aPartialState.setFont( maCurrentState.aFont );
+ }
+
+ if (eFlags & vcl::PushFlags::CLIPREGION)
+ {
+ aPartialState.mnRegionClipPathId = maCurrentState.nRegionClipPathId;
+ }
+
+ maStateStack.push( std::move(aPartialState) );
+}
+
+void SVGContextHandler::popState()
+{
+ if (maStateStack.empty())
+ return;
+
+ const PartialState& rPartialState = maStateStack.top();
+ vcl::PushFlags eFlags = rPartialState.meFlags;
+
+ if (eFlags & vcl::PushFlags::FONT)
+ {
+ maCurrentState.aFont = rPartialState.getFont( vcl::Font() );
+ }
+
+ if (eFlags & vcl::PushFlags::CLIPREGION)
+ {
+ maCurrentState.nRegionClipPathId = rPartialState.mnRegionClipPathId;
+ }
+
+ maStateStack.pop();
+}
+
+SVGAttributeWriter::SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport, SVGState& rCurState )
+ : mrExport( rExport )
+ , mrFontExport( rFontExport )
+ , mrCurrentState( rCurState )
+{
+}
+
+
+SVGAttributeWriter::~SVGAttributeWriter()
+{
+}
+
+
+double SVGAttributeWriter::ImplRound( double fValue )
+{
+ return floor( fValue * pow( 10.0, 3 ) + 0.5 ) / pow( 10.0, 3 );
+}
+
+
+void SVGAttributeWriter::ImplGetColorStr( const Color& rColor, OUString& rColorStr )
+{
+ if( rColor.GetAlpha() == 0 )
+ rColorStr = "none";
+ else
+ {
+ rColorStr = "rgb(" + OUString::number(rColor.GetRed()) + "," + OUString::number(rColor.GetGreen()) +
+ "," + OUString::number(rColor.GetBlue()) + ")";
+ }
+}
+
+
+void SVGAttributeWriter::AddColorAttr( const OUString& pColorAttrName,
+ const OUString& pColorOpacityAttrName,
+ const Color& rColor )
+{
+ OUString aColor, aColorOpacity;
+
+ ImplGetColorStr( rColor, aColor );
+
+ if( rColor.GetAlpha() < 255 && rColor.GetAlpha() > 0 )
+ aColorOpacity = OUString::number( ImplRound( rColor.GetAlpha() / 255.0 ) );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, pColorAttrName, aColor );
+
+ if( !aColorOpacity.isEmpty() && mrExport.IsUseOpacity() )
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, pColorOpacityAttrName, aColorOpacity );
+}
+
+
+void SVGAttributeWriter::AddPaintAttr( const Color& rLineColor, const Color& rFillColor,
+ const tools::Rectangle* pObjBoundRect, const Gradient* pFillGradient )
+{
+ // Fill
+ if( pObjBoundRect && pFillGradient )
+ {
+ OUString aGradientId;
+
+ AddGradientDef( *pObjBoundRect, *pFillGradient, aGradientId );
+
+ if( !aGradientId.isEmpty() )
+ {
+ OUString aGradientURL = "url(#" + aGradientId + ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFill, aGradientURL );
+ }
+ }
+ else
+ AddColorAttr( aXMLAttrFill, "fill-opacity", rFillColor );
+
+ // Stroke
+ AddColorAttr( "stroke", "stroke-opacity", rLineColor );
+}
+
+
+void SVGAttributeWriter::AddGradientDef( const tools::Rectangle& rObjRect, const Gradient& rGradient, OUString& rGradientId )
+{
+ if( rObjRect.GetWidth() && rObjRect.GetHeight() &&
+ ( rGradient.GetStyle() == GradientStyle::Linear || rGradient.GetStyle() == GradientStyle::Axial ||
+ rGradient.GetStyle() == GradientStyle::Radial || rGradient.GetStyle() == GradientStyle::Elliptical ) )
+ {
+ SvXMLElementExport aDesc( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
+ Color aStartColor( rGradient.GetStartColor() ), aEndColor( rGradient.GetEndColor() );
+ Degree10 nAngle = rGradient.GetAngle() % 3600_deg10;
+ Point aObjRectCenter( rObjRect.Center() );
+ tools::Polygon aPoly( rObjRect );
+ static sal_Int32 nCurGradientId = 1;
+
+ aPoly.Rotate( aObjRectCenter, nAngle );
+ tools::Rectangle aRect( aPoly.GetBoundRect() );
+
+ // adjust start/end colors with intensities
+ aStartColor.SetRed( static_cast<sal_uInt8>( ( aStartColor.GetRed() * rGradient.GetStartIntensity() ) / 100 ) );
+ aStartColor.SetGreen( static_cast<sal_uInt8>( ( aStartColor.GetGreen() * rGradient.GetStartIntensity() ) / 100 ) );
+ aStartColor.SetBlue( static_cast<sal_uInt8>( ( aStartColor.GetBlue() * rGradient.GetStartIntensity() ) / 100 ) );
+
+ aEndColor.SetRed( static_cast<sal_uInt8>( ( aEndColor.GetRed() * rGradient.GetEndIntensity() ) / 100 ) );
+ aEndColor.SetGreen( static_cast<sal_uInt8>( ( aEndColor.GetGreen() * rGradient.GetEndIntensity() ) / 100 ) );
+ aEndColor.SetBlue( static_cast<sal_uInt8>( ( aEndColor.GetBlue() * rGradient.GetEndIntensity() ) / 100 ) );
+
+ rGradientId = "Gradient_" + OUString::number( nCurGradientId++ );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, rGradientId );
+
+ {
+ std::unique_ptr< SvXMLElementExport > apGradient;
+ OUString aColorStr;
+
+ if( rGradient.GetStyle() == GradientStyle::Linear || rGradient.GetStyle() == GradientStyle::Axial )
+ {
+ tools::Polygon aLinePoly( 2 );
+
+ aLinePoly[ 0 ] = Point( aObjRectCenter.X(), aRect.Top() );
+ aLinePoly[ 1 ] = Point( aObjRectCenter.X(), aRect.Bottom() );
+
+ aLinePoly.Rotate( aObjRectCenter, nAngle );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrGradientUnits, "userSpaceOnUse" );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, OUString::number( aLinePoly[ 0 ].X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, OUString::number( aLinePoly[ 0 ].Y() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, OUString::number( aLinePoly[ 1 ].X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, OUString::number( aLinePoly[ 1 ].Y() ) );
+
+ apGradient.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemLinearGradient, true, true ) );
+
+ // write stop values
+ double fBorder = static_cast< double >( rGradient.GetBorder() ) *
+ ( ( rGradient.GetStyle() == GradientStyle::Axial ) ? 0.005 : 0.01 );
+
+ ImplGetColorStr( ( rGradient.GetStyle() == GradientStyle::Axial ) ? aEndColor : aStartColor, aColorStr );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( fBorder ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
+
+ {
+ SvXMLElementExport aDesc2( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
+ }
+
+ if( rGradient.GetStyle() == GradientStyle::Axial )
+ {
+ ImplGetColorStr( aStartColor, aColorStr );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( 0.5 ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
+
+ {
+ SvXMLElementExport aDesc3( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
+ }
+ }
+
+ if( rGradient.GetStyle() != GradientStyle::Axial )
+ fBorder = 0.0;
+
+ ImplGetColorStr( aEndColor, aColorStr );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( ImplRound( 1.0 - fBorder ) ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
+
+ {
+ SvXMLElementExport aDesc4( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
+ }
+ }
+ else
+ {
+ const double fCenterX = rObjRect.Left() + rObjRect.GetWidth() * rGradient.GetOfsX() * 0.01;
+ const double fCenterY = rObjRect.Top() + rObjRect.GetHeight() * rGradient.GetOfsY() * 0.01;
+ const double fRadius = std::hypot(rObjRect.GetWidth(), rObjRect.GetHeight()) * 0.5;
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrGradientUnits, "userSpaceOnUse" );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, OUString::number( ImplRound( fCenterX ) ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCY, OUString::number( ImplRound( fCenterY ) ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "r", OUString::number( ImplRound( fRadius ) ) );
+
+ apGradient.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, "radialGradient", true, true ) );
+
+ // write stop values
+ ImplGetColorStr( aEndColor, aColorStr );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( 0.0 ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
+
+ {
+ SvXMLElementExport aDesc5( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
+ }
+
+ ImplGetColorStr( aStartColor, aColorStr );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset,
+ OUString::number( ImplRound( 1.0 - rGradient.GetBorder() * 0.01 ) ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStopColor, aColorStr );
+
+ {
+ SvXMLElementExport aDesc6( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
+ }
+ }
+ }
+ }
+ else
+ rGradientId.clear();
+}
+
+
+void SVGAttributeWriter::SetFontAttr( const vcl::Font& rFont )
+{
+ vcl::Font& rCurFont = mrCurrentState.aFont;
+
+ if( rFont == rCurFont )
+ return;
+
+ OUString aFontStyle;
+ sal_Int32 nFontWeight;
+
+ rCurFont = rFont;
+
+ // Font Family
+ setFontFamily();
+
+ // Font Size
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontSize,
+ OUString::number( rFont.GetFontHeight() ) + "px" );
+
+ // Font Style
+ if( rFont.GetItalic() != ITALIC_NONE )
+ {
+ if( rFont.GetItalic() == ITALIC_OBLIQUE )
+ aFontStyle = "oblique";
+ else
+ aFontStyle = "italic";
+ }
+ else
+ aFontStyle = "normal";
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontStyle, aFontStyle );
+
+ // Font Weight
+ switch( rFont.GetWeight() )
+ {
+ case WEIGHT_THIN: nFontWeight = 100; break;
+ case WEIGHT_ULTRALIGHT: nFontWeight = 200; break;
+ case WEIGHT_LIGHT: nFontWeight = 300; break;
+ case WEIGHT_SEMILIGHT: nFontWeight = 400; break;
+ case WEIGHT_NORMAL: nFontWeight = 400; break;
+ case WEIGHT_MEDIUM: nFontWeight = 500; break;
+ case WEIGHT_SEMIBOLD: nFontWeight = 600; break;
+ case WEIGHT_BOLD: nFontWeight = 700; break;
+ case WEIGHT_ULTRABOLD: nFontWeight = 800; break;
+ case WEIGHT_BLACK: nFontWeight = 900; break;
+ default: nFontWeight = 400; break;
+ }
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontWeight, OUString::number( nFontWeight ) );
+
+ if( mrExport.IsUseNativeTextDecoration() )
+ {
+ OUString aTextDecoration;
+ if( rFont.GetUnderline() != LINESTYLE_NONE || rFont.GetStrikeout() != STRIKEOUT_NONE )
+ {
+ if( rFont.GetUnderline() != LINESTYLE_NONE )
+ aTextDecoration = "underline ";
+
+ if( rFont.GetStrikeout() != STRIKEOUT_NONE )
+ aTextDecoration += "line-through ";
+ }
+ else
+ aTextDecoration = "none";
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTextDecoration, aTextDecoration );
+ }
+
+ startFontSettings();
+}
+
+
+void SVGAttributeWriter::startFontSettings()
+{
+ endFontSettings();
+ if( mrExport.IsUsePositionedCharacters() )
+ {
+ mpElemFont.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true ) );
+ }
+ else
+ {
+ mpElemFont.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, true, true ) );
+ }
+}
+
+
+void SVGAttributeWriter::endFontSettings()
+{
+ mpElemFont.reset();
+}
+
+
+void SVGAttributeWriter::setFontFamily()
+{
+ vcl::Font& rCurFont = mrCurrentState.aFont;
+
+ if( mrExport.IsUsePositionedCharacters() )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontFamily, mrFontExport.GetMappedFontName( rCurFont.GetFamilyName() ) );
+ }
+ else
+ {
+ const OUString& rsFontName = rCurFont.GetFamilyName();
+ OUString sFontFamily( rsFontName.getToken( 0, ';' ) );
+ FontPitch ePitch = rCurFont.GetPitch();
+ if( ePitch == PITCH_FIXED )
+ {
+ sFontFamily += ", monospace";
+ }
+ else
+ {
+ FontFamily eFamily = rCurFont.GetFamilyType();
+ if( eFamily == FAMILY_ROMAN )
+ sFontFamily += ", serif";
+ else if( eFamily == FAMILY_SWISS )
+ sFontFamily += ", sans-serif";
+ }
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontFamily, sFontFamily );
+ }
+}
+
+SVGTextWriter::SVGTextWriter(SVGExport& rExport, SVGAttributeWriter& rAttributeWriter,
+ SVGActionWriter& rActionWriter)
+: mrExport( rExport ),
+ mrAttributeWriter( rAttributeWriter ),
+ mrActionWriter(rActionWriter),
+ mpVDev( nullptr ),
+ mbIsTextShapeStarted( false ),
+ mpTextEmbeddedBitmapMtf( nullptr ),
+ mpTargetMapMode( nullptr ),
+ mnLeftTextPortionLength( 0 ),
+ maTextPos(0,0),
+ mnTextWidth(0),
+ mbPositioningNeeded( false ),
+ mbIsNewListItem( false ),
+ meNumberingType(0),
+ mcBulletChar(0),
+ mbIsListLevelStyleImage( false ),
+ mbLineBreak( false ),
+ mbIsURLField( false ),
+ mbIsPlaceholderShape( false )
+{
+}
+
+
+SVGTextWriter::~SVGTextWriter()
+{
+ endTextParagraph();
+}
+
+
+void SVGTextWriter::implRegisterInterface( const Reference< XInterface >& rxIf )
+{
+ if( rxIf.is() )
+ mrExport.getInterfaceToIdentifierMapper().registerReference( rxIf );
+}
+
+
+const OUString & SVGTextWriter::implGetValidIDFromInterface( const Reference< XInterface >& rxIf )
+{
+ return mrExport.getInterfaceToIdentifierMapper().getIdentifier( rxIf );
+}
+
+
+void SVGTextWriter::implMap( const Size& rSz, Size& rDstSz ) const
+{
+ if( mpVDev && mpTargetMapMode )
+ rDstSz = OutputDevice::LogicToLogic( rSz, mpVDev->GetMapMode(), *mpTargetMapMode );
+ else
+ OSL_FAIL( "SVGTextWriter::implMap: invalid virtual device or map mode." );
+}
+
+
+void SVGTextWriter::implMap( const Point& rPt, Point& rDstPt ) const
+{
+ if( mpVDev && mpTargetMapMode )
+ rDstPt = OutputDevice::LogicToLogic( rPt, mpVDev->GetMapMode(), *mpTargetMapMode );
+ else
+ OSL_FAIL( "SVGTextWriter::implMap: invalid virtual device or map mode." );
+}
+
+
+void SVGTextWriter::implSetCurrentFont()
+{
+ if( mpVDev )
+ {
+ maCurrentFont = mpVDev->GetFont();
+ Size aSz;
+
+ implMap( Size( 0, maCurrentFont.GetFontHeight() ), aSz );
+
+ maCurrentFont.SetFontHeight( aSz.Height() );
+ }
+ else
+ {
+ OSL_FAIL( "SVGTextWriter::implSetCorrectFontHeight: invalid virtual device." );
+ }
+}
+
+
+template< typename SubType >
+bool SVGTextWriter::implGetTextPosition( const MetaAction* pAction, Point& raPos, bool& rbEmpty )
+{
+ const SubType* pA = static_cast<const SubType*>(pAction);
+ sal_uInt16 nLength = pA->GetLen();
+ rbEmpty = ( nLength == 0 );
+ if( !rbEmpty )
+ {
+ raPos = pA->GetPoint();
+ return true;
+ }
+ return false;
+}
+
+
+template<>
+bool SVGTextWriter::implGetTextPosition<MetaTextRectAction>( const MetaAction* pAction, Point& raPos, bool& rbEmpty )
+{
+ const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
+ sal_uInt16 nLength = pA->GetText().getLength();
+ rbEmpty = ( nLength == 0 );
+ if( !rbEmpty )
+ {
+ raPos = pA->GetRect().TopLeft();
+ return true;
+ }
+ return false;
+}
+
+
+template< typename SubType >
+bool SVGTextWriter::implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, bool& rbEmpty )
+{
+ const SubType* pA = static_cast<const SubType*>(pAction);
+ raPos = pA->GetPoint();
+ rbEmpty = false;
+ return true;
+}
+
+
+/** setTextPosition
+ * Set the start position of the next line of text. In case no text is found
+ * the current action index is updated to the index value we reached while
+ * searching for text.
+ *
+ * @returns {sal_Int32}
+ * -2 if no text found and end of line is reached
+ * -1 if no text found and end of paragraph is reached
+ * 0 if no text found and end of text shape is reached
+ * 1 if text found!
+ */
+sal_Int32 SVGTextWriter::setTextPosition(const GDIMetaFile& rMtf, size_t& nCurAction,
+ sal_uInt32 nWriteFlags)
+{
+ Point aPos;
+ size_t nCount = rMtf.GetActionSize();
+ bool bEOL = false;
+ bool bEOP = false;
+ bool bETS = false;
+ bool bConfigured = false;
+ bool bEmpty = true;
+
+ size_t nActionIndex = nCurAction + 1;
+ for( ; nActionIndex < nCount; ++nActionIndex )
+ {
+ const MetaAction* pAction = rMtf.GetAction( nActionIndex );
+ const MetaActionType nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case MetaActionType::TEXT:
+ {
+ bConfigured = implGetTextPosition<MetaTextAction>( pAction, aPos, bEmpty );
+ }
+ break;
+
+ case MetaActionType::TEXTRECT:
+ {
+ bConfigured = implGetTextPosition<MetaTextRectAction>( pAction, aPos, bEmpty );
+ }
+ break;
+
+ case MetaActionType::TEXTARRAY:
+ {
+ bConfigured = implGetTextPosition<MetaTextArrayAction>( pAction, aPos, bEmpty );
+ }
+ break;
+
+ case MetaActionType::FLOATTRANSPARENT:
+ {
+ const MetaFloatTransparentAction* pA
+ = static_cast<const MetaFloatTransparentAction*>(pAction);
+ GDIMetaFile aTmpMtf(pA->GetGDIMetaFile());
+ size_t nTmpAction = 0;
+ if (setTextPosition(aTmpMtf, nTmpAction, nWriteFlags) == 1)
+ {
+ // Text is found in the inner metafile.
+ bConfigured = true;
+
+ // nTextFound == 1 is only possible if the inner setTextPosition() had bEmpty ==
+ // false, adjust our bEmpty accordingly.
+ bEmpty = false;
+
+ mrActionWriter.StartMask(pA->GetPoint(), pA->GetSize(), pA->GetGradient(),
+ nWriteFlags, &maTextOpacity);
+ }
+ }
+ break;
+
+ case MetaActionType::STRETCHTEXT:
+ {
+ bConfigured = implGetTextPosition<MetaStretchTextAction>( pAction, aPos, bEmpty );
+ }
+ break;
+
+ case MetaActionType::BMPSCALE:
+ {
+ bConfigured = implGetTextPositionFromBitmap<MetaBmpScaleAction>( pAction, aPos, bEmpty );
+ }
+ break;
+
+ case MetaActionType::BMPEXSCALE:
+ {
+ bConfigured = implGetTextPositionFromBitmap<MetaBmpExScaleAction>( pAction, aPos, bEmpty );
+ }
+ break;
+
+ // If we reach the end of the current line, paragraph or text shape
+ // without finding any text we stop searching
+ case MetaActionType::COMMENT:
+ {
+ const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
+ const OString& rsComment = pA->GetComment();
+ if( rsComment.equalsIgnoreAsciiCase( "XTEXT_EOL" ) )
+ {
+ bEOL = true;
+ }
+ else if( rsComment.equalsIgnoreAsciiCase( "XTEXT_EOP" ) )
+ {
+ bEOP = true;
+
+ OUString sContent;
+ while( nextTextPortion() )
+ {
+ sContent = mrCurrentTextPortion->getString();
+ if( sContent.isEmpty() )
+ {
+ continue;
+ }
+ else
+ {
+ if( sContent == "\n" )
+ mbLineBreak = true;
+ }
+ }
+ if( nextParagraph() )
+ {
+ while( nextTextPortion() )
+ {
+ sContent = mrCurrentTextPortion->getString();
+ if( sContent.isEmpty() )
+ {
+ continue;
+ }
+ else
+ {
+ if( sContent == "\n" )
+ mbLineBreak = true;
+ }
+ }
+ }
+ }
+ else if( rsComment.equalsIgnoreAsciiCase( "XTEXT_PAINTSHAPE_END" ) )
+ {
+ bETS = true;
+ }
+ }
+ break;
+ default: break;
+ }
+ if( bConfigured || bEOL || bEOP || bETS ) break;
+ }
+ implMap( aPos, maTextPos );
+
+ if( bEmpty )
+ {
+ nCurAction = nActionIndex;
+ return ( bEOL ? -2 : ( bEOP ? -1 : 0 ) );
+ }
+ else
+ {
+ return 1;
+ }
+}
+
+
+void SVGTextWriter::setTextProperties( const GDIMetaFile& rMtf, size_t nCurAction )
+{
+ size_t nCount = rMtf.GetActionSize();
+ bool bEOP = false;
+ bool bConfigured = false;
+ for( size_t nActionIndex = nCurAction + 1; nActionIndex < nCount; ++nActionIndex )
+ {
+ const MetaAction* pAction = rMtf.GetAction( nActionIndex );
+ const MetaActionType nType = pAction->GetType();
+ switch( nType )
+ {
+ case MetaActionType::TEXTLINECOLOR:
+ case MetaActionType::TEXTFILLCOLOR:
+ case MetaActionType::TEXTCOLOR:
+ case MetaActionType::TEXTALIGN:
+ case MetaActionType::FONT:
+ case MetaActionType::LAYOUTMODE:
+ {
+ const_cast<MetaAction*>(pAction)->Execute( mpVDev );
+ }
+ break;
+
+ case MetaActionType::TEXT:
+ {
+ const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
+ if( pA->GetLen() > 2 )
+ bConfigured = true;
+ }
+ break;
+ case MetaActionType::TEXTRECT:
+ {
+ const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
+ if( pA->GetText().getLength() > 2 )
+ bConfigured = true;
+ }
+ break;
+ case MetaActionType::TEXTARRAY:
+ {
+ const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
+ if( pA->GetLen() > 2 )
+ bConfigured = true;
+ }
+ break;
+ case MetaActionType::STRETCHTEXT:
+ {
+ const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
+ if( pA->GetLen() > 2 )
+ bConfigured = true;
+ }
+ break;
+ // If we reach the end of the paragraph without finding any text
+ // we stop searching
+ case MetaActionType::COMMENT:
+ {
+ const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
+ const OString& rsComment = pA->GetComment();
+ if( rsComment.equalsIgnoreAsciiCase( "XTEXT_EOP" ) )
+ {
+ bEOP = true;
+ }
+ }
+ break;
+ default: break;
+ }
+ if( bConfigured || bEOP ) break;
+ }
+}
+
+
+void SVGTextWriter::addFontAttributes( bool bIsTextContainer )
+{
+ implSetCurrentFont();
+
+ if( maCurrentFont == maParentFont )
+ return;
+
+ const OUString& rsCurFontName = maCurrentFont.GetFamilyName();
+ tools::Long nCurFontSize = maCurrentFont.GetFontHeight();
+ FontItalic eCurFontItalic = maCurrentFont.GetItalic();
+ FontWeight eCurFontWeight = maCurrentFont.GetWeight();
+
+ const OUString& rsParFontName = maParentFont.GetFamilyName();
+ tools::Long nParFontSize = maParentFont.GetFontHeight();
+ FontItalic eParFontItalic = maParentFont.GetItalic();
+ FontWeight eParFontWeight = maParentFont.GetWeight();
+
+
+ // Font Family
+ if( rsCurFontName != rsParFontName )
+ {
+ implSetFontFamily();
+ }
+
+ // Font Size
+ if( nCurFontSize != nParFontSize )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontSize,
+ OUString::number( nCurFontSize ) + "px" );
+ }
+
+ // Font Style
+ if( eCurFontItalic != eParFontItalic )
+ {
+ OUString sFontStyle;
+ if( eCurFontItalic != ITALIC_NONE )
+ {
+ if( eCurFontItalic == ITALIC_OBLIQUE )
+ sFontStyle = "oblique";
+ else
+ sFontStyle = "italic";
+ }
+ else
+ {
+ sFontStyle = "normal";
+ }
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontStyle, sFontStyle );
+ }
+
+ // Font Weight
+ if( eCurFontWeight != eParFontWeight )
+ {
+ sal_Int32 nFontWeight;
+ switch( eCurFontWeight )
+ {
+ case WEIGHT_THIN: nFontWeight = 100; break;
+ case WEIGHT_ULTRALIGHT: nFontWeight = 200; break;
+ case WEIGHT_LIGHT: nFontWeight = 300; break;
+ case WEIGHT_SEMILIGHT: nFontWeight = 400; break;
+ case WEIGHT_NORMAL: nFontWeight = 400; break;
+ case WEIGHT_MEDIUM: nFontWeight = 500; break;
+ case WEIGHT_SEMIBOLD: nFontWeight = 600; break;
+ case WEIGHT_BOLD: nFontWeight = 700; break;
+ case WEIGHT_ULTRABOLD: nFontWeight = 800; break;
+ case WEIGHT_BLACK: nFontWeight = 900; break;
+ default: nFontWeight = 400; break;
+ }
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontWeight, OUString::number( nFontWeight ) );
+ }
+
+
+ if( mrExport.IsUseNativeTextDecoration() )
+ {
+ FontLineStyle eCurFontLineStyle = maCurrentFont.GetUnderline();
+ FontStrikeout eCurFontStrikeout = maCurrentFont.GetStrikeout();
+
+ FontLineStyle eParFontLineStyle = maParentFont.GetUnderline();
+ FontStrikeout eParFontStrikeout = maParentFont.GetStrikeout();
+
+ OUString sTextDecoration;
+ bool bIsDecorationChanged = false;
+ if( eCurFontLineStyle != eParFontLineStyle )
+ {
+ if( eCurFontLineStyle != LINESTYLE_NONE )
+ sTextDecoration = "underline";
+ bIsDecorationChanged = true;
+ }
+ if( eCurFontStrikeout != eParFontStrikeout )
+ {
+ if( eCurFontStrikeout != STRIKEOUT_NONE )
+ {
+ if( !sTextDecoration.isEmpty() )
+ sTextDecoration += " ";
+ sTextDecoration += "line-through";
+ }
+ bIsDecorationChanged = true;
+ }
+
+ if( !sTextDecoration.isEmpty() )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTextDecoration, sTextDecoration );
+ }
+ else if( bIsDecorationChanged )
+ {
+ sTextDecoration = "none";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTextDecoration, sTextDecoration );
+ }
+ }
+
+ if( bIsTextContainer )
+ maParentFont = maCurrentFont;
+}
+
+
+void SVGTextWriter::implSetFontFamily()
+{
+ const OUString& rsFontName = maCurrentFont.GetFamilyName();
+ OUString sFontFamily( rsFontName.getToken( 0, ';' ) );
+ FontPitch ePitch = maCurrentFont.GetPitch();
+ if( ePitch == PITCH_FIXED )
+ {
+ sFontFamily += ", monospace";
+ }
+ else
+ {
+ FontFamily eFamily = maCurrentFont.GetFamilyType();
+ if( eFamily == FAMILY_ROMAN )
+ sFontFamily += ", serif";
+ else if( eFamily == FAMILY_SWISS )
+ sFontFamily += ", sans-serif";
+ }
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrFontFamily, sFontFamily );
+}
+
+
+void SVGTextWriter::createParagraphEnumeration()
+{
+ if( mrTextShape.is() )
+ {
+ msShapeId = implGetValidIDFromInterface( Reference<XInterface>(mrTextShape, UNO_QUERY) );
+
+ Reference< XEnumerationAccess > xEnumerationAccess( mrTextShape, UNO_QUERY_THROW );
+ Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_SET_THROW );
+ if( xEnumeration.is() )
+ {
+ mrParagraphEnumeration.set( xEnumeration );
+ }
+ else
+ {
+ OSL_FAIL( "SVGTextWriter::createParagraphEnumeration: no valid xEnumeration interface found." );
+ }
+ }
+ else
+ {
+ OSL_FAIL( "SVGTextWriter::createParagraphEnumeration: no valid XText interface found." );
+ }
+}
+
+
+bool SVGTextWriter::nextParagraph()
+{
+ mrTextPortionEnumeration.clear();
+ mrCurrentTextParagraph.clear();
+ mbIsNewListItem = false;
+ mbIsListLevelStyleImage = false;
+
+ if( !mrParagraphEnumeration || !mrParagraphEnumeration->hasMoreElements() )
+ return false;
+
+ Reference < XTextContent > xTextContent( mrParagraphEnumeration->nextElement(), UNO_QUERY_THROW );
+ if( xTextContent.is() )
+ {
+ Reference< XServiceInfo > xServiceInfo( xTextContent, UNO_QUERY_THROW );
+#if OSL_DEBUG_LEVEL > 0
+ OUString sInfo;
+#endif
+ if( xServiceInfo->supportsService( "com.sun.star.text.Paragraph" ) )
+ {
+ mrCurrentTextParagraph.set( xTextContent );
+ Reference< XPropertySet > xPropSet( xTextContent, UNO_QUERY_THROW );
+ Reference< XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+ if( xPropSetInfo->hasPropertyByName( "NumberingLevel" ) )
+ {
+ sal_Int16 nListLevel = 0;
+ if( xPropSet->getPropertyValue( "NumberingLevel" ) >>= nListLevel )
+ {
+ mbIsNewListItem = true;
+#if OSL_DEBUG_LEVEL > 0
+ sInfo = "NumberingLevel: " + OUString::number( nListLevel );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "style", sInfo );
+#endif
+ Reference< XIndexReplace > xNumRules;
+ if( xPropSetInfo->hasPropertyByName( "NumberingRules" ) )
+ {
+ xPropSet->getPropertyValue( "NumberingRules" ) >>= xNumRules;
+ }
+ if( xNumRules.is() && ( nListLevel < xNumRules->getCount() ) )
+ {
+ bool bIsNumbered = true;
+ OUString sNumberingIsNumber("NumberingIsNumber");
+ if( xPropSetInfo->hasPropertyByName( sNumberingIsNumber ) )
+ {
+ if( !(xPropSet->getPropertyValue( sNumberingIsNumber ) >>= bIsNumbered ) )
+ {
+ OSL_FAIL( "numbered paragraph without number info" );
+ bIsNumbered = false;
+ }
+#if OSL_DEBUG_LEVEL > 0
+ if( bIsNumbered )
+ {
+ sInfo = "true";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "is-numbered", sInfo );
+ }
+#endif
+ }
+ mbIsNewListItem = bIsNumbered;
+
+ if( bIsNumbered )
+ {
+ Sequence<PropertyValue> aProps;
+ if( xNumRules->getByIndex( nListLevel ) >>= aProps )
+ {
+ sal_Int16 eType = NumberingType::CHAR_SPECIAL;
+ sal_Unicode cBullet = 0xf095;
+ const sal_Int32 nCount = aProps.getLength();
+ const PropertyValue* pPropArray = aProps.getConstArray();
+ for( sal_Int32 i = 0; i < nCount; ++i )
+ {
+ const PropertyValue& rProp = pPropArray[i];
+ if( rProp.Name == "NumberingType" )
+ {
+ rProp.Value >>= eType;
+ }
+ else if( rProp.Name == "BulletChar" )
+ {
+ OUString sValue;
+ rProp.Value >>= sValue;
+ if( !sValue.isEmpty() )
+ {
+ cBullet = sValue[0];
+ }
+ }
+ }
+ meNumberingType = eType;
+ mbIsListLevelStyleImage = ( NumberingType::BITMAP == meNumberingType );
+ if( NumberingType::CHAR_SPECIAL == meNumberingType )
+ {
+ if( cBullet )
+ {
+ if( cBullet < ' ' )
+ {
+ cBullet = 0xF000 + 149;
+ }
+ mcBulletChar = cBullet;
+#if OSL_DEBUG_LEVEL > 0
+ sInfo = OUString::number( static_cast<sal_Int32>(cBullet) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "bullet-char", sInfo );
+#endif
+ }
+
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ Reference< XEnumerationAccess > xEnumerationAccess( xTextContent, UNO_QUERY_THROW );
+ Reference< XEnumeration > xEnumeration( xEnumerationAccess->createEnumeration(), UNO_SET_THROW );
+ if( xEnumeration.is() && xEnumeration->hasMoreElements() )
+ {
+ mrTextPortionEnumeration.set( xEnumeration );
+ }
+#if OSL_DEBUG_LEVEL > 0
+ sInfo = "Paragraph";
+#endif
+ }
+ else if( xServiceInfo->supportsService( "com.sun.star.text.Table" ) )
+ {
+ OSL_FAIL( "SVGTextWriter::nextParagraph: text tables are not handled." );
+#if OSL_DEBUG_LEVEL > 0
+ sInfo = "Table";
+#endif
+ }
+ else
+ {
+ OSL_FAIL( "SVGTextWriter::nextParagraph: Unknown text content." );
+ return false;
+ }
+#if OSL_DEBUG_LEVEL > 0
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", sInfo );
+ SvXMLElementExport aParaElem( mrExport, XML_NAMESPACE_NONE, "desc", mbIWS, mbIWS );
+#endif
+ }
+ else
+ {
+ OSL_FAIL( "SVGTextWriter::nextParagraph: no XServiceInfo interface available for text content." );
+ return false;
+ }
+
+ const OUString& rParagraphId = implGetValidIDFromInterface( Reference<XInterface>(xTextContent, UNO_QUERY) );
+ if( !rParagraphId.isEmpty() )
+ {
+ // if there is id for empty paragraph we need to create a empty text paragraph
+ Reference < XTextRange > xRange( xTextContent, UNO_QUERY_THROW );
+ if ( xRange.is() && xRange->getString().isEmpty() )
+ {
+ endTextParagraph();
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextParagraph" );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId );
+ mpTextParagraphElem.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ));
+ }
+ else
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rParagraphId );
+ }
+ }
+ return true;
+}
+
+
+bool SVGTextWriter::nextTextPortion()
+{
+ mrCurrentTextPortion.clear();
+ mbIsURLField = false;
+ if( !mrTextPortionEnumeration || !mrTextPortionEnumeration->hasMoreElements() )
+ return false;
+
+ mbIsPlaceholderShape = false;
+ Reference< XPropertySet > xPortionPropSet( mrTextPortionEnumeration->nextElement(), UNO_QUERY );
+ Reference< XPropertySetInfo > xPortionPropInfo( xPortionPropSet->getPropertySetInfo() );
+ Reference < XTextRange > xPortionTextRange( xPortionPropSet, UNO_QUERY);
+ if( !xPortionPropSet || !xPortionPropInfo
+ || !xPortionPropInfo->hasPropertyByName( "TextPortionType" ) )
+ return true;
+
+#if OSL_DEBUG_LEVEL > 0
+ OUString sInfo;
+ OUString sPortionType;
+ if( xPortionPropSet->getPropertyValue( "TextPortionType" ) >>= sPortionType )
+ {
+ sInfo = "type: " + sPortionType + "; ";
+ }
+#endif
+ msPageCount = "";
+ msDateTimeType = "";
+ msTextFieldType = "";
+ if( xPortionTextRange.is() )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ sInfo += "content: " + xPortionTextRange->getString() + "; ";
+#endif
+ mrCurrentTextPortion.set( xPortionTextRange );
+
+ Reference < XPropertySet > xRangePropSet( xPortionTextRange, UNO_QUERY );
+ if( xRangePropSet.is() && xRangePropSet->getPropertySetInfo()->hasPropertyByName( "TextField" ) )
+ {
+ Reference < XTextField > xTextField( xRangePropSet->getPropertyValue( "TextField" ), UNO_QUERY );
+ if( xTextField.is() )
+ {
+ static const OUStringLiteral sServicePrefix(u"com.sun.star.text.textfield.");
+ static const OUStringLiteral sPresentationServicePrefix(u"com.sun.star.presentation.TextField.");
+
+ Reference< XServiceInfo > xService( xTextField, UNO_QUERY );
+ const Sequence< OUString > aServices = xService->getSupportedServiceNames();
+
+ const OUString* pNames = aServices.getConstArray();
+ sal_Int32 nCount = aServices.getLength();
+
+ OUString sFieldName; // service name postfix of current field
+
+ // search for TextField service name
+ while( nCount-- )
+ {
+ if ( pNames->matchIgnoreAsciiCase( sServicePrefix ) )
+ {
+ // TextField found => postfix is field type!
+ sFieldName = pNames->copy( sServicePrefix.getLength() );
+ break;
+ }
+ else if( pNames->startsWith( sPresentationServicePrefix ) )
+ {
+ // TextField found => postfix is field type!
+ sFieldName = pNames->copy( sPresentationServicePrefix.getLength() );
+ break;
+ }
+
+ ++pNames;
+ }
+
+ msTextFieldType = sFieldName;
+#if OSL_DEBUG_LEVEL > 0
+ sInfo += "text field type: " + sFieldName + "; content: " + xTextField->getPresentation( /* show command: */ false ) + "; ";
+#endif
+ // This case handle Date or Time text field inserted by the user
+ // on both page/master page. It doesn't handle the standard Date/Time field.
+ if( sFieldName == "DateTime" )
+ {
+ Reference<XPropertySet> xTextFieldPropSet(xTextField, UNO_QUERY);
+ if( xTextFieldPropSet.is() )
+ {
+ Reference<XPropertySetInfo> xPropSetInfo = xTextFieldPropSet->getPropertySetInfo();
+ if( xPropSetInfo.is() )
+ {
+ // The standard Date/Time field has no property.
+ // Trying to get a property value on such field would cause a runtime exception.
+ // So the hasPropertyByName check is needed.
+ bool bIsFixed = true;
+ if( xPropSetInfo->hasPropertyByName("IsFixed") && ( ( xTextFieldPropSet->getPropertyValue( "IsFixed" ) ) >>= bIsFixed ) && !bIsFixed )
+ {
+ bool bIsDate = true;
+ if( xPropSetInfo->hasPropertyByName("IsDate") && ( ( xTextFieldPropSet->getPropertyValue( "IsDate" ) ) >>= bIsDate ) )
+ {
+ msDateTimeType = OUString::createFromAscii( bIsDate ? "<date>" : "<time>" );
+ }
+ }
+ }
+ }
+ }
+ if( sFieldName == "DateTime" || sFieldName == "Header"
+ || sFieldName == "Footer" || sFieldName == "PageNumber"
+ || sFieldName == "PageName" )
+ {
+ mbIsPlaceholderShape = true;
+ }
+ else if (sFieldName == "PageCount")
+ {
+ msPageCount = xTextField->getPresentation( /* show command: */ false );
+ }
+ else
+ {
+ mbIsURLField = sFieldName == "URL";
+
+ if( mbIsURLField )
+ {
+ Reference<XPropertySet> xTextFieldPropSet(xTextField, UNO_QUERY);
+ if( xTextFieldPropSet.is() )
+ {
+ OUString sURL;
+ if( ( xTextFieldPropSet->getPropertyValue( sFieldName ) ) >>= sURL )
+ {
+#if OSL_DEBUG_LEVEL > 0
+ sInfo += "url: " + mrExport.GetRelativeReference( sURL );
+#endif
+ msUrl = mrExport.GetRelativeReference( sURL );
+ if( !msUrl.isEmpty() )
+ {
+ implRegisterInterface( xPortionTextRange );
+
+ const OUString& rTextPortionId = implGetValidIDFromInterface( Reference<XInterface>(xPortionTextRange, UNO_QUERY) );
+ if( !rTextPortionId.isEmpty() )
+ {
+ msHyperlinkIdList += rTextPortionId + " ";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+#if OSL_DEBUG_LEVEL > 0
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextPortion" );
+ SvXMLElementExport aPortionElem( mrExport, XML_NAMESPACE_NONE, "desc", mbIWS, mbIWS );
+ mrExport.GetDocHandler()->characters( sInfo );
+#endif
+ return true;
+}
+
+
+void SVGTextWriter::startTextShape()
+{
+ if( mpTextShapeElem )
+ {
+ OSL_FAIL( "SVGTextWriter::startTextShape: text shape already defined." );
+ }
+
+ {
+ mbIsTextShapeStarted = true;
+ maParentFont = vcl::Font();
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "SVGTextShape" );
+
+ // if text is rotated, set transform matrix at text element
+ const vcl::Font& rFont = mpVDev->GetFont();
+ if( rFont.GetOrientation() )
+ {
+ Point aRot( maTextPos );
+ OUString aTransform = "rotate(" +
+ OUString::number( rFont.GetOrientation().get() * -0.1 ) + " " +
+ OUString::number( aRot.X() ) + " " +
+ OUString::number( aRot.Y() ) + ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
+ }
+
+ mpTextShapeElem.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemText, true, mbIWS ));
+ startTextParagraph();
+ }
+}
+
+
+void SVGTextWriter::endTextShape()
+{
+ endTextParagraph();
+ mrTextShape.clear();
+ mrParagraphEnumeration.clear();
+ mrCurrentTextParagraph.clear();
+ mpTextShapeElem.reset();
+ maTextOpacity.clear();
+ mbIsTextShapeStarted = false;
+ // these need to be invoked after the <text> element has been closed
+ implExportHyperlinkIds();
+ implWriteBulletChars();
+ implWriteEmbeddedBitmaps();
+
+}
+
+
+void SVGTextWriter::startTextParagraph()
+{
+ endTextParagraph();
+ nextParagraph();
+ if( mbIsNewListItem )
+ {
+ OUString sNumberingType;
+ switch( meNumberingType )
+ {
+ case NumberingType::CHAR_SPECIAL:
+ sNumberingType = "bullet-style";
+ break;
+ case NumberingType::BITMAP:
+ sNumberingType = "image-style";
+ break;
+ default:
+ sNumberingType = "number-style";
+ break;
+ }
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "ooo:numbering-type", sNumberingType );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "ListItem" );
+ }
+ else
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextParagraph" );
+ }
+ maParentFont = vcl::Font();
+ addFontAttributes( /* isTexTContainer: */ true );
+ mpTextParagraphElem.reset(new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ));
+
+ if( !mbIsListLevelStyleImage )
+ {
+ mbPositioningNeeded = true;
+ }
+}
+
+
+void SVGTextWriter::endTextParagraph()
+{
+ mrCurrentTextPortion.clear();
+ endTextPosition();
+ mbIsNewListItem = false;
+ mbIsListLevelStyleImage = false;
+ mbPositioningNeeded = false;
+ mpTextParagraphElem.reset();
+}
+
+
+void SVGTextWriter::startTextPosition( bool bExportX, bool bExportY )
+{
+ endTextPosition();
+ mnTextWidth = 0;
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "TextPosition" );
+ if( bExportX )
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( maTextPos.X() ) );
+ if( bExportY )
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( maTextPos.Y() ) );
+
+ mpTextPositionElem.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS ) );
+}
+
+
+void SVGTextWriter::endTextPosition()
+{
+ mpTextPositionElem.reset();
+}
+
+bool SVGTextWriter::hasTextOpacity() const { return !maTextOpacity.isEmpty(); }
+
+void SVGTextWriter::implExportHyperlinkIds()
+{
+ if( !msHyperlinkIdList.isEmpty() )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "HyperlinkIdList" );
+ SvXMLElementExport aDescElem( mrExport, XML_NAMESPACE_NONE, "desc", true, false );
+ mrExport.GetDocHandler()->characters( msHyperlinkIdList.trim() );
+ msHyperlinkIdList.clear();
+ }
+}
+
+
+void SVGTextWriter::implWriteBulletChars()
+{
+ if( maBulletListItemMap.empty() )
+ return;
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "BulletChars" );
+ SvXMLElementExport aGroupElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
+
+ OUString sId, sPosition, sScaling, sRefId;
+ for (auto const& bulletListItem : maBulletListItemMap)
+ {
+ // <g id="?" > (used by animations)
+ // As id we use the id of the text portion placeholder with prefix
+ // bullet-char-*
+ sId = "bullet-char-" + bulletListItem.first;
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "BulletChar" );
+ SvXMLElementExport aBulletCharElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
+
+ // <g transform="translate(x,y)" >
+ {
+ const BulletListItemInfo& rInfo = bulletListItem.second;
+
+ // Add positioning attribute through a translation
+ sPosition = "translate(" +
+ OUString::number( rInfo.aPos.X() ) +
+ "," + OUString::number( rInfo.aPos.Y() ) + ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "transform", sPosition );
+
+ mrAttributeWriter.AddPaintAttr( COL_TRANSPARENT, rInfo.aColor );
+
+ SvXMLElementExport aPositioningElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
+
+ if (mrExport.IsEmbeddedBulletGlyph(rInfo.cBulletChar))
+ {
+ // <use transform="scale(font-size)" xlink:ref="/" >
+ // Add size attribute through a scaling
+ sScaling = "scale(" + OUString::number( rInfo.aFont.GetFontHeight() ) +
+ "," + OUString::number( rInfo.aFont.GetFontHeight() )+ ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "transform", sScaling );
+
+ // Add ref attribute
+ sRefId = "#bullet-char-template-" +
+ OUString::number( rInfo.cBulletChar );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
+
+ SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", true, true );
+ }
+ else
+ {
+ // <path d="...">
+ tools::PolyPolygon aPolyPolygon;
+ OUString aStr(rInfo.cBulletChar);
+ mpVDev->Push(vcl::PushFlags::FONT);
+ mpVDev->SetFont(rInfo.aFont);
+ if (mpVDev->GetTextOutline(aPolyPolygon, aStr))
+ {
+ OUString aPathString(SVGActionWriter::GetPathString(aPolyPolygon, false));
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "d", aPathString);
+ SvXMLElementExport aPath(mrExport, XML_NAMESPACE_NONE, "path", true, true);
+ }
+ mpVDev->Pop();
+ }
+ } // close aPositioningElem
+ }
+
+ // clear the map
+ maBulletListItemMap.clear();
+}
+
+
+template< typename MetaBitmapActionType >
+void SVGTextWriter::writeBitmapPlaceholder( const MetaBitmapActionType* pAction )
+{
+ // text position element
+ const Point& rPos = pAction->GetPoint();
+ implMap( rPos, maTextPos );
+ startTextPosition();
+ mbPositioningNeeded = true;
+ if( mbIsNewListItem )
+ {
+ mbIsNewListItem = false;
+ mbIsListLevelStyleImage = false;
+ }
+
+ // bitmap placeholder element
+ BitmapChecksum nId = SVGActionWriter::GetChecksum( pAction );
+ OUString sId = "bitmap-placeholder(" + msShapeId + "." +
+ OUString::number( nId ) + ")";
+
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "BitmapPlaceholder" );
+ SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
+ }
+ endTextPosition();
+}
+
+
+void SVGTextWriter::implWriteEmbeddedBitmaps()
+{
+ if( !(mpTextEmbeddedBitmapMtf && mpTextEmbeddedBitmapMtf->GetActionSize()) )
+ return;
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "EmbeddedBitmaps" );
+ SvXMLElementExport aEmbBitmapGroupElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
+
+ const GDIMetaFile& rMtf = *mpTextEmbeddedBitmapMtf;
+
+ BitmapChecksum nId, nChecksum = 0;
+ Point aPt;
+ Size aSz;
+ size_t nCount = rMtf.GetActionSize();
+ for( size_t nCurAction = 0; nCurAction < nCount; nCurAction++ )
+ {
+
+ const MetaAction* pAction = rMtf.GetAction( nCurAction );
+ const MetaActionType nType = pAction->GetType();
+
+ switch( nType )
+ {
+ case MetaActionType::BMPSCALE:
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+ // The conversion to BitmapEx is needed since at the point
+ // where the bitmap is actually exported a Bitmap object is
+ // converted to BitmapEx before computing the checksum used
+ // to generate the <image> element id.
+ // (See GetBitmapChecksum in svgexport.cxx)
+ nChecksum = BitmapEx( pA->GetBitmap() ).GetChecksum();
+ aPt = pA->GetPoint();
+ aSz = pA->GetSize();
+ }
+ break;
+ case MetaActionType::BMPEXSCALE:
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+ nChecksum = pA->GetBitmapEx().GetChecksum();
+ aPt = pA->GetPoint();
+ aSz = pA->GetSize();
+ }
+ break;
+ default: break;
+ }
+
+ // <g id="?" > (used by animations)
+ {
+ // embedded bitmap id
+ nId = SVGActionWriter::GetChecksum( pAction );
+ OUString sId = "embedded-bitmap(" + msShapeId + "." + OUString::number( nId ) + ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "EmbeddedBitmap" );
+
+ SvXMLElementExport aEmbBitmapElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
+
+ // <use x="?" y="?" xlink:ref="?" >
+ {
+ // referenced bitmap template
+ OUString sRefId = "#bitmap(" + OUString::number( nChecksum ) + ")";
+
+ Point aPoint;
+ Size aSize;
+ implMap( aPt, aPoint );
+ implMap( aSz, aSize );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aPoint.X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPoint.Y() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
+
+ SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", true, true );
+ }
+ } // close aEmbBitmapElem
+ }
+}
+
+
+void SVGTextWriter::writeTextPortion( const Point& rPos,
+ const OUString& rText )
+{
+ if( rText.isEmpty() )
+ return;
+
+ bool bStandAloneTextPortion = false;
+ if( !isTextShapeStarted() )
+ {
+ bStandAloneTextPortion = true;
+ startTextShape();
+ }
+
+ mbLineBreak = false;
+
+ if( !mbIsNewListItem || mbIsListLevelStyleImage )
+ {
+ bool bNotSync = true;
+ OUString sContent;
+ sal_Int32 nStartPos;
+ while( bNotSync )
+ {
+ if( mnLeftTextPortionLength <= 0 || !mrCurrentTextPortion.is() )
+ {
+ if( !nextTextPortion() )
+ break;
+ else
+ {
+ sContent = mrCurrentTextPortion->getString();
+ if( mbIsURLField && sContent.isEmpty() )
+ {
+ Reference < XPropertySet > xPropSet( mrCurrentTextPortion, UNO_QUERY );
+ Reference < XTextField > xTextField( xPropSet->getPropertyValue( "TextField" ), UNO_QUERY );
+ sContent = xTextField->getPresentation( /* show command: */ false );
+ if( sContent.isEmpty() )
+ OSL_FAIL( "SVGTextWriter::writeTextPortion: content of URL TextField is empty." );
+ }
+ mnLeftTextPortionLength = sContent.getLength();
+ }
+ }
+ else
+ {
+ sContent = mrCurrentTextPortion->getString();
+ }
+
+ nStartPos = sContent.getLength() - mnLeftTextPortionLength;
+ if( nStartPos < 0 ) nStartPos = 0;
+ mnLeftTextPortionLength -= rText.getLength();
+
+ if( sContent.isEmpty() )
+ continue;
+ if( sContent == "\n" )
+ mbLineBreak = true;
+ else if (sContent == "\t")
+ {
+ // Need to emit position for the next text portion after a tab, otherwise the tab
+ // would appear as if it has 0 width.
+ mbPositioningNeeded = true;
+ }
+ if( sContent.match( rText, nStartPos ) )
+ bNotSync = false;
+ }
+ }
+
+ assert(mpVDev); //invalid virtual device
+
+#if 0
+ const FontMetric aMetric( mpVDev->GetFontMetric() );
+
+ bool bTextSpecial = aMetric.IsShadow() || aMetric.IsOutline() || (aMetric.GetRelief() != FontRelief::NONE);
+
+ if( true || !bTextSpecial )
+ {
+ implWriteTextPortion( rPos, rText, mpVDev->GetTextColor() );
+ }
+ else
+ {
+ // to be implemented
+ }
+#else
+ implWriteTextPortion( rPos, rText, mpVDev->GetTextColor() );
+#endif
+
+ if( bStandAloneTextPortion )
+ {
+ endTextShape();
+ }
+}
+
+
+void SVGTextWriter::implWriteTextPortion( const Point& rPos,
+ const OUString& rText,
+ Color aTextColor )
+{
+ Point aPos;
+ Point aBaseLinePos( rPos );
+ const FontMetric aMetric( mpVDev->GetFontMetric() );
+ const vcl::Font& rFont = mpVDev->GetFont();
+
+ if( rFont.GetAlignment() == ALIGN_TOP )
+ aBaseLinePos.AdjustY(aMetric.GetAscent() );
+ else if( rFont.GetAlignment() == ALIGN_BOTTOM )
+ aBaseLinePos.AdjustY( -(aMetric.GetDescent()) );
+
+ implMap( rPos, aPos );
+
+ if( mbPositioningNeeded )
+ {
+ mbPositioningNeeded = false;
+ maTextPos.setX( aPos.X() );
+ maTextPos.setY( aPos.Y() );
+ startTextPosition();
+ }
+ else if( maTextPos.Y() != aPos.Y() )
+ {
+ // In case the text position moved backward we could have a line break
+ // so we end the current line and start a new one.
+ if( mbLineBreak || ( ( maTextPos.X() + mnTextWidth ) > aPos.X() ) )
+ {
+ mbLineBreak = false;
+ maTextPos.setX( aPos.X() );
+ maTextPos.setY( aPos.Y() );
+ startTextPosition();
+ }
+ else // superscript, subscript, list item numbering
+ {
+ maTextPos.setY( aPos.Y() );
+ startTextPosition( false /* do not export x attribute */ );
+ }
+ }
+ // we are dealing with a bullet, so set up this for the next text portion
+ if( mbIsNewListItem )
+ {
+ mbIsNewListItem = false;
+ mbPositioningNeeded = true;
+
+ if( meNumberingType == NumberingType::CHAR_SPECIAL )
+ {
+ // Create an id for the current text portion
+ implRegisterInterface( mrCurrentTextParagraph );
+
+ // Add the needed info to the BulletListItemMap
+ OUString sId = implGetValidIDFromInterface( Reference<XInterface>(mrCurrentTextParagraph, UNO_QUERY) );
+ if( !sId.isEmpty() )
+ {
+ sId += ".bp";
+ BulletListItemInfo& aBulletListItemInfo = maBulletListItemMap[ sId ];
+ aBulletListItemInfo.aFont = rFont;
+ aBulletListItemInfo.aColor = aTextColor;
+ aBulletListItemInfo.aPos = maTextPos;
+ aBulletListItemInfo.cBulletChar = mcBulletChar;
+
+ // Make this text portion a bullet placeholder
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", sId );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "BulletPlaceholder" );
+ SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
+ return;
+ }
+ }
+ }
+
+ const OUString& rTextPortionId = implGetValidIDFromInterface( Reference<XInterface>(mrCurrentTextPortion, UNO_QUERY) );
+ if( !rTextPortionId.isEmpty() )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "id", rTextPortionId );
+ }
+
+ if( mbIsPlaceholderShape )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "PlaceholderText" );
+ }
+
+ addFontAttributes( /* isTexTContainer: */ false );
+
+ if (!maTextOpacity.isEmpty())
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, "fill-opacity", maTextOpacity);
+ }
+
+ mrAttributeWriter.AddPaintAttr( COL_TRANSPARENT, aTextColor );
+
+ // <a> tag for link should be the innermost tag, inside <tspan>
+ if( !mbIsPlaceholderShape && mbIsURLField && !msUrl.isEmpty() )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "UrlField" );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, msUrl );
+
+ SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, msUrl );
+ {
+ SvXMLElementExport aSVGAElem( mrExport, XML_NAMESPACE_NONE, "a", mbIWS, mbIWS );
+ mrExport.GetDocHandler()->characters( rText );
+ }
+ }
+ else if ( !msPageCount.isEmpty() )
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "PageCount" );
+ SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
+ mrExport.GetDocHandler()->characters( msPageCount );
+ }
+ // This case handle Date or Time text field inserted by the user
+ // on both page/master page. It doesn't handle the standard Date/Time field.
+ else if ( !msDateTimeType.isEmpty() )
+ {
+ SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
+ mrExport.GetDocHandler()->characters( msDateTimeType );
+ }
+ else if( mbIsPlaceholderShape && rText.startsWith("<") && rText.endsWith(">") )
+ {
+ OUString sContent;
+ if( msTextFieldType == "PageNumber" )
+ sContent = "<number>";
+ else if( msTextFieldType == "PageName" )
+ sContent = "<slide-name>";
+ else
+ sContent = rText;
+
+ SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
+ mrExport.GetDocHandler()->characters( sContent );
+ }
+ else
+ {
+ // Without the following attribute Google Chrome does not render leading spaces
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "style", "white-space: pre" );
+
+ SvXMLElementExport aSVGTspanElem( mrExport, XML_NAMESPACE_NONE, aXMLElemTspan, mbIWS, mbIWS );
+ mrExport.GetDocHandler()->characters( rText );
+ }
+
+ mnTextWidth += mpVDev->GetTextWidth( rText );
+}
+
+
+SVGActionWriter::SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport ) :
+ mnCurGradientId( 1 ),
+ mnCurMaskId( 1 ),
+ mnCurPatternId( 1 ),
+ mnCurClipPathId( 1 ),
+ mrExport( rExport ),
+ maContextHandler(),
+ mrCurrentState( maContextHandler.getCurrentState() ),
+ maAttributeWriter( rExport, rFontExport, mrCurrentState ),
+ maTextWriter(rExport, maAttributeWriter, *this),
+ mpVDev(VclPtr<VirtualDevice>::Create()),
+ mbClipAttrChanged( false ),
+ mbIsPlaceholderShape( false ),
+ mpEmbeddedBitmapsMap( nullptr ),
+ mbIsPreview( false )
+{
+ mpVDev->EnableOutput( false );
+ maTargetMapMode = MapMode(MapUnit::Map100thMM);
+ maTextWriter.setVirtualDevice( mpVDev, maTargetMapMode );
+}
+
+
+SVGActionWriter::~SVGActionWriter()
+{
+ mpVDev.disposeAndClear();
+}
+
+
+tools::Long SVGActionWriter::ImplMap( sal_Int32 nVal ) const
+{
+ Size aSz( nVal, nVal );
+
+ return ImplMap( aSz, aSz ).Width();
+}
+
+
+Point& SVGActionWriter::ImplMap( const Point& rPt, Point& rDstPt ) const
+{
+ rDstPt = OutputDevice::LogicToLogic( rPt, mpVDev->GetMapMode(), maTargetMapMode );
+ return rDstPt;
+}
+
+
+Size& SVGActionWriter::ImplMap( const Size& rSz, Size& rDstSz ) const
+{
+ rDstSz = OutputDevice::LogicToLogic( rSz, mpVDev->GetMapMode(), maTargetMapMode );
+ return rDstSz;
+}
+
+
+void SVGActionWriter::ImplMap( const tools::Rectangle& rRect, tools::Rectangle& rDstRect ) const
+{
+ Point aTL( rRect.TopLeft() );
+ Size aSz( rRect.GetSize() );
+
+ rDstRect = tools::Rectangle( ImplMap( aTL, aTL ), ImplMap( aSz, aSz ) );
+}
+
+
+tools::Polygon& SVGActionWriter::ImplMap( const tools::Polygon& rPoly, tools::Polygon& rDstPoly ) const
+{
+ rDstPoly = tools::Polygon( rPoly.GetSize() );
+
+ for( sal_uInt16 i = 0, nSize = rPoly.GetSize(); i < nSize; ++i )
+ {
+ ImplMap( rPoly[ i ], rDstPoly[ i ] );
+ rDstPoly.SetFlags( i, rPoly.GetFlags( i ) );
+ }
+
+ return rDstPoly;
+}
+
+
+tools::PolyPolygon& SVGActionWriter::ImplMap( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rDstPolyPoly ) const
+{
+ tools::Polygon aPoly;
+
+ rDstPolyPoly = tools::PolyPolygon();
+
+ for( sal_uInt16 i = 0, nCount = rPolyPoly.Count(); i < nCount; ++i )
+ {
+ rDstPolyPoly.Insert( ImplMap( rPolyPoly[ i ], aPoly ) );
+ }
+
+ return rDstPolyPoly;
+}
+
+
+OUString SVGActionWriter::GetPathString( const tools::PolyPolygon& rPolyPoly, bool bLine )
+{
+ OUStringBuffer aPathData;
+ static const OUStringLiteral aBlank( u" " );
+ static const OUStringLiteral aComma( u"," );
+ Point aPolyPoint;
+
+ for( tools::Long i = 0, nCount = rPolyPoly.Count(); i < nCount; i++ )
+ {
+ const tools::Polygon& rPoly = rPolyPoly[ static_cast<sal_uInt16>(i) ];
+ sal_uInt16 n = 1, nSize = rPoly.GetSize();
+
+ if( nSize > 1 )
+ {
+ aPolyPoint = rPoly[ 0 ];
+ aPathData.append("M " +
+ OUString::number( aPolyPoint.X() ) +
+ aComma +
+ OUString::number( aPolyPoint.Y() ));
+
+ char nCurrentMode = 0;
+ const bool bClose(!bLine || rPoly[0] == rPoly[nSize - 1]);
+ while( n < nSize )
+ {
+ aPathData.append(aBlank);
+
+ if ( ( rPoly.GetFlags( n ) == PolyFlags::Control ) && ( ( n + 2 ) < nSize ) )
+ {
+ if ( nCurrentMode != 'C' )
+ {
+ nCurrentMode = 'C';
+ aPathData.append("C ");
+ }
+ for ( int j = 0; j < 3; j++ )
+ {
+ if ( j )
+ aPathData.append(aBlank);
+
+ aPolyPoint = rPoly[ n++ ];
+ aPathData.append( OUString::number(aPolyPoint.X()) +
+ aComma +
+ OUString::number( aPolyPoint.Y() ) );
+ }
+ }
+ else
+ {
+ if ( nCurrentMode != 'L' )
+ {
+ nCurrentMode = 'L';
+ aPathData.append("L ");
+ }
+
+ aPolyPoint = rPoly[ n++ ];
+ aPathData.append( OUString::number(aPolyPoint.X()) +
+ aComma +
+ OUString::number(aPolyPoint.Y()) );
+ }
+ }
+
+ if(bClose)
+ aPathData.append(" Z");
+
+ if( i < ( nCount - 1 ) )
+ aPathData.append(aBlank);
+ }
+ }
+
+ return aPathData.makeStringAndClear();
+}
+
+BitmapChecksum SVGActionWriter::GetChecksum( const MetaAction* pAction )
+{
+ GDIMetaFile aMtf;
+ MetaAction* pA = const_cast<MetaAction*>(pAction);
+ aMtf.AddAction( pA );
+ return SvmWriter::GetChecksum( aMtf );
+}
+
+void SVGActionWriter::SetEmbeddedBitmapRefs( const MetaBitmapActionMap* pEmbeddedBitmapsMap )
+{
+ if (pEmbeddedBitmapsMap)
+ mpEmbeddedBitmapsMap = pEmbeddedBitmapsMap;
+ else
+ OSL_FAIL( "SVGActionWriter::SetEmbeddedBitmapRefs: passed pointer is null" );
+}
+
+void SVGActionWriter::ImplWriteLine( const Point& rPt1, const Point& rPt2,
+ const Color* pLineColor )
+{
+ Point aPt1, aPt2;
+
+ ImplMap( rPt1, aPt1 );
+ ImplMap( rPt2, aPt2 );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, OUString::number( aPt1.X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, OUString::number( aPt1.Y() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, OUString::number( aPt2.X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, OUString::number( aPt2.Y() ) );
+
+ if( pLineColor )
+ {
+ // !!! mrExport.AddAttribute( XML_NAMESPACE_NONE, ... )
+ OSL_FAIL( "SVGActionWriter::ImplWriteLine: Line color not implemented" );
+ }
+
+ {
+ SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, "line", true, true );
+ }
+}
+
+
+void SVGActionWriter::ImplWriteRect( const tools::Rectangle& rRect, tools::Long nRadX, tools::Long nRadY )
+{
+ tools::Rectangle aRect;
+
+ ImplMap( rRect, aRect );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aRect.Left() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aRect.Top() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, OUString::number( aRect.GetWidth() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, OUString::number( aRect.GetHeight() ) );
+
+ if( nRadX )
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, OUString::number( ImplMap( nRadX ) ) );
+
+ if( nRadY )
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, OUString::number( ImplMap( nRadY ) ) );
+
+ SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, "rect", true, true );
+}
+
+
+void SVGActionWriter::ImplWriteEllipse( const Point& rCenter, tools::Long nRadX, tools::Long nRadY )
+{
+ Point aCenter;
+
+ ImplMap( rCenter, aCenter );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCX, OUString::number( aCenter.X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrCY, OUString::number( aCenter.Y() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRX, OUString::number( ImplMap( nRadX ) ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrRY, OUString::number( ImplMap( nRadY ) ) );
+
+ {
+ SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, "ellipse", true, true );
+ }
+}
+
+
+void SVGActionWriter::ImplAddLineAttr( const LineInfo &rAttrs )
+{
+ if ( rAttrs.IsDefault() )
+ return;
+
+ sal_Int32 nStrokeWidth = ImplMap( rAttrs.GetWidth() );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStrokeWidth,
+ OUString::number( nStrokeWidth ) );
+ // support for LineJoint
+ switch(rAttrs.GetLineJoin())
+ {
+ case basegfx::B2DLineJoin::NONE:
+ case basegfx::B2DLineJoin::Miter:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "miter");
+ break;
+ }
+ case basegfx::B2DLineJoin::Bevel:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "bevel");
+ break;
+ }
+ case basegfx::B2DLineJoin::Round:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "round");
+ break;
+ }
+ }
+
+ // support for LineCap
+ switch(rAttrs.GetLineCap())
+ {
+ default: /* css::drawing::LineCap_BUTT */
+ {
+ // butt is Svg default, so no need to write until the exporter might write styles.
+ // If this happens, activate here
+ // mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "butt");
+ break;
+ }
+ case css::drawing::LineCap_ROUND:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "round");
+ break;
+ }
+ case css::drawing::LineCap_SQUARE:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "square");
+ break;
+ }
+ }
+
+}
+
+
+void SVGActionWriter::ImplWritePolyPolygon( const tools::PolyPolygon& rPolyPoly, bool bLineOnly,
+ bool bApplyMapping )
+{
+ tools::PolyPolygon aPolyPoly;
+
+ if( bApplyMapping )
+ ImplMap( rPolyPoly, aPolyPoly );
+ else
+ aPolyPoly = rPolyPoly;
+
+ // add path data attribute
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "d", GetPathString( aPolyPoly, bLineOnly ) );
+
+ {
+ // write polyline/polygon element
+ SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, "path", true, true );
+ }
+}
+
+
+void SVGActionWriter::ImplWriteShape( const SVGShapeDescriptor& rShape )
+{
+ tools::PolyPolygon aPolyPoly;
+
+ ImplMap( rShape.maShapePolyPoly, aPolyPoly );
+
+ const bool bLineOnly
+ = (rShape.maShapeFillColor == COL_TRANSPARENT) && (!rShape.mapShapeGradient);
+ tools::Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
+
+ maAttributeWriter.AddPaintAttr( rShape.maShapeLineColor, rShape.maShapeFillColor, &aBoundRect, rShape.mapShapeGradient.get() );
+
+ if( !rShape.maId.isEmpty() )
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, rShape.maId );
+
+ if( rShape.mnStrokeWidth )
+ {
+ sal_Int32 nStrokeWidth = ImplMap( rShape.mnStrokeWidth );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStrokeWidth, OUString::number( nStrokeWidth ) );
+ }
+
+ // support for LineJoin
+ switch(rShape.maLineJoin)
+ {
+ case basegfx::B2DLineJoin::NONE:
+ case basegfx::B2DLineJoin::Miter:
+ {
+ // miter is Svg default, so no need to write until the exporter might write styles.
+ // If this happens, activate here
+ // mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "miter");
+ break;
+ }
+ case basegfx::B2DLineJoin::Bevel:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "bevel");
+ break;
+ }
+ case basegfx::B2DLineJoin::Round:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinejoin, "round");
+ break;
+ }
+ }
+
+ // support for LineCap
+ switch(rShape.maLineCap)
+ {
+ default: /* css::drawing::LineCap_BUTT */
+ {
+ // butt is Svg default, so no need to write until the exporter might write styles.
+ // If this happens, activate here
+ // mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "butt");
+ break;
+ }
+ case css::drawing::LineCap_ROUND:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "round");
+ break;
+ }
+ case css::drawing::LineCap_SQUARE:
+ {
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStrokeLinecap, "square");
+ break;
+ }
+ }
+
+ if( !rShape.maDashArray.empty() )
+ {
+ OUStringBuffer aDashArrayStr;
+
+ for( size_t k = 0; k < rShape.maDashArray.size(); ++k )
+ {
+ const sal_Int32 nDash = ImplMap( FRound( rShape.maDashArray[ k ] ) );
+
+ if( k )
+ aDashArrayStr.append(",");
+
+ aDashArrayStr.append( nDash );
+ }
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "stroke-dasharray", aDashArrayStr.makeStringAndClear() );
+ }
+
+ ImplWritePolyPolygon( aPolyPoly, bLineOnly, false );
+}
+
+
+
+void SVGActionWriter::ImplCreateClipPathDef( const tools::PolyPolygon& rPolyPoly )
+{
+ OUString aClipPathId = aPrefixClipPathId + OUString::number( mnCurClipPathId++ );
+
+ SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
+
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aClipPathId );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "clipPathUnits", "userSpaceOnUse" );
+ SvXMLElementExport aElemClipPath( mrExport, XML_NAMESPACE_NONE, "clipPath", true, true );
+
+ ImplWritePolyPolygon(rPolyPoly, false);
+ }
+}
+
+void SVGActionWriter::ImplStartClipRegion(sal_Int32 nClipPathId)
+{
+ assert(!mpCurrentClipRegionElem);
+
+ if (nClipPathId == 0)
+ return;
+
+ OUString aUrl = OUString::Concat("url(#") + aPrefixClipPathId + OUString::number( nClipPathId ) + ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "clip-path", aUrl );
+ mpCurrentClipRegionElem.reset( new SvXMLElementExport( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true ) );
+}
+
+void SVGActionWriter::ImplEndClipRegion()
+{
+ if (mpCurrentClipRegionElem)
+ {
+ mpCurrentClipRegionElem.reset();
+ }
+}
+
+void SVGActionWriter::ImplWriteClipPath( const tools::PolyPolygon& rPolyPoly )
+{
+ ImplEndClipRegion();
+
+ if( rPolyPoly.Count() == 0 )
+ return;
+
+ ImplCreateClipPathDef(rPolyPoly);
+ mrCurrentState.nRegionClipPathId = mnCurClipPathId - 1;
+ ImplStartClipRegion( mrCurrentState.nRegionClipPathId );
+}
+
+void SVGActionWriter::ImplWritePattern( const tools::PolyPolygon& rPolyPoly,
+ const Hatch* pHatch,
+ const Gradient* pGradient,
+ sal_uInt32 nWriteFlags )
+{
+ if( !rPolyPoly.Count() )
+ return;
+
+ SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
+
+ OUString aPatternId = "pattern" + OUString::number( mnCurPatternId++ );
+
+ {
+ SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aPatternId );
+
+ tools::Rectangle aRect;
+ ImplMap( rPolyPoly.GetBoundRect(), aRect );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aRect.Left() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aRect.Top() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, OUString::number( aRect.GetWidth() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, OUString::number( aRect.GetHeight() ) );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "patternUnits", OUString( "userSpaceOnUse") );
+
+ {
+ SvXMLElementExport aElemPattern( mrExport, XML_NAMESPACE_NONE, "pattern", true, true );
+
+ // The origin of a pattern is positioned at (aRect.Left(), aRect.Top()).
+ // So we need to adjust the pattern coordinate.
+ OUString aTransform = "translate(" +
+ OUString::number( -aRect.Left() ) +
+ "," + OUString::number( -aRect.Top() ) +
+ ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
+
+ {
+ SvXMLElementExport aElemG2( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
+
+ GDIMetaFile aTmpMtf;
+ if( pHatch )
+ {
+ mpVDev->AddHatchActions( rPolyPoly, *pHatch, aTmpMtf );
+ }
+ else if ( pGradient )
+ {
+ Gradient aGradient(*pGradient);
+ aGradient.AddGradientActions( rPolyPoly.GetBoundRect(), aTmpMtf );
+ }
+
+ ImplWriteActions( aTmpMtf, nWriteFlags, "" );
+ }
+ }
+ }
+
+ OUString aPatternStyle = "fill:url(#" + aPatternId + ")";
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aPatternStyle );
+ ImplWritePolyPolygon( rPolyPoly, false );
+}
+
+
+void SVGActionWriter::ImplWriteGradientEx( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient,
+ sal_uInt32 nWriteFlags)
+{
+ if ( rGradient.GetStyle() == GradientStyle::Linear ||
+ rGradient.GetStyle() == GradientStyle::Axial )
+ {
+ ImplWriteGradientLinear( rPolyPoly, rGradient );
+ }
+ else
+ {
+ ImplWritePattern( rPolyPoly, nullptr, &rGradient, nWriteFlags );
+ }
+}
+
+
+void SVGActionWriter::ImplWriteGradientLinear( const tools::PolyPolygon& rPolyPoly,
+ const Gradient& rGradient )
+{
+ if( !rPolyPoly.Count() )
+ return;
+
+ SvXMLElementExport aElemG( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true );
+
+ OUString aGradientId = "gradient" + OUString::number( mnCurGradientId++ );
+
+ {
+ SvXMLElementExport aElemDefs( mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrId, aGradientId );
+ {
+ tools::Rectangle aTmpRect, aRect;
+ Point aTmpCenter, aCenter;
+
+ rGradient.GetBoundRect( rPolyPoly.GetBoundRect(), aTmpRect, aTmpCenter );
+ ImplMap( aTmpRect, aRect );
+ ImplMap( aTmpCenter, aCenter );
+ const Degree10 nAngle = rGradient.GetAngle() % 3600_deg10;
+
+ tools::Polygon aPoly( 2 );
+ // Setting x value of a gradient vector to rotation center to
+ // place a gradient vector in a target polygon.
+ // This would help editing it in SVG editors like inkscape.
+ aPoly[ 0 ].setX( aCenter.X() );
+ aPoly[ 1 ].setX( aCenter.X() );
+ aPoly[ 0 ].setY( aRect.Top() );
+ aPoly[ 1 ].setY( aRect.Bottom() );
+ aPoly.Rotate( aCenter, nAngle );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX1, OUString::number( aPoly[ 0 ].X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY1, OUString::number( aPoly[ 0 ].Y() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX2, OUString::number( aPoly[ 1 ].X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY2, OUString::number( aPoly[ 1 ].Y() ) );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrGradientUnits,
+ OUString( "userSpaceOnUse" ) );
+ }
+
+ {
+ SvXMLElementExport aElemLinearGradient( mrExport, XML_NAMESPACE_NONE, aXMLElemLinearGradient, true, true );
+
+ const Color aStartColor = ImplGetColorWithIntensity( rGradient.GetStartColor(), rGradient.GetStartIntensity() );
+ const Color aEndColor = ImplGetColorWithIntensity( rGradient.GetEndColor(), rGradient.GetEndIntensity() );
+ double fBorderOffset = rGradient.GetBorder() / 100.0;
+ const sal_uInt16 nSteps = rGradient.GetSteps();
+ if( rGradient.GetStyle() == GradientStyle::Linear )
+ {
+ // Emulate non-smooth gradient
+ if( 0 < nSteps && nSteps < 100 )
+ {
+ double fOffsetStep = ( 1.0 - fBorderOffset ) / static_cast<double>(nSteps);
+ for( sal_uInt16 i = 0; i < nSteps; i++ ) {
+ Color aColor = ImplGetGradientColor( aStartColor, aEndColor, i / static_cast<double>(nSteps) );
+ ImplWriteGradientStop( aColor, fBorderOffset + ( i + 1 ) * fOffsetStep );
+ aColor = ImplGetGradientColor( aStartColor, aEndColor, ( i + 1 ) / static_cast<double>(nSteps) );
+ ImplWriteGradientStop( aColor, fBorderOffset + ( i + 1 ) * fOffsetStep );
+ }
+ }
+ else
+ {
+ ImplWriteGradientStop( aStartColor, fBorderOffset );
+ ImplWriteGradientStop( aEndColor, 1.0 );
+ }
+ }
+ else
+ {
+ fBorderOffset /= 2;
+ // Emulate non-smooth gradient
+ if( 0 < nSteps && nSteps < 100 )
+ {
+ double fOffsetStep = ( 0.5 - fBorderOffset ) / static_cast<double>(nSteps);
+ // Upper half
+ for( sal_uInt16 i = 0; i < nSteps; i++ )
+ {
+ Color aColor = ImplGetGradientColor( aEndColor, aStartColor, i / static_cast<double>(nSteps) );
+ ImplWriteGradientStop( aColor, fBorderOffset + i * fOffsetStep );
+ aColor = ImplGetGradientColor( aEndColor, aStartColor, (i + 1 ) / static_cast<double>(nSteps) );
+ ImplWriteGradientStop( aColor, fBorderOffset + i * fOffsetStep );
+ }
+ // Lower half
+ for( sal_uInt16 i = 0; i < nSteps; i++ )
+ {
+ Color aColor = ImplGetGradientColor( aStartColor, aEndColor, i / static_cast<double>(nSteps) );
+ ImplWriteGradientStop( aColor, 0.5 + (i + 1) * fOffsetStep );
+ aColor = ImplGetGradientColor( aStartColor, aEndColor, (i + 1 ) / static_cast<double>(nSteps) );
+ ImplWriteGradientStop( aColor, 0.5 + (i + 1) * fOffsetStep );
+ }
+ }
+ else
+ {
+ ImplWriteGradientStop( aEndColor, fBorderOffset );
+ ImplWriteGradientStop( aStartColor, 0.5 );
+ ImplWriteGradientStop( aEndColor, 1.0 - fBorderOffset );
+ }
+ }
+ }
+ }
+
+ OUString aGradientStyle = "fill:url(#" + aGradientId + ")";
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aGradientStyle );
+ ImplWritePolyPolygon( rPolyPoly, false );
+}
+
+
+void SVGActionWriter::ImplWriteGradientStop( const Color& rColor, double fOffset )
+{
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrOffset, OUString::number( fOffset ) );
+
+ OUString aStyle, aColor;
+ aStyle += "stop-color:";
+ SVGAttributeWriter::ImplGetColorStr ( rColor, aColor );
+ aStyle += aColor;
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle );
+ {
+ SvXMLElementExport aElemStartStop( mrExport, XML_NAMESPACE_NONE, aXMLElemStop, true, true );
+ }
+}
+
+
+Color SVGActionWriter::ImplGetColorWithIntensity( const Color& rColor,
+ sal_uInt16 nIntensity )
+{
+ sal_uInt8 nNewRed = static_cast<sal_uInt8>( static_cast<tools::Long>(rColor.GetRed()) * nIntensity / 100 );
+ sal_uInt8 nNewGreen = static_cast<sal_uInt8>( static_cast<tools::Long>(rColor.GetGreen()) * nIntensity / 100 );
+ sal_uInt8 nNewBlue = static_cast<sal_uInt8>( static_cast<tools::Long>(rColor.GetBlue()) * nIntensity / 100 );
+ return Color( nNewRed, nNewGreen, nNewBlue);
+}
+
+
+Color SVGActionWriter::ImplGetGradientColor( const Color& rStartColor,
+ const Color& rEndColor,
+ double fOffset )
+{
+ tools::Long nRedStep = rEndColor.GetRed() - rStartColor.GetRed();
+ tools::Long nNewRed = rStartColor.GetRed() + static_cast<tools::Long>( nRedStep * fOffset );
+ nNewRed = ( nNewRed < 0 ) ? 0 : ( nNewRed > 0xFF) ? 0xFF : nNewRed;
+
+ tools::Long nGreenStep = rEndColor.GetGreen() - rStartColor.GetGreen();
+ tools::Long nNewGreen = rStartColor.GetGreen() + static_cast<tools::Long>( nGreenStep * fOffset );
+ nNewGreen = ( nNewGreen < 0 ) ? 0 : ( nNewGreen > 0xFF) ? 0xFF : nNewGreen;
+
+ tools::Long nBlueStep = rEndColor.GetBlue() - rStartColor.GetBlue();
+ tools::Long nNewBlue = rStartColor.GetBlue() + static_cast<tools::Long>( nBlueStep * fOffset );
+ nNewBlue = ( nNewBlue < 0 ) ? 0 : ( nNewBlue > 0xFF) ? 0xFF : nNewBlue;
+
+ return Color( static_cast<sal_uInt8>(nNewRed), static_cast<sal_uInt8>(nNewGreen), static_cast<sal_uInt8>(nNewBlue) );
+}
+
+void SVGActionWriter::StartMask(const Point& rDestPt, const Size& rDestSize,
+ const Gradient& rGradient, sal_uInt32 nWriteFlags,
+ OUString* pTextFillOpacity)
+{
+ OUString aStyle;
+ if (rGradient.GetStartColor() == rGradient.GetEndColor())
+ {
+ // Special case: constant alpha value.
+ const Color& rColor = rGradient.GetStartColor();
+ const double fOpacity = 1.0 - static_cast<double>(rColor.GetLuminance()) / 255;
+ if (pTextFillOpacity)
+ {
+ // Don't write anything, return what is a value suitable for <tspan fill-opacity="...">.
+ *pTextFillOpacity = OUString::number(fOpacity);
+ return;
+ }
+ else
+ {
+ aStyle = "opacity: " + OUString::number(fOpacity);
+ }
+ }
+ else
+ {
+ OUString aMaskId = "mask" + OUString::number(mnCurMaskId++);
+
+ {
+ SvXMLElementExport aElemDefs(mrExport, XML_NAMESPACE_NONE, aXMLElemDefs, true, true);
+
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrId, aMaskId);
+ {
+ SvXMLElementExport aElemMask(mrExport, XML_NAMESPACE_NONE, "mask", true, true);
+
+ const tools::PolyPolygon aPolyPolygon(tools::PolyPolygon(tools::Rectangle(rDestPt, rDestSize)));
+ Gradient aGradient(rGradient);
+
+ // swap gradient stops to adopt SVG mask
+ Color aTmpColor(aGradient.GetStartColor());
+ sal_uInt16 nTmpIntensity(aGradient.GetStartIntensity());
+ aGradient.SetStartColor(aGradient.GetEndColor());
+ aGradient.SetStartIntensity(aGradient.GetEndIntensity());
+ aGradient.SetEndColor(aTmpColor);
+ aGradient.SetEndIntensity(nTmpIntensity);
+
+ ImplWriteGradientEx(aPolyPolygon, aGradient, nWriteFlags);
+ }
+ }
+
+ aStyle = "mask:url(#" + aMaskId + ")";
+ }
+ mrExport.AddAttribute(XML_NAMESPACE_NONE, aXMLAttrStyle, aStyle);
+}
+
+void SVGActionWriter::ImplWriteMask(GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize,
+ const Gradient& rGradient, sal_uInt32 nWriteFlags)
+{
+ Point aSrcPt(rMtf.GetPrefMapMode().GetOrigin());
+ const Size aSrcSize(rMtf.GetPrefSize());
+ const double fScaleX
+ = aSrcSize.Width() ? static_cast<double>(rDestSize.Width()) / aSrcSize.Width() : 1.0;
+ const double fScaleY
+ = aSrcSize.Height() ? static_cast<double>(rDestSize.Height()) / aSrcSize.Height() : 1.0;
+ tools::Long nMoveX, nMoveY;
+
+ if (fScaleX != 1.0 || fScaleY != 1.0)
+ {
+ rMtf.Scale(fScaleX, fScaleY);
+ aSrcPt.setX(FRound(aSrcPt.X() * fScaleX));
+ aSrcPt.setY(FRound(aSrcPt.Y() * fScaleY));
+ }
+
+ nMoveX = rDestPt.X() - aSrcPt.X();
+ nMoveY = rDestPt.Y() - aSrcPt.Y();
+
+ if (nMoveX || nMoveY)
+ rMtf.Move(nMoveX, nMoveY);
+
+ {
+ std::unique_ptr<SvXMLElementExport> pElemG;
+ if (!maTextWriter.hasTextOpacity())
+ {
+ StartMask(rDestPt, rDestSize, rGradient, nWriteFlags);
+ pElemG.reset(
+ new SvXMLElementExport(mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, true));
+ }
+
+ mpVDev->Push();
+ ImplWriteActions( rMtf, nWriteFlags, "" );
+ mpVDev->Pop();
+ }
+}
+
+
+void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
+ o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth )
+{
+ const FontMetric aMetric( mpVDev->GetFontMetric() );
+
+ bool bTextSpecial = aMetric.IsShadow() || aMetric.IsOutline() || (aMetric.GetRelief() != FontRelief::NONE);
+
+ if( !bTextSpecial )
+ {
+ ImplWriteText( rPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+ }
+ else
+ {
+ if( aMetric.GetRelief() != FontRelief::NONE )
+ {
+ Color aReliefColor( COL_LIGHTGRAY );
+ Color aTextColor( mpVDev->GetTextColor() );
+
+ if ( aTextColor == COL_BLACK )
+ aTextColor = COL_WHITE;
+
+ // coverity[copy_paste_error : FALSE] - aReliefColor depending on aTextColor is correct
+ if (aTextColor == COL_WHITE)
+ aReliefColor = COL_BLACK;
+
+
+ Point aPos( rPos );
+ Point aOffset( 6, 6 );
+
+ if ( aMetric.GetRelief() == FontRelief::Engraved )
+ {
+ aPos -= aOffset;
+ }
+ else
+ {
+ aPos += aOffset;
+ }
+
+ ImplWriteText( aPos, rText, pDXArray, nWidth, aReliefColor );
+ ImplWriteText( rPos, rText, pDXArray, nWidth, aTextColor );
+ }
+ else
+ {
+ if( aMetric.IsShadow() )
+ {
+ tools::Long nOff = 1 + ((aMetric.GetLineHeight()-24)/24);
+ if ( aMetric.IsOutline() )
+ nOff += 6;
+
+ Color aTextColor( mpVDev->GetTextColor() );
+ Color aShadowColor( COL_BLACK );
+
+ if ( (aTextColor == COL_BLACK) || (aTextColor.GetLuminance() < 8) )
+ aShadowColor = COL_LIGHTGRAY;
+
+ Point aPos( rPos );
+ aPos += Point( nOff, nOff );
+ ImplWriteText( aPos, rText, pDXArray, nWidth, aShadowColor );
+
+ if( !aMetric.IsOutline() )
+ {
+ ImplWriteText( rPos, rText, pDXArray, nWidth, aTextColor );
+ }
+ }
+
+ if( aMetric.IsOutline() )
+ {
+ Point aPos = rPos + Point( -6, -6 );
+ ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+ aPos = rPos + Point( +6, +6);
+ ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+ aPos = rPos + Point( -6, +0);
+ ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+ aPos = rPos + Point( -6, +6);
+ ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+ aPos = rPos + Point( +0, +6);
+ ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+ aPos = rPos + Point( +0, -6);
+ ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+ aPos = rPos + Point( +6, -1);
+ ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+ aPos = rPos + Point( +6, +0);
+ ImplWriteText( aPos, rText, pDXArray, nWidth, mpVDev->GetTextColor() );
+
+ ImplWriteText( rPos, rText, pDXArray, nWidth, COL_WHITE );
+ }
+ }
+ }
+}
+
+
+void SVGActionWriter::ImplWriteText( const Point& rPos, const OUString& rText,
+ o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth,
+ Color aTextColor )
+{
+ sal_Int32 nLen = rText.getLength();
+ Size aNormSize;
+ Point aPos;
+ Point aBaseLinePos( rPos );
+ const FontMetric aMetric( mpVDev->GetFontMetric() );
+ const vcl::Font& rFont = mpVDev->GetFont();
+
+ if( rFont.GetAlignment() == ALIGN_TOP )
+ aBaseLinePos.AdjustY(aMetric.GetAscent() );
+ else if( rFont.GetAlignment() == ALIGN_BOTTOM )
+ aBaseLinePos.AdjustY( -(aMetric.GetDescent()) );
+
+ ImplMap( rPos, aPos );
+
+ std::vector<sal_Int32> aTmpArray(nLen);
+ // get text sizes
+ if( !pDXArray.empty() )
+ {
+ aNormSize = Size( mpVDev->GetTextWidth( rText ), 0 );
+ memcpy(aTmpArray.data(), pDXArray.data(), nLen * sizeof(sal_Int32));
+ }
+ else
+ {
+ aNormSize = Size( mpVDev->GetTextArray( rText, &aTmpArray ), 0 );
+ }
+ sal_Int32* pDX = aTmpArray.data();
+
+ // if text is rotated, set transform matrix at new g element
+ if( rFont.GetOrientation() )
+ {
+ Point aRot( aPos );
+ OUString aTransform = "rotate(" +
+ OUString::number( rFont.GetOrientation().get() * -0.1 ) + " " +
+ OUString::number( aRot.X() ) + " " +
+ OUString::number( aRot.Y() ) + ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, aTransform );
+ }
+
+
+ maAttributeWriter.AddPaintAttr( COL_TRANSPARENT, aTextColor );
+
+ // for each line of text there should be at least one group element
+ SvXMLElementExport aSVGGElem( mrExport, XML_NAMESPACE_NONE, aXMLElemG, true, false );
+
+ bool bIsPlaceholderField = false;
+
+ if( mbIsPlaceholderShape )
+ {
+ bIsPlaceholderField = rText.match( sPlaceholderTag );
+ // for a placeholder text field we export only one <text> svg element
+ if( bIsPlaceholderField )
+ {
+ OUString sCleanTextContent;
+ static const sal_Int32 nFrom = sPlaceholderTag.getLength();
+ if( rText.getLength() > nFrom )
+ {
+ sCleanTextContent = rText.copy( nFrom );
+ }
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "class", "PlaceholderText" );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aPos.X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPos.Y() ) );
+ {
+ SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, true, false );
+ // At least for the single slide case we need really to export placeholder text
+ mrExport.GetDocHandler()->characters( sCleanTextContent );
+ }
+ }
+ }
+
+ if( !bIsPlaceholderField )
+ {
+ if( nLen > 1 )
+ {
+ aNormSize.setWidth( pDX[ nLen - 2 ] + mpVDev->GetTextWidth( OUString(rText[nLen - 1]) ) );
+
+ if( nWidth && aNormSize.Width() && ( nWidth != aNormSize.Width() ) )
+ {
+ tools::Long i;
+ const double fFactor = static_cast<double>(nWidth) / aNormSize.Width();
+
+ for( i = 0; i < ( nLen - 1 ); i++ )
+ pDX[ i ] = FRound( pDX[ i ] * fFactor );
+ }
+ else
+ {
+ css::uno::Reference< css::i18n::XBreakIterator > xBI( vcl::unohelper::CreateBreakIterator() );
+ const css::lang::Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
+ sal_Int32 nCurPos = 0, nLastPos = 0, nX = aPos.X();
+
+ // write single glyphs at absolute text positions
+ for( bool bCont = true; bCont; )
+ {
+ sal_Int32 nCount = 1;
+
+ nLastPos = nCurPos;
+ nCurPos = xBI->nextCharacters( rText, nCurPos, rLocale,
+ css::i18n::CharacterIteratorMode::SKIPCELL,
+ nCount, nCount );
+
+ nCount = nCurPos - nLastPos;
+ bCont = ( nCurPos < rText.getLength() ) && nCount;
+
+ if( nCount )
+ {
+ const OUString aGlyph( rText.copy( nLastPos, nCount ) );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( nX ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPos.Y() ) );
+
+ {
+ SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, true, false );
+ mrExport.GetDocHandler()->characters( aGlyph );
+ }
+
+ if( bCont )
+ {
+ // #118796# do NOT access pDXArray, it may be zero (!)
+ sal_Int32 nDXWidth = pDX[ nCurPos - 1 ];
+ nDXWidth = ImplMap( nDXWidth );
+ nX = aPos.X() + nDXWidth;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aPos.X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPos.Y() ) );
+
+ {
+ SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, aXMLElemText, true, false );
+ mrExport.GetDocHandler()->characters( rText );
+ }
+ }
+ }
+
+
+ if( mrExport.IsUseNativeTextDecoration() )
+ return;
+
+ if( rFont.GetStrikeout() == STRIKEOUT_NONE && rFont.GetUnderline() == LINESTYLE_NONE )
+ return;
+
+ tools::Polygon aPoly( 4 );
+ const tools::Long nLineHeight = std::max<tools::Long>( FRound( aMetric.GetLineHeight() * 0.05 ), 1 );
+
+ if( rFont.GetStrikeout() )
+ {
+ const tools::Long nYLinePos = aBaseLinePos.Y() - FRound( aMetric.GetAscent() * 0.26 );
+
+ aPoly[ 0 ].setX( aBaseLinePos.X() ); aPoly[ 0 ].setY( nYLinePos - ( nLineHeight >> 1 ) );
+ aPoly[ 1 ].setX( aBaseLinePos.X() + aNormSize.Width() - 1 ); aPoly[ 1 ].setY( aPoly[ 0 ].Y() );
+ aPoly[ 2 ].setX( aPoly[ 1 ].X() ); aPoly[ 2 ].setY( aPoly[ 0 ].Y() + nLineHeight - 1 );
+ aPoly[ 3 ].setX( aPoly[ 0 ].X() ); aPoly[ 3 ].setY( aPoly[ 2 ].Y() );
+
+ ImplWritePolyPolygon( aPoly, false );
+ }
+
+ if( rFont.GetUnderline() )
+ {
+ const tools::Long nYLinePos = aBaseLinePos.Y() + ( nLineHeight << 1 );
+
+ aPoly[ 0 ].setX( aBaseLinePos.X() ); aPoly[ 0 ].setY( nYLinePos - ( nLineHeight >> 1 ) );
+ aPoly[ 1 ].setX( aBaseLinePos.X() + aNormSize.Width() - 1 ); aPoly[ 1 ].setY( aPoly[ 0 ].Y() );
+ aPoly[ 2 ].setX( aPoly[ 1 ].X() ); aPoly[ 2 ].setY( aPoly[ 0 ].Y() + nLineHeight - 1 );
+ aPoly[ 3 ].setX( aPoly[ 0 ].X() ); aPoly[ 3 ].setY( aPoly[ 2 ].Y() );
+
+ ImplWritePolyPolygon( aPoly, false );
+ }
+}
+
+namespace
+{
+void GetGraphicFromXShape(const css::uno::Reference<css::drawing::XShape>* pShape, Graphic& rGraphic)
+{
+ if (!pShape)
+ {
+ return;
+ }
+
+ uno::Reference<beans::XPropertySet> xPropertySet(*pShape, uno::UNO_QUERY);
+ if (!xPropertySet.is())
+ {
+ return;
+ }
+
+ uno::Reference<graphic::XGraphic> xGraphic;
+ if (xPropertySet->getPropertySetInfo()->hasPropertyByName("Graphic"))
+ {
+ xPropertySet->getPropertyValue("Graphic") >>= xGraphic;
+ }
+ rGraphic= Graphic(xGraphic);
+}
+}
+
+void SVGActionWriter::ImplWriteBmp( const BitmapEx& rBmpEx,
+ const Point& rPt, const Size& rSz,
+ const Point& rSrcPt, const Size& rSrcSz,
+ const css::uno::Reference<css::drawing::XShape>* pShape )
+{
+ if( rBmpEx.IsEmpty() )
+ return;
+ if( mpEmbeddedBitmapsMap && !mpEmbeddedBitmapsMap->empty())
+ {
+ BitmapChecksum nChecksum = rBmpEx.GetChecksum();
+ if( mpEmbeddedBitmapsMap->find( nChecksum ) != mpEmbeddedBitmapsMap->end() )
+ {
+ // <use transform="translate(?) scale(?)" xlink:ref="?" >
+ OUString sTransform;
+
+ Point aPoint;
+ ImplMap( rPt, aPoint );
+ if( aPoint.X() != 0 || aPoint.Y() != 0 )
+ sTransform = "translate(" + OUString::number( aPoint.X() ) + ", " + OUString::number( aPoint.Y() ) + ")";
+
+ Size aSize;
+ ImplMap( rSz, aSize );
+
+ MapMode aSourceMode( MapUnit::MapPixel );
+ Size aPrefSize = OutputDevice::LogicToLogic( rSrcSz, aSourceMode, maTargetMapMode );
+ Fraction aFractionX( aSize.Width(), aPrefSize.Width() );
+ Fraction aFractionY( aSize.Height(), aPrefSize.Height() );
+ double scaleX = rtl_math_round( double(aFractionX), 3, rtl_math_RoundingMode::rtl_math_RoundingMode_Corrected );
+ double scaleY = rtl_math_round( double(aFractionY), 3, rtl_math_RoundingMode::rtl_math_RoundingMode_Corrected );
+ if( !rtl_math_approxEqual( scaleX, 1.0 ) || !rtl_math_approxEqual( scaleY, 1.0 ) )
+ sTransform += " scale(" + OUString::number( double(aFractionX) ) + ", " + OUString::number( double(aFractionY) ) + ")";
+
+ if( !sTransform.isEmpty() )
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrTransform, sTransform );
+
+ // referenced bitmap template
+ OUString sRefId = "#bitmap(" + OUString::number( nChecksum ) + ")";
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
+
+ SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", true, true );
+ return;
+ }
+ }
+
+ BitmapEx aBmpEx( rBmpEx );
+ const tools::Rectangle aBmpRect( Point(), rBmpEx.GetSizePixel() );
+ const tools::Rectangle aSrcRect( rSrcPt, rSrcSz );
+
+ if( aSrcRect != aBmpRect )
+ aBmpEx.Crop( aSrcRect );
+
+ if( aBmpEx.IsEmpty() )
+ return;
+
+ SvMemoryStream aOStm( 65535, 65535 );
+
+ bool bCached = false;
+ Graphic aGraphic;
+ bool bJPG = false;
+ if (pShape)
+ {
+ GetGraphicFromXShape(pShape, aGraphic);
+ if (aGraphic.GetType() == GraphicType::Bitmap)
+ {
+ const BitmapEx& rGraphicBitmap = aGraphic.GetBitmapExRef();
+ if (rGraphicBitmap.GetChecksum() == rBmpEx.GetChecksum())
+ {
+ bool bPNG = false;
+ GfxLink aGfxLink = aGraphic.GetGfxLink();
+ if (aGfxLink.GetType() == GfxLinkType::NativePng)
+ {
+ bPNG = true;
+ }
+ else if (aGfxLink.GetType() == GfxLinkType::NativeJpg)
+ {
+ bJPG = true;
+ }
+ if (bPNG || bJPG)
+ {
+ aOStm.WriteBytes(aGfxLink.GetData(), aGfxLink.GetDataSize());
+ bCached = true;
+ }
+ }
+ }
+ }
+
+ const BitmapEx* pBitmap = &rBmpEx;
+ std::unique_ptr<BitmapEx> pNewBitmap;
+
+ // for preview we generate downscaled images (1280x720 max)
+ if (mbIsPreview)
+ {
+ Size aSize = rBmpEx.GetSizePixel();
+ double fX = static_cast<double>(aSize.getWidth()) / 1280;
+ double fY = static_cast<double>(aSize.getHeight()) / 720;
+ double fFactor = fX > fY ? fX : fY;
+ if (fFactor > 1.0)
+ {
+ aSize.setWidth(aSize.getWidth() / fFactor);
+ aSize.setHeight(aSize.getHeight() / fFactor);
+ pNewBitmap = std::make_unique<BitmapEx>(rBmpEx);
+ pNewBitmap->Scale(aSize);
+ pBitmap = pNewBitmap.get();
+ }
+ }
+
+ if( !(bCached || GraphicConverter::Export( aOStm, *pBitmap, ConvertDataFormat::PNG ) == ERRCODE_NONE) )
+ return;
+
+ Point aPt;
+ Size aSz;
+ Sequence< sal_Int8 > aSeq( static_cast<sal_Int8 const *>(aOStm.GetData()), aOStm.Tell() );
+ OUStringBuffer aBuffer;
+ if (bJPG)
+ {
+ aBuffer.append("data:image/jpeg;base64,");
+ }
+ else
+ {
+ aBuffer.append("data:image/png;base64,");
+ }
+ ::comphelper::Base64::encode( aBuffer, aSeq );
+
+ ImplMap( rPt, aPt );
+ ImplMap( rSz, aSz );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrX, OUString::number( aPt.X() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrY, OUString::number( aPt.Y() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrWidth, OUString::number( aSz.Width() ) );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrHeight, OUString::number( aSz.Height() ) );
+
+ // the image must be scaled to aSz in a non-uniform way
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, "preserveAspectRatio", "none" );
+
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, aBuffer.makeStringAndClear() );
+ {
+ SvXMLElementExport aElem( mrExport, XML_NAMESPACE_NONE, "image", true, true );
+ }
+}
+
+
+void SVGActionWriter::ImplWriteActions( const GDIMetaFile& rMtf,
+ sal_uInt32 nWriteFlags,
+ const OUString& aElementId,
+ const Reference< css::drawing::XShape >* pxShape,
+ const GDIMetaFile* pTextEmbeddedBitmapMtf )
+{
+ // need a counter for the actions written per shape to avoid double ID
+ // generation
+ sal_Int32 nEntryCount(0);
+
+ bool bUseElementId = !aElementId.isEmpty();
+
+#if OSL_DEBUG_LEVEL > 0
+ bool bIsTextShape = false;
+ if( !mrExport.IsUsePositionedCharacters() && pxShape
+ && Reference< XText >( *pxShape, UNO_QUERY ).is() )
+ {
+ bIsTextShape = true;
+ }
+#endif
+ mbIsPlaceholderShape = false;
+ if( bUseElementId && ( aElementId == sPlaceholderTag ) )
+ {
+ mbIsPlaceholderShape = true;
+ // since we utilize aElementId in an improper way we reset the boolean
+ // control variable bUseElementId to false before to go on
+ bUseElementId = false;
+ }
+
+ for( size_t nCurAction = 0, nCount = rMtf.GetActionSize(); nCurAction < nCount; nCurAction++ )
+ {
+ const MetaAction* pAction = rMtf.GetAction( nCurAction );
+ const MetaActionType nType = pAction->GetType();
+
+#if OSL_DEBUG_LEVEL > 0
+ if( bIsTextShape )
+ {
+ try
+ {
+ SvXMLElementExport aElem( mrExport,
+ XML_NAMESPACE_NONE, "desc", false, false );
+ OUStringBuffer sType(OUString::number(static_cast<sal_uInt16>(nType)));
+ if (pAction && (nType == MetaActionType::COMMENT))
+ {
+ sType.append(": ");
+ const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
+ OString sComment = pA->GetComment();
+ if (!sComment.isEmpty())
+ {
+ sType.append(OStringToOUString(
+ sComment, RTL_TEXTENCODING_UTF8));
+ }
+ if (sComment.equalsIgnoreAsciiCase("FIELD_SEQ_BEGIN"))
+ {
+ sal_uInt8 const*const pData = pA->GetData();
+ if (pData && (pA->GetDataSize()))
+ {
+ sal_uInt16 sz = static_cast<sal_uInt16>((pA->GetDataSize()) / 2);
+ if (sz)
+ {
+ sType.append("; ");
+ sType.append(
+ reinterpret_cast<sal_Unicode const*>(pData),
+ sz);
+ }
+ }
+ }
+ }
+ if (sType.getLength())
+ {
+ mrExport.GetDocHandler()->characters(
+ sType.makeStringAndClear());
+ }
+ }
+ catch( ... )
+ {
+ const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
+ SAL_WARN( "filter.svg", pA->GetComment() );
+ }
+
+ }
+#endif
+ switch( nType )
+ {
+ case MetaActionType::PIXEL:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaPixelAction* pA = static_cast<const MetaPixelAction*>(pAction);
+
+ maAttributeWriter.AddPaintAttr( pA->GetColor(), pA->GetColor() );
+ ImplWriteLine( pA->GetPoint(), pA->GetPoint(), &pA->GetColor() );
+ }
+ }
+ break;
+
+ case MetaActionType::POINT:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaPointAction* pA = static_cast<const MetaPointAction*>(pAction);
+
+ maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
+ ImplWriteLine( pA->GetPoint(), pA->GetPoint() );
+ }
+ }
+ break;
+
+ case MetaActionType::LINE:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaLineAction* pA = static_cast<const MetaLineAction*>(pAction);
+
+ maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetLineColor() );
+ ImplWriteLine( pA->GetStartPoint(), pA->GetEndPoint() );
+ }
+ }
+ break;
+
+ case MetaActionType::RECT:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
+ ImplWriteRect( static_cast<const MetaRectAction*>(pAction)->GetRect() );
+ }
+ }
+ break;
+
+ case MetaActionType::ROUNDRECT:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaRoundRectAction* pA = static_cast<const MetaRoundRectAction*>(pAction);
+
+ maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
+ ImplWriteRect( pA->GetRect(), pA->GetHorzRound(), pA->GetVertRound() );
+ }
+ }
+ break;
+
+ case MetaActionType::ELLIPSE:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaEllipseAction* pA = static_cast<const MetaEllipseAction*>(pAction);
+ const tools::Rectangle& rRect = pA->GetRect();
+
+ maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
+ ImplWriteEllipse( rRect.Center(), rRect.GetWidth() >> 1, rRect.GetHeight() >> 1 );
+ }
+ }
+ break;
+
+ case MetaActionType::ARC:
+ case MetaActionType::PIE:
+ case MetaActionType::CHORD:
+ case MetaActionType::POLYGON:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ tools::Polygon aPoly;
+
+ switch( nType )
+ {
+ case MetaActionType::ARC:
+ {
+ const MetaArcAction* pA = static_cast<const MetaArcAction*>(pAction);
+ aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Arc );
+ }
+ break;
+
+ case MetaActionType::PIE:
+ {
+ const MetaPieAction* pA = static_cast<const MetaPieAction*>(pAction);
+ aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Pie );
+ }
+ break;
+
+ case MetaActionType::CHORD:
+ {
+ const MetaChordAction* pA = static_cast<const MetaChordAction*>(pAction);
+ aPoly = tools::Polygon( pA->GetRect(), pA->GetStartPoint(), pA->GetEndPoint(), PolyStyle::Chord );
+ }
+ break;
+
+ case MetaActionType::POLYGON:
+ aPoly = static_cast<const MetaPolygonAction*>(pAction)->GetPolygon();
+ break;
+ default: break;
+ }
+
+ if( aPoly.GetSize() )
+ {
+ maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
+ ImplWritePolyPolygon( aPoly, false );
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::POLYLINE:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaPolyLineAction* pA = static_cast<const MetaPolyLineAction*>(pAction);
+ const tools::Polygon& rPoly = pA->GetPolygon();
+
+ if( rPoly.GetSize() )
+ {
+ maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), COL_TRANSPARENT );
+ ImplAddLineAttr( pA->GetLineInfo() );
+ ImplWritePolyPolygon( rPoly, true );
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::POLYPOLYGON:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaPolyPolygonAction* pA = static_cast<const MetaPolyPolygonAction*>(pAction);
+ const tools::PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
+
+ if( rPolyPoly.Count() )
+ {
+ maAttributeWriter.AddPaintAttr( mpVDev->GetLineColor(), mpVDev->GetFillColor() );
+ ImplWritePolyPolygon( rPolyPoly, false );
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::GRADIENT:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaGradientAction* pA = static_cast<const MetaGradientAction*>(pAction);
+ const tools::Polygon aRectPoly( pA->GetRect() );
+ const tools::PolyPolygon aRectPolyPoly( aRectPoly );
+
+ ImplWriteGradientEx( aRectPolyPoly, pA->GetGradient(), nWriteFlags );
+ }
+ }
+ break;
+
+ case MetaActionType::GRADIENTEX:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaGradientExAction* pA = static_cast<const MetaGradientExAction*>(pAction);
+ ImplWriteGradientEx( pA->GetPolyPolygon(), pA->GetGradient(), nWriteFlags );
+ }
+ }
+ break;
+
+ case MetaActionType::HATCH:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaHatchAction* pA = static_cast<const MetaHatchAction*>(pAction);
+ ImplWritePattern( pA->GetPolyPolygon(), &pA->GetHatch(), nullptr, nWriteFlags );
+ }
+ }
+ break;
+
+ case MetaActionType::Transparent:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaTransparentAction* pA = static_cast<const MetaTransparentAction*>(pAction);
+ const tools::PolyPolygon& rPolyPoly = pA->GetPolyPolygon();
+
+ if( rPolyPoly.Count() )
+ {
+ Color aNewLineColor( mpVDev->GetLineColor() ), aNewFillColor( mpVDev->GetFillColor() );
+
+ // tdf#149800 do not change transparency of fully transparent
+ // i.e. invisible line, because it makes it visible,
+ // resulting an extra line behind the normal shape line
+ if ( aNewLineColor.GetAlpha() > 0 )
+ aNewLineColor.SetAlpha( 255 - sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
+ aNewFillColor.SetAlpha( 255 - sal::static_int_cast<sal_uInt8>( FRound( pA->GetTransparence() * 2.55 ) ) );
+
+ maAttributeWriter.AddPaintAttr( aNewLineColor, aNewFillColor );
+ ImplWritePolyPolygon( rPolyPoly, false );
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::FLOATTRANSPARENT:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaFloatTransparentAction* pA = static_cast<const MetaFloatTransparentAction*>(pAction);
+ GDIMetaFile aTmpMtf( pA->GetGDIMetaFile() );
+ ImplWriteMask( aTmpMtf, pA->GetPoint(), pA->GetSize(),
+ pA->GetGradient(), nWriteFlags );
+ }
+ }
+ break;
+
+ case MetaActionType::EPS:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaEPSAction* pA = static_cast<const MetaEPSAction*>(pAction);
+ const GDIMetaFile& aGDIMetaFile( pA->GetSubstitute() );
+ bool bFound = false;
+
+ for( sal_uInt32 k = 0, nCount2 = aGDIMetaFile.GetActionSize(); ( k < nCount2 ) && !bFound; ++k )
+ {
+ const MetaAction* pSubstAct = aGDIMetaFile.GetAction( k );
+
+ if( pSubstAct->GetType() == MetaActionType::BMPSCALE )
+ {
+ bFound = true;
+ const MetaBmpScaleAction* pBmpScaleAction = static_cast<const MetaBmpScaleAction*>(pSubstAct);
+ ImplWriteBmp( BitmapEx(pBmpScaleAction->GetBitmap()),
+ pA->GetPoint(), pA->GetSize(),
+ Point(), pBmpScaleAction->GetBitmap().GetSizePixel(), pxShape );
+ }
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::COMMENT:
+ {
+ const MetaCommentAction* pA = static_cast<const MetaCommentAction*>(pAction);
+
+ if( ( pA->GetComment().equalsIgnoreAsciiCase("XGRAD_SEQ_BEGIN") ) &&
+ ( nWriteFlags & SVGWRITER_WRITE_FILL ) )
+ {
+ const MetaGradientExAction* pGradAction = nullptr;
+ bool bDone = false;
+
+ while( !bDone && ( ++nCurAction < nCount ) )
+ {
+ pAction = rMtf.GetAction( nCurAction );
+
+ if( pAction->GetType() == MetaActionType::GRADIENTEX )
+ pGradAction = static_cast<const MetaGradientExAction*>(pAction);
+ else if( ( pAction->GetType() == MetaActionType::COMMENT ) &&
+ ( static_cast<const MetaCommentAction*>( pAction )->GetComment().
+ equalsIgnoreAsciiCase("XGRAD_SEQ_END") ) )
+ {
+ bDone = true;
+ }
+ }
+
+ if( pGradAction )
+ ImplWriteGradientEx( pGradAction->GetPolyPolygon(), pGradAction->GetGradient(), nWriteFlags );
+ }
+ else if( ( pA->GetComment().equalsIgnoreAsciiCase("XPATHFILL_SEQ_BEGIN") ) &&
+ ( nWriteFlags & SVGWRITER_WRITE_FILL ) && !( nWriteFlags & SVGWRITER_NO_SHAPE_COMMENTS ) &&
+ pA->GetDataSize() )
+ {
+ // write open shape in every case
+ if (mapCurShape)
+ {
+ ImplWriteShape( *mapCurShape );
+ mapCurShape.reset();
+ }
+
+ SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pA->GetData()), pA->GetDataSize(), StreamMode::READ );
+ SvtGraphicFill aFill;
+
+ ReadSvtGraphicFill( aMemStm, aFill );
+
+ bool bGradient = SvtGraphicFill::fillGradient == aFill.getFillType() &&
+ ( SvtGraphicFill::GradientType::Linear == aFill.getGradientType() ||
+ SvtGraphicFill::GradientType::Radial == aFill.getGradientType() );
+ bool bSkip = ( SvtGraphicFill::fillSolid == aFill.getFillType() || bGradient );
+
+ if( bSkip )
+ {
+ tools::PolyPolygon aShapePolyPoly;
+
+ aFill.getPath( aShapePolyPoly );
+
+ if( aShapePolyPoly.Count() )
+ {
+ mapCurShape.reset( new SVGShapeDescriptor );
+
+ if( bUseElementId )
+ {
+ mapCurShape->maId = aElementId + "_" + OUString::number(nEntryCount++);
+ }
+
+ mapCurShape->maShapePolyPoly = aShapePolyPoly;
+ mapCurShape->maShapeFillColor = aFill.getFillColor();
+ mapCurShape->maShapeFillColor.SetAlpha( 255 - static_cast<sal_uInt8>(FRound( 255.0 * aFill.getTransparency() )) );
+
+ if( bGradient )
+ {
+ // step through following actions until the first Gradient/GradientEx action is found
+ while (!mapCurShape->mapShapeGradient && bSkip
+ && (++nCurAction < nCount))
+ {
+ pAction = rMtf.GetAction( nCurAction );
+
+ if( ( pAction->GetType() == MetaActionType::COMMENT ) &&
+ ( static_cast<const MetaCommentAction*>(pAction)->GetComment().
+ equalsIgnoreAsciiCase("XPATHFILL_SEQ_END") ) )
+ {
+ bSkip = false;
+ }
+ else if( pAction->GetType() == MetaActionType::GRADIENTEX )
+ {
+ mapCurShape->mapShapeGradient.reset( new Gradient(
+ static_cast< const MetaGradientExAction* >( pAction )->GetGradient() ) );
+ }
+ else if( pAction->GetType() == MetaActionType::GRADIENT )
+ {
+ mapCurShape->mapShapeGradient.reset( new Gradient(
+ static_cast< const MetaGradientAction* >( pAction )->GetGradient() ) );
+ }
+ }
+ }
+ }
+ else
+ bSkip = false;
+ }
+
+ // skip rest of comment
+ while( bSkip && ( ++nCurAction < nCount ) )
+ {
+ pAction = rMtf.GetAction( nCurAction );
+
+ if( ( pAction->GetType() == MetaActionType::COMMENT ) &&
+ ( static_cast<const MetaCommentAction*>( pAction )->GetComment().
+ equalsIgnoreAsciiCase("XPATHFILL_SEQ_END") ) )
+ {
+ bSkip = false;
+ }
+ }
+ }
+ else if( ( pA->GetComment().equalsIgnoreAsciiCase("XPATHSTROKE_SEQ_BEGIN") ) &&
+ ( nWriteFlags & SVGWRITER_WRITE_FILL ) && !( nWriteFlags & SVGWRITER_NO_SHAPE_COMMENTS ) &&
+ pA->GetDataSize() )
+ {
+ SvMemoryStream aMemStm( const_cast<sal_uInt8 *>(pA->GetData()), pA->GetDataSize(), StreamMode::READ );
+ SvtGraphicStroke aStroke;
+ tools::PolyPolygon aStartArrow, aEndArrow;
+
+ ReadSvtGraphicStroke( aMemStm, aStroke );
+ aStroke.getStartArrow( aStartArrow );
+ aStroke.getEndArrow( aEndArrow );
+
+ // Currently no support for strokes with start/end arrow(s)
+ // added that support
+ tools::Polygon aPoly;
+
+ aStroke.getPath(aPoly);
+
+ if (mapCurShape)
+ {
+ if(1 != mapCurShape->maShapePolyPoly.Count()
+ || !mapCurShape->maShapePolyPoly[0].IsEqual(aPoly))
+ {
+ // this path action is not covering the same path than the already existing
+ // fill polypolygon, so write out the fill polygon
+ ImplWriteShape( *mapCurShape );
+ mapCurShape.reset();
+ }
+ }
+
+ if (!mapCurShape)
+ {
+
+ mapCurShape.reset( new SVGShapeDescriptor );
+
+ if( bUseElementId )
+ {
+ mapCurShape->maId = aElementId + "_" + OUString::number(nEntryCount++);
+ }
+
+ mapCurShape->maShapePolyPoly = aPoly;
+ }
+
+ mapCurShape->maShapeLineColor = mpVDev->GetLineColor();
+ mapCurShape->maShapeLineColor.SetAlpha( 255 - static_cast<sal_uInt8>(FRound( aStroke.getTransparency() * 255.0 )) );
+ mapCurShape->mnStrokeWidth = FRound( aStroke.getStrokeWidth() );
+ aStroke.getDashArray( mapCurShape->maDashArray );
+
+ // added support for LineJoin
+ switch(aStroke.getJoinType())
+ {
+ default: /* SvtGraphicStroke::joinMiter, SvtGraphicStroke::joinNone */
+ {
+ mapCurShape->maLineJoin = basegfx::B2DLineJoin::Miter;
+ break;
+ }
+ case SvtGraphicStroke::joinRound:
+ {
+ mapCurShape->maLineJoin = basegfx::B2DLineJoin::Round;
+ break;
+ }
+ case SvtGraphicStroke::joinBevel:
+ {
+ mapCurShape->maLineJoin = basegfx::B2DLineJoin::Bevel;
+ break;
+ }
+ }
+
+ // added support for LineCap
+ switch(aStroke.getCapType())
+ {
+ default: /* SvtGraphicStroke::capButt */
+ {
+ mapCurShape->maLineCap = css::drawing::LineCap_BUTT;
+ break;
+ }
+ case SvtGraphicStroke::capRound:
+ {
+ mapCurShape->maLineCap = css::drawing::LineCap_ROUND;
+ break;
+ }
+ case SvtGraphicStroke::capSquare:
+ {
+ mapCurShape->maLineCap = css::drawing::LineCap_SQUARE;
+ break;
+ }
+ }
+
+ if (mapCurShape->maShapePolyPoly.Count() && (aStartArrow.Count() || aEndArrow.Count()))
+ {
+ ImplWriteShape( *mapCurShape );
+
+ mapCurShape->maShapeFillColor = mapCurShape->maShapeLineColor;
+ mapCurShape->maShapeLineColor = COL_TRANSPARENT;
+ mapCurShape->mnStrokeWidth = 0;
+ mapCurShape->maDashArray.clear();
+ mapCurShape->maLineJoin = basegfx::B2DLineJoin::Miter;
+ mapCurShape->maLineCap = css::drawing::LineCap_BUTT;
+
+ if(aStartArrow.Count())
+ {
+ mapCurShape->maShapePolyPoly = aStartArrow;
+
+ if( bUseElementId ) // #i124825# aElementId is optional, may be zero
+ {
+ mapCurShape->maId = aElementId + "_" + OUString::number(nEntryCount++);
+ }
+
+ ImplWriteShape( *mapCurShape );
+ }
+
+ if(aEndArrow.Count())
+ {
+ mapCurShape->maShapePolyPoly = aEndArrow;
+
+ if( bUseElementId ) // #i124825# aElementId is optional, may be zero
+ {
+ mapCurShape->maId = aElementId + "_" + OUString::number(nEntryCount++);
+ }
+
+ ImplWriteShape( *mapCurShape );
+ }
+
+ mapCurShape.reset();
+ }
+
+ // write open shape in every case
+ if (mapCurShape)
+ {
+ ImplWriteShape( *mapCurShape );
+ mapCurShape.reset();
+ }
+
+ // skip rest of comment
+ bool bSkip = true;
+
+ while( bSkip && ( ++nCurAction < nCount ) )
+ {
+ pAction = rMtf.GetAction( nCurAction );
+
+ if( ( pAction->GetType() == MetaActionType::COMMENT ) &&
+ ( static_cast<const MetaCommentAction*>(pAction)->GetComment().
+ equalsIgnoreAsciiCase("XPATHSTROKE_SEQ_END") ) )
+ {
+ bSkip = false;
+ }
+ }
+ }
+ else if( !mrExport.IsUsePositionedCharacters() && ( nWriteFlags & SVGWRITER_WRITE_TEXT ) )
+ {
+ if( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_PAINTSHAPE_BEGIN" ) )
+ {
+ if( pxShape )
+ {
+ Reference< XText > xText( *pxShape, UNO_QUERY );
+ if( xText.is() )
+ maTextWriter.setTextShape( xText, pTextEmbeddedBitmapMtf );
+ }
+ maTextWriter.createParagraphEnumeration();
+ {
+ // nTextFound == -1 => no text found
+ // nTextFound == 0 => no text found and end of text shape reached
+ // nTextFound == 1 => text found!
+ sal_Int32 nTextFound = -1;
+ while( ( nTextFound < 0 ) && ( nCurAction < nCount ) )
+ {
+ nTextFound
+ = maTextWriter.setTextPosition(rMtf, nCurAction, nWriteFlags);
+ }
+ // We found some text in the current text shape.
+ if( nTextFound > 0 )
+ {
+ maTextWriter.setTextProperties( rMtf, nCurAction );
+ maTextWriter.startTextShape();
+ }
+ // We reached the end of the current text shape
+ // without finding any text. So we need to go back
+ // by one action in order to handle the
+ // XTEXT_PAINTSHAPE_END action because on the next
+ // loop the nCurAction is incremented by one.
+ else
+ {
+ --nCurAction;
+ }
+ }
+ }
+ else if( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_PAINTSHAPE_END" ) )
+ {
+ maTextWriter.endTextShape();
+ }
+ else if( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_EOP" ) )
+ {
+ const MetaAction* pNextAction = rMtf.GetAction( nCurAction + 1 );
+ if( !( ( pNextAction->GetType() == MetaActionType::COMMENT ) &&
+ ( static_cast<const MetaCommentAction*>(pNextAction)->GetComment().equalsIgnoreAsciiCase("XTEXT_PAINTSHAPE_END") ) ))
+ {
+ // nTextFound == -1 => no text found and end of paragraph reached
+ // nTextFound == 0 => no text found and end of text shape reached
+ // nTextFound == 1 => text found!
+ sal_Int32 nTextFound = -1;
+ while( ( nTextFound < 0 ) && ( nCurAction < nCount ) )
+ {
+ nTextFound
+ = maTextWriter.setTextPosition(rMtf, nCurAction, nWriteFlags);
+ }
+ // We found a paragraph with some text in the
+ // current text shape.
+ if( nTextFound > 0 )
+ {
+ maTextWriter.setTextProperties( rMtf, nCurAction );
+ maTextWriter.startTextParagraph();
+ }
+ // We reached the end of the current text shape
+ // without finding any text. So we need to go back
+ // by one action in order to handle the
+ // XTEXT_PAINTSHAPE_END action because on the next
+ // loop the nCurAction is incremented by one.
+ else
+ {
+ --nCurAction;
+ }
+
+ }
+ }
+ else if( pA->GetComment().equalsIgnoreAsciiCase( "XTEXT_EOL" ) )
+ {
+ const MetaAction* pNextAction = rMtf.GetAction( nCurAction + 1 );
+ if( !( ( pNextAction->GetType() == MetaActionType::COMMENT ) &&
+ ( static_cast<const MetaCommentAction*>(pNextAction)->GetComment().equalsIgnoreAsciiCase("XTEXT_EOP") ) ) )
+ {
+ // nTextFound == -2 => no text found and end of line reached
+ // nTextFound == -1 => no text found and end of paragraph reached
+ // nTextFound == 1 => text found!
+ sal_Int32 nTextFound = -2;
+ while( ( nTextFound < -1 ) && ( nCurAction < nCount ) )
+ {
+ nTextFound
+ = maTextWriter.setTextPosition(rMtf, nCurAction, nWriteFlags);
+ }
+ // We found a line with some text in the current
+ // paragraph.
+ if( nTextFound > 0 )
+ {
+ maTextWriter.startTextPosition();
+ }
+ // We reached the end of the current paragraph
+ // without finding any text. So we need to go back
+ // by one action in order to handle the XTEXT_EOP
+ // action because on the next loop the nCurAction is
+ // incremented by one.
+ else
+ {
+ --nCurAction;
+ }
+ }
+ }
+ }
+ else if( pA->GetComment().startsWithIgnoreAsciiCase( sTiledBackgroundTag ) )
+ {
+ // In the tile case the background is rendered through a rectangle
+ // filled by exploiting an exported pattern element.
+ // Both the pattern and the rectangle are embedded in a <defs> element.
+ // The comment content has the following format: "SLIDE_BACKGROUND <background-id>"
+ const OString& sComment = pA->GetComment();
+ OUString sRefId = "#" + OUString::fromUtf8( o3tl::getToken(sComment, 1, ' ') );
+ mrExport.AddAttribute( XML_NAMESPACE_NONE, aXMLAttrXLinkHRef, sRefId );
+
+ SvXMLElementExport aRefElem( mrExport, XML_NAMESPACE_NONE, "use", true, true );
+ }
+ }
+ break;
+
+ case MetaActionType::BMP:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaBmpAction* pA = static_cast<const MetaBmpAction*>(pAction);
+
+ ImplWriteBmp( BitmapEx(pA->GetBitmap()),
+ pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmap().GetSizePixel() ),
+ Point(), pA->GetBitmap().GetSizePixel(), pxShape );
+ }
+ }
+ break;
+
+ case MetaActionType::BMPSCALE:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaBmpScaleAction* pA = static_cast<const MetaBmpScaleAction*>(pAction);
+
+ // Bitmaps embedded into text shapes are collected and exported elsewhere.
+ if( maTextWriter.isTextShapeStarted() )
+ {
+ maTextWriter.writeBitmapPlaceholder( pA );
+ }
+ else
+ {
+ ImplWriteBmp( BitmapEx(pA->GetBitmap()),
+ pA->GetPoint(), pA->GetSize(),
+ Point(), pA->GetBitmap().GetSizePixel(), pxShape );
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::BMPSCALEPART:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaBmpScalePartAction* pA = static_cast<const MetaBmpScalePartAction*>(pAction);
+
+ ImplWriteBmp( BitmapEx(pA->GetBitmap()),
+ pA->GetDestPoint(), pA->GetDestSize(),
+ pA->GetSrcPoint(), pA->GetSrcSize(), pxShape );
+ }
+ }
+ break;
+
+ case MetaActionType::BMPEX:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaBmpExAction* pA = static_cast<const MetaBmpExAction*>(pAction);
+
+ ImplWriteBmp( pA->GetBitmapEx(),
+ pA->GetPoint(), mpVDev->PixelToLogic( pA->GetBitmapEx().GetSizePixel() ),
+ Point(), pA->GetBitmapEx().GetSizePixel(), pxShape );
+ }
+ }
+ break;
+
+ case MetaActionType::BMPEXSCALE:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaBmpExScaleAction* pA = static_cast<const MetaBmpExScaleAction*>(pAction);
+
+ // Bitmaps embedded into text shapes are collected and exported elsewhere.
+ if( maTextWriter.isTextShapeStarted() )
+ {
+ maTextWriter.writeBitmapPlaceholder( pA );
+ }
+ else
+ {
+ ImplWriteBmp( pA->GetBitmapEx(),
+ pA->GetPoint(), pA->GetSize(),
+ Point(), pA->GetBitmapEx().GetSizePixel(), pxShape );
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::BMPEXSCALEPART:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_FILL )
+ {
+ const MetaBmpExScalePartAction* pA = static_cast<const MetaBmpExScalePartAction*>(pAction);
+
+ ImplWriteBmp( pA->GetBitmapEx(),
+ pA->GetDestPoint(), pA->GetDestSize(),
+ pA->GetSrcPoint(), pA->GetSrcSize(), pxShape );
+ }
+ }
+ break;
+
+ case MetaActionType::TEXT:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_TEXT )
+ {
+ const MetaTextAction* pA = static_cast<const MetaTextAction*>(pAction);
+ sal_Int32 aLength = std::min( pA->GetText().getLength(), pA->GetLen() );
+ const OUString aText = pA->GetText().copy( pA->GetIndex(), aLength );
+
+ if( !aText.isEmpty() )
+ {
+ if( mrExport.IsUsePositionedCharacters() )
+ {
+ vcl::Font aFont = ImplSetCorrectFontHeight();
+ maAttributeWriter.SetFontAttr( aFont );
+ ImplWriteText( pA->GetPoint(), aText, {}, 0 );
+ }
+ else
+ {
+ maTextWriter.writeTextPortion( pA->GetPoint(), aText );
+ }
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::TEXTRECT:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_TEXT )
+ {
+ const MetaTextRectAction* pA = static_cast<const MetaTextRectAction*>(pAction);
+
+ if (!pA->GetText().isEmpty())
+ {
+ if( mrExport.IsUsePositionedCharacters() )
+ {
+ vcl::Font aFont = ImplSetCorrectFontHeight();
+ maAttributeWriter.SetFontAttr( aFont );
+ ImplWriteText( pA->GetRect().TopLeft(), pA->GetText(), {}, 0 );
+ }
+ maTextWriter.writeTextPortion( pA->GetRect().TopLeft(), pA->GetText() );
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::TEXTARRAY:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_TEXT )
+ {
+ const MetaTextArrayAction* pA = static_cast<const MetaTextArrayAction*>(pAction);
+ sal_Int32 aLength = std::min( pA->GetText().getLength(), pA->GetLen() );
+ const OUString aText = pA->GetText().copy( pA->GetIndex(), aLength );
+
+ if( !aText.isEmpty() )
+ {
+ if( mrExport.IsUsePositionedCharacters() )
+ {
+ vcl::Font aFont = ImplSetCorrectFontHeight();
+ maAttributeWriter.SetFontAttr( aFont );
+ ImplWriteText( pA->GetPoint(), aText, pA->GetDXArray(), 0 );
+ }
+ else
+ {
+ maTextWriter.writeTextPortion( pA->GetPoint(), aText );
+ }
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::STRETCHTEXT:
+ {
+ if( nWriteFlags & SVGWRITER_WRITE_TEXT )
+ {
+ const MetaStretchTextAction* pA = static_cast<const MetaStretchTextAction*>(pAction);
+ sal_Int32 aLength = std::min( pA->GetText().getLength(), pA->GetLen() );
+ const OUString aText = pA->GetText().copy( pA->GetIndex(), aLength );
+
+ if( !aText.isEmpty() )
+ {
+ if( mrExport.IsUsePositionedCharacters() )
+ {
+ vcl::Font aFont = ImplSetCorrectFontHeight();
+ maAttributeWriter.SetFontAttr( aFont );
+ ImplWriteText( pA->GetPoint(), aText, {}, pA->GetWidth() );
+ }
+ else
+ {
+ maTextWriter.writeTextPortion( pA->GetPoint(), aText );
+ }
+ }
+ }
+ }
+ break;
+
+ case MetaActionType::CLIPREGION:
+ case MetaActionType::ISECTRECTCLIPREGION:
+ case MetaActionType::ISECTREGIONCLIPREGION:
+ case MetaActionType::MOVECLIPREGION:
+ {
+ const_cast<MetaAction*>(pAction)->Execute( mpVDev );
+ const vcl::Region& rClipRegion = mpVDev->GetActiveClipRegion();
+ ImplWriteClipPath( rClipRegion.GetAsPolyPolygon() );
+
+ mbClipAttrChanged = true;
+ }
+ break;
+
+ case MetaActionType::PUSH:
+ {
+ const MetaPushAction* pA = static_cast<const MetaPushAction*>(pAction);
+ vcl::PushFlags mnFlags = pA->GetFlags();
+
+ const_cast<MetaAction*>(pAction)->Execute( mpVDev );
+
+ maContextHandler.pushState( mnFlags );
+ }
+ break;
+
+ case MetaActionType::POP:
+ {
+ const_cast<MetaAction*>(pAction)->Execute( mpVDev );
+
+ vcl::PushFlags mnFlags = maContextHandler.getPushFlags();
+
+ maContextHandler.popState();
+
+ if( mnFlags & vcl::PushFlags::CLIPREGION )
+ {
+ ImplEndClipRegion();
+ ImplStartClipRegion( mrCurrentState.nRegionClipPathId );
+ }
+ }
+ break;
+
+ case MetaActionType::REFPOINT:
+ case MetaActionType::MAPMODE:
+ case MetaActionType::LINECOLOR:
+ case MetaActionType::FILLCOLOR:
+ case MetaActionType::TEXTLINECOLOR:
+ case MetaActionType::TEXTFILLCOLOR:
+ case MetaActionType::TEXTCOLOR:
+ case MetaActionType::TEXTALIGN:
+ case MetaActionType::FONT:
+ case MetaActionType::LAYOUTMODE:
+ {
+ const_cast<MetaAction*>(pAction)->Execute( mpVDev );
+ }
+ break;
+
+ case MetaActionType::RASTEROP:
+ case MetaActionType::MASK:
+ case MetaActionType::MASKSCALE:
+ case MetaActionType::MASKSCALEPART:
+ case MetaActionType::WALLPAPER:
+ case MetaActionType::TEXTLINE:
+ case MetaActionType::TEXTLANGUAGE:
+ {
+ // !!! >>> we don't want to support these actions
+ }
+ break;
+
+ default:
+ SAL_WARN("filter.svg", "SVGActionWriter::ImplWriteActions: unsupported MetaAction # " << sal_Int32(nType));
+ break;
+ }
+ }
+}
+
+
+vcl::Font SVGActionWriter::ImplSetCorrectFontHeight() const
+{
+ vcl::Font aFont( mpVDev->GetFont() );
+ Size aSz;
+
+ ImplMap( Size( 0, aFont.GetFontHeight() ), aSz );
+
+ aFont.SetFontHeight( aSz.Height() );
+
+ return aFont;
+}
+
+
+void SVGActionWriter::WriteMetaFile( const Point& rPos100thmm,
+ const Size& rSize100thmm,
+ const GDIMetaFile& rMtf,
+ sal_uInt32 nWriteFlags,
+ const OUString& aElementId,
+ const Reference< css::drawing::XShape >* pXShape,
+ const GDIMetaFile* pTextEmbeddedBitmapMtf )
+{
+ MapMode aMapMode( rMtf.GetPrefMapMode() );
+ Size aPrefSize( rMtf.GetPrefSize() );
+ Fraction aFractionX( aMapMode.GetScaleX() );
+ Fraction aFractionY( aMapMode.GetScaleY() );
+
+ mpVDev->Push();
+
+ Size aSize( OutputDevice::LogicToLogic(rSize100thmm, MapMode(MapUnit::Map100thMM), aMapMode) );
+ aFractionX *= Fraction( aSize.Width(), aPrefSize.Width() );
+ aMapMode.SetScaleX( aFractionX );
+ aFractionY *= Fraction( aSize.Height(), aPrefSize.Height() );
+ aMapMode.SetScaleY( aFractionY );
+
+ Point aOffset( OutputDevice::LogicToLogic(rPos100thmm, MapMode(MapUnit::Map100thMM), aMapMode ) );
+ aOffset += aMapMode.GetOrigin();
+ aMapMode.SetOrigin( aOffset );
+
+ mpVDev->SetMapMode( aMapMode );
+
+ mapCurShape.reset();
+
+ ImplWriteActions( rMtf, nWriteFlags, aElementId, pXShape, pTextEmbeddedBitmapMtf );
+ maTextWriter.endTextParagraph();
+ ImplEndClipRegion();
+
+ // draw open shape that doesn't have a border
+ if (mapCurShape)
+ {
+ ImplWriteShape( *mapCurShape );
+ mapCurShape.reset();
+ }
+
+ mpVDev->Pop();
+}
+
+
+SVGWriter::SVGWriter( const Sequence<Any>& args, const Reference< XComponentContext >& rxCtx )
+ : mxContext(rxCtx)
+{
+ if(args.getLength()==1)
+ args[0]>>=maFilterData;
+}
+
+
+SVGWriter::~SVGWriter()
+{
+}
+
+
+void SAL_CALL SVGWriter::write( const Reference<XDocumentHandler>& rxDocHandler,
+ const Sequence<sal_Int8>& rMtfSeq )
+{
+ SvMemoryStream aMemStm( const_cast<sal_Int8 *>(rMtfSeq.getConstArray()), rMtfSeq.getLength(), StreamMode::READ );
+ GDIMetaFile aMtf;
+
+ SvmReader aReader( aMemStm );
+ aReader.Read( aMtf );
+
+ rtl::Reference<SVGExport> pWriter(new SVGExport( mxContext, rxDocHandler, maFilterData ));
+ pWriter->writeMtf( aMtf );
+}
+
+// XServiceInfo
+sal_Bool SVGWriter::supportsService(const OUString& sServiceName)
+{
+ return cppu::supportsService(this, sServiceName);
+}
+OUString SVGWriter::getImplementationName()
+{
+ return "com.sun.star.comp.Draw.SVGWriter";
+}
+css::uno::Sequence< OUString > SVGWriter::getSupportedServiceNames()
+{
+ return { "com.sun.star.svg.SVGWriter" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_SVGWriter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& args)
+{
+ return cppu::acquire(new SVGWriter(args, context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/svgwriter.hxx b/filter/source/svg/svgwriter.hxx
new file mode 100644
index 000000000..d48d68bde
--- /dev/null
+++ b/filter/source/svg/svgwriter.hxx
@@ -0,0 +1,406 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <cppuhelper/implbase.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/diagnose.h>
+#include <vcl/gdimtf.hxx>
+#include <vcl/metaact.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/graphictools.hxx>
+#include <xmloff/xmlexp.hxx>
+
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/container/XEnumeration.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/text/XText.hpp>
+#include <com/sun/star/text/XTextContent.hpp>
+#include <com/sun/star/text/XTextRange.hpp>
+#include <com/sun/star/svg/XSVGWriter.hpp>
+
+#include <memory>
+#include <stack>
+#include <unordered_map>
+
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::text;
+using namespace ::com::sun::star::style;
+using namespace ::com::sun::star::svg;
+using namespace ::com::sun::star::xml::sax;
+
+inline constexpr OUStringLiteral SVG_DTD_STRING = u"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">";
+
+#define SVGWRITER_WRITE_FILL 0x00000001
+#define SVGWRITER_WRITE_TEXT 0x00000002
+#define SVGWRITER_NO_SHAPE_COMMENTS 0x01000000
+
+// This must match the same type definition in svgexport.hxx
+typedef std::unordered_map< BitmapChecksum, std::unique_ptr< GDIMetaFile > > MetaBitmapActionMap;
+
+struct SVGState
+{
+ vcl::Font aFont;
+// Color aLineColor;
+// Color aFillColor;
+// basegfx::B2DLineJoin aLineJoin;
+// com::sun::star::drawing::LineCap aLineCap;
+ sal_Int32 nRegionClipPathId;
+
+ SVGState()
+ : aFont()
+ , nRegionClipPathId( 0 )
+ {}
+};
+// - PartialState -
+
+struct PartialState
+{
+ vcl::PushFlags meFlags;
+ ::std::optional<vcl::Font> mupFont;
+ sal_Int32 mnRegionClipPathId;
+
+ const vcl::Font& getFont( const vcl::Font& rDefaultFont ) const
+ { return mupFont ? *mupFont : rDefaultFont; }
+
+ void setFont( const vcl::Font& rFont )
+ { mupFont = rFont; }
+
+ PartialState()
+ : meFlags( vcl::PushFlags::NONE )
+ , mupFont()
+ , mnRegionClipPathId( 0 )
+ {}
+
+ PartialState(PartialState&& aPartialState) noexcept
+ : meFlags( aPartialState.meFlags )
+ , mupFont( std::move( aPartialState.mupFont ) )
+ , mnRegionClipPathId( aPartialState.mnRegionClipPathId )
+ {
+ aPartialState.meFlags = vcl::PushFlags::NONE;
+ aPartialState.mnRegionClipPathId = 0;
+ }
+};
+
+
+// - SVGContextHandler -
+
+class SVGContextHandler
+{
+private:
+ ::std::stack<PartialState> maStateStack;
+ SVGState maCurrentState;
+
+public:
+ vcl::PushFlags getPushFlags() const;
+ SVGState& getCurrentState();
+ void pushState( vcl::PushFlags eFlags );
+ void popState();
+};
+
+
+// - SVGAttributeWriter -
+
+class SVGActionWriter;
+class SVGExport;
+class SVGFontExport;
+
+
+class SVGAttributeWriter final
+{
+private:
+
+ SVGExport& mrExport;
+ SVGFontExport& mrFontExport;
+ SVGState& mrCurrentState;
+ std::unique_ptr<SvXMLElementExport> mpElemFont;
+
+
+ static double ImplRound( double fVal );
+
+public:
+
+ SVGAttributeWriter( SVGExport& rExport, SVGFontExport& rFontExport, SVGState& rCurState );
+ ~SVGAttributeWriter();
+
+ void AddColorAttr( const OUString& pColorAttrName, const OUString& pColorOpacityAttrName, const Color& rColor );
+ void AddGradientDef( const tools::Rectangle& rObjRect,const Gradient& rGradient, OUString& rGradientId );
+ void AddPaintAttr( const Color& rLineColor, const Color& rFillColor,
+ const tools::Rectangle* pObjBoundRect = nullptr, const Gradient* pFillGradient = nullptr );
+
+ void SetFontAttr( const vcl::Font& rFont );
+ void startFontSettings();
+ void endFontSettings();
+ void setFontFamily();
+
+ static void ImplGetColorStr( const Color& rColor, OUString& rColorStr );
+};
+
+struct SVGShapeDescriptor
+{
+ tools::PolyPolygon maShapePolyPoly;
+ Color maShapeFillColor;
+ Color maShapeLineColor;
+ sal_Int32 mnStrokeWidth;
+ SvtGraphicStroke::DashArray maDashArray;
+ ::std::unique_ptr< Gradient > mapShapeGradient;
+ OUString maId;
+ basegfx::B2DLineJoin maLineJoin;
+ css::drawing::LineCap maLineCap;
+
+
+ SVGShapeDescriptor() :
+ maShapeFillColor( COL_TRANSPARENT ),
+ maShapeLineColor( COL_TRANSPARENT ),
+ mnStrokeWidth( 0 ),
+ maLineJoin(basegfx::B2DLineJoin::Miter), // miter is Svg 'stroke-linejoin' default
+ maLineCap(css::drawing::LineCap_BUTT) // butt is Svg 'stroke-linecap' default
+ {
+ }
+};
+
+
+class SVGAttributeWriter;
+class SVGExport;
+class GDIMetaFile;
+
+
+struct BulletListItemInfo
+{
+ vcl::Font aFont;
+ Color aColor;
+ Point aPos;
+ sal_Unicode cBulletChar;
+};
+
+
+class SVGTextWriter final
+{
+ private:
+ SVGExport& mrExport;
+ SVGAttributeWriter& mrAttributeWriter;
+ SVGActionWriter& mrActionWriter;
+ VclPtr<VirtualDevice> mpVDev;
+ bool mbIsTextShapeStarted;
+ Reference<XText> mrTextShape;
+ OUString msShapeId;
+ Reference<XEnumeration> mrParagraphEnumeration;
+ Reference<XTextContent> mrCurrentTextParagraph;
+ Reference<XEnumeration> mrTextPortionEnumeration;
+ Reference<XTextRange> mrCurrentTextPortion;
+ const GDIMetaFile* mpTextEmbeddedBitmapMtf;
+ MapMode* mpTargetMapMode;
+ std::unique_ptr<SvXMLElementExport> mpTextShapeElem;
+ std::unique_ptr<SvXMLElementExport> mpTextParagraphElem;
+ std::unique_ptr<SvXMLElementExport> mpTextPositionElem;
+ OUString maTextOpacity;
+ sal_Int32 mnLeftTextPortionLength;
+ Point maTextPos;
+ tools::Long mnTextWidth;
+ bool mbPositioningNeeded;
+ bool mbIsNewListItem;
+ sal_Int16 meNumberingType;
+ sal_Unicode mcBulletChar;
+ std::unordered_map< OUString, BulletListItemInfo > maBulletListItemMap;
+ bool mbIsListLevelStyleImage;
+ bool mbLineBreak;
+ bool mbIsURLField;
+ OUString msUrl;
+ OUString msHyperlinkIdList;
+ OUString msPageCount;
+ OUString msDateTimeType;
+ OUString msTextFieldType;
+ bool mbIsPlaceholderShape;
+ static const bool mbIWS = false;
+ vcl::Font maCurrentFont;
+ vcl::Font maParentFont;
+
+ public:
+ explicit SVGTextWriter(SVGExport& rExport, SVGAttributeWriter& rAttributeWriter,
+ SVGActionWriter& mrActionWriter);
+ ~SVGTextWriter();
+
+ sal_Int32 setTextPosition(const GDIMetaFile& rMtf, size_t& nCurAction,
+ sal_uInt32 nWriteFlags);
+ void setTextProperties( const GDIMetaFile& rMtf, size_t nCurAction );
+ void addFontAttributes( bool bIsTextContainer );
+
+ void createParagraphEnumeration();
+ bool nextParagraph();
+ bool nextTextPortion();
+
+ bool isTextShapeStarted() const { return mbIsTextShapeStarted; }
+ void startTextShape();
+ void endTextShape();
+ void startTextParagraph();
+ void endTextParagraph();
+ void startTextPosition( bool bExportX = true, bool bExportY = true);
+ void endTextPosition();
+ bool hasTextOpacity() const;
+ void implExportHyperlinkIds();
+ void implWriteBulletChars();
+ template< typename MetaBitmapActionType >
+ void writeBitmapPlaceholder( const MetaBitmapActionType* pAction );
+ void implWriteEmbeddedBitmaps();
+ void writeTextPortion( const Point& rPos, const OUString& rText );
+ void implWriteTextPortion( const Point& rPos, const OUString& rText,
+ Color aTextColor );
+
+ void setVirtualDevice( VirtualDevice* pVDev, MapMode& rTargetMapMode )
+ {
+ if( !pVDev )
+ OSL_FAIL( "SVGTextWriter::setVirtualDevice: invalid virtual device." );
+ mpVDev = pVDev;
+ mpTargetMapMode = &rTargetMapMode;
+ }
+
+ void setTextShape( const Reference<XText>& rxText,
+ const GDIMetaFile* pTextEmbeddedBitmapMtf )
+ {
+ mrTextShape.set( rxText );
+ mpTextEmbeddedBitmapMtf = pTextEmbeddedBitmapMtf;
+ }
+
+ private:
+ void implMap( const Size& rSz, Size& rDstSz ) const;
+ void implMap( const Point& rPt, Point& rDstPt ) const;
+ void implSetCurrentFont();
+ void implSetFontFamily();
+
+ template< typename SubType >
+ bool implGetTextPosition( const MetaAction* pAction, Point& raPos, bool& bEmpty );
+ template< typename SubType >
+ bool implGetTextPositionFromBitmap( const MetaAction* pAction, Point& raPos, bool& rbEmpty );
+
+ void implRegisterInterface( const Reference< XInterface >& rxIf );
+ const OUString & implGetValidIDFromInterface( const Reference< XInterface >& rxIf );
+};
+
+
+class SVGActionWriter final
+{
+private:
+
+ sal_Int32 mnCurGradientId;
+ sal_Int32 mnCurMaskId;
+ sal_Int32 mnCurPatternId;
+ sal_Int32 mnCurClipPathId;
+ ::std::unique_ptr< SvXMLElementExport > mpCurrentClipRegionElem;
+ ::std::unique_ptr< SVGShapeDescriptor > mapCurShape;
+ SVGExport& mrExport;
+ SVGContextHandler maContextHandler;
+ SVGState& mrCurrentState;
+ SVGAttributeWriter maAttributeWriter;
+ SVGTextWriter maTextWriter;
+ VclPtr<VirtualDevice> mpVDev;
+ MapMode maTargetMapMode;
+ bool mbClipAttrChanged;
+ bool mbIsPlaceholderShape;
+ const MetaBitmapActionMap* mpEmbeddedBitmapsMap;
+ bool mbIsPreview;
+
+
+ tools::Long ImplMap( sal_Int32 nVal ) const;
+ Point& ImplMap( const Point& rPt, Point& rDstPt ) const;
+ Size& ImplMap( const Size& rSz, Size& rDstSz ) const;
+ void ImplMap( const tools::Rectangle& rRect, tools::Rectangle& rDstRect ) const;
+ tools::Polygon& ImplMap( const tools::Polygon& rPoly, tools::Polygon& rDstPoly ) const;
+ tools::PolyPolygon& ImplMap( const tools::PolyPolygon& rPolyPoly, tools::PolyPolygon& rDstPolyPoly ) const;
+
+ void ImplWriteLine( const Point& rPt1, const Point& rPt2, const Color* pLineColor = nullptr );
+ void ImplWriteRect( const tools::Rectangle& rRect, tools::Long nRadX = 0, tools::Long nRadY = 0 );
+ void ImplWriteEllipse( const Point& rCenter, tools::Long nRadX, tools::Long nRadY );
+ void ImplWritePattern( const tools::PolyPolygon& rPolyPoly, const Hatch* pHatch, const Gradient* pGradient, sal_uInt32 nWriteFlags );
+ void ImplAddLineAttr( const LineInfo &rAttrs );
+ void ImplWritePolyPolygon( const tools::PolyPolygon& rPolyPoly, bool bLineOnly,
+ bool bApplyMapping = true );
+ void ImplWriteShape( const SVGShapeDescriptor& rShape );
+ void ImplCreateClipPathDef( const tools::PolyPolygon& rPolyPoly );
+ void ImplStartClipRegion(sal_Int32 nClipPathId);
+ void ImplEndClipRegion();
+ void ImplWriteClipPath( const tools::PolyPolygon& rPolyPoly );
+ void ImplWriteGradientEx( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient, sal_uInt32 nWriteFlags);
+ void ImplWriteGradientLinear( const tools::PolyPolygon& rPolyPoly, const Gradient& rGradient );
+ void ImplWriteGradientStop( const Color& rColor, double fOffset );
+ static Color ImplGetColorWithIntensity( const Color& rColor, sal_uInt16 nIntensity );
+ static Color ImplGetGradientColor( const Color& rStartColor, const Color& rEndColor, double fOffset );
+ void ImplWriteMask( GDIMetaFile& rMtf, const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient, sal_uInt32 nWriteFlags );
+ void ImplWriteText( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth );
+ void ImplWriteText( const Point& rPos, const OUString& rText, o3tl::span<const sal_Int32> pDXArray, tools::Long nWidth, Color aTextColor );
+ void ImplWriteBmp( const BitmapEx& rBmpEx, const Point& rPt, const Size& rSz, const Point& rSrcPt, const Size& rSrcSz, const css::uno::Reference<css::drawing::XShape>* pShape);
+
+ void ImplWriteActions( const GDIMetaFile& rMtf,
+ sal_uInt32 nWriteFlags,
+ const OUString& aElementId,
+ const Reference< css::drawing::XShape >* pXShape = nullptr,
+ const GDIMetaFile* pTextEmbeddedBitmapMtf = nullptr );
+
+ vcl::Font ImplSetCorrectFontHeight() const;
+
+public:
+
+ static OUString GetPathString( const tools::PolyPolygon& rPolyPoly, bool bLine );
+ static BitmapChecksum GetChecksum( const MetaAction* pAction );
+
+public:
+ SVGActionWriter( SVGExport& rExport, SVGFontExport& rFontExport );
+ ~SVGActionWriter();
+
+ void WriteMetaFile( const Point& rPos100thmm,
+ const Size& rSize100thmm,
+ const GDIMetaFile& rMtf,
+ sal_uInt32 nWriteFlags,
+ const OUString& aElementId = "",
+ const Reference< css::drawing::XShape >* pXShape = nullptr,
+ const GDIMetaFile* pTextEmbeddedBitmapMtf = nullptr );
+
+ void SetEmbeddedBitmapRefs( const MetaBitmapActionMap* pEmbeddedBitmapsMap );
+ void StartMask(const Point& rDestPt, const Size& rDestSize, const Gradient& rGradient,
+ sal_uInt32 nWriteFlags, OUString* pTextStyle = nullptr);
+ void SetPreviewMode(bool bState = true) { mbIsPreview = bState; }
+};
+
+
+class SVGWriter : public cppu::WeakImplHelper< XSVGWriter, XServiceInfo >
+{
+private:
+ Reference< XComponentContext > mxContext;
+ Sequence< css::beans::PropertyValue > maFilterData;
+
+public:
+ explicit SVGWriter( const Sequence<Any>& args,
+ const Reference< XComponentContext >& rxCtx );
+ virtual ~SVGWriter() override;
+
+ // XSVGWriter
+ virtual void SAL_CALL write( const Reference<XDocumentHandler>& rxDocHandler,
+ const Sequence<sal_Int8>& rMtfSeq ) override;
+
+ // XServiceInfo
+ virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override;
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/test/odfserializer.cxx b/filter/source/svg/test/odfserializer.cxx
new file mode 100644
index 000000000..cc3e7b30a
--- /dev/null
+++ b/filter/source/svg/test/odfserializer.cxx
@@ -0,0 +1,128 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "odfserializer.hxx"
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+#include <cppuhelper/compbase.hxx>
+#include <cppuhelper/basemutex.hxx>
+#include <com/sun/star/uno/Sequence.hxx>
+
+using namespace ::com::sun::star;
+
+namespace svgi
+{
+
+typedef ::cppu::WeakComponentImplHelper<
+ css::xml::sax::XDocumentHandler> ODFSerializerBase;
+
+class ODFSerializer : private cppu::BaseMutex,
+ public ODFSerializerBase
+{
+public:
+ explicit ODFSerializer(const uno::Reference<io::XOutputStream>& xOut) :
+ ODFSerializerBase(m_aMutex),
+ m_xOutStream(xOut),
+ m_aLineFeed(1),
+ m_aBuf()
+ {
+ m_aLineFeed[0] = '\n';
+ }
+ ODFSerializer(const ODFSerializer&) = delete;
+ ODFSerializer& operator=(const ODFSerializer&) = delete;
+
+ virtual void SAL_CALL startDocument( ) override;
+ virtual void SAL_CALL endDocument( ) override;
+ virtual void SAL_CALL startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) override;
+ virtual void SAL_CALL endElement( const OUString& aName ) override;
+ virtual void SAL_CALL characters( const OUString& aChars ) override;
+ virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override;
+ virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override;
+ virtual void SAL_CALL setDocumentLocator( const uno::Reference< xml::sax::XLocator >& xLocator ) override;
+
+private:
+ uno::Reference<io::XOutputStream> m_xOutStream;
+ uno::Sequence<sal_Int8> m_aLineFeed;
+ uno::Sequence<sal_Int8> m_aBuf;
+};
+
+void SAL_CALL ODFSerializer::startDocument( )
+{
+ OSL_PRECOND(m_xOutStream.is(), "ODFSerializer(): invalid output stream");
+
+ OUStringBuffer aElement;
+ aElement.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ characters(aElement.makeStringAndClear());
+}
+
+void SAL_CALL ODFSerializer::endDocument()
+{}
+
+void SAL_CALL ODFSerializer::startElement( const OUString& aName,
+ const uno::Reference< xml::sax::XAttributeList >& xAttribs )
+{
+ OUStringBuffer aElement("<" + aName + " ");
+
+ const sal_Int16 nLen=xAttribs->getLength();
+ for( sal_Int16 i=0; i<nLen; ++i )
+ aElement.append(xAttribs->getNameByIndex(i) + "=\"" +
+ xAttribs->getValueByIndex(i) + "\" ");
+
+ characters(aElement.makeStringAndClear() + ">");
+}
+
+void SAL_CALL ODFSerializer::endElement( const OUString& aName )
+{
+ characters("</" + aName + ">");
+}
+
+void SAL_CALL ODFSerializer::characters( const OUString& aChars )
+{
+ const OString aStr = OUStringToOString(aChars, RTL_TEXTENCODING_UTF8);
+ const sal_Int32 nLen( aStr.getLength() );
+ m_aBuf.realloc( nLen );
+ const char* pStr = aStr.getStr();
+ std::copy(pStr,pStr+nLen,m_aBuf.getArray());
+
+ m_xOutStream->writeBytes(m_aBuf);
+ // TODO(F1): Make pretty printing configurable
+ m_xOutStream->writeBytes(m_aLineFeed);
+}
+
+void SAL_CALL ODFSerializer::ignorableWhitespace( const OUString& aWhitespaces )
+{
+ // TODO(F1): Make pretty printing configurable
+ characters(aWhitespaces);
+}
+
+void SAL_CALL ODFSerializer::processingInstruction( const OUString&,
+ const OUString& )
+{}
+
+void SAL_CALL ODFSerializer::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& )
+{}
+
+uno::Reference< xml::sax::XDocumentHandler> createSerializer(const uno::Reference<io::XOutputStream>& xOut )
+{
+ return uno::Reference<xml::sax::XDocumentHandler>(new ODFSerializer(xOut));
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/test/odfserializer.hxx b/filter/source/svg/test/odfserializer.hxx
new file mode 100644
index 000000000..2724c9f0a
--- /dev/null
+++ b/filter/source/svg/test/odfserializer.hxx
@@ -0,0 +1,33 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/uno/Reference.hxx>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+namespace svgi
+{
+/// Creates a XDocumentHandler that serializes directly to an XOutputStream
+css::uno::Reference<css::xml::sax::XDocumentHandler>
+createSerializer(const css::uno::Reference<css::io::XOutputStream>&);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/svg/tokens.txt b/filter/source/svg/tokens.txt
new file mode 100644
index 000000000..1211e691f
--- /dev/null
+++ b/filter/source/svg/tokens.txt
@@ -0,0 +1,403 @@
+#######################################
+#
+# elements (SVG Tiny 1.2)
+#
+#######################################
+a
+animate
+animateColor
+animateMotion
+animateTransform
+animation
+audio
+circle
+defs
+desc
+discard
+ellipse
+font
+font-face
+font-face-src
+font-face-uri
+foreignObject
+g
+glyph
+handler
+hkern
+image
+line
+linearGradient
+listener
+metadata
+missing-glyph
+mpath
+path
+polygon
+polyline
+prefetch
+radialGradient
+rect
+script
+set
+solidColor
+stop
+svg
+switch
+tbreak
+text
+textArea
+title
+tspan
+use
+video
+#######################################
+#
+# properties (SVG Tiny 1.2)
+#
+#######################################
+audio-level
+color
+color-rendering
+display
+display-align
+fill
+fill-opacity
+fill-rule
+font-family
+font-size
+font-style
+font-variant
+font-weight
+image-rendering
+line-increment
+opacity
+pointer-events
+shape-rendering
+solid-color
+solid-opacity
+stop-color
+stop-opacity
+stroke
+stroke-dasharray
+stroke-dashoffset
+stroke-linecap
+stroke-linejoin
+stroke-miterlimit
+stroke-opacity
+stroke-width
+text-align
+text-anchor
+text-rendering
+vector-effect
+viewport-fill
+viewport-fill-opacity
+visibility
+#######################################
+#
+# attributes (SVG Tiny 1.2)
+#
+#######################################
+accent-height
+accumulate
+additive
+alphabetic
+arabic-form
+ascent
+attributeName
+attributeType
+bandwidth
+baseProfile
+bbox
+begin
+by
+calcMode
+cap-height
+class
+contentScriptType
+cx
+cy
+d
+defaultAction
+descent
+dur
+editable
+end
+event
+externalResourcesRequired
+fill
+focusHighlight
+focusable
+font-family
+font-stretch
+font-style
+font-variant
+font-weight
+from
+fx
+fy
+g1
+g2
+glyph-name
+gradientTransform
+gradientUnits
+handler
+hanging
+height
+height
+horiz-adv-x
+horiz-origin-x
+id
+ideographic
+initialVisibility
+k
+keyPoints
+keySplines
+keyTimes
+lang
+mathematical
+max
+mediaCharacterEncoding
+mediaContentEncodings
+mediaSize
+mediaTime
+min
+nav-down
+nav-down-left
+nav-down-right
+nav-left
+nav-next
+nav-prev
+nav-right
+nav-up
+nav-up-left
+nav-up-right
+observer
+offset
+origin
+overlay
+overline-position
+overline-thickness
+panose-1
+path
+pathLength
+phase
+playbackOrder
+points
+preserveAspectRatio
+propagate
+r
+repeatCount
+repeatDur
+requiredExtensions
+requiredFeatures
+requiredFonts
+requiredFormats
+restart
+rotate
+rx
+ry
+slope
+snapshotTime
+stemh
+stemv
+strikethrough-position
+strikethrough-thickness
+style
+syncBehavior
+syncBehaviorDefault
+syncMaster
+syncTolerance
+syncToleranceDefault
+systemLanguage
+target
+timelineBegin
+to
+transform
+transformBehavior
+type
+u1
+u2
+underline-position
+underline-thickness
+unicode
+unicode-range
+units-per-em
+values
+version
+viewBox
+width
+widths
+x
+x-height
+x1
+x2
+actuate
+arcrole
+href
+role
+show
+base
+space
+y
+y1
+y2
+zoomAndPan
+#######################################
+#
+# colour values
+#
+#######################################
+aliceblue
+antiquewhite
+aqua
+aquamarine
+azure
+beige
+bisque
+black
+blanchedalmond
+blue
+blueviolet
+brown
+burlywood
+cadetblue
+chartreuse
+chocolate
+coral
+cornflowerblue
+cornsilk
+crimson
+cyan
+darkblue
+darkcyan
+darkgoldenrod
+darkgray
+darkgreen
+darkgrey
+darkkhaki
+darkmagenta
+darkolivegreen
+darkorange
+darkorchid
+darkred
+darksalmon
+darkseagreen
+darkslateblue
+darkslategray
+darkslategrey
+darkturquoise
+darkviolet
+deeppink
+deepskyblue
+dimgray
+dimgrey
+dodgerblue
+firebrick
+floralwhite
+forestgreen
+fuchsia
+gainsboro
+ghostwhite
+gold
+goldenrod
+gray
+grey
+green
+greenyellow
+honeydew
+hotpink
+indianred
+indigo
+ivory
+khaki
+lavender
+lavenderblush
+lawngreen
+lemonchiffon
+lightblue
+lightcoral
+lightcyan
+lightgoldenrodyellow
+lightgray
+lightgreen
+lightgrey
+lightpink
+lightsalmon
+lightseagreen
+lightskyblue
+lightslategray
+lightslategrey
+lightsteelblue
+lightyellow
+lime
+limegreen
+linen
+magenta
+maroon
+mediumaquamarine
+mediumblue
+mediumorchid
+mediumpurple
+mediumseagreen
+mediumslateblue
+mediumspringgreen
+mediumturquoise
+mediumvioletred
+midnightblue
+mintcream
+mistyrose
+moccasin
+navajowhite
+navy
+oldlace
+olive
+olivedrab
+orange
+orangered
+orchid
+palegoldenrod
+palegreen
+paleturquoise
+palevioletred
+papayawhip
+peachpuff
+peru
+pink
+plum
+powderblue
+purple
+red
+rosybrown
+royalblue
+saddlebrown
+salmon
+sandybrown
+seagreen
+seashell
+sienna
+silver
+skyblue
+slateblue
+slategray
+slategrey
+snow
+springgreen
+steelblue
+tan
+teal
+thistle
+tomato
+turquoise
+violet
+wheat
+white
+whitesmoke
+yellow
+yellowgreen
+#######################################
+#
+# Gradient units values
+#
+#######################################
+userSpaceOnUse
+objectBoundingBox
diff --git a/filter/source/t602/t602filter.component b/filter/source/t602/t602filter.component
new file mode 100644
index 000000000..49b355f67
--- /dev/null
+++ b/filter/source/t602/t602filter.component
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.Writer.T602ImportFilter"
+ constructor="filter_T602ImportFilter_get_implementation">
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ <service name="com.sun.star.document.ImportFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.Writer.T602ImportFilterDialog"
+ constructor="filter_T602ImportFilterDialog_get_implementation">
+ <service name="com.sun.star.ui.dialogs.FilterOptionsDialog"/>
+ </implementation>
+</component>
diff --git a/filter/source/t602/t602filter.cxx b/filter/source/t602/t602filter.cxx
new file mode 100644
index 000000000..7aced6764
--- /dev/null
+++ b/filter/source/t602/t602filter.cxx
@@ -0,0 +1,1137 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "t602filter.hxx"
+#include <strings.hrc>
+
+#include <stdio.h>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/bootstrap.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/awt/Toolkit.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/awt/UnoControlDialog.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <osl/diagnose.h>
+#include <rtl/ref.hxx>
+#include <rtl/character.hxx>
+#include <unotools/resmgr.hxx>
+#include <unotools/streamwrap.hxx>
+#include <utility>
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::awt;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::document;
+using com::sun::star::io::XInputStream;
+
+namespace T602ImportFilter {
+
+ unsigned char const kam2lat[129] =
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ "\xAC\x81\x82\xD4\x84\xD2\x9B\x9F\xD8\xB7\x91\xD6\x96\x92\x8E\xB5" // 8
+ "\x90\xA7\xA6\x93\x94\xE0\x85\xE9\xEC\x99\x9A\xE6\x95\xED\xFC\x9C" // 9
+ "\xA0\xA1\xA2\xA3\xE5\xD5\xDE\xE2\xE7\xFD\xEA\xE8\xCE\xF5\xAE\xAF" // A
+ "\x80\x80\x83\xB3\xB4\xE1\x87\x88\x89\x8A\x8B\x8C\x8F\x97\x8D\xBF" // B
+ "\xC0\xC1\xC2\xC3\xC4\xC5\xCF\x98\x9D\x9E\xA4\xA5\xA8\xA9\x86\xF3" // C
+ "\xCD\xB1\xB2\xB6\xB8\xB9\xBA\xBB\xF7\xD9\xDA\xDB\xDC\xF8\xF9\xDF" // D
+ "\xD0\xD1\xD3\xD7\xAA\xAB\xDD\xB0\xE3\xE4\xEB\xEE\xEF\xF0\xF2\xF4" // E
+ "\xBC\xBD\xBE\xC6\xC7\xC8\xF6\xC9\xCA\xFA\xFB\xCB\xF1\xCC\xFE\xFF"; // F
+
+ unsigned char const koi2lat[129] =
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ "\x80\x83\x86\xF5\xE1\x87\x88\x89\x8A\x8B\x8C\x8F\x97\xCF\xCF\x98" // 8
+ "\x9D\x9E\xA4\xA5\xA8\xA9\xDB\xDC\xDF\xB1\xB2\xB6\xB8\xB9\xBA\xBB" // 9
+ "\xBC\xBD\xBE\xC6\xC7\xC8\xF6\xC9\xCA\xCB\xCC\xCD\xCE\xAD\xAE\xAF" // A
+ "\xD0\xD1\xD3\xD7\xAA\xAB\xDD\xB0\xE3\xE4\xEB\xEE\xEF\xF0\xF2\xF4" // B
+ "\xDA\xA0\xC0\x9F\xD4\xD8\xEA\xC4\x81\xA1\x85\x92\x96\x94\xE5\xA2" // C
+ "\x93\x84\xFD\xE7\x9C\xA3\xC3\x82\xF7\xEC\xA7\xC2\xF3\xF8\xF9\xC5" // D
+ "\xBF\xB5\xD9\xAC\xD2\xB7\xE8\xB3\x9A\xD6\xDE\x91\x95\x99\xD5\xE0" // E
+ "\xE2\x8E\xFC\xE6\x9B\xE9\xB4\x90\xFA\xED\xA6\xC1\xF1\xFB\xFE\xFF"; // F
+
+ unsigned char const lat2UNC[257] =
+ // 0 1 2 3 4 5 6 7
+ // 8 9 A B C D E F
+ "\x00\xe7\x00\xfc\x00\xe9\x00\xf9\x00\xe4\x01\x6f\x00\xe8\x00\xa3" // 8
+ "\x00\xc6\x00\xd8\x00\xc5\x00\xe6\x00\xf8\x00\xc4\x00\xc4\x00\xe5"
+ "\x00\xc9\x01\x39\x00\xf4\x00\xf4\x00\xf6\x01\x3d\x01\x3e\x00\x20" // 9
+ "\x00\xf2\x00\xd6\x00\xdc\x01\x64\x01\x65\x00\xec\x20\xa7\x01\x0d"
+ "\x00\xe1\x00\xed\x00\xf3\x00\xfa\x00\xa1\x00\xd1\x01\x7d\x01\x7e" // A
+ "\x00\xbf\x00\xf1\x22\x11\x03\xc3\x01\x0c\x00\xa7\x00\xbb\x00\xab"
+ "\x25\x91\x25\x92\x25\x93\x25\x02\x25\x24\x00\xc1\x00\xc2\x01\x1a" // B
+ "\x00\x20\x00\x20\x00\x20\x00\x20\x22\x61\x00\xb1\x22\x65\x25\x10"
+ "\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x00\x25\x3c\x22\x64\x23\x20" // C
+ "\x23\x21\x22\x48\x00\xba\x22\x1a\x00\xb2\x00\xbd\x00\xbc\x00\xa4"
+ "\x03\xb1\x03\xb2\x01\x0e\x03\x93\x01\x0f\x01\x47\x00\xcd\x03\xc0" // D
+ "\x01\x1b\x25\x18\x25\x0c\x25\x88\x25\x84\x00\xb5\x01\x6e\x25\x80"
+ "\x00\xd3\x00\xdf\x00\xd4\x03\xa6\x03\x98\x01\x48\x01\x60\x01\x61" // E
+ "\x01\x54\x00\xda\x01\x55\x03\xa9\x00\xfd\x00\xdd\x03\xb4\x22\x1e"
+ "\x00\xf8\x02\xdd\x03\xb5\x02\xc7\x22\x29\x00\xa7\x00\xf7\x00\xe0" // F
+ "\x00\xb4\x00\xb0\x00\xc0\x02\xc6\x01\x58\x01\x59\x00\x20\x00\x20";
+
+ unsigned char const rus2UNC[257] =
+ // 0 1 2 3 4 5 6 7
+ // 8 9 A B C D E F
+ "\x04\x11\x00\xfc\x00\xe9\x04\x12\x00\xe4\x01\x6f\x04\x13\x04\x14" // 8
+ "\x04\x01\x04\x16\x04\x17\x04\x18\x04\x19\x00\xc4\x00\xc4\x04\x1a"
+ "\x00\xc9\x01\x39\x01\x3a\x00\xf4\x00\xf6\x01\x3d\x01\x3e\x00\x20" // 9
+ "\x04\x1c\x00\xd6\x00\xdc\x01\x64\x01\x65\x04\x1d\x04\x1f\x01\x0a"
+ "\x00\xe1\x00\xed\x00\xf3\x00\xfa\x04\x20\x04\x22\x01\x7d\x01\x7e" // A
+ "\x04\x23\x04\x24\x04\x43\x04\x44\x01\x0c\x00\xa7\x04\x3b\x04\x3c"
+ "\x04\x47\x04\x26\x04\x27\x25\x02\x25\x24\x00\xc1\x04\x28\x01\x1a" // B
+ "\x04\x29\x04\x2a\x04\x2b\x04\x2c\x04\x2d\x04\x2e\x04\x2f\x25\x10"
+ "\x25\x14\x25\x34\x25\x2c\x25\x1c\x25\x00\x25\x3c\x04\x31\x04\x32" // C
+ "\x04\x33\x04\x51\x04\x36\x04\x37\x04\x38\x04\x39\x04\x3a\x04\x1b"
+ "\x04\x3d\x04\x3f\x01\x0e\x04\x40\x01\x0f\x01\x47\x00\xcd\x04\x42" // D
+ "\x01\x1b\x25\x18\x25\x0c\x25\x88\x25\x84\x04\x46\x01\x6e\x25\x80"
+ "\x00\xd3\x00\xdf\x00\xd4\x04\x48\x04\x49\x01\x48\x01\x60\x01\x61" // E
+ "\x01\x54\x00\xda\x01\x55\x04\x4a\x00\xfd\x00\xdd\x04\x4b\x04\x4c"
+ "\x04\x4d\x02\xdd\x04\x4e\x02\xc7\x04\x4f\x00\xa7\x04\x34\x00\xe0" // F
+ "\x00\xb4\x00\xb0\x00\xc0\x02\xc6\x01\x58\x01\x59\x00\x20\x00\x20";
+
+#define Start_(_nam) \
+ if (mxHandler.is()) \
+ { \
+ mxHandler->startElement(_nam, xAttrList); \
+ if (mpAttrList) \
+ mpAttrList->Clear(); \
+ }
+
+#define End_(_nam) \
+ if (mxHandler.is()) \
+ { \
+ mxHandler->endElement(_nam); \
+ }
+
+static inistruct ini;
+
+T602ImportFilter::T602ImportFilter(css::uno::Reference<css::uno::XComponentContext > x )
+ : mxContext(std::move(x))
+ , node(tnode::START)
+{
+}
+
+T602ImportFilter::T602ImportFilter(css::uno::Reference<css::io::XInputStream> xInputStream)
+ : mxInputStream(std::move(xInputStream))
+ , node(tnode::START)
+{
+}
+
+
+T602ImportFilter::~T602ImportFilter()
+{
+}
+
+// XExtendedTypeDetection
+OUString T602ImportFilter::detect( Sequence<PropertyValue>& Descriptor)
+{
+ sal_Int32 nLength = Descriptor.getLength();
+ const PropertyValue * pValue = Descriptor.getConstArray();
+ for ( sal_Int32 i = 0 ; i < nLength; i++)
+ {
+ if ( pValue[i].Name == "InputStream" )
+ pValue[i].Value >>= mxInputStream;
+ }
+
+ if (!mxInputStream.is())
+ return OUString();
+
+ css::uno::Sequence< sal_Int8 > aData;
+ const size_t numBytes = 4;
+ size_t numBytesRead = mxInputStream->readSomeBytes (aData, numBytes);
+
+ if ((numBytesRead != numBytes) || (aData[0] != '@') ||
+ (aData[1] != 'C') || (aData[2] != 'T') || (aData[3] != ' '))
+ return OUString();
+
+ return "writer_T602_Document";
+}
+
+// XFilter
+sal_Bool SAL_CALL T602ImportFilter::filter( const Sequence< css::beans::PropertyValue >& aDescriptor )
+{
+ return importImpl ( aDescriptor );
+}
+
+// XImporter
+void SAL_CALL T602ImportFilter::setTargetDocument( const Reference< css::lang::XComponent >& xDoc )
+{
+ mxDoc = xDoc;
+}
+
+// XInitialization
+void SAL_CALL T602ImportFilter::initialize( const Sequence< Any >& /*aArguments*/ )
+{
+}
+
+// Other functions
+
+void T602ImportFilter::inschr(unsigned char ch)
+{
+ Reference < XAttributeList > xAttrList ( mpAttrList );
+
+ if(!ini.showcomm&&pst.comment) return;
+
+ if(ch==' ') {
+ setfnt(chngul,true);
+ pst.wasspace++;
+ return;
+ }
+
+ if(pst.wasspace > 0) {
+ if(ini.reformatpars) {
+ if(!pst.wasfdash)
+ inschrdef(' ');
+ pst.wasfdash = false;
+ } else {
+ char s[20];
+ sprintf(s,"%i",pst.wasspace);
+ if (mpAttrList)
+ mpAttrList->AddAttribute("text:c",OUString::createFromAscii(s));
+ Start_("text:s");
+ End_("text:s");
+ }
+ }
+
+ pst.wasspace = 0;
+ setfnt(chngul,true);
+ inschrdef(ch);
+}
+
+bool T602ImportFilter::importImpl( const Sequence< css::beans::PropertyValue >& aDescriptor )
+{
+ Reset602();
+
+ sal_Int32 nLength = aDescriptor.getLength();
+ const PropertyValue * pValue = aDescriptor.getConstArray();
+ for ( sal_Int32 i = 0 ; i < nLength; i++)
+ {
+ if ( pValue[i].Name == "InputStream" )
+ pValue[i].Value >>= mxInputStream;
+ }
+
+ if ( !mxInputStream.is() )
+ {
+ OSL_ASSERT( false );
+ return false;
+ }
+
+ // An XML import service: what we push sax messages to...
+ mxHandler.set( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.comp.Writer.XMLImporter", mxContext ), UNO_QUERY );
+
+ // The XImporter sets up an empty target document for XDocumentHandler to write to...
+ Reference < XImporter > xImporter(mxHandler, UNO_QUERY);
+ xImporter->setTargetDocument(mxDoc);
+
+ char fs[32], fs2[32];
+ sprintf(fs, "%ipt", inistruct::fontsize);
+ sprintf(fs2,"%ipt", 2*inistruct::fontsize);
+
+ mpAttrList = new SvXMLAttributeList;
+
+ Reference < XAttributeList > xAttrList ( mpAttrList );
+
+ mxHandler->startDocument();
+
+ mpAttrList->AddAttribute("xmlns:office", "http://openoffice.org/2000/office");
+ mpAttrList->AddAttribute("xmlns:style", "http://openoffice.org/2000/style");
+ mpAttrList->AddAttribute("xmlns:text", "http://openoffice.org/2000/text");
+ mpAttrList->AddAttribute("xmlns:table", "http://openoffice.org/2000/table");
+ mpAttrList->AddAttribute("xmlns:draw", "http://openoffice.org/2000/draw");
+ mpAttrList->AddAttribute("xmlns:fo", "http://www.w3.org/1999/XSL/Format");
+ mpAttrList->AddAttribute("xmlns:xlink", "http://www.w3.org/1999/xlink");
+ mpAttrList->AddAttribute("xmlns:number", "http://openoffice.org/2000/datastyle");
+ mpAttrList->AddAttribute("xmlns:svg", "http://www.w3.org/2000/svg");
+ mpAttrList->AddAttribute("xmlns:chart", "http://openoffice.org/2000/chart");
+ mpAttrList->AddAttribute("xmlns:dr3d", "http://openoffice.org/2000/dr3d");
+ mpAttrList->AddAttribute("xmlns:math", "http://www.w3.org/1998/Math/MathML");
+ mpAttrList->AddAttribute("xmlns:form", "http://openoffice.org/2000/form");
+ mpAttrList->AddAttribute("xmlns:script", "http://openoffice.org/2000/script");
+ mpAttrList->AddAttribute("office:class", "text");
+ mpAttrList->AddAttribute("office:version", "1.0");
+ Start_("office:document-content");
+
+ Start_("office:font-decls");
+ mpAttrList->AddAttribute("style:name","Courier New");
+ mpAttrList->AddAttribute("fo:font-family","Courier New");
+ mpAttrList->AddAttribute("style:font-pitch","fixed");
+ Start_("style:font-decl");
+ End_("style:font-decl");
+ End_("office:font-decls");
+
+ Start_("office:automatic-styles");
+
+ // Standardni text
+ mpAttrList->AddAttribute("style:name","P1");
+ mpAttrList->AddAttribute("style:family","paragraph");
+ mpAttrList->AddAttribute("style:parent-style-name","Standard");
+ Start_("style:style");
+ mpAttrList->AddAttribute("style:font-name","Courier New");
+ mpAttrList->AddAttribute("fo:font-size",OUString::createFromAscii(fs));
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // Standardni text - konec stranky
+ mpAttrList->AddAttribute("style:name","P2");
+ mpAttrList->AddAttribute("style:family","paragraph");
+ mpAttrList->AddAttribute("style:parent-style-name","Standard");
+ Start_("style:style");
+ mpAttrList->AddAttribute("style:font-name","Courier New");
+ mpAttrList->AddAttribute("fo:font-size",OUString::createFromAscii(fs));
+ mpAttrList->AddAttribute("fo:break-before","page");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T1 Normalni text
+ mpAttrList->AddAttribute("style:name","T1");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T2 Tucny text
+ mpAttrList->AddAttribute("style:name","T2");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("fo:font-weight","bold");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T3 Kurziva
+ mpAttrList->AddAttribute("style:name","T3");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("fo:font-style","italic");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T4 Siroky text
+ mpAttrList->AddAttribute("style:name","T4");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("fo:font-weight","bold");
+ mpAttrList->AddAttribute("style:text-scale","200%");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T5 Vysoky text
+ mpAttrList->AddAttribute("style:name","T5");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("fo:font-size",OUString::createFromAscii(fs2));
+ mpAttrList->AddAttribute("fo:font-weight","bold");
+ mpAttrList->AddAttribute("style:text-scale","50%");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T6 Velky text
+ mpAttrList->AddAttribute("style:name","T6");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("fo:font-size",OUString::createFromAscii(fs2));
+ mpAttrList->AddAttribute("fo:font-weight","bold");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T7 Podtrzeny text
+ mpAttrList->AddAttribute("style:name","T7");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("style:text-underline","single");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T8 Podtrzena tucny text
+ mpAttrList->AddAttribute("style:name","T8");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("fo:font-weight","bold");
+ mpAttrList->AddAttribute("style:text-underline","single");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T9 Podtrzena kurziva
+ mpAttrList->AddAttribute("style:name","T9");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("fo:font-style","italic");
+ mpAttrList->AddAttribute("style:text-underline","single");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T10 Horni index
+ mpAttrList->AddAttribute("style:name","T10");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("style:text-position","27% 100%");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ // T11 Dolni index
+ mpAttrList->AddAttribute("style:name","T11");
+ mpAttrList->AddAttribute("style:family","text");
+ Start_("style:style");
+ mpAttrList->AddAttribute("style:text-position","-27% 100%");
+ Start_("style:properties");
+ End_("style:properties");
+ End_("style:style");
+
+ End_("office:automatic-styles");
+
+ Start_("office:styles");
+ End_("office:styles");
+
+ Start_("office:body");
+
+ Read602();
+
+ End_("office:body");
+ End_("office:document-content");
+
+ mxHandler->endDocument();
+
+ return true;
+}
+
+void T602ImportFilter::test()
+{
+ Reset602();
+ Read602();
+}
+
+void T602ImportFilter::Reset602()
+{
+ node = tnode::START;
+
+ format602.mt = 0;
+ format602.mb = 0;
+ format602.tb = 0;
+ format602.ct = 0;
+ format602.pn = 1;
+ format602.lh = 1;
+ format602.lm = 6;
+ format602.rm = 60;
+ format602.pl = 60;
+
+ ini.showcomm = false;
+ ini.forcecode = false;
+ ini.xcode = KAM;
+ ini.ruscode = false;
+ ini.reformatpars= false;
+
+ fst.nowfnt = fst.oldfnt = standard;
+ fst.uline = fst.olduline = false;
+
+ pst.pars = 0;
+ pst.comment = false;
+ pst.wasspace = 0;
+ pst.ccafterln = false;
+ pst.willbeeop = false;
+ pst.waspar = false;
+ pst.wasfdash = false;
+}
+
+void T602ImportFilter::inschrdef(unsigned char ch)
+{
+ sal_Unicode xch;
+
+ if(ch > 127) {
+
+ switch(ini.xcode) {
+ case L2 : break;
+ case KOI: ch = koi2lat[ch-128]; break;
+ case KAM: ch = kam2lat[ch-128]; break;
+ default : ch = kam2lat[ch-128];
+ }
+
+ if(ini.ruscode)
+ xch = (rus2UNC[(ch-128)*2] << 8) + rus2UNC[(ch-128)*2+1];
+ else
+ xch = (lat2UNC[(ch-128)*2] << 8) + lat2UNC[(ch-128)*2+1];
+ } else
+ xch = ch;
+
+ pst.waspar = false;
+ if (mxHandler.is())
+ mxHandler->characters(OUString(xch));
+}
+
+void T602ImportFilter::wrtfnt()
+{
+ Reference < XAttributeList > xAttrList ( mpAttrList );
+ const char *style = "P1";
+
+ switch(fst.nowfnt) {
+ case standard : style = fst.uline ? "T7" : "T1"; break;
+ case fat : style = fst.uline ? "T8" : "T2"; break;
+ case cursive : style = fst.uline ? "T9" : "T3"; break;
+ case bold : style = "T4"; break;
+ case tall : style = "T5"; break;
+ case big : style = "T6"; break;
+ case lindex : style = "T11";break;
+ case hindex : style = "T10";break;
+ default : style = "T1"; break;
+ }
+
+ End_("text:span");
+ if (mpAttrList)
+ mpAttrList->AddAttribute(
+ "text:style-name", OUString::createFromAscii(style));
+ Start_("text:span");
+}
+
+void T602ImportFilter::setfnt(fonts fnt,bool mustwrite)
+{
+ if (fnt == fst.oldfnt && fnt == fst.nowfnt && !mustwrite)
+ fst.nowfnt = standard;
+ else if (fnt != chngul)
+ fst.nowfnt = fnt;
+
+ if (mustwrite && (fst.oldfnt != fst.nowfnt || fst.olduline != fst.uline))
+ {
+ wrtfnt();
+ fst.oldfnt = fst.nowfnt;
+ fst.olduline = fst.uline;
+ }
+}
+
+unsigned char T602ImportFilter::Readchar602()
+{
+ static Sequence< sal_Int8 > aData;
+
+ return (mxInputStream->readBytes(aData, 1) > 0) ?
+ reinterpret_cast<unsigned char const *>(aData.getConstArray())[0] : 0;
+}
+
+void T602ImportFilter::par602(bool endofpage)
+{
+ sal_Int16 endp;
+ Reference < XAttributeList > xAttrList ( mpAttrList );
+
+ if(!endofpage || !pst.waspar) {
+ if(ini.showcomm||!pst.comment) {
+ if(pst.waspar||ini.reformatpars) {
+ End_("text:span");
+ End_("text:p");
+ if (mpAttrList)
+ mpAttrList->AddAttribute("text:style-name", "P1");
+ Start_("text:p");
+ Start_("text:span");
+ wrtfnt();
+ } else {
+ Start_("text:line-break");
+ End_("text:line-break");
+ }
+ }
+
+ pst.waspar = true;
+ }
+
+ if(pst.comment)
+ return;
+
+ switch(format602.lh) {
+ case 3: pst.pars += 4; break;
+ case 4: pst.pars += 3; break;
+ case 6: pst.pars += 2; break;
+ default: pst.pars +=2; break;
+ }
+ endp = format602.pl-format602.mt-format602.mb;
+ if(!(((pst.pars+1)/2) >= endp || endofpage)) return;
+
+ pst.pars = 0;
+ if(!ini.reformatpars) {
+ End_("text:span");
+ End_("text:p");
+ if (mpAttrList)
+ mpAttrList->AddAttribute("text:style-name", "P2");
+ Start_("text:p");
+ Start_("text:span");
+ wrtfnt();
+ }
+}
+
+sal_Int16 T602ImportFilter::readnum(unsigned char *ch, bool show)
+{
+ unsigned char buff[21];
+ sal_Int16 i=0;
+
+ while((i<20) && *ch && (*ch!='\n') && (*ch!=','))
+ {
+ *ch = Readchar602();
+ if(show) inschr(*ch);
+ buff[i++] = *ch;
+ }
+ buff[i]='\0';
+
+ // mba: cast from unsigned char via int to sal_Int16 seems to be safe
+ return static_cast<sal_Int16>(atoi(reinterpret_cast<char const *>(buff)));
+}
+
+unsigned char T602ImportFilter::Setformat602(const char *cmd)
+{
+ unsigned char ch;
+
+ ch = Readchar602();
+
+ if (cmd[0]=='M' && cmd[1]=='T') format602.mt = readnum(&ch,false);
+ else if (cmd[0]=='M' && cmd[1]=='B') format602.mb = readnum(&ch,false);
+ // else if (cmd[0]=='T' && cmd[1]=='B') {}
+ // else if (cmd[0]=='H' && cmd[1]=='E') {}
+ // else if (cmd[0]=='F' && cmd[1]=='O') {}
+ else if (cmd[0]=='C' && cmd[1]=='T') {
+ format602.ct = readnum(&ch,false);
+ if (!ini.forcecode)
+ switch(format602.ct) {
+ case 0: ini.xcode = KAM; break;
+ case 1: ini.xcode = L2; break;
+ case 2: ini.xcode = KOI; break;
+ default: ini.xcode = KAM; break;
+ }
+ }
+ else if (cmd[0]=='P' && cmd[1]=='N') format602.pn = readnum(&ch,false);
+ else if (cmd[0]=='L' && cmd[1]=='H') format602.lh = readnum(&ch,false);
+ // else if(cmd[0]=='S' && cmd[1]=='T') {} //styl
+ else if (cmd[0]=='L' && cmd[1]=='M') format602.lm = readnum(&ch,false);
+ else if (cmd[0]=='R' && cmd[1]=='M') format602.rm = readnum(&ch,false);
+ else if (cmd[0]=='P' && cmd[1]=='L') format602.pl = readnum(&ch,false);
+ else if (cmd[0]=='P' && cmd[1]=='A') { if(pst.pars) par602(true); }
+ else if (cmd[0]=='C' && cmd[1]=='P') {
+ sal_Int16 i = readnum(&ch,false);
+ if ((i+pst.pars/2) > (format602.pl-format602.mt-format602.mb))
+ if(pst.pars) par602(true);
+ }
+ while (ch && (ch != '\n')) ch = Readchar602();
+ return ch;
+}
+
+tnode T602ImportFilter::PointCmd602(unsigned char *ch)
+{
+ char pcmd[2];
+
+ // warning: uChar -> char
+ pcmd[0] = static_cast<char>(rtl::toAsciiUpperCase(*ch)); inschr(*ch);
+ *ch = Readchar602();
+ if (!*ch) return tnode::EEND;
+ if (*ch=='\n') return tnode::EOL;
+ if (!rtl::isAsciiAlpha(*ch)) return (*ch<32) ? tnode::SETCH : tnode::WRITE;
+
+ // warning: uChar -> char
+ pcmd[1] = static_cast<char>(rtl::toAsciiUpperCase(*ch)); inschr(*ch);
+
+ if (pcmd[0]=='P' && pcmd[1]=='A') { if (pst.pars) pst.willbeeop = true; }
+ else if (pcmd[0]=='C' && pcmd[1]=='P') { if (pst.pars) pst.willbeeop = true; }
+ else if (pcmd[0]=='P' && pcmd[1]=='I') {
+ while (*ch && (*ch != '\n') && (*ch != ','))
+ { *ch = Readchar602(); inschr(*ch); }
+ if (!*ch) return tnode::EEND;
+ if (*ch=='\n') return tnode::EOL;
+ if (*ch==',') { *ch = Readchar602(); inschr(*ch); }
+ pst.pars += (readnum(ch,true)*2);
+ if (!*ch) return tnode::EEND;
+ if (*ch=='\n') return tnode::EOL;
+ }
+ // else if(pcmd[0]=='K'&&pcmd[1]=='P') {}
+ // else if(pcmd[0]=='H'&&pcmd[1]=='E') {}
+ // else if(pcmd[0]=='F'&&pcmd[1]=='O') {}
+
+ return tnode::READCH;
+}
+
+
+void T602ImportFilter::Read602()
+{
+ unsigned char ch=0;
+ char cmd602[3] = {0};
+
+ Reference < XAttributeList > xAttrList ( mpAttrList );
+
+ if (node==tnode::QUIT) return;
+
+ if (mpAttrList)
+ mpAttrList->AddAttribute("text:style-name", "P1");
+ Start_("text:p");
+ if (mpAttrList)
+ mpAttrList->AddAttribute("text:style-name", "T1");
+ Start_("text:span");
+
+ if (node==tnode::START) { node = tnode::EOL; }
+
+ while (node != tnode::EEND) {
+ switch (node) {
+ case tnode::READCH:
+ ch = Readchar602();
+ if (ch == 0) node = tnode::EEND;
+ else if (ch == '\n') {
+ if(!pst.willbeeop) par602(false);
+ node = tnode::EOL;
+ } else if (ch < 32) node = tnode::SETCH;
+ else node = tnode::WRITE;
+ break;
+ case tnode::EOL:
+ ch = Readchar602();
+ pst.comment = false;
+ if (pst.willbeeop) par602(true);
+ pst.willbeeop = false;
+ if(ch == 0) node = tnode::EEND;
+ else if (ch == '@') node = tnode::EXPCMD;
+ else if (ch == '\n') { par602(false); node = tnode::EOL; }
+ else if (ch < 32) {pst.ccafterln = true; node = tnode::SETCH; break;}
+ else node = tnode::WRITE;
+ if (ch == '.') { pst.comment = true; node = tnode::POCMD; }
+ pst.ccafterln = false;
+ break;
+
+ case tnode::POCMD: inschr('.');
+ ch = Readchar602();
+ if(ch == 0) node = tnode::EEND;
+ else if(rtl::isAsciiAlpha(ch)) node = PointCmd602(&ch);
+ else if(ch <32) node=tnode::SETCH;
+ else node = tnode::WRITE;
+ break;
+
+ case tnode::EXPCMD: ch = Readchar602();
+ if(ch == 0) {inschr('@'); node = tnode::EEND; }
+ else if(rtl::isAsciiUpperCase(ch)) {
+ cmd602[0] = ch;
+ ch = Readchar602();
+ cmd602[1] = ch;
+ cmd602[2] = '\0';
+ if(rtl::isAsciiUpperCase(ch))
+ node = tnode::SETCMD; //nedodelano
+ else {
+ inschr('@');
+ if (mxHandler.is())
+ mxHandler->characters(OUString::createFromAscii(cmd602));
+ node = tnode::READCH;
+ }
+ } else {
+ inschr('@');
+ if(ch<32) node = tnode::SETCH;
+ else node = tnode::WRITE;}
+ break;
+
+ case tnode::SETCMD:
+ ch = Setformat602(cmd602);
+ if(ch == 0) node = tnode::EEND;
+ else if(ch == '\n') node = tnode::EOL;
+ else node = tnode::READCH;
+ break;
+
+ case tnode::SETCH :
+ // warning: potentially uninitialized
+ switch(ch) {
+ case '\t' : Start_("text:tab-stop");
+ End_("text:tab-stop");
+ break;
+ case 0x03 : break; //condensed
+ case 0x01 : break; //elite
+ case 0x11 : break; //uzv1
+ case 0x12 : break; //uzv2
+ case 0x15 : break; //uzv3
+ case 0x17 : break; //uzv4
+ case 0x18 : break; //uzv5
+ case 0x19 : break; //uzv6
+ case 0x13 : fst.uline = !fst.uline;break;
+ case 0x02 : setfnt(fat,false); break;
+ case 0x04 : setfnt(cursive,false); break;
+ case 0x0f : setfnt(bold,false); break;
+ case 0x10 : setfnt(tall,false); break;
+ case 0x1d : setfnt(big,false); break;
+ case 0x14 : setfnt(hindex,false); break;
+ case 0x16 : setfnt(lindex,false); break;
+ default : break;
+ }
+ if(pst.ccafterln) node = tnode::EOL;
+ else node = tnode::READCH;
+ break;
+
+ case tnode::WRITE :
+ switch(ch) {
+ case 0x8d:
+ ch = Readchar602();
+ if( ch == 0x0a) {
+ if(ini.reformatpars) inschr(' ');
+ else par602(false); //formatovaci radek
+ node = tnode::EOL;
+ } else {
+ inschr(0x8d);//inschr(' ');
+ if(ch == 0) node = tnode::EEND;
+ else if(ch < 32) node = tnode::SETCH;
+ else node = tnode::WRITE;
+ }
+ break;
+ case 0xfe:
+ if (ini.showcomm||!pst.comment) inschr(' ');
+ node = tnode::READCH;
+ break;
+ case 0xad:
+ ch = Readchar602();
+ if( ch==0x8d ) {
+ if(ini.showcomm||!pst.comment) { //formatovaci pomlcka
+ if(!ini.reformatpars)
+ inschr('-');
+ else {
+ pst.wasspace--;
+ pst.wasfdash = true;
+ }
+ }
+ node=tnode::WRITE;
+ } else {
+ inschr(0xad);
+ if(ch == 0) node = tnode::EEND;
+ else if(ch == '\n') {
+ if(!pst.willbeeop) par602(false);
+ node = tnode::EOL; }
+ else if(ch < 32) node = tnode::SETCH;
+ else node = tnode::WRITE;
+ }
+ break;
+ default:
+ inschr(ch);
+ node = tnode::READCH;
+ break;
+ }
+ break;
+ default: break;
+ }
+ }
+
+ End_("text:span");
+ End_("text:p");
+ node = tnode::QUIT;
+}
+
+// XServiceInfo
+OUString SAL_CALL T602ImportFilter::getImplementationName( )
+{
+ return "com.sun.star.comp.Writer.T602ImportFilter";
+}
+
+sal_Bool SAL_CALL T602ImportFilter::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+Sequence< OUString > SAL_CALL T602ImportFilter::getSupportedServiceNames( )
+{
+ return { "com.sun.star.document.ImportFilter", "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+T602ImportFilterDialog::T602ImportFilterDialog()
+ : maLocale(SvtSysLocale().GetUILanguageTag())
+ , maResLocale(Translate::Create("flt"))
+{
+}
+
+T602ImportFilterDialog::~T602ImportFilterDialog()
+{
+}
+
+// XLocalizable
+
+void SAL_CALL T602ImportFilterDialog::setLocale(const Locale& rLocale)
+{
+ LanguageTag aLocale(rLocale);
+ if (maLocale != aLocale)
+ {
+ maLocale = aLocale;
+ maResLocale = Translate::Create("flt", maLocale);
+ }
+}
+
+Locale SAL_CALL T602ImportFilterDialog::getLocale()
+{
+ return maLocale.getLocale(false);
+}
+
+bool T602ImportFilterDialog::OptionsDlg()
+{
+ Any any;
+#define propInt_(_prop,_nam,_val) \
+ any <<= static_cast<sal_Int32>(_val);\
+ _prop->setPropertyValue(_nam, any);
+#define propShort_(_prop,_nam,_val) \
+ any <<= static_cast<sal_Int16>(_val);\
+ _prop->setPropertyValue(_nam, any);
+#define propBool_(_prop,_nam,_val) \
+ any <<= _val;\
+ _prop->setPropertyValue(_nam, any);
+#define propString_(_prop,_nam,_val) \
+ any <<= OUString(_val);\
+ _prop->setPropertyValue(_nam, any);
+#define propStringFromResId_(_prop,_nam,_val) \
+ any <<= getResStr(_val);\
+ _prop->setPropertyValue(_nam, any);
+#define propGet_(_prop,_nam) \
+ _prop->getPropertyValue(_nam);
+#define Inst_(_path)\
+ xMultiServiceFactory->createInstance(_path);
+#define Insert_(_cont,_nam,_obj) \
+ any <<= _obj;\
+ _cont->insertByName( _nam, any );
+
+ Reference < XComponentContext > rComponentContext = defaultBootstrap_InitialComponentContext();
+ Reference < XMultiComponentFactory > rServiceManager = rComponentContext->getServiceManager();
+ Reference < XInterface > rInstance = rServiceManager->createInstanceWithContext("com.sun.star.awt.UnoControlDialogModel", rComponentContext );
+
+ Reference <XMultiServiceFactory> xMultiServiceFactory (rInstance,UNO_QUERY);
+
+ Reference < XPropertySet > xPSetDialog( rInstance, UNO_QUERY );
+ propInt_(xPSetDialog,"PositionX",100);
+ propInt_(xPSetDialog,"PositionY",100);
+ propInt_(xPSetDialog,"Width",130);
+ propInt_(xPSetDialog,"Height",90);
+ propStringFromResId_(xPSetDialog,"Title", T602FILTER_STR_IMPORT_DIALOG_TITLE);
+
+ static constexpr OUStringLiteral T602DLG_OK_BUTTON = u"ok_button";
+ static constexpr OUStringLiteral T602DLG_CANCEL_BUTTON = u"cancel_button";
+ static constexpr OUStringLiteral T602DLG_CODE_LB = u"code_lb";
+ static constexpr OUStringLiteral T602DLG_AZBUKA_CB = u"azbuka_cb";
+ static constexpr OUStringLiteral T602DLG_COMMENT_CB = u"comment_cb";
+ static constexpr OUStringLiteral T602DLG_REFORMAT_CB = u"reformat_cb";
+ static constexpr OUStringLiteral T602DLG_CODE_TXT = u"code_txt";
+
+ Reference < XInterface > TextModel = Inst_("com.sun.star.awt.UnoControlFixedTextModel");
+ Reference < XPropertySet > xPSetText( TextModel, UNO_QUERY );
+ propInt_(xPSetText,"PositionX",10);
+ propInt_(xPSetText,"PositionY",8);
+ propInt_(xPSetText,"Width",30);
+ propInt_(xPSetText,"Height",14);
+ propString_(xPSetText,"Name",T602DLG_CODE_TXT);
+ propStringFromResId_(xPSetText,"Label",T602FILTER_STR_ENCODING_LABEL);
+
+ Reference < XInterface > ListBoxModel = Inst_("com.sun.star.awt.UnoControlListBoxModel");
+ Reference < XPropertySet > xPSetCodeLB( ListBoxModel, UNO_QUERY );
+ propInt_(xPSetCodeLB,"PositionX",40);
+ propInt_(xPSetCodeLB,"PositionY",5);
+ propInt_(xPSetCodeLB,"Width",85);
+ propInt_(xPSetCodeLB,"Height",14);
+ propString_(xPSetCodeLB,"Name",T602DLG_CODE_LB);
+ propShort_(xPSetCodeLB,"TabIndex",1);
+ propBool_(xPSetCodeLB,"Dropdown",true);
+ propBool_(xPSetCodeLB,"MultiSelection",false);
+
+ Sequence< OUString > ous
+ {
+ getResStr(T602FILTER_STR_ENCODING_AUTO),
+ getResStr(T602FILTER_STR_ENCODING_CP852),
+ getResStr(T602FILTER_STR_ENCODING_CP895),
+ getResStr(T602FILTER_STR_ENCODING_KOI8CS2)
+ };
+ any <<= ous;
+ xPSetCodeLB->setPropertyValue("StringItemList", any);
+
+ Sequence < sal_Int16 > shr{ static_cast<sal_Int16>(ini.forcecode ? ini.xcode + 1 : 0) };
+ any <<= shr;
+ xPSetCodeLB->setPropertyValue("SelectedItems", any);
+
+ Reference < XInterface > AzbCheckBoxModel = Inst_("com.sun.star.awt.UnoControlCheckBoxModel");
+ Reference < XPropertySet > xPSetAzbukaCB( AzbCheckBoxModel, UNO_QUERY );
+ propInt_(xPSetAzbukaCB,"PositionX",10);
+ propInt_(xPSetAzbukaCB,"PositionY",25);
+ propInt_(xPSetAzbukaCB,"Width",100);
+ propInt_(xPSetAzbukaCB,"Height",14);
+ propString_(xPSetAzbukaCB,"Name",T602DLG_AZBUKA_CB);
+ propShort_(xPSetAzbukaCB,"TabIndex",2);
+ propStringFromResId_(xPSetAzbukaCB,"Label",T602FILTER_STR_CYRILLIC_MODE);
+ propShort_(xPSetAzbukaCB,"State",ini.ruscode);
+
+ Reference < XInterface > RefCheckBoxModel = Inst_("com.sun.star.awt.UnoControlCheckBoxModel");
+ Reference < XPropertySet > xPSetRefCB( RefCheckBoxModel, UNO_QUERY );
+ propInt_(xPSetRefCB,"PositionX",10);
+ propInt_(xPSetRefCB,"PositionY",40);
+ propInt_(xPSetRefCB,"Width",100);
+ propInt_(xPSetRefCB,"Height",14);
+ propString_(xPSetRefCB,"Name",T602DLG_REFORMAT_CB);
+ propShort_(xPSetRefCB,"TabIndex",3);
+ propStringFromResId_(xPSetRefCB,"Label",T602FILTER_STR_REFORMAT_TEXT);
+ propShort_(xPSetRefCB,"State",ini.reformatpars);
+
+ Reference < XInterface > CommCheckBoxModel = Inst_("com.sun.star.awt.UnoControlCheckBoxModel");
+ Reference < XPropertySet > xPSetCommCB( CommCheckBoxModel, UNO_QUERY );
+ propInt_(xPSetCommCB,"PositionX",10);
+ propInt_(xPSetCommCB,"PositionY",55);
+ propInt_(xPSetCommCB,"Width",100);
+ propInt_(xPSetCommCB,"Height",14);
+ propString_(xPSetCommCB,"Name",T602DLG_COMMENT_CB);
+ propShort_(xPSetCommCB,"TabIndex",4);
+ propStringFromResId_(xPSetCommCB,"Label",T602FILTER_STR_DOT_COMMANDS);
+ propShort_(xPSetCommCB,"State",ini.showcomm);
+
+ Reference < XInterface > CancelButtonModel = Inst_("com.sun.star.awt.UnoControlButtonModel");
+ Reference < XPropertySet > xPSetCancelButton( CancelButtonModel, UNO_QUERY );
+ propInt_(xPSetCancelButton,"PositionX",10);
+ propInt_(xPSetCancelButton,"PositionY",70);
+ propInt_(xPSetCancelButton,"Width",50);
+ propInt_(xPSetCancelButton,"Height",14);
+ propString_(xPSetCancelButton,"Name",T602DLG_CANCEL_BUTTON);
+ propShort_(xPSetCancelButton,"TabIndex",5);
+ propShort_(xPSetCancelButton,"PushButtonType",2);
+ propStringFromResId_(xPSetCancelButton,"Label",T602FILTER_STR_CANCEL_BUTTON);
+
+ Reference < XInterface > OkButtonModel = Inst_("com.sun.star.awt.UnoControlButtonModel");
+ Reference < XPropertySet > xPSetOkButton( OkButtonModel, UNO_QUERY );
+ propInt_(xPSetOkButton,"PositionX",70);
+ propInt_(xPSetOkButton,"PositionY",70);
+ propInt_(xPSetOkButton,"Width",50);
+ propInt_(xPSetOkButton,"Height",14);
+ propString_(xPSetOkButton,"Name",T602DLG_OK_BUTTON);
+ propShort_(xPSetOkButton,"TabIndex",0);
+ propShort_(xPSetOkButton,"PushButtonType",1);
+ propStringFromResId_(xPSetOkButton,"Label",T602FILTER_STR_OK_BUTTON);
+ propBool_(xPSetOkButton,"DefaultButton",true);
+
+ Reference < XNameContainer > xNameCont (rInstance,UNO_QUERY);
+
+ Insert_(xNameCont, T602DLG_OK_BUTTON, OkButtonModel);
+ Insert_(xNameCont, T602DLG_CANCEL_BUTTON, CancelButtonModel);
+ Insert_(xNameCont, T602DLG_AZBUKA_CB, AzbCheckBoxModel);
+ Insert_(xNameCont, T602DLG_REFORMAT_CB, RefCheckBoxModel);
+ Insert_(xNameCont, T602DLG_COMMENT_CB, CommCheckBoxModel);
+ Insert_(xNameCont, T602DLG_CODE_LB, ListBoxModel);
+ Insert_(xNameCont, T602DLG_CODE_TXT, TextModel);
+
+ Reference< XUnoControlDialog > dialog = UnoControlDialog::create(rComponentContext);
+
+ Reference < XControlModel > xControlModel (rInstance,UNO_QUERY);
+
+ dialog->setModel( xControlModel );
+
+ Reference < XToolkit > xToolkit = Toolkit::create( rComponentContext );
+
+ dialog->setVisible( false );
+ dialog->createPeer( xToolkit, nullptr );
+
+ bool ret = ( dialog->execute() != 0 );
+ if ( ret ) {
+
+ sal_Int16 tt = 0;
+
+ any = propGet_(xPSetAzbukaCB, "State"); any >>= tt; ini.ruscode = tt;
+ any = propGet_(xPSetRefCB, "State"); any >>= tt; ini.reformatpars = tt;
+ any = propGet_(xPSetCommCB, "State"); any >>= tt; ini.showcomm = tt;
+
+ any = propGet_(xPSetCodeLB, "SelectedItems"); any >>= shr;
+
+ if( shr[0] > 0 ) {
+ ini.xcode = static_cast<tcode>(shr[0]-1);
+ ini.forcecode = true;
+ } else {
+ ini.forcecode = false;
+ }
+ }
+
+ Reference<XControl>(dialog)->dispose();
+
+ return ret;
+}
+
+void SAL_CALL T602ImportFilterDialog::setTitle( const OUString& )
+{
+}
+
+sal_Int16 SAL_CALL T602ImportFilterDialog::execute()
+{
+ if (OptionsDlg())
+ return css::ui::dialogs::ExecutableDialogResults::OK;
+ else
+ return css::ui::dialogs::ExecutableDialogResults::CANCEL;
+}
+
+OUString T602ImportFilterDialog::getResStr(TranslateId resid)
+{
+ return Translate::get(resid, maResLocale);
+}
+
+uno::Sequence<beans::PropertyValue> SAL_CALL T602ImportFilterDialog::getPropertyValues()
+{
+ return uno::Sequence<beans::PropertyValue>();
+}
+
+void SAL_CALL T602ImportFilterDialog::setPropertyValues( const uno::Sequence<beans::PropertyValue>& )
+{
+}
+
+
+// XServiceInfo
+OUString SAL_CALL T602ImportFilterDialog::getImplementationName( )
+{
+ return "com.sun.star.comp.Writer.T602ImportFilterDialog";
+}
+
+sal_Bool SAL_CALL T602ImportFilterDialog::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+Sequence< OUString > SAL_CALL T602ImportFilterDialog::getSupportedServiceNames( )
+{
+ return { "com.sun.star.ui.dialogs.FilterOptionsDialog" };
+}
+
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_T602ImportFilterDialog_get_implementation(
+ css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new T602ImportFilter::T602ImportFilterDialog());
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_T602ImportFilter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new T602ImportFilter::T602ImportFilter(context));
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT bool TestImport602(SvStream &rStream)
+{
+ css::uno::Reference<io::XInputStream> xStream(new utl::OSeekableInputStreamWrapper(rStream));
+ rtl::Reference<T602ImportFilter::T602ImportFilter> aImport(
+ new T602ImportFilter::T602ImportFilter(xStream));
+ aImport->test();
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/t602/t602filter.hxx b/filter/source/t602/t602filter.hxx
new file mode 100644
index 000000000..26fa088fa
--- /dev/null
+++ b/filter/source/t602/t602filter.hxx
@@ -0,0 +1,255 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XLocalizable.hpp>
+#include <com/sun/star/beans/XPropertyAccess.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <xmloff/attrlist.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <rtl/ref.hxx>
+#include <unotools/resmgr.hxx>
+
+namespace T602ImportFilter {
+
+typedef enum {L2,KAM,KOI} tcode;
+
+typedef enum {
+ standard, // default
+ fat, // bold
+ cursive, // italic
+ bold, // wide
+ tall, // high
+ big, // big
+ lindex, // lower index
+ hindex, // upper index
+ err, // not set yet
+ chngul // change underline
+} fonts;
+
+enum class tnode {START,READCH,EOL,POCMD,EXPCMD,SETCMD,SETCH,WRITE,EEND,QUIT};
+
+
+
+struct inistruct
+{
+ bool showcomm; // true show comment lines
+ bool forcecode; // false the user has changed the encoding with something else than @CT
+ tcode xcode; // KAM encoding set - forced
+ bool ruscode; // false Russian tables turned on
+ bool reformatpars; // false Reformat paragraphs (whitespaces and line breaks)
+ static const sal_Int16 fontsize = 10; // font size in points
+
+ inistruct()
+ : showcomm( true )
+ , forcecode( false )
+ , xcode ( KAM )
+ , ruscode ( false )
+ , reformatpars ( false )
+ {
+ };
+};
+
+class T602ImportFilterDialog : public cppu::WeakImplHelper <
+ css::ui::dialogs::XExecutableDialog,
+ css::lang::XLocalizable,
+ css::lang::XServiceInfo,
+ css::beans::XPropertyAccess
+>
+{
+ LanguageTag maLocale;
+ std::locale maResLocale;
+ bool OptionsDlg();
+ OUString getResStr(TranslateId resid);
+
+ virtual ~T602ImportFilterDialog() override;
+
+ // XExecutableDialog
+ virtual void SAL_CALL setTitle( const OUString& aTitle ) override;
+ virtual sal_Int16 SAL_CALL execute() override;
+
+ // XLocalizable
+ virtual void SAL_CALL setLocale( const css::lang::Locale& eLocale ) override;
+ virtual css::lang::Locale SAL_CALL getLocale() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XPropertyAccess
+ virtual css::uno::Sequence< css::beans::PropertyValue >
+ SAL_CALL getPropertyValues() override;
+ virtual void SAL_CALL setPropertyValues( const css::uno::Sequence<
+ css::beans::PropertyValue >& aProps ) override;
+
+public:
+ explicit T602ImportFilterDialog();
+
+};
+
+
+class T602ImportFilter : public cppu::WeakImplHelper <
+ css::document::XFilter,
+ css::document::XImporter,
+ css::document::XExtendedFilterDetection,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo
+>
+{
+private:
+ css::uno::Reference<css::xml::sax::XDocumentHandler> mxHandler;
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::lang::XComponent > mxDoc;
+ css::uno::Reference < css::io::XInputStream > mxInputStream;
+
+ rtl::Reference<SvXMLAttributeList> mpAttrList;
+
+ tnode node; // START
+
+ struct format602struct
+ {
+ sal_Int16 mt; // row for header
+ sal_Int16 mb; // row for footer
+ sal_Int16 tb; // tabs
+ sal_Int16 ct; // encoding (0-kamenik, 1-latin2, 2-koi8)
+ sal_Int16 pn; // from page number
+ sal_Int16 lh; // linespacing 3-2x, 4-1.5x, 6-1x
+ sal_Int16 lm; // left border
+ sal_Int16 rm; // right border
+ sal_Int16 pl; // page length
+ format602struct()
+ : mt(0)
+ , mb(0)
+ , tb(0)
+ , ct(0)
+ , pn(0)
+ , lh(0)
+ , lm(0)
+ , rm(0)
+ , pl(0)
+ {
+ }
+ };
+
+ format602struct format602;
+
+ // Initialisation constants - they are not changed during the conversion
+
+ inistruct ini;
+
+ // Font state - changes based on font
+
+ struct fststruct
+ {
+ fonts nowfnt; // current font
+ fonts oldfnt; // previous font
+ bool uline; // underlined
+ bool olduline; // previous value of uline (font change)
+ fststruct()
+ : nowfnt(standard)
+ , oldfnt(standard)
+ , uline(false)
+ , olduline(false)
+ {
+ }
+ };
+
+ fststruct fst;
+
+ // Paragraph state
+
+ struct pststruct
+ {
+ sal_Int16 pars; // the number of line endings times linespacing on the current page
+ bool comment; // in comments
+ sal_Int16 wasspace; // 0 there was a space - for reformatting
+ bool wasfdash; // 0 formatting dash
+ bool ccafterln; // false
+ bool willbeeop; // false
+ bool waspar; // false
+ pststruct()
+ : pars(0)
+ , comment(false)
+ , wasspace(0)
+ , wasfdash(false)
+ , ccafterln(false)
+ , willbeeop(false)
+ , waspar(false)
+ {
+ }
+ };
+
+ pststruct pst;
+
+ void Reset602();
+ unsigned char Readchar602();
+ void Read602();
+ void par602(bool endofpage);
+ void inschr(unsigned char ch);
+ void inschrdef(unsigned char ch);
+ unsigned char Setformat602(const char *cmd);
+ sal_Int16 readnum(unsigned char *ch, bool show);
+ tnode PointCmd602(unsigned char *ch);
+ void setfnt(fonts fnt,bool mustwrite);
+ void wrtfnt();
+
+ /// @throws css::uno::RuntimeException
+ bool importImpl( const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor );
+
+ public:
+ explicit T602ImportFilter(css::uno::Reference<css::uno::XComponentContext > x );
+ explicit T602ImportFilter(css::uno::Reference<css::io::XInputStream> xInputStream);
+ virtual ~T602ImportFilter() override;
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor ) override;
+ virtual void SAL_CALL cancel( ) override {};
+
+ // XImporter
+ virtual void SAL_CALL setTargetDocument( const css::uno::Reference< css::lang::XComponent >& xDoc ) override;
+
+ // XExtendedTypeDetection
+ virtual OUString SAL_CALL detect(
+ css::uno::Sequence< css::beans::PropertyValue >& Descriptor ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ void test();
+};
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/textfilterdetect/filterdetect.cxx b/filter/source/textfilterdetect/filterdetect.cxx
new file mode 100644
index 000000000..9d25e289e
--- /dev/null
+++ b/filter/source/textfilterdetect/filterdetect.cxx
@@ -0,0 +1,247 @@
+/* -*- 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 "filterdetect.hxx"
+
+#include <svtools/htmltokn.h>
+#include <tools/urlobj.hxx>
+#include <tools/zcodec.hxx>
+#include <ucbhelper/content.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <memory>
+
+constexpr OUStringLiteral WRITER_TEXT_FILTER = u"Text";
+constexpr OUStringLiteral CALC_TEXT_FILTER = u"Text - txt - csv (StarCalc)";
+
+constexpr OUStringLiteral WEB_HTML_FILTER = u"HTML";
+constexpr OUStringLiteral WRITER_HTML_FILTER = u"HTML (StarWriter)";
+constexpr OUStringLiteral CALC_HTML_FILTER = u"calc_HTML_WebQuery";
+
+constexpr OUStringLiteral WRITER_DOCSERVICE = u"com.sun.star.text.TextDocument";
+constexpr OUStringLiteral CALC_DOCSERVICE = u"com.sun.star.sheet.SpreadsheetDocument";
+
+using namespace ::com::sun::star;
+using utl::MediaDescriptor;
+
+namespace {
+
+bool IsHTMLStream( const uno::Reference<io::XInputStream>& xInStream )
+{
+ std::unique_ptr<SvStream> pInStream( utl::UcbStreamHelper::CreateStream( xInStream ) );
+ if ( !pInStream || pInStream->GetError() )
+ // No stream
+ return false;
+
+ // Read the stream header
+ pInStream->StartReadingUnicodeText( RTL_TEXTENCODING_DONTKNOW );
+ const sal_uInt64 nUniPos = pInStream->Tell();
+ const sal_uInt16 nSize = 4096;
+
+ OString sHeader;
+ if ( nUniPos == 3 || nUniPos == 0 ) // UTF-8 or non-Unicode
+ sHeader = read_uInt8s_ToOString( *pInStream, nSize );
+ else // UTF-16 (nUniPos = 2)
+ sHeader = OUStringToOString( read_uInt16s_ToOUString( *pInStream, nSize ), RTL_TEXTENCODING_ASCII_US );
+
+ // Now check whether the stream begins with a known HTML tag.
+ enum DetectPhase { BeforeTag, TagOpened, InTagName };
+ DetectPhase dp = BeforeTag;
+ /// BeforeDeclaration -> ? -> DeclarationOpened -> > -> BeforeDeclaration.
+ enum DeclarationPhase
+ {
+ BeforeDeclaration,
+ DeclarationOpened
+ };
+ DeclarationPhase eDeclaration = BeforeDeclaration;
+
+ const char* pHeader = sHeader.getStr();
+ const int nLength = sHeader.getLength();
+ int i = 0, nStartOfTagIndex = 0;
+
+ for ( i = 0; i < nLength; ++i, ++pHeader )
+ {
+ char c = *pHeader;
+ if ((c == ' ' || c == '\n' || c == '\t' || c == '\r' || c == '\f')
+ && eDeclaration == BeforeDeclaration)
+ {
+ if ( dp == TagOpened )
+ return false; // Invalid: Should start with a tag name
+ else if ( dp == InTagName )
+ break; // End of tag name reached
+ }
+ else if ( c == '<' )
+ {
+ if ( dp == BeforeTag )
+ dp = TagOpened;
+ else
+ return false; // Invalid: Nested '<'
+ }
+ else if ( c == '>' )
+ {
+ if ( dp == InTagName )
+ break; // End of tag name reached
+ else if (eDeclaration == DeclarationOpened)
+ {
+ dp = BeforeTag;
+ eDeclaration = BeforeDeclaration;
+ }
+ else
+ return false; // Invalid: Empty tag or before '<'
+ }
+ else if ( c == '!' )
+ {
+ if ( dp == TagOpened )
+ return true; // "<!" - DOCTYPE or comments block
+ else
+ return false; // Invalid: '!' before '<' or inside tag name
+ }
+ else
+ {
+ if ( dp == BeforeTag )
+ return false; // Invalid: Should start with a tag
+ else if ( dp == TagOpened )
+ {
+ if (c == '?' && eDeclaration == BeforeDeclaration)
+ eDeclaration = DeclarationOpened;
+ else if (eDeclaration == BeforeDeclaration)
+ {
+ nStartOfTagIndex = i;
+ dp = InTagName;
+ }
+ }
+ }
+ }
+
+ // The string following '<' has to be a known HTML token.
+ OString aToken = sHeader.copy( nStartOfTagIndex, i - nStartOfTagIndex );
+ return GetHTMLToken( OStringToOUString( aToken.toAsciiLowerCase(), RTL_TEXTENCODING_ASCII_US ) ) != HtmlTokenId::NONE;
+}
+}
+
+PlainTextFilterDetect::PlainTextFilterDetect() {}
+
+PlainTextFilterDetect::~PlainTextFilterDetect() {}
+
+OUString SAL_CALL PlainTextFilterDetect::detect(uno::Sequence<beans::PropertyValue>& lDescriptor)
+{
+ MediaDescriptor aMediaDesc(lDescriptor);
+
+ OUString aType = aMediaDesc.getUnpackedValueOrDefault(MediaDescriptor::PROP_TYPENAME, OUString() );
+ OUString aDocService = aMediaDesc.getUnpackedValueOrDefault(MediaDescriptor::PROP_DOCUMENTSERVICE, OUString() );
+
+ if ((aType == "generic_HTML") || (aType == "calc_HTML"))
+ {
+ uno::Reference<io::XInputStream> xInStream(aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM], uno::UNO_QUERY);
+ if (!xInStream.is() || !IsHTMLStream(xInStream))
+ return OUString();
+
+ if ((aDocService == CALC_DOCSERVICE) || (aType == "calc_HTML"))
+ aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= OUString(CALC_HTML_FILTER);
+ else if (aDocService == WRITER_DOCSERVICE)
+ aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= OUString(WRITER_HTML_FILTER);
+ else
+ aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= OUString(WEB_HTML_FILTER);
+ }
+
+ else if (aType == "generic_Text")
+ {
+ uno::Reference<io::XStream> xStream(aMediaDesc[MediaDescriptor::PROP_STREAM], uno::UNO_QUERY);
+ uno::Reference<io::XInputStream> xInStream(aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM], uno::UNO_QUERY);
+ if (xStream.is() || xInStream.is())
+ {
+ ZCodec aCodecGZ;
+ std::unique_ptr<SvStream> pInStream;
+ if (xStream.is())
+ pInStream = utl::UcbStreamHelper::CreateStream(xStream);
+ else
+ pInStream = utl::UcbStreamHelper::CreateStream(xInStream);
+ std::unique_ptr<SvMemoryStream> pDecompressedStream(new SvMemoryStream());
+ if (aCodecGZ.AttemptDecompression(*pInStream, *pDecompressedStream))
+ {
+ uno::Reference<io::XStream> xStreamDecompressed(new utl::OStreamWrapper(std::move(pDecompressedStream)));
+ aMediaDesc[MediaDescriptor::PROP_STREAM] <<= xStreamDecompressed;
+ aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM] <<= xStreamDecompressed->getInputStream();
+ OUString aURL = aMediaDesc.getUnpackedValueOrDefault(MediaDescriptor::PROP_URL, OUString() );
+ sal_Int32 nIdx = aURL.lastIndexOf(".gz");
+ if (nIdx != -1)
+ aMediaDesc[MediaDescriptor::PROP_URL] <<= aURL.copy(0, nIdx);
+ }
+ }
+ // Get the file name extension.
+ INetURLObject aParser(aMediaDesc.getUnpackedValueOrDefault(MediaDescriptor::PROP_URL, OUString() ) );
+ OUString aExt = aParser.getExtension(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset);
+ aExt = aExt.toAsciiLowerCase();
+ OUString aName = aParser.getName().toAsciiLowerCase();
+
+ // Decide which filter to use based on the document service first,
+ // then on extension if that's not available.
+
+ if (aDocService == CALC_DOCSERVICE)
+ aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= OUString(CALC_TEXT_FILTER);
+ else if (aDocService == WRITER_DOCSERVICE)
+ aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= OUString(WRITER_TEXT_FILTER);
+ else if (aExt == "csv" || aExt == "tsv" || aExt == "tab" || aExt == "xls" || aName.endsWith(".csv.gz"))
+ aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= OUString(CALC_TEXT_FILTER);
+ else
+ aMediaDesc[MediaDescriptor::PROP_FILTERNAME] <<= OUString(WRITER_TEXT_FILTER);
+ }
+
+ else
+ // Nothing to detect.
+ return OUString();
+
+ aMediaDesc >> lDescriptor;
+ return aType;
+}
+
+// XInitialization
+
+void SAL_CALL PlainTextFilterDetect::initialize(const uno::Sequence<uno::Any>& /*aArguments*/)
+{
+}
+
+OUString PlainTextFilterDetect_getImplementationName()
+{
+ return "com.sun.star.comp.filters.PlainTextFilterDetect";
+}
+
+uno::Sequence<OUString> PlainTextFilterDetect_getSupportedServiceNames()
+{
+ return { "com.sun.star.document.ExtendedTypeDetection", "com.sun.star.comp.filters.PlainTextFilterDetect" };
+}
+
+// XServiceInfo
+OUString SAL_CALL PlainTextFilterDetect::getImplementationName()
+{
+ return PlainTextFilterDetect_getImplementationName();
+}
+
+sal_Bool SAL_CALL PlainTextFilterDetect::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL PlainTextFilterDetect::getSupportedServiceNames()
+{
+ return PlainTextFilterDetect_getSupportedServiceNames();
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+com_sun_star_comp_filters_PlainTextFilterDetect_get_implementation(css::uno::XComponentContext* ,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ return cppu::acquire(new PlainTextFilterDetect);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/textfilterdetect/filterdetect.hxx b/filter/source/textfilterdetect/filterdetect.hxx
new file mode 100644
index 000000000..a981d869f
--- /dev/null
+++ b/filter/source/textfilterdetect/filterdetect.hxx
@@ -0,0 +1,59 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <cppuhelper/implbase.hxx>
+
+class PlainTextFilterDetect : public cppu::WeakImplHelper<
+ css::document::XExtendedFilterDetection,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo>
+{
+public:
+
+ PlainTextFilterDetect();
+ virtual ~PlainTextFilterDetect() override;
+
+ // XExtendedFilterDetection
+
+ virtual OUString SAL_CALL detect(css::uno::Sequence<css::beans::PropertyValue>& lDescriptor) override;
+
+ // XInitialization
+
+ virtual void SAL_CALL initialize( const css::uno::Sequence<css::uno::Any>& aArguments) override;
+
+ // XServiceInfo
+
+ virtual OUString SAL_CALL getImplementationName() override;
+
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
+};
+
+OUString PlainTextFilterDetect_getImplementationName();
+
+css::uno::Sequence<OUString> PlainTextFilterDetect_getSupportedServiceNames();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/textfilterdetect/textfd.component b/filter/source/textfilterdetect/textfd.component
new file mode 100644
index 000000000..1617f4b2f
--- /dev/null
+++ b/filter/source/textfilterdetect/textfd.component
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.filters.PlainTextFilterDetect"
+ constructor="com_sun_star_comp_filters_PlainTextFilterDetect_get_implementation">
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ <service name="com.sun.star.comp.filters.PlainTextFilterDetect"/>
+ </implementation>
+</component>
diff --git a/filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx b/filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx
new file mode 100644
index 000000000..93c6c892f
--- /dev/null
+++ b/filter/source/xmlfilteradaptor/XmlFilterAdaptor.cxx
@@ -0,0 +1,391 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <iostream>
+#include <rtl/ustring.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include "XmlFilterAdaptor.hxx"
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/xml/XImportFilter.hpp>
+#include <com/sun/star/xml/XImportFilter2.hpp>
+#include <com/sun/star/xml/XExportFilter.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/style/XStyleLoader.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <comphelper/fileurl.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <unotools/mediadescriptor.hxx>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <comphelper/genericpropertyset.hxx>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/scopeguard.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <unotools/pathoptions.hxx>
+#include <xmloff/xmlimp.hxx>
+
+using namespace comphelper;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::io;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+using namespace com::sun::star::document;
+using namespace com::sun::star::style;
+using namespace com::sun::star::xml;
+using namespace com::sun::star::xml::sax;
+using namespace com::sun::star::frame;
+using namespace ::com::sun::star::task;
+
+bool XmlFilterAdaptor::importImpl( const Sequence< css::beans::PropertyValue >& aDescriptor )
+{
+ OUString udConvertClass = msUserData[0];
+ const OUString sXMLImportService = msUserData[2];
+ sal_Int32 nSteps= 0;
+
+ utl::MediaDescriptor aMediaMap(aDescriptor);
+ Reference< XStatusIndicator > xStatusIndicator(aMediaMap.getUnpackedValueOrDefault(
+ utl::MediaDescriptor::PROP_STATUSINDICATOR, Reference< XStatusIndicator >()));
+
+ if (xStatusIndicator.is()){
+ xStatusIndicator->start( "Loading :", 4);
+ }
+
+ OUString aBaseURI;
+ if (aMediaMap.find(OUString( "URL" ))->second >>= aBaseURI)
+ {
+ INetURLObject aURLObj(aBaseURI);
+ // base URI in this case is the URI of the actual saving location
+ // aURLObj.removeSegment();
+ aBaseURI = aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ }
+
+ // create an XProperty set to configure the exporter for pretty printing
+ static const PropertyMapEntry aImportInfoMap[] =
+ {
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), PropertyAttribute::MAYBEVOID, 0},
+ { OUString("BuildId"), 0, ::cppu::UnoType<OUString>::get(), PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("DefaultDocumentSettings"), 0,
+ ::cppu::UnoType<Sequence<PropertyValue>>::get(), PropertyAttribute::MAYBEVOID, 0 },
+ };
+
+ Reference< XPropertySet > xInfoSet(
+ GenericPropertySet_CreateInstance( new PropertySetInfo( aImportInfoMap ) ) );
+ xInfoSet->setPropertyValue( "BaseURI", Any( aBaseURI ));
+
+ OUString aFilterName;
+ auto It = aMediaMap.find(OUString("FilterName"));
+ if (It != aMediaMap.end() && (It->second >>= aFilterName)
+ && aFilterName == "OpenDocument Text Flat XML")
+ {
+ PropertyValue EmptyDbFieldHidesPara("EmptyDbFieldHidesPara", 0, Any(false),
+ PropertyState::PropertyState_DIRECT_VALUE);
+ Sequence<PropertyValue> aSettings{ EmptyDbFieldHidesPara };
+ xInfoSet->setPropertyValue("DefaultDocumentSettings", Any(aSettings));
+ }
+ Sequence< Any > aAnys{ Any(xInfoSet) };
+
+
+ // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler
+ // ...except when it's one of the XMLTransformer subclasses
+ Reference < XInterface > xFilter = mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( sXMLImportService, aAnys, mxContext );
+ assert(xFilter);
+ Reference < XImporter > xImporter( xFilter, UNO_QUERY );
+ assert(xImporter);
+ xImporter->setTargetDocument ( mxDoc );
+
+ if (xStatusIndicator.is()){
+ xStatusIndicator->setValue(nSteps++);
+ }
+
+
+ // Creating a ConverterBridge instance
+
+ Reference< XInterface > xConvBridge(
+ mxContext->getServiceManager()->createInstanceWithContext(udConvertClass, mxContext), UNO_QUERY);
+ if (!xConvBridge.is()) {
+ SAL_WARN("filter.xmlfa", "XmlFilterAdaptor: unable to create service " << udConvertClass);
+ return false;
+ }
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ Reference< XImportFilter > xConverter1( xConvBridge, UNO_QUERY );
+ Reference< XImportFilter2 > xConverter2( xConvBridge, UNO_QUERY );
+
+ // prevent unnecessary broadcasting when loading
+ Reference< XModel > xModel( mxDoc, UNO_QUERY );
+ if( xModel.is() )
+ xModel->lockControllers();
+ comphelper::ScopeGuard guard([&]() {
+ // cleanup when leaving
+ if( xModel.is() )
+ xModel->unlockControllers();
+ });
+
+ //Template Loading if Required
+
+ if (!msTemplateName.isEmpty()){
+ Reference< XStyleFamiliesSupplier > xstylefamiliessupplier(mxDoc, UNO_QUERY);
+ Reference< XStyleLoader > xstyleLoader (xstylefamiliessupplier->getStyleFamilies(), UNO_QUERY);
+ if(xstyleLoader.is()){
+ Sequence<css::beans::PropertyValue> aValue = xstyleLoader->getStyleLoaderOptions();
+
+ //Load the Styles from the Template URL Supplied in the TypeDetection file
+ if(!comphelper::isFileUrl(msTemplateName))
+ {
+ SvtPathOptions aOptions;
+ msTemplateName = aOptions.SubstituteVariable("$(progurl)") + "/" + msTemplateName;
+ }
+
+ xstyleLoader->loadStylesFromURL(msTemplateName,aValue);
+ }
+ }
+
+ if (xStatusIndicator.is()){
+ xStatusIndicator->setValue(nSteps++);
+ }
+
+ // Calling Filtering Component
+
+ try {
+ Reference < XFastParser > xFastParser( xFilter, UNO_QUERY ); // SvXMLImport subclasses
+ Reference < XDocumentHandler > xDocHandler( xFilter, UNO_QUERY ); // XMLTransformer subclasses
+ assert(xFastParser || xDocHandler);
+ if (xConverter2 && xFastParser)
+ {
+ if (!xConverter2->importer(aDescriptor,xFastParser,msUserData)) {
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return false;
+ }
+ }
+ else if (xConverter1 && xDocHandler)
+ {
+ if (!xConverter1->importer(aDescriptor,xDocHandler,msUserData)) {
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return false;
+ }
+ }
+ else if (xConverter1 && xFastParser)
+ {
+ auto pImport = static_cast<SvXMLImport*>(xFastParser.get());
+ Reference<XDocumentHandler> xLegacyDocHandler = new SvXMLLegacyToFastDocHandler(pImport);
+ if (!xConverter1->importer(aDescriptor,xLegacyDocHandler,msUserData)) {
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return false;
+ }
+ }
+ else
+ {
+ SAL_WARN("filter.xmlfa", "no working combination found");
+ assert(false);
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return false;
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xmlfa", "XmlFilterAdaptor");
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return false;
+ }
+ if (xStatusIndicator.is()) {
+ xStatusIndicator->setValue(nSteps++);
+ xStatusIndicator->end();
+ }
+ return true;
+}
+
+bool XmlFilterAdaptor::exportImpl( const Sequence< css::beans::PropertyValue >& aDescriptor )
+{
+
+ OUString udConvertClass = msUserData[0];
+ OUString udExport = msUserData[3];
+
+ // Status Bar
+ sal_Int32 nSteps= 1;
+ utl::MediaDescriptor aMediaMap(aDescriptor);
+ Reference< XStatusIndicator > xStatusIndicator(aMediaMap.getUnpackedValueOrDefault(
+ utl::MediaDescriptor::PROP_STATUSINDICATOR, Reference< XStatusIndicator >()));
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->start( "Saving :", 3);
+
+ // Set up converter bridge.
+ Reference< css::xml::XExportFilter > xConverter(mxContext->getServiceManager()->createInstanceWithContext( udConvertClass, mxContext ), UNO_QUERY);
+ if (!xConverter.is()) {
+ SAL_WARN("filter.xmlfa", "XmlFilterAdaptor: unable to create service " << udConvertClass);
+ return false;
+ }
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ //put filter component into exporting state
+ if (!xConverter->exporter(aDescriptor, msUserData)) {
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return false;
+ }
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ try{
+ // create the xml exporter service and supply the converter component
+ // which implements the document handler
+
+ // pretty printing is confusing for some filters so it is disabled by default
+ bool bPrettyPrint =
+ (msUserData.getLength() > 6 && msUserData[6].equalsIgnoreAsciiCase("true"));
+
+ // export of <text:number> element for <text:list-item> elements are
+ // needed for certain filters.
+ bool bExportTextNumberElementForListItems =
+ ( msUserData.getLength() > 7 &&
+ msUserData[7].equalsIgnoreAsciiCase("true") );
+
+ // get the base URI, so we can use relative links
+ OUString aBaseURI;
+ if (aMediaMap.find(OUString( "URL" ))->second >>= aBaseURI)
+ {
+ INetURLObject aURLObj(aBaseURI);
+ // base URI in this case is the URI of the actual saving location
+ // aURLObj.removeSegment();
+ aBaseURI = aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ }
+
+ // create an XProperty set to configure the exporter for pretty printing
+ static const PropertyMapEntry aImportInfoMap[] =
+ {
+ { OUString("UsePrettyPrinting"), 0, cppu::UnoType<sal_Bool>::get(), PropertyAttribute::MAYBEVOID, 0},
+ { OUString("ExportTextNumberElement"), 0, cppu::UnoType<sal_Bool>::get(), PropertyAttribute::MAYBEVOID, 0},
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), PropertyAttribute::MAYBEVOID, 0},
+ };
+
+ Reference< XPropertySet > xInfoSet(
+ GenericPropertySet_CreateInstance( new PropertySetInfo( aImportInfoMap ) ) );
+ xInfoSet->setPropertyValue("UsePrettyPrinting", Any( bPrettyPrint ));
+ xInfoSet->setPropertyValue(
+ "ExportTextNumberElement",
+ Any( bExportTextNumberElementForListItems ));
+ xInfoSet->setPropertyValue("BaseURI", Any( aBaseURI ));
+ Sequence < Any > aAnys{ Any(xConverter), Any(xInfoSet) };
+
+ Reference< XExporter > xExporter( mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ udExport, aAnys, mxContext ), UNO_QUERY_THROW );
+
+ // attach to source document
+ xExporter->setSourceDocument( mxDoc );
+
+ // get XFilter interface
+ Reference< XFilter > xFilter( xExporter, UNO_QUERY_THROW );
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->setValue(nSteps++);
+
+ // call the actual filtering component
+ if (!xFilter->filter(aDescriptor))
+ {
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return false;
+ }
+ }
+ catch (const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xmlfa", "XmlFilterAdaptor");
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return false;
+ }
+
+ // done
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return true;
+}
+
+sal_Bool SAL_CALL XmlFilterAdaptor::filter( const Sequence< css::beans::PropertyValue >& aDescriptor )
+{
+ return meType == FILTER_EXPORT ? exportImpl ( aDescriptor ) : importImpl ( aDescriptor );
+}
+void SAL_CALL XmlFilterAdaptor::cancel( )
+{
+}
+// XExporter
+void SAL_CALL XmlFilterAdaptor::setSourceDocument( const Reference< css::lang::XComponent >& xDoc )
+{
+ meType = FILTER_EXPORT;
+ mxDoc = xDoc;
+}
+
+// XImporter
+void SAL_CALL XmlFilterAdaptor::setTargetDocument( const Reference< css::lang::XComponent >& xDoc )
+{
+ meType = FILTER_IMPORT;
+ mxDoc = xDoc;
+}
+// XInitialization
+void SAL_CALL XmlFilterAdaptor::initialize( const Sequence< Any >& aArguments )
+{
+ Sequence < PropertyValue > aAnySeq;
+ if ( aArguments.hasElements() && ( aArguments[0] >>= aAnySeq ) )
+ {
+ comphelper::SequenceAsHashMap aMap(aAnySeq);
+ msFilterName = aMap.getUnpackedValueOrDefault(
+ "Type", OUString());
+ msUserData = aMap.getUnpackedValueOrDefault(
+ "UserData", Sequence< OUString >());
+ msTemplateName = aMap.getUnpackedValueOrDefault(
+ "TemplateName", OUString());
+ }
+}
+
+// XServiceInfo
+OUString SAL_CALL XmlFilterAdaptor::getImplementationName( )
+{
+ return "com.sun.star.comp.Writer.XmlFilterAdaptor";
+}
+
+sal_Bool SAL_CALL XmlFilterAdaptor::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+Sequence< OUString > SAL_CALL XmlFilterAdaptor::getSupportedServiceNames( )
+{
+ return { "com.sun.star.document.ExportFilter", "com.sun.star.document.ImportFilter" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_XmlFilterAdaptor_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XmlFilterAdaptor(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xmlfilteradaptor/XmlFilterAdaptor.hxx b/filter/source/xmlfilteradaptor/XmlFilterAdaptor.hxx
new file mode 100644
index 000000000..a276d396e
--- /dev/null
+++ b/filter/source/xmlfilteradaptor/XmlFilterAdaptor.hxx
@@ -0,0 +1,106 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <utility>
+
+
+enum FilterType
+{
+ FILTER_IMPORT,
+ FILTER_EXPORT
+};
+
+/* This component will be instantiated for both import or export. Whether it calls
+ * setSourceDocument or setTargetDocument determines which Impl function the filter
+ * member calls */
+
+class XmlFilterAdaptor final : public cppu::WeakImplHelper
+<
+ css::document::XFilter,
+ css::document::XExporter,
+ css::document::XImporter,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo
+>
+{
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::lang::XComponent > mxDoc;
+ OUString msFilterName;
+ css::uno::Sequence< OUString > msUserData;
+ OUString msTemplateName;
+ FilterType meType;
+
+ /// @throws css::uno::RuntimeException
+ bool exportImpl( const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor );
+
+ /// @throws css::uno::RuntimeException
+ bool importImpl( const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor );
+
+
+public:
+
+ explicit XmlFilterAdaptor( css::uno::Reference< css::uno::XComponentContext > xContext)
+ : mxContext(std::move(xContext))
+ , meType(FILTER_IMPORT)
+ {
+ }
+
+ // XFilter
+
+ virtual sal_Bool SAL_CALL filter( const css::uno::Sequence< css::beans::PropertyValue >& aDescriptor ) override;
+
+ virtual void SAL_CALL cancel( ) override;
+
+
+ // XExporter
+
+ virtual void SAL_CALL setSourceDocument( const css::uno::Reference< css::lang::XComponent >& xDoc ) override;
+
+
+ // XImporter
+
+ virtual void SAL_CALL setTargetDocument( const css::uno::Reference< css::lang::XComponent >& xDoc ) override;
+
+
+ // XInitialization
+
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+
+ // XServiceInfo
+
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xmlfilteradaptor/xmlfa.component b/filter/source/xmlfilteradaptor/xmlfa.component
new file mode 100644
index 000000000..7e6c316db
--- /dev/null
+++ b/filter/source/xmlfilteradaptor/xmlfa.component
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.Writer.XmlFilterAdaptor"
+ constructor="filter_XmlFilterAdaptor_get_implementation">
+ <service name="com.sun.star.document.ExportFilter"/>
+ <service name="com.sun.star.document.ImportFilter"/>
+ </implementation>
+</component>
diff --git a/filter/source/xmlfilterdetect/filterdetect.cxx b/filter/source/xmlfilterdetect/filterdetect.cxx
new file mode 100644
index 000000000..e7cab3323
--- /dev/null
+++ b/filter/source/xmlfilterdetect/filterdetect.cxx
@@ -0,0 +1,246 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "filterdetect.hxx"
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/PropertyState.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <tools/diagnose_ex.h>
+#include <ucbhelper/content.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <svl/inettype.hxx>
+#include <memory>
+#include <o3tl/string_view.hxx>
+
+using namespace com::sun::star::container;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::beans;
+
+namespace {
+
+OUString supportedByType( std::u16string_view clipBoardFormat, std::u16string_view resultString, const OUString& checkType)
+{
+ OUString sTypeName;
+ if ( o3tl::starts_with(clipBoardFormat, u"doctype:") )
+ {
+ std::u16string_view tryStr = clipBoardFormat.substr(8);
+ if (resultString.find(tryStr) != std::u16string_view::npos)
+ {
+ sTypeName = checkType;
+ }
+ }
+ return sTypeName;
+}
+
+bool IsMediaTypeXML( const OUString& mediaType )
+{
+ if (!mediaType.isEmpty())
+ {
+ OUString sType, sSubType;
+ if (INetContentTypes::parse(mediaType, sType, sSubType)
+ && sType == "application")
+ {
+ // RFC 3023: application/xml; don't detect text/xml
+ if (sSubType == "xml")
+ return true;
+ // Registered media types: application/XXXX+xml
+ if (sSubType.endsWith("+xml"))
+ return true;
+ }
+ }
+ return false;
+}
+
+}
+
+OUString SAL_CALL FilterDetect::detect( css::uno::Sequence< css::beans::PropertyValue >& aArguments )
+{
+ OUString sTypeName;
+ OUString sUrl;
+ Sequence<PropertyValue > lProps ;
+
+ css::uno::Reference< css::io::XInputStream > xInStream;
+ const PropertyValue * pValue = aArguments.getConstArray();
+ sal_Int32 nLength;
+ OUString resultString;
+
+ nLength = aArguments.getLength();
+ sal_Int32 location=nLength;
+ for (sal_Int32 i = 0 ; i < nLength; i++)
+ {
+ if ( pValue[i].Name == "TypeName" )
+ {
+ location=i;
+ }
+ else if ( pValue[i].Name == "URL" )
+ {
+ pValue[i].Value >>= sUrl;
+ }
+ else if ( pValue[i].Name == "InputStream" )
+ {
+ pValue[i].Value >>= xInStream ;
+ }
+ }
+ try
+ {
+ if (!xInStream.is())
+ {
+ ::ucbhelper::Content aContent(
+ sUrl, Reference< css::ucb::XCommandEnvironment >(),
+ mxCtx);
+ xInStream = aContent.openStream();
+ if (!xInStream.is())
+ {
+ return sTypeName;
+ }
+ }
+
+ std::unique_ptr< SvStream > pInStream( ::utl::UcbStreamHelper::CreateStream( xInStream ) );
+ pInStream->StartReadingUnicodeText( RTL_TEXTENCODING_DONTKNOW );
+ sal_uInt64 const nUniPos = pInStream->Tell();
+
+ const sal_uInt16 nSize = 4000;
+ bool bTryUtf16 = false;
+
+ if ( nUniPos == 0 ) // No BOM detected, try to guess UTF-16 endianness
+ {
+ sal_uInt16 nHeader = 0;
+ pInStream->ReadUInt16( nHeader );
+ if ( nHeader == 0x003C )
+ bTryUtf16 = true;
+ else if ( nHeader == 0x3C00 )
+ {
+ bTryUtf16 = true;
+ pInStream->SetEndian( pInStream->GetEndian() == SvStreamEndian::LITTLE ? SvStreamEndian::BIG : SvStreamEndian::LITTLE );
+ }
+ pInStream->Seek( STREAM_SEEK_TO_BEGIN );
+ }
+
+ if ( nUniPos == 3 || ( nUniPos == 0 && !bTryUtf16 ) ) // UTF-8 or non-Unicode
+ {
+ OString const str(read_uInt8s_ToOString(*pInStream, nSize));
+ resultString = OUString(str.getStr(), str.getLength(),
+ RTL_TEXTENCODING_ASCII_US,
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT|RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT|RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT);
+ }
+ else if ( nUniPos == 2 || bTryUtf16 ) // UTF-16
+ resultString = read_uInt16s_ToOUString( *pInStream, nSize );
+
+ if ( !resultString.startsWith( "<?xml" ) )
+ {
+ // Check the content type; XML declaration is optional in XML files according to XML 1.0 ch.2.8
+ // (see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-prolog-dtd)
+ OUString sMediaType;
+ try
+ {
+ ::ucbhelper::Content aContent(
+ sUrl, Reference< css::ucb::XCommandEnvironment >(),
+ mxCtx);
+ aContent.getPropertyValue("MediaType") >>= sMediaType;
+ if (sMediaType.isEmpty())
+ {
+ aContent.getPropertyValue("Content-Type") >>= sMediaType;
+ }
+ }
+ catch (...) {}
+
+ if (!IsMediaTypeXML(sMediaType))
+ {
+ // This is not an XML stream. It makes no sense to try to detect
+ // a non-XML file type here.
+ return OUString();
+ }
+ }
+
+ // test typedetect code
+ Reference <XNameAccess> xTypeCont(mxCtx->getServiceManager()->createInstanceWithContext("com.sun.star.document.TypeDetection", mxCtx), UNO_QUERY);
+ Sequence < OUString > myTypes= xTypeCont->getElementNames();
+ nLength = myTypes.getLength();
+
+ sal_Int32 new_nlength=0;
+ sal_Int32 i = 0 ;
+ while ((i < nLength) && (sTypeName.isEmpty()))
+ {
+ Any elem = xTypeCont->getByName(myTypes[i]);
+ elem >>=lProps;
+ new_nlength = lProps.getLength();
+ sal_Int32 j =0;
+ while (j < new_nlength && (sTypeName.isEmpty()))
+ {
+ OUString tmpStr;
+ lProps[j].Value >>=tmpStr;
+ if ( lProps[j].Name == "ClipboardFormat" && !tmpStr.isEmpty() )
+ {
+ sTypeName = supportedByType(tmpStr,resultString, myTypes[i]);
+ }
+ j++;
+ }
+ i++;
+ }
+ }
+ catch (const Exception &)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xmlfd", "An Exception occurred while opening File stream");
+ }
+
+ if (!sTypeName.isEmpty())
+ {
+ if (location == aArguments.getLength())
+ {
+ aArguments.realloc(nLength+1);
+ aArguments.getArray()[location].Name = "TypeName";
+ }
+ aArguments.getArray()[location].Value <<=sTypeName;
+ }
+
+ return sTypeName;
+}
+
+// XInitialization
+void SAL_CALL FilterDetect::initialize( const Sequence< Any >& /*aArguments*/ )
+{
+}
+
+// XServiceInfo
+OUString SAL_CALL FilterDetect::getImplementationName( )
+{
+ return "com.sun.star.comp.filters.XMLFilterDetect";
+}
+
+sal_Bool SAL_CALL FilterDetect::supportsService( const OUString& rServiceName )
+{
+ return cppu::supportsService( this, rServiceName );
+}
+
+Sequence< OUString > SAL_CALL FilterDetect::getSupportedServiceNames( )
+{
+ return { "com.sun.star.document.ExtendedTypeDetection" };
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_XMLFilterDetect_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new FilterDetect(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xmlfilterdetect/filterdetect.hxx b/filter/source/xmlfilterdetect/filterdetect.hxx
new file mode 100644
index 000000000..c84b9f066
--- /dev/null
+++ b/filter/source/xmlfilterdetect/filterdetect.hxx
@@ -0,0 +1,59 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/document/XExtendedFilterDetection.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <utility>
+
+namespace com::sun::star::uno {
+ class XComponentContext;
+}
+
+class FilterDetect final : public cppu::WeakImplHelper <
+ css::document::XExtendedFilterDetection,
+ css::lang::XInitialization,
+ css::lang::XServiceInfo
+>
+{
+
+ css::uno::Reference< css::uno::XComponentContext > mxCtx;
+
+public:
+ explicit FilterDetect( css::uno::Reference< css::uno::XComponentContext > xCtx)
+ : mxCtx(std::move( xCtx )) {}
+
+ //XExtendedFilterDetection
+ virtual OUString SAL_CALL detect( css::uno::Sequence< css::beans::PropertyValue >& lDescriptor ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const css::uno::Sequence< css::uno::Any >& aArguments ) override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName( ) override;
+
+ virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override;
+
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xmlfilterdetect/xmlfd.component b/filter/source/xmlfilterdetect/xmlfd.component
new file mode 100644
index 000000000..77a8ea0fd
--- /dev/null
+++ b/filter/source/xmlfilterdetect/xmlfd.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.filters.XMLFilterDetect"
+ constructor="filter_XMLFilterDetect_get_implementation">
+ <service name="com.sun.star.document.ExtendedTypeDetection"/>
+ </implementation>
+</component>
diff --git a/filter/source/xslt/common/copy.xsl b/filter/source/xslt/common/copy.xsl
new file mode 100644
index 000000000..24fbe007a
--- /dev/null
+++ b/filter/source/xslt/common/copy.xsl
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <xsl:output method="xml" encoding="UTF-8"/>
+
+ <xsl:template match="/">
+ <xsl:copy-of select="."/>
+ </xsl:template>
+</xsl:stylesheet>
+
diff --git a/filter/source/xslt/common/math.xsl b/filter/source/xslt/common/math.xsl
new file mode 100644
index 000000000..6b0dafc1f
--- /dev/null
+++ b/filter/source/xslt/common/math.xsl
@@ -0,0 +1,580 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<!--
+ xslt math lib by Wind Li
+Public Functions
+ sin(x,rounding-factor=100)
+ cos(x,rounding-factor=100)
+ tan(x,rounding-factor=100)
+ ctan(x,rounding-factor=100)
+ atan2(x, y ,rounding-factor=100)
+ atan(x,rounding-factor=100)
+ acos(x,rounding-factor=100)
+ asin(x,rounding-factor=100)
+ abs(x)
+ max(x1,x2)
+ min(x1,x2)
+ power(x,power(integer only), rounding-factor=100)
+ sqrt(x, rounding-factor=100)
+ convert2radian(x,rounding-factor=100)
+ convert2degree(x,rounding-factor=100)
+ convert2fd(x,rounding-factor=100)
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:text="http://openoffice.org/2000/text" xmlns:style="http://openoffice.org/2000/style" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:office="http://openoffice.org/2000/office" exclude-result-prefixes="draw svg style office fo text">
+ <xsl:variable name="pi" select="3.1416"/>
+ <xsl:template name="math-test">
+ sin(34.8)
+ <xsl:call-template name="sin">
+ <xsl:with-param name="x" select="34.8"/>
+ <xsl:with-param name="rounding-factor" select="100000"/>
+ </xsl:call-template>
+ cos(34.8)
+ <xsl:call-template name="cos">
+ <xsl:with-param name="x" select="34.8"/>
+ <xsl:with-param name="rounding-factor" select="100000"/>
+ </xsl:call-template>
+ atan(2.74)
+ <xsl:call-template name="atan">
+ <xsl:with-param name="x" select="2.74"/>
+ <xsl:with-param name="rounding-factor" select="100000"/>
+ </xsl:call-template>
+ acos(0.5)
+ <xsl:call-template name="acos">
+ <xsl:with-param name="x" select="0.5"/>
+ <xsl:with-param name="rounding-factor" select="100000"/>
+ </xsl:call-template>
+ asin(0.5)
+ <xsl:call-template name="asin">
+ <xsl:with-param name="x" select="0.5"/>
+ <xsl:with-param name="rounding-factor" select="100000"/>
+ </xsl:call-template>
+ sqrt(1328.3414)
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="1328.3414"/>
+ <xsl:with-param name="rounding-factor" select="100000"/>
+ </xsl:call-template>
+ </xsl:template>
+ <!-- public functions start -->
+ <xsl:template name="sin">
+ <xsl:param name="x" select="0"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:variable name="angle" select="$x * 180 div $pi "/>
+ <xsl:variable name="mod-angle" select="$angle mod 360"/>
+ <xsl:variable name="sinx">
+ <xsl:call-template name="sin-private">
+ <xsl:with-param name="x" select=" ( $angle mod 360 ) * $pi div 180 "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select=" round ( number($sinx) * $rounding-factor ) div $rounding-factor"/>
+ </xsl:template>
+ <xsl:template name="cos">
+ <xsl:param name="x" select="0"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:variable name="angle" select="$x * 180 div $pi "/>
+ <xsl:variable name="mod-angle" select="$angle mod 360"/>
+ <xsl:variable name="cosx">
+ <xsl:call-template name="cos-private">
+ <xsl:with-param name="x" select=" ( $angle mod 360 ) * $pi div 180 "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select=" round ( number($cosx) * $rounding-factor ) div $rounding-factor"/>
+ </xsl:template>
+ <xsl:template name="tan">
+ <xsl:param name="x" select="0"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:variable name="sinx">
+ <xsl:call-template name="sin">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor * 10"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cosx">
+ <xsl:call-template name="cos">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor * 10"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test=" $cosx = 0 ">
+ <xsl:message>tan error : tan(<xsl:value-of select="$x"/>) is infinite!</xsl:message>
+ <xsl:value-of select="63535"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" round( $sinx div $cosx * $rounding-factor) div $rounding-factor"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="ctan">
+ <xsl:param name="x" select="0"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:variable name="sinx">
+ <xsl:call-template name="sin">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor * 10"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cosx">
+ <xsl:call-template name="cos">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor * 10"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test=" $sinx = 0 ">
+ <xsl:message>tan error : tan(<xsl:value-of select="$x"/>) is infinite!</xsl:message>
+ <xsl:value-of select="63535"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" round( $cosx div $sinx * $rounding-factor) div $rounding-factor"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="atan">
+ <xsl:param name="x" select="0"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:choose>
+ <xsl:when test="$x = 0">
+ <xsl:value-of select="0"/>
+ </xsl:when>
+ <xsl:when test="$x &lt; 0">
+ <xsl:variable name="atan-x">
+ <xsl:call-template name="atan">
+ <xsl:with-param name="x" select=" -1 * $x"/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="-1 * $atan-x"/>
+ </xsl:when>
+ <xsl:when test="$x &gt; 1">
+ <xsl:variable name="atan-div-x">
+ <xsl:call-template name="atan">
+ <xsl:with-param name="x" select="1 div $x "/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select=" $pi div 2 - $atan-div-x"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="arctanx">
+ <xsl:call-template name="atan-private">
+ <xsl:with-param name="x" select=" $x "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select=" round ( number($arctanx) * $rounding-factor ) div $rounding-factor"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="atan2">
+ <xsl:param name="x"/>
+ <xsl:param name="y"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:choose>
+ <xsl:when test="$x = 0">
+ <xsl:value-of select=" $pi div 2"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="atan">
+ <xsl:with-param name="x" select="$y div $x"/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="acos">
+ <xsl:param name="x"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:variable name="abs-x">
+ <xsl:call-template name="abs">
+ <xsl:with-param name="x" select="$x"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$abs-x &gt; 1">
+ <xsl:message>acos error : abs(<xsl:value-of select="$x"/>) greater than 1 !</xsl:message>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="atan2">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="y">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="1 - $x * $x"/>
+ <xsl:with-param name="rounding-factor" select=" concat($rounding-factor,'0') "/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="asin">
+ <xsl:param name="x"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:variable name="abs-x">
+ <xsl:call-template name="abs">
+ <xsl:with-param name="x" select="$x"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$abs-x &gt; 1">
+ <xsl:message>asin error : abs(<xsl:value-of select="$x"/>) greater than 1 !</xsl:message>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="atan2">
+ <xsl:with-param name="y" select="$x"/>
+ <xsl:with-param name="x">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="1 - $x * $x"/>
+ <xsl:with-param name="rounding-factor" select=" concat($rounding-factor,'0') "/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="abs">
+ <xsl:param name="x"/>
+ <xsl:choose>
+ <xsl:when test="$x &gt; 0">
+ <xsl:value-of select="$x"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$x * -1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="max">
+ <xsl:param name="x1"/>
+ <xsl:param name="x2"/>
+ <xsl:choose>
+ <xsl:when test="$x1 &gt; $x2">
+ <xsl:value-of select="$x1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$x2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="min">
+ <xsl:param name="x1"/>
+ <xsl:param name="x2"/>
+ <xsl:choose>
+ <xsl:when test="$x1 &lt; $x2">
+ <xsl:value-of select="$x1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$x2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="power">
+ <xsl:param name="x"/>
+ <xsl:param name="y" select="1"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <!-- z is a private param -->
+ <xsl:param name="z" select="1"/>
+ <xsl:choose>
+ <xsl:when test="$y &gt; 0">
+ <xsl:call-template name="power">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="y" select="$y - 1"/>
+ <xsl:with-param name="z" select="$z * $x"/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" round( $z * $rounding-factor) div $rounding-factor"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="sqrt">
+ <xsl:param name="x"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:choose>
+ <xsl:when test="$x = 0">0</xsl:when>
+ <xsl:when test="$x &lt; 0">
+ <xsl:message>sqrt error : <xsl:value-of select="$x"/> less than 0!</xsl:message>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="sqrt-private">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="rounding-factor" select="$rounding-factor"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- public functions end -->
+ <!--
+Private functions:
+sin-private
+cos-private
+atan-private
+sqrt-private
+integer-sqrt
+Sqrt-GetOneDigit
+-->
+ <xsl:template name="sin-private">
+ <xsl:param name="x" select="0"/>
+ <xsl:param name="n" select="0"/>
+ <xsl:param name="nx" select="1"/>
+ <xsl:param name="sign" select="1"/>
+ <xsl:param name="max-n" select="20"/>
+ <xsl:param name="sinx" select="0"/>
+ <xsl:choose>
+ <xsl:when test="not ($max-n &gt; $n) or $nx = 0 ">
+ <xsl:value-of select="$sinx"/>
+ </xsl:when>
+ <xsl:when test="$n = 0">
+ <xsl:call-template name="sin-private">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="n" select="$n + 1"/>
+ <xsl:with-param name="sign" select="$sign * -1"/>
+ <xsl:with-param name="max-n" select="$max-n"/>
+ <xsl:with-param name="nx" select="$x "/>
+ <xsl:with-param name="sinx" select="$sinx + $x"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="new-nx" select="($nx * $x * $x) div ( 2 * $n ) div ( 2 * $n + 1) "/>
+ <xsl:call-template name="sin-private">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="n" select="$n + 1"/>
+ <xsl:with-param name="sign" select="$sign * -1"/>
+ <xsl:with-param name="max-n" select="$max-n"/>
+ <xsl:with-param name="nx" select=" $new-nx "/>
+ <xsl:with-param name="sinx" select="$sinx + $new-nx * $sign"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="cos-private">
+ <xsl:param name="x" select="0"/>
+ <xsl:param name="n" select="0"/>
+ <xsl:param name="nx" select="1"/>
+ <xsl:param name="sign" select="1"/>
+ <xsl:param name="max-n" select="20"/>
+ <xsl:param name="cosx" select="0"/>
+ <xsl:choose>
+ <xsl:when test="not ($max-n &gt; $n) or $nx = 0 ">
+ <xsl:value-of select="$cosx"/>
+ </xsl:when>
+ <xsl:when test="$n = 0">
+ <xsl:call-template name="cos-private">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="n" select="$n + 1"/>
+ <xsl:with-param name="sign" select="$sign * -1"/>
+ <xsl:with-param name="max-n" select="$max-n"/>
+ <xsl:with-param name="nx" select=" 1 "/>
+ <xsl:with-param name="cosx" select="1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="new-nx" select="($nx * $x * $x) div ( 2 * $n -1 ) div ( 2 * $n ) "/>
+ <xsl:call-template name="cos-private">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="n" select="$n + 1"/>
+ <xsl:with-param name="sign" select="$sign * -1"/>
+ <xsl:with-param name="max-n" select="$max-n"/>
+ <xsl:with-param name="nx" select=" $new-nx "/>
+ <xsl:with-param name="cosx" select="$cosx + $new-nx * $sign"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="atan-private">
+ <xsl:param name="x" select="0"/>
+ <xsl:param name="n" select="0"/>
+ <xsl:param name="nx" select="1"/>
+ <xsl:param name="sign" select="1"/>
+ <xsl:param name="max-n" select="40"/>
+ <xsl:param name="arctanx" select="0"/>
+ <xsl:choose>
+ <xsl:when test="not ($max-n &gt; $n) or $nx = 0 ">
+ <xsl:value-of select="$arctanx"/>
+ </xsl:when>
+ <xsl:when test="$n = 0">
+ <xsl:call-template name="atan-private">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="n" select="$n + 1"/>
+ <xsl:with-param name="sign" select="$sign * -1"/>
+ <xsl:with-param name="max-n" select="$max-n"/>
+ <xsl:with-param name="nx" select="$x "/>
+ <xsl:with-param name="arctanx" select="$arctanx + $x"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="new-nx" select=" $nx * $x * $x "/>
+ <xsl:call-template name="atan-private">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="n" select="$n + 1"/>
+ <xsl:with-param name="sign" select="$sign * -1"/>
+ <xsl:with-param name="max-n" select="$max-n"/>
+ <xsl:with-param name="nx" select=" $new-nx "/>
+ <xsl:with-param name="arctanx" select="$arctanx + $new-nx div (2 * $n +1) * $sign"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="sqrt-private">
+ <xsl:param name="x"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:variable name="shift" select="string-length( $rounding-factor)"/>
+ <xsl:variable name="power">
+ <xsl:call-template name="power">
+ <xsl:with-param name="x" select="100"/>
+ <xsl:with-param name="y" select="$shift"/>
+ <xsl:with-param name="rounding-factor" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="integer-x" select=" round( $power * $x )"/>
+ <xsl:variable name="integer-quotient">
+ <xsl:call-template name="integer-sqrt">
+ <xsl:with-param name="x" select="$integer-x"/>
+ <xsl:with-param name="length" select=" string-length( $integer-x ) "/>
+ <xsl:with-param name="curr-pos" select=" 2 - (round (string-length( $integer-x ) div 2 ) * 2 - string-length( $integer-x ) ) "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="power-10">
+ <xsl:call-template name="power">
+ <xsl:with-param name="x" select="10"/>
+ <xsl:with-param name="y" select="$shift - 1"/>
+ <xsl:with-param name="rounding-factor" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select=" round( $integer-quotient div 10) div $power-10 "/>
+ </xsl:template>
+ <xsl:template name="integer-sqrt">
+ <xsl:param name="x"/>
+ <xsl:param name="length"/>
+ <xsl:param name="curr-pos"/>
+ <xsl:param name="last-quotient" select="0"/>
+ <xsl:choose>
+ <xsl:when test="$curr-pos &gt; $length">
+ <xsl:value-of select="$last-quotient"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="curr-x" select="substring( $x, 1, $curr-pos )"/>
+ <xsl:variable name="new-quotient">
+ <xsl:call-template name="get-one-sqrt-digit">
+ <xsl:with-param name="x" select="$curr-x"/>
+ <xsl:with-param name="last-quotient" select="$last-quotient"/>
+ <xsl:with-param name="n" select="5"/>
+ <xsl:with-param name="direct" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="integer-sqrt">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="length" select="$length"/>
+ <xsl:with-param name="curr-pos" select="$curr-pos + 2"/>
+ <xsl:with-param name="last-quotient" select="number($new-quotient)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-one-sqrt-digit">
+ <xsl:param name="x"/>
+ <xsl:param name="last-quotient"/>
+ <xsl:param name="n"/>
+ <xsl:param name="direct" select="1"/>
+ <xsl:variable name="quotient" select=" concat( $last-quotient, $n) "/>
+ <xsl:variable name="accumulate" select="$quotient * $quotient "/>
+ <xsl:choose>
+ <xsl:when test="$accumulate = $x">
+ <xsl:value-of select="concat($last-quotient , $n )"/>
+ </xsl:when>
+ <xsl:when test="$direct = 0 and $accumulate &lt; $x">
+ <xsl:call-template name="get-one-sqrt-digit">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="last-quotient" select="$last-quotient"/>
+ <xsl:with-param name="n" select="$n + 1"/>
+ <xsl:with-param name="direct" select="1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$direct = 0 and $accumulate &gt; $x">
+ <xsl:call-template name="get-one-sqrt-digit">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="last-quotient" select="$last-quotient"/>
+ <xsl:with-param name="n" select="$n - 1"/>
+ <xsl:with-param name="direct" select="-1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" $accumulate * $direct &lt; $x * $direct ">
+ <xsl:call-template name="get-one-sqrt-digit">
+ <xsl:with-param name="x" select="$x"/>
+ <xsl:with-param name="last-quotient" select="$last-quotient"/>
+ <xsl:with-param name="n" select="$n+ $direct"/>
+ <xsl:with-param name="direct" select="$direct"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="not($n &lt; 9) or $n = -1">
+ <xsl:value-of select="concat($last-quotient , $n - $direct) "/>
+ </xsl:when>
+ <xsl:when test="$direct = 1">
+ <xsl:value-of select="concat($last-quotient , $n - 1) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($last-quotient , $n) "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="convert2redian">
+ <xsl:param name="x" select="'0'"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:choose>
+ <xsl:when test="contains($x,'deg')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($x, 'deg') div 180 * $pi)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($x,'fd')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($x, 'fd') div 180 div 65536 * $pi)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="round($rounding-factor * number($x) div 180 * $pi) div $rounding-factor"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="convert2degree">
+ <xsl:param name="x" select="'0'"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:choose>
+ <xsl:when test="contains($x,'deg')">
+ <xsl:value-of select="round($rounding-factor * substring-before($x,'deg')) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($x,'fd')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($x, 'fd')) div 65536 ) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="round($rounding-factor * number($x) * 180 div $pi) div $rounding-factor"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="convert2fd">
+ <xsl:param name="x" select="'0'"/>
+ <xsl:param name="rounding-factor" select="100"/>
+ <xsl:choose>
+ <xsl:when test="contains($x,'deg')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($x, 'deg') * 65535)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($x,'fd')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($x, 'fd'))) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="round($rounding-factor * number($x) * 180 div $pi * 65535) div $rounding-factor"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/common/measure_conversion.xsl b/filter/source/xslt/common/measure_conversion.xsl
new file mode 100644
index 000000000..50f34e959
--- /dev/null
+++ b/filter/source/xslt/common/measure_conversion.xsl
@@ -0,0 +1,479 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+ <!-- DPI (dots per inch) the standard resolution of given pictures (necessary for the conversion of 'cm' into 'pixel')
+ Although many pictures have a 96 dpi resolution, a higher resolution give better results for common browsers -->
+ <xsl:param name="dpi" select="111"/>
+ <xsl:param name="centimeter-in-mm" select="10"/>
+ <xsl:param name="inch-in-mm" select="25.4"/>
+ <xsl:param name="didot-point-in-mm" select="0.376065"/>
+ <xsl:param name="pica-in-mm" select="4.2333333"/>
+ <xsl:param name="point-in-mm" select="0.3527778"/>
+ <xsl:param name="twip-in-mm" select="0.017636684"/>
+ <xsl:param name="pixel-in-mm" select="$inch-in-mm div $dpi"/>
+ <!-- ***** MEASUREMENT CONVERSIONS *****
+ PARAM 'value'
+ The measure to be converted.
+ The current measure is judged by a substring (e.g. 'mm', 'cm', 'in', 'pica'...)
+ directly added to the number.
+
+ PARAM 'rounding-factor'
+ Is used for the rounding of decimal places.
+ The parameter number is the product of 1 and some '10', where
+ every zero represents a decimal place.
+
+ For example, providing as parameter:
+ <xsl:param name="rounding-factor" select="10000" />
+ Gives by default four decimal places.
+
+ To round two decimal places, basically the following is done:
+ <xsl:value-of select="round(100 * value) div 100"/>
+
+ RETURN The converted number, by default rounded to four decimal places.
+ In case the input measure could not be matched the same value is
+ returned and a warning message is written out.
+
+
+
+ MEASURE LIST:
+ * 1 millimeter (mm), the basic measure
+
+ * 1 centimeter (cm) = 10 mm
+
+ * 1 inch (in) = 25.4 mm
+ While the English have already seen the light (read: the metric system), the US
+ remains loyal to this medieval system.
+
+ * 1 point (pt) = 0.35277777.. mm
+ Sometimes called PostScript point (ppt), as when Adobe created PostScript, they added their own system of points.
+ There are exactly 72 PostScript points in 1 inch.
+
+ * 1 twip = twentieth of a (PostScript) point
+ A twip (twentieth of a point) is a 1/20th of a PostScript point, a traditional measure in printing.
+
+ * 1 didot point (dpt) = 0.376065 mm
+ Didot point after the French typographer Firmin Didot (1764-1836).
+
+ More details under
+ http://www.unc.edu/~rowlett/units/dictP.html:
+ "A unit of length used by typographers and printers. When printing was done
+ from hand-set metal type, one point represented the smallest element of type
+ that could be handled, roughly 1/64 inch. Eventually, the point was standardized
+ in Britain and America as exactly 1/72.27 = 0.013 837 inch, which is
+ about 0.35 mm (351.46 micrometers). In continental Europe, typographers
+ traditionally used a slightly larger point of 0.014 83 inch (about
+ 1/72 pouce, 0.377 mm, or roughly 1/67 English inch), called a Didot point
+ after the French typographer Firmin Didot (1764-1836). In the U.S.,
+ Adobe software defines the point to be exactly 1/72 inch (0.013 888 9 inch
+ or 0.352 777 8 millimeters) and TeX software uses a slightly smaller point
+ of 0.351 459 8035 mm. The German standards agency DIN has proposed that
+ all these units be replaced by multiples of 0.25 millimeters (1/101.6 inch).
+
+ * 1 pica = 4.233333 mm
+ 1/6 inch or 12 points
+
+ * 1 pixel (px) = 0.26458333.. mm (relative to 'DPI', here: 96 dpi)
+ Most pictures have the 96 dpi resolution, but the dpi variable may vary by stylesheet parameter
+
+
+ -->
+ <!-- changing measure to mm -->
+ <xsl:template name="convert2mm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="substring-before($value, 'mm')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm' ) * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in' ) * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'mm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to cm -->
+ <xsl:template name="convert2cm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="substring-before($value, 'cm')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $centimeter-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $centimeter-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $centimeter-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $centimeter-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $centimeter-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $centimeter-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'cm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to inch (cp. section comment) -->
+ <xsl:template name="convert2in">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $inch-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="substring-before($value, 'in')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $inch-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $inch-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $inch-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $inch-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $inch-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'in'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to dpt (cp. section comment) -->
+ <xsl:template name="convert2dpt">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $didot-point-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $didot-point-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $didot-point-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="substring-before($value, 'dpt')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $didot-point-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $didot-point-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $didot-point-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'dpt'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pica (cp. section comment) -->
+ <xsl:template name="convert2pica">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $pica-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $pica-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $pica-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $pica-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="substring-before($value, 'pica')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $pica-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $pica-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'pica'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pt (cp. section comment) -->
+ <xsl:template name="convert2pt">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $point-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $point-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="substring-before($value, 'pt')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $point-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $point-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $point-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $point-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'pt'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to twip (cp. section comment) -->
+ <xsl:template name="convert2twip">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $twip-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $twip-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $twip-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $twip-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $twip-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="substring-before($value, 'twip')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $twip-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'twip'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pixel by via parameter provided dpi (dots per inch) standard factor (cp. section comment) -->
+ <xsl:template name="convert2px">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round(number(substring-before($value, 'mm')) div $pixel-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round(number(substring-before($value, 'cm')) div $pixel-in-mm * $centimeter-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round(number(substring-before($value, 'in')) div $pixel-in-mm * $inch-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round(number(substring-before($value, 'pt')) div $pixel-in-mm * $point-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round(number(substring-before($value, 'dpt')) div $pixel-in-mm * $didot-point-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round(number(substring-before($value, 'pica')) div $pixel-in-mm * $pica-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round(number(substring-before($value, 'twip')) div $pixel-in-mm * $twip-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'px'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="ConvertMeasure">
+ <xsl:param name="TargetMeasure" select="'cm'"/>
+ <xsl:param name="TargetTruncate" select=" 'all' "/>
+ <xsl:param name="value"/>
+ <!-- When TargetTruncate ='all' it returns the number whichsoever the return value is negative or positive
+ When TargetTruncate ='nonNegative' it only returns nonNegative number, all negative number to be returned as 0
+ When TargetTruncate ='positive" it only returns positive number, all nonPositive number to be returned as 1 -->
+ <xsl:variable name="return_value">
+ <xsl:choose>
+ <!-- remove the measure mark, if the value is null, the result should be 0. Must be the first case -->
+ <xsl:when test="string-length(translate(string($value),'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ','')) = 0">0</xsl:when>
+ <xsl:when test="string-length(translate(string($value),'- .0123456789','')) = 0">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:when test="$TargetMeasure = 'cm'">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$TargetMeasure = 'pt'">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$TargetMeasure = 'twip'">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$TargetMeasure = 'in'">
+ <xsl:call-template name="convert2in">
+ <xsl:with-param name="value" select="$value"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$TargetTruncate = 'all' ">
+ <xsl:choose>
+ <xsl:when test="string(number($TargetMeasure)) = 'NaN' ">
+ <xsl:value-of select=" '0' "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return_value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$TargetTruncate = 'nonNegative' ">
+ <xsl:choose>
+ <xsl:when test="string(number($TargetMeasure)) = 'NaN' ">
+ <xsl:value-of select=" '0' "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test=" $return_value &lt; 0 ">
+ <xsl:value-of select=" '0' "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return_value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$TargetTruncate = 'positive' ">
+ <xsl:choose>
+ <xsl:when test="string(number($TargetMeasure)) = 'NaN' ">
+ <xsl:value-of select=" '1' "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test=" $return_value &lt;= 0 ">
+ <xsl:value-of select=" '1' "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return_value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="Add-With-Measure">
+ <xsl:param name="value1"/>
+ <xsl:param name="value2"/>
+ <xsl:param name="TargetMeasure" select="'in'"/>
+ <xsl:variable name="number-value1">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="$value1"/>
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="number-value2">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="$value2"/>
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$number-value1 + $number-value2"/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/common/ooo2ms_docpr.xsl b/filter/source/xslt/export/common/ooo2ms_docpr.xsl
new file mode 100644
index 000000000..df1de5fb1
--- /dev/null
+++ b/filter/source/xslt/export/common/ooo2ms_docpr.xsl
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:template match="office:meta">
+ <o:DocumentProperties>
+ <o:Title>
+ <xsl:value-of select="dc:title"/>
+ </o:Title>
+ <o:Subject>
+ <xsl:value-of select="dc:subject"/>
+ </o:Subject>
+ <o:Keywords>
+ <xsl:for-each select="meta:keywords/meta:keyword">
+ <xsl:value-of select="."/>
+ <xsl:if test="position()!=last()">, </xsl:if>
+ </xsl:for-each>
+ </o:Keywords>
+ <o:Description>
+ <xsl:value-of select="dc:description"/>
+ </o:Description>
+ <o:Category>
+ <xsl:value-of select="meta:user-defined[@meta:name = 'Category']"/>
+ </o:Category>
+ <o:Author>
+ <xsl:value-of select="meta:initial-creator"/>
+ </o:Author>
+ <o:LastAuthor>
+ <xsl:value-of select="dc:creator"/>
+ </o:LastAuthor>
+ <o:Manager>
+ <xsl:value-of select="meta:user-defined[@meta:name = 'Manager']"/>
+ </o:Manager>
+ <o:Company>
+ <xsl:value-of select="meta:user-defined[@meta:name = 'Company']"/>
+ </o:Company>
+ <o:HyperlinkBase>
+ <xsl:value-of select="meta:user-defined[@meta:name = 'HyperlinkBase']"/>
+ </o:HyperlinkBase>
+ <o:Revision>
+ <xsl:value-of select="meta:editing-cycles"/>
+ </o:Revision>
+ <!-- PresentationFormat, Guid, AppName, Version -->
+ <o:TotalTime>
+ <xsl:if test="meta:editing-duration">
+ <xsl:variable name="hours">
+ <xsl:choose>
+ <xsl:when test="contains(meta:editing-duration, 'H')">
+ <xsl:value-of select="substring-before( substring-after( meta:editing-duration, 'PT'), 'H')"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="minutes">
+ <xsl:choose>
+ <xsl:when test="contains(meta:editing-duration, 'M') and contains(meta:editing-duration, 'H')">
+ <xsl:value-of select="substring-before( substring-after( meta:editing-duration, 'H'), 'M')"/>
+ </xsl:when>
+ <xsl:when test="contains(meta:editing-duration, 'M')">
+ <xsl:value-of select="substring-before( substring-after( meta:editing-duration, 'PT'), 'M')"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$hours * 60 + $minutes"/>
+ </xsl:if>
+ </o:TotalTime>
+ <o:LastPrinted>
+ <xsl:if test="meta:print-date">
+ <xsl:value-of select="concat( meta:print-date, 'Z')"/>
+ </xsl:if>
+ </o:LastPrinted>
+ <o:Created>
+ <xsl:if test="meta:creation-date">
+ <xsl:value-of select="concat( meta:creation-date, 'Z')"/>
+ </xsl:if>
+ </o:Created>
+ <o:LastSaved>
+ <xsl:if test="dc:date">
+ <xsl:value-of select="concat( dc:date, 'Z')"/>
+ </xsl:if>
+ </o:LastSaved>
+ <o:Pages>
+ <xsl:value-of select="meta:document-statistic/@meta:page-count"/>
+ </o:Pages>
+ <o:Words>
+ <xsl:value-of select="meta:document-statistic/@meta:word-count"/>
+ </o:Words>
+ <o:Characters>
+ <xsl:value-of select="meta:document-statistic/@meta:character-count"/>
+ </o:Characters>
+ <!-- CharactersWithSpaces, Bytes, Lines -->
+ <o:Paragraphs>
+ <xsl:value-of select="meta:document-statistic/@meta:paragraph-count"/>
+ </o:Paragraphs>
+ </o:DocumentProperties>
+ <o:CustomDocumentProperties>
+ <o:Editor dt:dt="string">
+ <xsl:value-of select="meta:generator"/>
+ </o:Editor>
+ <o:Language dt:dt="string">
+ <xsl:value-of select="dc:language"/>
+ </o:Language>
+ <xsl:for-each select="meta:user-defined">
+ <!-- transfer strings to XML QName, necessary to convert several characters -->
+ <!-- &#x7b;&#x7d; -->
+ <xsl:variable name="foo">.,| ~`!@#$%^*()&amp;&lt;&gt;+=[];:&quot;/\?{}'</xsl:variable>
+ <xsl:element name="{concat( 'o:', translate(@meta:name,string($foo),'_'))}">
+ <xsl:attribute name="dt:dt">string</xsl:attribute>
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:for-each>
+ </o:CustomDocumentProperties>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/spreadsheetml/formular.xsl b/filter/source/xslt/export/spreadsheetml/formular.xsl
new file mode 100644
index 000000000..f284e342d
--- /dev/null
+++ b/filter/source/xslt/export/spreadsheetml/formular.xsl
@@ -0,0 +1,631 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xt="http://www.jclark.com/xt"
+ xmlns:common="http://exslt.org/common"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xlink xt common xalan">
+
+
+ <!-- Mapping @table:formula to @ss:Formula translating the expression syntax -->
+ <xsl:template match="@table:formula">
+ <xsl:param name="calculatedCellPosition" />
+ <xsl:param name="calculatedRowPosition" />
+
+ <xsl:attribute name="ss:Formula">
+ <xsl:call-template name="translate-formular-expression">
+ <xsl:with-param name="rowPos" select="$calculatedRowPosition" />
+ <xsl:with-param name="columnPos" select="$calculatedCellPosition" />
+ <xsl:with-param name="expression" select="." />
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:template>
+
+
+ <!-- Translate OOOC formula expressions of table cells to spreadsheetml expression
+
+ For example:
+ "oooc:=ROUNDDOWN(123.321;2)"
+ to "=ROUNDDOWN(123.321,2)"
+ "oooc:=([.B2]-[.C2])"
+ to "=(RC[-2]-RC[-1])"
+ "oooc:=DCOUNTA([.E14:.F21];[.F14];[.H14:.I15])"
+ to "=DCOUNTA(R[-17]C[3]:R[-10]C[4],R[-17]C[4],R[-17]C[6]:R[-16]C[7])" -->
+ <xsl:template name="translate-formular-expression">
+ <!-- return position or range for formula or other -->
+ <xsl:param name="rowPos" /> <!-- the position in row (vertical) of cell -->
+ <xsl:param name="columnPos" /> <!-- the position in column (horizontal of cell) -->
+ <xsl:param name="expression" /> <!-- the expression string to be converted -->
+
+ <xsl:choose>
+ <xsl:when test="$expression != ''">
+ <xsl:choose>
+ <!-- OASIS Open Document XML formular expressions -->
+ <xsl:when test="starts-with($expression,'oooc:')">
+ <!-- giving out the '=', which will be removed with 'oooc:=' to enable recursive string parsing -->
+ <xsl:text>=</xsl:text>
+ <xsl:call-template name="function-parameter-mapping">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <!-- 1) remove 'oooc:=' prefix and exchange ';' with ',' -->
+ <xsl:with-param name="expression" select="translate(substring($expression,7),';',',')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$expression" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$expression" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- As the function API of our Office and MS Office show differences in the argumentlists,
+ - sometimes the last parameter have to be neglected
+ - sometimes a default have to be added
+ these exchanges have to be done as well -->
+ <xsl:template name="function-parameter-mapping">
+ <xsl:param name="rowPos" /> <!-- the position in row (vertical of cell) -->
+ <xsl:param name="columnPos" /> <!-- the position in column (horizontal of cell) -->
+ <xsl:param name="expression" /> <!-- expression to be exchanged -->
+
+ <!-- Choose if the expression contains one of the function, which might need changes -->
+ <xsl:choose>
+ <!-- if not contain one of the functions, which need parameter mapping -->
+ <xsl:when test="not(contains($expression, 'ADDRESS(') or
+ contains($expression, 'CEILING(') or
+ contains($expression, 'FLOOR(') or
+ contains($expression, 'IF(') or
+ contains($expression, 'ROUND('))">
+ <!-- simply translate possibly existing column & row references -->
+ <xsl:call-template name="translate-oooc-expression">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="$expression"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- functions to be mapped -->
+ <xsl:otherwise>
+ <xsl:variable name="functionPrefix" select="substring-before($expression, '(')" />
+ <xsl:variable name="expressionSuffix" select="substring-after($expression, '(')" />
+
+ <!-- translate in case the expression contains row/cell references aside of the function name -->
+ <xsl:call-template name="translate-oooc-expression">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="$functionPrefix"/>
+ </xsl:call-template>
+ <!-- Prefix do not include the bracket -->
+ <xsl:text>(</xsl:text>
+ <xsl:choose>
+ <xsl:when test="not(contains($functionPrefix, 'ADDRESS') or
+ contains($functionPrefix, 'CEILING') or
+ contains($functionPrefix, 'FLOOR') or
+ (contains($functionPrefix, 'IF') and not(
+ contains($functionPrefix, 'COUNTIF') or
+ contains($functionPrefix, 'SUMIF'))) or
+ contains($functionPrefix, 'ROUND'))">
+ <xsl:call-template name="function-parameter-mapping">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="$expressionSuffix"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="contains($functionPrefix, 'ADDRESS')">
+ <xsl:call-template name="find-parameters">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ <xsl:with-param name="parameterRemoval" select="4" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($functionPrefix, 'CEILING') or
+ contains($functionPrefix, 'FLOOR')">
+ <xsl:call-template name="find-parameters">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ <xsl:with-param name="parameterRemoval" select="3" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($functionPrefix, 'IF')">
+ <xsl:if test="not(contains($functionPrefix, 'COUNTIF') or
+ contains($functionPrefix, 'SUMIF'))">
+ <xsl:call-template name="find-parameters">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ <xsl:with-param name="parameterAddition" select="'true'" />
+ <xsl:with-param name="additonAfterLastParameter" select="2" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="contains($functionPrefix, 'ROUND')">
+ <xsl:call-template name="find-parameters">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ <xsl:with-param name="parameterAddition" select="'null'" />
+ <xsl:with-param name="additonAfterLastParameter" select="1" />
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Each parameter of the argumentlist have to be determined.
+ Due to the low level string functionality in XSLT it becomes a clumsy task -->
+ <xsl:template name="find-parameters">
+ <!-- used for mapping of row/column reference -->
+ <xsl:param name="rowPos" /> <!-- the position in row (vertical of cell) -->
+ <xsl:param name="columnPos" /> <!-- the position in column (horizontal of cell) -->
+ <!-- used for mapping of parameter -->
+ <xsl:param name="parameterRemoval" />
+ <xsl:param name="parameterAddition" />
+ <xsl:param name="additonAfterLastParameter" />
+ <!-- used as helper to find a parameter -->
+ <xsl:param name="expressionSuffix" />
+ <xsl:param name="parameterNumber" select="1" />
+
+ <xsl:variable name="parameter">
+ <xsl:call-template name="getParameter">
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <!-- if it is not the last parameter -->
+ <xsl:when test="starts-with(substring-after($expressionSuffix, $parameter), ',')">
+ <!-- searches the argument for functions to be mapped -->
+ <xsl:if test="not($parameterRemoval = $parameterNumber)">
+ <xsl:call-template name="function-parameter-mapping">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression">
+ <xsl:choose>
+ <!-- in case a character will be removed the preceding won't make a comma -->
+ <xsl:when test="$parameterRemoval = ($parameterNumber + 1)">
+ <xsl:value-of select="$parameter" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($parameter, ',')" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <!-- searches for the next parameter -->
+ <xsl:call-template name="find-parameters">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expressionSuffix" select="substring-after(substring-after($expressionSuffix, $parameter),',')"/>
+ <xsl:with-param name="parameterAddition" select="$parameterAddition" />
+ <xsl:with-param name="parameterRemoval" select="$parameterRemoval" />
+ <xsl:with-param name="additonAfterLastParameter" select="$additonAfterLastParameter" />
+ <xsl:with-param name="parameterNumber" select="$parameterNumber + 1" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- the last parameter -->
+ <xsl:choose>
+ <xsl:when test="$parameterRemoval = $parameterNumber">
+ <!-- searches the rest of the expression for functions to be mapped -->
+ <xsl:call-template name="function-parameter-mapping">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="substring-after($expressionSuffix, $parameter)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$parameterAddition and ($parameterNumber = $additonAfterLastParameter)">
+ <!-- searches the rest of the expression for functions to be mapped -->
+ <xsl:call-template name="function-parameter-mapping">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="$parameter" />
+ </xsl:call-template>
+ <!-- searches last parameter and additional parameters for functions to be mapped -->
+ <xsl:call-template name="function-parameter-mapping">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <!-- for the final parameter the latter substring is the ')' -->
+ <xsl:with-param name="expression" select="concat(',', $parameterAddition, substring-after($expressionSuffix, $parameter))"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- searches the argument for functions to be mapped -->
+ <xsl:call-template name="function-parameter-mapping">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="$parameter" />
+ </xsl:call-template>
+ <!-- searches the rest of the expression for functions to be mapped -->
+ <xsl:call-template name="function-parameter-mapping">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="substring-after($expressionSuffix, $parameter)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="getParameter">
+ <xsl:param name="closingBracketCount" select="0" />
+ <xsl:param name="openingBracketCount" select="0" />
+ <xsl:param name="expressionSuffix" />
+ <xsl:param name="parameterCandidate">
+ <xsl:choose>
+ <!-- if there are multiple parameter -->
+ <xsl:when test="contains(substring-before($expressionSuffix, ')'), ',')">
+ <xsl:value-of select="substring-before($expressionSuffix, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($expressionSuffix, ')')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+ <xsl:param name="earlierCandidate" select="$parameterCandidate" />
+
+ <xsl:choose>
+ <xsl:when test="contains($parameterCandidate, '(') or contains($parameterCandidate, ')')">
+ <xsl:choose>
+ <!-- contains only closing bracket(s) -->
+ <xsl:when test="contains($parameterCandidate, '(') and not(contains($parameterCandidate, ')'))">
+ <xsl:call-template name="getParameter">
+ <xsl:with-param name="openingBracketCount" select="$openingBracketCount + 1" />
+ <xsl:with-param name="closingBracketCount" select="$closingBracketCount" />
+ <xsl:with-param name="parameterCandidate" select="substring-after($parameterCandidate, '(')" />
+ <xsl:with-param name="earlierCandidate" select="$earlierCandidate" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- contains only opening bracket(s) -->
+ <xsl:when test="not(contains($parameterCandidate, '(')) and contains($parameterCandidate, ')')">
+ <xsl:call-template name="getParameter">
+ <xsl:with-param name="openingBracketCount" select="$openingBracketCount" />
+ <xsl:with-param name="closingBracketCount" select="$closingBracketCount + 1" />
+ <xsl:with-param name="parameterCandidate" select="substring-after($parameterCandidate, ')')" />
+ <xsl:with-param name="earlierCandidate" select="$earlierCandidate" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="string-length(substring-before($parameterCandidate, '(')) &lt;
+ string-length(substring-before($parameterCandidate, ')'))">
+ <xsl:call-template name="getParameter">
+ <xsl:with-param name="openingBracketCount" select="$openingBracketCount + 1" />
+ <xsl:with-param name="closingBracketCount" select="$closingBracketCount" />
+ <xsl:with-param name="parameterCandidate" select="substring-after($parameterCandidate, '(')" />
+ <xsl:with-param name="earlierCandidate" select="$earlierCandidate" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="getParameter">
+ <xsl:with-param name="openingBracketCount" select="$openingBracketCount" />
+ <xsl:with-param name="closingBracketCount" select="$closingBracketCount + 1" />
+ <xsl:with-param name="parameterCandidate" select="substring-after($parameterCandidate, ')')" />
+ <xsl:with-param name="earlierCandidate" select="$earlierCandidate" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$openingBracketCount = $closingBracketCount">
+ <xsl:value-of select="$earlierCandidate" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$earlierCandidate" />
+ <xsl:variable name="parameterCandidate2">
+ <xsl:variable name="formularAfterCandidate" select="substring-after($expressionSuffix, $earlierCandidate)" />
+ <xsl:variable name="parameterTillBracket" select="concat(substring-before($formularAfterCandidate,')'),')')" />
+ <xsl:variable name="parameterTillComma" select="substring-before(substring-after($expressionSuffix, $parameterTillBracket),',')" />
+ <xsl:choose>
+ <xsl:when test="string-length($parameterTillComma) &gt; 0 and
+ not(contains($parameterTillComma, '('))">
+ <xsl:choose>
+ <xsl:when test="starts-with($formularAfterCandidate, ',')">
+ <xsl:value-of select="concat(',',substring-before(substring-after($formularAfterCandidate,','),','))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($formularAfterCandidate,',')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$parameterTillBracket"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="getParameter">
+ <xsl:with-param name="closingBracketCount" select="$closingBracketCount" />
+ <xsl:with-param name="openingBracketCount" select="$openingBracketCount" />
+ <xsl:with-param name="parameterCandidate" select="$parameterCandidate2" />
+ <xsl:with-param name="earlierCandidate" select="$parameterCandidate2" />
+ <xsl:with-param name="expressionSuffix" select="$expressionSuffix" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Mapping table-cell definitions by exchangomg all table cell definitions:
+ a) a pair of cells e.g. "[.E14:.F21]" to "R[-17]C[3]:R[-10]C[4]"
+ b) a single cell e.g. "[.F14]" to "R[-17]"-->
+ <xsl:template name="translate-oooc-expression">
+ <xsl:param name="rowPos" /> <!-- the position in row (vertical of cell) -->
+ <xsl:param name="columnPos" /> <!-- the position in column (horizontal of cell) -->
+ <xsl:param name="expression" /> <!-- expression to be exchanged -->
+
+ <xsl:choose>
+ <xsl:when test="contains($expression, '[')">
+
+ <!-- Giving out the part before '[.' -->
+ <xsl:value-of select="substring-before($expression, '[')" />
+
+ <!-- Mapping cell definitions
+ 1) a pair of cells e.g. "[.E14:.F21]" to "R[-17]C[3]:R[-10]C[4]"
+ 2) a single cell e.g. "[.F14]" to "R[-17]"-->
+ <xsl:variable name="remainingExpression" select="substring-after($expression, '[')"/>
+ <xsl:choose>
+ <xsl:when test="contains(substring-before($remainingExpression, ']'), ':')">
+ <xsl:call-template name="translate-cell-expression">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="substring-before($remainingExpression, ':')" />
+ </xsl:call-template>
+ <xsl:value-of select="':'" />
+ <xsl:call-template name="translate-cell-expression">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="substring-after(substring-before($remainingExpression, ']'), ':')" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="translate-cell-expression">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="substring-before($remainingExpression, ']')" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="translate-oooc-expression">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="substring-after($remainingExpression,']')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Giving out the remaining part -->
+ <xsl:value-of select="$expression" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- A cell expression has usually starts with a '.' otherwise it references to a sheet -->
+ <xsl:template name="translate-cell-expression">
+ <xsl:param name="rowPos" /> <!-- the vertical position of the current cell -->
+ <xsl:param name="columnPos" /> <!-- the horizontal position of the current cell -->
+ <xsl:param name="targetRowPos" select="0"/> <!-- the vertical position of the target cell -->
+ <xsl:param name="targetColumnPos" select="0"/> <!-- the horizontal position of the target cell -->
+ <xsl:param name="charPos" select="0"/> <!-- current column position (needed for multiplying) -->
+ <xsl:param name="digitPos" select="0"/> <!-- current row position (needed for multiplying) -->
+ <xsl:param name="expression" /> <!-- expression to be parsed by character -->
+ <xsl:param name="isRow" select="true()"/> <!-- the string (e.g. $D39 is parsed character per character from the back,
+ first the row, later the column is parsed -->
+
+ <xsl:choose>
+ <xsl:when test="starts-with($expression, '.')">
+ <xsl:variable name="expLength" select="string-length($expression)" />
+ <xsl:choose>
+ <!-- parsing from the end, till only the '.' remains -->
+ <xsl:when test="$expLength != 1">
+ <xsl:variable name="token" select="substring($expression, $expLength)" />
+ <xsl:choose>
+ <xsl:when test="$token='0' or $token='1' or $token='2' or $token='3' or $token='4' or $token='5' or $token='6' or $token='7' or $token='8' or $token='9'">
+ <xsl:variable name="multiplier">
+ <xsl:call-template name="calculate-square-numbers">
+ <xsl:with-param name="base" select="10" />
+ <xsl:with-param name="exponent" select="$digitPos"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="translate-cell-expression">
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="targetColumnPos" select="$targetColumnPos" />
+ <xsl:with-param name="targetRowPos" select="$targetRowPos + $multiplier * $token" />
+ <xsl:with-param name="digitPos" select="$digitPos + 1" />
+ <xsl:with-param name="charPos" select="$charPos" />
+ <!-- removing the last character-->
+ <xsl:with-param name="expression" select="substring($expression, 1, $expLength - 1)" />
+ <xsl:with-param name="isRow" select="true()" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$token = '$'">
+ <xsl:choose>
+ <!-- if this is the first '$' after '.' (column-->
+ <xsl:when test="$expLength = 2">
+ <xsl:text>C</xsl:text><xsl:value-of select="$targetColumnPos"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>R</xsl:text><xsl:value-of select="$targetRowPos"/>
+ <xsl:call-template name="translate-cell-expression">
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="targetColumnPos" select="$targetColumnPos" />
+ <xsl:with-param name="targetRowPos" select="$targetRowPos" />
+ <xsl:with-param name="charPos" select="$charPos" />
+ <!-- removing the last character-->
+ <xsl:with-param name="expression" select="substring($expression, 1, $expLength - 1)" />
+ <xsl:with-param name="isRow" select="false()" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- in case of a letter -->
+ <xsl:otherwise>
+ <xsl:if test="$isRow">
+ <xsl:text>R</xsl:text>
+ <xsl:if test="$targetRowPos != $rowPos">
+ <xsl:text>[</xsl:text><xsl:value-of select="$targetRowPos - $rowPos"/><xsl:text>]</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ <xsl:variable name="multiplier">
+ <xsl:call-template name="calculate-square-numbers">
+ <xsl:with-param name="base" select="26" />
+ <xsl:with-param name="exponent" select="$charPos"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="tokenNumber">
+ <xsl:call-template name="character-to-number">
+ <xsl:with-param name="character" select="$token" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:call-template name="translate-cell-expression">
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="targetColumnPos" select="$targetColumnPos + $multiplier * $tokenNumber" />
+ <xsl:with-param name="targetRowPos" select="$targetRowPos" />
+ <xsl:with-param name="digitPos" select="$digitPos" />
+ <xsl:with-param name="charPos" select="$charPos + 1" />
+ <!-- removing the last character-->
+ <xsl:with-param name="expression" select="substring($expression, 1, $expLength - 1)" />
+ <xsl:with-param name="isRow" select="false()" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>C</xsl:text>
+ <xsl:if test="$targetColumnPos != $columnPos">
+ <xsl:text>[</xsl:text><xsl:value-of select="$targetColumnPos - $columnPos"/><xsl:text>]</xsl:text>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="sheetName" select="substring-before($expression, '.')" />
+ <xsl:value-of select="$sheetName"/><xsl:text>!</xsl:text>
+ <xsl:call-template name="translate-cell-expression">
+ <xsl:with-param name="rowPos" select="$rowPos" />
+ <xsl:with-param name="columnPos" select="$columnPos" />
+ <xsl:with-param name="expression" select="substring-after($expression, $sheetName)" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="calculate-square-numbers">
+ <xsl:param name="base" />
+ <xsl:param name="exponent" />
+ <xsl:param name="return" select="1" />
+
+ <xsl:choose>
+ <xsl:when test="$exponent > '1'">
+ <xsl:call-template name="calculate-square-numbers">
+ <xsl:with-param name="base" select="$base" />
+ <xsl:with-param name="exponent" select="$exponent - 1"/>
+ <xsl:with-param name="return" select="$return * $base" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$exponent = '1'">
+ <xsl:value-of select="$return * $base"/>
+ </xsl:when>
+ <!-- if exponent is equal '0' -->
+ <xsl:otherwise>
+ <xsl:value-of select="1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="character-to-number">
+ <xsl:param name="character" />
+ <xsl:choose>
+ <xsl:when test="$character = 'A'">1</xsl:when>
+ <xsl:when test="$character = 'B'">2</xsl:when>
+ <xsl:when test="$character = 'C'">3</xsl:when>
+ <xsl:when test="$character = 'D'">4</xsl:when>
+ <xsl:when test="$character = 'E'">5</xsl:when>
+ <xsl:when test="$character = 'F'">6</xsl:when>
+ <xsl:when test="$character = 'G'">7</xsl:when>
+ <xsl:when test="$character = 'H'">8</xsl:when>
+ <xsl:when test="$character = 'I'">9</xsl:when>
+ <xsl:when test="$character = 'J'">10</xsl:when>
+ <xsl:when test="$character = 'K'">11</xsl:when>
+ <xsl:when test="$character = 'L'">12</xsl:when>
+ <xsl:when test="$character = 'M'">13</xsl:when>
+ <xsl:when test="$character = 'N'">14</xsl:when>
+ <xsl:when test="$character = 'O'">15</xsl:when>
+ <xsl:when test="$character = 'P'">16</xsl:when>
+ <xsl:when test="$character = 'Q'">17</xsl:when>
+ <xsl:when test="$character = 'R'">18</xsl:when>
+ <xsl:when test="$character = 'S'">19</xsl:when>
+ <xsl:when test="$character = 'T'">20</xsl:when>
+ <xsl:when test="$character = 'U'">21</xsl:when>
+ <xsl:when test="$character = 'V'">22</xsl:when>
+ <xsl:when test="$character = 'W'">23</xsl:when>
+ <xsl:when test="$character = 'X'">24</xsl:when>
+ <xsl:when test="$character = 'Y'">25</xsl:when>
+ <xsl:when test="$character = 'Z'">26</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/spreadsheetml/ooo2spreadsheetml.xsl b/filter/source/xslt/export/spreadsheetml/ooo2spreadsheetml.xsl
new file mode 100644
index 000000000..321369efc
--- /dev/null
+++ b/filter/source/xslt/export/spreadsheetml/ooo2spreadsheetml.xsl
@@ -0,0 +1,408 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xlink">
+
+
+ <!--+++++ INCLUDED XSL MODULES +++++-->
+
+ <!-- helper collection, to convert measures (e.g. inch to pixel using DPI (dots per inch) parameter)-->
+ <xsl:import href="../../common/measure_conversion.xsl" />
+
+ <!-- excel table handling -->
+ <xsl:include href="table.xsl" />
+
+ <!-- mapping rules of office style properties to Excel style properties -->
+ <xsl:include href="style_mapping.xsl" />
+
+ <!-- creating the Excel styles element -->
+ <xsl:include href="styles.xsl" />
+
+ <!-- mapping formular Expressions -->
+ <xsl:include href="formular.xsl" />
+
+ <xsl:output method = "xml"
+ indent = "no"
+ encoding = "UTF-8"
+ omit-xml-declaration = "no" />
+
+ <xsl:strip-space elements="ss:Data html:Data" />
+
+
+ <!-- common table handling -->
+ <xsl:variable name="namespace" select="'urn:schemas-microsoft-com:office:spreadsheet'" />
+
+ <!--+++++ PARAMETER SECTION +++++-->
+
+ <!-- OPTIONAL: (MANDATORY: for all input document with relative external links): parameter is a (relative) URL to the target directory.
+ Relative links from the office document (e.g. to external graphics) will get this parameter as a prefix -->
+ <xsl:param name="targetBaseURL" select="'./'" />
+
+ <!-- OPTIONAL: (MANDATORY: for input document with relative internal links)
+ To access contents of an office file (content like the meta.xml, styles.xml file or graphics) a URL could be chosen.
+ This could be even a JAR URL. The sourceBase of the content URL "jar:file:/C:/temp/Test.sxw!/content.xml" would be
+ "jar:file:/C:/temp/Test.sxw!/" for example.
+ When working with OpenOffice API a Package-URL encoded over HTTP can be used to access the jared contents of the jared document. -->
+ <xsl:param name="sourceBaseURL" select="'./'" />
+
+ <!-- OPTIONAL: (MANDATORY: for session management by URL rewriting)
+ Useful for WebApplications: if a HTTP session is not cookie based, URL rewriting is being used (the session is appended to the URL).
+ This URL session is used for example when links to graphics are created by XSLT. Otherwise the user has to log again in for every graphic he likes to see. -->
+ <xsl:param name="optionalURLSuffix" />
+
+ <!-- OPTIONAL: URL to office meta file (flat xml use the URL to the input file) -->
+ <xsl:param name="metaFileURL" />
+
+ <!-- OPTIONAL: URL to office meta file (flat xml use the URL to the input file) -->
+ <xsl:param name="stylesFileURL" />
+
+ <!-- OPTIONAL: in case of using a different processor than a JAVA XSLT, you can unable the Java functionality
+ (e.g. encoding chapter names for the content-table as href and anchors ) -->
+ <xsl:param name="java" select="true()" />
+ <xsl:param name="javaEnabled" select="boolean($java)" />
+
+ <!-- OPTIONAL: for activating the debug mode set the variable here to 'true()' or give any value from outside -->
+ <xsl:param name="debug" select="false()" />
+ <xsl:param name="debugEnabled" select="boolean($debug)" />
+
+ <!-- matching configuration entries -->
+ <xsl:key name="config" use="@config:name"
+ match="/*/office:settings/config:config-item-set/config:config-item-map-indexed/config:config-item-map-entry/config:config-item |
+ /*/office:settings/config:config-item-set/config:config-item-map-indexed/config:config-item-map-entry/config:config-item-map-named/config:config-item-map-entry/config:config-item" />
+
+ <xsl:key name="colors" match="/*/office:styles//@*[name() = 'fo:background-color' or name() = 'fo:color'] |
+ /*/office:automatic-styles//@*[name() = 'fo:background-color' or name() = 'fo:color']" use="/" />
+ <xsl:key name="colorRGB" match="@fo:background-color | @fo:color" use="." />
+ <!-- *************************** -->
+ <!-- *** Built up Excel file *** -->
+ <!-- *************************** -->
+ <xsl:template match="/">
+ <xsl:processing-instruction name="mso-application">progid="Excel.Sheet"</xsl:processing-instruction>
+ <!-- Note: for debugging purpose include schema location
+ <Workbook xsi:schemaLocation="urn:schemas-microsoft-com:office:spreadsheet <YOUR_SCHEMA_URL>/excelss.xsd"> -->
+ <Workbook>
+ <!-- adding some default settings -->
+ <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
+ <Colors>
+ <xsl:for-each select="key('colors', /)
+ [generate-id(.) =
+ generate-id(key('colorRGB', .)[1]) and starts-with(., '#')] ">
+ <xsl:sort select="." />
+ <Color>
+ <Index><xsl:value-of select="position() + 2" /></Index>
+ <RGB><xsl:value-of select="." /></RGB>
+ </Color>
+ </xsl:for-each>
+ <xsl:for-each select="key('config', 'TabColor')[not(.=preceding::config:config-item)]">
+ <xsl:sort select="." />
+ <Color>
+ <Index><xsl:value-of select="56 - position()" /></Index>
+ <RGB>
+ <xsl:call-template name="colordecimal2rgb">
+ <xsl:with-param name="colordecimal" select="."/>
+ </xsl:call-template>
+ </RGB>
+ </Color>
+ </xsl:for-each>
+ </Colors>
+ </OfficeDocumentSettings>
+ <ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">
+ <xsl:if test="key('config', 'HasSheetTabs') = 'false'">
+ <xsl:element name="HideWorkbookTabs" />
+ </xsl:if>
+ <WindowHeight>9000</WindowHeight>
+ <WindowWidth>13860</WindowWidth>
+ <WindowTopX>240</WindowTopX>
+ <WindowTopY>75</WindowTopY>
+ <ProtectStructure>False</ProtectStructure>
+ <ProtectWindows>False</ProtectWindows>
+ </ExcelWorkbook>
+ <!-- Note: the following handling will exchange the default, later
+ <x:ExcelWorkbook>
+ <xsl:apply-templates select="table:calculation-settings" />
+ </x:ExcelWorkbook>
+ -->
+ <xsl:element name="Styles">
+ <!-- our application default will not be used for export to Excel
+ <xsl:apply-templates select="/*/office:styles/style:default-style" mode="styles" />-->
+ <xsl:apply-templates select="/*/office:styles/style:style" mode="styles" />
+ <xsl:apply-templates select="/*/office:automatic-styles/style:style" mode="styles" >
+ <xsl:with-param name="isAutomatic" select="true()" />
+ </xsl:apply-templates>
+ </xsl:element>
+ <xsl:apply-templates select="/*/office:body" />
+ </Workbook>
+ </xsl:template>
+
+ <xsl:template name="colordecimal2rgb">
+ <xsl:param name="colordecimal"/>
+ <xsl:choose>
+ <xsl:when test="$colordecimal &lt;= 16777215 and $colordecimal &gt;= 65536">
+ <xsl:variable name="redValue" select="floor(($colordecimal) div 65536)"/>
+ <xsl:variable name="greenValue" select="floor(($colordecimal - ($redValue*65536)) div 256)"/>
+ <xsl:variable name="blueValue" select="$colordecimal - ($redValue*65536) - ($greenValue*256)"/>
+ <xsl:call-template name="dec_rgb2Hex">
+ <xsl:with-param name="decRedValue" select="$redValue"/>
+ <xsl:with-param name="decGreenValue" select="$greenValue"/>
+ <xsl:with-param name="decBlueValue" select="$blueValue"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$colordecimal &lt;= 65535 and $colordecimal &gt;= 256">
+ <xsl:variable name="redValue" select="0"/>
+ <xsl:variable name="greenValue" select="$colordecimal div 256"/>
+ <xsl:variable name="blueValue" select="$colordecimal - ($greenValue*256)"/>
+ <xsl:call-template name="dec_rgb2Hex">
+ <xsl:with-param name="decRedValue" select="$redValue"/>
+ <xsl:with-param name="decGreenValue" select="$greenValue"/>
+ <xsl:with-param name="decBlueValue" select="$blueValue"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$colordecimal &lt;= 255 and $colordecimal &gt;= 0">
+ <xsl:variable name="redValue" select="0"/>
+ <xsl:variable name="greenValue" select="0"/>
+ <xsl:variable name="blueValue" select="$colordecimal"/>
+ <xsl:call-template name="dec_rgb2Hex">
+ <xsl:with-param name="decRedValue" select="$redValue"/>
+ <xsl:with-param name="decGreenValue" select="$greenValue"/>
+ <xsl:with-param name="decBlueValue" select="$blueValue"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="dec_rgb2Hex">
+ <xsl:param name="decRedValue"/>
+ <xsl:param name="decGreenValue"/>
+ <xsl:param name="decBlueValue"/>
+ <xsl:variable name="hexRedValue">
+ <xsl:variable name="tmpHexRedValue">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="$decRedValue"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($tmpHexRedValue) = 1">
+ <xsl:value-of select="concat('0',$tmpHexRedValue)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$tmpHexRedValue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="hexGreenValue">
+ <xsl:variable name="tmpHexGreenValue">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="$decGreenValue"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($tmpHexGreenValue) = 1">
+ <xsl:value-of select="concat('0',$tmpHexGreenValue)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$tmpHexGreenValue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="hexBlueValue">
+ <xsl:variable name="tmpHexBlueValue">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="$decBlueValue"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($tmpHexBlueValue) = 1">
+ <xsl:value-of select="concat('0',$tmpHexBlueValue)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$tmpHexBlueValue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat('#',$hexRedValue,$hexGreenValue,$hexBlueValue)"/>
+ </xsl:template>
+ <xsl:template name="decimal2hex">
+ <!-- transforms a decimal number to a hex number,only for two-bit hex(less than 256 in decimal) currently -->
+ <xsl:param name="dec-number"/>
+ <xsl:param name="last-value"/>
+ <xsl:variable name="current-value">
+ <xsl:call-template name="decNumber2hex">
+ <xsl:with-param name="dec-value">
+ <xsl:if test="$dec-number &gt; 15">
+ <xsl:value-of select="floor($dec-number div 16)"/>
+ </xsl:if>
+ <xsl:if test="$dec-number &lt; 16">
+ <xsl:value-of select="$dec-number"/>
+ </xsl:if>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$dec-number &gt; 15">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="$dec-number mod 16"/>
+ <xsl:with-param name="last-value" select="concat($last-value,$current-value)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$dec-number &lt; 16">
+ <xsl:value-of select="substring-after(concat($last-value,$current-value),'H')"/>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="decNumber2hex">
+ <!-- return a hex number for a decimal character -->
+ <xsl:param name="dec-value"/>
+ <xsl:choose>
+ <xsl:when test="$dec-value = 10">
+ <xsl:value-of select="'A'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 11">
+ <xsl:value-of select="'B'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 12">
+ <xsl:value-of select="'C'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 13">
+ <xsl:value-of select="'D'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 14">
+ <xsl:value-of select="'E'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 15">
+ <xsl:value-of select="'F'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$dec-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="GetTabColorIndex">
+ <xsl:param name="SheetColor"/>
+ <xsl:for-each select="key('config', 'TabColor')[not(.=preceding::config:config-item)]">
+ <xsl:sort select="." />
+ <xsl:variable name="tmpColor" select="."/>
+ <xsl:if test=". = $SheetColor" >
+ <xsl:value-of select="56 - position()"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="office:body">
+ <!-- office:body table:table children are spreadsheets -->
+ <xsl:apply-templates />
+ </xsl:template>
+
+ <xsl:template match="office:spreadsheet">
+ <xsl:apply-templates />
+ </xsl:template>
+
+ <!-- office:body table:table children are spreadsheets -->
+ <xsl:template match="office:spreadsheet/table:table">
+ <xsl:element name="ss:Worksheet">
+ <xsl:variable name="TableName">
+ <xsl:value-of select="@table:name" />
+ </xsl:variable>
+ <xsl:attribute name="ss:Name">
+ <xsl:value-of select="$TableName" />
+ </xsl:attribute>
+ <xsl:call-template name="table:table" />
+ <xsl:element name="x:WorksheetOptions">
+ <xsl:if test="key('config', 'ShowGrid') = 'false'">
+ <xsl:element name="x:DoNotDisplayGridlines" />
+ </xsl:if>
+ <xsl:if test="key('config', 'HasColumnRowHeaders') = 'false'">
+ <xsl:element name="x:DoNotDisplayHeadings" />
+ </xsl:if>
+ <xsl:if test="key('config', 'IsOutlineSymbolsSet') = 'false'">
+ <xsl:element name="x:DoNotDisplayOutline" />
+ </xsl:if>
+ <xsl:if test="key('config', 'ShowZeroValues') = 'false'">
+ <xsl:element name="x:DoNotDisplayZeros" />
+ </xsl:if>
+ <xsl:if test="/*/office:settings/config:config-item-set/config:config-item-map-indexed/config:config-item-map-entry/config:config-item-map-named/config:config-item-map-entry[@config:name=$TableName]/config:config-item[@config:name='TabColor']">
+ <xsl:element name="x:TabColorIndex">
+ <xsl:variable name="TabColorIndex">
+ <xsl:call-template name="GetTabColorIndex">
+ <xsl:with-param name="SheetColor" select="/*/office:settings/config:config-item-set/config:config-item-map-indexed/config:config-item-map-entry/config:config-item-map-named/config:config-item-map-entry[@config:name=$TableName]/config:config-item[@config:name='TabColor']"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$TabColorIndex"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="table:decls" mode="ExcelWorkbook">
+ <xsl:apply-templates mode="ExcelWorkbook" />
+ </xsl:template>
+
+ <xsl:template match="table:calculation-settings" mode="ExcelWorkbook">
+ <xsl:if test="table:precision-as-shown">
+ <x:PrecisionAsDisplayed/>
+ </xsl:if>
+ <xsl:if test="table:null-date/@office:date-value='1904-01-01'">
+ <x:Date1904/>
+ </xsl:if>
+ <xsl:apply-templates select="table:iteration" />
+ </xsl:template>
+
+ <xsl:template match="table:iteration" mode="ExcelWorkbook">
+ <xsl:element name="x:ExcelWorkbook">
+ <xsl:if test="@table:status = 'enable'">
+ <x:Iteration/>
+ </xsl:if>
+ <xsl:if test="@table:steps">
+ <xsl:element name="x:MaxIterations">
+ <xsl:value-of select="@table:steps" />
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@table:maximum-difference">
+ <xsl:element name="x:MaxChange">
+ <xsl:value-of select="@table:maximum-difference" />
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/spreadsheetml/style_mapping.xsl b/filter/source/xslt/export/spreadsheetml/style_mapping.xsl
new file mode 100644
index 000000000..b338afcc2
--- /dev/null
+++ b/filter/source/xslt/export/spreadsheetml/style_mapping.xsl
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xt="http://www.jclark.com/xt"
+ xmlns:common="http://exslt.org/common"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xlink xt common xalan">
+
+ <xsl:variable name="namespace-html" select="'http://www.w3.org/TR/REC-html40'" />
+
+ <xsl:template match="@table:style-name | @table:default-cell-style-name">
+ <xsl:if test="not(name() = 'Default')">
+ <xsl:attribute name="ss:StyleID">
+ <xsl:value-of select="." />
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:key match="table:table-cell" name="getCellByStyle" use="@table:style-name"/>
+ <xsl:template match="@table:style-name" mode="table-row">
+ <!-- only row styles used by cells are exported,
+ as usual row style properties are already written as row attributes -->
+ <xsl:if test="key('getCellByStyle', '.')">
+ <xsl:attribute name="ss:StyleID">
+ <xsl:value-of select="." />
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="style-and-contents">
+ <xsl:param name="cellStyleName" />
+
+ <!-- WorkAround of Excel2003 issue:
+ Styles from the CellStyle will not be inherited to HTML content (e.g. Colour style).
+ -->
+ <xsl:choose>
+ <xsl:when test="@text:style-name">
+ <xsl:variable name="styles">
+ <xsl:copy-of select="key('styles', @text:style-name)/*" />
+ <xsl:copy-of select="key('styles', $cellStyleName)/*" />
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="create-nested-format-tags">
+ <xsl:with-param name="styles" select="xalan:nodeset($styles)" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="create-nested-format-tags">
+ <xsl:with-param name="styles" select="xt:node-set($styles)" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="create-nested-format-tags">
+ <xsl:with-param name="styles" select="common:node-set($styles)" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@table:style-name">
+ <xsl:variable name="styles">
+ <xsl:copy-of select="key('styles', @text:style-name)/*" />
+ <xsl:copy-of select="key('styles', $cellStyleName)/*" />
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="create-nested-format-tags">
+ <xsl:with-param name="styles" select="xalan:nodeset($styles)" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="create-nested-format-tags">
+ <xsl:with-param name="styles" select="xt:node-set($styles)" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="create-nested-format-tags">
+ <xsl:with-param name="styles" select="common:node-set($styles)" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- *********************************** -->
+ <!-- *** creating nested format tags *** -->
+ <!-- *********************************** -->
+
+ <!-- Bold -->
+ <xsl:template name="create-nested-format-tags">
+ <xsl:param name="styles" />
+ <xsl:param name="cellStyleName" />
+
+ <xsl:choose>
+ <xsl:when test="$styles/*/@fo:font-weight = 'bold' or $styles/*/@fo:font-weight = 'bolder'">
+ <xsl:element namespace="{$namespace-html}" name="B">
+ <xsl:call-template name="italic">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="italic">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- Italic -->
+ <xsl:template name="italic">
+ <xsl:param name="styles" />
+ <xsl:param name="cellStyleName" />
+
+ <xsl:choose>
+ <xsl:when test="$styles/*/@fo:font-style = 'italic' or $styles/*/@fo:font-style = 'oblique'">
+ <xsl:element namespace="{$namespace-html}" name="I">
+ <xsl:call-template name="underline">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="underline">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- Underline -->
+ <xsl:template name="underline">
+ <xsl:param name="styles" />
+ <xsl:param name="cellStyleName" />
+
+ <xsl:choose>
+ <xsl:when test="$styles/*/@style:text-underline-type and not($styles/*/@style:text-underline-type = 'none')">
+ <xsl:element namespace="{$namespace-html}" name="U">
+ <xsl:call-template name="strikethrough">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="strikethrough">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+
+ <!-- strikethrough -->
+ <xsl:template name="strikethrough">
+ <xsl:param name="styles" />
+ <xsl:param name="cellStyleName" />
+
+ <xsl:choose>
+ <xsl:when test="$styles/*/@style:text-line-through-style and not($styles/*/@style:text-line-through-style = 'none')">
+ <xsl:element namespace="{$namespace-html}" name="S">
+ <xsl:call-template name="super-subscript">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="super-subscript">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+
+ <!-- superscript & subscript -->
+ <xsl:template name="super-subscript">
+ <xsl:param name="styles" />
+ <xsl:param name="cellStyleName" />
+
+ <xsl:choose>
+ <xsl:when test="$styles/*/@style:text-position">
+ <xsl:variable name="textPosition" select="number(substring-before($styles/*/@style:text-position, '% '))" />
+ <xsl:choose>
+ <xsl:when test="$textPosition &gt; 0">
+ <xsl:element namespace="{$namespace-html}" name="Sup">
+ <xsl:call-template name="align">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="$textPosition &lt; 0">
+ <xsl:element namespace="{$namespace-html}" name="Sub">
+ <xsl:call-template name="align">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="align">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="align">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- Alignment - normally called by strikethrough, but no DIV elements in HTML -->
+ <xsl:template name="align">
+ <xsl:param name="styles" />
+ <xsl:param name="cellStyleName" />
+
+ <xsl:choose>
+ <xsl:when test="$styles/*/@fo:font-align">
+ <xsl:element namespace="{$namespace-html}" name="DIV">
+ <xsl:attribute name="html:style">
+ <xsl:choose>
+ <xsl:when test="$styles/*/@fo:font-align = 'start'">
+ <xsl:text>text-align:left;</xsl:text>
+ </xsl:when>
+ <xsl:when test="$styles/*/@fo:font-align = 'end'">
+ <xsl:text>text-align:right;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>text-align:center;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:call-template name="font">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="font">
+ <xsl:with-param name="styles" select="$styles" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- Font (size and color) -->
+ <xsl:template name="font">
+ <xsl:param name="styles" />
+ <xsl:param name="cellStyleName" />
+
+ <xsl:choose>
+ <xsl:when test="$styles/*/@style:font-name or
+ $styles/*/@fo:font-size or
+ $styles/*/@fo:color">
+ <xsl:element namespace="{$namespace-html}" name="Font">
+ <xsl:if test="$styles/*/@style:font-name">
+ <xsl:attribute name="html:Face">
+ <xsl:value-of select="$styles/*/@style:font-name" />
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styles/*/@fo:color">
+ <xsl:attribute name="html:Color">
+ <xsl:value-of select="$styles/*/@fo:color" />
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styles/*/@fo:font-size">
+ <!-- WORKAROUND TO EXCEL2003 issue where nested FONT elements with size attributes result in unloadable documents -->
+ <!-- Only create size attribute if parent do not have already one -->
+
+ <!--<xsl:choose>
+ <xsl:when test="not(key('styles', parent::*/@text:style-name)/*/@fo:font-size)"> -->
+ <xsl:if test="not(key('styles', parent::*/@text:style-name)/*/@fo:font-size)">
+ <xsl:attribute name="html:Size">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$styles/*/@fo:font-size" />
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <!--</xsl:when>
+ <xsl:otherwise>
+ <xsl:message>Due Excel issue we have to neglect size from @text:style-name '<xsl:value-of select="@text:style-name"/>'!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>-->
+ </xsl:if>
+ <!-- get the embedded content -->
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- get the embedded content -->
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/spreadsheetml/styles.xsl b/filter/source/xslt/export/spreadsheetml/styles.xsl
new file mode 100644
index 000000000..a3c4b8bae
--- /dev/null
+++ b/filter/source/xslt/export/spreadsheetml/styles.xsl
@@ -0,0 +1,686 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xt="http://www.jclark.com/xt"
+ xmlns:common="http://exslt.org/common"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xlink xt common xalan">
+
+ <!-- Used in case of 'style:map', conditional formatting, where a style references to another -->
+ <xsl:key name="styles" match="/*/office:styles/style:style | /*/office:automatic-styles/style:style" use="@style:name" />
+ <!--
+ Mapping of OOo style:name and style:family to excel ss:ID
+ Styles form style:style map from style:name to ss:Name
+ style:parent-style map to ss:Parent
+ -->
+ <!-- default styles of the application
+ <xsl:template match="style:default-style" mode="styles" >
+ <xsl:call-template name="style:style">
+ <xsl:with-param name="styleName" select="'Default'" />
+ </xsl:call-template>
+ </xsl:template>
+ -->
+
+ <xsl:template match="style:style" mode="styles">
+ <xsl:param name="isAutomatic" />
+ <xsl:param name="styleName" select="@style:name" />
+ <xsl:param name="styleParentName" select="@style:parent-style-name" />
+
+ <!-- only row styles used by cells are exported,
+ as usual row style properties are already exported as row attributes -->
+ <xsl:if test="not(@style:family='table-row') or @style:family='table-row' and key('getCellByStyle', '.')">
+ <xsl:element name="Style">
+ <xsl:attribute name="ss:ID">
+ <!-- neglecting that a style is only unique in conjunction with its family name -->
+ <xsl:value-of select="@style:name" />
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="not($isAutomatic)">
+ <xsl:choose>
+ <xsl:when test="@style:display-name">
+ <xsl:attribute name="ss:Name"><xsl:value-of select="@style:display-name"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="ss:Name"><xsl:value-of select="@style:name" /></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <!-- when a non-allowed parent style is found
+ (in spreadsheetml no style with ss:Name is able to have a ss:Parent) -->
+ <xsl:when test="@style:parent-style-name">
+ <!-- styles have to be merged (flatting heritance tree) -->
+ <xsl:variable name="stylePropertiesContainer">
+ <xsl:call-template name="merge-all-parent-styles">
+ <xsl:with-param name="currentStyle" select="." />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="write-style-properties">
+ <xsl:with-param name="styleProperties" select="xalan:nodeset($stylePropertiesContainer)/*" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="write-style-properties">
+ <xsl:with-param name="styleProperties" select="common:node-set($stylePropertiesContainer)/*" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="write-style-properties">
+ <xsl:with-param name="styleProperties" select="xt:node-set($stylePropertiesContainer)/*" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">WARNING: The required node set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="write-style-properties" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- automatic styles are implicit inheriting from a style called 'Default',
+ furthermore nor in spreadsheetml nor in OpenDocument automatic styles are able to inherit from each other -->
+ <xsl:choose>
+ <xsl:when test="@style:parent-style-name and not(@style:parent-style-name = 'Default')">
+ <xsl:attribute name="ss:Parent"><xsl:value-of select="@style:parent-style-name" /></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:call-template name="write-style-properties" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- resolving the style inheritance by starting from uppermost parent and
+ overriding existing style properties by new found child properties -->
+ <xsl:template name="merge-all-parent-styles">
+ <xsl:param name="currentStyle" />
+
+ <xsl:choose>
+ <!-- in case of a parent, styles have to be merged (flatting heritance tree) -->
+ <xsl:when test="$currentStyle/@style:parent-style-name">
+ <!-- collect parent style properties -->
+ <xsl:variable name="parentStyleContainer">
+ <!-- take a look if the parent style has a parent himself -->
+ <xsl:call-template name="merge-all-parent-styles" >
+ <xsl:with-param name="currentStyle" select="key('styles', $currentStyle/@style:parent-style-name)" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="merge-style-properties">
+ <xsl:with-param name="childStyleContainer" select="$currentStyle" />
+ <xsl:with-param name="parentStyleContainer" select="xalan:nodeset($parentStyleContainer)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="merge-style-properties">
+ <xsl:with-param name="childStyleContainer" select="$currentStyle" />
+ <xsl:with-param name="parentStyleContainer" select="common:node-set($parentStyleContainer)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="merge-style-properties">
+ <xsl:with-param name="childStyleContainer" select="$currentStyle" />
+ <xsl:with-param name="parentStyleContainer" select="xt:node-set($parentStyleContainer)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">WARNING: The required node-set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- called for top parents (or styles without parents) -->
+ <xsl:otherwise>
+ <xsl:copy-of select="$currentStyle/*"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="merge-style-properties">
+ <xsl:param name="childStyleContainer" />
+ <xsl:param name="parentStyleContainer" />
+
+ <xsl:choose>
+ <xsl:when test="$parentStyleContainer/*">
+ <xsl:apply-templates select="$parentStyleContainer/*" mode="inheritance">
+ <xsl:with-param name="childStyleContainer" select="$childStyleContainer" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$childStyleContainer/*"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="*" mode="inheritance">
+ <xsl:param name="childStyleContainer" />
+
+ <!-- create an element named equal to the current properties parent element (e.g. style:table-cell-properties) -->
+ <xsl:element name="{name()}" namespace="urn:oasis:names:tc:opendocument:xmlns:style:1.0">
+ <!-- attributes will be automatically replaced -->
+ <xsl:copy-of select="@*" />
+ <xsl:copy-of select="$childStyleContainer/*[name() = name(current() )]/@*"/>
+
+ <!-- elements are not needed yet, will be neglected for simplicity reasons -->
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:key match="/*/office:styles/number:date-style |
+ /*/office:styles/number:time-style |
+ /*/office:styles/number:number-style |
+ /*/office:styles/number:percentage-style |
+ /*/office:styles/number:currency-style |
+ /*/office:automatic-styles/number:date-style |
+ /*/office:automatic-styles/number:time-style |
+ /*/office:automatic-styles/number:number-style |
+ /*/office:automatic-styles/number:percentage-style |
+ /*/office:automatic-styles/number:currency-style" name="number-style" use="@style:name" />
+
+
+ <xsl:template name="write-style-properties">
+ <xsl:param name="styleProperties" select="key('styles', @style:name)/*" />
+
+ <xsl:call-template name="Alignment">
+ <xsl:with-param name="styleProperties" select="$styleProperties" />
+ </xsl:call-template>
+ <xsl:call-template name="Border">
+ <xsl:with-param name="styleProperties" select="$styleProperties" />
+ </xsl:call-template>
+ <xsl:call-template name="Font">
+ <xsl:with-param name="styleProperties" select="$styleProperties" />
+ <xsl:with-param name="styleParentName" select="@style:parent-style-name" />
+ </xsl:call-template>
+ <xsl:call-template name="Interior">
+ <xsl:with-param name="styleProperties" select="$styleProperties" />
+ </xsl:call-template>
+ <xsl:call-template name="NumberFormat">
+ <xsl:with-param name="styleProperties" select="$styleProperties" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- context is element 'style:style' -->
+ <xsl:template name="NumberFormat">
+ <xsl:if test="@style:data-style-name">
+ <xsl:variable name="numberStyleName" select="@style:data-style-name" />
+ <xsl:variable name="numberStyle" select="key('number-style', $numberStyleName)" />
+
+ <xsl:element name="NumberFormat">
+ <xsl:attribute name="ss:Format">
+ <xsl:choose>
+ <xsl:when test="not($numberStyle/node())">
+ <!-- Excel2003sp1 issue: 'General' and 'General Number' is not supported -->
+ <xsl:text>General</xsl:text>
+ </xsl:when>
+ <xsl:when test="name($numberStyle) = 'number:number-style'">
+ <xsl:choose>
+ <xsl:when test="$numberStyle/number:scientific-number">
+ <xsl:text>Scientific</xsl:text>
+ </xsl:when>
+ <!-- Excel2003sp1 issue: 'General Number' not supported -->
+ <xsl:when test="$numberStyle/number:number/@number:decimal-places and
+ $numberStyle/number:number/@number:decimal-places='0'">
+ <xsl:text>General</xsl:text>
+ </xsl:when>
+ <xsl:when test="$numberStyle/number:text">
+ <xsl:choose>
+ <xsl:when test="$numberStyle/number:text = 'No' or $numberStyle/number:text = 'Nein'">
+ <xsl:text>Yes/No</xsl:text>
+ </xsl:when>
+ <xsl:when test="$numberStyle/number:text = 'False' or $numberStyle/number:text = 'Falsch'">
+ <xsl:text>True/False</xsl:text>
+ </xsl:when>
+ <xsl:when test="$numberStyle/number:text = 'Off' or $numberStyle/number:text = 'Aus'">
+ <xsl:text>On/Off</xsl:text>
+ </xsl:when>
+ <!-- Excel2003sp1 issue: currency is saved as 'float' -->
+ <xsl:when test="$numberStyle/number:currency-symbol">
+ <xsl:choose>
+ <xsl:when test="contains($numberStyle/number:currency-symbol, '€')">
+ <xsl:text>Euro Currency</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>Currency</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- Excel2003sp1 issue: 'Currency' is saved as 'float' -->
+ <xsl:when test="contains($numberStyle/number:text, '$')">
+ <xsl:text>Currency</xsl:text>
+ </xsl:when>
+ <!-- OASIS XML adaptation -->
+ <xsl:otherwise>
+ <xsl:text>General</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$numberStyle/number:grouping">
+ <xsl:text>Standard</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>Fixed</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name($numberStyle) = 'number:time-style'">
+ <xsl:choose>
+ <xsl:when test="$numberStyle/number:am-pm">
+ <xsl:choose>
+ <xsl:when test="$numberStyle/number:seconds">
+ <xsl:text>Long Time</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>Medium Time</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>Short Time</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name($numberStyle) = 'number:percentage-style'">
+ <xsl:text>Percent</xsl:text>
+ </xsl:when>
+ <xsl:when test="name($numberStyle) = 'number:currency-style'">
+ <xsl:choose>
+ <xsl:when test="contains($numberStyle/number:currency-symbol, '€')">
+ <xsl:text>Euro Currency</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>Currency</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$numberStyle/number:month">
+ <xsl:choose>
+ <xsl:when test="$numberStyle/number:month/@number:textual and
+ $numberStyle/number:month/@number:textual=true()">
+ <xsl:text>Medium Date</xsl:text>
+ <!-- Excel2003 sp1 issue: No difference between 'Long Date' and 'Medium Date' -->
+ </xsl:when>
+ <xsl:when test="$numberStyle/number:hours">
+ <xsl:text>General Date</xsl:text>
+ </xsl:when>
+ <xsl:when test="$numberStyle/number:year/@number:style and
+ $numberStyle/number:year/@number:style='long'">
+ <xsl:text>Short Date</xsl:text>
+ </xsl:when>
+ <!-- OASIS XML adaptation -->
+ <xsl:otherwise>
+ <xsl:text>Short Date</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- OASIS XML adaptation -->
+ <xsl:otherwise>
+ <xsl:text>General</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="Alignment">
+ <xsl:param name="styleProperties" />
+
+ <!-- An empty Alignment element, might overwrite parents setting by
+ the default attributes -->
+ <xsl:if test="$styleProperties/@fo:text-align or
+ $styleProperties/@style:vertical-align or
+ $styleProperties/@fo:wrap-option or
+ $styleProperties/@fo:margin-left or
+ $styleProperties/@style:rotation-angle or
+ $styleProperties/@style:direction">
+ <xsl:element name="Alignment">
+ <xsl:if test="$styleProperties/@fo:text-align">
+ <xsl:attribute name="ss:Horizontal">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@fo:text-align = 'center'">Center</xsl:when>
+ <xsl:when test="$styleProperties/@fo:text-align = 'end'">Right</xsl:when>
+ <xsl:when test="$styleProperties/@fo:text-align = 'justify'">Justify</xsl:when>
+ <xsl:otherwise>Left</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:vertical-align">
+ <xsl:attribute name="ss:Vertical">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:vertical-align = 'top'">Top</xsl:when>
+ <xsl:when test="$styleProperties/@style:vertical-align = 'bottom'">Bottom</xsl:when>
+ <xsl:when test="$styleProperties/@style:vertical-align = 'middle'">Center</xsl:when>
+ <xsl:otherwise>Automatic</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:wrap-option = 'wrap'">
+ <xsl:attribute name="ss:WrapText">1</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:margin-left">
+ <xsl:attribute name="ss:Indent">
+ <xsl:variable name="margin">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$styleProperties/@fo:margin-left" />
+ <xsl:with-param name="rounding-factor" select="1" />
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- one ss:Indent is equal to 10 points -->
+ <xsl:value-of select="number($margin) div 10"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- Excel is only able to rotate between 90 and -90 degree (inclusive).
+ Other degrees will be mapped by 180 degrees -->
+ <xsl:if test="$styleProperties/@style:rotation-angle">
+ <xsl:attribute name="ss:Rotate">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:rotation-angle &gt; 90">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:rotation-angle &gt;= 270">
+ <xsl:value-of select="$styleProperties/@style:rotation-angle - 360" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:rotation-angle - 180" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$styleProperties/@style:rotation-angle &lt; -90">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:rotation-angle &lt;= -270">
+ <xsl:value-of select="$styleProperties/@style:rotation-angle + 360" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:rotation-angle + 180" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:rotation-angle" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:direction = 'ttb'">
+ <xsl:attribute name="ss:VerticalText">1</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template name="Border">
+ <xsl:param name="styleProperties" />
+
+ <!-- An empty border element, might overwrite parents setting by
+ the default attributes -->
+ <xsl:if test="$styleProperties/@fo:border or
+ $styleProperties/@fo:border-bottom or
+ $styleProperties/@fo:border-left or
+ $styleProperties/@fo:border-right or
+ $styleProperties/@fo:border-top">
+ <xsl:element name="Borders">
+ <xsl:if test="$styleProperties/@fo:border-bottom and not($styleProperties/@fo:border-bottom = 'none')">
+ <xsl:element name="Border">
+ <xsl:attribute name="ss:Position">Bottom</xsl:attribute>
+ <xsl:call-template name="border-attributes">
+ <xsl:with-param name="border_properties" select="$styleProperties/@fo:border-bottom" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:border-left and not($styleProperties/@fo:border-left = 'none')">
+ <xsl:element name="Border">
+ <xsl:attribute name="ss:Position">Left</xsl:attribute>
+ <xsl:call-template name="border-attributes">
+ <xsl:with-param name="border_properties" select="$styleProperties/@fo:border-left" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:border-right and not($styleProperties/@fo:border-right = 'none')">
+ <xsl:element name="Border">
+ <xsl:attribute name="ss:Position">Right</xsl:attribute>
+ <xsl:call-template name="border-attributes">
+ <xsl:with-param name="border_properties" select="$styleProperties/@fo:border-right" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:border-top and not($styleProperties/@fo:border-top = 'none')">
+ <xsl:element name="Border">
+ <xsl:attribute name="ss:Position">Top</xsl:attribute>
+ <xsl:call-template name="border-attributes">
+ <xsl:with-param name="border_properties" select="$styleProperties/@fo:border-top" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <!-- write out all table border -->
+ <xsl:if test="$styleProperties/@fo:border and not($styleProperties/@fo:border = 'none')">
+ <xsl:element name="Border">
+ <xsl:attribute name="ss:Position">Bottom</xsl:attribute>
+ <xsl:call-template name="border-attributes">
+ <xsl:with-param name="border_properties" select="$styleProperties/@fo:border" />
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:element name="Border">
+ <xsl:attribute name="ss:Position">Left</xsl:attribute>
+ <xsl:call-template name="border-attributes">
+ <xsl:with-param name="border_properties" select="$styleProperties/@fo:border" />
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:element name="Border">
+ <xsl:attribute name="ss:Position">Right</xsl:attribute>
+ <xsl:call-template name="border-attributes">
+ <xsl:with-param name="border_properties" select="$styleProperties/@fo:border" />
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:element name="Border">
+ <xsl:attribute name="ss:Position">Top</xsl:attribute>
+ <xsl:call-template name="border-attributes">
+ <xsl:with-param name="border_properties" select="$styleProperties/@fo:border" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template name="border-attributes">
+ <xsl:param name="border_properties" />
+
+ <xsl:variable name="border-width">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="substring-before($border_properties, ' ')" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="border-style" select="substring-before(substring-after($border_properties, ' '), ' ')" />
+ <xsl:variable name="border-color" select="substring-after(substring-after($border_properties, ' '), ' ')" />
+<!--
+ <xsl:message>border-width:<xsl:value-of select="$border-width" /></xsl:message>
+ <xsl:message>border-style:<xsl:value-of select="$border-style" /></xsl:message>
+ <xsl:message>border-color:<xsl:value-of select="$border-color" /></xsl:message>
+ -->
+
+ <!-- Dash, Dot, DashDot, DashDotDot, SlantDashDot are not supported yet -->
+ <xsl:attribute name="ss:LineStyle">
+ <xsl:choose>
+ <xsl:when test="$border-style = 'none'">None</xsl:when>
+ <xsl:when test="$border-style = 'double'">Double</xsl:when>
+ <xsl:otherwise>Continuous</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <xsl:attribute name="ss:Weight">
+ <xsl:choose>
+ <!-- 0: Hairline -->
+ <xsl:when test="$border-width &lt;= 0.002">0</xsl:when>
+ <!-- 1: Thin -->
+ <xsl:when test="$border-width &lt;= 0.035">1</xsl:when>
+ <!-- 2: Medium -->
+ <xsl:when test="$border-width &lt;= 0.088">2</xsl:when>
+ <!-- 3: Thick -->
+ <xsl:otherwise>3</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <xsl:attribute name="ss:Color">
+ <xsl:choose>
+ <xsl:when test="$border-color"><xsl:value-of select="$border-color" /></xsl:when>
+ <xsl:otherwise>Automatic</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:template>
+
+
+ <xsl:template name="Font">
+ <xsl:param name="styleProperties" />
+ <xsl:param name="styleParentName" />
+
+ <!-- An empty font element, might overwrite parents setting by
+ the default attributes -->
+ <xsl:if test="$styleProperties/@style:font-weight or
+ $styleProperties/@fo:color or
+ $styleProperties/@style:font-name or
+ $styleProperties/@fo:font-style or
+ $styleProperties/@style:text-outline or
+ $styleProperties/@style:text-shadow or
+ $styleProperties/@style:font-size or
+ $styleProperties/@style:text-line-through-style or
+ $styleProperties/@style:text-underline-type or
+ $styleProperties/@style:text-underline-style or
+ $styleProperties/@style:text-position">
+
+
+ <xsl:element name="Font">
+ <xsl:call-template name="getParentBold">
+ <xsl:with-param name="styleProperties" select="$styleProperties" />
+ <xsl:with-param name="styleParentName" select="$styleParentName" />
+ </xsl:call-template>
+ <xsl:if test="$styleProperties/@fo:color">
+ <xsl:attribute name="ss:Color"><xsl:value-of select="$styleProperties/@fo:color" /></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:font-name">
+ <xsl:attribute name="ss:FontName"><xsl:value-of select="$styleProperties/@style:font-name" /></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:font-style = 'italic'">
+ <xsl:attribute name="ss:Italic">1</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-outline = 'true'">
+ <xsl:attribute name="ss:Outline">1</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-shadow = 'shadow'">
+ <xsl:attribute name="ss:Shadow">1</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:font-size">
+ <xsl:attribute name="ss:Size">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$styleProperties/@fo:font-size" />
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-line-through-style and $styleProperties/@style:text-line-through-style != 'none'">
+ <xsl:attribute name="ss:StrikeThrough">1</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="($styleProperties/@style:text-underline-type and $styleProperties/@style:text-underline-type != 'none') or
+ ($styleProperties/@style:text-underline-style and $styleProperties/@style:text-underline-style != 'none')">
+ <xsl:attribute name="ss:Underline">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:text-underline-type = 'double'">Double</xsl:when>
+ <xsl:otherwise>Single</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-position">
+ <xsl:attribute name="ss:VerticalAlign">
+ <xsl:choose>
+ <xsl:when test="substring-before($styleProperties/@style:text-position, '% ') &gt; 0">Superscript</xsl:when>
+ <xsl:otherwise>Subscript</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="Interior">
+ <xsl:param name="styleProperties" />
+ <xsl:if test="$styleProperties/@fo:background-color and not($styleProperties/@fo:background-color = 'transparent')">
+ <xsl:element name="Interior">
+ <xsl:attribute name="ss:Color">
+ <xsl:value-of select="$styleProperties/@fo:background-color" />
+ </xsl:attribute>
+ <!-- Background color (i.e. Interior/ss:Color) not shown without ss:Pattern (or with 'none')
+ Therefore a default is set -->
+ <xsl:attribute name="ss:Pattern">Solid</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- Excel issue workaround: <Font ss:Bold="1"> is not inherited -->
+ <xsl:template name="getParentBold">
+ <xsl:param name="styleProperties" />
+ <xsl:param name="styleParentName" />
+ <xsl:param name="styleName" />
+
+ <xsl:if test="$styleParentName and $styleParentName != $styleName">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@fo:font-weight = 'bold'">
+ <xsl:attribute name="ss:Bold">1</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="getParentBold">
+ <xsl:with-param name="styleProperties" select="key('styles', $styleParentName)/*" />
+ <xsl:with-param name="styleParentName" select="key('styles', $styleParentName)/@style:parent-style-name" />
+ <xsl:with-param name="styleName" select="$styleParentName" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/spreadsheetml/table.xsl b/filter/source/xslt/export/spreadsheetml/table.xsl
new file mode 100644
index 000000000..73d16b3eb
--- /dev/null
+++ b/filter/source/xslt/export/spreadsheetml/table.xsl
@@ -0,0 +1,928 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xt="http://www.jclark.com/xt"
+ xmlns:common="http://exslt.org/common"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xlink xt common xalan">
+
+
+ <!-- ************** -->
+ <!-- *** Table *** -->
+ <!-- ************** -->
+
+ <!-- check existence of default cell style -->
+ <xsl:variable name="firstDefaultCellStyle" select="descendant::table:table-column/@table:default-cell-style-name" />
+
+
+ <xsl:template match="table:table" name="table:table">
+ <xsl:element name="Table">
+ <xsl:apply-templates select="@table:style-name" />
+
+ <!-- find all columns in the table -->
+ <xsl:variable name="columnNodes" select="descendant::table:table-column" />
+ <!-- calculate the overall column amount -->
+ <xsl:variable name="maxColumnNo">
+ <xsl:choose>
+ <xsl:when test="$columnNodes/@table:number-columns-repeated">
+ <xsl:value-of select="count($columnNodes)
+ + number(sum($columnNodes/@table:number-columns-repeated))
+ - count($columnNodes/@table:number-columns-repeated)" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="count($columnNodes)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- create columns -->
+ <xsl:apply-templates select="$columnNodes[1]">
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ <xsl:with-param name="maxColumnNo" select="$maxColumnNo" />
+ </xsl:apply-templates>
+
+ <!-- create rows -->
+ <xsl:choose>
+ <xsl:when test="not($columnNodes/@table:number-columns-repeated)">
+ <xsl:call-template name="optimized-row-handling">
+ <xsl:with-param name="rowNodes" select="descendant::table:table-row" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- To be able to match from a cell to the corresponding column to match @table:default-cell-style-name,
+ the repeated columns are being resolved by copying them in a helper variable -->
+ <xsl:variable name="columnNodes-RTF">
+ <xsl:for-each select="$columnNodes">
+ <xsl:call-template name="adding-column-styles-entries" />
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="optimized-row-handling">
+ <xsl:with-param name="rowNodes" select="descendant::table:table-row" />
+ <xsl:with-param name="columnNodes" select="xalan:nodeset($columnNodes-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="optimized-row-handling">
+ <xsl:with-param name="rowNodes" select="descendant::table:table-row" />
+ <xsl:with-param name="columnNodes" select="common:node-set($columnNodes-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="optimized-row-handling">
+ <xsl:with-param name="rowNodes" select="descendant::table:table-row" />
+ <xsl:with-param name="columnNodes" select="xt:node-set($columnNodes-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- **************** -->
+ <!-- *** Columns *** -->
+ <!-- **************** -->
+
+ <xsl:template match="table:table-column">
+ <xsl:param name="columnNodes" />
+ <xsl:param name="currentColumnNumber" select="1" />
+ <xsl:param name="setIndex" select="false()" />
+ <xsl:param name="maxColumnNo" />
+
+ <xsl:element name="Column">
+ <xsl:if test="@table:visibility = 'collapse' or @table:visibility = 'filter'">
+ <xsl:attribute name="ss:Hidden">1</xsl:attribute>
+ </xsl:if>
+
+ <xsl:if test="@table:number-columns-repeated">
+ <xsl:attribute name="ss:Span">
+ <xsl:value-of select="@table:number-columns-repeated - 1" />
+ </xsl:attribute>
+ </xsl:if>
+
+ <xsl:if test="$setIndex">
+ <xsl:attribute name="ss:Index">
+ <xsl:value-of select="$currentColumnNumber" />
+ </xsl:attribute>
+ </xsl:if>
+
+ <xsl:choose>
+ <xsl:when test="@style:use-optimal-column-width = 'true'">
+ <xsl:attribute name="ss:AutoFitWidth">1</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="width" select="key('styles', @table:style-name)/style:table-column-properties/@style:column-width" />
+ <xsl:if test="$width">
+ <xsl:attribute name="ss:Width">
+ <!-- using the absolute width in point -->
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$width" />
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="@table:number-columns-repeated">
+ <xsl:attribute name="ss:Span">
+ <xsl:value-of select="@table:number-columns-repeated - 1" />
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+
+ <xsl:variable name="columnNumber">
+ <xsl:choose>
+ <xsl:when test="@table:number-columns-repeated">
+ <xsl:value-of select="$currentColumnNumber + @table:number-columns-repeated"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$currentColumnNumber"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$columnNumber &lt; $maxColumnNo">
+ <xsl:variable name="nextColumnNodes" select="$columnNodes[position() != 1]" />
+ <xsl:choose>
+ <xsl:when test="@table:number-columns-repeated">
+ <xsl:apply-templates select="$nextColumnNodes[1]">
+ <xsl:with-param name="columnNodes" select="$nextColumnNodes" />
+ <xsl:with-param name="currentColumnNumber" select="$columnNumber" />
+ <xsl:with-param name="maxColumnNo" select="$maxColumnNo" />
+ <xsl:with-param name="setIndex" select="true()" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$nextColumnNodes[1]">
+ <xsl:with-param name="columnNodes" select="$nextColumnNodes" />
+ <xsl:with-param name="currentColumnNumber" select="$columnNumber + 1" />
+ <xsl:with-param name="maxColumnNo" select="$maxColumnNo" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- current node is a table:table-column -->
+ <xsl:template name="adding-column-styles-entries">
+ <xsl:choose>
+ <xsl:when test="not(@table:number-columns-repeated and @table:number-columns-repeated > 1)">
+ <!-- writes an entry of a column in the columns-variable -->
+ <xsl:copy-of select="." />
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- repeated columns will be written explicit several times in the variable-->
+ <xsl:call-template name="repeat-adding-table-column">
+ <xsl:with-param name="numberColumnsRepeated" select="@table:number-columns-repeated" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- current node is a table:table-column -->
+ <!-- duplicates column elements in case of column-repeated attribute -->
+ <xsl:template name="repeat-adding-table-column">
+ <xsl:param name="table:table-column" />
+ <xsl:param name="numberColumnsRepeated" />
+
+ <xsl:choose>
+ <xsl:when test="$numberColumnsRepeated > 1">
+ <!-- writes an entry of a column in the columns-variable -->
+ <xsl:copy-of select="." />
+ <!-- repeat calling this method until all elements written out -->
+ <xsl:call-template name="repeat-adding-table-column">
+ <xsl:with-param name="numberColumnsRepeated" select="$numberColumnsRepeated - 1" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- writes an entry of a column in the columns-variable -->
+ <xsl:copy-of select="." />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- ************* -->
+ <!-- *** Rows *** -->
+ <!-- ************* -->
+
+
+ <!-- Recursions are much faster when the stack size is small -->
+ <xsl:template name="optimized-row-handling">
+ <xsl:param name="rowNodes" />
+ <xsl:param name="columnNodes" />
+ <xsl:param name="offset" select="0"/>
+ <xsl:param name="threshold" select="10"/>
+
+ <xsl:variable name="rowCount" select="count($rowNodes)"/>
+ <xsl:choose>
+ <xsl:when test="$rowCount &lt;= $threshold">
+ <xsl:apply-templates select="$rowNodes[1]">
+ <xsl:with-param name="rowNodes" select="$rowNodes" />
+ <xsl:with-param name="offset" select="$offset" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="rowCountHalf" select="floor($rowCount div 2)"/>
+ <xsl:variable name="rowNodesSetA" select="$rowNodes[position() &lt;= $rowCountHalf]"/>
+ <xsl:variable name="rowNodesSetB" select="$rowNodes[position() &gt; $rowCountHalf]"/>
+ <!-- to keep track of the rownumber, the repeated rows have to kept into accounts -->
+ <xsl:variable name="rowsCreatedByRepetition">
+ <xsl:choose>
+ <xsl:when test="$rowNodesSetA/@table:number-rows-repeated">
+ <xsl:value-of select="number(sum($rowNodesSetA/@table:number-rows-repeated))
+ - count($rowNodesSetA/@table:number-rows-repeated)" />
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$rowCountHalf &gt; $threshold">
+ <xsl:call-template name="optimized-row-handling">
+ <xsl:with-param name="rowNodes" select="$rowNodesSetA"/>
+ <xsl:with-param name="offset" select="$offset" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ <xsl:call-template name="optimized-row-handling">
+ <xsl:with-param name="rowNodes" select="$rowNodesSetB"/>
+ <xsl:with-param name="offset" select="$offset + $rowCountHalf + $rowsCreatedByRepetition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$rowNodesSetA[1]">
+ <xsl:with-param name="rowNodes" select="$rowNodesSetA"/>
+ <xsl:with-param name="offset" select="$offset" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ <xsl:apply-templates select="$rowNodesSetB[1]">
+ <xsl:with-param name="rowNodes" select="$rowNodesSetB" />
+ <xsl:with-param name="offset" select="$offset + $rowCountHalf + $rowsCreatedByRepetition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!--
+ Rows as "table:table-row" might be grouped in
+ "table:table-header-rows" or "table:table-row-group"
+ This row-tree will be traversed providing each Row with its
+ calculatedRowPosition and earlierRowNumber.
+ By this repeated empty rows might be neglected in the spreadsheetml output,
+ as the following row will notice the 'gap' and provide @ss:Index,
+ which results in filling up the gap by a row without style and content.
+
+ In Excel created rows by ss:Index are 'default' rows.
+ -->
+ <xsl:template match="table:table-row">
+ <xsl:param name="earlierRowNumber" select="0" />
+ <xsl:param name="offset" />
+ <xsl:param name="calculatedRowPosition" select="$offset + 1" />
+ <xsl:param name="rowNodes" />
+ <xsl:param name="columnNodes" />
+
+ <xsl:choose>
+ <xsl:when test="@table:number-rows-repeated &gt; 1">
+ <xsl:call-template name="write-table-row">
+ <xsl:with-param name="earlierRowNumber" select="$earlierRowNumber" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ <xsl:if test="@table:number-rows-repeated &gt; 2 and (table:table-cell/@office:value-type or $firstDefaultCellStyle != '')">
+ <!-- In case a cell is being repeated, the cell will be created
+ in a variable, which is as many times given out, as being repeated -->
+ <xsl:variable name="tableRow">
+ <xsl:call-template name="write-table-row">
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="optimized-row-repeating">
+ <xsl:with-param name="tableRow" select="$tableRow" />
+ <xsl:with-param name="repetition" select="@table:number-rows-repeated - 1" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="write-table-row">
+ <xsl:with-param name="earlierRowNumber" select="$earlierRowNumber" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:variable name="nextRowNodes" select="$rowNodes[position()!=1]" />
+ <xsl:choose>
+ <xsl:when test="@table:number-rows-repeated &gt; 1">
+ <xsl:apply-templates select="$nextRowNodes[1]">
+ <xsl:with-param name="earlierRowNumber" select="$calculatedRowPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition + @table:number-rows-repeated" />
+ <xsl:with-param name="rowNodes" select="$nextRowNodes" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$nextRowNodes[1]">
+ <xsl:with-param name="earlierRowNumber" select="$calculatedRowPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition + 1" />
+ <xsl:with-param name="rowNodes" select="$nextRowNodes" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="write-table-row">
+ <xsl:param name="earlierRowNumber" select="0" />
+ <xsl:param name="calculatedRowPosition" select="1" />
+ <xsl:param name="columnNodes" />
+
+ <xsl:element name="Row">
+ <xsl:if test="@table:visibility = 'collapse' or @table:visibility = 'filter'">
+ <xsl:attribute name="ss:Hidden">1</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not($earlierRowNumber + 1 = $calculatedRowPosition)">
+ <xsl:attribute name="ss:Index"><xsl:value-of select="$calculatedRowPosition" /></xsl:attribute>
+ </xsl:if>
+
+ <!-- writing the style of the row -->
+ <xsl:apply-templates select="@table:style-name" mode="table-row" />
+
+ <xsl:variable name="rowProperties" select="key('styles', @table:style-name)/*" />
+ <xsl:if test="$rowProperties/@style:use-optimal-row-height = 'false'">
+ <!-- default is '1', therefore write only '0' -->
+ <xsl:attribute name="ss:AutoFitHeight">0</xsl:attribute>
+ </xsl:if>
+
+ <xsl:variable name="height" select="$rowProperties/@style:row-height" />
+ <xsl:if test="$height">
+ <xsl:attribute name="ss:Height">
+ <!-- using the absolute height in point -->
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$height" />
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="table:table-cell[1]">
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="cellNodes" select="table:table-cell" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- Recursions are much faster when the stack size is small -->
+ <xsl:template name="optimized-row-repeating">
+ <xsl:param name="tableRow" />
+ <xsl:param name="repetition" />
+ <!-- resource optimization: instead of '1' it will be '1000' and the column is not full -->
+ <xsl:param name="thresholdmax" select="512"/>
+ <xsl:param name="thresholdmin" select="256"/>
+
+ <xsl:choose>
+ <xsl:when test="$repetition &lt;= $thresholdmax">
+ <xsl:copy-of select="$tableRow" />
+ <xsl:if test="$repetition &gt;= $thresholdmin">
+ <xsl:call-template name="optimized-row-repeating">
+ <xsl:with-param name="repetition" select="$repetition - 1"/>
+ <xsl:with-param name="tableRow" select="$tableRow" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$repetition mod 2 = 1">
+ <xsl:copy-of select="$tableRow" />
+ </xsl:if>
+ <xsl:variable name="repetitionHalf" select="floor($repetition div 2)"/>
+ <xsl:call-template name="optimized-row-repeating">
+ <xsl:with-param name="repetition" select="$repetitionHalf"/>
+ <xsl:with-param name="tableRow" select="$tableRow" />
+ </xsl:call-template>
+ <xsl:call-template name="optimized-row-repeating">
+ <xsl:with-param name="repetition" select="$repetitionHalf"/>
+ <xsl:with-param name="tableRow" select="$tableRow" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+
+ <!-- ************** -->
+ <!-- *** Cells *** -->
+ <!-- ************** -->
+
+ <!-- Table cells are able to be repeated by attribute in StarOffice,
+ but not in Excel. If more cells are repeated -->
+ <xsl:template name="table:table-cell" match="table:table-cell">
+ <xsl:param name="calculatedCellPosition" select="1" /><!-- the later table position of the current cell -->
+ <xsl:param name="calculatedRowPosition" /><!-- the later table position of the current row -->
+ <xsl:param name="setIndex" select="false()" /> <!-- if not '0' @ss:Index used for neglecting repeated empty cells -->
+ <xsl:param name="repetition" select="@table:number-columns-repeated" /> <!-- used for explicit written out cells -->
+ <xsl:param name="repetitionCellPosition" select="$calculatedCellPosition" /><!-- during repetition formula needs exact cell positioning -->
+ <xsl:param name="nextMatchedCellPosition"><!-- the later table position of the next cell -->
+ <xsl:choose>
+ <xsl:when test="not(@table:number-columns-repeated) and not(@table:number-columns-spanned)">
+ <xsl:value-of select="$calculatedCellPosition + 1" />
+ </xsl:when>
+ <xsl:when test="not(@table:number-columns-spanned)">
+ <xsl:value-of select="$calculatedCellPosition + @table:number-columns-repeated" />
+ </xsl:when>
+ <xsl:when test="not(@table:number-columns-repeated)">
+ <xsl:value-of select="$calculatedCellPosition + @table:number-columns-spanned" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$calculatedCellPosition + @table:number-columns-spanned * @table:number-columns-repeated" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:param>
+ <xsl:param name="cellNodes" /><!-- cells to be handled -->
+ <xsl:param name="columnNodes" />
+
+ <xsl:choose>
+ <!-- in case a repetition took place -->
+ <xsl:when test="$repetition &gt; 0">
+ <xsl:choose>
+ <!-- In case of no cell content (text, subelements, attribute, except repeated style) the ss:Index could be used -->
+ <xsl:when test="not(text()) and not(*) and not(@*[name() != 'table:number-columns-repeated'])">
+ <xsl:choose>
+ <xsl:when test="count($cellNodes) = 1">
+ <xsl:call-template name="create-table-cell">
+ <xsl:with-param name="setIndex" select="true()" />
+ <xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition - 1" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$cellNodes[2]">
+ <xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="setIndex" select="true()" />
+ <xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- Fastest cell repetition by creating cell once and copying, works not for
+ a) cells with formula (need of actual cell position)
+ b) cells, which start with ss:Index (as ss:Index is not allowed to be repeated) -->
+ <xsl:when test="not(@table:formula) and not($setIndex)">
+ <!-- In case a non-empty cell is being repeated, the cell will be created
+ in a variable, which is as many times given out, as being repeated -->
+ <xsl:variable name="tableCell">
+ <xsl:call-template name="create-table-cell">
+ <xsl:with-param name="setIndex" select="false()" /><!-- copied cells may not have indices -->
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="repeat-copy-table-cell">
+ <xsl:with-param name="tableCell" select="$tableCell" />
+ <xsl:with-param name="repetition" select="$repetition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ <xsl:apply-templates select="$cellNodes[2]">
+ <xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:when>
+ <!-- explicit writing (instead of copying) of cell for the cases mentioned above -->
+ <xsl:otherwise>
+ <xsl:call-template name="create-table-cell">
+ <xsl:with-param name="setIndex" select="$setIndex" /><!-- a possible Index will be created -->
+ <xsl:with-param name="calculatedCellPosition" select="$repetitionCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ <xsl:choose>
+ <!-- as long there is a repetition (higher '1') stay on the same cell node -->
+ <xsl:when test="$repetition &gt; 1">
+ <xsl:call-template name="table:table-cell">
+ <xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="repetitionCellPosition">
+ <xsl:choose>
+ <xsl:when test="@table:number-columns-spanned">
+ <xsl:value-of select="$repetitionCellPosition + @table:number-columns-spanned" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$repetitionCellPosition + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="nextMatchedCellPosition" select="$nextMatchedCellPosition" />
+ <xsl:with-param name="repetition" select="$repetition - 1" />
+ <xsl:with-param name="cellNodes" select="$cellNodes" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$cellNodes[2]">
+ <xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- in case no repetition took place -->
+ <xsl:choose>
+ <!-- neglect an empty cell by using ss:Index Attribute -->
+ <xsl:when test="not(text()) and not(*) and not(@*)">
+ <xsl:choose>
+ <!-- if it is the last cell, write this cell -->
+ <xsl:when test="count($cellNodes) = 1">
+ <xsl:call-template name="create-table-cell">
+ <xsl:with-param name="setIndex" select="true()" />
+ <xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition - 1" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$cellNodes[2]">
+ <xsl:with-param name="setIndex" select="true()" />
+ <xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- create cell and use/unset the ss:Index -->
+ <xsl:call-template name="create-table-cell">
+ <xsl:with-param name="setIndex" select="$setIndex" />
+ <xsl:with-param name="calculatedCellPosition" select="$calculatedCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:call-template>
+ <xsl:apply-templates select="$cellNodes[2]">
+ <xsl:with-param name="calculatedCellPosition" select="$nextMatchedCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ <xsl:with-param name="cellNodes" select="$cellNodes[position() != 1]" />
+ <xsl:with-param name="columnNodes" select="$columnNodes" />
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Copies the variable 'tableCell' to the output as often as 'repetition' -->
+ <xsl:template name="repeat-copy-table-cell">
+ <xsl:param name="tableCell" />
+ <xsl:param name="repetition" />
+
+ <xsl:if test="$repetition &gt; 0">
+ <xsl:copy-of select="$tableCell"/>
+ <xsl:call-template name="repeat-copy-table-cell">
+ <xsl:with-param name="tableCell" select="$tableCell" />
+ <xsl:with-param name="repetition" select="$repetition - 1" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="create-table-cell">
+ <xsl:param name="setIndex" select="false()" />
+ <xsl:param name="calculatedCellPosition" />
+ <xsl:param name="calculatedRowPosition" />
+ <xsl:param name="columnNodes" />
+
+ <xsl:element name="Cell" namespace="urn:schemas-microsoft-com:office:spreadsheet">
+ <xsl:if test="$setIndex">
+ <xsl:attribute name="ss:Index">
+ <xsl:value-of select="$calculatedCellPosition"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@table:number-columns-spanned &gt; 1">
+ <xsl:attribute name="ss:MergeAcross">
+ <xsl:value-of select="@table:number-columns-spanned - 1" />
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@table:number-rows-spanned &gt; 1">
+ <xsl:attribute name="ss:MergeDown">
+ <xsl:value-of select="@table:number-rows-spanned - 1" />
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="link" select="descendant::text:a/@xlink:href" />
+ <xsl:if test="$link">
+ <xsl:attribute name="ss:HRef">
+ <xsl:value-of select="$link" />
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@table:style-name">
+ <xsl:apply-templates select="@table:style-name" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$firstDefaultCellStyle != ''">
+ <xsl:variable name="defaultCellStyle" select="$columnNodes/table:table-column[position() = $calculatedCellPosition]/@table:default-cell-style-name" />
+ <xsl:if test="$defaultCellStyle">
+ <xsl:if test="not($defaultCellStyle = 'Default')">
+ <xsl:attribute name="ss:StyleID"><xsl:value-of select="$defaultCellStyle"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates select="@table:formula">
+ <xsl:with-param name="calculatedCellPosition" select="$calculatedCellPosition" />
+ <xsl:with-param name="calculatedRowPosition" select="$calculatedRowPosition" />
+ </xsl:apply-templates>
+ <xsl:choose>
+ <xsl:when test="*">
+ <!-- in case it is not an empty cell
+
+ As the sequence of comment and data is opposite in Excel and Calc no match work here, in both comments exist only once
+ Possible Table Content of interest: text:h|text:p|text:list -->
+ <xsl:if test="text:h | text:p | text:list">
+ <xsl:variable name="valueType">
+ <xsl:choose>
+ <xsl:when test="@office:value-type">
+ <xsl:value-of select="@office:value-type" />
+ </xsl:when>
+ <xsl:otherwise>string</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="ss:Data">
+ <xsl:with-param name="valueType" select="$valueType" />
+ <xsl:with-param name="cellStyleName" select="@table:style-name" />
+ </xsl:call-template>
+ </xsl:if>
+
+ <xsl:if test="office:annotation">
+ <xsl:element name="Comment">
+ <xsl:if test="office:annotation/@office:author">
+ <xsl:attribute name="ss:Author"><xsl:value-of select="office:annotation/@office:author" /></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="office:annotation/@office:display = 'true'">
+ <xsl:attribute name="ss:ShowAlways">1</xsl:attribute>
+ </xsl:if>
+ <!-- ss:Data is obligatory, but not the same as the ss:Cell ss:Data child, as it has no attributes -->
+ <ss:Data xmlns="http://www.w3.org/TR/REC-html40">
+ <xsl:for-each select="office:annotation/text:p">
+ <xsl:choose>
+ <xsl:when test="*">
+ <!-- paragraph style have to be neglected due to Excel error,
+ which does not allow shadowing their HTML attributes -->
+ <xsl:for-each select="*">
+ <xsl:call-template name="style-and-contents" />
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="@text:style-name">
+ <xsl:call-template name="style-and-contents" />
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- if no style is set, BOLD is set as default -->
+ <B>
+ <xsl:call-template name="style-and-contents" />
+ </B>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </ss:Data>
+ </xsl:element>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- comments are handled separately in the cell -->
+ <xsl:template match="office:annotation" />
+ <xsl:template match="dc:date" />
+
+ <xsl:template name="ss:Data">
+ <!-- the default value is 'String' in the office -->
+ <xsl:param name="valueType" select="'string'" />
+ <xsl:param name="cellStyleName" />
+
+ <xsl:choose>
+ <xsl:when test="descendant::*/@text:style-name">
+ <xsl:choose>
+ <xsl:when test="$valueType = 'string'">
+ <ss:Data ss:Type="String" xmlns="http://www.w3.org/TR/REC-html40">
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:apply-templates>
+ </ss:Data>
+ </xsl:when>
+ <xsl:when test="$valueType = 'boolean'">
+ <ss:Data ss:Type="Boolean" xmlns="http://www.w3.org/TR/REC-html40">
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:apply-templates>
+ </ss:Data>
+ </xsl:when>
+ <xsl:when test="$valueType = 'date'">
+ <ss:Data ss:Type="DateTime" xmlns="http://www.w3.org/TR/REC-html40">
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:apply-templates>
+ </ss:Data>
+ </xsl:when>
+ <!-- float, time, percentage, currency (no 'Error' setting) -->
+ <xsl:otherwise>
+ <ss:Data ss:Type="Number" xmlns="http://www.w3.org/TR/REC-html40">
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:apply-templates>
+ </ss:Data>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="Data">
+ <xsl:call-template name="ss:Type">
+ <xsl:with-param name="valueType" select="$valueType" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="ss:Type">
+ <xsl:param name="valueType" select="'string'" />
+
+ <xsl:choose>
+ <xsl:when test="$valueType = 'string'">
+ <xsl:attribute name="ss:Type">String</xsl:attribute>
+ <xsl:apply-templates select="*"/>
+ </xsl:when>
+ <xsl:when test="$valueType = 'boolean'">
+ <xsl:attribute name="ss:Type">Boolean</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@office:boolean-value = 'true'">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$valueType = 'date' or $valueType = 'time'">
+ <!-- issue in Excel: can not have an empty 'DateTime' cell -->
+ <xsl:attribute name="ss:Type">DateTime</xsl:attribute>
+ <!-- Gathering information of two StarOffice date/time attributes
+ Excel always needs both pieces of information in one attribute -->
+ <xsl:choose>
+ <xsl:when test="@office:date-value">
+ <!-- office:date-value may contain time (after 'T')-->
+ <xsl:choose>
+ <xsl:when test="contains(@office:date-value, 'T')">
+ <!-- in case time is also part of the date -->
+ <xsl:value-of select="substring-before(@office:date-value, 'T')" />
+ <xsl:text>T</xsl:text>
+ <xsl:value-of select="substring-after(@office:date-value,'T')" />
+ <xsl:if test="not(contains(@office:date-value,'.'))">
+ <xsl:text>.</xsl:text>
+ </xsl:if>
+ <xsl:text>000</xsl:text>
+ </xsl:when>
+ <xsl:when test="@office:time-value">
+ <!-- contains date and time (time will be evaluated later -->
+ <xsl:value-of select="@office:date-value" />
+ <xsl:text>T</xsl:text>
+ <xsl:choose>
+ <xsl:when test="@table:formula or contains(@office:time-value,',')">
+ <!-- customized number types not implemented yet -->
+ <xsl:text>00:00:00.000</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(substring-after(@office:time-value,'PT'),'HMS','::.')" />
+ <xsl:if test="not(contains(@office:time-value,'S'))">
+ <xsl:text>.</xsl:text>
+ </xsl:if>
+ <xsl:text>000</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@office:date-value" />
+ <xsl:text>T00:00:00.000</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="@office:time-value">
+ <xsl:text>1899-12-31T</xsl:text>
+ <xsl:choose>
+ <xsl:when test="@table:formula or contains(@office:time-value,',')">
+ <!-- customized number types not implemented yet -->
+ <xsl:text>00:00:00.000</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(substring-after(@office:time-value,'PT'),'HMS','::.')" />
+ <xsl:if test="not(contains(@office:time-value,'S'))">
+ <xsl:text>.</xsl:text>
+ </xsl:if>
+ <xsl:text>000</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- float, percentage, currency (no 'Error' setting) -->
+ <xsl:otherwise>
+ <xsl:attribute name="ss:Type">Number</xsl:attribute>
+ <xsl:value-of select="@office:value" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- ******************** -->
+ <!-- *** Common Rules *** -->
+ <!-- ******************** -->
+
+ <xsl:template match="*">
+ <xsl:param name="cellStyleName" />
+
+<!-- LineBreak in Cell -->
+ <xsl:if test="preceding-sibling::text:p[1]"><xsl:text>&#10;</xsl:text></xsl:if>
+ <xsl:call-template name="style-and-contents">
+ <xsl:with-param name="cellStyleName" select="$cellStyleName" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- disabling draw:frames -->
+ <xsl:template match="draw:frame" />
+
+ <xsl:template match="text:s">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="@text:c" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <!--write the number of 'whitespaces' -->
+ <xsl:template name="write-breakable-whitespace">
+ <xsl:param name="whitespaces" />
+
+ <xsl:text> </xsl:text>
+ <xsl:if test="$whitespaces >= 1">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="$whitespaces - 1" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- allowing all matched text nodes -->
+ <xsl:template match="text()"><xsl:value-of select="." /></xsl:template>
+
+</xsl:stylesheet>
+
diff --git a/filter/source/xslt/export/uof/odf2uof_presentation.xsl b/filter/source/xslt/export/uof/odf2uof_presentation.xsl
new file mode 100644
index 000000000..a18113c58
--- /dev/null
+++ b/filter/source/xslt/export/uof/odf2uof_presentation.xsl
@@ -0,0 +1,3392 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:数="http://www.w3.org/1998/Math/MathML" xmlns:图="http://schemas.uof.org/cn/2003/graph" exclude-result-prefixes="office style text table draw fo xlink dc meta number presentation svg chart dr3d math form script config ooo ooow oooc dom xforms smil anim">
+ <xsl:output method="xml" indent="no" encoding="UTF-8" version="1.0" standalone="no" omit-xml-declaration="no"/>
+ <xsl:variable name="impresswithUnit">
+ <xsl:value-of select="/office:document/office:styles/style:style[@style:family='graphic']/style:graphic-properties/@svg:stroke-width"/>
+ </xsl:variable>
+ <xsl:variable name="uofUnit">
+ <xsl:choose>
+ <xsl:when test="contains($impresswithUnit,'inch')">inch</xsl:when>
+ <xsl:when test="contains($impresswithUnit,'cm')">cm</xsl:when>
+ <xsl:when test="contains($impresswithUnit,'mm')">mm</xsl:when>
+ <xsl:when test="contains($impresswithUnit,'pt')">pt</xsl:when>
+ <xsl:otherwise>cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="cm-to-other">
+ <xsl:choose>
+ <xsl:when test="$uofUnit='cm'">1</xsl:when>
+ <xsl:when test="$uofUnit='inch'">0.394</xsl:when>
+ <xsl:when test="$uofUnit='pt'">28.346</xsl:when>
+ <xsl:when test="$uofUnit='mm'">10</xsl:when>
+ <xsl:when test="$uofUnit='pica'">2.364</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:key match="/office:document/office:automatic-styles/style:style | /office:document/office:styles/style:style" name="graphicset" use="@style:name"/>
+ <xsl:template match="/">
+ <xsl:apply-templates select="office:document"/>
+ </xsl:template>
+ <xsl:template match="office:document">
+ <uof:UOF xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:图="http://schemas.uof.org/cn/2003/graph" xmlns:数="http://www.w3.org/1998/Math/MathML" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" uof:language="cn" uof:version="1.0" uof:locID="u0000" uof:mimetype="vnd.uof.presentation">
+ <xsl:apply-templates select="office:meta"/>
+ <xsl:if test="//text:bookmark|//text:bookmark-start">
+ <uof:书签集 uof:locID="u0027">
+ <xsl:for-each select="//text:bookmark|//text:bookmark-start">
+ <uof:书签 uof:名称="{@text:name}" uof:locID="u0028" uof:attrList="名称">
+ <uof:文本位置 uof:区域引用="{generate-id(.)}" uof:locID="u0029" uof:attrList="区域引用"/>
+ </uof:书签>
+ </xsl:for-each>
+ </uof:书签集>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/text:p/text:a | /office:document/office:body/text:p/draw:a">
+ <uof:链接集 uof:locID="u0031">
+ <xsl:for-each select="/office:document/office:body/text:p/text:a | /office:document/office:body/text:p/draw:a">
+ <xsl:variable name="hyperStr" select="@xlink:href"/>
+ <uof:超级链接 uof:locID="u0032" uof:attrList="标识符 目标 书签 式样引用 已访问式样引用 提示 链源">
+ <xsl:if test="contains($hyperStr,'#')">
+ <xsl:attribute name="uof:书签"><xsl:value-of select="substring-after($hyperStr,'#')"/></xsl:attribute>
+ <xsl:attribute name="uof:提示"><xsl:value-of select="."/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="num">
+ <xsl:number from="/office:document/office:body" level="any" count="text:p[text:a]"/>
+ </xsl:variable>
+ <xsl:attribute name="uof:链源"><xsl:value-of select="concat('hlnk',$num)"/></xsl:attribute>
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat('hyk_','hlnk',$num)"/></xsl:attribute>
+ <xsl:if test="not(contains($hyperStr,'#'))">
+ <xsl:attribute name="uof:目标"><xsl:value-of select="$hyperStr"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="contains($hyperStr,'@')">
+ <xsl:attribute name="uof:提示">链接到邮件地址</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="uof:提示">链接文件</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@text:style-name">
+ <xsl:attribute name="uof:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@text:visited-style-name">
+ <xsl:attribute name="uof:已访问式样引用"><xsl:value-of select="@text:visited-style-name"/></xsl:attribute>
+ </xsl:if>
+ </uof:超级链接>
+ </xsl:for-each>
+ </uof:链接集>
+ </xsl:if>
+ <uof:对象集 uof:locID="u0033">
+ <xsl:apply-templates select="office:master-styles/style:handout-master" mode="styles"/>
+ <xsl:apply-templates select="office:master-styles/style:master-page" mode="styles"/>
+ <xsl:apply-templates select="office:body/office:presentation/draw:page" mode="styles"/>
+ <xsl:apply-templates select="office:styles/style:presentation-page-layout/presentation:placeholder" mode="graphic"/>
+ <xsl:apply-templates select="office:body/office:presentation/draw:page/presentation:notes" mode="styles"/>
+ <xsl:for-each select="(/office:document/office:styles/draw:fill-image) | (/office:document/office:automatic-styles/draw:fill-image)">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="@draw:name"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">jpg</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="office:binary-data"/>
+ </uof:数据>
+ </uof:其他对象>
+ </xsl:for-each>
+ <xsl:for-each select="(/office:document/office:styles/style:style/style:graphic-properties/text:list-style/text:list-level-style-image) | (/office:document/office:automatic-styles/style:style/style:graphic-properties/text:list-style/text:list-level-style-image)">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat('image_numbering_',count(preceding::text:list-level-style-image))"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">jpg</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="office:binary-data"/>
+ </uof:数据>
+ </uof:其他对象>
+ </xsl:for-each>
+ </uof:对象集>
+ <uof:式样集 uof:locID="u0039">
+ <xsl:apply-templates select="office:font-face-decls"/>
+ <xsl:element name="uof:自动编号集">
+ <xsl:attribute name="uof:locID">u0042</xsl:attribute>
+ <xsl:for-each select="/office:document//text:list-style">
+ <xsl:element name="字:自动编号">
+ <xsl:attribute name="uof:locID">t0169</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 父编号引用 多级编号</xsl:attribute>
+ <xsl:attribute name="字:标识符">
+ <xsl:variable name="count1" select="count(preceding::text:list-style)"/>
+ <xsl:choose><xsl:when test="@style:name"><xsl:value-of select="concat(@style:name,$count1)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat(../../@style:name,$count1)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:多级编号">true</xsl:attribute>
+ <xsl:for-each select="./* ">
+ <xsl:if test="number(@text:level) &lt; 10">
+ <xsl:element name="字:级别">
+ <xsl:attribute name="uof:locID">t0159</xsl:attribute>
+ <xsl:attribute name="uof:attrList">级别值 编号对齐方式 尾随字符</xsl:attribute>
+ <xsl:attribute name="字:级别值"><xsl:value-of select="number(@text:level)"/></xsl:attribute>
+ <xsl:if test="style:list-level-properties/@fo:text-align">
+ <xsl:attribute name="字:编号对齐方式"><xsl:value-of select="style:list-level-properties/@fo:text-align"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="level">
+ <xsl:value-of select="@text:level"/>
+ </xsl:variable>
+ <xsl:if test="office:binary-data">
+ <xsl:element name="字:图片符号引用" uof:locID="t0164" uof:attrList="宽度 高度">
+ <xsl:attribute name="字:宽度"><xsl:value-of select="substring-before(style:list-level-properties/@fo:width,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:高度"><xsl:value-of select="substring-before(style:list-level-properties/@fo:height,$uofUnit)"/></xsl:attribute>
+ <xsl:value-of select="concat('image_numbering_',count(preceding::text:list-level-style-image))"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@text:bullet-char">
+ <xsl:element name="字:项目符号">
+ <xsl:attribute name="uof:locID">t0171</xsl:attribute>
+ <xsl:value-of select="@text:bullet-char"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:符号字体">
+ <xsl:attribute name="uof:locID">t0160</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ <xsl:if test="@style:num-format">
+ <xsl:choose>
+ <xsl:when test="string(@style:num-format)='a'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">lower-letter</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='A'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">upper-letter</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='i'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">lower-roman</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='I'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">upper-roman</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='①, ②, ③, ...'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">decimal-enclosed-circle</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='甲, 乙, 丙, ...'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">ideograph-traditional</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='子, 丑, 寅, ...'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">ideograph-zodiac</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='一, 二, 三, ...'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">chinese-counting</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='壹, 贰, 叁, ...'">
+ <xsl:element name="字:编号格式" uof:locID="t0162">chinese-legal-simplified</xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="字:编号格式" uof:locID="t0162">decimal</xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:variable name="jibie">
+ <xsl:value-of select="position()"/>
+ </xsl:variable>
+ <xsl:variable name="xianshijibie">
+ <xsl:choose>
+ <xsl:when test="@text:display-levels">
+ <xsl:value-of select="@text:display-levels"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <字:编号格式表示 uof:locID="t0163">
+ <xsl:call-template name="字:编号格式表示">
+ <xsl:with-param name="bubianjibie" select="$jibie"/>
+ <xsl:with-param name="jibie" select="$jibie"/>
+ <xsl:with-param name="xianshijibie" select="$xianshijibie"/>
+ <xsl:with-param name="biaoshi" select="concat(string(@style:num-prefix),'%',$jibie,string(@style:num-suffix))"/>
+ </xsl:call-template>
+ </字:编号格式表示>
+ <xsl:element name="字:缩进">
+ <xsl:attribute name="uof:locID">t0165</xsl:attribute>
+ <xsl:call-template name="字:缩进类型"/>
+ </xsl:element>
+ <xsl:element name="字:制表符位置">
+ <xsl:attribute name="uof:locID">t0166</xsl:attribute>
+ <xsl:value-of select="substring-before(style:list-level-properties/@text:min-label-width,$uofUnit)"/>
+ </xsl:element>
+ <xsl:if test="@text:start-value">
+ <xsl:element name="字:起始编号">
+ <xsl:value-of select="@text:start-value"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@text:num-regular-exp">
+ <xsl:element name="字:正规格式" uof:locID="t0168" uof:attrList="值">
+ <xsl:attribute name="值"><xsl:value-of select="@text:num-regular-exp"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:for-each select="/office:document//text:list-style/*">
+ <xsl:if test="style:text-properties/@fo:font-family">
+ <xsl:element name="uof:句式样">
+ <xsl:attribute name="uof:locID">u0043</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用</xsl:attribute>
+ <xsl:variable name="count"><xsl:value-of select="count(preceding::node())"/></xsl:variable>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="concat('ID',$count)"/></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="concat(ancestor::style:style/@style:name,@text:level)"/></xsl:attribute>
+ <xsl:attribute name="字:类型">auto</xsl:attribute>
+ <xsl:if test="ancestor::style:style/@style:parent-style-name">
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="ancestor::style:style/@style:parent-style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:apply-templates select="office:styles | office:automatic-styles" mode="style"/>
+ <xsl:for-each select="/office:document/office:master-styles/style:master-page">
+ <xsl:for-each select="child::draw:frame">
+ <xsl:variable name="stylename" select="@presentation:style-name"/>
+ <xsl:variable name="parent" select="/office:document/office:automatic-styles/style:style[@style:name=$stylename]/@style:parent-style-name"/>
+ <xsl:for-each select="/office:document/*/style:style[@style:name=$parent]">
+ <xsl:if test="not(contains(@style:name,'outline'))">
+ <xsl:call-template name="段落式样"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:for-each>
+ <xsl:for-each select="/office:document/office:styles/style:style[contains(@style:name,'outline')]">
+ <xsl:call-template name="段落式样"/>
+ </xsl:for-each>
+ </uof:式样集>
+ <uof:演示文稿 uof:locID="u0048">
+ <演:公用处理规则 uof:locID="p0000">
+ <xsl:element name="演:度量单位">
+ <xsl:attribute name="uof:locID">p0055</xsl:attribute>
+ <xsl:value-of select="$uofUnit"/>
+ </xsl:element>
+ <演:页面设置集 uof:locID="p0001">
+ <xsl:apply-templates select="office:automatic-styles/style:page-layout"/>
+ </演:页面设置集>
+ <演:配色方案集 uof:locID="p0007">
+ <xsl:for-each select="/office:document/office:master-styles/*[@draw:style-name]">
+ <xsl:call-template name="配色方案"/>
+ </xsl:for-each>
+ <xsl:for-each select="/office:document/office:body/office:presentation/draw:page">
+ <xsl:call-template name="配色方案"/>
+ </xsl:for-each>
+ </演:配色方案集>
+ <演:页面版式集 uof:locID="p0017">
+ <xsl:apply-templates select="office:styles/style:presentation-page-layout" mode="pagestyle"/>
+ </演:页面版式集>
+ <xsl:if test="office:styles/style:style='标准-title' or office:styles/style:style='标准-outline'" >
+ <演:文本式样集 uof:locID="p0131">
+ <xsl:for-each select="office:styles/style:style">
+ <xsl:variable name="name"><xsl:value-of select="@style:name"/></xsl:variable>
+ <xsl:if test="$name='标准-title' or contains($name,'标准-outline')">
+ <演:文本式样 uof:locID="p0132" uof:attrList="标识符 名称">
+ <xsl:attribute name="演:标识符">text-style</xsl:attribute>
+ <xsl:attribute name="演:名称">文本式样</xsl:attribute>
+ <xsl:element name="演:段落式样">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">auto</xsl:attribute>
+ <xsl:if test="@style:parent-style-name">
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:别名"><xsl:value-of select="@style:class"/></xsl:attribute>
+ <xsl:call-template name="ParaAttribute">
+ <xsl:with-param name="text-style-name" select="@text:style-name"/>
+ </xsl:call-template>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ </演:文本式样>
+ </xsl:if>
+ </xsl:for-each>
+ </演:文本式样集>
+ </xsl:if>
+ <演:显示比例 uof:locID="p0020">
+ <xsl:variable name="VisibleAreaWidth">
+ <xsl:value-of select="/office:document/office:settings/config:config-item-set/config:config-item-map-indexed/config:config-item-map-entry/config:config-item[@config:name='VisibleAreaWidth']"/>
+ </xsl:variable>
+ <xsl:value-of select="substring-before((13997 div $VisibleAreaWidth)*100,'.')"/>
+ </演:显示比例>
+ <演:放映设置 uof:locID="p0021">
+ <演:幻灯片序列 uof:locID="p0022" uof:attrList="标识符 名称 自定义">
+ <xsl:attribute name="演:标识符">customList</xsl:attribute>
+ <xsl:attribute name="演:名称">幻灯片序列</xsl:attribute>
+ <xsl:attribute name="演:自定义">true</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="office:body/office:presentation/presentation:settings/@presentation:start-page">
+ <xsl:variable name="start-page">
+ <xsl:value-of select="office:body/office:presentation/presentation:settings/@presentation:start-page"/>
+ </xsl:variable>
+ <xsl:variable name="before-slides">
+ <xsl:call-template name="幻灯片序列">
+ <xsl:with-param name="start-node" select="office:body/office:presentation/draw:page[@draw:name=$start-page]"/>
+ <xsl:with-param name="end-node" select="office:body/office:presentation/draw:page[last()]"/>
+ <xsl:with-param name="value"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="after-slides">
+ <xsl:for-each select="office:body/office:presentation/draw:page[@draw:name=$start-page]">
+ <xsl:call-template name="幻灯片序列">
+ <xsl:with-param name="start-node" select="/office:document/office:body/office:presentation/draw:page[1]"/>
+ <xsl:with-param name="end-node" select="preceding-sibling::node()[1]"/>
+ <xsl:with-param name="value"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:value-of select="concat($before-slides,' ',$after-slides)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="幻灯片序列">
+ <xsl:with-param name="start-node" select="office:body/office:presentation/draw:page[1]"/>
+ <xsl:with-param name="end-node" select="office:body/office:presentation/draw:page[last()]"/>
+ <xsl:with-param name="value"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </演:幻灯片序列>
+ <演:放映顺序 uof:locID="p0023" uof:attrList="名称 序列引用">
+ <xsl:attribute name="演:名称">放映顺序</xsl:attribute>
+ <xsl:attribute name="演:序列引用">customList</xsl:attribute>
+ </演:放映顺序>
+ <演:全屏放映 uof:locID="p0024">
+ <xsl:choose>
+ <xsl:when test="office:body/office:presentation/presentation:settings/@presentation:full-screen='false'">false</xsl:when>
+ <xsl:otherwise>true</xsl:otherwise>
+ </xsl:choose>
+ </演:全屏放映>
+ <演:循环放映 uof:locID="p0025">
+ <xsl:choose>
+ <xsl:when test="office:body/office:presentation/presentation:settings/@presentation:endless='true'">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </演:循环放映>
+ <xsl:if test="office:body/office:presentation/presentation:settings/@presentation:pause">
+ <演:放映间隔 uof:locID="p0026">
+ <xsl:variable name="hms">
+ <xsl:value-of select="substring-after(office:body/office:presentation/presentation:settings/@presentation:pause,'PT')"/>
+ </xsl:variable>
+ <xsl:value-of select="concat('P0Y0M0DT',$hms)"/>
+ </演:放映间隔>
+ </xsl:if>
+ <演:手动方式 uof:locID="p0027">
+ <xsl:choose>
+ <xsl:when test="office:body/office:presentation/presentation:settings/@presentation:force-manual='true'">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </演:手动方式>
+ <演:导航帮助 uof:locID="p0029">
+ <xsl:choose>
+ <xsl:when test="office:body/office:presentation/presentation:settings/@presentation:start-with-navigator='true'">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </演:导航帮助>
+ <演:放映动画 uof:locID="p0030">
+ <xsl:choose>
+ <xsl:when test="office:body/office:presentation/presentation:settings/@presentation:animations='disabled'">false</xsl:when>
+ <xsl:otherwise>true</xsl:otherwise>
+ </xsl:choose>
+ </演:放映动画>
+ <演:前端显示 uof:locID="p0031">
+ <xsl:choose>
+ <xsl:when test="office:body/office:presentation/presentation:settings/@presentation:stay-on-top='true'">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </演:前端显示>
+ </演:放映设置>
+ </演:公用处理规则>
+ <演:主体 uof:locID="p0034">
+ <演:母版集 uof:locID="p0035">
+ <xsl:apply-templates select="office:master-styles"/>
+ </演:母版集>
+ <演:幻灯片集 uof:locID="p0039">
+ <xsl:apply-templates select="office:body/office:presentation/draw:page"/>
+ </演:幻灯片集>
+ </演:主体>
+ </uof:演示文稿>
+ </uof:UOF>
+ </xsl:template>
+<xsl:template name="配色方案">
+ <xsl:variable name="page-name"><xsl:value-of select="@draw:style-name"/></xsl:variable>
+ <演:配色方案 uof:locID="p0008" uof:attrList="标识符 名称 类型">
+ <xsl:attribute name="演:标识符">
+ <xsl:choose>
+ <xsl:when test="@draw:name"><xsl:value-of select="@draw:name"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="@draw:style-name"/></xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:attribute>
+ <xsl:for-each select="/office:document/office:automatic-styles/style:style[@style:name = $page-name]">
+ <xsl:attribute name="演:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="演:类型"><xsl:choose><xsl:when test="not(contains(@style:name,'color'))">custom</xsl:when><xsl:otherwise>standard</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="style:drawing-page-properties/@draw:fill-color">
+ <演:背景色 uof:locID="p0009">
+ <xsl:value-of select="style:drawing-page-properties/@draw:fill-color"/>
+ </演:背景色>
+ </xsl:if>
+ <xsl:if test="style:drawing-page-properties/@svg:stroke-color">
+ <演:文本和线条 uof:locID="p0010">
+ <xsl:value-of select="style:drawing-page-properties/@svg:stroke-color"/>
+ </演:文本和线条>
+ </xsl:if>
+ <xsl:if test="style:drawing-page-properties/@draw:shadow-color">
+ <演:阴影 uof:locID="p0011">
+ <xsl:value-of select="style:drawing-page-properties/@draw:shadow-color"/>
+ </演:阴影>
+ </xsl:if>
+ <xsl:if test="style:drawing-page-properties/@svg:stroke-color">
+ <演:标题文本 uof:locID="p0012">
+ <xsl:value-of select="style:drawing-page-properties/@svg:stroke-color"/>
+ </演:标题文本>
+ </xsl:if>
+ <xsl:if test="style:drawing-page-properties/@draw:fill-color">
+ <演:填充 uof:locID="p0013">
+ <xsl:value-of select="style:drawing-page-properties/@draw:fill-color"/>
+ </演:填充>
+ </xsl:if>
+ <演:强调 uof:locID="p0014">#FFFFFF</演:强调>
+ <演:强调和超级链接 uof:locID="p0015">#FF0000</演:强调和超级链接>
+ <演:强调和尾随超级链接 uof:locID="p0016">#FF00FF</演:强调和尾随超级链接>
+ </xsl:for-each>
+ </演:配色方案>
+</xsl:template>
+ <xsl:template name="幻灯片序列">
+ <xsl:param name="start-node"/>
+ <xsl:param name="end-node"/>
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="not($start-node/@draw:name = $end-node/@draw:name)">
+ <xsl:for-each select="$start-node">
+ <xsl:variable name="value1">
+ <xsl:value-of select="concat($value,@draw:name,'_',@draw:style-name,' ')"/>
+ </xsl:variable>
+ <xsl:call-template name="幻灯片序列">
+ <xsl:with-param name="start-node" select="following-sibling::node()[1]"/>
+ <xsl:with-param name="end-node" select="$end-node"/>
+ <xsl:with-param name="value" select="$value1"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($value,$start-node/@draw:name)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="字:编号格式表示">
+ <xsl:param name="bubianjibie"/>
+ <xsl:param name="jibie"/>
+ <xsl:param name="xianshijibie"/>
+ <xsl:param name="biaoshi"/>
+ <xsl:choose>
+ <xsl:when test="number($xianshijibie)= 1">
+ <xsl:value-of select="$biaoshi"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="num-prefix">
+ <xsl:value-of select="preceding-sibling::*[number($bubianjibie -$jibie +1)]/@style:num-prefix"/>
+ </xsl:variable>
+ <xsl:variable name="num-suffix">
+ <xsl:value-of select="preceding-sibling::*[number($bubianjibie -$jibie +1)]/@style:num-suffix"/>
+ </xsl:variable>
+ <xsl:call-template name="字:编号格式表示">
+ <xsl:with-param name="bubianjibie" select="$bubianjibie"/>
+ <xsl:with-param name="jibie" select="$jibie -1"/>
+ <xsl:with-param name="xianshijibie" select="$xianshijibie -1"/>
+ <xsl:with-param name="biaoshi" select="concat($num-prefix,'%',number($jibie -1),$num-suffix,'.',$biaoshi)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="字:句属性">
+ <xsl:element name="字:字体">
+ <xsl:attribute name="uof:locID">t0088</xsl:attribute>
+ <xsl:attribute name="uof:attrList">西文字体引用 中文字体引用 特殊字体引用 西文绘制 字号 相对字号 颜色</xsl:attribute>
+ <xsl:if test=".//@fo:font-size or .//@style:font-size-asian or .//@style:font-size-complex">
+ <xsl:choose>
+ <xsl:when test="contains(.//@fo:font-size,'%') or contains(.//@style:font-size-asian,'%')">
+ <xsl:attribute name="字:相对字号"><xsl:choose><xsl:when test=".//@fo:font-size"><xsl:value-of select="substring-before(.//@fo:font-size,'%')"/></xsl:when><xsl:when test=".//@style:font-size-asian"><xsl:value-of select="substring-before(.//@style:font-size-asian,'%')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:字号"><xsl:choose><xsl:when test=".//@fo:font-size"><xsl:value-of select="substring-before(.//@fo:font-size,'pt')"/></xsl:when><xsl:when test=".//@style:font-size-asian"><xsl:value-of select="substring-before(.//@style:font-size-asian,'pt')"/></xsl:when><xsl:when test=".//@style:font-size-complex"><xsl:value-of select="substring-before(.//@style:font-size-complex,'pt')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test=".//@style:font-name">
+ <xsl:attribute name="字:西文字体引用"><xsl:value-of select=".//@style:font-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//@style:font-name-asian">
+ <xsl:attribute name="字:中文字体引用"><xsl:value-of select=".//@style:font-name-asian"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select=".//@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test=".//@style:text-background-color and not(.//@style:text-background-color='transparent')">
+ <xsl:element name="字:填充">
+ <xsl:element name="图:图案">
+ <xsl:attribute name="uof:locID">g0036</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 图形引用 前景色 背景色</xsl:attribute>
+ <xsl:if test=".//@style:text-background-color">
+ <xsl:attribute name="图:前景色"><xsl:value-of select=".//@style:text-background-color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:font-weight or .//@style:font-weight-asian">
+ <xsl:element name="字:粗体">
+ <xsl:attribute name="uof:locID">t0089</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test=".//@style:font-weight-asian='bold' or .//@fo:font-weight='bold'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:font-style or .//@style:font-style-asian">
+ <xsl:element name="字:斜体">
+ <xsl:attribute name="uof:locID">t0090</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test=".//@fo:font-style='italic' or .//@style:font-style-asian='italic'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:text-crossing-out">
+ <xsl:element name="字:删除线">
+ <xsl:attribute name="uof:locID">t0094</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:线型类型"><xsl:with-param name="lineType" select=".//@style:text-crossing-out"/></xsl:call-template></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:text-underline">
+ <xsl:element name="字:下划线">
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:线型类型"><xsl:with-param name="lineType" select=".//@style:text-underline"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0095</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:if test=".//@style:text-underline-color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select=".//@style:text-underline-color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:text-shadow and not(.//@fo:text-shadow='none')">
+ <xsl:element name="字:阴影">
+ <xsl:attribute name="uof:locID">t0100</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test=".//@fo:text-shadow='none'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:text-emphasize">
+ <xsl:element name="字:着重号">
+ <xsl:attribute name="uof:locID">t0096</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 颜色 字着重号</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test=".//@style:text-emphasize='none'">
+ <xsl:attribute name="字:字着重号">false</xsl:attribute>
+ <xsl:attribute name="字:类型">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:字着重号">true</xsl:attribute>
+ <xsl:attribute name="字:类型">dot</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test=".//@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select=".//@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@text:display and not(.//@text:display='none')">
+ <xsl:element name="字:隐藏文字">
+ <xsl:attribute name="uof:locID">t0097</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:text-outline and not(.//@style:text-outline='none')">
+ <xsl:element name="字:空心">
+ <xsl:attribute name="uof:locID">t0098</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select=".//@style:text-outline"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:font-relief and not(.//@style:font-relief='none')">
+ <xsl:element name="字:浮雕">
+ <xsl:attribute name="uof:locID">t0099</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test=".//@style:font-relief='embossed'">emboss</xsl:when><xsl:when test=".//@style:font-relief='engraved'">engrave</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:text-transform or .//@fo:font-variant">
+ <xsl:element name="字:醒目字体">
+ <xsl:attribute name="uof:locID">t0101</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test=".//@fo:text-transform='uppercase'">uppercase</xsl:when><xsl:when test=".//@fo:text-transform='lowercase'">lowercase</xsl:when><xsl:when test=".//@fo:text-transform='capitalize'">capital</xsl:when><xsl:when test=".//@fo:font-variant='small-caps'">small-caps</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:text-position">
+ <xsl:element name="字:位置">
+ <xsl:attribute name="uof:locID">t0102</xsl:attribute>
+ <xsl:value-of select=".//@style:text-position"/>
+ </xsl:element>
+ <字:上下标 uof:locID="t0205" uof:attrList="值">
+ <xsl:attribute name="字:值">none</xsl:attribute>
+ </字:上下标>
+ </xsl:if>
+ <xsl:if test=".//@style:text-scale">
+ <xsl:element name="字:缩放">
+ <xsl:attribute name="uof:locID">t0103</xsl:attribute>
+ <xsl:value-of select=".//@style:text-scale"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:letter-spacing">
+ <xsl:element name="字:字符间距">
+ <xsl:attribute name="uof:locID">t0104</xsl:attribute>
+ <xsl:value-of select=".//@fo:letter-spacing"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:letter-kerning">
+ <xsl:element name="字:调整字间距">
+ <xsl:attribute name="uof:locID">t015</xsl:attribute>
+ <xsl:value-of select=".//@style:letter-kerning"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:字符对齐网格">
+ <xsl:attribute name="字:值">false</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0106</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="style:presentation-page-layout" mode="pagestyle">
+ <演:页面版式 uof:locID="p0018" uof:attrList="标识符 名称">
+ <xsl:attribute name="演:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="演:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <演:布局 uof:locID="p0129" uof:attrList="类型">
+ <xsl:attribute name="演:类型">
+ <xsl:variable name="layout" select="substring-after(@style:name,'T')"/>
+ <xsl:choose>
+ <xsl:when test="$layout='0'">title-subtitle</xsl:when><xsl:when test="$layout='1'">title-body</xsl:when><xsl:when test="$layout='19'">title-only</xsl:when><xsl:when test="$layout='12'">column-2-rows</xsl:when><xsl:when test="$layout='15'">2-rows-column</xsl:when><xsl:when test="$layout='16'">2-columns-row</xsl:when><xsl:when test="$layout='17'">2-rows</xsl:when><xsl:when test="$layout='18'">4-objects</xsl:when><xsl:when test="$layout='27'">v-2-rows</xsl:when><xsl:when test="$layout='28'">v-title-body</xsl:when><xsl:when test="$layout='29'">big-object</xsl:when><xsl:when test="$layout='30'">2-columns</xsl:when>
+ <xsl:otherwise>title-only</xsl:otherwise>
+ </xsl:choose></xsl:attribute>
+ </演:布局>
+ <xsl:apply-templates select="presentation:placeholder" mode="anchor"/>
+ </演:页面版式>
+ </xsl:template>
+ <xsl:template match="presentation:placeholder" mode="anchor">
+ <演:占位符 uof:locID="p0130" uof:attrList="类型">
+ <xsl:attribute name="演:类型"><xsl:choose><xsl:when test="@presentation:object = 'vertical_outline'">vertical_text</xsl:when><xsl:when test="@presentation:object = 'date-time'">date</xsl:when><xsl:when test="@presentation:object = 'page_number'">number</xsl:when><xsl:otherwise><xsl:value-of select="@presentation:object"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <uof:锚点 uof:locID="u0064" uof:attrList="x坐标 y坐标 宽度 高度 图形引用 随动方式 缩略图 占位符">
+ <xsl:attribute name="uof:x坐标"><xsl:value-of select="substring-before(@svg:x,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:y坐标"><xsl:value-of select="substring-before(@svg:y,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(@svg:width,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:高度"><xsl:value-of select="substring-before(@svg:height,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:图形引用"><xsl:variable name="number"><xsl:value-of select="concat('_',count(preceding-sibling::presentation:placeholder))"/></xsl:variable><xsl:value-of select="concat(parent::style:presentation-page-layout/@style:name,$number)"/></xsl:attribute>
+ </uof:锚点>
+ </演:占位符>
+ </xsl:template>
+ <xsl:template match="presentation:placeholder" mode="graphic">
+ <图:图形 uof:locID="g0000" uof:attrList="层次 标识符 组合列表 其他对象" 图:层次="3">
+ <xsl:attribute name="图:标识符"><xsl:variable name="number"><xsl:value-of select="concat('_',count(preceding-sibling::presentation:placeholder))"/></xsl:variable><xsl:value-of select="concat(parent::style:presentation-page-layout/@style:name,$number)"/></xsl:attribute>
+ </图:图形>
+ </xsl:template>
+ <xsl:template match="office:master-styles">
+ <xsl:apply-templates select="style:handout-master"/>
+ <xsl:apply-templates select="style:master-page"/>
+ <xsl:if test="style:master-page/presentation:notes">
+ <xsl:apply-templates select="style:master-page/presentation:notes"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="style:handout-master">
+ <演:母版 uof:locID="p0036" uof:attrList="标识符 名称 类型 页面设置引用 配色方案引用 页面版式引用 文本式样引用" 演:名称="handout母版" 演:类型="handout">
+ <xsl:attribute name="演:页面设置引用"><xsl:value-of select="@style:page-layout-name"/></xsl:attribute>
+ <xsl:if test="@draw:style-name">
+ <xsl:attribute name="演:配色方案引用"><xsl:value-of select="@draw:style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@presentation:presentation-page-layout-name">
+ <xsl:attribute name="演:页面版式引用"><xsl:value-of select="@presentation:presentation-page-layout-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="产生锚点"/>
+ </演:母版>
+ </xsl:template>
+ <xsl:template match="style:master-page">
+ <演:母版 uof:locID="p0036" uof:attrList="标识符 名称 类型 页面设置引用 配色方案引用 页面版式引用 文本式样引用" 演:名称="slide母版" 演:类型="slide">
+ <xsl:attribute name="演:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="演:页面设置引用"><xsl:value-of select="@style:page-layout-name"/></xsl:attribute>
+ <xsl:if test="@draw:style-name">
+ <xsl:attribute name="演:配色方案引用"><xsl:value-of select="@draw:style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@presentation:presentation-page-layout-name">
+ <xsl:attribute name="演:页面版式引用"><xsl:value-of select="@presentation:presentation-page-layout-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="产生锚点"/>
+ <xsl:variable name="stylename">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="name">
+ <xsl:value-of select="name(.)"/>
+ </xsl:variable>
+ <xsl:for-each select="/office:document/*/style:style[@style:name=$stylename]/style:drawing-page-properties">
+ <xsl:if test="@draw:fill and not(@draw:fill='none')">
+ <演:背景 uof:locID="p0057">
+ <xsl:call-template name="填充">
+ <xsl:with-param name="picname" select="$stylename"/>
+ <xsl:with-param name="nodename" select="$name"/>
+ </xsl:call-template>
+ </演:背景>
+ </xsl:if>
+ </xsl:for-each>
+ </演:母版>
+ </xsl:template>
+ <xsl:template match="presentation:notes">
+ <演:母版 uof:locID="p0036" uof:attrList="标识符 名称 类型 页面设置引用 配色方案引用 页面版式引用 文本式样引用" 演:名称="notes母版" 演:类型="notes">
+ <xsl:attribute name="演:标识符"><xsl:value-of select="concat('note-',parent::style:master-page/@style:name)"/></xsl:attribute>
+ <xsl:attribute name="演:页面设置引用"><xsl:value-of select="@style:page-layout-name"/></xsl:attribute>
+ <xsl:if test="@draw:style-name">
+ <xsl:attribute name="演:配色方案引用"><xsl:value-of select="@draw:style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@presentation:presentation-page-layout-name">
+ <xsl:attribute name="演:页面版式引用"><xsl:value-of select="@presentation:presentation-page-layout-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="产生锚点"/>
+ </演:母版>
+ </xsl:template>
+ <xsl:template match="draw:page">
+ <演:幻灯片 uof:locID="p0040" uof:attrList="名称 标识符 母版引用 配色方案引用 页面版式引用 显示 显示背景 显示背景对象">
+ <xsl:attribute name="演:标识符"><xsl:value-of select="concat(@draw:name,'_',@draw:style-name)"/></xsl:attribute>
+ <xsl:attribute name="演:名称"><xsl:value-of select="@draw:name"/></xsl:attribute>
+ <xsl:attribute name="演:母版引用"><xsl:value-of select="@draw:master-page-name"/></xsl:attribute>
+ <xsl:if test="@presentation:presentation-page-layout-name">
+ <xsl:attribute name="演:页面版式引用"><xsl:value-of select="@presentation:presentation-page-layout-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="产生锚点"/>
+ <xsl:apply-templates select="presentation:notes" mode="page"/>
+ <xsl:variable name="stylename">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="name">
+ <xsl:value-of select="name(.)"/>
+ </xsl:variable>
+ <xsl:for-each select="/office:document/*/style:style[@style:name=$stylename]/style:drawing-page-properties">
+ <xsl:if test="@draw:fill and not(@draw:fill='none')">
+ <演:背景 uof:locID="p0057">
+ <xsl:call-template name="填充">
+ <xsl:with-param name="picname" select="$stylename"/>
+ <xsl:with-param name="nodename" select="$name"/>
+ </xsl:call-template>
+ </演:背景>
+ </xsl:if>
+ </xsl:for-each>
+ <演:切换 uof:locID="p0058" uof:attrList="效果 速度">
+ <xsl:for-each select="key('graphicset',$stylename)/style:drawing-page-properties">
+ <xsl:attribute name="演:速度"><xsl:choose><xsl:when test="@presentation:transition-speed='slow'">slow</xsl:when><xsl:otherwise>fast</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="演:效果"><xsl:variable name="type"><xsl:value-of select="@smil:type"/></xsl:variable><xsl:variable name="subtype"><xsl:value-of select="@smil:subtype"/></xsl:variable><xsl:choose><xsl:when test="$type='irisWipe' and $subtype='rectangle' and @smil:direction='reverse'">box in</xsl:when><xsl:when test="$type='irisWipe' and $subtype='rectangle'">box out</xsl:when><xsl:when test="$type='checkerBoardWipe' and $subtype='across'">checkerboard across</xsl:when><xsl:when test="$type='checkerBoardWipe' and $subtype='down'">checkerboard down</xsl:when><xsl:when test="$type='pushWipe' and $subtype='combHorizontal'">comb horizontal</xsl:when><xsl:when test="$type='pushWipe' and $subtype='combVertical'">comb vertical</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromTop' and @smil:direction='reverse'">uncover down</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromRight' and @smil:direction='reverse'">uncover left</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromLeft' and @smil:direction='reverse'">uncover right</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromBottom' and @smil:direction='reverse'">uncover up</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromTopRight' and @smil:direction='reverse'">uncover left-down</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromBottomRight' and @smil:direction='reverse'">uncover left-up</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromTopLeft' and @smil:direction='reverse'">uncover right-down</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromBottomLeft' and @smil:direction='reverse'">uncover right-up</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromTop'">cover down</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromRight'">cover left</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromLeft'">cover right</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromBottom'">cover up</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromTopRight'">cover left-down</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromBottomRight'">cover left-up</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromTopLeft'">cover right-down</xsl:when><xsl:when test="$type='slideWipe' and $subtype='fromBottomLeft'">cover right-up</xsl:when><xsl:when test="$type='fade' and $subtype='fadeOverColor'">fade through black</xsl:when><xsl:when test="$type='pushWipe' and $subtype='fromTop'">push down</xsl:when><xsl:when test="$type='pushWipe' and $subtype='fromRight'">push left</xsl:when><xsl:when test="$type='pushWipe' and $subtype='fromLeft'">push right</xsl:when><xsl:when test="$type='pushWipe' and $subtype='fromBottom'">push up</xsl:when><xsl:when test="$type='randomBarWipe' and $subtype='horizontal'">random bars horizontal</xsl:when><xsl:when test="$type='randomBarWipe' and $subtype='vertical'">random bars vertical</xsl:when><xsl:when test="$type='ellipseWipe' and $subtype='circle'">shape circle</xsl:when><xsl:when test="$type='irisWipe' and $subtype='diamond'">shape diamond</xsl:when><xsl:when test="$type='fourBoxWipe' and $subtype='cornersOut'">shape plus</xsl:when><xsl:when test="$type='barnDoorWipe' and $subtype='horizontal' and @smil:direction='reverse'">split horizontal in</xsl:when><xsl:when test="$type='barnDoorWipe' and $subtype='horizontal'">split horizontal out</xsl:when><xsl:when test="$type='barnDoorWipe' and $subtype='vertical' and @smil:direction='reverse'">split vertical in</xsl:when><xsl:when test="$type='barnDoorWipe' and $subtype='vertical'">split vertical out</xsl:when><xsl:when test="$type='fanWipe' and $subtype='centerTop'">wedge</xsl:when><xsl:when test="$type='pinWheelWipe' and $subtype='oneBlade'">wheel clockwise – 1 spoke</xsl:when><xsl:when test="$type='pinWheelWipe' and $subtype='twoBladeVertical'">wheel clockwise – 2 spoke</xsl:when><xsl:when test="$type='pinWheelWipe' and $subtype='threeBlade'">wheel clockwise – 3 spoke</xsl:when><xsl:when test="$type='pinWheelWipe' and $subtype='fourBlade'">wheel clockwise – 4 spoke</xsl:when><xsl:when test="$type='pinWheelWipe' and $subtype='eightBlade'">wheel clockwise – 8 spoke</xsl:when><xsl:when test="$type='barWipe' and $subtype='leftToRight' and @smil:direction='reverse'">wipe left</xsl:when><xsl:when test="$type='barWipe' and $subtype='leftToRight'">wipe right</xsl:when><xsl:when test="$type='barWipe' and $subtype='topToBottom' and @smil:direction='reverse'">wipe up</xsl:when><xsl:when test="$type='barWipe' and $subtype='topToBottom'">wipe down</xsl:when><xsl:when test="$type='blindsWipe' and $subtype='vertical'">blinds vertical</xsl:when><xsl:when test="$type='blindsWipe' and $subtype='horizontal'">blinds horizontal</xsl:when><xsl:when test="$type='dissolve'">dissolve</xsl:when><xsl:when test="$type='random'">random transition</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <演:声音 uof:locID="p0061" uof:attrList="预定义声音 自定义声音">
+ <xsl:choose>
+ <xsl:when test="not(presentation:sound)">
+ <xsl:attribute name="演:预定义声音">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="lujing">
+ <xsl:value-of select="substring-after(presentation:sound/@xlink:href,'share/gallery/sounds/')"/>
+ </xsl:variable>
+ <xsl:variable name="ming">
+ <xsl:value-of select="substring-before($lujing,'.wav')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$ming='applause'">
+ <xsl:attribute name="演:预定义声音">applause</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$ming='explos'">
+ <xsl:attribute name="演:预定义声音">explosion</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$ming='laser'">
+ <xsl:attribute name="演:预定义声音">laser</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:自定义声音"><xsl:value-of select="presentation:sound/@xlink:href"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </演:声音>
+ <演:方式 uof:locID="p0062">
+ <演:单击鼠标 uof:locID="p0065">
+ <xsl:choose>
+ <xsl:when test="@presentation:transition-type='automatic'">false</xsl:when>
+ <xsl:otherwise>true</xsl:otherwise>
+ </xsl:choose>
+ </演:单击鼠标>
+ <xsl:if test="@presentation:duration">
+ <演:时间间隔 uof:locID="p0066">
+ <xsl:variable name="hms">
+ <xsl:value-of select="substring-after(@presentation:duration,'PT')"/>
+ </xsl:variable>
+ <xsl:variable name="h">
+ <xsl:value-of select="number(substring-before($hms,'H'))"/>
+ </xsl:variable>
+ <xsl:variable name="ms">
+ <xsl:value-of select="substring-after($hms,'H')"/>
+ </xsl:variable>
+ <xsl:variable name="m">
+ <xsl:value-of select="number(substring-before($ms,'M'))"/>
+ </xsl:variable>
+ <xsl:variable name="s">
+ <xsl:value-of select="number(substring-before(substring-after($ms,'M'),'S'))"/>
+ </xsl:variable>
+ <xsl:value-of select="$h *3600 + $m * 60 + $s"/>
+ </演:时间间隔>
+ </xsl:if>
+ </演:方式>
+ </xsl:for-each>
+ </演:切换>
+ </演:幻灯片>
+ </xsl:template>
+ <xsl:template match="presentation:notes" mode="page">
+ <演:幻灯片备注 uof:locID="p0054" uof:attrList="备注母版引用">
+ <xsl:attribute name="演:备注母版引用"><xsl:variable name="cute"><xsl:value-of select="parent::node()/@draw:master-page-name"/></xsl:variable><xsl:value-of select="concat('note-',$cute)"/></xsl:attribute>
+ <xsl:call-template name="产生锚点"/>
+ <演:背景 uof:locID="p0057">
+ <图:颜色 uof:locID="g0034">#ffffff</图:颜色>
+ </演:背景>
+ </演:幻灯片备注>
+ </xsl:template>
+ <xsl:template name="产生锚点">
+ <xsl:for-each select="child::node( )">
+ <xsl:choose>
+ <xsl:when test="substring-before(name(),':')='draw'">
+ <uof:锚点 uof:locID="u0064" uof:attrList="x坐标 y坐标 宽度 高度 图形引用 随动方式 缩略图 占位符">
+ <xsl:variable name="nodename">
+ <xsl:value-of select="name(.)"/>
+ </xsl:variable>
+ <xsl:variable name="refpicname">
+ <xsl:choose>
+ <xsl:when test="@draw:style-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@presentation:style-name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="picnumber">
+ <xsl:choose>
+ <xsl:when test="@draw:style-name">
+ <xsl:value-of select="count(preceding::*[@draw:style-name=$refpicname])"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="count(preceding::*[@presentation:style-name=$refpicname])"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="uof:x坐标"><xsl:choose><xsl:when test="name(.)='draw:g'"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:choose><xsl:when test="@svg:x"><xsl:value-of select="substring-before(@svg:x,$uofUnit)"/></xsl:when><xsl:when test="@svg:x1"><xsl:value-of select="substring-before(@svg:x1,$uofUnit)"/></xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:y坐标"><xsl:choose><xsl:when test="name(.)='draw:g'"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:choose><xsl:when test="@svg:y"><xsl:value-of select="substring-before(@svg:y,$uofUnit)"/></xsl:when><xsl:when test="@svg:y1"><xsl:value-of select="substring-before(@svg:y1,$uofUnit)"/></xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:choose><xsl:when test="@svg:width"><xsl:value-of select="substring-before(@svg:width,$uofUnit)"/></xsl:when><xsl:when test="@svg:x1"><xsl:value-of select="substring-before(@svg:x2,$uofUnit) - substring-before(@svg:x1,$uofUnit)"/></xsl:when><xsl:when test="name(.)='draw:g'"><xsl:variable name="minx"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:variable name="svgx"><xsl:value-of select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/></xsl:variable><xsl:variable name="width"><xsl:value-of select="number(substring-before(descendant::node()[@svg:x][1]/@svg:width,$uofUnit))"/></xsl:variable><xsl:variable name="maxx"><xsl:call-template name="groupmaxx"><xsl:with-param name="value" select="$svgx + $width"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:value-of select="$maxx - $minx"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:高度"><xsl:choose><xsl:when test="@svg:height"><xsl:value-of select="substring-before(@svg:height,$uofUnit)"/></xsl:when><xsl:when test="@svg:x1"><xsl:value-of select="substring-before(@svg:y2,$uofUnit) - substring-before(@svg:y1,$uofUnit)"/></xsl:when><xsl:when test="name(.)='draw:g'"><xsl:variable name="miny"><xsl:call-template name="groupminy"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:variable name="svgy"><xsl:value-of select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/></xsl:variable><xsl:variable name="height"><xsl:value-of select="number(substring-before(descendant::node()[@svg:y][1]/@svg:height,$uofUnit))"/></xsl:variable><xsl:variable name="maxy"><xsl:call-template name="groupmaxy"><xsl:with-param name="value" select="$svgy + $height"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:value-of select="$maxy - $miny"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:图形引用"><xsl:choose><xsl:when test="@draw:id"><xsl:value-of select="@draw:id"/></xsl:when><xsl:when test="not(@draw:style-name) and name()='draw:g'"><xsl:value-of select="concat(child::node()[1]/@draw:style-name,'_',$picnumber)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat($refpicname,'_',$picnumber)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:随动方式"><xsl:choose><xsl:when test="key('graphicset',$refpicname)/node()/@style:protect"><xsl:for-each select="key('graphicset',$refpicname)/node()"><xsl:choose><xsl:when test="@style:protect='size'">move</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:for-each></xsl:when><xsl:otherwise>movesize</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="name(.)='draw:page-thumbnail'">
+ <xsl:attribute name="uof:缩略图">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(name(parent::node())='style:handout-master')">
+ <xsl:attribute name="uof:占位符"><xsl:choose><xsl:when test="@presentation:object"><xsl:value-of select="@presentation:object"/></xsl:when><xsl:when test=".//draw:image">graphic</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="@presentation:class">
+ <xsl:attribute name="uof:占位符"><xsl:value-of select="@presentation:class"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </uof:锚点>
+ </xsl:when>
+ <xsl:when test="name()= 'anim:par'">
+ <演:动画 uof:locID="p0042">
+ <xsl:apply-templates select="anim:seq"/>
+ </演:动画>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="anim:seq">
+ <xsl:apply-templates select="anim:par/anim:par/anim:par"/>
+ <xsl:apply-templates select="anim:par/anim:par/anim:iterate"/>
+ </xsl:template>
+ <xsl:template match="anim:par | anim:iterate">
+ <演:序列 uof:locID="p0043" uof:attrList="段落引用 动画对象">
+ <xsl:attribute name="演:动画对象"><xsl:choose>
+ <xsl:when test=".//@smil:targetElement"><xsl:value-of select=".//@smil:targetElement"/></xsl:when><xsl:when test="@anim:id"><xsl:value-of select="@anim:id"/></xsl:when><xsl:otherwise><xsl:value-of select="../@smil:targetElement"/></xsl:otherwise></xsl:choose></xsl:attribute>
+
+ <演:定时 uof:locID="p0067" uof:attrList="事件 延时 速度 重复 回卷">
+ <xsl:attribute name="演:事件">
+ <xsl:choose>
+ <xsl:when test="@presentation:node-type='on-click'">on click</xsl:when>
+ <xsl:when test="@presentation:node-type='with-previous'">with previous</xsl:when>
+ <xsl:otherwise><xsl:value-of select="@presentation:node-type"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="演:延时"><xsl:value-of select="substring-before(@smil:begin,'s')"/></xsl:attribute>
+ <xsl:attribute name="演:速度"><xsl:choose><xsl:when test="anim:animate/@smil:dur='0.5s'">very fast</xsl:when><xsl:when test="anim:animate/@smil:dur='1s'">fast</xsl:when><xsl:when test="anim:animate/@smil:dur='2s'">medium</xsl:when><xsl:when test="anim:animate/@smil:dur='3s'">slow</xsl:when><xsl:when test="anim:animate/@smil:dur='5s'">very slow</xsl:when><xsl:otherwise>medium</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="演:重复"><xsl:choose><xsl:when test="@smil:repeatCount = 'indefinite' "><xsl:choose><xsl:when test="@smil:end='next'">until next click</xsl:when><xsl:otherwise>until next slide</xsl:otherwise></xsl:choose></xsl:when><xsl:when test="@smil:repeatCount ='2' or @smil:repeatCount ='3' or @smil:repeatCount ='4' or @smil:repeatCount ='5' or @smil:repeatCount ='10' "><xsl:value-of select="@smil:repeatCount"/></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="演:回卷"><xsl:choose><xsl:when test="@smil:fill='remove'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </演:定时>
+ <演:增强 uof:locID="p0068">
+ <演:动画播放后 uof:locID="p0070" uof:attrList="颜色 变暗 播放后隐藏 单击后隐藏">
+ <xsl:if test="../anim:animateColor">
+ <xsl:attribute name="演:颜色"><xsl:value-of select="../anim:animateColor/@smil:to"/></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="../anim:animateColor">
+ <xsl:attribute name="演:变暗">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:变暗">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@presentation:preset-property='Direction;Accelerate;Decelerate' ">
+ <xsl:attribute name="演:播放后隐藏">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:播放后隐藏">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="../anim:set/@smil:to">
+ <xsl:attribute name="演:单击后隐藏">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:单击后隐藏">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </演:动画播放后>
+ <演:动画文本 uof:locID="p0071" uof:attrList="发送 间隔 动画形状 相反顺序">
+ <xsl:attribute name="演:发送"><xsl:choose><xsl:when test="@anim:iterate-type = 'by-word' ">by word</xsl:when><xsl:when test="@anim:iterate-type = 'by-letter' ">by letter</xsl:when><xsl:otherwise>all at once</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="演:间隔"><xsl:choose><xsl:when test="@anim:iterate-interval"><xsl:value-of select="substring-before(@anim:iterate-interval,'s')"/>
+</xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="演:动画形状">false</xsl:attribute>
+ <xsl:attribute name="演:相反顺序">false</xsl:attribute>
+ </演:动画文本>
+ <xsl:if test="anim:audio">
+ <演:声音 uof:locID="p0061" uof:attrList="预定义声音 自定义声音">
+ <xsl:variable name="audioname">
+ <xsl:value-of select="substring-after(anim:audio/@xlink:href,'gallery/sounds/')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="not($audioname='')">
+ <xsl:attribute name="演:预定义声音"><xsl:choose><xsl:when test="anim:audio/@xlink:href"><xsl:value-of select="anim:audio/@xlink:href"/></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:自定义声音"><xsl:value-of select="anim:audio/@xlink:href"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </演:声音>
+ </xsl:if>
+ </演:增强>
+ <演:效果 uof:locID="p0069">
+ <xsl:choose>
+ <xsl:when test="./@presentation:preset-class = 'entrance'">
+ <演:进入 uof:locID="p0073">
+ <xsl:apply-templates select="@presentation:preset-id"/>
+ </演:进入>
+ </xsl:when>
+ <xsl:when test="./@presentation:preset-class = 'exit'">
+ <演:退出 uof:locID="p0074">
+ <xsl:apply-templates select="@presentation:preset-id"/>
+ </演:退出>
+ </xsl:when>
+ <xsl:when test="./@presentation:preset-class = 'emphasis' ">
+ <演:强调 uof:locID="p0075">
+ <xsl:apply-templates select="@presentation:preset-id"/>
+ </演:强调>
+ </xsl:when>
+ <xsl:otherwise>
+ <演:动作路径 uof:locID="p0133" uof:attrList="路径">
+ <xsl:attribute name="演:路径">
+ <xsl:value-of select="anim:animateMotion/@svg:path"/>
+ </xsl:attribute>
+ </演:动作路径>
+ </xsl:otherwise>
+ </xsl:choose>
+ </演:效果>
+ </演:序列>
+ </xsl:template>
+ <xsl:template name="anim_speed">
+ <xsl:param name="speed"/>
+ <xsl:choose>
+ <xsl:when test="$speed='0.5s' or $speed='0.25s'">very fast</xsl:when>
+ <xsl:when test="$speed='1s'">fast</xsl:when>
+ <xsl:when test="$speed='2s'">medium</xsl:when>
+ <xsl:when test="$speed='3s'">slow</xsl:when>
+ <xsl:when test="$speed='5s'">very slow</xsl:when>
+ <xsl:otherwise>medium</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-venetian-blinds']">
+ <演:百叶窗 uof:locID="p0080" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:百叶窗>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-appear']">
+ <演:出现 uof:locID="p0081">
+ </演:出现>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-box']">
+ <演:盒状 uof:locID="p0082" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:盒状>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-diagonal-squares']">
+ <演:阶梯状 uof:locID="p0083" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'left-to-bottom' ">left down</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'left-to-top' ">left up</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'right-to-bottom' ">right down</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'right-to-top' ">right up</xsl:when></xsl:choose></xsl:attribute>
+ </演:阶梯状>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-wheel']">
+ <演:轮子 uof:locID="p0084" uof:attrList="速度 辐射状">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:辐射状"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:轮子>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-checkerboard']">
+ <演:棋盘 uof:locID="p0085" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:subtype"/></xsl:attribute>
+ </演:棋盘>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-flash-once']">
+ <演:闪烁一次 uof:locID="p0086" uof:attrList="速度">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:set/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ </演:闪烁一次>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-plus']">
+ <演:十字形扩展 uof:locID="p0087" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:十字形扩展>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-random']">
+ <演:随机效果 uof:locID="p0088">
+ </演:随机效果>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-circle']">
+ <演:圆形扩展 uof:locID="p0089" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:圆形扩展>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-wipe']">
+ <演:擦除 uof:locID="p0090" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'from-right'">from right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-left'">from left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top'">from top</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom'">from bottom</xsl:when></xsl:choose></xsl:attribute>
+ </演:擦除>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-fly-in']">
+ <演:飞入 uof:locID="p0091" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:animate/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'from-bottom'">from bottom</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top-right'">from top-right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top-left'">from top-left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom-left'">from bottom-left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom-right'">from bottom-right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-right'">from right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-left'">from left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top'">from top</xsl:when></xsl:choose></xsl:attribute>
+ </演:飞入>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-fly-in-slow']">
+ <演:缓慢飞入 uof:locID="p0092" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:animate/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'from-right'">from right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-left'">from left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top'">from top</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom'">from bottom</xsl:when></xsl:choose></xsl:attribute>
+ </演:缓慢飞入>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-diamond']">
+ <演:菱形 uof:locID="p0093" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:菱形>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-split']">
+ <演:劈裂 uof:locID="p0094" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'horizontal-out'">horizontal out</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'horizontal-in'">horizontal in</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'vertical-in'">vertical in</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'vertical-out'">vertical out</xsl:when></xsl:choose></xsl:attribute>
+ </演:劈裂>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-peek-in']">
+ <演:切入 uof:locID="p0095" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'from-right'">from right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-left'">from left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top'">from top</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom'">from bottom</xsl:when></xsl:choose></xsl:attribute>
+ </演:切入>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-wedge']">
+ <演:扇形展开 uof:locID="p0096" uof:attrList="速度">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ </演:扇形展开>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-random-bars']">
+ <演:随机线条 uof:locID="p0097" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:随机线条>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-dissolve-in']">
+ <演:向内溶解 uof:locID="p0098" uof:attrList="速度">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ </演:向内溶解>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-boomerang']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-bounce']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-curve-up']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-falling-in']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-flip']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-float']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-fold']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-glide']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-magnify']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-movie-credits']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-pinwheel']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-breaks']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-sling']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-spiral-in']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-swivel']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-thread']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-whip']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'oooo-entrance-ascend']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-center-revolve']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-colored-lettering']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-compress']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-descend']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-ease-in']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-rise-up']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-spin-in']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-stretchy']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-turn-and-grow']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-unfold']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-colored-lettering']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-expand']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-fade-in']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-fade-in-and-swivel']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-entrance-fade-in-and-zoom']">
+ <演:其他 uof:locID="p0099">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-fill-color']">
+ <演:更改填充颜色 uof:locID="p0124" uof:attrList="速度 颜色">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="../anim:animateColor/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:颜色"><xsl:value-of select="../anim:animateColor/@smil:to"/></xsl:attribute>
+ </演:更改填充颜色>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-font-color']">
+ <演:更改字体颜色 uof:locID="p0126" uof:attrList="速度 颜色">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="../anim:animateColor/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:颜色"><xsl:value-of select="../anim:animateColor/@smil:to"/></xsl:attribute>
+ </演:更改字体颜色>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-grow-and-shrink']">
+ <演:缩放 uof:locID="p0120" uof:attrList="速度 方向 预定义尺寸 自定义尺寸">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="../anim:animateTransform/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向">horizontal</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="../anim:animateTransform/@smil:to='0.25,1' ">
+ <xsl:attribute name="演:预定义尺寸">tiny</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="../anim:animateTransform/@smil:to='0.5,1' ">
+ <xsl:attribute name="演:预定义尺寸">smaller</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="../anim:animateTransform/@smil:to='1.5,1' ">
+ <xsl:attribute name="演:预定义尺寸">larger</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="../anim:animateTransform/@smil:to='4,1' ">
+ <xsl:attribute name="演:预定义尺寸">huge</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:自定义尺寸"><xsl:choose><xsl:when test="../anim:animateTransform/@smil:to"><xsl:value-of select="../anim:animateTransform/@smil:to"/></xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </演:缩放>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-font-size']">
+ <演:更改字号 uof:locID="p0125" uof:attrList="速度 预定义尺寸 自定义尺寸">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="../anim:animate/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="parent::anim:par/anim:animate/@smil:to='0.25,1' ">
+ <xsl:attribute name="演:预定义尺寸">tiny</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="parent::anim:par/anim:animate/@smil:to='0.5,1' ">
+ <xsl:attribute name="演:预定义尺寸">smaller</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="parent::anim:par/anim:animate/@smil:to='1.5,1' ">
+ <xsl:attribute name="演:预定义尺寸">larger</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="parent::anim:par/anim:animate/@smil:to='4,1' ">
+ <xsl:attribute name="演:预定义尺寸">huge</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:自定义尺寸"><xsl:choose><xsl:when test="parent::anim:par/anim:animate/@smil:to"><xsl:value-of select="parent::anim:par/anim:animate/@smil:to"/></xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </演:更改字号>
+ </xsl:template>
+ <xsl:template name="getfontstyle_emphasis">
+ <xsl:value-of select="concat(@smil:to,' ')"/>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-font-style']">
+ <演:更改字形 uof:locID="p0122" uof:attrList="字形 期间">
+ <xsl:attribute name="演:字形"><xsl:variable name="fontstyle"><xsl:for-each select="../anim:set"><xsl:call-template name="getfontstyle_emphasis"/></xsl:for-each></xsl:variable><xsl:value-of select="$fontstyle"/></xsl:attribute>
+ <xsl:attribute name="演:期间"><xsl:choose><xsl:when test="../@smil:repeatCount = 'indefinite' "><xsl:choose><xsl:when test="../@smil:end='next'">until next click</xsl:when><xsl:otherwise>until next slide</xsl:otherwise></xsl:choose></xsl:when><xsl:when test="../@smil:repeatCount ='2' or ../@smil:repeatCount ='3' or ../@smil:repeatCount ='4' or ../@smil:repeatCount ='5' or ../@smil:repeatCount ='10'"><xsl:value-of select="../@smil:repeatCount"/></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </演:更改字形>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-line-color']">
+ <演:更改线条颜色 uof:locID="p0121" uof:attrList="速度 颜色">
+ <xsl:attribute name="演:速度">medium</xsl:attribute>
+ <xsl:attribute name="演:颜色"><xsl:value-of select="../anim:animateColor/@smil:to"/></xsl:attribute>
+ </演:更改线条颜色>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-spin']">
+ <演:陀螺旋 uof:locID="p0123" uof:attrList="速度 顺时针方向 预定义角度 自定义角度">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:animateTransform/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:顺时针方向">true</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="parent::anim:par/anim:animateTransform/@smil:by='90'">
+ <xsl:attribute name="演:预定义角度">quarter spin</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="parent::anim:par/anim:animateTransform/@smil:by='180'">
+ <xsl:attribute name="演:预定义角度">half spin</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="parent::anim:par/anim:animateTransform/@smil:by='360'">
+ <xsl:attribute name="演:预定义角度">full spin</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="parent::anim:par/anim:animateTransform/@smil:by='720'">
+ <xsl:attribute name="演:预定义角度">two spins</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:自定义角度"><xsl:value-of select="parent::anim:par/anim:animateTransform/@smil:by"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </演:陀螺旋>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-transparency']">
+ <演:透明 uof:locID="p0127" uof:attrList="预定义透明度 自定义透明度 期间">
+ <xsl:choose>
+ <xsl:when test="../anim:set/@smil:to='0.25' ">
+ <xsl:attribute name="演:预定义透明度">25</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="../anim:set/@smil:to='0.5' ">
+ <xsl:attribute name="演:预定义透明度">50</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="../anim:set/@smil:to='0.75' ">
+ <xsl:attribute name="演:预定义透明度">75</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="../anim:set/@smil:to='1' ">
+ <xsl:attribute name="演:预定义透明度">100</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="演:自定义透明度"><xsl:value-of select="../anim:set/@smil:to"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="演:期间"><xsl:choose><xsl:when test="../@smil:repeatCount = 'indefinite' "><xsl:choose><xsl:when test="../@smil:end='next'">until next click</xsl:when><xsl:otherwise>until next slide</xsl:otherwise></xsl:choose></xsl:when><xsl:when test="../@smil:repeatCount ='2' or ../@smil:repeatCount ='3' or ../@smil:repeatCount ='4' or ../@smil:repeatCount ='5' or ../@smil:repeatCount ='10'"><xsl:value-of select="../@smil:repeatCount"/></xsl:when><xsl:otherwise>until next click</xsl:otherwise></xsl:choose></xsl:attribute>
+ </演:透明>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-font']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-blast']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-blink']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-bold-reveal']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-style-emphasis']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-wave']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-flicker']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-grow-with-color']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-shimmer']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-teeter']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-bold-flash']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-color-blend']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-color-over-by-letter']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-color-over-by-word']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-complementary-color']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-complementary-color-2']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-contrasting-color']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-darken']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-desaturate']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-flash-bulb']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-lighten']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-emphasis-reveal-underline']">
+ <演:其他 uof:locID="p0128">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-box']">
+ <演:盒状 uof:locID="p0111" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:盒状>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-checkerboard']">
+ <演:棋盘 uof:locID="p0114" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:subtype"/></xsl:attribute>
+ </演:棋盘>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-circle']">
+ <演:圆形扩展 uof:locID="p0109" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:圆形扩展>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-crawl-out']">
+ <演:缓慢移出 uof:locID="p0102" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="../anim:animate/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'from-right'">to right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-left'">to left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top'">to top</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom'">to bottom</xsl:when></xsl:choose></xsl:attribute>
+ </演:缓慢移出>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-diagonal-squares']">
+ <演:阶梯状 uof:locID="p0112" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'left-to-bottom' ">left down</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'left-to-top' ">left up</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'right-to-bottom' ">right down</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'right-to-top' ">right up</xsl:when></xsl:choose></xsl:attribute>
+ </演:阶梯状>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-diamond']">
+ <演:菱形 uof:locID="p0103" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:菱形>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-disappear']">
+ <演:消失 uof:locID="p0118">
+ </演:消失>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-dissolve']">
+ <演:向外溶解 uof:locID="p0108" uof:attrList="速度">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ </演:向外溶解>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-flash-once']">
+ <演:闪烁一次 uof:locID="p0115" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="../anim:animate/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ </演:闪烁一次>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-fly-out']">
+ <演:飞出 uof:locID="p0101" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="../anim:animate/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'from-bottom'">to bottom</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top-right'">to top-right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top-left'">to top-left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom-left'">to bottom-left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom-right'">to bottom-right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-right'">to right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-left'">to left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top'">to top</xsl:when></xsl:choose></xsl:attribute>
+ </演:飞出>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-peek-out']">
+ <演:切出 uof:locID="p0105" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'from-right'">to right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-left'">to left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top'">to top</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom'">to bottom</xsl:when></xsl:choose></xsl:attribute>
+ </演:切出>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-plus']">
+ <演:十字形扩展 uof:locID="p0116" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:十字形扩展>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-random-bars']">
+ <演:随机线条 uof:locID="p0107" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:随机线条>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-random']">
+ <演:随机效果 uof:locID="p0117">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:choose><xsl:when test="parent::anim:par/anim:transitionFilter/@smil:dur"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:when><xsl:otherwise><xsl:value-of select="../anim:animate/@smil:dur"/></xsl:otherwise></xsl:choose></xsl:with-param></xsl:call-template></xsl:attribute>
+ </演:随机效果>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-split']">
+ <演:劈裂 uof:locID="p0104" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'horizontal-out'">horizontal out</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'horizontal-in'">horizontal in</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'vertical-in'">vertical in</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'vertical-out'">vertical out</xsl:when></xsl:choose></xsl:attribute>
+ </演:劈裂>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-venetian-blinds']">
+ <演:百叶窗 uof:locID="p0100" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:百叶窗>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-wedge']">
+ <演:扇形展开 uof:locID="p0106" uof:attrList="速度">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ </演:扇形展开>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-wheel']">
+ <演:轮子 uof:locID="p0113" uof:attrList="速度 轮辐">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:轮辐"><xsl:value-of select="../@presentation:preset-sub-type"/></xsl:attribute>
+ </演:轮子>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-wipe']">
+ <演:擦除 uof:locID="p0110" uof:attrList="速度 方向">
+ <xsl:attribute name="演:速度"><xsl:call-template name="anim_speed"><xsl:with-param name="speed"><xsl:value-of select="parent::anim:par/anim:transitionFilter/@smil:dur"/></xsl:with-param></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="演:方向"><xsl:choose><xsl:when test="../@presentation:preset-sub-type = 'from-right'">from right</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-left'">from left</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-top'">from top</xsl:when><xsl:when test="../@presentation:preset-sub-type = 'from-bottom'">from bottom</xsl:when></xsl:choose></xsl:attribute>
+ </演:擦除>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-boomerang']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-bounce']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-curve-down']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-flip']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-float']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-fold']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-glide']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-magnify']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-movie-credits']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-pinwheel']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-breaks']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-sling']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-swish']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-swivel']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-thread']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-whip']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-ascend']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-center-revolve']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-collapse']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-colored-lettering']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-descend']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-ease-out']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-sink-down']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-spin-out']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-stretchy']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-turn-and-grow ']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-unfold']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-zoom']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-contract']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-fade-out']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-fade-out-and-swivel']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="@presentation:preset-id[. = 'ooo-exit-fade-out-and-zoom']">
+ <演:其他 uof:locID="p0119">
+ <xsl:copy-of select="parent::node()"/>
+ </演:其他>
+ </xsl:template>
+ <xsl:template match="draw:page" mode="styles">
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:template>
+ <xsl:template match="style:handout-master" mode="styles">
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:template>
+ <xsl:template match="style:master-page" mode="styles">
+ <xsl:apply-templates select="presentation:notes" mode="styles"/>
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:template>
+ <xsl:template match="presentation:notes" mode="styles">
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:template>
+ <xsl:template name="creategraphicstyles">
+ <xsl:for-each select="node()">
+ <xsl:variable name="nodename1">
+ <xsl:value-of select="name()"/>
+ </xsl:variable>
+ <xsl:if test="(substring-before($nodename1,':') = 'draw')">
+ <xsl:call-template name="draw">
+ <xsl:with-param name="nodename1" select="$nodename1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="draw">
+ <xsl:param name="nodename1"/>
+ <xsl:choose>
+ <xsl:when test="substring-after($nodename1,':') = 'a'">
+ <xsl:for-each select="child::*">
+ <xsl:call-template name="draw">
+ <xsl:with-param name="nodename">
+ <xsl:value-of select="name()"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="substring-after($nodename1,':') = 'g'">
+ <xsl:call-template name="draw:g"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="creategraphic"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="draw:g">
+ <xsl:for-each select="child::*">
+ <xsl:choose>
+ <xsl:when test="name()='draw:g'">
+ <xsl:call-template name="draw:g"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="creategraphic"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:call-template name="creategraphic"/>
+ </xsl:template>
+ <xsl:template name="zuheliebiao">
+ <xsl:param name="allnode"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="../child::*[$pos]">
+ <xsl:for-each select="../child::*[$pos]">
+ <xsl:variable name="nodepos">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="picnumber1">
+ <xsl:value-of select="count(preceding::*[@draw:style-name=$nodepos])"/>
+ </xsl:variable>
+ <xsl:variable name="pic-name1">
+ <xsl:value-of select="concat($nodepos,'_',$picnumber1)"/>
+ </xsl:variable>
+ <xsl:variable name="allnode1">
+ <xsl:value-of select="concat($allnode,',',$pic-name1)"/>
+ </xsl:variable>
+ <xsl:call-template name="zuheliebiao">
+ <xsl:with-param name="allnode" select="$allnode1"/>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$allnode"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="creategraphic">
+ <xsl:variable name="nodename">
+ <xsl:value-of select="name()"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="@draw:style-name or name()='draw:g'">
+ <xsl:variable name="pic-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="pic-num">
+ <xsl:value-of select="count(/descendant::*[@draw:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:variable name="picnumber">
+ <xsl:value-of select="count(preceding::*[@draw:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:call-template name="pic-process">
+ <xsl:with-param name="pic-name" select="$pic-name"/>
+ <xsl:with-param name="nodename" select="$nodename"/>
+ <xsl:with-param name="picnumber" select="$picnumber"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="@presentation:style-name">
+ <xsl:variable name="pic-name">
+ <xsl:value-of select="@presentation:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="pic-num">
+ <xsl:value-of select="count(/descendant::*[@presentation:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:variable name="picnumber">
+ <xsl:value-of select="count(preceding::*[@presentation:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:call-template name="pic-process">
+ <xsl:with-param name="pic-name" select="$pic-name"/>
+ <xsl:with-param name="picnumber" select="$picnumber"/>
+ <xsl:with-param name="nodename" select="$nodename"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="pic-process">
+ <xsl:param name="pic-name"/>
+ <xsl:param name="nodename"/>
+ <xsl:param name="picnumber"/>
+ <图:图形 uof:locID="g0000" uof:attrList="层次 标识符 组合列表 其他对象">
+ <xsl:attribute name="图:标识符"><xsl:choose><xsl:when test="@draw:id"><xsl:value-of select="@draw:id"/></xsl:when><xsl:when test="not(@draw:style-name) and name()='draw:g'"><xsl:value-of select="concat(child::node()[1]/@draw:style-name,'-',$picnumber)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat($pic-name,'_',$picnumber)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:层次"><xsl:choose><xsl:when test="name(parent::node())='draw:g'"><xsl:value-of select="position()"/></xsl:when><xsl:when test="@draw:z-index"><xsl:value-of select="@draw:z-index"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="position()"/></xsl:otherwise>
+ </xsl:choose></xsl:attribute>
+ <xsl:if test="$nodename='draw:g'">
+ <xsl:attribute name="图:组合列表"><xsl:for-each select="child::*[1]"><xsl:variable name="node1"><xsl:value-of select="@draw:style-name"/></xsl:variable><xsl:variable name="picnumber2"><xsl:value-of select="count(preceding::*[@draw:style-name=$node1])"/></xsl:variable><xsl:call-template name="zuheliebiao"><xsl:with-param name="allnode"><xsl:value-of select="concat($node1,'_',$picnumber2)"/></xsl:with-param><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:for-each></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//office:binary-data">
+ <xsl:attribute name="图:其他对象"><xsl:choose><xsl:when test="@draw:name"><xsl:value-of select="@draw:name"/></xsl:when><xsl:otherwise><xsl:value-of select="concat($pic-name,'_b1')"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="arrow-sign">
+ <xsl:choose>
+ <xsl:when test="key('graphicset',$pic-name)/style:graphic-properties/@draw:marker-start or key('graphicset',$pic-name)/style:graphic-properties/@draw:marker-end">
+ <xsl:value-of select="'1'"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:line' or $nodename='draw:rect' or $nodename='draw:circle' or $nodename='draw:polygon' or $nodename='draw:polyline' or $nodename='draw:ellipse' or $nodename='draw:page-thumbnail' or $nodename='draw:frame' or $nodename='draw:path'or $nodename='draw:g'">
+ <图:预定义图形 uof:locID="g0005">
+ <图:类别 uof:locID="g0006">
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:rect'">11</xsl:when>
+ <xsl:when test="$nodename='draw:line'">61</xsl:when>
+ <xsl:when test="$nodename='draw:circle'">19</xsl:when>
+ <xsl:when test="$nodename='draw:polygon'">65</xsl:when>
+ <xsl:when test="$nodename='draw:polyline'">66</xsl:when>
+ <xsl:when test="$nodename='draw:ellipse'">19</xsl:when>
+ <xsl:when test="$nodename='draw:page-thumbnail'">67</xsl:when>
+ <xsl:when test="$nodename='draw:frame'">3</xsl:when>
+ <xsl:when test="$nodename='draw:path'">64</xsl:when>
+ <xsl:when test="$nodename='draw:g'">4</xsl:when>
+ </xsl:choose>
+ </图:类别>
+ <图:名称 uof:locID="g0007">
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:rect'">Rectangle</xsl:when>
+ <xsl:when test="$nodename='draw:line'">Line</xsl:when>
+ <xsl:when test="$nodename='draw:circle'">Oval</xsl:when>
+ <xsl:when test="$nodename='draw:polygon'">Freeform</xsl:when>
+ <xsl:when test="$nodename='draw:polyline'">Scribble</xsl:when>
+ <xsl:when test="$nodename='draw:ellipse'">Oval</xsl:when>
+ <xsl:when test="$nodename='draw:page-thumbnail'">缩略图</xsl:when>
+ <xsl:when test="$nodename='draw:frame'">文本框</xsl:when>
+ <xsl:when test="$nodename='draw:path'">Curve</xsl:when>
+ <xsl:when test="$nodename='draw:g'">group</xsl:when>
+ </xsl:choose>
+ </图:名称>
+ <图:生成软件 uof:locID="g0008">PNG</图:生成软件>
+ <xsl:if test="./@draw:points or ./@svg:d">
+ <图:关键点坐标 uof:locID="g0009" uofattrList="路径">
+ <xsl:attribute name="图:路径"><xsl:choose><xsl:when test="@svg:d"><xsl:value-of select="@svg:d"/></xsl:when><xsl:when test="@draw:points"><xsl:call-template name="draw:points"><xsl:with-param name="point" select="@draw:points"/><xsl:with-param name="lujing"/></xsl:call-template></xsl:when></xsl:choose></xsl:attribute>
+ </图:关键点坐标>
+ </xsl:if>
+ <图:属性 uof:locID="g0011">
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$pic-name]) | (/office:document/*/style:style[@style:name=$pic-name]) ">
+ <xsl:for-each select="style:graphic-properties">
+ <xsl:if test="not(@draw:fill='none')">
+ <图:填充 uof:locID="g0012">
+ <xsl:call-template name="填充">
+ <xsl:with-param name="nodename" select="$nodename"/>
+ <xsl:with-param name="picname" select="$pic-name"/>
+ </xsl:call-template>
+ </图:填充>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="style:graphic-properties/@svg:stroke-color">
+ <图:线颜色 uof:locID="g0013">
+ <xsl:value-of select="style:graphic-properties/@svg:stroke-color"/>
+ </图:线颜色>
+ </xsl:if>
+ <图:线型 uof:locID="g0014">
+ <xsl:variable name="linetype" select="style:graphic-properties/@draw:stroke-dash"/>
+ <xsl:choose>
+ <xsl:when test="not(style:graphic-properties/@draw:stroke)">
+ <xsl:choose>
+ <xsl:when test="not(style:graphic-properties/@svg:stroke-width)">single</xsl:when>
+ <xsl:otherwise>thick</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:stroke = 'none'">none</xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$linetype='Fine_20_Dashed' and style:graphic-properties/@svg:stroke-width">dash-long-heavy</xsl:when>
+ <xsl:when test="$linetype='Fine_20_Dashed'">dash-long</xsl:when>
+ <xsl:when test="$linetype='_32__20_Dots_20_1_20_Dash' and style:graphic-properties/@svg:stroke-width">dash-dot-dot-heavy</xsl:when>
+ <xsl:when test="$linetype='_32__20_Dots_20_1_20_Dash'">dot-dot-dash</xsl:when>
+ <xsl:when test="$linetype='Ultrafine_20_Dashed' and style:graphic-properties/@svg:stroke-width">dashed-heavy</xsl:when>
+ <xsl:when test="$linetype='Ultrafine_20_Dotted_20__28_var_29_'and style:graphic-properties/@svg:stroke-width">dotted-heavy</xsl:when>
+ <xsl:when test="$linetype='Ultrafine_20_Dotted_20__28_var_29_'">dotted</xsl:when>
+ <xsl:when test="$linetype='Line_20_with_20_Fine_20_Dots'">double</xsl:when>
+ <xsl:when test="$linetype='_33__20_Dashes_20_3_20_Dots_20__28_var_29_' and style:graphic-properties/@svg:stroke-width">dash-dot-heavy</xsl:when>
+ <xsl:when test="$linetype='_33__20_Dashes_20_3_20_Dots_20__28_var_29_'">dot-dash</xsl:when>
+ <xsl:when test="$linetype='Ultrafine_20_2_20_Dots_20_3_20_Dashes'and style:graphic-properties/@svg:stroke-width">wavy-heavy</xsl:when>
+ <xsl:when test="$linetype='Ultrafine_20_2_20_Dots_20_3_20_Dashes'">wave</xsl:when>
+ <xsl:when test="$linetype='Fine_20_Dashed_20__28_var_29_'">wavy-double</xsl:when>
+ <xsl:otherwise>dash</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </图:线型>
+ <xsl:if test="style:graphic-properties/@svg:stroke-width">
+ <图:线粗细 uof:locID="g0016">
+ <xsl:value-of select="substring-before(style:graphic-properties/@svg:stroke-width,$uofUnit)"/>
+ </图:线粗细>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:marker-start and string-length(style:graphic-properties/@draw:marker-start)&gt;0">
+ <图:前端箭头 uof:locID="g0017">
+ <图:式样 uof:locID="g0018">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Arrow'">normal</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Line_20_Arrow'">open</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Arrow_20_concave'">stealth</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Circle'">oval</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Square_20_45'">diamond</xsl:when>
+ <xsl:otherwise>normal</xsl:otherwise>
+ </xsl:choose>
+ </图:式样>
+ <xsl:if test="style:graphic-properties/@draw:marker-start-width">
+ <图:大小 uof:locID="g0019">
+ <xsl:variable name="width">
+ <xsl:value-of select="substring-before(style:graphic-properties/@draw:marker-start-width,$uofUnit)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="($width&lt;0.05 and 0&lt;$width) or $width=0.05">1</xsl:when>
+ <xsl:when test="($width&lt;0.10 and 0.05&lt;$width) or $width=0.10">2</xsl:when>
+ <xsl:when test="($width&lt;0.15 and 0.10&lt;$width) or $width=0.15">3</xsl:when>
+ <xsl:when test="($width&lt;0.20 and 0.15&lt;$width) or $width=0.20">4</xsl:when>
+ <xsl:when test="($width&lt;0.25 and 0.20&lt;$width) or $width=0.25">5</xsl:when>
+ <xsl:when test="($width&lt;0.30 and 0.25&lt;$width) or $width=0.30">6</xsl:when>
+ <xsl:when test="($width&lt;0.35 and 0.30&lt;$width) or $width=0.35">7</xsl:when>
+ <xsl:when test="($width&lt;0.40 and 0.35&lt;$width) or $width=0.40">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </图:大小>
+ </xsl:if>
+ </图:前端箭头>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:marker-end">
+ <图:后端箭头 uof:locID="g0020">
+ <图:式样 uof:locID="g0021">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Arrow'">normal</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Line_20_Arrow'">open</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Arrow_20_concave'">stealth</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Circle'">oval</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Square_20_45'">diamond</xsl:when>
+ <xsl:otherwise>normal</xsl:otherwise>
+ </xsl:choose>
+ </图:式样>
+ <xsl:if test="style:graphic-properties/@draw:marker-end-width">
+ <图:大小 uof:locID="g0022">
+ <xsl:variable name="width">
+ <xsl:value-of select="number(substring-before(style:graphic-properties/@draw:marker-end-width,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="($width&lt;0.05 and 0&lt;$width) or $width=0.05">1</xsl:when>
+ <xsl:when test="($width&lt;0.10 and 0.05&lt;$width) or $width=0.10">2</xsl:when>
+ <xsl:when test="($width&lt;0.15 and 0.10&lt;$width) or $width=0.15">3</xsl:when>
+ <xsl:when test="($width&lt;0.20 and 0.15&lt;$width) or $width=0.20">4</xsl:when>
+ <xsl:when test="($width&lt;0.25 and 0.20&lt;$width) or $width=0.25">5</xsl:when>
+ <xsl:when test="($width&lt;0.30 and 0.25&lt;$width) or $width=0.30">6</xsl:when>
+ <xsl:when test="($width&lt;0.35 and 0.30&lt;$width) or $width=0.35">7</xsl:when>
+ <xsl:when test="($width&lt;0.40 and 0.35&lt;$width) or $width=0.40">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </图:大小>
+ </xsl:if>
+ </图:后端箭头>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:opacity or style:graphic-properties/@svg:stroke-opacity or style:graphic-properties/@svg:stroke-opacity">
+ <图:透明度 uof:locID="g0038">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:opacity">
+ <xsl:variable name="transparency">
+ <xsl:value-of select="substring-before(style:graphic-properties/@draw:opacity,'%')"/>
+ </xsl:variable>
+ <xsl:value-of select="(100 - $transparency) div 100"/>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@svg:stroke-opacity">
+ <xsl:variable name="transparency">
+ <xsl:value-of select="substring-before(style:graphic-properties/@svg:stroke-opacity,'%')"/>
+ </xsl:variable>
+ <xsl:value-of select="(100 - $transparency) div 100"/>
+ </xsl:when>
+ <xsl:when test="style:properties/@svg:stroke-opacity">
+ <xsl:value-of select="substring-before(style:properties/@svg:stroke-opacity,'%')"/>
+ </xsl:when>
+ </xsl:choose>
+ </图:透明度>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="@svg:x1">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:x2,$uofUnit) - substring-before(@svg:x1,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:y2,$uofUnit) - substring-before(@svg:y1,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="@svg:x">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="@svg:width">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ </xsl:choose>
+ <图:旋转角度 uof:locID="g0025">
+ <xsl:choose>
+ <xsl:when test="@draw:transform">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="@draw:transform"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-temp">
+ <xsl:value-of select="substring-before(substring-after($rotate-angle,'rotate ('),')')"/>
+ </xsl:variable>
+ <xsl:value-of select="($rotate-temp * 360) div (2 * 3.14159265)"/>
+ </xsl:when>
+ <xsl:otherwise>0.0</xsl:otherwise>
+ </xsl:choose>
+ </图:旋转角度>
+ <图:X-缩放比例 uof:locID="g0026">1</图:X-缩放比例>
+ <图:Y-缩放比例 uof:locID="g0027">1</图:Y-缩放比例>
+ <图:锁定纵横比 uof:locID="g0028">0</图:锁定纵横比>
+ <图:相对原始比例 uof:locID="g0029">1</图:相对原始比例>
+ <图:打印对象 uof:locID="g0032">true</图:打印对象>
+ <图:Web文字 uof:locID="g0033"/>
+ </图:属性>
+ </图:预定义图形>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="./text:p or ./draw:text-box">
+ <图:文本内容 uof:locID="g0002" uof:attrList="文本框 左边距 右边距 上边距 下边距 水平对齐 垂直对齐 文字排列方向 自动换行 大小适应文字 前一链接 后一链接">
+ <xsl:if test="$nodename='draw:text-box'">
+ <xsl:attribute name="图:文本框">true</xsl:attribute>
+ <xsl:if test="./@draw:name = /office:document/office:body
+//draw:text-box/@draw:chain-next-name">
+ <xsl:attribute name="图:前一链接"><xsl:variable name="drawname"><xsl:value-of select="./@draw:name"/></xsl:variable><xsl:variable name="befor-link-name"><xsl:value-of select="/office:document/office:body
+//draw:text-box[@draw:name=$drawname]/@draw:style-name"/></xsl:variable><xsl:value-of select="concat($befor-link-name,'_',$picnumber)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="./@draw:chain-next-name">
+ <xsl:attribute name="图:后一链接"><xsl:variable name="next-link"><xsl:value-of select="./@draw:chain-next-name"/></xsl:variable><xsl:variable name="link-name"><xsl:value-of select="/office:document/office:body
+//draw:text-box[@draw:name=$next-link]/@draw:style-name"/></xsl:variable><xsl:value-of select="concat($link-name,'_',$picnumber)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$pic-name]) | (/office:document/office:automatic-styles/descendant::*[@style:name=$pic-name]) ">
+ <xsl:if test="style:graphic-properties/@fo:padding-left">
+ <xsl:attribute name="图:左边距"><xsl:value-of select="substring-before(style:graphic-properties/@fo:padding-left,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:右边距"><xsl:value-of select="substring-before(style:graphic-properties/@fo:padding-right,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:上边距"><xsl:value-of select="substring-before(style:graphic-properties/@fo:padding-top,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:下边距"><xsl:value-of select="substring-before(style:graphic-properties/@fo:padding-bottom,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:文字排列方向">
+ <xsl:choose>
+ <xsl:when test="style:paragraph-properties/@style:writing-mode">
+ <xsl:choose>
+ <xsl:when test="style:paragraph-properties/@style:writing-mode='tb-rl' and style:graphic-properties/@draw:textarea-vertical-align='bottom'">vert-l2r</xsl:when>
+ <xsl:when test="style:paragraph-properties/@style:writing-mode='tb-rl'">vert-r2l</xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:textarea-horizontal-align='right'">hori-r2l</xsl:when>
+ <xsl:otherwise>hori-l2r</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:if test="style:graphic-properties/@fo:wrap-option">
+ <xsl:attribute name="图:自动换行">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:auto-grow-width='true'">
+ <xsl:attribute name="图:大小适应文字">true</xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="./draw:text-box">
+ <xsl:for-each select="draw:text-box/node( )">
+ <xsl:choose>
+ <xsl:when test="name()='text:list'">
+ <xsl:call-template name="unordered-ordered-list">
+ <xsl:with-param name="currlistlvl" select="number('1')"/>
+ <xsl:with-param name="liststylename" select="@text:style-name"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name()='text:p'or name()='text:h'">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="./text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </图:文本内容>
+ </xsl:if>
+ <图:控制点 uof:locID="g0003" uof:attrList="x坐标 y坐标">
+ <xsl:attribute name="图:x坐标"><xsl:value-of select="substring-before(@svg:x,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:y坐标"><xsl:value-of select="substring-before(@svg:y,$uofUnit)"/></xsl:attribute>
+ </图:控制点>
+ <图:翻转 uof:locID="g0040" uof:attrList="方向" 图:方向="x"/>
+ </图:图形>
+ <xsl:if test="name(..)='draw:g'">
+ <图:组合位置 uof:locID="g0041" uof:attrList="x坐标 y坐标">
+ <xsl:attribute name="图:x坐标"><xsl:variable name="minx"><xsl:for-each select="parent::node()"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:for-each></xsl:variable><xsl:choose><xsl:when test="name(.)='draw:g'"><xsl:variable name="current-minx"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:value-of select="$current-minx - $minx"/></xsl:when><xsl:otherwise><xsl:variable name="current-x" select="number(substring-before(@svg:x,$uofUnit))"/><xsl:value-of select="$current-x - $minx"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:y坐标"><xsl:variable name="miny"><xsl:for-each select="parent::node()"><xsl:call-template name="groupminy"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:for-each></xsl:variable><xsl:choose><xsl:when test="name(.)='draw:g'"><xsl:variable name="current-miny"><xsl:call-template name="groupminy"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:value-of select="$current-miny - $miny"/></xsl:when><xsl:otherwise><xsl:variable name="current-y" select="number(substring-before(@svg:y,$uofUnit))"/><xsl:value-of select="$current-y - $miny"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </图:组合位置>
+ </xsl:if>
+ <xsl:if test="name()='draw:frame' and ./draw:image">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:choose><xsl:when test="@draw:id"><xsl:value-of select="@draw:id"/></xsl:when><xsl:otherwise><xsl:value-of select="concat($pic-name,'_',$picnumber)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <xsl:attribute name="uof:公共类型">jpg</xsl:attribute>
+ <xsl:if test="./draw:image/office:binary-data">
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="./draw:image/office:binary-data"/>
+ </uof:数据>
+ </xsl:if>
+ <xsl:if test="./draw:image/@xlink:href">
+ <uof:路径 uof:locID="u0038">
+ <xsl:value-of select="./draw:image/@xlink:href"/>
+ </uof:路径>
+ </xsl:if>
+ </uof:其他对象>
+ </xsl:if>
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$pic-name]) | (/office:document/office:automatic-styles/descendant::*[@style:name=$pic-name]) ">
+ <xsl:if test="style:graphic-properties/@draw:fill-image-name and @draw:fill='bitmap'">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:choose><xsl:when test="@draw:id"><xsl:value-of select="@draw:id"/></xsl:when><xsl:otherwise><xsl:value-of select="concat($pic-name,'_',$picnumber)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">jpg</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <xsl:variable name="fill-name">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-image-name"/>
+ </xsl:variable>
+ <uof:数据 uof:locID="u0037">
+ <xsl:for-each select="/office:document/office:styles/draw:fill-image[@draw:name=$fill-name]">
+ <xsl:value-of select="office:binary-data"/>
+ </xsl:for-each>
+ </uof:数据>
+ <uof:路径 uof:locID="u0038">
+ <xsl:value-of select="@xlink:href"/>
+ </uof:路径>
+ </uof:其他对象>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="unordered-ordered-list">
+ <xsl:param name="currlistlvl"/>
+ <xsl:param name="liststylename"/>
+ <xsl:for-each select="text:list-item">
+ <xsl:if test="text:p">
+ <xsl:for-each select="text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="$currlistlvl"/>
+ <xsl:with-param name="liststylename" select="$liststylename"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:for-each select="node( )">
+ <xsl:if test="name()='text:list'">
+ <xsl:call-template name="unordered-ordered-list">
+ <xsl:with-param name="currlistlvl" select="$currlistlvl +1"/>
+ <xsl:with-param name="liststylename" select="$liststylename"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="groupminx">
+ <xsl:param name="value"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="descendant::node()[@svg:x][position()=$pos]">
+ <xsl:variable name="othervalue" select="number(substring-before(descendant::node()[@svg:x][position()=$pos]/@svg:x,$uofUnit))"/>
+ <xsl:call-template name="groupminx">
+ <xsl:with-param name="value">
+ <xsl:choose>
+ <xsl:when test="$value&gt;$othervalue">
+ <xsl:value-of select="$othervalue"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="groupminy">
+ <xsl:param name="value"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="descendant::node()[@svg:y][position()=$pos]">
+ <xsl:variable name="othervalue" select="number(substring-before(descendant::node()[@svg:y][position()=$pos]/@svg:y,$uofUnit))"/>
+ <xsl:call-template name="groupminy">
+ <xsl:with-param name="value">
+ <xsl:choose>
+ <xsl:when test="$value&gt;$othervalue">
+ <xsl:value-of select="$othervalue"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="groupmaxx">
+ <xsl:param name="value"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="descendant::node()[@svg:x][position()=$pos]">
+ <xsl:variable name="svgx">
+ <xsl:value-of select="number(substring-before(descendant::node()[@svg:x][position()=$pos]/@svg:x,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:variable name="width">
+ <xsl:value-of select="number(substring-before(descendant::node()[@svg:x][position()=$pos]/@svg:width,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:variable name="othervalue" select="$svgx + $width"/>
+ <xsl:call-template name="groupminx">
+ <xsl:with-param name="value">
+ <xsl:choose>
+ <xsl:when test="$value&gt;$othervalue">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$othervalue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="groupmaxy">
+ <xsl:param name="value"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="descendant::node()[@svg:y][position()=$pos]">
+ <xsl:variable name="svgy">
+ <xsl:value-of select="number(substring-before(descendant::node()[@svg:y][position()=$pos]/@svg:y,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:variable name="height">
+ <xsl:value-of select="number(substring-before(descendant::node()[@svg:y][position()=$pos]/@svg:height,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:variable name="othervalue" select="$svgy + $height"/>
+ <xsl:call-template name="groupminy">
+ <xsl:with-param name="value">
+ <xsl:choose>
+ <xsl:when test="$value&gt;$othervalue">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$othervalue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="draw:points">
+ <xsl:param name="point"/>
+ <xsl:param name="lujing"/>
+ <xsl:choose>
+ <xsl:when test="contains($point,' ' )">
+ <xsl:variable name="first-point" select="substring-before($point,' ')"/>
+ <xsl:variable name="other-point" select="substring-after($point,' ')"/>
+ <xsl:variable name="xzuobiao">
+ <xsl:value-of select="substring-before($first-point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:variable name="yzuobiao">
+ <xsl:value-of select="substring-after($first-point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:call-template name="draw:points">
+ <xsl:with-param name="point" select="$other-point"/>
+ <xsl:with-param name="lujing" select="concat($lujing,$xzuobiao,' ',$yzuobiao,'lineto')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="xzuobiao">
+ <xsl:value-of select="substring-before($point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:variable name="yzuobiao">
+ <xsl:value-of select="substring-after($point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:value-of select="concat($lujing,$xzuobiao,' ',$yzuobiao)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="execParagraph">
+ <xsl:param name="currlistlvl"/>
+ <xsl:param name="liststylename"/>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <xsl:if test="@text:id">
+ <xsl:attribute name="字:动画标识"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:choose><xsl:when test="@text:id"><xsl:value-of select="@text:id"/></xsl:when><xsl:otherwise><xsl:value-of select="@text:style-name"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="not(number($currlistlvl) =number('0'))">
+ <xsl:variable name="parent-position">
+ <xsl:number from="/office:document/office:body/text:ordered-list" level="any" count="text:list-item/text:p" format="1"/>
+ </xsl:variable>
+ <xsl:element name="字:自动编号信息">
+ <xsl:attribute name="uof:locID">t0059</xsl:attribute>
+ <xsl:attribute name="uof:attrList">编号引用 编号级别 重新编号 起始编号</xsl:attribute>
+ <xsl:attribute name="字:编号引用"><xsl:value-of select="$liststylename"/></xsl:attribute>
+ <xsl:attribute name="字:编号级别"><xsl:value-of select="$currlistlvl"/></xsl:attribute>
+ <xsl:attribute name="字:重新编号"><xsl:choose><xsl:when test="number($parent-position)=number('1')">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="字:起始编号"><xsl:for-each select="//text:list-style[$liststylename=@style:name]/*[number($currlistlvl)=number(@text:level)]"><xsl:choose><xsl:when test="@text:start-value"><xsl:value-of select="@text:start-value"/></xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:for-each></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:variable name="stylename">
+ <xsl:value-of select="@text:style-name"/>
+ </xsl:variable>
+ <xsl:for-each select="(//style:style[@style:name=$stylename])">
+ <xsl:call-template name="ParaAttribute">
+ <xsl:with-param name="text-style-name" select="@text:style-name"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:for-each select="node( )">
+ <xsl:choose>
+ <xsl:when test="self::node( )[name(.)='text:span']">
+ <xsl:call-template name="textspan"/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:time']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:s']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="substring-before(name(.),':')='draw' and not(name(.)='draw:a')">
+ </xsl:when>
+ <xsl:when test="name(.)='text:a'">
+ <字:句 uof:locID="t0085">
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <字:字体 uof:locID="t0088" uof:attrList="西文字体引用 中文字体引用 字号 颜色" 字:颜色="#0000ff"/>
+ <字:下划线 uof:locID="t0095" 字:类型="single" 字:颜色="#0000ff" uof:attrList="类型 颜色 字下划线"/>
+ </xsl:element>
+ <xsl:element name="字:区域开始">
+ <xsl:attribute name="字:标识符">hlnk<xsl:number from="/office:document/office:body" level="any" count="text:p[text:a]"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Hyperlink</xsl:attribute>
+ <xsl:attribute name="字:类型">hyperlink</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0121</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型</xsl:attribute>
+ </xsl:element>
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ <xsl:element name="字:区域结束">
+ <xsl:attribute name="字:标识符引用">hlnk<xsl:number from="/office:document/office:body" level="any" count="text:p[text:a]"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0122</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符引用</xsl:attribute>
+ </xsl:element>
+ </字:句>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="字:句"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </字:段落>
+ </xsl:template>
+ <xsl:template name="字:句">
+ <xsl:if test="not(name(.)='text:bookmark-start' or name(.)='text:bookmark-end' or name(.)='draw:image' or name(.)='office:binary-data')">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用">
+ <xsl:choose>
+ <xsl:when test="@text:style-name">
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="parent::node( )/@text:style-name"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:句属性>
+ <xsl:choose>
+ <xsl:when test="(preceding-sibling::text:bookmark-start) and (following-sibling::text:bookmark-end)">
+ <字:区域开始 uof:locID="t0121" uof:attrList="标识符 名称 类型">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="preceding-sibling::text:bookmark-start/@text:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Bookmark</xsl:attribute>
+ <xsl:attribute name="字:类型">bookmark</xsl:attribute>
+ </字:区域开始>
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ <字:区域结束 uof:locID="t0122" uof:attrList="标识符引用">
+ <xsl:attribute name="字:标识符引用"><xsl:value-of select="following-sibling::text:bookmark-end/@text:name"/></xsl:attribute>
+ </字:区域结束>
+ </xsl:when>
+ <xsl:when test="preceding-sibling::text:bookmark">
+ <字:区域开始 uof:locID="t0121" uof:attrList="标识符 名称 类型">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="preceding-sibling::text:bookmark/@text:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Bookmark</xsl:attribute>
+ <xsl:attribute name="字:类型">bookmark</xsl:attribute>
+ </字:区域开始>
+ <字:区域结束 uof:locID="t0122" uof:attrList="标识符引用">
+ <xsl:attribute name="字:标识符引用"><xsl:value-of select="preceding-sibling::text:bookmark/@text:name"/></xsl:attribute>
+ </字:区域结束>
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </xsl:when>
+ <xsl:when test="name(.)='draw:a'">
+ <xsl:variable name="link-name">
+ <xsl:value-of select="substring-after(@xlink:href,'#')"/>
+ </xsl:variable>
+ <字:区域开始 uof:locID="t0121" uof:attrList="标识符 名称 类型">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="$link-name"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Bookmark</xsl:attribute>
+ <xsl:attribute name="字:类型">bookmark</xsl:attribute>
+ </字:区域开始>
+ <字:区域结束 uof:locID="t0122" uof:attrList="标识符引用">
+ <xsl:attribute name="字:标识符引用"><xsl:value-of select="$link-name"/></xsl:attribute>
+ </字:区域结束>
+ </xsl:when>
+ <xsl:when test="self::node( )[name(.)='text:tab-stop']">
+ <xsl:element name="字:制表符">
+ <xsl:attribute name="uof:locID">t0123</xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="name(.)='text:bookmark-start' or name(.)='text:bookmark-end' or name(.)='draw:image' or name(.)='office:binary-data'">
+ </xsl:when>
+ <xsl:otherwise>
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:句>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="jiaozhu">
+ <字:脚注 uof:locID="t0107" uof:attrList="引文体">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </字:脚注>
+ </xsl:template>
+ <xsl:template match="text:s">
+ <xsl:param name="bText"/>
+ <xsl:choose>
+ <xsl:when test="$bText='0'">
+ <xsl:variable name="count">
+ <xsl:choose>
+ <xsl:when test="not(@text:c)">1</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@text:c+1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <字:句 uof:locID="t0085">
+ <字:空格符 uof:locID="t0126" uof:attrList="个数" 字:个数="{$count}"/>
+ </字:句>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:空格符 uof:locID="t0126" uof:attrList="个数" 字:个数="{@text:c}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="weizhu">
+ <字:尾注 uof:locID="t0108" uof:attrList="引文体">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </字:尾注>
+ </xsl:template>
+ <xsl:template match="text:time">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'TIME'"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <字:段落 uof:locID="t0051">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <xsl:variable name="timefmt">
+ <xsl:variable name="aa" select="@style:data-style-name"/>
+ <xsl:for-each select="key('geshi',$aa)/number:hours | key('geshi',$aa)/number:minutes | key('geshi',$aa)/number:am-pm | key('geshi',$aa)/number:seconds | key('geshi',$aa)/number:text">
+ <xsl:choose>
+ <xsl:when test="@number:style='long' ">
+ <xsl:if test="self::node( )[name(.)='number:hours']">HH</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:minutes']">MM</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:seconds']">SS</xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="self::node( )[name(.)='number:text']">
+ <xsl:value-of select="."/>
+ </xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:hours']">H</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:minutes']">M</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:seconds']">S</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:am-pm']">AMPM</xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="quote">"</xsl:variable>
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="concat('TIME \@ ',$quote,$timefmt,$quote,' \* MERGEFORMAT ')"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="ParaAttribute">
+ <xsl:param name="text-style-name"/>
+ <xsl:for-each select="/office:document/office:styles/style:style">
+ <xsl:if test="@style:name=$text-style-name and not($text-style-name='Standard')">
+ <xsl:element name="字:格式修订">
+ <xsl:attribute name="uof:locID">t0053</xsl:attribute>
+ <xsl:attribute name="uof:attrList">修订信息引用</xsl:attribute>
+ <xsl:attribute name="字:修订信息引用"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@style:name"/></xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="@style:name='Heading'">
+ <xsl:element name="字:大纲级别">
+ <xsl:attribute name="uof:locID">t0054</xsl:attribute>
+ <xsl:value-of select="substring-after(@style:name,'Heading')"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:text-align or .//@style:vertical-align">
+ <xsl:element name="字:对齐">
+ <xsl:attribute name="uof:locID">t0055</xsl:attribute>
+ <xsl:attribute name="uof:attrList">水平对齐 文字对齐</xsl:attribute>
+ <xsl:attribute name="字:水平对齐"><xsl:choose><xsl:when test=".//@fo:text-align='end'">right</xsl:when><xsl:when test=".//@fo:text-align='center'">center</xsl:when><xsl:when test=".//@fo:text-align='justify' and not(.//@fo:text-align-last='justify')">justified</xsl:when><xsl:when test=".//@fo:text-align='justify' and .//@fo:text-align-last='justify'">distributed</xsl:when><xsl:otherwise>left</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="字:文字对齐"><xsl:choose><xsl:when test=".//@style:vertical-align='baseline'">base</xsl:when><xsl:when test=".//@style:vertical-align='top'">top</xsl:when><xsl:when test=".//@style:vertical-align='middle'">center</xsl:when><xsl:when test=".//@style:vertical-align='bottom'">bottom</xsl:when><xsl:otherwise>auto</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:margin-left or .//@fo:margin-right or .//@fo:text-indent">
+ <xsl:element name="字:缩进">
+ <xsl:attribute name="uof:locID">t0056</xsl:attribute>
+ <xsl:call-template name="字:缩进类型"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:行距">
+ <xsl:attribute name="uof:locID">t0057</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 值</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="contains(.//@fo:line-height,$uofUnit)">
+ <xsl:attribute name="字:类型">fixed</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(.//@fo:line-height,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(.//@fo:line-height,'%')">
+ <xsl:attribute name="字:类型">multi-lines</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(.//@fo:line-height,'%') div 100"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test=".//@style:line-height-at-least">
+ <xsl:attribute name="字:类型">at-least</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(.//@style:line-height-at-least,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test=".//@style:line-spacing">
+ <xsl:attribute name="字:类型">line-space</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(.//@style:line-spacing,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:类型">multi-lines</xsl:attribute>
+ <xsl:attribute name="字:值">1.0</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test=".//@fo:orphans">
+ <xsl:element name="字:孤行控制">
+ <xsl:attribute name="uof:locID">t0060</xsl:attribute>
+ <xsl:value-of select=".//@fo:orphans"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:widows">
+ <xsl:element name="字:寡行控制">
+ <xsl:attribute name="uof:locID">t0061</xsl:attribute>
+ <xsl:value-of select=".//@fo:widows"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:break-inside">
+ <xsl:element name="字:段中不分页">
+ <xsl:attribute name="uof:locID">t0062</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:keep-with-next">
+ <xsl:element name="字:与下段同页">
+ <xsl:attribute name="uof:locID">t0063</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:break-before">
+ <xsl:element name="字:段前分页">
+ <xsl:attribute name="uof:locID">t0064</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:snap-to-layout-grid">
+ <xsl:element name="字:对齐网格">
+ <xsl:attribute name="uof:locID">t0069</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test=".//@style:snap-to-layout-grid='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//style:drop-cap">
+ <xsl:element name="字:首字下沉">
+ <xsl:attribute name="uof:locID">t0070</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 字体引用 字符数 行数 间距</xsl:attribute>
+ <xsl:attribute name="字:类型">dropped</xsl:attribute>
+ <xsl:if test=".//style:drop-cap/@style:style-name">
+ <xsl:attribute name="字:字体引用"><xsl:value-of select=".//style:drop-cap/@style:style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//style:drop-cap/@style:distance">
+ <xsl:attribute name="字:间距"><xsl:value-of select="substring-before(.//style:drop-cap/@style:distance,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//style:drop-cap/@style:length">
+ <xsl:attribute name="字:字符数"><xsl:value-of select=".//style:drop-cap/@style:length"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//style:drop-cap/@style:lines">
+ <xsl:attribute name="字:行数"><xsl:value-of select=".//style:drop-cap/@style:lines"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:hyphenate">
+ <xsl:element name="字:取消断字">
+ <xsl:attribute name="uof:locID">t0071</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select=".//@fo:hyphenate"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@text:number-lines">
+ <xsl:element name="字:取消行号">
+ <xsl:attribute name="字:值"><xsl:value-of select=".//@text:number-lines"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0072</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:允许单词断字">
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0073</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ <xsl:if test=".//@style:punctuation-wrap">
+ <xsl:element name="字:行首尾标点控制">
+ <xsl:attribute name="uof:locID">t0074</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test=".//@style:punctuation-wrap='hanging'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:是否行首标点压缩">
+ <xsl:attribute name="uof:locID">t0075</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">false</xsl:attribute>
+ </xsl:element>
+ <xsl:if test=".//@style:line-break ">
+ <xsl:element name="字:中文习惯首尾字符">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test=".//@style:line-break='strict'">true</xsl:when><xsl:when test=".//@style:line-break='normal'">false</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0076</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:text-autospace">
+ <xsl:element name="字:自动调整中英文字符间距">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test=".//@style:text-autospace='ideograph-alpha'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0077</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@style:text-autospace">
+ <xsl:element name="字:自动调整中文与数字间距">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test=".//@style:text-autospace='ideograph-alpha'">true </xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0078</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:有网格自动调整右缩进">
+ <xsl:attribute name="字:值">false</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0195</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ <xsl:if test=".//@fo:border or .//@fo:border-top or .//@fo:border-bottom or .//@fo:border-left or .//@fo:border-right or .//@style:shadow[.!='none']">
+ <xsl:element name="字:边框">
+ <xsl:attribute name="uof:locID">t0065</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:background-color">
+ <xsl:element name="字:填充">
+ <xsl:attribute name="uof:locID">t0066</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test=".//@fo:margin-top or .//@fo:margin-bottom">
+ <字:段间距 uof:locID="t0058">
+ <xsl:if test=".//@fo:margin-top">
+ <字:段前距 uof:locID="t0196">
+ <字:绝对值 uof:locID="t0199" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(.//@fo:margin-top,$uofUnit)"/></xsl:attribute>
+ </字:绝对值>
+ </字:段前距>
+ </xsl:if>
+ <xsl:if test=".//@fo:margin-bottom">
+ <字:段后距 uof:locID="t0196">
+ <字:绝对值 uof:locID="t0202" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(.//@fo:margin-bottom,$uofUnit)"/></xsl:attribute>
+ </字:绝对值>
+ </字:段后距>
+ </xsl:if>
+ </字:段间距>
+ </xsl:if>
+ <xsl:if test=".//style:tab-stops">
+ <xsl:element name="字:制表位设置">
+ <xsl:attribute name="uof:locID">t0067</xsl:attribute>
+ <xsl:for-each select=".//style:tab-stops/style:tab-stop">
+ <xsl:element name="字:制表位">
+ <xsl:attribute name="uof:locID">t0068</xsl:attribute>
+ <xsl:attribute name="uof:attrList">位置 类型 前导符</xsl:attribute>
+ <xsl:attribute name="字:位置"><xsl:value-of select="@style:position"/></xsl:attribute>
+ <xsl:variable name="aa">
+ <xsl:value-of select="@style:type"/>
+ </xsl:variable>
+ <xsl:variable name="zbflx">
+ <xsl:choose>
+ <xsl:when test="$aa='right'">right</xsl:when>
+ <xsl:when test="$aa='center'">center</xsl:when>
+ <xsl:when test="$aa='char'and @style:char!=''">decimal</xsl:when>
+ <xsl:otherwise>left</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="字:类型"><xsl:value-of select="$zbflx"/></xsl:attribute>
+ <xsl:if test="$zbflx='decimal'">
+ <xsl:attribute name="字:制表位字符"><xsl:value-of select="@style:char"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@style:leader-char">
+ <xsl:attribute name="字:前导符"><xsl:value-of select="@style:leader-char"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="textspan">
+ <字:句 uof:locID="t0085">
+ <xsl:choose>
+ <xsl:when test="./text:footnote">
+ <xsl:call-template name="jiaozhu"/>
+ </xsl:when>
+ <xsl:when test="./text:endnote">
+ <xsl:call-template name="weizhu"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:variable name="textstyle">
+ <xsl:value-of select="@text:style-name"/>
+ </xsl:variable>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ <xsl:for-each select="/office:document/office:automatic-styles//style:style[@style:family='text']">
+ <xsl:if test="@style:name=$textstyle and not(@style:parent-style-name='Standard')">
+ <xsl:if test="@style:parent-style-name=/office:document/office:styles/style:style/@style:name">
+ <xsl:call-template name="SentenceXD">
+ <xsl:with-param name="Sentencestyle" select="@style:parent-style-name"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="/office:document/office:styles//style:style[@style:family='text']">
+ <xsl:if test="@style:name=$textstyle">
+ <xsl:call-template name="SentenceXD">
+ <xsl:with-param name="Sentencestyle" select="@style:name"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:句>
+ </xsl:template>
+ <xsl:template name="SentenceXD">
+ <xsl:param name="Sentencestyle"/>
+ <xsl:element name="字:格式修订">
+ <xsl:attribute name="uof:locID">t0087</xsl:attribute>
+ <xsl:attribute name="uof:attrList">修订信息引用</xsl:attribute>
+ <xsl:attribute name="字:修订信息引用"><xsl:value-of select="$Sentencestyle"/></xsl:attribute>
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="$Sentencestyle"/></xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="add-space">
+ <xsl:param name="number"/>
+ <xsl:if test="$number &gt; 1">
+ <xsl:call-template name="add-space">
+ <xsl:with-param name="number" select="$number - 1"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="office:styles | office:automatic-styles" mode="style">
+ <xsl:for-each select="style:style[@style:family= 'paragraph' or @style:family= 'text']">
+ <xsl:choose>
+ <xsl:when test="@style:family = 'text'">
+ <xsl:call-template name="句式样"/>
+ </xsl:when>
+ <xsl:when test="@style:family = 'paragraph'">
+ <xsl:call-template name="段落式样"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="段落式样">
+ <xsl:element name="uof:段落式样">
+ <xsl:attribute name="uof:locID">u0044</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用</xsl:attribute>
+ <xsl:variable name="count"><xsl:value-of select="count(preceding::style:style)"/></xsl:variable>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="concat(@style:name,$count)"/></xsl:attribute>
+ <xsl:attribute name="字:类型">default</xsl:attribute>
+ <xsl:attribute name="字:基式样引用"><xsl:variable name="stylename" select="@style:name"/><xsl:variable name="frame-parent"><xsl:choose><xsl:when test="/office:document/office:master-styles/style:master-page/draw:frame[draw:text-box//text:p/@text:style-name = $stylename]"><xsl:for-each select="/office:document/office:master-styles/style:master-page/draw:frame[draw:text-box//text:p/@text:style-name = $stylename][1]"><xsl:variable name="frame-style" select="@presentation:style-name"/><xsl:value-of select="/office:document/*/style:style[@style:name=$frame-style]/@style:parent-style-name"/></xsl:for-each></xsl:when><xsl:otherwise>not-master</xsl:otherwise></xsl:choose></xsl:variable><xsl:choose><xsl:when test="@style:parent-style-name"><xsl:value-of select="@style:parent-style-name"/></xsl:when><xsl:when test="not($frame-parent='not-master')"><xsl:value-of select="$frame-parent"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:apply-templates select="style:paragraph-properties"/>
+ <xsl:for-each select="style:text-properties">
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="style:paragraph-properties">
+ <xsl:element name="字:缩进">
+ <xsl:attribute name="uof:locID">t0056</xsl:attribute>
+ <xsl:call-template name="字:缩进类型"/>
+ </xsl:element>
+ <xsl:if test="@fo:text-align | @fotext-align-last">
+ <xsl:element name="字:对齐">
+ <xsl:attribute name="uof:locID">t0055</xsl:attribute>
+ <xsl:if test="@fo:text-align">
+ <xsl:attribute name="字:水平对齐"><xsl:choose><xsl:when test=".//@fo:text-align='end'">right</xsl:when><xsl:when test=".//@fo:text-align='center'">center</xsl:when><xsl:when test=".//@fo:text-align='justify' and not(.//@fo:text-align-last='justify')">justified</xsl:when><xsl:when test=".//@fo:text-align='justify' and .//@fo:text-align-last='justify'">distributed</xsl:when><xsl:otherwise>left</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@style:vertical-align">
+ <xsl:attribute name="字:文字对齐"><xsl:choose><xsl:when test=".//@style:vertical-align='baseline'">base</xsl:when><xsl:when test=".//@style:vertical-align='top'">top</xsl:when><xsl:when test=".//@style:vertical-align='middle'">center</xsl:when><xsl:when test=".//@style:vertical-align='bottom'">bottom</xsl:when><xsl:otherwise>auto</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="uof:attrList">水平对齐 文字对齐</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="句式样">
+ <xsl:element name="uof:句式样">
+ <xsl:attribute name="uof:locID">u0043</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">auto</xsl:attribute>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="style:text-properties">
+ <xsl:element name="字:字体">
+ <xsl:attribute name="uof:locID">t0088</xsl:attribute>
+ <xsl:attribute name="uof:attrList">西文字体引用 中文字体引用 特殊字体引用 西文绘制 字号 相对字号 颜色</xsl:attribute>
+ <xsl:if test=".//@fo:font-size or .//@style:font-size-asian or .//@style:font-size-complex">
+ <xsl:choose>
+ <xsl:when test="contains(.//@fo:font-size,'%') or contains(.//@style:font-size-asian,'%')">
+ <xsl:attribute name="字:相对字号"><xsl:choose><xsl:when test=".//@fo:font-size"><xsl:value-of select="substring-before(.//@fo:font-size,'%')"/></xsl:when><xsl:when test=".//@style:font-size-asian"><xsl:value-of select="substring-before(.//@style:font-size-asian,'%')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:字号"><xsl:choose><xsl:when test=".//@fo:font-size"><xsl:value-of select="substring-before(.//@fo:font-size,'pt')"/></xsl:when><xsl:when test=".//@style:font-size-asian"><xsl:value-of select="substring-before(.//@style:font-size-asian,'pt')"/></xsl:when><xsl:when test=".//@style:font-size-complex"><xsl:value-of select="substring-before(.//@style:font-size-complex,'pt')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test=".//@style:font-name">
+ <xsl:attribute name="字:西文字体引用"><xsl:value-of select=".//@style:font-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//@style:font-name-asian">
+ <xsl:attribute name="字:中文字体引用"><xsl:value-of select=".//@style:font-name-asian"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select=".//@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="(@fo:font-weight='bold') or (@fo:font-weight-asian='bold') or (@style:font-weight-asian='bold') or (@style:font-weight-complex='bold')">
+ <xsl:element name="字:粗体">
+ <xsl:attribute name="字:值">1</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0089</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="(@style:font-style-asian='italic') or (@style:font-style-complex='italic') or (@fo:font-style-asian='italic') or (@fo:font-style='italic')">
+ <xsl:element name="字:斜体">
+ <xsl:attribute name="字:值">1</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0090</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="style:page-layout">
+ <xsl:element name="演:页面设置">
+ <xsl:attribute name="uof:locID">p0002</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称</xsl:attribute>
+ <xsl:attribute name="演:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="演:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="演:名称">页面设置</xsl:attribute>
+ <xsl:element name="演:纸张">
+ <xsl:attribute name="uof:locID">p0003</xsl:attribute>
+ <xsl:attribute name="uof:attrList">宽度 高度 纸型</xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:page-width,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:高度"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:page-height,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:纸型"><xsl:variable name="height"><xsl:value-of select="style:page-layout-properties/@fo:page-height"/></xsl:variable><xsl:variable name="width"><xsl:value-of select="style:page-layout-properties/@fo:page-width"/></xsl:variable><xsl:choose><xsl:when test="$height='29.7cm' and $width='42cm'">A3</xsl:when><xsl:when test="$height='21cm' and $width='29.7cm'">A4</xsl:when><xsl:when test="$height='14.8cm' and $width='21cm'">A5</xsl:when><xsl:when test="$height='25cm' and $width='35.3cm'">B4</xsl:when><xsl:when test="$height='17.6cm' and $width='25cm'">B5</xsl:when><xsl:when test="$height='12.5cm' and $width='17.6cm'">B6</xsl:when><xsl:otherwise>使用者</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="演:页边距">
+ <xsl:attribute name="uof:locID">p0004</xsl:attribute>
+ <xsl:attribute name="uof:attrList">左 上 右 下</xsl:attribute>
+ <xsl:attribute name="uof:左"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:margin-left,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:上"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:margin-top,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:右"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:margin-right,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:下"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:margin-bottom,$uofUnit)"/></xsl:attribute>
+ </xsl:element>
+ <xsl:variable name="PageNumberFormat">
+ <xsl:value-of select="/office:document/office:settings/config:config-item-set/config:config-item[@config:name='PageNumberFormat']"/>
+ </xsl:variable>
+ <xsl:if test="not($PageNumberFormat='5')">
+ <xsl:element name="演:页码格式">
+ <xsl:attribute name="uof:locID">p0005</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$PageNumberFormat='0'">upper-letter</xsl:when>
+ <xsl:when test="$PageNumberFormat='1'">lower-letter</xsl:when>
+ <xsl:when test="$PageNumberFormat='2'">upper-roman</xsl:when>
+ <xsl:when test="$PageNumberFormat='3'">lower-letter</xsl:when>
+ <xsl:when test="$PageNumberFormat='4'">decimal</xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="演:纸张方向">
+ <xsl:attribute name="uof:locID">p0006</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="style:page-layout-properties/@style:print-orientation">
+ <xsl:value-of select="style:page-layout-properties/@style:print-orientation"/>
+ </xsl:when>
+ <xsl:otherwise>portrait</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="obtain_anim_type">
+ <xsl:param name="flytype"/>
+ <xsl:variable name="flytypestr" select="substring-after($flytype,'from-')"/>
+ <xsl:choose>
+ <xsl:when test="contains($flytypestr,'-')">
+ <xsl:value-of select="concat(substring-before($flytypestr,'-'),substring-after($flytypestr,'-'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$flytypestr"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="cm2pt">
+ <xsl:param name="cmval"/>
+ <xsl:value-of select="substring-before($cmval,$uofUnit)* $cm-to-other "/>
+ </xsl:template>
+ <xsl:template match="office:font-face-decls">
+ <uof:字体集 uof:locID="u0040">
+ <uof:默认字体 uof:ascii="Times New Roman" uof:fareast="宋体" uof:h-ansi="宋体" uof:cs="宋体"/>
+ <xsl:for-each select="style:font-face">
+ <xsl:element name="uof:字体声明">
+ <xsl:attribute name="uof:attrList">标识符 名称 字体族</xsl:attribute>
+ <xsl:attribute name="uof:locID">u0041</xsl:attribute>
+ <xsl:attribute name="uof:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="uof:字体族"><xsl:value-of select="@svg:font-family"/></xsl:attribute>
+ <xsl:if test="@style:font-charset= '02'">
+ <xsl:attribute name="uof:字符集">x-symbol</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@style:font-family-generic">
+ <xsl:choose>
+ <xsl:when test="@style:font-family-generic = 'swiss'">
+ <xsl:attribute name="uof:字体族">Swiss</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='modern'">
+ <xsl:attribute name="uof:字符集">Modern</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic='roman'">
+ <xsl:attribute name="uof:字符集">Roman</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='script'">
+ <xsl:attribute name="uof:字符集">Script</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='decorative'">
+ <xsl:attribute name="uof:字符集">Decorative</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='system'">
+ <xsl:attribute name="uof:字符集">System</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="uof:字符集">System</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:apply-templates select="style:font-decl"/>
+ </uof:字体集>
+ </xsl:template>
+ <xsl:template match="office:meta">
+ <uof:元数据 uof:locID="u0001">
+ <uof:标题 uof:locID="u0002">
+ <xsl:value-of select="dc:title"/>
+ </uof:标题>
+ <uof:创建应用程序 uof:locID="u0011">
+ <xsl:value-of select="meta:generator"/>
+ </uof:创建应用程序>
+ <uof:摘要 uof:locID="u0007">
+ <xsl:value-of select="dc:description"/>
+ </uof:摘要>
+ <uof:主题 uof:locID="u0003">
+ <xsl:value-of select="dc:subject"/>
+ </uof:主题>
+ <uof:创建者 uof:locID="u0004"/>
+ <uof:作者 uof:locID="u0005">
+ <xsl:value-of select="meta:initial-creator"/>
+ </uof:作者>
+ <uof:创建日期 uof:locID="u0008">
+ <xsl:value-of select="meta:creation-date"/>
+ </uof:创建日期>
+ <uof:最后作者 uof:locID="u0006">
+ <xsl:value-of select="dc:creator"/>
+ </uof:最后作者>
+ <uof:关键字集 uof:locID="u0014">
+ <xsl:for-each select=".">
+ <uof:关键字 uof:locID="u0015">
+ <xsl:value-of select="meta:keywords/@meta:keyword"/>
+ </uof:关键字>
+ </xsl:for-each>
+ </uof:关键字集>
+ <uof:编辑次数 uof:locID="u0009">
+ <xsl:value-of select="meta:editing-cycles"/>
+ </uof:编辑次数>
+ <xsl:if test="meta:editing-duration">
+ <uof:编辑时间 uof:locID="u0010">
+ <xsl:value-of select="meta:editing-duration"/>
+ </uof:编辑时间>
+ </xsl:if>
+ <xsl:if test="meta:template/@xlink:href">
+ <uof:文档模板 uof:locID="u0013">
+ <xsl:value-of select="meta:template/@xlink:href"/>
+ </uof:文档模板>
+ </xsl:if>
+ <xsl:if test="meta:user-defined/@meta:name">
+ <uof:用户自定义元数据集 uof:locID="u0016">
+ <xsl:for-each select="meta:user-defined">
+ <uof:用户自定义元数据 uof:locID="u0017" uof:attrList="名称 类型">
+ <xsl:attribute name="uof:名称"><xsl:value-of select="@meta:name"/></xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:value-of select="'string'"/></xsl:attribute>
+ </uof:用户自定义元数据>
+ </xsl:for-each>
+ </uof:用户自定义元数据集>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:page-count">
+ <uof:页数 uof:locID="u0020">
+ <xsl:value-of select="meta:document-statistic/@meta:page-count"/>
+ </uof:页数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:paragraph-count">
+ <uof:段落数 uof:locID="u0025">
+ <xsl:value-of select="meta:document-statistic/@meta:paragraph-count"/>
+ </uof:段落数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:object-count">
+ <uof:对象数 uof:locID="u0026">
+ <xsl:value-of select="meta:document-statistic/@meta:object-count"/>
+ </uof:对象数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:character-count">
+ <uof:字数 uof:locID="u0021">
+ <xsl:value-of select="meta:document-statistic/@meta:character-count"/>
+ </uof:字数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:word-count">
+ <uof:中文字符数 uof:locID="u0023">
+ <xsl:value-of select="meta:document-statistic/@meta:word-count"/>
+ </uof:中文字符数>
+ </xsl:if>
+ </uof:元数据>
+ </xsl:template>
+ <xsl:template name="填充">
+ <xsl:param name="picname"/>
+ <xsl:param name="nodename"/>
+ <xsl:choose>
+ <xsl:when test="@draw:fill='gradient'">
+ <xsl:variable name="gradient-name">
+ <xsl:value-of select="@draw:fill-gradient-name"/>
+ </xsl:variable>
+ <xsl:for-each select="/descendant::draw:gradient[@draw:name=$gradient-name]">
+ <图:渐变 uof:locID="g0037" uof:attrList="起始色 终止色 种子类型 起始浓度 终止浓度 渐变方向 边界 种子X位置 种子Y位置 类型">
+ <xsl:attribute name="图:起始色"><xsl:value-of select="@draw:start-color"/></xsl:attribute>
+ <xsl:attribute name="图:终止色"><xsl:value-of select="@draw:end-color"/></xsl:attribute>
+ <xsl:attribute name="图:种子类型"><xsl:choose><xsl:when test="@draw:style='linear' or @draw:style='axial'">linear</xsl:when><xsl:when test="@draw:style='radial'">radar</xsl:when><xsl:when test="@draw:style='ellipsoid'">oval</xsl:when><xsl:when test="@draw:style='square'">square</xsl:when><xsl:when test="@draw:style='rectangular'">rectangle</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:起始浓度"><xsl:value-of select="substring-before(@draw:start-intensity,'%')"/></xsl:attribute>
+ <xsl:attribute name="图:终止浓度"><xsl:value-of select="substring-before(@draw:end-intensity,'%')"/></xsl:attribute>
+ <xsl:variable name="angle">
+ <xsl:value-of select="@draw:angle div 10"/>
+ </xsl:variable>
+ <xsl:attribute name="图:渐变方向"><xsl:choose><xsl:when test="0&lt;$angle and $angle&lt;25">0</xsl:when><xsl:when test="25&lt;$angle and $angle&lt;70">45</xsl:when><xsl:when test="70&lt;$angle and $angle&lt;115">90</xsl:when><xsl:when test="115&lt;$angle and $angle&lt;160">135</xsl:when><xsl:when test="160&lt;$angle and $angle&lt;205">180</xsl:when><xsl:when test="205&lt;$angle and $angle&lt;250">225</xsl:when><xsl:when test="250&lt;$angle and $angle&lt;295">270</xsl:when><xsl:when test="295&lt;$angle and $angle&lt;340">315</xsl:when><xsl:when test="340&lt;$angle and $angle&lt;360">360</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:边界"><xsl:value-of select="substring-before(@draw:border,'%')"/></xsl:attribute>
+ <xsl:if test="@draw:cx">
+ <xsl:attribute name="图:种子X位置"><xsl:value-of select="substring-before(@draw:cx,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@draw:cy">
+ <xsl:attribute name="图:种子Y位置"><xsl:value-of select="substring-before(@draw:cy,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:类型">-2</xsl:attribute>
+ </图:渐变>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="@draw:fill='bitmap'">
+ <图:图片 uof:locID="g0035" uof:attrList="位置 图形引用 类型 名称">
+ <xsl:attribute name="图:位置"><xsl:choose><xsl:when test="not(@style:repeat)">title</xsl:when><xsl:otherwise><xsl:choose><xsl:when test="@style:repeat = 'stretch'">stretch</xsl:when><xsl:when test="@style:repeat = 'repeat'">title</xsl:when><xsl:when test="@style:repeat = 'no-repeat'">center</xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:图形引用"><xsl:value-of select="@draw:fill-image-name"/></xsl:attribute>
+ <xsl:attribute name="图:类型">png</xsl:attribute>
+ <xsl:attribute name="图:名称"><xsl:value-of select="concat($picname,'_b1')"/></xsl:attribute>
+ </图:图片>
+ </xsl:when>
+ <xsl:when test="@draw:fill='hatch'">
+ <图:图案 uof:locID="g0036" uof:attrList="类型 图形引用 前景色 背景色">
+ <xsl:attribute name="图:类型"><xsl:value-of select="/office:document/office:styles/draw:hatch/@draw:name"/></xsl:attribute>
+ <xsl:attribute name="图:图形引用"/>
+ <xsl:attribute name="图:前景色"><xsl:value-of select="/office:document/office:styles/draw:hatch/@draw:color"/></xsl:attribute>
+ <xsl:attribute name="图:背景色"><xsl:choose><xsl:when test="@draw:fill-color"><xsl:value-of select="@draw:fill-color"/></xsl:when><xsl:otherwise>#ffffff</xsl:otherwise></xsl:choose></xsl:attribute>
+ </图:图案>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:frame'">
+ <xsl:if test="@draw:fill='solid'">
+ <图:颜色 uof:locID="g0034">
+ <xsl:value-of select="@draw:fill-color"/>
+ </图:颜色>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <图:颜色 uof:locID="g0034">
+ <xsl:choose>
+ <xsl:when test="@draw:fill-color">
+ <xsl:value-of select="@draw:fill-color"/>
+ </xsl:when>
+ <xsl:otherwise>#99ccff</xsl:otherwise>
+ </xsl:choose>
+ </图:颜色>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="字:缩进类型">
+ <xsl:if test="style:list-level-properties/@text:space-before">
+ <字:左 uof:locID="t0182">
+ <字:绝对 uof:locID="t0185" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:list-level-properties/@text:space-before,$uofUnit)"/></xsl:attribute>
+ </字:绝对>
+ </字:左>
+ </xsl:if>
+ <xsl:if test="style:list-level-properties/@text:min-label-width">
+ <字:右 uof:locID="t0183">
+ <字:绝对 uof:locID="t0187" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:list-level-properties/@text:min-label-width,$uofUnit)"/></xsl:attribute>
+ </字:绝对>
+ </字:右>
+ </xsl:if>
+ <xsl:if test="style:list-level-properties/@text:min-label-distance">
+ <字:首行 uof:locID="t0184">
+ <字:绝对 uof:locID="t0189" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:list-level-properties/@text:min-label-distance,$uofUnit)"/></xsl:attribute>
+ </字:绝对>
+ </字:首行>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="uof:线型类型">
+ <xsl:param name="lineType"/>
+ <xsl:choose>
+ <xsl:when test="$lineType='single-line'">single</xsl:when>
+ <xsl:when test="$lineType='double-line'">double</xsl:when>
+ <xsl:when test="$lineType='single'">single</xsl:when>
+ <xsl:when test="$lineType='double'">double</xsl:when>
+ <xsl:when test="$lineType='dash'">dash</xsl:when>
+ <xsl:when test="$lineType='long-dash'">dash-long</xsl:when>
+ <xsl:when test="$lineType='dot-dash'">dot-dash</xsl:when>
+ <xsl:when test="$lineType='dot-dot-dash'">dot-dot-dash</xsl:when>
+ <xsl:when test="$lineType='wave'">wave</xsl:when>
+ <xsl:when test="$lineType='bold-dotted'">dotted-heavy</xsl:when>
+ <xsl:when test="$lineType='bold-dash'">dashed-heavy</xsl:when>
+ <xsl:when test="$lineType='bold-long-dash'">dash-long-heavy</xsl:when>
+ <xsl:when test="$lineType='bold-dot-dash'">dash-dot-heavy</xsl:when>
+ <xsl:when test="$lineType='bold-dot-dot-dash'">dash-dot-dot-heavy</xsl:when>
+ <xsl:when test="$lineType='bold-wave'">wavy-heavy</xsl:when>
+ <xsl:when test="$lineType='double-wave'">wavy-double</xsl:when>
+ <xsl:when test="$lineType='bold'">bold</xsl:when>
+ <xsl:when test="$lineType='small-wave'">wave</xsl:when>
+ <xsl:when test="$lineType='dotted'">dotted</xsl:when>
+ <xsl:when test="$lineType='none'">none</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/uof/odf2uof_spreadsheet.xsl b/filter/source/xslt/export/uof/odf2uof_spreadsheet.xsl
new file mode 100644
index 000000000..e8bb6fa79
--- /dev/null
+++ b/filter/source/xslt/export/uof/odf2uof_spreadsheet.xsl
@@ -0,0 +1,6245 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:图="http://schemas.uof.org/cn/2003/graph" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" office:version="1.0" exclude-result-prefixes="office style text table draw fo xlink dc meta number presentation svg chart dr3d math form script config ooo ooow oooc dom xforms smil anim">
+ <xsl:output method="xml" indent="no" encoding="UTF-8" version="1.0"/>
+ <xsl:variable name="scValueWithUnit">
+ <xsl:value-of select="/office:document/office:automatic-styles/style:style[@style:name='co1']/style:table-column-properties/@style:column-width"/>
+ </xsl:variable>
+ <xsl:variable name="uofUnit">
+ <xsl:choose>
+ <xsl:when test="contains($scValueWithUnit,'in')">inch</xsl:when>
+ <xsl:when test="contains($scValueWithUnit,'cm')">cm</xsl:when>
+ <xsl:when test="contains($scValueWithUnit,'mm')">mm</xsl:when>
+ <xsl:when test="contains($scValueWithUnit,'pt')">pt</xsl:when>
+ <xsl:otherwise>inch</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="ooUnit">
+ <xsl:choose>
+ <xsl:when test="contains($scValueWithUnit,'inch')">inch</xsl:when>
+ <xsl:when test="contains($scValueWithUnit,'cm')">cm</xsl:when>
+ <xsl:when test="contains($scValueWithUnit,'mm')">mm</xsl:when>
+ <xsl:when test="contains($scValueWithUnit,'pt')">pt</xsl:when>
+ <xsl:otherwise>inch</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:template match="office:document">
+ <uof:UOF xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:图="http://schemas.uof.org/cn/2003/graph" uof:language="cn" uof:locID="u0000" uof:version="1.0" uof:mimetype="vnd.uof.spreadsheet">
+ <xsl:apply-templates select="/office:document/office:meta"/>
+ <uof:对象集 uof:locID="u0033">
+ <xsl:if test="/office:document/office:body/office:spreadsheet/table:table//table:table-cell/office:annotation">
+ <xsl:for-each select="/office:document/office:body/office:spreadsheet/table:table//table:table-cell/office:annotation">
+ <xsl:variable name="num">
+ <xsl:value-of select="substring-after(@draw:style-name,'gr')"/>
+ </xsl:variable>
+ <图:图形 uof:locID="g0000" uof:attrList="层次 标识符 组合列表 其他对象">
+ <xsl:attribute name="图:标识符"><xsl:value-of select="concat('pz',$num)"/></xsl:attribute>
+ <xsl:variable name="name" select="@draw:style-name"/>
+ <图:预定义图形 uof:locID="g0005">
+ <图:属性 uof:locID="g0011">
+ <xsl:for-each select="/office:document/office:automatic-styles/style:style[@style:name=$name]">
+ <xsl:call-template name="graphicattr"/>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="@svg:x1">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:x2,$uofUnit) - substring-before(@svg:x1,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:y2,$uofUnit) - substring-before(@svg:y1,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="@svg:x">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="@svg:width">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ </xsl:choose>
+ <图:旋转角度 uof:locID="g0025">
+ <xsl:choose>
+ <xsl:when test="@draw:transform">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="@draw:transform"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-temp">
+ <xsl:value-of select="substring-before(substring-after($rotate-angle,'rotate ('),')')"/>
+ </xsl:variable>
+ <xsl:value-of select="($rotate-temp * 360) div (2 * 3.14159265)"/>
+ </xsl:when>
+ <xsl:otherwise>0.0</xsl:otherwise>
+ </xsl:choose>
+ </图:旋转角度>
+ <图:X-缩放比例 uof:locID="g0026">1</图:X-缩放比例>
+ <图:Y-缩放比例 uof:locID="g0027">1</图:Y-缩放比例>
+ <图:锁定纵横比 uof:locID="g0028">0</图:锁定纵横比>
+ <图:相对原始比例 uof:locID="g0029">1</图:相对原始比例>
+ <图:打印对象 uof:locID="g0032">true</图:打印对象>
+ <图:Web文字 uof:locID="g0033"/>
+ </图:属性>
+ </图:预定义图形>
+ <图:文本内容 uof:locID="g0002" uof:attrList="文本框 左边距 右边距 上边距 下边距 水平对齐 垂直对齐 文字排列方向 自动换行 大小适应文字 前一链接 后一链接">
+ <xsl:for-each select="/office:document/office:automatic-styles/style:style[@style:name=$name]">
+ <xsl:attribute name="图:文字排列方向"><xsl:choose><xsl:when test="style:paragraph-properties/@style:writing-mode"><xsl:choose><xsl:when test="style:paragraph-properties/@style:writing-mode='tb-rl'">vert-r2l</xsl:when><xsl:when test="style:paragraph-properties/@style:writing-mode='tb-lr'">vert-l2r</xsl:when></xsl:choose></xsl:when><xsl:when test="style:graphic-properties/@draw:textarea-horizontal-align='right'">hori-r2l</xsl:when><xsl:otherwise>hori-l2r</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="style:graphic-properties/@draw:textarea-horizontal-align">
+ <xsl:attribute name="图:水平对齐"><xsl:value-of select="style:graphic-properties/@draw:textarea-horizontal-align"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:textarea-vertical-align">
+ <xsl:attribute name="图:垂直对齐"><xsl:value-of select="style:graphic-properties/@draw:textarea-vertical-align"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@fo:wrap-option">
+ <xsl:attribute name="图:自动换行">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:auto-grow-width='true' and style:graphic-properties/@draw:auto-grow-height='true'">
+ <xsl:attribute name="图:大小适应文字">true</xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="./text:p">
+ <xsl:call-template name="textp"/>
+ </xsl:for-each>
+ </图:文本内容>
+ </图:图形>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:for-each select="/office:document/office:body/office:spreadsheet/table:table//table:table-cell/office:annotation">
+ <xsl:variable name="name1" select="@draw:style-name"/>
+ <xsl:for-each select="/office:document/office:automatic-styles/style:style[@style:name=$name1]">
+ <xsl:if test="style:graphic-properties/@draw:fill-image-name">
+ <xsl:variable name="bsh">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-image-name"/>
+ </xsl:variable>
+ <xsl:for-each select="/office:document/office:styles/draw:fill-image">
+ <xsl:if test="@draw:name=$bsh">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat($name1,'_b1')"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="office:binary-data"/>
+ </uof:数据>
+ </uof:其他对象>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ <xsl:for-each select="/office:document/office:body/office:spreadsheet/table:table/table:shapes/child::* | /office:document/office:body/office:spreadsheet/table:table/table:table-row/table:table-cell/child::*">
+ <xsl:if test="starts-with(name(.),'draw:')">
+ <xsl:choose>
+ <xsl:when test="name(.)='draw:frame' and self::node()/draw:object">
+ <xsl:for-each select="draw:image">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat('chart_image_',count(preceding::draw:fill-image))"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="office:binary-data"/>
+ </uof:数据>
+ </uof:其他对象>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="draw">
+ <xsl:with-param name="nodename1" select="name(.)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ </uof:对象集>
+ <xsl:if test="/office:document/office:body//text:bookmark-start">
+ <uof:书签集 uof:locID="u0027">
+ <xsl:for-each select="/office:document/office:body//text:bookmark-start">
+ <xsl:element name="uof:书签">
+ <xsl:attribute name="uof:名称"><xsl:value-of select="@text:name"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">u0028</xsl:attribute>
+ <xsl:attribute name="uof:attrList">名称</xsl:attribute>
+ <xsl:element name="uof:文本位置">
+ <xsl:attribute name="字:区域引用"><xsl:value-of select="concat('bk_',@text:name)"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">u0029</xsl:attribute>
+ <xsl:attribute name="uof:attrList">区域引用</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </uof:书签集>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/text:p/text:a">
+ <uof:链接集 uof:locID="u0031">
+ <xsl:for-each select="/office:document/office:body/text:p/text:a">
+ <!--chengxz 要改-->
+ <xsl:variable name="hyperStr" select="@xlink:href"/>
+ <xsl:element name="uof:超级链接">
+ <xsl:if test="contains($hyperStr,'#')">
+ <xsl:attribute name="uof:书签"><xsl:value-of select="substring-after($hyperStr,'#')"/></xsl:attribute>
+ </xsl:if>
+ <!--暂时不写uof:提示-->
+ <xsl:attribute name="uof:链源">hlnk<xsl:number from="/office:document/office:body" level="any" count="text:p[text:a]"/></xsl:attribute>
+ <xsl:if test="contains($hyperStr,'http://') or contains($hyperStr,'mailto')">
+ <xsl:attribute name="uof:目标"><xsl:value-of select="$hyperStr"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="uof:locID">u0032</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 目标 书签 式样引用 已访问式样引用 提示 链源</xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </uof:链接集>
+ </xsl:if>
+ <uof:式样集 uof:locID="u0039">
+ <xsl:apply-templates select="/office:document/office:font-face-decls"/>
+ <xsl:apply-templates select="/office:document/office:styles/style:style" mode="styles"/>
+ <xsl:apply-templates select="/office:document/office:automatic-styles/style:style" mode="styles">
+ <xsl:with-param name="isAutomatic" select="true()"/>
+ </xsl:apply-templates>
+ </uof:式样集>
+ <uof:电子表格 uof:locID="u0049">
+ <表:公用处理规则 uof:locID="s0000">
+ <表:度量单位 uof:locID="s0001">
+ <xsl:value-of select="$uofUnit"/>
+ </表:度量单位>
+ <xsl:apply-templates select="/office:document/office:body/office:spreadsheet/table:calculation-settings" mode="common"/>
+ <xsl:apply-templates select="/office:document/office:body/office:spreadsheet/table:content-validations" mode="common"/>
+ <xsl:if test="/office:document/office:automatic-styles/style:style[@style:family='table-cell' and style:map]">
+ <xsl:element name="表:条件格式化集">
+ <xsl:attribute name="uof:locID">s0016</xsl:attribute>
+ <xsl:call-template name="create-condition-format"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:spreadsheet/table:database-ranges/table:database-range">
+ <表:区域公式集 uof:locID="s0122">
+ <表:区域公式 uof:locID="s0123" uof:attrList="类型">
+ <xsl:attribute name="表:类型">table</xsl:attribute>
+ <xsl:for-each select="/office:document/office:body/office:spreadsheet/table:database-ranges/table:database-range">
+ <表:区域 uof:locID="s0007">
+ <xsl:value-of select="@table:target-range-address"/>
+ </表:区域>
+ <表:公式 uof:locID="s0125"/>
+ </xsl:for-each>
+ </表:区域公式>
+ </表:区域公式集>
+ </xsl:if>
+ <表:是否RC引用 uof:locID="s0124" uof:attrList="值" 表:值="false"/>
+ </表:公用处理规则>
+ <表:主体 uof:locID="s0024">
+ <xsl:apply-templates select="office:body"/>
+ </表:主体>
+ </uof:电子表格>
+ </uof:UOF>
+ </xsl:template>
+ <xsl:template match="office:body">
+ <xsl:apply-templates select="office:spreadsheet"/>
+ </xsl:template>
+ <xsl:template match="office:spreadsheet">
+ <xsl:apply-templates select="./*"/>
+ </xsl:template>
+ <xsl:template match="office:meta">
+ <uof:元数据 uof:locID="u0001">
+ <uof:标题 uof:locID="u0002">
+ <xsl:value-of select="dc:title"/>
+ </uof:标题>
+ <uof:创建应用程序 uof:locID="u0011">
+ <xsl:value-of select="meta:generator"/>
+ </uof:创建应用程序>
+ <uof:摘要 uof:locID="u0007">
+ <xsl:value-of select="dc:description"/>
+ </uof:摘要>
+ <uof:主题 uof:locID="u0003">
+ <xsl:value-of select="dc:subject"/>
+ </uof:主题>
+ <uof:创建者 uof:locID="u0004"/>
+ <uof:作者 uof:locID="u0005">
+ <xsl:value-of select="meta:initial-creator"/>
+ </uof:作者>
+ <uof:创建日期 uof:locID="u0008">
+ <xsl:value-of select="meta:creation-date"/>
+ </uof:创建日期>
+ <xsl:if test="dc:creator">
+ <uof:最后作者 uof:locID="u0006">
+ <xsl:value-of select="dc:creator"/>
+ </uof:最后作者>
+ </xsl:if>
+ <uof:关键字集 uof:locID="u0014">
+ <uof:关键字 uof:locID="u0015">
+ <xsl:value-of select="meta:keyword"/>
+ </uof:关键字>
+ </uof:关键字集>
+ <uof:编辑次数 uof:locID="u0009">
+ <xsl:value-of select="meta:editing-cycles"/>
+ </uof:编辑次数>
+ <xsl:if test="meta:editing-duration">
+ <uof:编辑时间 uof:locID="u0010">
+ <xsl:value-of select="meta:editing-duration"/>
+ </uof:编辑时间>
+ </xsl:if>
+ <xsl:if test="meta:template/@xlink:href">
+ <uof:文档模板 uof:locID="u0013">
+ <xsl:value-of select="meta:template/@xlink:href"/>
+ </uof:文档模板>
+ </xsl:if>
+ <xsl:if test="meta:user-defined/@meta:name">
+ <uof:用户自定义元数据集 uof:locID="u0016">
+ <xsl:for-each select="meta:user-defined">
+ <uof:用户自定义元数据 uof:locID="u0017" uof:attrList="名称 类型">
+ <xsl:attribute name="uof:名称"><xsl:value-of select="@meta:name"/></xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:value-of select="'string'"/></xsl:attribute>
+ <xsl:value-of select="."/>
+ </uof:用户自定义元数据>
+ </xsl:for-each>
+ </uof:用户自定义元数据集>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:page-count">
+ <uof:页数 uof:locID="u0020">
+ <xsl:value-of select="meta:document-statistic/@meta:page-count"/>
+ </uof:页数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:paragraph-count">
+ <uof:段落数 uof:locID="u0025">
+ <xsl:value-of select="meta:document-statistic/@meta:paragraph-count"/>
+ </uof:段落数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:object-count">
+ <uof:对象数 uof:locID="u0026">
+ <xsl:value-of select="meta:document-statistic/@meta:object-count"/>
+ </uof:对象数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:character-count">
+ <uof:字数 uof:locID="u0021">
+ <xsl:value-of select="meta:document-statistic/@meta:character-count"/>
+ </uof:字数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:word-count">
+ <uof:中文字符数 uof:locID="u0023">
+ <xsl:value-of select="meta:document-statistic/@meta:word-count"/>
+ </uof:中文字符数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:character-count - meta:document-statistic/@meta:word-count">
+ <uof:英文字符数 uof:locID="u0022">
+ <xsl:value-of select="meta:document-statistic/@meta:character-count - meta:document-statistic/@meta:word-count"/>
+ </uof:英文字符数>
+ </xsl:if>
+ <xsl:if test="meta:document-statistic/@meta:character-count">
+ <uof:行数 uof:locID="u0024">
+ <xsl:variable name="quzhi">
+ <xsl:value-of select="(meta:document-statistic/@meta:character-count div 39) + 0.9"/>
+ </xsl:variable>
+ <xsl:value-of select="substring-before($quzhi,'.')"/>
+ </uof:行数>
+ </xsl:if>
+ <xsl:if test="meta:user-defined[@meta:name='Category']">
+ <uof:分类 uof:locID="u0012">
+ <xsl:value-of select="meta:user-defined[@meta:name='Category']"/>
+ </uof:分类>
+ </xsl:if>
+ <xsl:if test="meta:user-defined[@meta:name='Manager']">
+ <uof:经理名称 uof:locID="u0019">
+ <xsl:value-of select="meta:user-defined[meta:name='Manager']"/>
+ </uof:经理名称>
+ </xsl:if>
+ <xsl:if test="meta:user-defined[@meta:name='Company']">
+ <uof:公司名称 uof:locID="u0018">
+ <xsl:value-of select="meta:user-defined[meta:name='Company']"/>
+ </uof:公司名称>
+ </xsl:if>
+ </uof:元数据>
+ </xsl:template>
+ <xsl:template match="table:table">
+ <xsl:element name="表:工作表">
+ <xsl:attribute name="uof:locID">s0025</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 隐藏 背景 式样引用</xsl:attribute>
+ <xsl:attribute name="表:标识符"><xsl:value-of select="@table:name"/></xsl:attribute>
+ <xsl:attribute name="表:名称"><xsl:value-of select="@table:name"/></xsl:attribute>
+ <xsl:attribute name="表:隐藏"><xsl:choose><xsl:when test="@table:style-name='ta1'"><xsl:value-of select="'false'"/></xsl:when><xsl:otherwise><xsl:value-of select="'true'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:背景"><xsl:choose><xsl:when test="/office:document/office:automatic-styles/style:page-master/style:table-properties/@fo:background-color"><xsl:value-of select="/office:document/office:automatic-styles/style:page-master/style:table-properties/@fo:background-color"/></xsl:when><xsl:otherwise>#ffffff</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:式样引用"><xsl:value-of select="@table:style-name"/></xsl:attribute>
+ <xsl:element name="表:工作表属性">
+ <xsl:attribute name="uof:locID">s0026</xsl:attribute>
+ <表:标签前景色 uof:locID="s0027">#000000</表:标签前景色>
+ <表:标签背景色 uof:locID="s0028">#ffffff</表:标签背景色>
+ <xsl:call-template name="create-page-setting">
+ <xsl:with-param name="master-page" select="/*/office:master-styles/style:master-page"/>
+ <xsl:with-param name="page-master-style" select="/*/office:automatic-styles/style:page-layout/style:page-layout-properties"/>
+ </xsl:call-template>
+ <xsl:call-template name="create-view">
+ <xsl:with-param name="table-name" select="/*/office:body/office:spreadsheet/table:table/@table:name"/>
+ <xsl:with-param name="view-id" select="count(preceding-sibling::table:table) + 1"/>
+ <xsl:with-param name="aaa" select="/*/office:settings/config:config-item-set/config:config-item-map-indexed/config:config-item-map-entry"/>
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:call-template name="table"/>
+ <xsl:variable name="filter" select="/*/office:body/office:spreadsheet/table:database-ranges/table:database-range"/>
+ <xsl:if test="$filter">
+ <xsl:variable name="target-range-address" select="//table:database-range[table:filter]/@table:target-range-address"/>
+ <xsl:element name="表:筛选">
+ <xsl:attribute name="uof:locID">s0101</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="表:类型"><xsl:choose><xsl:when test="$filter/@table:display-filter-buttons">auto</xsl:when><xsl:otherwise>advance</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:element name="表:范围">
+ <xsl:attribute name="uof:locID">s0102</xsl:attribute>
+ <xsl:value-of select="$filter/@table:target-range-address"/>
+ </xsl:element>
+ <xsl:variable name="column-and-row" select="substring-before(substring-after($target-range-address,'.'),':')"/>
+ <xsl:variable name="dd" select="number(substring($column-and-row,2,1))"/>
+ <xsl:variable name="zone-left-column-string">
+ <xsl:choose>
+ <xsl:when test="contains($dd,'NaN') ">
+ <xsl:value-of select="substring($column-and-row,1,2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring($column-and-row,1,1)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="zone-left-column-num">
+ <xsl:call-template name="translate-column-char-to-number">
+ <xsl:with-param name="string" select="$zone-left-column-string"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="create-filter-conditions">
+ <xsl:with-param name="filter-condition-set" select="$filter//table:filter-condition"/>
+ <xsl:with-param name="zone-left-column-num" select="$zone-left-column-num"/>
+ </xsl:call-template>
+ <xsl:if test="$filter/@table:condition-source-range-address">
+ <xsl:element name="表:条件区域">
+ <xsl:attribute name="uof:locID">s0108</xsl:attribute>
+ <xsl:value-of select="$filter/@table:condition-source-range-address"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$filter/@table:display-duplicates">
+ <xsl:element name="表:结果区域">
+ <xsl:attribute name="uof:locID">s0109</xsl:attribute>
+ <xsl:value-of select="$filter/@table:display-duplicates"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="key('styles', .//@table:style-name)/style:table-row-properties/@fo:break-before = 'page' or key('styles',.//@table:style-name)/style:table-column-properties/@fo:break-before='page'">
+ <xsl:element name="表:分页符集">
+ <xsl:attribute name="uof:locID">s0111</xsl:attribute>
+ <xsl:call-template name="分页符集"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:param name="tableElement" select="'表:工作表内容'"/>
+ <xsl:param name="rowElement" select="'表:行'"/>
+ <!--xsl:param name="cellElement" select="'表:单元格'" /-->
+ <!-- ************** -->
+ <!-- *** Table *** -->
+ <!-- ************** -->
+ <xsl:template name="table">
+ <!-- The table will only be created if the table:scenario is active -->
+ <xsl:if test="not(table:scenario) or table:scenario/@table:is-active">
+ <xsl:call-template name="create-table"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-table">
+ <!-- collecting all visible "table:table-row" elements of the table -->
+ <xsl:variable name="allVisibleTableRows" select="table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')] | table:table-header-rows/descendant::table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')] | table:table-row-group/descendant::table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')]"/>
+ <xsl:call-template name="create-table-element">
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="create-table-element">
+ <xsl:param name="allVisibleTableRows"/>
+ <xsl:element name="表:工作表内容">
+ <xsl:attribute name="uof:locID">s0018</xsl:attribute>
+ <xsl:attribute name="uof:attrList">最大行 最大列 缺省行高 缺省列宽</xsl:attribute>
+ <xsl:variable name="group-column" select="./table:table-column-group"/>
+ <xsl:variable name="group-row" select="./table:table-row-group"/>
+ <xsl:apply-templates select="@table:style-name"/>
+ <xsl:for-each select="table:table-column">
+ <表:列 uof:locID="s0048" uof:attrList="列号 隐藏 列宽 式样引用 跨度">
+ <xsl:attribute name="表:列号"><xsl:value-of select="position()"/></xsl:attribute>
+ <xsl:if test="@table:visibility">
+ <xsl:attribute name="表:隐藏"><xsl:choose><xsl:when test="@table:visibility='collapse'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="表:列宽"><xsl:value-of select="substring-before(key('styles',@table:style-name)/style:table-column-properties/@style:column-width,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="表:式样引用"><xsl:value-of select="@table:style-name"/></xsl:attribute>
+ <xsl:attribute name="表:跨度"><xsl:choose><xsl:when test="@table:number-columns-repeated"><xsl:value-of select="@table:number-columns-repeated"/></xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:attribute>
+ </表:列>
+ </xsl:for-each>
+ <xsl:variable name="columnNodes" select="table:table-column"/>
+ <xsl:variable name="columnsRepeated" select="table:table-column/@table:number-columns-repeated"/>
+ <xsl:variable name="columnCount">
+ <xsl:choose>
+ <xsl:when test="$columnNodes[last()]/@table:number-columns-repeated &gt; 99">
+ <xsl:value-of select="count($columnNodes)+ number(sum($columnsRepeated))- count($columnsRepeated)- $columnNodes[last()]/@table:number-columns-repeated+ 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="count($columnNodes)+ number(sum($columnsRepeated))- count($columnsRepeated)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="table-name" select="@table:name"/>
+ <xsl:apply-templates select="table:table-row">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ </xsl:apply-templates>
+ <xsl:if test="table:table-row-group//table:table-row">
+ <xsl:apply-templates select="table:table-row-group//table:table-row">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ <xsl:for-each select="table:shapes/child::*">
+ <xsl:if test="starts-with(name(.),'draw:')">
+ <xsl:choose>
+ <xsl:when test="name(.)='draw:frame' and self::node()/draw:object">
+ <xsl:call-template name="draw:chart-frame">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="uof锚点"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="table:table-row-group or table:table-column-group">
+ <xsl:element name="表:分组集">
+ <xsl:attribute name="uof:locID">s0098</xsl:attribute>
+ <xsl:for-each select="table:table-column-group">
+ <xsl:variable name="numcolumnrep" select="count(descendant::table:table-column[@table:number-columns-repeated])"/>
+ <xsl:variable name="numrep" select="sum(descendant::table:table-column/@table:number-columns-repeated)"/>
+ <xsl:variable name="numcolumn" select="count(descendant::table:table-column)"/>
+ <xsl:call-template name="table:table-column-group">
+ <xsl:with-param name="start" select="count(preceding::table:table-column)"/>
+ <xsl:with-param name="end" select="count(preceding::table:table-column) + $numrep + $numcolumn - $numcolumnrep"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ <xsl:for-each select="table:table-row-group">
+ <xsl:variable name="numrowrep" select="count(descendant::table:table-row[@table:number-rows-repeated])"/>
+ <xsl:variable name="numrep" select="sum(descendant::table:table-row/@table:number-rows-repeated)"/>
+ <xsl:variable name="numrow" select="count(descendant::table:table-row)"/>
+ <xsl:call-template name="table:table-row-group">
+ <xsl:with-param name="start" select="count(preceding::table:table-row)"/>
+ <xsl:with-param name="end" select="count(preceding::table:table-row) + $numrep + $numrow - $numrowrep"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="table:table-row-group">
+ <xsl:param name="start"/>
+ <xsl:param name="end"/>
+ <xsl:element name="表:行">
+ <xsl:attribute name="uof:locID">s0100</xsl:attribute>
+ <xsl:attribute name="uof:attrList">起始 终止 隐藏</xsl:attribute>
+ <xsl:attribute name="表:起始"><xsl:value-of select="$start + 1"/></xsl:attribute>
+ <xsl:attribute name="表:终止"><xsl:value-of select="$end"/></xsl:attribute>
+ <xsl:attribute name="表:隐藏"><xsl:choose><xsl:when test="@table:display"><xsl:value-of select="'true'"/></xsl:when><xsl:otherwise><xsl:value-of select="'false'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:for-each select="table:table-row-group">
+ <xsl:call-template name="table:table-row-group">
+ <xsl:with-param name="start" select="count(preceding::table:table-row) + number(sum(preceding::table:table-row/@table:number-rows-repeated)) - count(preceding::table:table-row[@table:number-rows-repeated])"/>
+ <xsl:with-param name="end" select="count(preceding::table:table-row) + number(sum(preceding::table:table-row/@table:number-rows-repeated)) - count(preceding::table:table-row[@table:number-rows-repeated]) + number(sum(descendant::table:table-row/@table:number-rows-repeated)) + count(descendant::table:table-row) - count(descendant::table:table-row[@table:number-rows-repeated])"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="table:table-column-group">
+ <xsl:param name="start"/>
+ <xsl:param name="end"/>
+ <xsl:element name="表:列">
+ <xsl:attribute name="uof:locID">s0099</xsl:attribute>
+ <xsl:attribute name="uof:attrList">起始 终止 隐藏</xsl:attribute>
+ <xsl:attribute name="表:起始"><xsl:value-of select="$start + 1"/></xsl:attribute>
+ <xsl:attribute name="表:终止"><xsl:value-of select="$end"/></xsl:attribute>
+ <xsl:attribute name="表:隐藏"><xsl:choose><xsl:when test="@table:display"><xsl:value-of select="'true'"/></xsl:when><xsl:otherwise><xsl:value-of select="'false'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:for-each select="table:table-column-group">
+ <xsl:call-template name="table:table-column-group">
+ <xsl:with-param name="start" select="count(preceding::table:table-column) + number(sum(preceding::table:table-column/@table:number-columns-repeated)) - count(preceding::table:table-column[@table:number-columns-repeated])"/>
+ <xsl:with-param name="end" select="count(preceding::table:table-column) + number(sum(preceding::table:table-column/@table:number-columns-repeated)) - count(preceding::table:table-column[@table:number-columns-repeated]) + number(sum(descendant::table:table-column/@table:number-columns-repeated)) + count(descendant::table:table-column) - count(descendant::table:table-column[@table:number-columns-repeated])"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="uof锚点">
+ <xsl:if test="not(name(.)='draw:glue-point')">
+ <xsl:variable name="name">
+ <xsl:value-of select="name(.)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="name='draw:a'">
+ <xsl:for-each select="child::node( )">
+ <xsl:call-template name="uof锚点"/>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <uof:锚点 uof:locID="u0064" uof:attrList="x坐标 y坐标 宽度 高度 图形引用 随动方式 缩略图 占位符">
+ <xsl:attribute name="uof:x坐标"><xsl:choose><xsl:when test="name(.)='draw:g'"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:choose><xsl:when test="@svg:x"><xsl:value-of select="substring-before(@svg:x,$uofUnit)"/></xsl:when><xsl:when test="@svg:x1"><xsl:value-of select="substring-before(@svg:x1,$uofUnit)"/></xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:y坐标"><xsl:choose><xsl:when test="name(.)='draw:g'"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:when><xsl:otherwise><xsl:choose><xsl:when test="@svg:y"><xsl:value-of select="substring-before(@svg:y,$uofUnit)"/></xsl:when><xsl:when test="@svg:y1"><xsl:value-of select="substring-before(@svg:y1,$uofUnit)"/></xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:choose><xsl:when test="@svg:width"><xsl:value-of select="substring-before(@svg:width,$uofUnit)"/></xsl:when><xsl:when test="@svg:x1"><xsl:value-of select="substring-before(@svg:x2,$uofUnit) - substring-before(@svg:x1,$uofUnit)"/></xsl:when><xsl:when test="name(.)='draw:g'"><xsl:variable name="minx"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:variable name="svgx"><xsl:value-of select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/></xsl:variable><xsl:variable name="width"><xsl:value-of select="number(substring-before(descendant::node()[@svg:x][1]/@svg:width,$uofUnit))"/></xsl:variable><xsl:variable name="maxx"><xsl:call-template name="groupmaxx"><xsl:with-param name="value" select="$svgx + $width"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:value-of select="$maxx - $minx"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:高度"><xsl:choose><xsl:when test="@svg:height"><xsl:value-of select="substring-before(@svg:height,$uofUnit)"/></xsl:when><xsl:when test="@svg:x1"><xsl:value-of select="substring-before(@svg:y2,$uofUnit) - substring-before(@svg:y1,$uofUnit)"/></xsl:when><xsl:when test="name(.)='draw:g'"><xsl:variable name="miny"><xsl:call-template name="groupminy"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:variable name="svgy"><xsl:value-of select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/></xsl:variable><xsl:variable name="height"><xsl:value-of select="number(substring-before(descendant::node()[@svg:y][1]/@svg:height,$uofUnit))"/></xsl:variable><xsl:variable name="maxy"><xsl:call-template name="groupmaxy"><xsl:with-param name="value" select="$svgy + $height"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:value-of select="$maxy - $miny"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:variable name="refpicname">
+ <xsl:choose>
+ <xsl:when test="./@draw:style-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:when>
+ <xsl:when test="./@table:end-cell-address">
+ <xsl:value-of select="@table:end-cell-address"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./@draw:id"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="uof:图形引用"><xsl:variable name="picnumber"><xsl:value-of select="count(preceding::*[@draw:style-name=$refpicname])"/></xsl:variable><xsl:value-of select="concat($refpicname,'_',$picnumber)"/></xsl:attribute>
+ <xsl:attribute name="uof:随动方式"><xsl:choose><xsl:when test="key('graphicset',$refpicname)/style:graphic-properties/@style:protect"><xsl:for-each select="key('graphicset',$refpicname)/style:graphic-properties"><xsl:choose><xsl:when test="@style:protect='size'">move</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:for-each></xsl:when><xsl:otherwise>movesize</xsl:otherwise></xsl:choose></xsl:attribute>
+ </uof:锚点>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <!--end 06.02.14 -->
+ <!-- **************** -->
+ <!-- *** Columns *** -->
+ <!-- **************** -->
+ <!--Redoffice comment liliang 06.05.23-->
+ <!--xsl:template name="create-table-column">
+ <xsl:param name="columnNodes"/>
+ <xsl:param name="currentColumn"/>
+ <xsl:param name="columnCount"/>
+ <xsl:param name="columnNo"/>
+ <xsl:param name="columnNodeNo"/>
+ <xsl:param name="index"/>
+ <xsl:element name="表:列">
+ <xsl:attribute name="locID">s0048</xsl:attribute>
+ <xsl:attribute name="attrList">列号 隐藏 列宽 式样引用 跨度</xsl:attribute>
+ <xsl:if test="$currentColumn/@table:visibility = 'collapse' or $currentColumn/@table:visibility = 'filter'">
+ <xsl:attribute name="表:隐藏">true</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="表:跨度"><xsl:choose><xsl:when test="$currentColumn/@table:number-columns-repeated"><xsl:value-of select="$currentColumn/@table:number-columns-repeated - 1"/></xsl:when><xsl:otherwise><xsl:value-of select="'0'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$index">
+ <xsl:attribute name="表:列号"><xsl:value-of select="$columnNo"/></xsl:attribute>
+ </xsl:if-->
+ <!--自动列宽没有,暂略 autofitwidth-->
+ <!--Redoffice comment liliang 06.05.22-->
+ <!--xsl:variable name="width">
+ <xsl:value-of select="key('styles', $currentColumn/@table:style-name)/style:properties/@style:column-width"/>
+ </xsl:variable-->
+ <!--end-->
+ <!--xsl:if test="$width">
+ <xsl:attribute name="表:宽度"><xsl:call-template name="convert2pt"><xsl:with-param name="value" select="$width"/></xsl:call-template></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="表:跨度"><xsl:choose><xsl:when test="$currentColumn/@table:number-columns-repeated"><xsl:value-of select="$currentColumn/@table:number-columns-repeated - 1"/></xsl:when><xsl:otherwise><xsl:value-of select="'0'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:if test="$columnNo &lt; $columnCount">
+ <xsl:choose>
+ <xsl:when test="@table:number-columns-repeated">
+ <xsl:call-template name="create-table-column">
+ <xsl:with-param name="columnNodes" select="$columnNodes"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="columnNo" select="$columnNo + $currentColumn/@table:number-columns-repeated"/>
+ <xsl:with-param name="columnNodeNo" select="$columnNodeNo + 1"/>
+ <xsl:with-param name="currentColumn" select="$columnNodes[$columnNodeNo + 1]"/>
+ <xsl:with-param name="index" select="true()"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-table-column">
+ <xsl:with-param name="columnNodes" select="$columnNodes"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="columnNo" select="$columnNo + 1"/>
+ <xsl:with-param name="columnNodeNo" select="$columnNodeNo + 1"/>
+ <xsl:with-param name="currentColumn" select="$columnNodes[$columnNodeNo + 1]"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template-->
+ <!-- ************* -->
+ <!-- *** Rows *** -->
+ <!-- ************* -->
+ <xsl:template match="table:table-row">
+ <xsl:param name="table-name"/>
+ <xsl:param name="columnCount"/>
+ <xsl:choose>
+ <xsl:when test="@table:number-rows-repeated &gt; 1">
+ <xsl:choose>
+ <xsl:when test="(last() or (last() - 1)) and @table:number-rows-repeated &gt; 99">
+ <xsl:call-template name="write-table-row">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="lastRow" select="true()"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- In case a cell is being repeated, the cell will be created
+ in a variable, which is as many times given out, as being repeated -->
+ <xsl:variable name="tableRow">
+ <xsl:call-template name="write-table-row">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="repeat-write-table-row">
+ <xsl:with-param name="tableRow" select="$tableRow"/>
+ <xsl:with-param name="repetition" select="@table:number-rows-repeated"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="write-table-row">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="write-table-row">
+ <xsl:param name="table-name"/>
+ <xsl:param name="columnCount"/>
+ <xsl:param name="lastRow"/>
+ <xsl:element name="表:行">
+ <xsl:attribute name="uof:locID">s0049</xsl:attribute>
+ <xsl:attribute name="uof:attrList">行号 隐藏 行高 式样引用 跨度</xsl:attribute>
+ <xsl:if test="./table:table-cell/@office:value-type">
+ <xsl:attribute name="表:行号"><xsl:value-of select="count(preceding::table:table-row[not(@table:number-rows-repeated)])+1+number(sum(preceding::table:table-row[@table:number-rows-repeated]/@table:number-rows-repeated))"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@table:visibility = 'collapse' or @table:visibility = 'filter'">
+ <xsl:attribute name="表:隐藏">true</xsl:attribute>
+ </xsl:if>
+ <!-- although valid, can not be opened with Excel - issue i31949)
+ <xsl:if test="$lastRow">
+ <xsl:attribute name="ss:Span"><xsl:value-of select="@table:number-rows-repeated - 1" /></xsl:attribute>
+ </xsl:if>-->
+ <!-- writing the style of the row -->
+ <xsl:apply-templates select="@table:style-name"/>
+ <xsl:variable name="rowProperties" select="key('styles', @table:style-name)/*"/>
+ <!--xsl:if test="$rowProperties/@style:use-optimal-row-height = 'false'">
+ <! - - default is '1', therefore write only '0' - ->
+ <xsl:attribute name="ss:AutoFitHeight">0</xsl:attribute>
+ </xsl:if-->
+ <xsl:variable name="height" select="$rowProperties/@style:row-height"/>
+ <xsl:if test="$height">
+ <xsl:attribute name="表:行高"><!-- using the absolute height in point --><xsl:call-template name="convert2pt"><xsl:with-param name="value" select="$height"/></xsl:call-template></xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="table:table-cell">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="repeat-write-table-row">
+ <xsl:param name="tableRow"/>
+ <xsl:param name="repetition"/>
+ <xsl:copy-of select="$tableRow"/>
+ <xsl:if test="$repetition &gt; 1">
+ <xsl:call-template name="repeat-write-table-row">
+ <xsl:with-param name="tableRow" select="$tableRow"/>
+ <xsl:with-param name="repetition" select="$repetition - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <!-- ************** -->
+ <!-- *** Cells *** -->
+ <!-- ************** -->
+ <!-- Table cells are able to be repeated by attribute in StarOffice,
+ but not in Excel. If more cells are repeated
+ (e.g. for emulating background) only as many cells as columns are
+ allowed to be written out. -->
+ <xsl:template match="table:table-cell">
+ <xsl:param name="table-name"/>
+ <xsl:param name="columnCount"/>
+ <!--xsl:choose>
+ <xsl:when test="@table:number-columns-repeated &gt; 1">
+ <xsl:variable name="tableCell">
+ <xsl:call-template name="write-table-cell"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="not(following-sibling::table:table-cell)">
+ <xsl:call-template name="repeat-write-table-cell">
+ <xsl:with-param name="tableCell" select="$tableCell"/>
+ <xsl:with-param name="repetition" select="@table:number-columns-repeated"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="cellNo" select="position()+ sum(preceding-sibling::table:table-cell/@table:number-columns-repeated)- count(preceding-sibling::table:table-cell/@table:number-columns-repeated)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="repeat-write-table-cell">
+ <xsl:with-param name="tableCell" select="$tableCell"/>
+ <xsl:with-param name="repetition" select="@table:number-columns-repeated"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="write-table-cell"/>
+ </xsl:otherwise>
+ </xsl:choose-->
+ <xsl:choose>
+ <xsl:when test="@table:number-columns-repeated">
+ <xsl:call-template name="write-table-cell">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="repeat-table-cell-no" select="@table:number-columns-repeated"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="write-table-cell">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="repeat-table-cell-no" select="number(1)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--xsl:template name="repeat-write-table-cell">
+ <xsl:param name="tableCell"/>
+ <xsl:param name="repetition"/>
+ <xsl:param name="columnCount"/>
+ <xsl:param name="cellNo"/>
+ <xsl:copy-of select="$tableCell"/>
+ <xsl:if test="$repetition &gt; 1">
+ <xsl:choose>
+ <xsl:when test="$cellNo">
+ <xsl:if test="$cellNo &lt; $columnCount">
+ <xsl:call-template name="repeat-write-table-cell">
+ <xsl:with-param name="tableCell" select="$tableCell"/>
+ <xsl:with-param name="repetition" select="$repetition - 1"/>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="cellNo" select="$cellNo + 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="repeat-write-table-cell">
+ <xsl:with-param name="tableCell" select="$tableCell"/>
+ <xsl:with-param name="repetition" select="$repetition - 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template-->
+ <xsl:template name="write-table-cell">
+ <xsl:param name="table-name"/>
+ <xsl:param name="repeat-table-cell-no"/>
+ <xsl:if test="$repeat-table-cell-no &gt; 0">
+ <表:单元格 uof:locID="s0050" uof:attrList="列号 式样引用 超链接引用 合并列数 合并行数">
+ <xsl:if test="@table:number-columns-spanned &gt; 1">
+ <xsl:attribute name="表:合并列数"><xsl:value-of select="@table:number-columns-spanned - 1"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@table:number-rows-spanned &gt; 1">
+ <xsl:attribute name="表:合并行数"><xsl:value-of select="@table:number-rows-spanned - 1"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="link" select="descendant::text:a/@xlink:href"/>
+ <xsl:if test="$link">
+ <xsl:attribute name="表:超链接引用"><xsl:value-of select="$link"/></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@table:style-name">
+ <xsl:apply-templates select="@table:style-name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="ancestor::table:table/table:table-column/@table:default-cell-style-name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="*">
+ <xsl:if test="text:p">
+ <xsl:variable name="valueType">
+ <xsl:choose>
+ <xsl:when test="@office:value-type">
+ <xsl:value-of select="@office:value-type"/>
+ </xsl:when>
+ <xsl:otherwise>string</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="表的数据">
+ <xsl:with-param name="valueType" select="$valueType"/>
+ <xsl:with-param name="cellStyleName" select="@table:style-name"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="office:annotation">
+ <xsl:element name="表:批注">
+ <xsl:attribute name="uof:locID">s0053</xsl:attribute>
+ <xsl:attribute name="uof:attrList">是否显示</xsl:attribute>
+ <xsl:attribute name="表:是否显示"><xsl:choose><xsl:when test="office:annotation/@office:display = 'true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <uof:锚点 uof:locID="u0064" uof:attrList="x坐标 y坐标 宽度 高度 图形引用 随动方式 缩略图 占位符">
+ <xsl:variable name="num">
+ <xsl:value-of select="substring-after(office:annotation/@draw:style-name,'gr')"/>
+ </xsl:variable>
+ <xsl:attribute name="uof:图形引用"><xsl:value-of select="concat('pz',$num)"/></xsl:attribute>
+ <xsl:attribute name="uof:x坐标"><xsl:value-of select="substring-before(office:annotation/@svg:x,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:y坐标"><xsl:value-of select="substring-before(office:annotation/@svg:y,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(office:annotation/@svg:width,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:高度"><xsl:value-of select="substring-before(office:annotation/@svg:height,$uofUnit)"/></xsl:attribute>
+ </uof:锚点>
+ </xsl:element>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:for-each select="child::*">
+ <xsl:if test="starts-with(name(.),'draw:')">
+ <xsl:choose>
+ <xsl:when test="name(.)='draw:frame' and self::node()/draw:object">
+ <xsl:call-template name="draw:chart-frame">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="uof锚点"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="/office:document/office:body/office:spreadsheet/table:tracked-changes and not(self::node()/@table:style-name) and self::node()/text:p">
+ <xsl:element name="表:数据">
+ <xsl:attribute name="uof:locID">s0051</xsl:attribute>
+ <xsl:attribute name="uof:attrList">数据类型</xsl:attribute>
+ <xsl:element name="字:句">
+ <xsl:attribute name="uof:locID">t0085</xsl:attribute>
+ <xsl:call-template name="table:tracked-changes"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </表:单元格>
+ <xsl:variable name="repeat-table-cell-no1">
+ <xsl:value-of select="$repeat-table-cell-no - 1"/>
+ </xsl:variable>
+ <xsl:call-template name="write-table-cell">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="repeat-table-cell-no" select="$repeat-table-cell-no1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="office:annotation"/>
+ <xsl:template match="dc:date"/>
+ <xsl:template name="表的数据">
+ <xsl:param name="valueType"/>
+ <xsl:param name="cellStyleName"/>
+ <xsl:choose>
+ <xsl:when test="descendant::*/@text:style-name">
+ <xsl:choose>
+ <xsl:when test="$valueType = 'string'">
+ <表:数据 表:数据类型="string" uof:locID="s0051" uof:attrList="数据类型">
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName"/>
+ </xsl:apply-templates>
+ </表:数据>
+ </xsl:when>
+ <xsl:when test="$valueType = 'boolean'">
+ <表:数据 表:数据类型="boolean" uof:locID="s0051" uof:attrList="数据类型">
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName"/>
+ </xsl:apply-templates>
+ </表:数据>
+ </xsl:when>
+ <xsl:when test="$valueType = 'date'">
+ <表:数据 表:数据类型="date" uof:locID="s0051" uof:attrList="数据类型">
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName"/>
+ </xsl:apply-templates>
+ </表:数据>
+ </xsl:when>
+ <xsl:otherwise>
+ <表:数据 表:数据类型="number" uof:locID="s0051" uof:attrList="数据类型">
+ <xsl:apply-templates>
+ <xsl:with-param name="cellStyleName" select="$cellStyleName"/>
+ </xsl:apply-templates>
+ </表:数据>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <表:数据 uof:locID="s0051" uof:attrList="数据类型">
+ <xsl:choose>
+ <xsl:when test="$valueType = 'string'">
+ <xsl:attribute name="表:数据类型">text</xsl:attribute>
+ <!--xsl:attribute name="表:数据数值"><xsl:value-of select="@office:string-value"/></xsl:attribute-->
+ <!--chengxz schema no this attr-->
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="text:p"/>
+ </字:文本串>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="$valueType = 'boolean'">
+ <xsl:attribute name="表:数据类型">boolean</xsl:attribute>
+ <字:句 uof:locID="t0085">
+ <xsl:choose>
+ <xsl:when test="@table:boolean-value = 'true'">
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">true</字:文本串>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">false</字:文本串>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="$valueType = 'date'">
+ <xsl:attribute name="表:数据类型">date</xsl:attribute>
+ <xsl:attribute name="表:数据数值"><xsl:value-of select="@office:date-value"/></xsl:attribute>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="text:p"/>
+ </字:文本串>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="$valueType = 'time'">
+ <xsl:attribute name="表:数据类型">time</xsl:attribute>
+ <xsl:attribute name="表:数据数值"><xsl:value-of select="@office:time-value"/></xsl:attribute>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="text:p"/>
+ </字:文本串>
+ </字:句>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="表:数据类型">number</xsl:attribute>
+ <xsl:attribute name="表:数据数值"><xsl:value-of select="@office:value"/></xsl:attribute>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="text:p"/>
+ </字:文本串>
+ </字:句>
+ </xsl:otherwise>
+ </xsl:choose>
+ </表:数据>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="分页符集">
+ <xsl:for-each select="table:table-row">
+ <xsl:if test="key('styles', @table:style-name)/style:table-row-properties/@fo:break-before">
+ <xsl:variable name="table-break-before">
+ <xsl:value-of select="key('styles', @table:style-name)/style:table-row-properties/@fo:break-before"/>
+ </xsl:variable>
+ <xsl:if test="$table-break-before = 'page'">
+ <xsl:element name="表:分页符">
+ <xsl:attribute name="uof:locID">s0112</xsl:attribute>
+ <xsl:attribute name="uof:attrList">行号 列号</xsl:attribute>
+ <xsl:if test="preceding-sibling::table:table-row/@table:number-rows-repeated">
+ <xsl:attribute name="表:行号"><xsl:value-of select="sum(preceding-sibling::table:table-row/@table:number-rows-repeated)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(preceding-sibling::table:table-row/@table:number-rows-repeated)">
+ <xsl:attribute name="表:行号">1</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="key('styles', @table:style-name)/style:table-row-properties/@fo:break-after">
+ <xsl:variable name="table-break-after" select="key('styles', @table:style-name)/style:table-row-properties/@fo:break-after"/>
+ <xsl:if test="$table-break-after = 'page'">
+ <xsl:element name="表:分页符">
+ <xsl:attribute name="uof:locID">s0112</xsl:attribute>
+ <xsl:attribute name="uof:attrList">行号 列号</xsl:attribute>
+ <xsl:if test="preceding-sibling::table:table-row/@table:number-rows-repeated">
+ <xsl:attribute name="表:行号"><xsl:value-of select="sum(preceding-sibling::table:table-row/@table:number-rows-repeated)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(preceding-sibling::table:table-row/@table:number-rows-repeated)">
+ <xsl:attribute name="表:行号">1</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="table:table-column">
+ <xsl:if test="key('styles', @table:style-name)/style:table-column-properties/@fo:break-before">
+ <xsl:variable name="table-break-before" select="key('styles', @table:style-name)/style:table-column-properties/@fo:break-before"/>
+ <xsl:if test="$table-break-before = 'page'">
+ <xsl:element name="表:分页符">
+ <xsl:attribute name="uof:locID">s0112</xsl:attribute>
+ <xsl:attribute name="uof:attrList">行号 列号</xsl:attribute>
+ <xsl:if test="preceding-sibling::table:table-column/@table:number-columns-repeated">
+ <xsl:attribute name="表:列号"><xsl:value-of select="sum(preceding-sibling::table:table-column/@table:number-columns-repeated)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(preceding-sibling::table:table-column/@table:number-columns-repeated)">
+ <xsl:attribute name="表:列号">1</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="key('styles', @table:style-name)/style:table-column-properties/@fo:break-after">
+ <xsl:variable name="table-break-after" select="key('styles', @table:style-name)/style:table-column-properties/@fo:break-after"/>
+ <xsl:if test="$table-break-after = 'page'">
+ <xsl:element name="表:分页符">
+ <xsl:attribute name="uof:locID">s0112</xsl:attribute>
+ <xsl:attribute name="uof:attrList">行号 列号</xsl:attribute>
+ <xsl:if test="preceding-sibling::table:table-column/@table:number-columns-repeated">
+ <xsl:attribute name="表:列号"><xsl:value-of select="sum(preceding-sibling::table:table-column/@table:number-columns-repeated)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(preceding-sibling::table:table-column/@table:number-columns-repeated)">
+ <xsl:attribute name="表:列号">1</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="text:s">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="@text:c"/>
+ </xsl:call-template>
+ </xsl:template>
+ <!--write the number of 'whitespaces' -->
+ <xsl:template name="write-breakable-whitespace">
+ <xsl:param name="whitespaces"/>
+ <xsl:text> </xsl:text>
+ <xsl:if test="$whitespaces >= 1">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="$whitespaces - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <!-- allowing all matched text nodes -->
+ <!--chengxz0630-->
+ <!--xsl:template match="text()">
+ <字:句 uof:locID="t0085">
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="locID">t0109</xsl:attribute>
+
+ <xsl:value-of select="." />
+ </xsl:element>
+ </字:句>
+ </xsl:template-->
+ <xsl:variable name="namespace-html" select="'http://www.w3.org/TR/REC-html40'"/>
+ <xsl:template match="@table:style-name | @table:default-cell-style-name">
+ <xsl:attribute name="表:式样引用"><!--ss:styleID--><xsl:value-of select="."/><!--chengxz 060114--></xsl:attribute>
+ </xsl:template>
+ <xsl:template name="style-and-contents">
+ <xsl:param name="cellStyleName"/>
+ <字:句 uof:locID="t0085">
+ <xsl:element name="字:文本串">
+ <!--chengxz0630-->
+ </xsl:element>
+ </字:句>
+ </xsl:template>
+ <!-- *************88-->
+ <xsl:param name="dpi" select="111"/>
+ <xsl:param name="centimeter-in-mm" select="10"/>
+ <xsl:param name="inch-in-mm" select="25.4"/>
+ <xsl:param name="didot-point-in-mm" select="0.376065"/>
+ <xsl:param name="pica-in-mm" select="4.2333333"/>
+ <xsl:param name="point-in-mm" select="0.3527778"/>
+ <xsl:param name="twip-in-mm" select="0.017636684"/>
+ <xsl:param name="pixel-in-mm" select="$inch-in-mm div $dpi"/>
+ <!-- ***** MEASUREMENT CONVERSIONS *****
+ PARAM 'value'
+ The measure to be converted.
+ The current measure is judged by a substring (e.g. 'mm', 'cm', 'in', 'pica'...)
+ directly added to the number.
+
+ PARAM 'rounding-factor'
+ Is used for the rounding of decimal places.
+ The parameter number is the product of 1 and some '10', where
+ every zero represents a decimal place.
+
+ For example, providing as parameter:
+ <xsl:param name="rounding-factor" select="10000" />
+ Gives by default four decimal places.
+
+ To round two decimal places, basically the following is done:
+ <xsl:value-of select="round(100 * value) div 100"/>
+
+ RETURN The converted number, by default rounded to four decimal places.
+ In case the input measure could not be matched the same value is
+ returned and a warning message is written out.
+
+
+
+ MEASURE LIST:
+ * 1 millimeter (mm), the basic measure
+
+ * 1 centimeter (cm) = 10 mm
+
+ * 1 inch (in) = 25.4 mm
+ While the English have already seen the light (read: the metric system), the US
+ remains loyal to this medieval system.
+
+ * 1 point (pt) = 0.35277777.. mm
+ Sometimes called PostScript point (ppt), as when Adobe created PostScript, they added their own system of points.
+ There are exactly 72 PostScript points in 1 inch.
+
+ * 1 twip = twentieth of a (PostScript) point
+ A twip (twentieth of a point) is a 1/20th of a PostScript point, a traditional measure in printing.
+
+ * 1 didot point (dpt) = 0.376065 mm
+ Didot point after the French typographer Firmin Didot (1764-1836).
+
+ More details under
+ http://www.unc.edu/~rowlett/units/dictP.html:
+ "A unit of length used by typographers and printers. When printing was done
+ from hand-set metal type, one point represented the smallest element of type
+ that could be handled, roughly 1/64 inch. Eventually, the point was standardized
+ in Britain and America as exactly 1/72.27 = 0.013 837 inch, which is
+ about 0.35 mm (351.46 micrometers). In continental Europe, typographers
+ traditionally used a slightly larger point of 0.014 83 inch (about
+ 1/72 pouce, 0.377 mm, or roughly 1/67 English inch), called a Didot point
+ after the French typographer Firmin Didot (1764-1836). In the U.S.,
+ Adobe software defines the point to be exactly 1/72 inch (0.013 888 9 inch
+ or 0.352 777 8 millimeters) and TeX software uses a slightly smaller point
+ of 0.351 459 8035 mm. The German standards agency DIN has proposed that
+ all these units be replaced by multiples of 0.25 millimeters (1/101.6 inch).
+
+ * 1 pica = 4.233333 mm
+ 1/6 inch or 12 points
+
+ * 1 pixel (px) = 0.26458333.. mm (relative to 'DPI', here: 96 dpi)
+ Most pictures have the 96 dpi resolution, but the dpi variable may vary by stylesheet parameter
+
+
+ -->
+ <!-- changing measure to mm -->
+ <xsl:template name="convert2mm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="substring-before($value, 'mm')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm' ) * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in' ) * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'mm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to cm -->
+ <xsl:template name="convert2cm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="substring-before($value, 'cm')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $centimeter-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $centimeter-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $centimeter-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $centimeter-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $centimeter-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $centimeter-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'cm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to inch (cp. section comment) -->
+ <xsl:template name="convert2in">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $inch-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="substring-before($value, 'in')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $inch-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $inch-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $inch-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $inch-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $inch-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'in'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to dpt (cp. section comment) -->
+ <xsl:template name="convert2dpt">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $didot-point-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $didot-point-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $didot-point-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="substring-before($value, 'dpt')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $didot-point-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $didot-point-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $didot-point-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'dpt'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pica (cp. section comment) -->
+ <xsl:template name="convert2pica">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $pica-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $pica-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $pica-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $pica-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="substring-before($value, 'pica')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $pica-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $pica-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'pica'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pt (cp. section comment) -->
+ <xsl:template name="convert2pt">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $point-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $point-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="substring-before($value, 'pt')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $point-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $point-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $point-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $point-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'pt'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pt (cp. section comment) -->
+ <xsl:template name="convert2twip">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $twip-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $twip-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $twip-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $twip-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $twip-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="substring-before($value, 'twip')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $twip-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'twip'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="convert2px">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round(number(substring-before($value, 'mm')) div $pixel-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round(number(substring-before($value, 'cm')) div $pixel-in-mm * $centimeter-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round(number(substring-before($value, 'in')) div $pixel-in-mm * $inch-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round(number(substring-before($value, 'pt')) div $pixel-in-mm * $point-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round(number(substring-before($value, 'dpt')) div $pixel-in-mm * $didot-point-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round(number(substring-before($value, 'pica')) div $pixel-in-mm * $pica-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round(number(substring-before($value, 'twip')) div $pixel-in-mm * $twip-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'px'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:key match="draw:object/office:document/office:automatic-styles/style:style" name="chart-style-name" use="@style:name"/>
+ <xsl:template name="draw:chart-frame">
+ <xsl:param name="table-name"/>
+ <表:图表 uof:locID="s0055" uof:attrList="类型 子类型 宽度 高度 x坐标 y坐标 随动方式">
+ <xsl:variable name="plot-area">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="data-area">
+ <xsl:value-of select="draw:object/@draw:notify-on-update-of-ranges"/>
+ </xsl:variable>
+ <xsl:variable name="series-generate">
+ <xsl:for-each select="key('chart-style-name',$plot-area)">
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@chart:series-source='columns'">col</xsl:when>
+ <xsl:otherwise>row</xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:call-template name="表:图表">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ </xsl:call-template>
+ <表:图表区 uof:locID="s0056">
+ <xsl:call-template name="表:图表区">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ </xsl:call-template>
+ </表:图表区>
+ <表:绘图区 uof:locID="s0060">
+ <xsl:attribute name="表:宽度"><xsl:value-of select="substring-before(draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/@svg:width,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="表:高度"><xsl:value-of select="substring-before(draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/@svg:height,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="表:x坐标"><xsl:value-of select="substring-before(draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/@svg:x,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="表:y坐标"><xsl:value-of select="substring-before(draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/@svg:y,$uofUnit)"/></xsl:attribute>
+ <xsl:call-template name="表:绘图区">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ </xsl:call-template>
+ </表:绘图区>
+ <表:分类轴 uof:locID="s0061" uof:attrList="主刻度类型 次刻度类型 刻度线标志">
+ <xsl:variable name="axis-style-name">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[child::chart:categories]/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:for-each select="draw:object/office:document/office:automatic-styles/style:style[@style:name=$axis-style-name]">
+ <xsl:attribute name="表:主刻度类型"><xsl:choose><xsl:when test="style:chart-properties/@chart:tick-marks-major-inner='true' and style:chart-properties/@chart:tick-marks-major-outer='true'">cross</xsl:when><xsl:when test="style:chart-properties/@chart:tick-marks-major-inner='false'">inside</xsl:when><xsl:when test="style:chart-properties/@chart:tick-marks-major-inner='true'">outside</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:次刻度类型"><xsl:choose><xsl:when test="style:chart-properties/@chart:tick-marks-minor-inner='true' and style:chart-properties/@chart:tick-marks-minor-outer='true'">cross</xsl:when><xsl:when test="style:chart-properties/@chart:tick-marks-minor-inner='true'">inside</xsl:when><xsl:when test="style:chart-properties/@chart:tick-marks-minor-inner='true'">outside</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:刻度线标志"><xsl:choose><xsl:when test="style:chart-properties/@chart:display-label='true'">next to axis</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:call-template name="表:坐标轴类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="axis-type" select="category-axis"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </表:分类轴>
+ <表:数值轴 uof:locID="s0082" uof:attrList="主刻度类型 次刻度类型 刻度线标志">
+ <xsl:variable name="axis-style-name">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[child::chart:grid]/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:for-each select="draw:object/office:document/office:automatic-styles/style:style[@style:name=$axis-style-name]">
+ <xsl:attribute name="表:主刻度类型"><xsl:choose><xsl:when test="style:chart-properties/@chart:tick-marks-major-inner='true' and style:chart-properties/@chart:tick-marks-major-outer='true'">cross</xsl:when><xsl:when test="style:chart-properties/@chart:tick-marks-major-inner='true'">inside</xsl:when><xsl:when test="style:chart-properties/@chart:tick-marks-major-inner='true'">outside</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:次刻度类型"><xsl:choose><xsl:when test="style:chart-properties/@chart:tick-marks-minor-inner='true' and style:chart-properties/@chart:tick-marks-minor-outer='true'">cross</xsl:when><xsl:when test="style:chart-properties/@chart:tick-marks-minor-inner='true'">inside</xsl:when><xsl:when test="style:chart-properties/@chart:tick-marks-minor-inner='true'">outside</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:刻度线标志"><xsl:choose><xsl:when test="style:chart-properties/@chart:display-label='true'">next to axis</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:call-template name="表:坐标轴类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="axis-type" select="category-axis"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </表:数值轴>
+ <表:图例 uof:locID="s0083" uof:attrList="位置">
+ <xsl:attribute name="表:位置"><xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:legend/@chart:legend-position"/></xsl:attribute>
+ <xsl:attribute name="表:x坐标"><xsl:value-of select="substring-before(draw:object/office:document/office:body/office:chart/chart:chart/chart:legend/@svg:x,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="表:y坐标"><xsl:value-of select="substring-before(draw:object/office:document/office:body/office:chart/chart:chart/chart:legend/@svg:y,$uofUnit)"/></xsl:attribute>
+ <xsl:call-template name="表:图例">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ </xsl:call-template>
+ </表:图例>
+ <!--表:数据表 uof:locID="s0085">
+ <xsl:call-template name="表:数据表">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ </xsl:call-template>
+ </表:数据表-->
+ <表:数据系列集 uof:locID="s0086">
+ <xsl:variable name="data-series-path" select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:series"/>
+ <xsl:call-template name="表:数据系列">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="data-series-path" select="$data-series-path"/>
+ </xsl:call-template>
+ </表:数据系列集>
+ <!--0825 by lil -->
+ <xsl:if test="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:series">
+ <表:数据点集 uof:locID="s0090">
+ <xsl:variable name="data-series-path" select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:series"/>
+ <xsl:call-template name="表:数据点">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="data-series-path" select="$data-series-path"/>
+ </xsl:call-template>
+ </表:数据点集>
+ </xsl:if>
+ <!--end-->
+ <表:网格线集 uof:locID="s0092">
+ <xsl:if test="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='x' and @chart:style-name]/chart:grid">
+ <xsl:call-template name="表:网格线">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="grid-type" select="'category axis'"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='y']/@chart:style-name">
+ <xsl:call-template name="表:网格线">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="grid-type" select="'value axis'"/>
+ </xsl:call-template>
+ </xsl:if>
+ </表:网格线集>
+ <表:数据源 uof:locID="s0094" uof:attrList="数据区域 系列产生">
+ <xsl:variable name="series-row-start">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring-before(substring(substring-after($data-area,'.'),2),':')"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="series-row-end">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after(substring-after($data-area,'.'),'.'),2)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="series-col-start">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($data-area,'.'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="series-col-end">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after(substring-after($data-area,'.'),'.'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="series-value-count">
+ <xsl:choose>
+ <xsl:when test="$series-generate='col'">
+ <xsl:value-of select="$series-col-end -$series-col-start +1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$series-row-end -$series-row-start +1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="表:数据区域"><xsl:value-of select="draw:object/@draw:notify-on-update-of-ranges"/></xsl:attribute>
+ <xsl:attribute name="表:系列产生"><xsl:choose><xsl:when test="contains($series-generate,'col')">col</xsl:when><xsl:when test="contains($series-generate,'row')">row</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:call-template name="表:系列">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="series-row-start" select="$series-row-start"/>
+ <xsl:with-param name="series-row-end" select="$series-row-end"/>
+ <xsl:with-param name="series-col-start" select="$series-col-start"/>
+ <xsl:with-param name="series-col-end" select="$series-col-end"/>
+ <xsl:with-param name="series-value-current" select="'1'"/>
+ <xsl:with-param name="series-value-count" select="$series-value-count"/>
+ </xsl:call-template>
+ </表:数据源>
+ <表:标题集 uof:locID="s0096">
+ <xsl:if test="draw:object/office:document/office:body/office:chart/chart:chart/chart:title">
+ <xsl:call-template name="表:标题">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="caption-type" select="'chart'"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='x']">
+ <xsl:call-template name="表:标题">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="caption-type" select="'category axis'"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='y']">
+ <xsl:call-template name="表:标题">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="caption-type" select="'value axis'"/>
+ </xsl:call-template>
+ </xsl:if>
+ </表:标题集>
+ </表:图表>
+ </xsl:template>
+ <xsl:template name="表:图表">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:variable name="chart-class">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/@chart:class"/>
+ </xsl:variable>
+ <xsl:variable name="chart-area">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="plot-area">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$chart-class='chart:bar'">
+ <xsl:variable name="chart-sub-class">
+ <xsl:value-of select="key('chart-style-name',$plot-area)/style:chart-properties/@chart:vertical"/>
+ </xsl:variable>
+ <xsl:attribute name="表:类型"><xsl:choose><xsl:when test="$chart-sub-class='true'">bar</xsl:when><xsl:when test="$chart-sub-class='false'">column</xsl:when><xsl:otherwise/></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:子类型"><xsl:choose><xsl:when test="$chart-sub-class='true'"><xsl:choose><xsl:when test="key('chart-style-name',$plot-area)/style:chart-properties/@chart:percentage">bar_percent</xsl:when><xsl:when test="key('chart-style-name',$plot-area)/style:chart-properties/@chart:stacked">bar_stacked</xsl:when><xsl:otherwise>bar_standard</xsl:otherwise></xsl:choose></xsl:when><xsl:when test="$chart-sub-class='false'"><xsl:choose><xsl:when test="key('chart-style-name',$plot-area)/style:chart-properties/@chart:percentage">column_percent</xsl:when><xsl:when test="key('chart-style-name',$plot-area)/style:chart-properties/@chart:stacked">column_stacked</xsl:when><xsl:otherwise>column_standard</xsl:otherwise></xsl:choose></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$chart-class='chart:line'">
+ <xsl:attribute name="表:类型">line</xsl:attribute>
+ <xsl:attribute name="表:子类型"><xsl:choose><xsl:when test="key('chart-style-name',$plot-area)/style:chart-properties/@chart:percentage">line_percent</xsl:when><xsl:when test="key('chart-style-name',$plot-area)/style:chart-properties/@chart:stacked">line_stacked</xsl:when><xsl:otherwise>line_standard</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$chart-class='chart:circle'">
+ <xsl:attribute name="表:类型">pie</xsl:attribute>
+ <xsl:variable name="data-point-end" select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:series[1]/chart:data-point"/>
+ <xsl:choose>
+ <xsl:when test="count($data-point-end) &lt;=1">
+ <xsl:attribute name="表:子类型">pie_standard</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="data-point-position-1">
+ <xsl:for-each select="$data-point-end[position()=1]">
+ <xsl:choose>
+ <xsl:when test="@chart:style-name">
+ <xsl:for-each select="key('chart-style-name',@chart:style-name)">
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@chart:pie-offset">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$data-point-position-1='0'">
+ <xsl:attribute name="表:子类型">pie_standard</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="$data-point-end[position()=2]">
+ <xsl:choose>
+ <xsl:when test="@chart:style-name">
+ <xsl:for-each select="key('chart-style-name',@chart:style-name)">
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@chart:pie-offset">
+ <xsl:attribute name="表:子类型">pie_offset2</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="表:子类型">pie_offset1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="表:子类型">pie_offset1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$chart-class='chart:ring'">
+ <xsl:attribute name="表:类型">pie</xsl:attribute>
+ <xsl:attribute name="表:子类型">pie_ring</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:attribute name="表:宽度"><xsl:value-of select="substring-before(@svg:width,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="表:高度"><xsl:value-of select="substring-before(@svg:height,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="表:x坐标"><xsl:value-of select="substring-before(@svg:x,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="表:y坐标"><xsl:value-of select="substring-before(@svg:y,$uofUnit)"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@draw:style-name">
+ <xsl:variable name="draw-style-name" select="@draw:style-name"/>
+ <xsl:for-each select="draw:object//office:document/office:automatic-styles/style:style[@style:name=$draw-style-name]">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:move-protect='true' and style:graphic-properties/@draw:size-protect='true'">
+ <xsl:attribute name="表:随动方式">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:size-protect='true'">
+ <xsl:attribute name="表:随动方式">move</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="表:随动方式">move and re-size</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="表:随动方式">move and re-size</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:图表区">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:variable name="chart-style-name" select="draw:object/office:document/office:body/office:chart/chart:chart/@chart:style-name"/>
+ <xsl:for-each select="draw:object/office:document/office:automatic-styles/style:style[@style:name=$chart-style-name]">
+ <表:边框 uof:locID="s0057" uof:attrList="类型 宽度 边距 颜色 阴影">
+ <xsl:call-template name="表:边框"/>
+ </表:边框>
+ <xsl:if test="style:graphic-properties/@draw:fill-color or (style:graphic-properties/@draw:fill and not(style:graphic-properties/@draw:fill='none'))">
+ <表:填充 uof:locID="s0058">
+ <xsl:call-template name="图:填充类型"/>
+ </表:填充>
+ </xsl:if>
+ <表:字体 uof:locID="s0059" uof:attrList="式样引用">
+ <xsl:call-template name="字:句属性类型">
+ </xsl:call-template>
+ </表:字体>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:绘图区">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:variable name="plot-style-name" select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:wall/@chart:style-name"/>
+ <xsl:for-each select="draw:object/office:document/office:automatic-styles/style:style[@style:name=$plot-style-name]">
+ <表:边框 uof:locID="s0057" uof:attrList="类型 宽度 边距 颜色 阴影">
+ <xsl:call-template name="表:边框"/>
+ </表:边框>
+ <xsl:if test="style:graphic-properties/@draw:fill-color or (style:graphic-properties/@draw:fill and not(style:graphic-properties/@draw:fill='none'))">
+ <表:填充 uof:locID="s0058">
+ <xsl:call-template name="图:填充类型2"/>
+ </表:填充>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:图例">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:variable name="legend">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:legend/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:for-each select="draw:object/office:document/office:automatic-styles/style:style[@style:name=$legend]">
+ <表:边框 uof:locID="s0057" uof:attrList="类型 宽度 边距 颜色 阴影">
+ <xsl:call-template name="表:边框"/>
+ </表:边框>
+ <xsl:if test="style:graphic-properties/@draw:fill-color or (style:graphic-properties/@draw:fill and not(style:graphic-properties/@draw:fill='none'))">
+ <表:填充 uof:locID="s0058">
+ <xsl:call-template name="图:填充类型"/>
+ </表:填充>
+ </xsl:if>
+ <表:字体 uof:locID="s0059" uof:attrList="式样引用">
+ <xsl:call-template name="字:句属性类型"/>
+ </表:字体>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:图例项">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <表:图例项 uof:locID="s0084" uof:attrList="系列">
+ <表:字体 uof:locID="s0059" uof:attrList="式样引用">
+ <xsl:call-template name="字:句属性类型"/>
+ </表:字体>
+ </表:图例项>
+ </xsl:template>
+ <xsl:template name="表:数据表">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:if test="style:graphic-properties/@draw:fill-color or (style:graphic-properties/@draw:fill and not(style:graphic-properties/@draw:fill='none'))">
+ <表:填充 uof:locID="s0058">
+ <xsl:call-template name="图:填充类型"/>
+ </表:填充>
+ </xsl:if>
+ <表:字体 uof:locID="s0059" uof:attrList="式样引用">
+ <xsl:call-template name="字:句属性类型"/>
+ </表:字体>
+ </xsl:template>
+ <xsl:template name="表:数据系列">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:param name="data-series-path"/>
+ <xsl:for-each select="$data-series-path">
+ <表:数据系列 uof:locID="s0087" uof:attrList="系列">
+ <xsl:variable name="data-series-position">
+ <xsl:value-of select="position()"/>
+ </xsl:variable>
+ <xsl:attribute name="表:系列"><xsl:value-of select="$data-series-position"/></xsl:attribute>
+ <xsl:variable name="data-series-point" select="@chart:style-name"/>
+ <xsl:call-template name="表:数据点类型">
+ <xsl:with-param name="data-series-point" select="$data-series-point"/>
+ <xsl:with-param name="data-series-position" select="$data-series-position"/>
+ </xsl:call-template>
+ </表:数据系列>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:数据点">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:param name="data-series-path"/>
+ <xsl:for-each select="$data-series-path">
+ <xsl:variable name="data-series-position" select="position()"/>
+ <xsl:for-each select="chart:data-point">
+ <!--xsl:if test="@chart:style-name"-->
+ <xsl:variable name="data-point-position">
+ <xsl:call-template name="count-chart-data-point">
+ <xsl:with-param name="data-point-count" select="'1'"/>
+ <xsl:with-param name="data-point-position-temp" select="position() -1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <表:数据点 uof:locID="s0091" uof:attrList="系列 点">
+ <xsl:attribute name="表:系列"><xsl:value-of select="$data-series-position"/></xsl:attribute>
+ <xsl:attribute name="表:点"><xsl:value-of select="$data-point-position"/></xsl:attribute>
+ <xsl:variable name="data-series-point" select="@chart:style-name"/>
+ <xsl:for-each select="../../../../../office:automatic-styles/style:style[@style:name=$data-series-point]">
+ <表:边框 uof:locID="s0057" uof:attrList="类型 宽度 边距 颜色 阴影">
+ <xsl:call-template name="表:边框"/>
+ </表:边框>
+ <xsl:if test="style:graphic-properties/@draw:fill-color or (style:graphic-properties/@draw:fill and not(style:graphic-properties/@draw:fill='none'))">
+ <表:填充 uof:locID="s0058">
+ <xsl:call-template name="图:填充类型"/>
+ </表:填充>
+ </xsl:if>
+ <表:字体 uof:locID="s0059" uof:attrList="式样引用">
+ <xsl:call-template name="字:句属性类型"/>
+ </表:字体>
+ <表:显示标志 uof:locID="s0088" uof:attrList="系列名 类别名 数值 百分数 分隔符 图例标志">
+ <xsl:attribute name="表:系列名"/>
+ <xsl:attribute name="表:分隔符"/>
+ <xsl:if test="style:chart-properties/@chart:data-label-text">
+ <xsl:attribute name="表:类别名"><xsl:value-of select="style:chart-properties/@chart:data-label-text"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@chart:data-label-number">
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@chart:data-label-number='value'">
+ <xsl:attribute name="表:数值">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="style:chart-properties/@chart:data-label-number='percentage'">
+ <xsl:attribute name="表:百分数">true</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@chart:data-label-symbol">
+ <xsl:attribute name="表:图例标志"><xsl:value-of select="style:chart-properties/@chart:data-label-symbol"/></xsl:attribute>
+ </xsl:if>
+ </表:显示标志>
+ <表:系列名 uof:locID="s0089">
+ <xsl:value-of select="concat('系列',$data-series-position)"/>
+ </表:系列名>
+ </xsl:for-each>
+ </表:数据点>
+ <!--/xsl:if-->
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:网格线">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:param name="grid-type"/>
+ <xsl:if test="$grid-type='category axis'">
+ <xsl:variable name="category-axis-grid">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='x']/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:for-each select="key('chart-style-name',$category-axis-grid)">
+ <表:网格线 uof:locID="s0093" uof:attrList="类型 宽度 边距 颜色 阴影 位置">
+ <xsl:call-template name="表:边框"/>
+ <xsl:attribute name="表:位置"><xsl:value-of select="$grid-type"/></xsl:attribute>
+ </表:网格线>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="$grid-type='value axis'">
+ <xsl:variable name="value-axis-grid">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='y']/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:for-each select="key('chart-style-name',$value-axis-grid)">
+ <表:网格线 uof:locID="s0093" uof:attrList="类型 宽度 边距 颜色 阴影 位置">
+ <xsl:call-template name="表:边框"/>
+ <xsl:attribute name="表:位置"><xsl:value-of select="$grid-type"/></xsl:attribute>
+ </表:网格线>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="表:系列">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:param name="series-row-start"/>
+ <xsl:param name="series-row-end"/>
+ <xsl:param name="series-col-start"/>
+ <xsl:param name="series-col-end"/>
+ <xsl:param name="series-value-current"/>
+ <xsl:param name="series-value-count"/>
+ <xsl:choose>
+ <xsl:when test="$series-value-current>$series-value-count"/>
+ <xsl:otherwise>
+ <表:系列 uof:locID="s0095" uof:attrList="系列名 系列值 分类名">
+ <xsl:attribute name="表:系列名"><xsl:value-of select="concat('系列',$series-value-current)"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$series-generate='col'">
+ <xsl:variable name="series-col-letter-start">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="$series-col-start +$series-value-current -1"/>
+ <xsl:with-param name="output-type" select="'CHARS_UPPER_LETTER'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="表:系列值"><xsl:value-of select="concat($table-name,'!',$series-col-letter-start,$series-row-start,':',$series-col-letter-start,$series-row-end)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="series-col-letter-start">
+ <xsl:value-of select="substring(substring-after($data-area,'.'),1,1)"/>
+ </xsl:variable>
+ <xsl:variable name="series-col-letter-end">
+ <xsl:value-of select="substring(substring-after(substring-after($data-area,'.'),'.'),1,1)"/>
+ </xsl:variable>
+ <xsl:attribute name="表:系列值"><xsl:value-of select="concat($table-name,'!',$series-col-letter-start,$series-row-start +$series-value-current -1,':',$series-col-letter-end,$series-row-start +$series-value-current -1)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </表:系列>
+ <xsl:call-template name="表:系列">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="data-area" select="$data-area"/>
+ <xsl:with-param name="series-generate" select="$series-generate"/>
+ <xsl:with-param name="series-row-start" select="$series-row-start"/>
+ <xsl:with-param name="series-row-end" select="$series-row-end"/>
+ <xsl:with-param name="series-col-start" select="$series-col-start"/>
+ <xsl:with-param name="series-col-end" select="$series-col-end"/>
+ <xsl:with-param name="series-value-current" select="$series-value-current +1"/>
+ <xsl:with-param name="series-value-count" select="$series-value-count"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:标题">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:param name="caption-type"/>
+ <xsl:if test="$caption-type='chart'">
+ <xsl:variable name="chart-title">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:title/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="chart-title-name">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:title/text:p"/>
+ </xsl:variable>
+ <xsl:for-each select="key('chart-style-name',$chart-title)">
+ <表:标题 uof:locID="s0097" uof:attrList="名称 位置">
+ <xsl:attribute name="表:名称"><xsl:value-of select="$chart-title-name"/></xsl:attribute>
+ <xsl:attribute name="表:位置"><xsl:value-of select="$caption-type"/></xsl:attribute>
+ <xsl:call-template name="表:标题类型"/>
+ </表:标题>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="$caption-type='category axis'">
+ <xsl:variable name="category-axis-title">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='x']/chart:title/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="category-axis-title-name">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='x']/chart:title/text:p"/>
+ </xsl:variable>
+ <xsl:for-each select="key('chart-style-name',$category-axis-title)">
+ <表:标题 uof:locID="s0097" uof:attrList="名称 位置">
+ <xsl:attribute name="表:名称"><xsl:value-of select="$category-axis-title-name"/></xsl:attribute>
+ <xsl:attribute name="表:位置"><xsl:value-of select="$caption-type"/></xsl:attribute>
+ <xsl:call-template name="表:标题类型"/>
+ </表:标题>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="$caption-type='value axis'">
+ <xsl:variable name="value-axis-title">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='y']/chart:title/@chart:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="value-axis-title-name">
+ <xsl:value-of select="draw:object/office:document/office:body/office:chart/chart:chart/chart:plot-area/chart:axis[@chart:dimension='y']/chart:title/text:p"/>
+ </xsl:variable>
+ <xsl:for-each select="key('chart-style-name',$value-axis-title)">
+ <表:标题 uof:locID="s0097" uof:attrList="名称 位置">
+ <xsl:attribute name="表:名称"><xsl:value-of select="$value-axis-title-name"/></xsl:attribute>
+ <xsl:attribute name="表:位置"><xsl:value-of select="$caption-type"/></xsl:attribute>
+ <xsl:call-template name="表:标题类型"/>
+ </表:标题>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="表:坐标轴类型">
+ <xsl:param name="table-name"/>
+ <xsl:param name="data-area"/>
+ <xsl:param name="series-generate"/>
+ <xsl:param name="axis-type"/>
+ <表:线型 uof:locID="s0062" uof:attrList="类型 宽度 边距 颜色 阴影">
+ <xsl:attribute name="uof:类型"><xsl:call-template name="表:线型"/></xsl:attribute>
+ </表:线型>
+ <表:数值 uof:locID="s0063" uof:attrList="链接到源 分类名称 格式码">
+ <xsl:attribute name="表:链接到源"><xsl:choose><xsl:when test="style:chart-properties/@chart:link-data-style-to-source"><xsl:value-of select="style:chart-properties/@chart:link-data-style-to-source"/></xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="@style:data-style-name">
+ <xsl:call-template name="Chart-NumberFormat">
+ <xsl:with-param name="temp-style" select="@style:data-style-name"/>
+ </xsl:call-template>
+ </xsl:if>
+ </表:数值>
+ <表:字体 uof:locID="s0059" uof:attrList="式样引用">
+ <xsl:call-template name="字:句属性类型"/>
+ </表:字体>
+ <表:刻度 uof:locID="s0064">
+ <xsl:call-template name="表:刻度类型"/>
+ </表:刻度>
+ <表:对齐 uof:locID="s0078">
+ <xsl:if test="style:chart-properties/@style:direction">
+ <xsl:element name="表:文字方向">
+ <xsl:attribute name="uof:locID">s0079</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@style:direction = 'ttb'">vertical</xsl:when>
+ <xsl:otherwise>horizontal</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@text:rotation-angle">
+ <表:旋转角度 uof:locID="s0080">
+ <xsl:value-of select="style:chart-properties/@text:rotation-angle"/>
+ </表:旋转角度>
+ </xsl:if>
+ <表:偏移量 uof:locID="s0081"/>
+ </表:对齐>
+ </xsl:template>
+ <xsl:template name="Chart-NumberFormat">
+ <xsl:param name="temp-style"/>
+ <xsl:for-each select="(preceding-sibling::*[@style:name=$temp-style]) | (following-sibling::*[@style:name=$temp-style])">
+ <xsl:attribute name="表:分类名称"><xsl:choose><xsl:when test="name(.)='number:currency-style'">currency</xsl:when><xsl:when test="name(.)='number:percentage-style'">percentage</xsl:when><xsl:when test="name(.)='number:date-style'">date</xsl:when><xsl:when test="name(.)='number:time-style'">time</xsl:when><xsl:when test="name(.)='number:boolean-style'">custom</xsl:when><xsl:when test="name(.)='number:text-style'">text</xsl:when><xsl:when test="name(.)='number:number-style'"><xsl:choose><xsl:when test="number:fraction">fraction</xsl:when><xsl:when test="number:scientific-number">scientific</xsl:when><xsl:otherwise>number</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>general</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:格式码"><xsl:call-template name="element-attribute"/><xsl:for-each select="style:map"><xsl:text>[</xsl:text><xsl:value-of select="@style:condition"/><xsl:text>]</xsl:text><xsl:variable name="apply-style" select="@style:apply-style-name"/><xsl:for-each select="../../child::*[@style:name=$apply-style]/*"><xsl:call-template name="general-number-format"/></xsl:for-each><xsl:text>;</xsl:text></xsl:for-each><xsl:for-each select="*[not(name(.)='style:map')]"><xsl:call-template name="general-number-format"/></xsl:for-each></xsl:attribute>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:数据点类型">
+ <xsl:param name="data-series-point"/>
+ <xsl:param name="data-series-position"/>
+ <xsl:for-each select="ancestor::draw:object/office:document/office:automatic-styles/style:style[@style:name=$data-series-point]">
+ <表:边框 uof:locID="s0057" uof:attrList="类型 宽度 边距 颜色 阴影">
+ <xsl:call-template name="表:边框"/>
+ </表:边框>
+ <xsl:if test="style:graphic-properties/@draw:fill-color or (style:graphic-properties/@draw:fill and not(style:graphic-properties/@draw:fill='none'))">
+ <表:填充 uof:locID="s0058">
+ <xsl:call-template name="图:填充类型"/>
+ </表:填充>
+ </xsl:if>
+ <表:字体 uof:locID="s0059" uof:attrList="式样引用">
+ <xsl:call-template name="字:句属性类型"/>
+ </表:字体>
+ <表:显示标志 uof:locID="s0088" uof:attrList="系列名 类别名 数值 百分数 分隔符 图例标志">
+ <xsl:attribute name="表:系列名">true</xsl:attribute>
+ <xsl:if test="style:chart-properties/@chart:data-label-text">
+ <xsl:attribute name="表:类别名"><xsl:value-of select="style:chart-properties/@chart:data-label-text"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@chart:data-label-number">
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@chart:data-label-number='value'">
+ <xsl:attribute name="表:数值">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="style:chart-properties/@chart:data-label-number='percentage'">
+ <xsl:attribute name="表:百分数">true</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@chart:data-label-symbol">
+ <xsl:attribute name="表:图例标志"><xsl:value-of select="style:chart-properties/@chart:data-label-symbol"/></xsl:attribute>
+ </xsl:if>
+ </表:显示标志>
+ <表:系列名 uof:locID="s0089">
+ <xsl:value-of select="concat('系列',$data-series-position)"/>
+ </表:系列名>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:标题类型">
+ <表:边框 uof:locID="s0057" uof:attrList="类型 宽度 边距 颜色 阴影">
+ <xsl:call-template name="表:边框"/>
+ </表:边框>
+ <xsl:if test="style:graphic-properties/@draw:fill-color or (style:graphic-properties/@draw:fill and not(style:graphic-properties/@draw:fill='none'))">
+ <表:填充 uof:locID="s0058">
+ <xsl:call-template name="图:填充类型"/>
+ </表:填充>
+ </xsl:if>
+ <表:字体 uof:locID="s0059" uof:attrList="式样引用">
+ <xsl:call-template name="字:句属性类型"/>
+ </表:字体>
+ <表:对齐 uof:locID="s0020">
+ <xsl:call-template name="表:对齐格式类型"/>
+ </表:对齐>
+ </xsl:template>
+ <xsl:template name="count-chart-data-point">
+ <xsl:param name="data-point-count"/>
+ <xsl:param name="data-point-position-temp"/>
+ <xsl:choose>
+ <xsl:when test="$data-point-position-temp=0">
+ <xsl:value-of select="$data-point-count"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="temp">
+ <xsl:for-each select="../chart:data-point[position()=$data-point-position-temp]">
+ <xsl:choose>
+ <xsl:when test="@chart:repeated">
+ <xsl:value-of select="@chart:repeated"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:call-template name="count-chart-data-point">
+ <xsl:with-param name="data-point-count" select="$data-point-count +$temp"/>
+ <xsl:with-param name="data-point-position-temp" select="$data-point-position-temp -1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:边框">
+ <xsl:attribute name="uof:类型"><xsl:call-template name="表:线型"/></xsl:attribute>
+ <xsl:if test="style:graphic-properties/@svg:stroke-width">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(style:graphic-properties/@svg:stroke-width,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@svg:stroke-color">
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="style:graphic-properties/@svg:stroke-color"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="uof:阴影">false</xsl:attribute>
+ </xsl:template>
+ <xsl:template name="图:填充类型">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:fill='gradient'">
+ <xsl:variable name="gradient-name">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-gradient-name"/>
+ </xsl:variable>
+ <xsl:for-each select="/descendant::draw:gradient[@draw:name=$gradient-name]">
+ <图:渐变 uof:locID="g0037" uof:attrList="起始色 终止色 种子类型 起始浓度 终止浓度 渐变方向 边界 种子X位置 种子Y位置 类型">
+ <xsl:attribute name="图:起始色"><xsl:value-of select="@draw:start-color"/></xsl:attribute>
+ <xsl:attribute name="图:终止色"><xsl:value-of select="@draw:end-color"/></xsl:attribute>
+ <xsl:attribute name="图:种子类型"><xsl:choose><xsl:when test="@draw:style='linear' or @draw:style='axial'">linear</xsl:when><xsl:when test="@draw:style='radial'">radar</xsl:when><xsl:when test="@draw:style='ellipsoid'">oval</xsl:when><xsl:when test="@draw:style='square'">square</xsl:when><xsl:when test="@draw:style='rectangular'">rectangle</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:起始浓度"><xsl:value-of select="substring-before(@draw:start-intensity,'%')"/></xsl:attribute>
+ <xsl:attribute name="图:终止浓度"><xsl:value-of select="substring-before(@draw:end-intensity,'%')"/></xsl:attribute>
+ <xsl:variable name="angle">
+ <xsl:value-of select="@draw:angle div 10"/>
+ </xsl:variable>
+ <xsl:attribute name="图:渐变方向"><xsl:choose><xsl:when test="0&lt;$angle and $angle&lt;25">0</xsl:when><xsl:when test="25&lt;$angle and $angle&lt;70">45</xsl:when><xsl:when test="70&lt;$angle and $angle&lt;115">90</xsl:when><xsl:when test="115&lt;$angle and $angle&lt;160">135</xsl:when><xsl:when test="160&lt;$angle and $angle&lt;205">180</xsl:when><xsl:when test="205&lt;$angle and $angle&lt;250">225</xsl:when><xsl:when test="250&lt;$angle and $angle&lt;295">270</xsl:when><xsl:when test="295&lt;$angle and $angle&lt;340">315</xsl:when><xsl:when test="340&lt;$angle and $angle&lt;360">360</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:边界"><xsl:value-of select="substring-before(@draw:border,'%')"/></xsl:attribute>
+ <xsl:if test="@draw:cx">
+ <xsl:attribute name="图:种子X位置"><xsl:value-of select="substring-before(@draw:cx,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@draw:cy">
+ <xsl:attribute name="图:种子Y位置"><xsl:value-of select="substring-before(@draw:cy,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:类型">-2</xsl:attribute>
+ </图:渐变>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:fill-image-name">
+ <图:图片 uof:locID="g0035" uof:attrList="位置 图形引用 类型 名称">
+ <xsl:attribute name="图:位置"><xsl:choose><xsl:when test="not(style:graphic-properties/@style:repeat)">tile</xsl:when><xsl:otherwise><xsl:choose><xsl:when test="style:graphic-properties/@style:repeat = 'stretch'">stretch</xsl:when><xsl:when test="style:graphic-properties/@style:repeat = 'repeat'">tile</xsl:when><xsl:when test="style:graphic-properties/@style:repeat = 'no-repeat'">center</xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:图形引用"><xsl:value-of select="concat('chart_image_',count(preceding::draw:fill-image))"/></xsl:attribute>
+ <xsl:attribute name="图:类型">png</xsl:attribute>
+ <xsl:attribute name="图:名称"><xsl:value-of select="style:graphic-properties/@draw:fill-image-name"/></xsl:attribute>
+ </图:图片>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:fill='hatch'">
+ <图:图案 uof:locID="g0036" uof:attrList="类型 图形引用 前景色 背景色">
+ <xsl:attribute name="图:类型"><xsl:value-of select="../../office:styles/draw:hatch/@draw:name"/></xsl:attribute>
+ <xsl:attribute name="图:图形引用">gr1</xsl:attribute>
+ <xsl:attribute name="图:前景色"><xsl:value-of select="../../office:styles/draw:hatch/@draw:color"/></xsl:attribute>
+ <xsl:attribute name="图:背景色"><xsl:choose><xsl:when test="style:graphic-properties/@draw:fill-color"><xsl:value-of select="style:graphic-properties/@draw:fill-color"/></xsl:when><xsl:otherwise>#ffffff</xsl:otherwise></xsl:choose></xsl:attribute>
+ </图:图案>
+ </xsl:when>
+ <xsl:otherwise>
+ <图:颜色 uof:locID="g0034">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:fill-color">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-color"/>
+ </xsl:when>
+ <xsl:otherwise>#99ccff</xsl:otherwise>
+ </xsl:choose>
+ </图:颜色>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="图:填充类型2">
+ <xsl:if test="style:graphic-properties/@draw:fill-color">
+ <图:颜色 uof:locID="g0034">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-color"/>
+ </图:颜色>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:fill-image-name">
+ <xsl:variable name="chart-image-name" select="style:graphic-properties/@draw:fill-image-name"/>
+ <图:图片 uof:locID="g0035" uof:attrList="位置 图形引用 类型 名称">
+ <xsl:attribute name="图:位置"><xsl:choose><xsl:when test="not(style:graphic-properties/@style:repeat)">tile</xsl:when><xsl:otherwise><xsl:choose><xsl:when test="style:graphic-properties/@style:repeat = 'stretch'">stretch</xsl:when><xsl:when test="style:graphic-properties/@style:repeat = 'repeat'">tile</xsl:when><xsl:when test="style:graphic-properties/@style:repeat = 'no-repeat'">center</xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:for-each select="../../office:styles/draw:fill-image[@draw:name=$chart-image-name]">
+ <xsl:attribute name="图:图形引用"><xsl:value-of select="concat('chart_image_',count(preceding::draw:fill-image))"/></xsl:attribute>
+ </xsl:for-each>
+ <xsl:attribute name="图:类型">png</xsl:attribute>
+ <xsl:attribute name="图:名称"><xsl:value-of select="$chart-image-name"/></xsl:attribute>
+ </图:图片>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:fill-hatch-name">
+ <xsl:variable name="chart-hatch-name" select="style:graphic-properties/@draw:fill-hatch-name"/>
+ <图:图案 uof:locID="g0036" uof:attrList="类型 图形引用 前景色 背景色">
+ <xsl:for-each select="../../office:styles/draw:hatch[@draw:name=$chart-hatch-name]">
+ <xsl:attribute name="图:类型"><xsl:value-of select="@draw:style"/></xsl:attribute>
+ <xsl:attribute name="图:前景色"><xsl:value-of select="@draw:color"/></xsl:attribute>
+ <xsl:attribute name="图:背景色"/>
+ <xsl:attribute name="图:距离"><xsl:value-of select="@draw:distance"/></xsl:attribute>
+ <xsl:attribute name="图:旋转度"><xsl:value-of select="@draw:rotation"/></xsl:attribute>
+ </xsl:for-each>
+ <xsl:attribute name="图:图形引用"><xsl:value-of select="$chart-hatch-name"/></xsl:attribute>
+ </图:图案>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:fill-gradient-name">
+ <xsl:variable name="chart-gradient-name" select="style:graphic-properties/@draw:fill-gradient-name"/>
+ <图:渐变 uof:locID="g0037" uof:attrList="起始色 终止色 种子类型 起始浓度 终止浓度 渐变方向 边界 种子X位置 种子Y位置 类型">
+ <xsl:for-each select="../../office:styles/draw:gradient[@draw:name=$chart-gradient-name]">
+ <xsl:attribute name="图:起始色"><xsl:value-of select="@draw:start-color"/></xsl:attribute>
+ <xsl:attribute name="图:终止色"><xsl:value-of select="@draw:end-color"/></xsl:attribute>
+ <xsl:attribute name="图:种子类型"><xsl:choose><xsl:when test="@draw:style='linear' or @draw:style='axial'">linear</xsl:when><xsl:when test="@draw:style='radial'">radar</xsl:when><xsl:when test="@draw:style='ellipsoid'">oval</xsl:when><xsl:when test="@draw:style='square'">square</xsl:when><xsl:when test="@draw:style='rectangular'">rectangle</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:起始浓度"><xsl:value-of select="substring-before(@draw:start-intensity,'%')"/></xsl:attribute>
+ <xsl:attribute name="图:终止浓度"><xsl:value-of select="substring-before(@draw:end-intensity,'%')"/></xsl:attribute>
+ <xsl:variable name="angle">
+ <xsl:value-of select="@draw:angle div 10"/>
+ </xsl:variable>
+ <xsl:attribute name="图:渐变方向"><xsl:choose><xsl:when test="0&lt;$angle and $angle&lt;25">0</xsl:when><xsl:when test="25&lt;$angle and $angle&lt;70">45</xsl:when><xsl:when test="70&lt;$angle and $angle&lt;115">90</xsl:when><xsl:when test="115&lt;$angle and $angle&lt;160">135</xsl:when><xsl:when test="160&lt;$angle and $angle&lt;205">180</xsl:when><xsl:when test="205&lt;$angle and $angle&lt;250">225</xsl:when><xsl:when test="250&lt;$angle and $angle&lt;295">270</xsl:when><xsl:when test="295&lt;$angle and $angle&lt;340">315</xsl:when><xsl:when test="340&lt;$angle and $angle&lt;360">360</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:边界"><xsl:value-of select="substring-before(@draw:border,'%')"/></xsl:attribute>
+ <xsl:if test="@draw:cx">
+ <xsl:attribute name="图:种子X位置"><xsl:value-of select="substring-before(@draw:cx,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@draw:cy">
+ <xsl:attribute name="图:种子Y位置"><xsl:value-of select="substring-before(@draw:cy,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:类型">-2</xsl:attribute>
+ </xsl:for-each>
+ <xsl:attribute name="图:图形引用"><xsl:value-of select="$chart-gradient-name"/></xsl:attribute>
+ </图:渐变>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="表:对齐格式类型">
+ <xsl:if test="style:chart-properties/@style:rotation-angle">
+ <表:文字旋转角度 uof:locID="s0080">
+ <xsl:value-of select="style:chart-properties/@style:rotation-angle"/>
+ </表:文字旋转角度>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@fo:text-align">
+ <xsl:element name="表:水平对齐方式">
+ <xsl:attribute name="uof:locID">s0115</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@fo:text-align = 'center'">center</xsl:when>
+ <xsl:when test="style:chart-properties/@fo:text-align = 'end'">right</xsl:when>
+ <xsl:when test="style:chart-properties/@fo:text-align = 'justify'">justify</xsl:when>
+ <xsl:when test="style:chart-properties/@fo:text-align = 'start'">left</xsl:when>
+ <xsl:otherwise>fill</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="(style:chart-properties/@style:vertical-align) or (style:chart-properties/@fo:vertical-align)">
+ <xsl:element name="表:垂直对齐方式">
+ <xsl:attribute name="uof:locID">s0116</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@fo:vertical-align = 'top'">top</xsl:when>
+ <xsl:when test="style:chart-properties/@fo:vertical-align = 'middle'">center</xsl:when>
+ <xsl:when test="style:chart-properties/@fo:vertical-align = 'bottom'">bottom</xsl:when>
+ <xsl:when test="style:chart-properties/@fo:vertical-align = 'justify'">justify</xsl:when>
+ <xsl:otherwise>distributed</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:margin-left">
+ <表:缩进 uof:locID="s0117">
+ <xsl:value-of select="substring-before(style:paragraph-properties/@fo:margin-left,$uofUnit)"/>
+ </表:缩进>
+ </xsl:if>
+ <xsl:element name="表:文字方向">
+ <xsl:attribute name="uof:locID">s0118</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="style:chart-properties/@style:direction = 'ttb'">vertical</xsl:when>
+ <xsl:otherwise>horizontal</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <表:自动换行 uof:locID="s0120" uof:attrList="值">
+ <xsl:attribute name="表:值">true</xsl:attribute>
+ </表:自动换行>
+ <表:缩小字体填充 uof:locID="s0121" uof:attrList="值">
+ <xsl:attribute name="表:值">true</xsl:attribute>
+ </表:缩小字体填充>
+ </xsl:template>
+ <xsl:template name="表:线型">
+ <xsl:variable name="linetype" select="style:graphic-properties/@draw:stroke-dash"/>
+ <xsl:variable name="stroke" select="style:graphic-properties/@draw:stroke"/>
+ <xsl:choose>
+ <xsl:when test="$stroke='solid'">single</xsl:when>
+ <xsl:when test="$stroke='none'">none</xsl:when>
+ <xsl:when test="$stroke='dash'">
+ <xsl:choose>
+ <xsl:when test="$linetype='Ultrafine_20_Dashed'">dash</xsl:when>
+ <xsl:when test="$linetype='Fine_20_Dashed'">dashed-heavy</xsl:when>
+ <xsl:when test="$linetype='Ultrafine_20_2_20_Dots_20_3_20_Dashes'">dot-dash</xsl:when>
+ <xsl:when test="$linetype='Fine_20_Dotted'">dotted</xsl:when>
+ <xsl:when test="$linetype='Line_20_with_20_Fine_20_Dots'">dash-long-heavy</xsl:when>
+ <xsl:when test="$linetype='Fine_20_Dashed_20__28_var_29_'">dash-long</xsl:when>
+ <xsl:when test="$linetype='_33__20_Dashes_20_3_20_Dots_20__28_var_29_'">dash-dot-dot</xsl:when>
+ <xsl:when test="$linetype='Ultrafine_20_Dotted_20__28_var_29_'">dotted-heavy</xsl:when>
+ <xsl:when test="$linetype='Line_20_Style_20_9'">thick</xsl:when>
+ <xsl:when test="$linetype='_32__20_Dots_20_1_20_Dash'">dot-dot-dash</xsl:when>
+ <xsl:when test="$linetype='Dashed_20__28_var_29_'">dash-dot-dot-heavy</xsl:when>
+ <xsl:when test="$linetype='Dash_20_10'">dash-dot-heavy</xsl:when>
+ <xsl:otherwise>single</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>single</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:刻度类型">
+ <xsl:if test="style:chart-properties/@chart:minimum">
+ <表:最小值 uof:locID="s0065">
+ <xsl:value-of select="style:chart-properties/@chart:minimum"/>
+ </表:最小值>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@chart:maximum">
+ <表:最大值 uof:locID="s0066">
+ <xsl:value-of select="style:chart-properties/@chart:maximum"/>
+ </表:最大值>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@chart:interval-major">
+ <表:主单位 uof:locID="s0067">
+ <xsl:value-of select="style:chart-properties/@chart:interval-major"/>
+ </表:主单位>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@chart:interval-minor">
+ <表:次单位 uof:locID="s0068">
+ <xsl:value-of select="style:chart-properties/@chart:interval-minor"/>
+ </表:次单位>
+ </xsl:if>
+ <xsl:if test="style:chart-properties/@chart:origin">
+ <表:分类交叉点 uof:locID="s0069">
+ <xsl:value-of select="style:chart-properties/@chart:origin"/>
+ </表:分类交叉点>
+ </xsl:if>
+ <表:单位 uof:locID="s0070">none</表:单位>
+ <表:显示单位 uof:locID="s0071" uof:attrList="值" 表:值="false"/>
+ <表:对数 uof:locID="s0072" uof:attrList="值" 表:值="false"/>
+ </xsl:template>
+ <xsl:template name="字:句属性类型">
+ <xsl:element name="字:字体">
+ <xsl:attribute name="uof:locID">t0088</xsl:attribute>
+ <xsl:attribute name="uof:attrList">西文字体引用 中文字体引用 特殊字体引用 西文绘制 字号 相对字号 颜色</xsl:attribute>
+ <xsl:if test="style:text-properties/@fo:font-size or style:text-properties/@style:font-size-asian or style:text-properties/@style:font-size-complex">
+ <xsl:choose>
+ <xsl:when test="contains(style:text-properties/@fo:font-size,'%') or contains(style:text-properties/@style:font-size-asian,'%')">
+ <xsl:attribute name="字:相对字号"><xsl:choose><xsl:when test="style:text-properties/@fo:font-size"><xsl:value-of select="substring-before(style:text-properties/@fo:font-size,'%')"/></xsl:when><xsl:when test="style:text-properties/@style:font-size-asian"><xsl:value-of select="substring-before(style:text-properties/@style:font-size-asian,'%')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:字号"><xsl:choose><xsl:when test="style:text-properties/@fo:font-size"><xsl:value-of select="substring-before(style:text-properties/@fo:font-size,'pt')"/></xsl:when><xsl:when test="style:text-properties/@style:font-size-asian"><xsl:value-of select="substring-before(style:text-properties/@style:font-size-asian,'pt')"/></xsl:when><xsl:when test="style:text-properties/@style:font-size-complex"><xsl:value-of select="substring-before(style:text-properties/@style:font-size-complex,'pt')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:font-family">
+ <xsl:attribute name="字:西文字体引用"><xsl:value-of select="style:text-properties/@fo:font-family"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:font-family-asian">
+ <xsl:attribute name="字:中文字体引用"><xsl:value-of select="style:text-properties/@style:font-family-asian"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select="style:text-properties/@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="style:text-properties/@style:text-background-color and not(style:text-properties/@style:text-background-color='transparent')">
+ <xsl:element name="字:填充">
+ <xsl:element name="图:图案">
+ <xsl:attribute name="uof:locID">g0036</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 图形引用 前景色 背景色</xsl:attribute>
+ <xsl:if test="style:text-properties/@style:text-background-color">
+ <xsl:attribute name="图:前景色"><xsl:value-of select="style:text-properties/@style:text-background-color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:font-weight or style:text-properties/@style:font-weight-asian">
+ <xsl:element name="字:粗体">
+ <xsl:attribute name="uof:locID">t0089</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@style:font-weight-asian='bold' or style:text-properties/@fo:font-weight='bold'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:font-style or style:text-properties/@style:font-style-asian">
+ <xsl:element name="字:斜体">
+ <xsl:attribute name="uof:locID">t0090</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@fo:font-style='italic' or style:text-properties/@style:font-style-asian='italic'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-line-through-style and not(style:text-properties/@style:text-line-through-style='none')">
+ <xsl:element name="字:删除线">
+ <xsl:attribute name="uof:locID">t0094</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:delete线型类型"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-underline">
+ <xsl:element name="字:下划线">
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:线型类型"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0095</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:if test="style:text-properties/@style:text-underline-color">
+ <xsl:attribute name="字:颜色"><xsl:choose><xsl:when test="style:text-properties/@style:text-underline-color='font-color'">auto</xsl:when><xsl:otherwise><xsl:value-of select="style:text-properties/@style:text-underline-color"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:text-shadow">
+ <xsl:element name="字:阴影">
+ <xsl:attribute name="uof:locID">t0100</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@fo:text-shadow='none'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-emphasize">
+ <xsl:element name="字:着重号">
+ <xsl:attribute name="uof:locID">t0096</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 颜色 字着重号</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="style:text-properties/@style:text-emphasize='none'">
+ <xsl:attribute name="字:字着重号">false</xsl:attribute>
+ <xsl:attribute name="字:类型">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:字着重号">true</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:着重号类型"><xsl:with-param name="te" select="style:text-properties/@style:text-emphasize"/></xsl:call-template></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="style:text-properties/@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select="style:text-properties/@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@text:display">
+ <xsl:element name="字:隐藏文字">
+ <xsl:attribute name="uof:locID">t0097</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-outline">
+ <xsl:element name="字:空心">
+ <xsl:attribute name="uof:locID">t0098</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="style:text-properties/@style:text-outline"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:font-relief">
+ <xsl:element name="字:浮雕">
+ <xsl:attribute name="uof:locID">t0099</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test="style:text-properties/@style:font-relief='embossed'">emboss</xsl:when><xsl:when test="style:text-properties/@style:font-relief='engraved'">engrave</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:text-transform or style:text-properties/@fo:font-variant">
+ <xsl:element name="字:醒目字体">
+ <xsl:attribute name="uof:locID">t0101</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test="style:text-properties/@fo:text-transform='uppercase'">uppercase</xsl:when><xsl:when test="style:text-properties/@fo:text-transform='lowercase'">lowercase</xsl:when><xsl:when test="style:text-properties/@fo:text-transform='capitalize'">capital</xsl:when><xsl:when test="style:text-properties/@fo:font-variant='small-caps'">small-caps</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-position">
+ <xsl:element name="字:位置">
+ <xsl:attribute name="uof:locID">t0102</xsl:attribute>
+ <xsl:value-of select="style:text-properties/@style:text-position"/>
+ </xsl:element>
+ <字:上下标 uof:locID="t0205" uof:attrList="值">
+ <xsl:attribute name="字:值">none</xsl:attribute>
+ </字:上下标>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-scale">
+ <xsl:element name="字:缩放">
+ <xsl:attribute name="uof:locID">t0103</xsl:attribute>
+ <xsl:value-of select="style:text-properties/@style:text-scale"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:letter-spacing">
+ <xsl:element name="字:字符间距">
+ <xsl:attribute name="uof:locID">t0104</xsl:attribute>
+ <xsl:value-of select="style:text-properties/@fo:letter-spacing"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:letter-kerning">
+ <xsl:element name="字:调整字间距">
+ <xsl:attribute name="uof:locID">t015</xsl:attribute>
+ <xsl:value-of select="style:text-properties/@style:letter-kerning"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="uof:着重号类型">
+ <xsl:param name="te"/>
+ <xsl:choose>
+ <xsl:when test="$te='disc above' ">disc above</xsl:when>
+ <xsl:when test="$te='circle above' ">circle above</xsl:when>
+ <xsl:when test="$te='dot above' ">dot above</xsl:when>
+ <xsl:when test="$te='accent above' ">accent above</xsl:when>
+ <xsl:when test="$te='dot below' ">dot below</xsl:when>
+ <xsl:when test="$te='circle below' ">circle below</xsl:when>
+ <xsl:when test="$te='disc below' ">disc below</xsl:when>
+ <xsl:when test="$te='accent below' ">accent below</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="uof:线型类型">
+ <xsl:variable name="spath" select="style:text-properties/@style:text-underline-style"/>
+ <xsl:variable name="wpath" select="style:text-properties/@style:text-underline-width"/>
+ <xsl:variable name="tpath" select="style:text-properties/@style:text-underline-type"/>
+ <xsl:choose>
+ <xsl:when test="$spath='solid' and not($tpath='double' ) and $wpath='auto' ">single</xsl:when>
+ <xsl:when test="$spath='solid' and $tpath='double' and $wpath='auto' ">double</xsl:when>
+ <xsl:when test="$spath='solid' and not($tpath='double' )and $wpath='bold' ">thick</xsl:when>
+ <xsl:when test="$spath='dotted' and not($tpath='double' )and $wpath='auto' ">dotted</xsl:when>
+ <xsl:when test="$spath='dotted' and not($tpath='double' )and $wpath='bold' ">dotted-heavy</xsl:when>
+ <xsl:when test="$spath='dash' and not($tpath='double' )and $wpath='auto' ">dash</xsl:when>
+ <xsl:when test="$spath='dash' and not($tpath='double' )and $wpath='bold' ">dashed-heavy</xsl:when>
+ <xsl:when test="$spath='long-dash' and not($tpath='double' )and $wpath='auto' ">dash-long</xsl:when>
+ <xsl:when test="$spath='long-dash' and not($tpath='double' )and $wpath='bold' ">dash-long-heavy</xsl:when>
+ <xsl:when test="$spath='dot-dash' and not($tpath='double' )and $wpath='auto' ">dot-dash</xsl:when>
+ <xsl:when test="$spath='dot-dash' and not($tpath='double' )and $wpath='bold' ">dash-dot-heavy</xsl:when>
+ <xsl:when test="$spath='dot-dot-dash' and not($tpath='double' )and $wpath='auto' ">dot-dot-dash</xsl:when>
+ <xsl:when test="$spath='dot-dot-dash' and not($tpath='double' )and $wpath='bold' ">dash-dot-dot-heavy</xsl:when>
+ <xsl:when test="$spath='wave' and not($tpath='double' )and $wpath='auto' ">wave</xsl:when>
+ <xsl:when test="$spath='wave' and not($tpath='double' )and $wpath='bold' ">wavy-heavy</xsl:when>
+ <xsl:when test="$spath='wave' and $tpath='double' and $wpath='auto' ">wavy-double</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="uof:delete线型类型">
+ <xsl:variable name="wpath" select="style:text-properties/@style:text-line-through-width"/>
+ <xsl:variable name="textpath" select="style:text-properties/@style:text-line-through-text"/>
+ <xsl:variable name="umpath" select="style:text-properties/@style:text-underline-mode"/>
+ <xsl:variable name="tmpath" select="style:text-properties/@style:text-line-through-mode"/>
+ <xsl:variable name="tpath" select="style:text-properties/@style:text-line-through-type"/>
+ <xsl:choose>
+ <xsl:when test="$umpath='continuous' and $tmpath='continuous'">single</xsl:when>
+ <xsl:when test="$tpath='double'">double</xsl:when>
+ <xsl:when test="$wpath='bold'">bold</xsl:when>
+ <xsl:when test="$textpath='/'">带/</xsl:when>
+ <xsl:when test="$textpath='X'">带X</xsl:when>
+ <xsl:otherwise>none</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--comment: if input char is Roman,please add a prefix 'Roman_'-->
+ <xsl:template name="General-Char-Transition">
+ <xsl:param name="input-char"/>
+ <xsl:param name="output-type"/>
+ <xsl:choose>
+ <xsl:when test="$input-char='A' or $input-char='a' or $input-char='1' or $input-char='Roman_I' or $input-char='Roman_i' or $input-char='一' or $input-char='壹' or $input-char='甲' or $input-char='子'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">1</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">a</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">A</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">I</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">i</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">1</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">一</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">1</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">壹</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">1</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">甲</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">子</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='B' or $input-char='b' or $input-char='2' or $input-char='Roman_II' or $input-char='Roman_ii' or $input-char='二' or $input-char='贰' or $input-char='乙' or $input-char='丑'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">2</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">b</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">B</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">II</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">ii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">2</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">2</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">2</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">乙</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">丑</xsl:when>
+ <xsl:otherwise>2</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='C' or $input-char='c' or $input-char='3' or $input-char='Roman_III' or $input-char='Roman_iii' or $input-char='三' or $input-char='叁' or $input-char='丙' or $input-char='寅'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">3</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">c</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">C</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">III</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">iii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">3</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">三</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">3</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">叁</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">3</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">丙</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">寅</xsl:when>
+ <xsl:otherwise>3</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='D' or $input-char='d' or $input-char='4' or $input-char='Roman_IV' or $input-char='Roman_iv' or $input-char='四' or $input-char='肆' or $input-char='丁' or $input-char='卯'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">4</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">d</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">D</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">IV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">iv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">4</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">四</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">4</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">肆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">4</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">丁</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">卯</xsl:when>
+ <xsl:otherwise>4</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='E' or $input-char='e' or $input-char='5' or $input-char='Roman_V' or $input-char='Roman_v' or $input-char='五' or $input-char='伍' or $input-char='戊' or $input-char='辰'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">5</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">e</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">E</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">V</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">v</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">5</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">五</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">5</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">伍</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">5</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">戊</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">辰</xsl:when>
+ <xsl:otherwise>5</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='F' or $input-char='f' or $input-char='6' or $input-char='Roman_VI' or $input-char='Roman_vi' or $input-char='六' or $input-char='陆' or $input-char='己' or $input-char='巳'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">6</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">f</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">F</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">VI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">vi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">6</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">六</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">6</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">陆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">6</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">己</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">巳</xsl:when>
+ <xsl:otherwise>6</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='G' or $input-char='g' or $input-char='7' or $input-char='Roman_VII' or $input-char='Roman_vii' or $input-char='七' or $input-char='柒' or $input-char='庚' or $input-char='午'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">7</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">g</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">G</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">VII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">vii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">7</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">七</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">7</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">柒</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">7</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">庚</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">午</xsl:when>
+ <xsl:otherwise>7</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='H' or $input-char='h' or $input-char='8' or $input-char='Roman_VIII' or $input-char='Roman_viii' or $input-char='八' or $input-char='捌' or $input-char='辛' or $input-char='未'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">8</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">h</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">H</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">VIII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">viii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">8</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">八</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">8</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">捌</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">8</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">辛</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">未</xsl:when>
+ <xsl:otherwise>8</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='I' or $input-char='i' or $input-char='9' or $input-char='Roman_IX' or $input-char='Roman_ix' or $input-char='九' or $input-char='玖' or $input-char='壬' or $input-char='申'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">9</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">i</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">I</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">IX</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">ix</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">9</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">九</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">9</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">玖</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">9</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">壬</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">申</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='J' or $input-char='j' or $input-char='10' or $input-char='Roman_X' or $input-char='Roman_x' or $input-char='十' or $input-char='拾' or $input-char='癸' or $input-char='酉'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">10</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">j</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">J</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">X</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">x</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">10</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">10</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">10</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">癸</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">酉</xsl:when>
+ <xsl:otherwise>10</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='K' or $input-char='k' or $input-char='11' or $input-char='Roman_XI' or $input-char='Roman_xi' or $input-char='十一' or $input-char='拾壹' or $input-char='戌'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">11</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">k</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">K</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">11</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十一</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">11</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾壹</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">11</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">戌</xsl:when>
+ <xsl:otherwise>11</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='L' or $input-char='l' or $input-char='12' or $input-char='Roman_XII' or $input-char='Roman_xii' or $input-char='十二' or $input-char='拾贰' or $input-char='亥'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">12</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">l</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">L</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">12</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十二</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">12</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾贰</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">12</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">亥</xsl:when>
+ <xsl:otherwise>12</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='M' or $input-char='m' or $input-char='13' or $input-char='Roman_XIII' or $input-char='Roman_xiii' or $input-char='十三' or $input-char='拾叁'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">13</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">m</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">M</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XIII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xiii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">13</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十三</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">13</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾叁</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">13</xsl:when>
+ <xsl:otherwise>13</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='N' or $input-char='n' or $input-char='14' or $input-char='Roman_XIV' or $input-char='Roman_xiv' or $input-char='十四' or $input-char='拾肆'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">14</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">n</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">N</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XIV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xiv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">14</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十四</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">14</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾肆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">14</xsl:when>
+ <xsl:otherwise>14</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='O' or $input-char='o' or $input-char='15' or $input-char='Roman_XV' or $input-char='Roman_xv' or $input-char='十五' or $input-char='拾伍'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">15</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">o</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">O</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">15</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十五</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">15</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾伍</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">15</xsl:when>
+ <xsl:otherwise>15</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='P' or $input-char='p' or $input-char='16' or $input-char='Roman_XVI' or $input-char='Roman_xvi' or $input-char='十六' or $input-char='拾陆'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">16</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">p</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">P</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XVI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xvi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">16</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十六</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">16</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾陆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">16</xsl:when>
+ <xsl:otherwise>16</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='Q' or $input-char='q' or $input-char='17' or $input-char='Roman_XVII' or $input-char='Roman_xvii' or $input-char='十七' or $input-char='拾柒'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">17</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">q</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">Q</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XVII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xvii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">17</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十七</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">17</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾柒</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">17</xsl:when>
+ <xsl:otherwise>17</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='R' or $input-char='r' or $input-char='18' or $input-char='Roman_XVIII' or $input-char='Roman_xviii' or $input-char='十八' or $input-char='拾捌'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">18</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">r</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">R</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XVIII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xviii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">18</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十八</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">18</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾捌</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">18</xsl:when>
+ <xsl:otherwise>18</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='S' or $input-char='s' or $input-char='19' or $input-char='Roman_XIX' or $input-char='Roman_xix' or $input-char='十九' or $input-char='拾玖'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">19</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">s</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">S</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XIX</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xix</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">19</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十九</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">19</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾玖</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">19</xsl:when>
+ <xsl:otherwise>19</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='T' or $input-char='t' or $input-char='20' or $input-char='Roman_XX' or $input-char='Roman_xx' or $input-char='二十' or $input-char='贰拾'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">20</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">t</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">T</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XX</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xx</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">20</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">20</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">20</xsl:when>
+ <xsl:otherwise>20</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='U' or $input-char='u' or $input-char='21' or $input-char='Roman_XXI' or $input-char='Roman_xxi' or $input-char='二十一' or $input-char='贰拾壹'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">21</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">u</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">U</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">21</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十一</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">21</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾壹</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">21</xsl:when>
+ <xsl:otherwise>21</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='V' or $input-char='v' or $input-char='22' or $input-char='Roman_XXII' or $input-char='Roman_xxii' or $input-char='二十二' or $input-char='贰拾贰'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">22</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">v</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">V</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">22</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十二</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">22</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾贰</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">22</xsl:when>
+ <xsl:otherwise>22</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='W' or $input-char='w' or $input-char='23' or $input-char='Roman_XXIII' or $input-char='Roman_xxiii' or $input-char='二十三' or $input-char='贰拾叁'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">23</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">w</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">W</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXIII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxiii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">23</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十三</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">23</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾叁</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">23</xsl:when>
+ <xsl:otherwise>23</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='X' or $input-char='x' or $input-char='24' or $input-char='Roman_XXIV' or $input-char='Roman_xxiv' or $input-char='二十四' or $input-char='贰拾肆'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">24</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">x</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">X</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXIV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxiv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">24</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十四</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">24</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾肆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">24</xsl:when>
+ <xsl:otherwise>24</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='Y' or $input-char='y' or $input-char='25' or $input-char='Roman_XXV' or $input-char='Roman_xxv' or $input-char='二十五' or $input-char='贰拾伍'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">25</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">y</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">Y</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">25</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十五</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">25</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾伍</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">25</xsl:when>
+ <xsl:otherwise>25</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='Z' or $input-char='z' or $input-char='26' or $input-char='Roman_XXVI' or $input-char='Roman_xxvi' or $input-char='二十六' or $input-char='贰拾陆'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">26</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">z</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">Z</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXVI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxvi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">26</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十六</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">26</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾陆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">26</xsl:when>
+ <xsl:otherwise>26</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">1</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">a</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">A</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">I</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">i</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">1</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">一</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">1</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">壹</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">1</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--RedOffice comment (Zengjh) end charts-->
+ <!-- 以下模板的作用是将网格线的R或者G或者B颜色从十进制转换为16进制-->
+ <xsl:template name="transform-decimal-to-hexadecimal">
+ <xsl:param name="color-decimal"/>
+ <xsl:variable name="first-number" select="floor($color-decimal div 16)"/>
+ <xsl:variable name="first-char">
+ <xsl:call-template name="decimal-to-hex">
+ <xsl:with-param name="number" select="$first-number"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="second-number" select="$color-decimal - ($first-number * 16)"/>
+ <xsl:variable name="second-char">
+ <xsl:call-template name="decimal-to-hex">
+ <xsl:with-param name="number" select="$second-number"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat($first-char,$second-char)"/>
+ </xsl:template>
+ <!-- 以下模板的作用为将0到15的整数转换为16进制数-->
+ <xsl:template name="decimal-to-hex">
+ <xsl:param name="number"/>
+ <xsl:choose>
+ <xsl:when test="$number=0">0</xsl:when>
+ <xsl:when test="$number=1">1</xsl:when>
+ <xsl:when test="$number=2">2</xsl:when>
+ <xsl:when test="$number=3">3</xsl:when>
+ <xsl:when test="$number=4">4</xsl:when>
+ <xsl:when test="$number=5">5</xsl:when>
+ <xsl:when test="$number=6">6</xsl:when>
+ <xsl:when test="$number=7">7</xsl:when>
+ <xsl:when test="$number=8">8</xsl:when>
+ <xsl:when test="$number=9">9</xsl:when>
+ <xsl:when test="$number=10">a</xsl:when>
+ <xsl:when test="$number=11">b</xsl:when>
+ <xsl:when test="$number=12">c</xsl:when>
+ <xsl:when test="$number=13">d</xsl:when>
+ <xsl:when test="$number=14">e</xsl:when>
+ <xsl:when test="$number='15'">f</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="setDefaultPageWidth">
+ <xsl:choose>
+ <xsl:when test="$uofUnit='inch'">
+ <xsl:value-of select="'7.9'"/>
+ </xsl:when>
+ <xsl:when test="$uofUnit='cm'">
+ <xsl:value-of select="'20.999'"/>
+ </xsl:when>
+ <xsl:when test="$uofUnit='mm'">
+ <xsl:value-of select="'200.99'"/>
+ </xsl:when>
+ <xsl:when test="$uofUnit='pt'">
+ <xsl:value-of select="'7870'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'20.990'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="setDefaultPageHeight">
+ <xsl:choose>
+ <xsl:when test="$uofUnit='inch'">
+ <xsl:value-of select="'10.14'"/>
+ </xsl:when>
+ <xsl:when test="$uofUnit='cm'">
+ <xsl:value-of select="'26.999'"/>
+ </xsl:when>
+ <xsl:when test="$uofUnit='mm'">
+ <xsl:value-of select="'269.99'"/>
+ </xsl:when>
+ <xsl:when test="$uofUnit='pt'">
+ <xsl:value-of select="'1023'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'26.990'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--ro000179 chenjh-->
+ <xsl:template name="create-condition-format">
+ <xsl:variable name="unique-map-cellstyle" select="/office:document/office:automatic-styles/style:style[style:map and not(style:map/@style:condition=preceding-sibling::style:style/style:map/@style:condition and style:map/@style:apply-style-name=preceding-sibling::style:style/style:map/@style:apply-style-name and style:map/@style:base-cell-address=preceding-sibling::style:style/style:map/@style:base-cell-address)]"/>
+ <xsl:for-each select="$unique-map-cellstyle">
+ <xsl:call-template name="create-cell-condition-format"/>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="create-cell-condition-format">
+ <xsl:element name="表:条件格式化">
+ <xsl:attribute name="uof:locID">s0017</xsl:attribute>
+ <xsl:element name="表:区域">
+ <xsl:attribute name="uof:locID">s0007</xsl:attribute>
+ <xsl:variable name="cellstylenamelist">
+ <xsl:call-template name="createcellnamelist">
+ <xsl:with-param name="list">
+ <xsl:value-of select="/office:document/office:automatic-styles/style:style[style:map and (style:map/@style:condition=current()/style:map/@style:condition and style:map/@style:apply-style-name=current()/style:map/@style:apply-style-name and style:map/@style:base-cell-address=current()/style:map/@style:base-cell-address)]"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- <xsl:value-of select="concat($cellstylenamelist,'end')"/>-->
+ <xsl:variable name="left-top">
+ <xsl:call-template name="search-left-top">
+ <xsl:with-param name="cellstylenamelist" select="$cellstylenamelist"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- <xsl:value-of select="concat('qqqqqqqq ',$left-top)"/> -->
+ <xsl:variable name="after-translated-left-top">
+ <xsl:call-template name="translate-left-top-condition">
+ <xsl:with-param name="left-top" select="$left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat($after-translated-left-top,':',style:map/@style:base-cell-address)"/>
+ </xsl:element>
+ <xsl:for-each select="style:map">
+ <xsl:element name="表:条件">
+ <xsl:attribute name="uof:locID">s0019</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:variable name="conditiontext" select="@style:condition"/>
+ <xsl:attribute name="表:类型"><xsl:choose><xsl:when test="contains($conditiontext,'cell-content')">cell value</xsl:when><xsl:when test="contains($conditiontext,'is-true-formula')">formula</xsl:when><xsl:otherwise>条件字符串错误!</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:element name="表:操作码">
+ <xsl:attribute name="uof:locID">s0009</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="starts-with($conditiontext,'is-true-formula')">equal to</xsl:when>
+ <xsl:when test="starts-with($conditiontext,'cell-content()')">
+ <xsl:variable name="operatortext" select="substring-after($conditiontext,'cell-content()')"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($operatortext,'&lt;=')">less than or equal to</xsl:when>
+ <xsl:when test="starts-with($operatortext,'&gt;=')">greater than or equal to</xsl:when>
+ <xsl:when test="starts-with($operatortext,'&lt;')">less than</xsl:when>
+ <xsl:when test="starts-with($operatortext,'&gt;')">greater than</xsl:when>
+ <xsl:when test="starts-with($operatortext,'!=')">not equal to</xsl:when>
+ <xsl:when test="starts-with($operatortext,'=')">equal to</xsl:when>
+ <!-- 注意:uof有的另几种操作码在oo中没有,他们是contain,not contain,start with,not start with, end with,not end with-->
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with($conditiontext,'cell-content-is-between')">between</xsl:when>
+ <xsl:when test="starts-with($conditiontext,'cell-content-is-not-between')">not between</xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="表:第一操作数">
+ <xsl:attribute name="uof:locID">s0010</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="starts-with($conditiontext,'is-true-formula')">
+ <xsl:value-of select="substring(substring-after($conditiontext,'is-true-formula('),1,string-length($conditiontext)-1-string-length('is-true-formula('))"/>
+ </xsl:when>
+ <xsl:when test="starts-with($conditiontext,'cell-content-is-between')">
+ <xsl:value-of select="substring-before(substring-after($conditiontext,'cell-content-is-between('),',')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($conditiontext,'cell-content-is-not-between')">
+ <xsl:value-of select="substring-before(substring-after($conditiontext,'cell-content-is-not-between('),',')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($conditiontext,'cell-content()')">
+ <xsl:variable name="operatortext" select="substring-after($conditiontext,'cell-content()')"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($operatortext,'&lt;=')">
+ <xsl:value-of select="substring-after($conditiontext,'&lt;=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operatortext,'&gt;=')">
+ <xsl:value-of select="substring-after($conditiontext,'&gt;=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operatortext,'&lt;')">
+ <xsl:value-of select="substring-after($conditiontext,'&lt;')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operatortext,'&gt;')">
+ <xsl:value-of select="substring-after($conditiontext,'&gt;')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operatortext,'!=')">
+ <xsl:value-of select="substring-after($conditiontext,'!=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operatortext,'=')">
+ <xsl:value-of select="substring-after($conditiontext,'=')"/>
+ </xsl:when>
+ <!-- 注意:uof有的另几种操作码在oo中没有,他们是contain,not contain,start with,not start with, end with,not end with-->
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="starts-with($conditiontext,'cell-content-is-between') or starts-with($conditiontext,'cell-content-is-not-between')">
+ <xsl:element name="表:第二操作数">
+ <xsl:attribute name="uof:locID">s0011</xsl:attribute>
+ <xsl:value-of select="substring(substring-after($conditiontext,','),1,string-length(substring-after($conditiontext,','))-1)"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="表:格式">
+ <xsl:variable name="apply-style-name" select="@style:apply-style-name"/>
+ <xsl:attribute name="uof:locID">s0023</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="表:式样引用"><xsl:value-of select="$apply-style-name"/></xsl:attribute>
+ <!--xsl:attribute name="表:式样引用"><xsl:value-of select="generate-id(//style:style[@style:name=$apply-style-name])"/></xsl:attribute-->
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="createcellnamelist">
+ <xsl:param name="list"/>
+ <xsl:choose>
+ <xsl:when test="$list">
+ <xsl:variable name="first" select="$list[1]"/>
+ <xsl:variable name="stringlist-of-rest">
+ <xsl:call-template name="createcellnamelist">
+ <xsl:with-param name="list" select="$list[position()!=1]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat($first/@style:name,' ',$stringlist-of-rest)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="search-left-top">
+ <xsl:param name="cellstylenamelist"/>
+ <xsl:choose>
+ <xsl:when test="$cellstylenamelist!=''">
+ <xsl:variable name="first-cellstylename" select="substring-before($cellstylenamelist, ' ')"/>
+ <xsl:variable name="tableslist" select="/office:document/office:body/office:spreadsheet/table:table"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-with-one-cellstyle">
+ <xsl:with-param name="cellstylename" select="$first-cellstylename"/>
+ <xsl:with-param name="tableslist" select="$tableslist"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top">
+ <xsl:with-param name="cellstylenamelist" select="substring-after($cellstylenamelist,' ')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="final-left-top">
+ <xsl:choose>
+ <xsl:when test="$rest-left-top =''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$first-left-top =''">
+ <xsl:value-of select="$rest-left-top"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="after-compared-left-top">
+ <xsl:call-template name="compare-two-left-top">
+ <xsl:with-param name="first" select="$first-left-top"/>
+ <xsl:with-param name="second" select="$rest-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$after-compared-left-top"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$final-left-top"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="translate-left-top-condition">
+ <xsl:param name="left-top"/>
+ <xsl:variable name="column-number" select="substring-before(substring-after($left-top,'.'),' ')"/>
+ <xsl:variable name="column-number1">
+ <xsl:value-of select="floor( $column-number div 26 )"/>
+ </xsl:variable>
+ <xsl:variable name="column-number2">
+ <xsl:value-of select="$column-number mod 26"/>
+ </xsl:variable>
+ <xsl:variable name="column-character1">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="column-character2">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat(substring-before($left-top,'.'),'.',$column-character1,$column-character2,substring-after($left-top,' '))"/>
+ </xsl:template>
+ <xsl:template name="search-left-top-with-one-cellstyle">
+ <xsl:param name="cellstylename"/>
+ <xsl:param name="tableslist"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$tableslist and $return=''">
+ <xsl:variable name="firsttablerows" select="$tableslist[1]//table:table-row"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-with-one-cellstyle-inatable">
+ <xsl:with-param name="row-num" select="'1'"/>
+ <xsl:with-param name="firsttablerows" select="$firsttablerows"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-with-one-cellstyle">
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="tableslist" select="$tableslist[position()!=1]"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top!=''">
+ <xsl:value-of select="$rest-left-top"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="compare-two-left-top">
+ <xsl:param name="first"/>
+ <xsl:param name="second"/>
+ <xsl:variable name="first-column" select="substring-before(substring-after($first,'.'),' ')"/>
+ <xsl:variable name="first-row" select="substring-after($first,' ')"/>
+ <xsl:variable name="second-column" select="substring-before(substring-after($second,'.'),' ')"/>
+ <xsl:variable name="second-row" select="substring-after($second,' ')"/>
+ <xsl:choose>
+ <xsl:when test="$first-row&lt;$second-row">
+ <xsl:value-of select="$first"/>
+ </xsl:when>
+ <xsl:when test="$first-row=$second-row">
+ <xsl:choose>
+ <xsl:when test="$first-column&lt;=$second-column">
+ <xsl:value-of select="$first"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$second"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$second"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="search-left-top-with-one-cellstyle-inatable">
+ <xsl:param name="row-num"/>
+ <xsl:param name="firsttablerows"/>
+ <xsl:param name="cellstylename"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$firsttablerows and $return=''">
+ <xsl:variable name="firstcells" select="$firsttablerows[1]/table:table-cell"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-with-one-cellstyle-inarow">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="column-num" select="'1'"/>
+ <xsl:with-param name="firstcells" select="$firstcells"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="row-num-p">
+ <xsl:choose>
+ <xsl:when test="$firsttablerows[1]/@table:number-rows-repeated">
+ <xsl:value-of select="$row-num+ $firsttablerows[1]/@table:number-rows-repeated"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$row-num+1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-with-one-cellstyle-inatable">
+ <xsl:with-param name="row-num" select="$row-num-p"/>
+ <xsl:with-param name="firsttablerows" select="$firsttablerows[position()!=1]"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top !=''">
+ <xsl:value-of select="$rest-left-top "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="search-left-top-with-one-cellstyle-inarow">
+ <xsl:param name="row-num"/>
+ <xsl:param name="column-num"/>
+ <xsl:param name="firstcells"/>
+ <xsl:param name="cellstylename"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$firstcells and $return=''">
+ <xsl:variable name="firstcell" select="$firstcells[1]"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-with-one-cellstyle-inacell">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="column-num" select="$column-num"/>
+ <xsl:with-param name="cell" select="$firstcell"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="column-num-p">
+ <xsl:choose>
+ <xsl:when test="$firstcell/@table:number-columns-repeated">
+ <xsl:value-of select="$column-num+ $firstcell/@table:number-columns-repeated"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$column-num+ 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-with-one-cellstyle-inarow">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="column-num" select="$column-num-p"/>
+ <xsl:with-param name="firstcells" select="$firstcells[position()!=1]"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top !=''">
+ <xsl:value-of select="$rest-left-top "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="search-left-top-with-one-cellstyle-inacell">
+ <xsl:param name="row-num"/>
+ <xsl:param name="column-num"/>
+ <xsl:param name="cell"/>
+ <xsl:param name="cellstylename"/>
+ <xsl:choose>
+ <xsl:when test="$cell/@table:style-name">
+ <xsl:if test="$cell/@table:style-name=$cellstylename">
+ <xsl:value-of select="concat($cell/ancestor::table:table/@table:name,'.',$column-num,' ',$row-num)"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="style-is-default">
+ <xsl:call-template name="is-default-or-not">
+ <xsl:with-param name="column-num" select="$column-num"/>
+ <xsl:with-param name="cell" select="$cell"/>
+ <xsl:with-param name="preceding-cellstylename" select="''"/>
+ <xsl:with-param name="temp-num" select="'0'"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="table-columns" select="$cell/ancestor::table:table//table:table-column "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$style-is-default='yes' ">
+ <xsl:value-of select="concat($cell/ancestor::table:table/@table:name,'.',$column-num,' ',$row-num)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="is-default-or-not">
+ <xsl:param name="column-num"/>
+ <xsl:param name="cell"/>
+ <xsl:param name="preceding-cellstylename"/>
+ <xsl:param name="temp-num"/>
+ <xsl:param name="cellstylename"/>
+ <xsl:param name="table-columns"/>
+ <xsl:choose>
+ <xsl:when test="$temp-num&lt;$column-num">
+ <xsl:variable name="firstcolumn">
+ <xsl:choose>
+ <xsl:when test="$table-columns[1]/@table:number-columns-repeated">
+ <xsl:value-of select="$table-columns[1]/@table:number-columns-repeated"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'1'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="preceding-cellstylename-to-param">
+ <xsl:choose>
+ <xsl:when test="$table-columns[1]/@table:default-cell-style-name">
+ <xsl:value-of select="$table-columns[1]/@table:default-cell-style-name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="is-default-or-not">
+ <xsl:with-param name="column-num" select="$column-num"/>
+ <xsl:with-param name="temp-num" select="$temp-num + $firstcolumn"/>
+ <xsl:with-param name="preceding-cellstylename" select="$preceding-cellstylename-to-param"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="table-columns" select="$table-columns[position()!=1]"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$cellstylename=$preceding-cellstylename">
+ <xsl:value-of select="'yes'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'no'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="table:tracked-changes">
+ <xsl:for-each select="/office:document/office:body/office:spreadsheet/table:tracked-changes">
+ <xsl:if test="table:cell-content-change/table:cell-address">
+ <xsl:variable name="row" select="table:cell-content-change/table:cell-address/@table:row"/>
+ <xsl:variable name="column" select="table:cell-content-change/table:cell-address/@table:column"/>
+ <xsl:element name="字:修订开始">
+ <xsl:attribute name="uof:locID">t0206</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 类型 修订信息引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="concat($row,'-',$column)"/></xsl:attribute>
+ <xsl:attribute name="字:类型">format</xsl:attribute>
+ <xsl:if test="table:cell-content-change/office:change-info and table:cell-content-change/table:previous">
+ <xsl:variable name="creator" select="table:cell-content-change/office:change-info/dc:creator"/>
+ <xsl:variable name="date" select="table:cell-content-change/office:change-info/dc:date"/>
+ <xsl:variable name="text" select="table:cell-content-change/table:previous/table:change-track-table-cell/text:p"/>
+ <xsl:attribute name="字:修订信息引用"><xsl:value-of select="concat($creator,'+',$date,'%',$text)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="字:修订结束">
+ <xsl:attribute name="uof:locID">t0207</xsl:attribute>
+ <xsl:attribute name="uof:attrList">开始标识引用</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="office:font-face-decls">
+ <uof:字体集 uof:locID="u0040">
+ <xsl:for-each select="style:font-face">
+ <xsl:element name="uof:字体声明">
+ <xsl:attribute name="uof:attrList">标识符 名称 字体族</xsl:attribute>
+ <xsl:attribute name="uof:locID">u0041</xsl:attribute>
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="translate(@style:name,' ','_')"/></xsl:attribute>
+ <xsl:attribute name="uof:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="uof:字体族"><xsl:value-of select="@svg:font-family"/></xsl:attribute>
+ <!-- added by glu, for process special fonts e.g. Marlett, -->
+ <!--chengxz 060821 delete uof:字符集,because there is no this attr-->
+ <!--xsl:if test="@style:font-charset= '02'">
+ <xsl:attribute name="uof:字符集">x-symbol</xsl:attribute>
+ </xsl:if-->
+ <!--xsl:if test="@style:font-family-generic">
+ <xsl:choose>
+ <xsl:when test="@style:font-family-generic = 'swiss'">
+ <xsl:attribute name="uof:字体族">Swiss</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='modern'">
+ <xsl:attribute name="uof:字体族">Modern</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic='roman'">
+ <xsl:attribute name="uof:字体族">Roman</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='script'">
+ <xsl:attribute name="uof:字体族">Script</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='decorative'">
+ <xsl:attribute name="uof:字体族">Decorative</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='system'">
+ <xsl:attribute name="uof:字体族">System</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="uof:字体族">System</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if-->
+ <!--xsl:if test="@style:font-pitch">
+ <xsl:attribute name="uof:字号">12</xsl:attribute>
+ </xsl:if-->
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:apply-templates select="style:font-face"/>
+ </uof:字体集>
+ </xsl:template>
+ <xsl:key name="styles" match="/*/office:styles/style:style | /*/office:automatic-styles/style:style" use="@style:name"/>
+ <xsl:template match="style:style" mode="styles">
+ <xsl:param name="isAutomatic"/>
+ <xsl:param name="styleName" select="@style:name"/>
+ <xsl:choose>
+ <xsl:when test="@style:family='text'">
+ <xsl:element name="uof:句式样">
+ <xsl:attribute name="uof:locID">u0043</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">auto</xsl:attribute>
+ <xsl:call-template name="字:字体"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@style:family='paragraph'">
+ <xsl:element name="uof:段落式样">
+ <xsl:attribute name="uof:locID">u0044</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用 后继式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">auto</xsl:attribute>
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ </xsl:element>
+ <xsl:if test="style:text-properties">
+ <xsl:element name="uof:句式样">
+ <xsl:attribute name="uof:locID">u0043</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">custum</xsl:attribute>
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute>
+ <xsl:call-template name="字:字体"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="uof:单元格式样">
+ <xsl:attribute name="uof:locID">u0046</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型</xsl:attribute>
+ <xsl:attribute name="表:标识符"><xsl:value-of select="$styleName"/></xsl:attribute>
+ <xsl:attribute name="表:类型"><xsl:choose><xsl:when test="ancestor::office:automatic-styles">auto</xsl:when><xsl:when test="ancestor::office:styles">custom</xsl:when><xsl:otherwise>default</xsl:otherwise></xsl:choose></xsl:attribute>
+ <!--xsl:attribute name="表:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute-->
+ <xsl:choose>
+ <xsl:when test="style:map">
+ <xsl:attribute name="表:名称"><xsl:value-of select="style:map/@style:apply-style-name"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="表:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="not($isAutomatic)">
+ <xsl:choose>
+ <xsl:when test="$styleName='Default'">
+ <xsl:attribute name="表:名称"><xsl:value-of select="'Normal'"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="表:名称"><xsl:value-of select="$styleName"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <!--xsl:if test="@style:parent-style-name">
+ <xsl:attribute name="表:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute>
+ </xsl:if-->
+ <!--chengxz change the order-->
+ <xsl:variable name="styleProperties" select="key('styles', $styleName)/*"/>
+ <xsl:call-template name="Font">
+ <xsl:with-param name="styleProperties" select="$styleProperties"/>
+ </xsl:call-template>
+ <xsl:call-template name="Alignment">
+ <xsl:with-param name="styleProperties" select="$styleProperties"/>
+ </xsl:call-template>
+ <!--chenjh changed 1103-->
+ <!--xsl:if test="/*/office:automatic-styles/style:style[@style:name=/*/office:body/table:table/table:table-row/table:table-cell/@table:style-name]/style:properties/@fo:border"-->
+ <xsl:if test="@style:data-style-name">
+ <!--RedOffice Comment from Zengjh:UOF0020 2006-04-26-->
+ <xsl:call-template name="NumberFormat">
+ <xsl:with-param name="temp-style" select="@style:data-style-name"/>
+ </xsl:call-template>
+ <!--RedOffice comment (Zengjh) end-->
+ </xsl:if>
+ <xsl:call-template name="Border">
+ <xsl:with-param name="styleProperties" select="$styleProperties"/>
+ <!--xsl:with-param name="styleProperties" select="/*/office:automatic-styles/style:style"/-->
+ </xsl:call-template>
+ <!--/xsl:if-->
+ <!--chenjh end 1103-->
+ <xsl:call-template name="Interior">
+ <xsl:with-param name="styleProperties" select="$styleProperties"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="字:字体">
+ <xsl:element name="字:字体">
+ <xsl:attribute name="uof:locID">t0088</xsl:attribute>
+ <xsl:attribute name="uof:attrList">西文字体引用 中文字体引用 特殊字体引用 西文绘制 字号 相对字号 颜色</xsl:attribute>
+ <xsl:if test="style:text-properties/@fo:font-size or style:text-properties/@fo:font-size-asian or style:text-properties/@style:font-size-asian or style:text-properties/@style:font-size">
+ <xsl:attribute name="字:字号"><xsl:choose><xsl:when test="style:text-properties/@fo:font-size"><xsl:value-of select="substring-before(style:text-properties/@fo:font-size,'pt')"/></xsl:when><xsl:when test="style:text-properties/@fo:font-size-asian"><xsl:value-of select="substring-before(style:text-properties/@fo:font-size-asian,'pt')"/></xsl:when><xsl:when test="style:text-properties/@style:font-size-asian"><xsl:value-of select="substring-before(style:text-properties/@style:font-size-asian,'pt')"/></xsl:when><xsl:when test="style:text-properties/@style:font-size"><xsl:value-of select="substring-before(style:text-properties/@style:font-size,'pt')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:font-name">
+ <xsl:attribute name="字:西文字体引用"><xsl:value-of select="style:text-properties/@style:font-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:font-name-complex">
+ <xsl:attribute name="字:中文字体引用"><xsl:value-of select="style:text-properties/@style:font-name-complex"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select="style:text-properties/@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="style:text-properties/@fo:font-weight or style:text-properties/@style:font-weight-asian">
+ <xsl:element name="字:粗体">
+ <xsl:attribute name="uof:locID">t0089</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@style:font-weight-asian='bold' or style:text-properties/@fo:font-weight='bold'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:font-style or style:text-properties/@style:font-style-asian">
+ <xsl:element name="字:斜体">
+ <xsl:attribute name="uof:locID">t0090</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@fo:font-style='italic' or style:text-properties/@style:font-style-asian='italic'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-line-through-style and not(style:text-properties/@style:text-line-through-style='none')">
+ <xsl:element name="字:删除线">
+ <xsl:attribute name="uof:locID">t0094</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:delete线型类型"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-underline-style">
+ <xsl:element name="字:下划线">
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:线型类型"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0095</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:if test="style:text-properties/@style:text-underline-color">
+ <xsl:attribute name="字:颜色"><xsl:choose><xsl:when test="style:text-properties/@style:text-underline-color='font-color'">auto</xsl:when><xsl:otherwise><xsl:value-of select="style:text-properties/@style:text-underline-color"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:text-shadow">
+ <xsl:element name="字:阴影">
+ <xsl:attribute name="uof:locID">t0100</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@fo:text-shadow='none'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-position">
+ <xsl:element name="字:位置">
+ <xsl:attribute name="uof:locID">t0102</xsl:attribute>
+ <xsl:value-of select="style:text-properties/@style:text-position"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <!--RedOffice Comment from Zengjh:UOF0020 2006-04-01 Based on Original-->
+ <xsl:template name="NumberFormat">
+ <xsl:param name="temp-style"/>
+ <xsl:for-each select="(/*/office:styles/child::*[@style:name=$temp-style]) | (/*/office:automatic-styles/child::*[@style:name=$temp-style])">
+ <表:数字格式 uof:locID="s0021" uof:attrList="分类名称 格式码">
+ <xsl:attribute name="表:分类名称"><xsl:choose><xsl:when test="name(.)='number:currency-style'">currency</xsl:when><xsl:when test="name(.)='number:percentage-style'">percentage</xsl:when><xsl:when test="name(.)='number:date-style'">date</xsl:when><xsl:when test="name(.)='number:time-style'">time</xsl:when><xsl:when test="name(.)='number:boolean-style'">custom</xsl:when><xsl:when test="name(.)='number:text-style'">text</xsl:when><xsl:when test="name(.)='number:number-style'"><xsl:choose><xsl:when test="number:fraction">fraction</xsl:when><xsl:when test="number:scientific-number">scientific</xsl:when><xsl:otherwise>number</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>general</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:格式码"><xsl:call-template name="element-attribute"/><xsl:for-each select="style:map"><xsl:text>[</xsl:text><xsl:value-of select="@style:condition"/><xsl:text>]</xsl:text><xsl:variable name="apply-style" select="@style:apply-style-name"/><xsl:for-each select="../../child::*[@style:name=$apply-style]/*"><xsl:call-template name="general-number-format"/></xsl:for-each><xsl:text>;</xsl:text></xsl:for-each><xsl:for-each select="*[not(name(.)='style:map')]"><xsl:call-template name="general-number-format"/></xsl:for-each></xsl:attribute>
+ </表:数字格式>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="general-number-format">
+ <xsl:choose>
+ <xsl:when test="name(.)='style:text-properties'">
+ <xsl:call-template name="general-color-format"/>
+ </xsl:when>
+ <xsl:when test="name(.)='number:text'">&quot;<xsl:value-of select="text()"/>&quot;</xsl:when>
+ <xsl:when test="name(.)='number:text-content' ">@</xsl:when>
+ <xsl:when test="name(.)='number:boolean'">boolean</xsl:when>
+ <xsl:when test="name(.)='number:currency-symbol'">
+ <xsl:call-template name="general-currency-format"/>
+ </xsl:when>
+ <xsl:when test="name(.)='number:fraction' or name(.)='number:number' or name(.)='number:scientific-number'">
+ <xsl:if test="@number:min-integer-digits and not(@number:grouping)">
+ <xsl:choose>
+ <xsl:when test="@number:min-integer-digits='0'">#</xsl:when>
+ <xsl:when test="@number:min-integer-digits='1'">0</xsl:when>
+ <xsl:when test="@number:min-integer-digits='2'">00</xsl:when>
+ <xsl:when test="@number:min-integer-digits='3'">000</xsl:when>
+ <xsl:when test="@number:min-integer-digits='4'">0000</xsl:when>
+ <xsl:when test="@number:min-integer-digits='5'">00000</xsl:when>
+ <xsl:when test="@number:min-integer-digits='6'">000000</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@number:min-integer-digits and @number:grouping">
+ <xsl:choose>
+ <xsl:when test="@number:min-integer-digits='0'">#,###</xsl:when>
+ <xsl:when test="@number:min-integer-digits='1'">#,##0</xsl:when>
+ <xsl:when test="@number:min-integer-digits='2'">#,#00</xsl:when>
+ <xsl:when test="@number:min-integer-digits='3'">#,000</xsl:when>
+ <xsl:when test="@number:min-integer-digits='4'">##0,000</xsl:when>
+ <xsl:when test="@number:min-integer-digits='5'">#00,000</xsl:when>
+ <xsl:when test="@number:min-integer-digits='6'">#,000,000</xsl:when>
+ <xsl:when test="@number:min-integer-digits='7'">##0,000,000</xsl:when>
+ <xsl:when test="@number:min-integer-digits='8'">#,#00,000,000</xsl:when>
+ <xsl:otherwise>#,##0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@number:decimal-places and not(@number:decimal-replacement)">
+ <xsl:choose>
+ <xsl:when test="@number:decimal-places='0'"/>
+ <xsl:when test="@number:decimal-places='1'">.0</xsl:when>
+ <xsl:when test="@number:decimal-places='2'">.00</xsl:when>
+ <xsl:when test="@number:decimal-places='3'">.000</xsl:when>
+ <xsl:when test="@number:decimal-places='4'">.0000</xsl:when>
+ <xsl:when test="@number:decimal-places='5'">.00000</xsl:when>
+ <xsl:when test="@number:decimal-places='6'">.000000</xsl:when>
+ <xsl:otherwise>.00</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@number:decimal-places and @number:decimal-replacement">
+ <xsl:choose>
+ <xsl:when test="@number:decimal-places='0'"/>
+ <xsl:when test="@number:decimal-places='1'">.#</xsl:when>
+ <xsl:when test="@number:decimal-places='2'">.##</xsl:when>
+ <xsl:when test="@number:decimal-places='3'">.###</xsl:when>
+ <xsl:when test="@number:decimal-places='4'">.####</xsl:when>
+ <xsl:when test="@number:decimal-places='5'">.#####</xsl:when>
+ <xsl:when test="@number:decimal-places='6'">.######</xsl:when>
+ <xsl:otherwise>.##</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@number:display-factor">
+ <xsl:choose>
+ <xsl:when test="@number:display-factor='1000'">,</xsl:when>
+ <xsl:when test="@number:display-factor='1000000'">,,</xsl:when>
+ <xsl:when test="@number:display-factor='1000000000'">,,,</xsl:when>
+ <xsl:when test="@number:display-factor='1000000000000000'">,,,,</xsl:when>
+ <xsl:when test="@number:display-factor='1000000000000000000'">,,,,,</xsl:when>
+ <xsl:when test="@number:display-factor='1000000000000000000000'">,,,,,</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@number:min-exponent-digits">
+ <xsl:choose>
+ <xsl:when test="@number:min-exponent-digits='1'">E+0</xsl:when>
+ <xsl:when test="@number:min-exponent-digits='2'">E+00</xsl:when>
+ <xsl:when test="@number:min-exponent-digits='3'">E+000</xsl:when>
+ <xsl:when test="@number:min-exponent-digits='4'">E+0000</xsl:when>
+ <xsl:when test="@number:min-exponent-digits='5'">E+00000</xsl:when>
+ <xsl:when test="@number:min-exponent-digits='6'">E+000000</xsl:when>
+ <xsl:otherwise>E+00</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@number:min-numerator-digits">
+ <xsl:choose>
+ <xsl:when test="@number:min-numerator-digits='1' "> ?</xsl:when>
+ <xsl:when test="@number:min-numerator-digits='2' "> ??</xsl:when>
+ <xsl:when test="@number:min-numerator-digits='3' "> ???</xsl:when>
+ <xsl:when test="@number:min-numerator-digits='4' "> ????</xsl:when>
+ <xsl:when test="@number:min-numerator-digits='5' "> ?????</xsl:when>
+ <xsl:when test="@number:min-numerator-digits='6' "> ??????</xsl:when>
+ <xsl:otherwise> ???</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@number:min-denominator-digits">
+ <xsl:choose>
+ <xsl:when test="@number:min-denominator-digits='1' ">/?</xsl:when>
+ <xsl:when test="@number:min-denominator-digits='2' ">/??</xsl:when>
+ <xsl:when test="@number:min-denominator-digits='3' ">/???</xsl:when>
+ <xsl:when test="@number:min-denominator-digits='4' ">/????</xsl:when>
+ <xsl:when test="@number:min-denominator-digits='5' ">/?????</xsl:when>
+ <xsl:when test="@number:min-denominator-digits='6' ">/??????</xsl:when>
+ <xsl:otherwise>/???</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="name(.)='number:year'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long'">YYYY</xsl:when>
+ <xsl:otherwise>YY</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(.)='number:month'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long' and @number:textual='true'">MMMM</xsl:when>
+ <xsl:when test="not(@number:style='long') and @number:textual='true'">MMM</xsl:when>
+ <xsl:when test="@number:style='long' and not(@number:textual)">MM</xsl:when>
+ <xsl:when test="not(@number:style='long') and not(@number:textual)">M</xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(.)='number:day'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long'">DD</xsl:when>
+ <xsl:otherwise>D</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(.)='number:day-of-week'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long'">NNNN</xsl:when>
+ <xsl:otherwise>NNN</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(.)='number:quarter'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long'">QQ</xsl:when>
+ <xsl:otherwise>Q</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(.)='number:hours'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long' and ../@number:truncate-on-overflow='false'">[HH]</xsl:when>
+ <xsl:when test="@number:style='long'">HH</xsl:when>
+ <xsl:otherwise>H</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(.)='number:minutes'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long'">MM</xsl:when>
+ <xsl:otherwise>M</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(.)='number:seconds'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long' and @number:decimal-places='2'">SS.00</xsl:when>
+ <xsl:when test="@number:style='long'">SS</xsl:when>
+ <xsl:otherwise>S</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name(.)='number:am-pm'">AM/PM</xsl:when>
+ <xsl:when test="name(.)='number:week-of-year'">
+ <xsl:choose>
+ <xsl:when test="@number:style='long'">WW</xsl:when>
+ <xsl:otherwise>WW</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="general-color-format">
+ <xsl:choose>
+ <xsl:when test="@fo:color='#000000'">[Black]</xsl:when>
+ <xsl:when test="@fo:color='#0000ff'">[Blue]</xsl:when>
+ <xsl:when test="@fo:color='#00ffff'">[Cyan]</xsl:when>
+ <xsl:when test="@fo:color='#00ff00'">[Green]</xsl:when>
+ <xsl:when test="@fo:color='#ff00ff'">[Magenta]</xsl:when>
+ <xsl:when test="@fo:color='#ff0000'">[Red]</xsl:when>
+ <xsl:when test="@fo:color='#ffffff'">[White]</xsl:when>
+ <xsl:when test="@fo:color='#ffff00'">[Yellow]</xsl:when>
+ <xsl:otherwise>[Black]</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="general-currency-format">
+ <xsl:choose>
+ <xsl:when test="text()='¥' and @number:language='zh' and @number:country='CN'">[$¥-804]</xsl:when>
+ <xsl:when test="text()='$' and @number:language='en' and @number:country='US'">[$$-409]</xsl:when>
+ <xsl:when test="text()='$' and @number:language='es' and @number:country='AR'">[$$-2C0A]</xsl:when>
+ <xsl:when test="text()='$' and @number:language='fr' and @number:country='CA'">[$$-C0C]</xsl:when>
+ <xsl:when test="text()='CNY'">[$CNY]</xsl:when>
+ <xsl:when test="text()='AFA'">[$AFA]</xsl:when>
+ <xsl:when test="text()='CCC'">CCC</xsl:when>
+ <xsl:otherwise>¥</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="element-attribute">
+ <xsl:if test="@number:transliteration-format='一' and @number:transliteration-style='short'">[NatNum1]</xsl:if>
+ <xsl:if test="@number:transliteration-format='一' and @number:transliteration-style='medium'">[NatNum7]</xsl:if>
+ <xsl:if test="@number:transliteration-format='一' and @number:transliteration-style='long'">[NatNum4]</xsl:if>
+ <xsl:if test="@number:transliteration-format='壹' and @number:transliteration-style='short'">[NatNum2]</xsl:if>
+ <xsl:if test="@number:transliteration-format='壹' and @number:transliteration-style='medium'">[NatNum8]</xsl:if>
+ <xsl:if test="@number:transliteration-format='壹' and @number:transliteration-style='long'">[NatNum5]</xsl:if>
+ <xsl:if test="@number:transliteration-format='1' and @number:transliteration-style='short'">[NatNum3]</xsl:if>
+ <xsl:if test="@number:transliteration-format='1' and @number:transliteration-style='medium'">[NatNum0]</xsl:if>
+ <xsl:if test="@number:transliteration-format='1' and @number:transliteration-style='long'">[NatNum6]</xsl:if>
+ <xsl:if test="@number:transliteration-format='1' and @number:transliteration-style='short'">[NatNum0]</xsl:if>
+ <xsl:if test="@number:transliteration-format='1' and @number:transliteration-style='medium'">[NatNum0]</xsl:if>
+ <xsl:if test="@number:transliteration-format='1' and @number:transliteration-style='long'">[NatNum0]</xsl:if>
+ <xsl:if test="@number:transliteration-language='zh' and @number:transliteration-country='CN'">[$-804]</xsl:if>
+ </xsl:template>
+ <!--RedOffice comment (Zengjh) end-->
+ <!--huangzf0715-->
+ <xsl:template name="Alignment">
+ <xsl:param name="styleProperties"/>
+ <xsl:if test="($styleProperties/@fo:text-align) or ($styleProperties/@style:vertical-align) or ($styleProperties/@fo:wrap-option) or($styleProperties/@fo:margin-left) or ($styleProperties/@style:rotation-angle) or ($styleProperties/@style:direction)">
+ <xsl:element name="表:对齐格式">
+ <xsl:attribute name="uof:locID">s0114</xsl:attribute>
+ <xsl:if test="$styleProperties/@fo:margin-left">
+ <xsl:attribute name="表:缩进"><xsl:variable name="margin"><xsl:call-template name="convert2pt"><xsl:with-param name="value" select="$styleProperties/@fo:margin-left"/><xsl:with-param name="rounding-factor" select="1"/></xsl:call-template></xsl:variable><xsl:value-of select="number($margin) div 10"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="表:水平对齐方式">
+ <xsl:attribute name="uof:locID">s0115</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@fo:text-align">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@fo:text-align = 'center'">center</xsl:when>
+ <xsl:when test="$styleProperties/@fo:text-align = 'end'">right</xsl:when>
+ <xsl:when test="$styleProperties/@fo:text-align = 'justify'">justify</xsl:when>
+ <xsl:when test="$styleProperties/@fo:text-align = 'start'">left</xsl:when>
+ <xsl:otherwise>fill</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>general</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="($styleProperties/@style:vertical-align) or ($styleProperties/@fo:vertical-align)">
+ <xsl:element name="表:垂直对齐方式">
+ <xsl:attribute name="uof:locID">s0116</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@fo:vertical-align = 'top'">top</xsl:when>
+ <xsl:when test="$styleProperties/@fo:vertical-align = 'bottom'">bottom</xsl:when>
+ <xsl:when test="$styleProperties/@fo:vertical-align = 'middle'">center</xsl:when>
+ <xsl:when test="$styleProperties/@fo:vertical-align = 'justify'">justify</xsl:when>
+ <xsl:when test="$styleProperties/@fo:vertical-align = 'top'">top</xsl:when>
+ <xsl:otherwise>distributed</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="表:文字方向">
+ <xsl:attribute name="uof:locID">s0118</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:direction = 'ttb'">vertical</xsl:when>
+ <xsl:otherwise>horizontal</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="$styleProperties/@style:rotation-angle">
+ <xsl:element name="表:文字旋转角度">
+ <xsl:attribute name="uof:locID">s0119</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:rotation-angle &gt; 90">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:rotation-angle &gt;= 270">
+ <xsl:value-of select="$styleProperties/@style:rotation-angle - 360"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:rotation-angle - 180"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$styleProperties/@style:rotation-angle &lt; -90">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:rotation-angle &lt;= -270">
+ <xsl:value-of select="$styleProperties/@style:rotation-angle + 360"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:rotation-angle + 180"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:rotation-angle"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:wrap-option = 'wrap'">
+ <xsl:element name="表:自动换行">
+ <xsl:attribute name="uof:locID">s0120</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="表:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:shrink-to-fit">
+ <xsl:element name="表:缩小字体填充">
+ <xsl:attribute name="uof:locID">s0121</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="表:值"><xsl:value-of select="$styleProperties/@style:shrink-to-fit"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="Font">
+ <xsl:param name="styleProperties"/>
+ <!--xsl:if test="(style:text-properties/@fo:font-weight) or (style:text-properties/@fo:color) or ($styleProperties/@style:font-name) or ($styleProperties/@fo:font-style) or ($styleProperties/@style:text-outline) or ($styleProperties/@style:text-shadow) or ($styleProperties/@style:font-size) or ($styleProperties/@style:text-crossing-out) or ($styleProperties/@style:text-underline) or ($styleProperties/@style:text-underline-style) or ($styleProperties/@style:text-position)"-->
+ <xsl:if test="not(@style:name='Default')">
+ <xsl:element name="表:字体格式">
+ <xsl:attribute name="uof:locID">s0113</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:if test="$styleProperties/@fo:font-weight or $styleProperties/@style:font-weight-asian">
+ <xsl:element name="字:粗体">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="$styleProperties/@style:font-weight-asian='bold' or $styleProperties/@fo:font-weight='bold'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0089</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:font-style or $styleProperties/@style:font-style-asian">
+ <xsl:element name="字:斜体">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="$styleProperties/@fo:font-style='italic' or $styleProperties/@style:font-style-asian='italic'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0090</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-outline = 'true'">
+ <字:空心 uof:locID="t0098" uof:attrList="值" 字:值="true"/>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-shadow = 'shadow'">
+ <字:阴影 uof:locID="t0100" uof:attrList="值" 字:值="true"/>
+ </xsl:if>
+ <xsl:if test="(style:text-properties/@style:text-underline-style) and ($styleProperties/@style:text-underline-style != 'none')">
+ <xsl:element name="字:下划线">
+ <xsl:attribute name="uof:locID">t0095</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 颜色 字下划线</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:线型类型"/></xsl:attribute>
+ <xsl:attribute name="字:字下划线">true</xsl:attribute>
+ <xsl:if test="$styleProperties/@style:text-underline-color">
+ <xsl:attribute name="字:颜色"><xsl:choose><xsl:when test="$styleProperties/@style:text-underline-color='font-color'">auto</xsl:when><xsl:otherwise><xsl:value-of select="$styleProperties/@style:text-underline-color"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-line-through-style and not($styleProperties/@style:text-line-through-style='none')">
+ <xsl:element name="字:删除线">
+ <xsl:attribute name="uof:locID">t0094</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:delete线型类型"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-emphasize">
+ <xsl:element name="字:着重号">
+ <xsl:attribute name="uof:locID">t0096</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 颜色 字着重号</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:text-emphasize='none'">
+ <xsl:attribute name="字:字着重号">false</xsl:attribute>
+ <xsl:attribute name="字:类型">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:字着重号">true</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:着重号类型"><xsl:with-param name="te" select="$styleProperties/@style:text-emphasize"/></xsl:call-template></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$styleProperties/@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select="$styleProperties/@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:text-position">
+ <xsl:element name="字:上下标">
+ <xsl:choose>
+ <xsl:when test="substring-before($styleProperties/@style:text-position, '% ') &gt; 0">
+ <xsl:attribute name="字:上下标">sup</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:上下标">sub</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:字体">
+ <xsl:attribute name="uof:locID">t0088</xsl:attribute>
+ <xsl:attribute name="uof:attrList">西文字体引用 中文字体引用 特殊字体引用 西文绘制 字号 相对字号 颜色</xsl:attribute>
+ <xsl:if test="$styleProperties/@style:font-name-asian">
+ <xsl:attribute name="字:中文字体引用"><xsl:value-of select="translate($styleProperties/@style:font-name-asian,' ','_')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@style:font-name or $styleProperties/@fo:font-family">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:font-name">
+ <xsl:attribute name="字:西文字体引用"><xsl:value-of select="translate($styleProperties/@style:font-name,' ','_')"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:西文字体引用"><xsl:value-of select="translate($styleProperties/@fo:font-family,' ','_')"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$styleProperties/@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select="$styleProperties/@fo:color"/></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@fo:font-size">
+ <xsl:attribute name="字:字号"><xsl:call-template name="convert2pt"><xsl:with-param name="value" select="$styleProperties/@fo:font-size"/></xsl:call-template></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$styleProperties/@style:font-size-asian">
+ <xsl:attribute name="字:字号"><xsl:call-template name="convert2pt"><xsl:with-param name="value" select="$styleProperties/@style:font-size-asian"/></xsl:call-template></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$styleProperties/@style:font-size-complex">
+ <xsl:attribute name="字:字号"><xsl:call-template name="convert2pt"><xsl:with-param name="value" select="$styleProperties/@style:font-size-complex"/></xsl:call-template></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="style:text-properties/@style:font-relief">
+ <xsl:element name="字:浮雕">
+ <xsl:attribute name="uof:locID">t0099</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test="style:text-properties/@style:font-relief='embossed'">emboss</xsl:when><xsl:when test="style:text-properties/@style:font-relief='engraved'">engrave</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:text-transform or style:text-properties/@fo:font-variant">
+ <xsl:element name="字:醒目字体">
+ <xsl:attribute name="uof:locID">t0101</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test="style:text-properties/@fo:text-transform='uppercase'">uppercase</xsl:when><xsl:when test="style:text-properties/@fo:text-transform='lowercase'">lowercase</xsl:when><xsl:when test="style:text-properties/@fo:text-transform='capitalize'">capital</xsl:when><xsl:when test="style:text-properties/@fo:font-variant='small-caps'">small-caps</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:text-shadow">
+ <xsl:element name="字:阴影">
+ <xsl:attribute name="uof:locID">t0100</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@fo:text-shadow='none'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="Border">
+ <xsl:param name="styleProperties"/>
+ <xsl:if test="style:table-cell-properties/@fo:border and not($styleProperties/@fo:border-top or $styleProperties/@fo:border-left or $styleProperties/@fo:border-bottom or $styleProperties/@fo:border-right)">
+ <xsl:element name="表:边框">
+ <xsl:attribute name="uof:locID">s0022</xsl:attribute>
+ <xsl:variable name="border">
+ <xsl:value-of select="$styleProperties/@fo:border"/>
+ </xsl:variable>
+ <xsl:element name="uof:左">
+ <xsl:attribute name="uof:locID">u0057</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($border,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='double'">double</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dotted'">dotted</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dashed'">dash</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$border!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($border,' '),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($border,' '),' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains(substring-before(substring-after($styleProperties/@style:shadow,' '),' '),'-')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="uof:上">
+ <xsl:attribute name="uof:locID">u0058</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($border,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='double'">double</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dotted'">dotted</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dashed'">dash</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$border!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($border,' '),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($border,' '),' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains(substring-after(substring-after($styleProperties/@style:shadow,' '),' '),'-')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="uof:右">
+ <xsl:attribute name="uof:locID">u0059</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($border,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='double'">double</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dotted'">dotted</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dashed'">dash</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$border!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($border,' '),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($border,' '),' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="substring-before(substring-before(substring-after($styleProperties/@style:shadow,' '),' '),$uofUnit) &gt;0 or contains(substring-before(substring-after($styleProperties/@style:shadow,' '),' '),'+')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="uof:下">
+ <xsl:attribute name="uof:locID">u0060</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($border,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='double'">double</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dotted'">dotted</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dashed'">dash</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$border!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($border,' '),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($border,' '),' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="substring-before(substring-after(substring-after($styleProperties/@style:shadow,' '),' '),$uofUnit) &gt;0 or contains(substring-after(substring-after($styleProperties/@style:shadow,' '),' '),'+')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="$styleProperties/@style:diagonal-bl-tr">
+ <xsl:element name="uof:对角线1">
+ <xsl:attribute name="uof:locID">u0061</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="border-width">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:diagonal-bl-tr !='none'">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="substring-before($styleProperties/@style:diagonal-bl-tr, ' ')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:diagonal-bl-tr" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="border-style" select="substring-before(substring-after($styleProperties/@style:diagonal-bl-tr, ' '), ' ')"/>
+ <xsl:variable name="border-color" select="substring-after(substring-after($styleProperties/@style:diagonal-bl-tr, ' '), ' ')"/>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border-style = 'none'">none</xsl:when><xsl:when test="$border-style = 'none'">none</xsl:when><xsl:when test="$border-style='solid'">single</xsl:when><xsl:when test="$border-style='double'">double</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="$border-width"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:choose><xsl:when test="$border-color"><xsl:value-of select="$border-color"/></xsl:when><xsl:otherwise>Automatic</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <!--end of uo:对角线1-->
+ <!--xsl:if test="$styleProperties/@fo:border and $styleProperties/@style:diagonal-tl-br"-->
+ <xsl:if test="$styleProperties/@style:diagonal-tl-br">
+ <xsl:element name="uof:对角线2">
+ <xsl:attribute name="uof:locID">u0062</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="border-width">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:diagonal-tl-br !='none'">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="substring-before($styleProperties/@style:diagonal-tl-br, ' ')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:diagonal-tl-br" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="border-style" select="substring-before(substring-after($styleProperties/@style:diagonal-tl-br, ' '), ' ')"/>
+ <xsl:variable name="border-color" select="substring-after(substring-after($styleProperties/@style:diagonal-tl-br, ' '), ' ')"/>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border-style = 'none'">none</xsl:when><xsl:when test="$border-style = 'none'">none</xsl:when><xsl:when test="$border-style='solid'">single</xsl:when><xsl:when test="$border-style='double'">double</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="$border-width"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:choose><xsl:when test="$border-color"><xsl:value-of select="$border-color"/></xsl:when><xsl:otherwise>Automatic</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <!--end of uo:对角线2-->
+ </xsl:element>
+ </xsl:if>
+ <!--end of fo:border-->
+ <xsl:if test="$styleProperties/@fo:border-top or $styleProperties/@fo:border-left or $styleProperties/@fo:border-bottom or $styleProperties/@fo:border-right or $styleProperties/@style:diagonal-tl-br or $styleProperties/@style:diagonal-bl-tr">
+ <xsl:element name="表:边框">
+ <xsl:attribute name="uof:locID">s0022</xsl:attribute>
+ <xsl:if test="$styleProperties/@fo:border-left or $styleProperties/@style:shadow">
+ <xsl:element name="uof:左">
+ <xsl:attribute name="uof:locID">u0057</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="borderleft">
+ <xsl:value-of select="$styleProperties/@fo:border-left"/>
+ </xsl:variable>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$borderleft!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($borderleft,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($borderleft,' '),' ')='double'">double</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$borderleft!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($borderleft,' '),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($borderleft,' '),' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains(substring-before(substring-after($styleProperties/@style:shadow,' '),' '),'-')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <!--end of uof:左-->
+ <xsl:if test="$styleProperties/@fo:border-top or $styleProperties/@style:shadow">
+ <xsl:element name="uof:上">
+ <xsl:attribute name="uof:locID">u0058</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="bordertop">
+ <xsl:value-of select="$styleProperties/@fo:border-top"/>
+ </xsl:variable>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$bordertop!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($bordertop,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($bordertop,' '),' ')='double'">double</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$bordertop!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($bordertop,' '),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($bordertop,' '),' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains(substring-after(substring-after($styleProperties/@style:shadow,' '),' '),'-')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <!--end of uof:上-->
+ <xsl:if test="$styleProperties/@fo:border-right or $styleProperties/@style:shadow">
+ <xsl:element name="uof:右">
+ <xsl:attribute name="uof:locID">u0059</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="borderright">
+ <xsl:value-of select="$styleProperties/@fo:border-right"/>
+ </xsl:variable>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$borderright!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($borderright,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($borderright,' '),' ')='double'">double</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$borderright!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($borderright,' '),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($borderright,' '),' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="substring-before(substring-before(substring-after($styleProperties/@style:shadow,' '),' '),$uofUnit)&gt;0 or contains(substring-before(substring-after($styleProperties/@style:shadow,' '),' '),'+')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <!--end of uof:右-->
+ <xsl:if test="$styleProperties/@fo:border-bottom or $styleProperties/@style:shadow">
+ <xsl:element name="uof:下">
+ <xsl:attribute name="uof:locID">u0060</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="borderbottom">
+ <xsl:value-of select="$styleProperties/@fo:border-bottom"/>
+ </xsl:variable>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$borderbottom!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($borderbottom,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($borderbottom,' '),' ')='double'">double</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$borderbottom!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($borderbottom,' '),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($borderbottom,' '),' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="substring-before(substring-after(substring-after($styleProperties/@style:shadow,' '),' '),$uofUnit) &gt;0 or contains(substring-after(substring-after($styleProperties/@style:shadow,' '),' '),'+')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <!--end of uof:下-->
+ <xsl:if test="$styleProperties/@style:diagonal-bl-tr">
+ <xsl:element name="uof:对角线1">
+ <xsl:attribute name="uof:locID">u0061</xsl:attribute>
+ <xsl:attribute name="attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="border-width">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:diagonal-bl-tr !='none'">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="substring-before($styleProperties/@style:diagonal-bl-tr, ' ')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:diagonal-bl-tr" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="border-style" select="substring-before(substring-after($styleProperties/@style:diagonal-bl-tr, ' '), ' ')"/>
+ <xsl:variable name="border-color" select="substring-after(substring-after($styleProperties/@style:diagonal-bl-tr, ' '), ' ')"/>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border-style = 'none'">none</xsl:when><xsl:when test="$border-style='solid'">single</xsl:when><xsl:when test="$border-style='double'">double</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="$border-width"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:choose><xsl:when test="$border-color"><xsl:value-of select="$border-color"/></xsl:when><xsl:otherwise>Automatic</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <!--end of uo:对角线1-->
+ <xsl:if test="$styleProperties/@style:diagonal-tl-br">
+ <xsl:element name="uof:对角线2">
+ <xsl:attribute name="uof:locID">u0062</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="border-width">
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@style:diagonal-tl-br !='none'">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="substring-before($styleProperties/@style:diagonal-tl-br, ' ')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$styleProperties/@style:diagonal-tl-br" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="border-style" select="substring-before(substring-after($styleProperties/@style:diagonal-tl-br, ' '), ' ')"/>
+ <xsl:variable name="border-color" select="substring-after(substring-after($styleProperties/@style:diagonal-tl-br, ' '), ' ')"/>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border-style = 'none'">none</xsl:when><xsl:when test="$border-style='solid'">single</xsl:when><xsl:when test="$border-style='double'">double</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="$border-width"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:choose><xsl:when test="$border-color"><xsl:value-of select="$border-color"/></xsl:when><xsl:otherwise>Automatic</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <!--end of uo:对角线2-->
+ </xsl:element>
+ <!--end of 表:边框-->
+ </xsl:if>
+ <!--chenjh 边框 E -->
+ </xsl:template>
+ <xsl:template name="border-attributes">
+ <xsl:param name="border_properties"/>
+ <xsl:attribute name="attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:variable name="border-width">
+ <xsl:choose>
+ <xsl:when test="$border_properties !='none'">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="substring-before($border_properties, ' ')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$border_properties" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="border-style" select="substring-before(substring-after($border_properties, ' '), ' ')"/>
+ <xsl:variable name="border-color" select="substring-after(substring-after($border_properties, ' '), ' ')"/>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border-style = 'none'">none</xsl:when><xsl:otherwise><xsl:value-of select="$border-style"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="$border-width"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:choose><xsl:when test="$border-color"><xsl:value-of select="$border-color"/></xsl:when><xsl:otherwise>Automatic</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:template>
+ <xsl:template name="Interior">
+ <xsl:param name="styleProperties"/>
+ <xsl:if test="style:table-cell-properties/@fo:background-color and not($styleProperties/@fo:background-color = 'transparent')">
+ <xsl:element name="表:填充">
+ <!--chenp modify redo0000047-->
+ <xsl:attribute name="uof:locID">s0058</xsl:attribute>
+ <!--0821 by lil -->
+ <xsl:choose>
+ <xsl:when test="$styleProperties/@fo:background-color">
+ <xsl:element name="图:颜色">
+ <xsl:attribute name="uof:locID">g0034</xsl:attribute>
+ <xsl:value-of select="$styleProperties/@fo:background-color"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="表:图案">
+ <xsl:value-of select="' Solid'"/>
+ <xsl:attribute name="xsl:lodID">g0036</xsl:attribute>
+ <xsl:attribute name="attrList">类型 图形引用 前景色 背景色</xsl:attribute>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--end-->
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <!--chengxz 0621 E-->
+ <!--xsl:template name="image">
+
+ <xsl:element name="图:图形">
+ <xsl:attribute name="图:标识符"><xsl:value-of select="@draw:name"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">g0000</xsl:attribute>
+ <xsl:attribute name="uof:attrList">层次 标识符 组合列表 其他对象</xsl:attribute>
+ <xsl:element name="图:预定义图形">
+ <xsl:attribute name="uof:locID">g0005</xsl:attribute>
+ <xsl:element name="图:类别">图片</xsl:element>
+ <xsl:element name="图:生成软件"><xsl:value-of select="office:binary-data" ></xsl:value-of></xsl:element>
+ <xsl:element name="图:属性">
+ <xsl:element name="图:宽度"><xsl:value-of select="substring-before(@svg:width,'cm')"/></xsl:element>
+ <xsl:element name="图:高度"><xsl:value-of select="substring-before(@svg:height,'cm')"/></xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template-->
+ <!--1新增内容-->
+ <xsl:key match="/office:document/office:automatic-styles/style:style | /office:document/office:styles/style:style" name="graphicset" use="@style:name"/>
+ <xsl:template name="draw">
+ <xsl:param name="nodename1"/>
+ <xsl:choose>
+ <xsl:when test="substring-after($nodename1,':') = 'a'">
+ <xsl:for-each select="child::*">
+ <xsl:call-template name="draw">
+ <xsl:with-param name="nodename">
+ <xsl:value-of select="name()"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="substring-after($nodename1,':') = 'g'">
+ <xsl:call-template name="draw:g"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="draw:g">
+ <!--xsl:variable name="picnumber1">
+ <xsl:value-of select="count(preceding::draw:g)"/>
+ </xsl:variable>
+ <图:图形 uof:locID="g0000" uof:attrList="层次 标识符 组合列表 其他对象">
+ <xsl:attribute name="图:标识符"><xsl:value-of select="concat(@draw:style-name,'_',$picnumber1)"/></xsl:attribute>
+ <xsl:attribute name="图:层次"><xsl:value-of select="@draw:z-index"/></xsl:attribute>
+ <xsl:attribute name="图:组合列表"><xsl:for-each select="child::*[1]"><xsl:variable name="node1"><xsl:value-of select="@draw:style-name"/></xsl:variable><xsl:variable name="picnumber2"><xsl:value-of select="count(preceding::*[@draw:style-name=$node1])"/></xsl:variable><xsl:call-template name="zuheliebiao"><xsl:with-param name="allnode"><xsl:value-of select="concat($node1,'_',$picnumber2)"/></xsl:with-param><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:for-each></xsl:attribute>
+ </图:图形>
+ <xsl:for-each select="child::*">
+ <xsl:choose>
+ <xsl:when test="name()='draw:g'">
+ <xsl:call-template name="draw:g"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each-->
+ <!--根据新修改的Schema做的修改-->
+ <xsl:for-each select="child::*">
+ <xsl:choose>
+ <xsl:when test="name()='draw:g'">
+ <xsl:call-template name="draw:g"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:template>
+ <xsl:template name="zuheliebiao">
+ <xsl:param name="allnode"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="../child::*[$pos]">
+ <xsl:for-each select="../child::*[$pos]">
+ <xsl:variable name="nodepos">
+ <!--add by lvxg -->
+ <xsl:choose>
+ <xsl:when test="./@draw:style-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@draw:id"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--end-->
+ </xsl:variable>
+ <xsl:variable name="picnumber1">
+ <xsl:value-of select="count(preceding::*[@draw:style-name=$nodepos])"/>
+ </xsl:variable>
+ <xsl:variable name="pic-name1">
+ <xsl:value-of select="concat($nodepos,'_',$picnumber1)"/>
+ </xsl:variable>
+ <xsl:variable name="allnode1">
+ <xsl:value-of select="concat($allnode,',',$pic-name1)"/>
+ </xsl:variable>
+ <xsl:call-template name="zuheliebiao">
+ <xsl:with-param name="allnode" select="$allnode1"/>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$allnode"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="creategraphicstyles">
+ <xsl:variable name="nodename">
+ <xsl:value-of select="name()"/>
+ </xsl:variable>
+ <xsl:variable name="pic-name">
+ <xsl:choose>
+ <xsl:when test="./@draw:style-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:when>
+ <xsl:when test="./@table:end-cell-address">
+ <xsl:value-of select="@table:end-cell-address"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./@draw:id"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--end -->
+ </xsl:variable>
+ <xsl:variable name="pic-num">
+ <xsl:value-of select="count(/descendant::*[@draw:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:variable name="picnumber">
+ <xsl:value-of select="count(preceding::*[@draw:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:call-template name="pic-process">
+ <xsl:with-param name="pic-name" select="$pic-name"/>
+ <xsl:with-param name="nodename" select="$nodename"/>
+ <xsl:with-param name="picnumber" select="$picnumber"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="pic-process">
+ <xsl:param name="pic-name"/>
+ <xsl:param name="nodename"/>
+ <xsl:param name="picnumber"/>
+ <xsl:variable name="aa">
+ <xsl:choose>
+ <xsl:when test="./@draw:style-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:when>
+ <xsl:when test="./@table:end-cell-address">
+ <xsl:value-of select="@table:end-cell-address"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./@draw:id"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <图:图形 uof:locID="g0000" uof:attrList="层次 标识符 组合列表 其他对象">
+ <xsl:attribute name="图:标识符"><xsl:value-of select="concat($pic-name,'_',$picnumber)"/></xsl:attribute>
+ <xsl:attribute name="图:层次"><xsl:choose><xsl:when test="name(parent::node())='draw:g'"><xsl:value-of select="position()"/></xsl:when><xsl:when test="@draw:z-index"><xsl:value-of select="@draw:z-index"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="$nodename='draw:g'">
+ <xsl:attribute name="图:组合列表"><xsl:for-each select="child::*[1]"><xsl:variable name="node1"><xsl:value-of select="@draw:style-name | @draw:id"/></xsl:variable><xsl:variable name="picnumber2"><xsl:value-of select="count(preceding::*[@draw:style-name=$node1 or @draw:id=$node1])"/></xsl:variable><xsl:call-template name="zuheliebiao"><xsl:with-param name="allnode"><xsl:value-of select="concat($node1,'_',$picnumber2)"/></xsl:with-param><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:for-each></xsl:attribute>
+ </xsl:if>
+ <xsl:if test=".//office:binary-data">
+ <xsl:attribute name="图:其他对象"><xsl:choose><xsl:when test="@draw:name"><xsl:value-of select="@draw:name"/></xsl:when><xsl:otherwise><xsl:value-of select="concat($pic-name,'_b1')"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="arrow-sign">
+ <xsl:choose>
+ <xsl:when test="key('graphicset',$pic-name)/style:graphic-properties/@draw:marker-start or key('graphicset',$pic-name)/style:graphic-properties/@draw:marker-end">
+ <xsl:value-of select="'1'"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:line' or $nodename='draw:rect' or $nodename='draw:circle' or $nodename='draw:polygon' or $nodename='draw:polyline' or $nodename='draw:ellipse' or $nodename='draw:path'or $nodename='draw:g'">
+ <图:预定义图形 uof:locID="g0005">
+ <图:类别 uof:locID="g0006">
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:line' and $arrow-sign='1'">62</xsl:when>
+ <xsl:when test="$nodename='draw:rect'">11</xsl:when>
+ <xsl:when test="$nodename='draw:line'">61</xsl:when>
+ <xsl:when test="$nodename='draw:circle'">19</xsl:when>
+ <xsl:when test="$nodename='draw:polygon'">65</xsl:when>
+ <xsl:when test="$nodename='draw:polyline'">66</xsl:when>
+ <xsl:when test="$nodename='draw:ellipse'">19</xsl:when>
+ <xsl:when test="$nodename='draw:path'">64</xsl:when>
+ <xsl:when test="$nodename='draw:g'">4</xsl:when>
+ </xsl:choose>
+ </图:类别>
+ <图:名称 uof:locID="g0007">
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:rect'">Rectangle</xsl:when>
+ <xsl:when test="$nodename='draw:line'">Line</xsl:when>
+ <xsl:when test="$nodename='draw:circle'">Oval</xsl:when>
+ <xsl:when test="$nodename='draw:polygon'">Freeform</xsl:when>
+ <xsl:when test="$nodename='draw:polyline'">Scribble</xsl:when>
+ <xsl:when test="$nodename='draw:ellipse'">Oval</xsl:when>
+ <xsl:when test="$nodename='draw:path'">Curve</xsl:when>
+ <xsl:when test="$nodename='draw:g'">group</xsl:when>
+ </xsl:choose>
+ </图:名称>
+ <图:生成软件 uof:locID="g0008">PNG</图:生成软件>
+ <xsl:if test="./@draw:points or ./@svg:d">
+ <图:关键点坐标 uof:locID="g0009" uofattrList="路径">
+ <!--xsl:call-template name="draw:points">
+ <xsl:with-param name="point" select="./@draw:points"/>
+ </xsl:call-template-->
+ <xsl:attribute name="图:路径"><xsl:choose><xsl:when test="@svg:d"><xsl:value-of select="@svg:d"/></xsl:when><xsl:when test="@draw:points"><xsl:call-template name="draw:points"><xsl:with-param name="point" select="@draw:points"/><xsl:with-param name="lujing"/></xsl:call-template></xsl:when></xsl:choose></xsl:attribute>
+ </图:关键点坐标>
+ </xsl:if>
+ <图:属性 uof:locID="g0011">
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$aa]) | (/office:document/office:automatic-styles/descendant::*[@style:name=$aa]) ">
+ <xsl:call-template name="graphicattr"/>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="@svg:x1">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:x2,$uofUnit) - substring-before(@svg:x1,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:y2,$uofUnit) - substring-before(@svg:y1,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="@svg:x">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="@svg:width">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ </xsl:choose>
+ <图:旋转角度 uof:locID="g0025">
+ <xsl:choose>
+ <xsl:when test="@draw:transform">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="@draw:transform"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-temp">
+ <xsl:value-of select="substring-before(substring-after($rotate-angle,'rotate ('),')')"/>
+ </xsl:variable>
+ <xsl:value-of select="($rotate-temp * 360) div (2 * 3.14159265)"/>
+ </xsl:when>
+ <xsl:otherwise>0.0</xsl:otherwise>
+ </xsl:choose>
+ </图:旋转角度>
+ <图:X-缩放比例 uof:locID="g0026">1</图:X-缩放比例>
+ <图:Y-缩放比例 uof:locID="g0027">1</图:Y-缩放比例>
+ <图:锁定纵横比 uof:locID="g0028">0</图:锁定纵横比>
+ <图:相对原始比例 uof:locID="g0029">1</图:相对原始比例>
+ <图:打印对象 uof:locID="g0032">true</图:打印对象>
+ <图:Web文字 uof:locID="g0033"/>
+ <!--0820 by lil -->
+ </图:属性>
+ </图:预定义图形>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="string(.//text:p)">
+ <图:文本内容 uof:locID="g0002" uof:attrList="文本框 左边距 右边距 上边距 下边距 水平对齐 垂直对齐 文字排列方向 自动换行 大小适应文字 前一链接 后一链接">
+ <xsl:if test="$nodename='draw:text-box'">
+ <xsl:attribute name="图:文本框">true</xsl:attribute>
+ <xsl:if test="./@draw:name = /office:document/office:body
+//draw:text-box/@draw:chain-next-name">
+ <xsl:attribute name="图:前一链接"><xsl:variable name="drawname"><xsl:value-of select="./@draw:name"/></xsl:variable><xsl:variable name="befor-link-name"><xsl:value-of select="/office:document/office:body
+//draw:text-box[@draw:name=$drawname]/@draw:style-name"/></xsl:variable><xsl:value-of select="concat($befor-link-name,'_',$picnumber)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="./@draw:chain-next-name">
+ <xsl:attribute name="图:后一链接"><xsl:variable name="next-link"><xsl:value-of select="./@draw:chain-next-name"/></xsl:variable><xsl:variable name="link-name"><xsl:value-of select="/office:document/office:body
+//draw:text-box[@draw:name=$next-link]/@draw:style-name"/></xsl:variable><xsl:value-of select="concat($link-name,'_',$picnumber)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$pic-name]) | (/office:document/office:automatic-styles/descendant::*[@style:name=$pic-name]) ">
+ <xsl:if test="style:graphic-properties/@fo:padding-left">
+ <xsl:attribute name="图:左边距"><xsl:value-of select="substring-before(style:graphic-properties/@fo:padding-left,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:右边距"><xsl:value-of select="substring-before(style:graphic-properties/@fo:padding-right,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:上边距"><xsl:value-of select="substring-before(style:graphic-properties/@fo:padding-top,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:下边距"><xsl:value-of select="substring-before(style:graphic-properties/@fo:padding-bottom,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:文字排列方向"><xsl:choose><xsl:when test="style:paragraph-properties/@style:writing-mode"><xsl:choose><xsl:when test="style:paragraph-properties/@style:writing-mode='tb-lr'">vert-l2r</xsl:when><xsl:when test="style:paragraph-properties/@style:writing-mode='tb-rl'">vert-r2l</xsl:when></xsl:choose></xsl:when><xsl:when test="style:graphic-properties/@draw:textarea-horizontal-align='right'">hori-r2l</xsl:when><xsl:otherwise>hori-l2r</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="style:graphic-properties/@fo:wrap-option">
+ <xsl:attribute name="图:自动换行">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:auto-grow-width='true' or style:graphic-properties/@draw:auto-grow-height='true'">
+ <xsl:attribute name="图:大小适应文字">true</xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="text:p">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ <xsl:if test="style:paragraph-properties">
+ <xsl:apply-templates select="style:paragraph-properties"/>
+ </xsl:if>
+ <xsl:call-template name="textp"/>
+ </xsl:for-each>
+ </图:文本内容>
+ </xsl:if>
+ <图:控制点 uof:locID="g0003" uof:attrList="x坐标 y坐标">
+ <xsl:attribute name="图:x坐标"><xsl:value-of select="substring-before(@svg:x,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:y坐标"><xsl:value-of select="substring-before(@svg:y,$uofUnit)"/></xsl:attribute>
+ </图:控制点>
+ <!--新增内容-->
+ <xsl:if test="name(..)='draw:g'">
+ <图:组合位置 uof:locID="g0041" uof:attrList="x坐标 y坐标">
+ <xsl:attribute name="图:x坐标"><xsl:variable name="minx"><xsl:for-each select="parent::node()"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:for-each></xsl:variable><xsl:choose><xsl:when test="name(.)='draw:g'"><xsl:variable name="current-minx"><xsl:call-template name="groupminx"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:x][1]/@svg:x,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:value-of select="$current-minx - $minx"/></xsl:when><xsl:otherwise><xsl:variable name="current-x" select="number(substring-before(@svg:x,$uofUnit))"/><xsl:value-of select="$current-x - $minx"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:y坐标"><xsl:variable name="miny"><xsl:for-each select="parent::node()"><xsl:call-template name="groupminy"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:for-each></xsl:variable><xsl:choose><xsl:when test="name(.)='draw:g'"><xsl:variable name="current-miny"><xsl:call-template name="groupminy"><xsl:with-param name="value" select="number(substring-before(descendant::node()[@svg:y][1]/@svg:y,$uofUnit))"/><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:variable><xsl:value-of select="$current-miny - $miny"/></xsl:when><xsl:otherwise><xsl:variable name="current-y" select="number(substring-before(@svg:y,$uofUnit))"/><xsl:value-of select="$current-y - $miny"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </图:组合位置>
+ </xsl:if>
+ <!--Redoffice comment liliang 06.03.28 end-->
+ </图:图形>
+ <xsl:if test="name()='draw:image'">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat($pic-name,'_',$picnumber)"/></xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:if test="./office:binary-data">
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="./office:binary-data"/>
+ </uof:数据>
+ </xsl:if>
+ <xsl:if test="@xlink:href">
+ <uof:路径 uof:locID="u0038">
+ <xsl:value-of select="@xlink:href"/>
+ </uof:路径>
+ </xsl:if>
+ </uof:其他对象>
+ </xsl:if>
+ <xsl:if test="name()='draw:frame'">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat($pic-name,'_',$picnumber)"/></xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:if test="draw:image/office:binary-data">
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="draw:image/office:binary-data"/>
+ </uof:数据>
+ </xsl:if>
+ <xsl:if test="@xlink:href">
+ <uof:路径 uof:locID="u0038">
+ <xsl:value-of select="@xlink:href"/>
+ </uof:路径>
+ </xsl:if>
+ </uof:其他对象>
+ </xsl:if>
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$pic-name]) | (/office:document/office:automatic-styles/descendant::*[@style:name=$pic-name]) ">
+ <xsl:if test="style:graphic-properties/@draw:fill-image-name">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat($pic-name,'_b1')"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <xsl:variable name="fill-name">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-image-name"/>
+ </xsl:variable>
+ <uof:数据 uof:locID="u0037">
+ <xsl:for-each select="/office:document/office:styles/draw:fill-image[@draw:name=$fill-name]">
+ <xsl:value-of select="office:binary-data"/>
+ </xsl:for-each>
+ </uof:数据>
+ <uof:路径 uof:locID="u0038">
+ <xsl:value-of select="@xlink:href"/>
+ </uof:路径>
+ </uof:其他对象>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <!--Redoffice comment liliang 06.03.29-->
+ <!--新增内容-->
+ <xsl:template name="graphicattr">
+ <xsl:variable name="aa" select="@style:name"/>
+ <xsl:if test="not(style:graphic-properties/@draw:fill='none')">
+ <图:填充 uof:locID="g0012">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:fill='gradient'">
+ <xsl:variable name="gradient-name">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-gradient-name"/>
+ </xsl:variable>
+ <xsl:for-each select="/descendant::draw:gradient[@draw:name=$gradient-name]">
+ <图:渐变 uof:locID="g0037" uof:attrList="起始色 终止色 种子类型 起始浓度 终止浓度 渐变方向 边界 种子X位置 种子Y位置 类型">
+ <xsl:attribute name="图:起始色"><xsl:value-of select="@draw:start-color"/></xsl:attribute>
+ <xsl:attribute name="图:终止色"><xsl:value-of select="@draw:end-color"/></xsl:attribute>
+ <xsl:attribute name="图:种子类型"><xsl:choose><xsl:when test="@draw:style='linear' or @draw:style='axial'">linear</xsl:when><xsl:when test="@draw:style='radial'">radar</xsl:when><xsl:when test="@draw:style='ellipsoid'">oval</xsl:when><xsl:when test="@draw:style='square'">square</xsl:when><xsl:when test="@draw:style='rectangular'">rectangle</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:起始浓度"><xsl:value-of select="substring-before(@draw:start-intensity,'%')"/></xsl:attribute>
+ <xsl:attribute name="图:终止浓度"><xsl:value-of select="substring-before(@draw:end-intensity,'%')"/></xsl:attribute>
+ <xsl:variable name="angle">
+ <xsl:value-of select="@draw:angle div 10"/>
+ </xsl:variable>
+ <xsl:attribute name="图:渐变方向"><xsl:choose><xsl:when test="0&lt;$angle and $angle&lt;25">0</xsl:when><xsl:when test="25&lt;$angle and $angle&lt;70">45</xsl:when><xsl:when test="70&lt;$angle and $angle&lt;115">90</xsl:when><xsl:when test="115&lt;$angle and $angle&lt;160">135</xsl:when><xsl:when test="160&lt;$angle and $angle&lt;205">180</xsl:when><xsl:when test="205&lt;$angle and $angle&lt;250">225</xsl:when><xsl:when test="250&lt;$angle and $angle&lt;295">270</xsl:when><xsl:when test="295&lt;$angle and $angle&lt;340">315</xsl:when><xsl:when test="340&lt;$angle and $angle&lt;360">360</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:边界"><xsl:value-of select="substring-before(@draw:border,'%')"/></xsl:attribute>
+ <xsl:if test="@draw:cx">
+ <xsl:attribute name="图:种子X位置"><xsl:value-of select="substring-before(@draw:cx,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@draw:cy">
+ <xsl:attribute name="图:种子Y位置"><xsl:value-of select="substring-before(@draw:cy,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:类型">-2</xsl:attribute>
+ </图:渐变>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:fill-image-name">
+ <图:图片 uof:locID="g0035" uof:attrList="位置 图形引用 类型 名称">
+ <xsl:attribute name="图:位置"><xsl:choose><xsl:when test="not(style:graphic-properties/@style:repeat)">tile</xsl:when><xsl:otherwise><xsl:choose><xsl:when test="style:graphic-properties/@style:repeat = 'stretch'">stretch</xsl:when><xsl:when test="style:graphic-properties/@style:repeat = 'repeat'">tile</xsl:when><xsl:when test="style:graphic-properties/@style:repeat = 'no-repeat'">center</xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:图形引用"><xsl:value-of select="concat($aa,'_b1')"/></xsl:attribute>
+ <xsl:attribute name="图:类型">png</xsl:attribute>
+ <xsl:attribute name="图:名称"><xsl:value-of select="style:graphic-properties/@draw:fill-image-name"/></xsl:attribute>
+ </图:图片>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:fill='hatch'">
+ <图:图案 uof:locID="g0036" uof:attrList="类型 图形引用 前景色 背景色">
+ <xsl:if test="/office:document/office:styles/draw:hatch/@draw:name">
+ <xsl:attribute name="图:类型"><xsl:value-of select="/office:document/office:styles/draw:hatch/@draw:name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:图形引用">rogr1</xsl:attribute>
+ <xsl:if test="/office:document/office:styles/draw:hatch/@draw:color">
+ <xsl:attribute name="图:前景色"><xsl:value-of select="/office:document/office:styles/draw:hatch/@draw:color"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:背景色"><xsl:choose><xsl:when test="style:graphic-properties/@draw:fill-color"><xsl:value-of select="style:graphic-properties/@draw:fill-color"/></xsl:when><xsl:otherwise>#ffffff</xsl:otherwise></xsl:choose></xsl:attribute>
+ </图:图案>
+ </xsl:when>
+ <xsl:otherwise>
+ <图:颜色 uof:locID="g0034">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:fill-color">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-color"/>
+ </xsl:when>
+ <xsl:otherwise>#99ccff</xsl:otherwise>
+ </xsl:choose>
+ </图:颜色>
+ </xsl:otherwise>
+ </xsl:choose>
+ </图:填充>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@svg:stroke-color">
+ <图:线颜色 uof:locID="g0013">
+ <xsl:value-of select="style:graphic-properties/@svg:stroke-color"/>
+ </图:线颜色>
+ </xsl:if>
+ <图:线型 uof:locID="g0014">
+ <xsl:call-template name="表:线型"/>
+ </图:线型>
+ <xsl:if test="style:graphic-properties/@svg:stroke-width">
+ <图:线粗细 uof:locID="g0016">
+ <xsl:value-of select="substring-before(style:graphic-properties/@svg:stroke-width,$uofUnit)"/>
+ </图:线粗细>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:marker-start and string-length(style:graphic-properties/@draw:marker-start)&gt;0">
+ <图:前端箭头 uof:locID="g0017">
+ <图:式样 uof:locID="g0018">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Arrow'">normal</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Line Arrow'">open</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Arrow concave'">stealth</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Circle'">oval</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Square 45'">diamond</xsl:when>
+ <xsl:otherwise>normal</xsl:otherwise>
+ </xsl:choose>
+ </图:式样>
+ <xsl:if test="style:graphic-properties/@draw:marker-start-width">
+ <图:大小 uof:locID="g0019">
+ <xsl:variable name="width">
+ <xsl:value-of select="substring-before(style:graphic-properties/@draw:marker-start-width,$uofUnit)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="($width&lt;0.05 and 0&lt;$width) or $width=0.05">1</xsl:when>
+ <xsl:when test="($width&lt;0.10 and 0.05&lt;$width) or $width=0.10">2</xsl:when>
+ <xsl:when test="($width&lt;0.15 and 0.10&lt;$width) or $width=0.15">3</xsl:when>
+ <xsl:when test="($width&lt;0.20 and 0.15&lt;$width) or $width=0.20">4</xsl:when>
+ <xsl:when test="($width&lt;0.25 and 0.20&lt;$width) or $width=0.25">5</xsl:when>
+ <xsl:when test="($width&lt;0.30 and 0.25&lt;$width) or $width=0.30">6</xsl:when>
+ <xsl:when test="($width&lt;0.35 and 0.30&lt;$width) or $width=0.35">7</xsl:when>
+ <xsl:when test="($width&lt;0.40 and 0.35&lt;$width) or $width=0.40">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </图:大小>
+ </xsl:if>
+ </图:前端箭头>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:marker-end">
+ <!--0820 by lil -->
+ <图:后端箭头 uof:locID="g0020">
+ <图:式样 uof:locID="g0021">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Arrow'">normal</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Line Arrow'">open</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Arrow concave'">stealth</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Circle'">oval</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Square 45'">diamond</xsl:when>
+ <xsl:otherwise>normal</xsl:otherwise>
+ </xsl:choose>
+ </图:式样>
+ <xsl:if test="style:graphic-properties/@draw:marker-end-width">
+ <图:大小 uof:locID="g0022">
+ <xsl:variable name="width">
+ <xsl:value-of select="number(substring-before(style:graphic-properties/@draw:marker-end-width,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="($width&lt;0.05 and 0&lt;$width) or $width=0.05">1</xsl:when>
+ <xsl:when test="($width&lt;0.10 and 0.05&lt;$width) or $width=0.10">2</xsl:when>
+ <xsl:when test="($width&lt;0.15 and 0.10&lt;$width) or $width=0.15">3</xsl:when>
+ <xsl:when test="($width&lt;0.20 and 0.15&lt;$width) or $width=0.20">4</xsl:when>
+ <xsl:when test="($width&lt;0.25 and 0.20&lt;$width) or $width=0.25">5</xsl:when>
+ <xsl:when test="($width&lt;0.30 and 0.25&lt;$width) or $width=0.30">6</xsl:when>
+ <xsl:when test="($width&lt;0.35 and 0.30&lt;$width) or $width=0.35">7</xsl:when>
+ <xsl:when test="($width&lt;0.40 and 0.35&lt;$width) or $width=0.40">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </图:大小>
+ </xsl:if>
+ </图:后端箭头>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:opacity">
+ <xsl:variable name="trans" select="style:graphic-properties/@draw:opacity"/>
+ <图:透明度 uof:locID="g0038">
+ <xsl:value-of select="substring($trans,1,2)"/>
+ </图:透明度>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="groupminx">
+ <xsl:param name="value"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="descendant::node()[@svg:x][position()=$pos]">
+ <xsl:variable name="othervalue" select="number(substring-before(descendant::node()[@svg:x][position()=$pos]/@svg:x,$uofUnit))"/>
+ <xsl:call-template name="groupminx">
+ <xsl:with-param name="value">
+ <xsl:choose>
+ <xsl:when test="$value&gt;$othervalue">
+ <xsl:value-of select="$othervalue"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--Redoffice comment liliang end 06.03.29-->
+ <!--Redoffice comment liliang 06.03.29-->
+ <!--新增内容-->
+ <xsl:template name="groupminy">
+ <xsl:param name="value"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="descendant::node()[@svg:y][position()=$pos]">
+ <xsl:variable name="othervalue" select="number(substring-before(descendant::node()[@svg:y][position()=$pos]/@svg:y,$uofUnit))"/>
+ <xsl:call-template name="groupminy">
+ <xsl:with-param name="value">
+ <xsl:choose>
+ <xsl:when test="$value&gt;$othervalue">
+ <xsl:value-of select="$othervalue"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="groupmaxx">
+ <xsl:param name="value"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="descendant::node()[@svg:x][position()=$pos]">
+ <xsl:variable name="svgx">
+ <xsl:value-of select="number(substring-before(descendant::node()[@svg:x][position()=$pos]/@svg:x,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:variable name="width">
+ <xsl:value-of select="number(substring-before(descendant::node()[@svg:x][position()=$pos]/@svg:width,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:variable name="othervalue" select="$svgx + $width"/>
+ <xsl:call-template name="groupminx">
+ <xsl:with-param name="value">
+ <xsl:choose>
+ <xsl:when test="$value&gt;$othervalue">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$othervalue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="groupmaxy">
+ <xsl:param name="value"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="descendant::node()[@svg:y][position()=$pos]">
+ <xsl:variable name="svgy">
+ <xsl:value-of select="number(substring-before(descendant::node()[@svg:y][position()=$pos]/@svg:y,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:variable name="height">
+ <xsl:value-of select="number(substring-before(descendant::node()[@svg:y][position()=$pos]/@svg:height,$uofUnit))"/>
+ </xsl:variable>
+ <xsl:variable name="othervalue" select="$svgy + $height"/>
+ <xsl:call-template name="groupminy">
+ <xsl:with-param name="value">
+ <xsl:choose>
+ <xsl:when test="$value&gt;$othervalue">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$othervalue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--Redoffice comment liliang end 06.03.29-->
+ <xsl:template name="draw:points">
+ <xsl:param name="point"/>
+ <xsl:param name="lujing"/>
+ <xsl:choose>
+ <xsl:when test="contains($point,' ' )">
+ <xsl:variable name="first-point" select="substring-before($point,' ')"/>
+ <xsl:variable name="other-point" select="substring-after($point,' ')"/>
+ <xsl:variable name="xzuobiao">
+ <xsl:value-of select="substring-before($first-point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:variable name="yzuobiao">
+ <xsl:value-of select="substring-after($first-point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:call-template name="draw:points">
+ <xsl:with-param name="point" select="$other-point"/>
+ <xsl:with-param name="lujing" select="concat($lujing,$xzuobiao,' ',$yzuobiao,'lineto')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="xzuobiao">
+ <xsl:value-of select="substring-before($point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:variable name="yzuobiao">
+ <xsl:value-of select="substring-after($point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:value-of select="concat($lujing,$xzuobiao,' ',$yzuobiao)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--Redoffice comment end liliang-->
+ <!--chenjh add 20050624-->
+ <xsl:template name="create-page-setting">
+ <xsl:param name="master-page"/>
+ <xsl:param name="page-master-style"/>
+ <xsl:element name="表:页面设置">
+ <xsl:attribute name="uof:locID">s0029</xsl:attribute>
+ <xsl:attribute name="uof:attrList">名称</xsl:attribute>
+ <xsl:attribute name="表:名称"><xsl:value-of select="$master-page/@style:name"/></xsl:attribute>
+ <xsl:element name="表:纸张">
+ <xsl:attribute name="uof:locID">s0030</xsl:attribute>
+ <xsl:attribute name="uof:attrList">纸型 宽度 高度</xsl:attribute>
+ <xsl:attribute name="uof:纸型"><xsl:variable name="height"><xsl:value-of select="$page-master-style/@fo:page-height"/></xsl:variable><xsl:variable name="width"><xsl:value-of select="$page-master-style/@fo:page-width"/></xsl:variable><xsl:choose><xsl:when test="$width='29.699cm' and $height='42cm'">A3</xsl:when><xsl:when test="not($page-master-style/@fo:page-height) and not($page-master-style/@fo:page-width)">A4</xsl:when><xsl:when test="$width='14.799cm' and $height='20.999cm'">A5</xsl:when><xsl:when test="$width='25cm' and $height='35.299cm'">B4</xsl:when><xsl:when test="$width='17.598cm' and $height='25cm'">B5</xsl:when><xsl:when test="$width='12.499cm' and $height='17.598cm'">B6</xsl:when><xsl:otherwise>使用者</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:choose><xsl:when test="$page-master-style/@fo:page-width"><xsl:value-of select="substring-before($page-master-style/@fo:page-width,$uofUnit)"/></xsl:when><xsl:otherwise><xsl:call-template name="setDefaultPageWidth"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:高度"><xsl:choose><xsl:when test="$page-master-style/@fo:page-height"><xsl:value-of select="substring-before($page-master-style/@fo:page-height,$uofUnit)"/></xsl:when><xsl:otherwise><xsl:call-template name="setDefaultPageHeight"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="表:纸张方向">
+ <xsl:attribute name="uof:locID">s0031</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$page-master-style/@style:print-orientation">
+ <xsl:value-of select="$page-master-style/@style:print-orientation"/>
+ </xsl:when>
+ <xsl:otherwise>portrait</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="表:缩放">
+ <xsl:attribute name="uof:locID">s0032</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$page-master-style/@style:scale-to">
+ <xsl:value-of select="$page-master-style/@style:scale-to"/>
+ </xsl:when>
+ <xsl:otherwise>100</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="$page-master-style/@fo:margin-left or $page-master-style/@fo:margin-top or $page-master-style/@fo:margin-right or $page-master-style/@fo:margin-bottom">
+ <xsl:element name="表:页边距">
+ <xsl:attribute name="uof:locID">s0033</xsl:attribute>
+ <xsl:attribute name="uof:attrList">左 上 右 下</xsl:attribute>
+ <xsl:attribute name="uof:左"><xsl:value-of select="substring-before($page-master-style/@fo:margin-left,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:上"><xsl:value-of select="substring-before($page-master-style/@fo:margin-top,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:右"><xsl:value-of select="substring-before($page-master-style/@fo:margin-right,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:下"><xsl:value-of select="substring-before($page-master-style/@fo:margin-bottom,$uofUnit)"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:for-each select="$master-page[@style:page-layout-name='pm1']/style:header/child::*">
+ <表:页眉页脚 uof:locID="s0034" uof:attrList="位置">
+ <xsl:attribute name="表:位置"><xsl:choose><xsl:when test="name()='style:region-left'">headerleft</xsl:when><xsl:when test="name()='style:region-right'">headerright</xsl:when><xsl:otherwise>headercenter</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:call-template name="create-page-header-footer-paragraph">
+ <xsl:with-param name="paragraph-set" select="text:p"/>
+ </xsl:call-template>
+ </表:页眉页脚>
+ </xsl:for-each>
+ <xsl:for-each select="$master-page[@style:page-layout-name='pm1']/style:footer/child::*">
+ <表:页眉页脚 uof:locID="s0034" uof:attrList="位置">
+ <xsl:attribute name="表:位置"><xsl:choose><xsl:when test="name()='style:region-left'">footerleft</xsl:when><xsl:when test="name()='style:region-right'">footerright</xsl:when><xsl:otherwise>footercenter</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:call-template name="create-page-header-footer-paragraph">
+ <xsl:with-param name="paragraph-set" select="text:p"/>
+ </xsl:call-template>
+ </表:页眉页脚>
+ </xsl:for-each>
+ <xsl:if test="$page-master-style/@style:print-page-order or $page-master-style/@style:print">
+ <表:打印 uof:locID="s126" uof:attrList="网格线 行号列标 按草稿方式 先列后行">
+ <xsl:if test="$page-master-style/@style:print-page-order='ltr'">
+ <xsl:attribute name="表:先列后行">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains($page-master-style/@style:print,'grid')">
+ <xsl:attribute name="表:网格线">true</xsl:attribute>
+ </xsl:if>
+ </表:打印>
+ </xsl:if>
+ <xsl:if test="$page-master-style/@style:table-centering='vertical' or $page-master-style/@style:table-centering='both'">
+ <表:垂直对齐 uof:locID="s0128" uof:attrList="对齐方式">
+ <xsl:attribute name="表:对齐方式">center</xsl:attribute>
+ </表:垂直对齐>
+ </xsl:if>
+ <xsl:if test="$page-master-style/@style:table-centering='horizontal' or $page-master-style/@style:table-centering='both'">
+ <表:水平对齐 uof:locID="s0129" uof:attrList="对齐方式">
+ <xsl:attribute name="表:对齐方式">center</xsl:attribute>
+ </表:水平对齐>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="create-page-header-footer-paragraph">
+ <xsl:param name="paragraph-set"/>
+ <xsl:choose>
+ <xsl:when test="$paragraph-set">
+ <xsl:element name="字:段落">
+ <xsl:attribute name="uof:locID">t0051</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:element name="字:句">
+ <xsl:attribute name="uof:locID">t0085</xsl:attribute>
+ <xsl:apply-templates select="$paragraph-set//text()">
+ <xsl:with-param name="bText" select="'0'"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:element>
+ <xsl:call-template name="create-page-header-footer-paragraph">
+ <xsl:with-param name="paragraph-set" select="$paragraph-set[position()!=1]"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="text:p" name="textp">
+ <xsl:apply-templates select="text()|text:span|text:tab-stop|text:line-break|text:s|text:ruby|text:bookmark|text:bookmark-start|text:bookmark-end|text:a|text:footnote|text:endnote">
+ <xsl:with-param name="bText" select="'1'"/>
+ <xsl:with-param name="sText" select="'1'"/>
+ </xsl:apply-templates>
+ </xsl:template>
+ <xsl:template match="text:a">
+ <xsl:param name="bText"/>
+ <xsl:choose>
+ <xsl:when test="$bText='0'">
+ <xsl:element name="字:句">
+ <xsl:attribute name="uof:locID">t0085</xsl:attribute>
+ <xsl:element name="字:区域开始">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="generate-id(.)"/></xsl:attribute>
+ <xsl:attribute name="字:类型">hyperlink</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0121</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="字:区域开始">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="generate-id(.)"/></xsl:attribute>
+ <xsl:attribute name="字:类型">hyperlink</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0121</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型</xsl:attribute>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="text()">
+ <xsl:param name="bText"/>
+ <xsl:param name="sText"/>
+ <xsl:if test="normalize-space(.)!=''">
+ <xsl:choose>
+ <xsl:when test="$bText='1' and $sText='1'">
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:文本串 uof:locID="t0109" uof:attrList="udsPath">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="text:span">
+ <xsl:param name="bText"/>
+ <xsl:choose>
+ <xsl:when test="$bText='0'">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用">
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </字:句属性>
+ <xsl:apply-templates select="text:s|text()|text:line-break|text:tab-stop| text:a | text:footnote|text:endnote|draw:image|office:annotation|draw:frame">
+ <xsl:with-param name="bText" select="1"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用" 字:式样引用="{@text:style-name}"/>
+ <xsl:apply-templates select="text:s|text()|text:line-break|text:tab-stop| text:a |text:footnote|text:endnote|draw:image|office:annotation|draw:frame">
+ <xsl:with-param name="bText" select="1"/>
+ </xsl:apply-templates>
+ </字:句>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="text:s">
+ <xsl:param name="bText"/>
+ <xsl:choose>
+ <xsl:when test="$bText='0'">
+ <xsl:variable name="count">
+ <xsl:choose>
+ <xsl:when test="not(@text:c)">1</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@text:c"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <字:句 uof:locID="t0085">
+ <字:空格符 uof:locID="t0126" uof:attrList="个数" 字:个数="{$count}"/>
+ </字:句>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:空格符 uof:locID="t0126" uof:attrList="个数" 字:个数="{@text:c}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="text:line-break">
+ <xsl:param name="bText"/>
+ <xsl:choose>
+ <xsl:when test="$bText='0'">
+ <字:句 uof:locID="t0085">
+ <字:换行符 uof:locID="t0124"/>
+ </字:句>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:换行符 uof:locID="t0124"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="text:tab-stop">
+ <xsl:param name="bText"/>
+ <xsl:choose>
+ <xsl:when test="$bText='0'">
+ <字:句 uof:locID="t0085">
+ <字:制表符 uof:locID="t0123"/>
+ </字:句>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:制表符 uof:locID="t0123"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--chenjh0713-->
+ <!--chenjh0629E-->
+ <!--chenjh add 20050629 -->
+ <!--字符串转换为数字-->
+ <xsl:template name="translate-column-char-to-number">
+ <xsl:param name="string"/>
+ <xsl:choose>
+ <xsl:when test="string-length($string)=1">
+ <xsl:call-template name="char-to-number">
+ <xsl:with-param name="char" select="$string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="tens-place">
+ <xsl:call-template name="char-to-number">
+ <xsl:with-param name="char" select="substring($string,1,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="units-place">
+ <xsl:call-template name="char-to-number">
+ <xsl:with-param name="char" select="substring($string,2,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$tens-place * 26 + $units-place"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="char-to-number">
+ <xsl:param name="char"/>
+ <xsl:choose>
+ <xsl:when test="$char='A'">1</xsl:when>
+ <xsl:when test="$char='B'">2</xsl:when>
+ <xsl:when test="$char='C'">3</xsl:when>
+ <xsl:when test="$char='D'">4</xsl:when>
+ <xsl:when test="$char='E'">5</xsl:when>
+ <xsl:when test="$char='F'">6</xsl:when>
+ <xsl:when test="$char='G'">7</xsl:when>
+ <xsl:when test="$char='H'">8</xsl:when>
+ <xsl:when test="$char='I'">9</xsl:when>
+ <xsl:when test="$char='J'">10</xsl:when>
+ <xsl:when test="$char='K'">11</xsl:when>
+ <xsl:when test="$char='L'">12</xsl:when>
+ <xsl:when test="$char='M'">13</xsl:when>
+ <xsl:when test="$char='N'">14</xsl:when>
+ <xsl:when test="$char='O'">15</xsl:when>
+ <xsl:when test="$char='P'">16</xsl:when>
+ <xsl:when test="$char='Q'">17</xsl:when>
+ <xsl:when test="$char='R'">18</xsl:when>
+ <xsl:when test="$char='S'">19</xsl:when>
+ <xsl:when test="$char='T'">20</xsl:when>
+ <xsl:when test="$char='U'">21</xsl:when>
+ <xsl:when test="$char='V'">22</xsl:when>
+ <xsl:when test="$char='W'">23</xsl:when>
+ <xsl:when test="$char='X'">24</xsl:when>
+ <xsl:when test="$char='Y'">25</xsl:when>
+ <xsl:when test="$char='Z'">26</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-filter-conditions">
+ <xsl:param name="filter-condition-set"/>
+ <xsl:param name="zone-left-column-num"/>
+ <xsl:if test="$filter-condition-set">
+ <xsl:variable name="first-condition" select="$filter-condition-set"/>
+ <xsl:element name="表:条件">
+ <xsl:attribute name="uof:locID">s0103</xsl:attribute>
+ <xsl:attribute name="uof:attrList">列号</xsl:attribute>
+ <xsl:attribute name="表:列号"><xsl:value-of select="$zone-left-column-num + $first-condition/@table:field-number"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$first-condition/@table:operator ='top values'">
+ <xsl:element name="表:普通">
+ <xsl:attribute name="uof:locID">s0104</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 值</xsl:attribute>
+ <xsl:attribute name="表:类型">topitem</xsl:attribute>
+ <xsl:attribute name="表:值"><xsl:value-of select="$first-condition/@table:value"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="表:自定义">
+ <xsl:attribute name="uof:locID">s0105</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:element name="表:操作条件">
+ <xsl:attribute name="uof:locID">s0106</xsl:attribute>
+ <!--redoffice comment from lvxg 8.27-->
+ <xsl:if test="$first-condition/@table:operator">
+ <xsl:element name="表:操作码">
+ <xsl:attribute name="uof:locID">s0009</xsl:attribute>
+ <xsl:variable name="operator-text" select="$first-condition/@table:operator"/>
+ <xsl:choose>
+ <xsl:when test="$operator-text ='&lt;' ">less than</xsl:when>
+ <xsl:when test="$operator-text ='&gt;' ">greater than</xsl:when>
+ <xsl:when test="$operator-text ='=' ">equal to</xsl:when>
+ <xsl:when test="$operator-text ='&gt;=' ">greater than or equal to</xsl:when>
+ <xsl:when test="$operator-text ='&lt;=' ">less than or equal to</xsl:when>
+ <xsl:when test="$operator-text ='!=' ">not equal to</xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="表:值">
+ <xsl:attribute name="uof:locID">s0107</xsl:attribute>
+ <xsl:value-of select="$first-condition/@table:value"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:call-template name="create-filter-conditions">
+ <xsl:with-param name="filter-condition-set" select="$filter-condition-set[position()!=1]"/>
+ <xsl:with-param name="zone-left-column-num" select="$zone-left-column-num"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-view">
+ <xsl:param name="table-name"/>
+ <xsl:param name="view-id"/>
+ <!--xsl:param name="ActiveTable"/-->
+ <xsl:param name="aaa"/>
+ <!--xsl:variable name="aaa" select="/*/office:settings/config:config-item-set/config:config-item-map-indexed"-->
+ <xsl:element name="表:视图">
+ <xsl:attribute name="uof:locID">s0035</xsl:attribute>
+ <xsl:attribute name="uof:attrList">窗口标识符</xsl:attribute>
+ <xsl:attribute name="表:窗口标识符"><xsl:value-of select="$view-id"/></xsl:attribute>
+ <xsl:if test="$table-name='ActiveTable'">
+ <xsl:element name="表:选中">
+ <xsl:attribute name="uof:locID">s0036</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="表:值">1</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:variable name="name" select="./@table:name"/>
+ <xsl:choose>
+ <xsl:when test="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$name]/config:config-item[@config:name='HorizontalSplitMode']/text()='2' or $aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=name]/config:config-item[@config:name='VerticalSplitMode']/text()='2' ">
+ <xsl:element name="表:冻结">
+ <xsl:attribute name="uof:locID">s0038</xsl:attribute>
+ <xsl:attribute name="uof:attrList">行号 列号</xsl:attribute>
+ <xsl:attribute name="表:行号"><xsl:value-of select="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$name]/config:config-item[@config:name='VerticalSplitPosition']/text()"/></xsl:attribute>
+ <xsl:attribute name="表:列号"><xsl:value-of select="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$name]/config:config-item[@config:name='HorizontalSplitPosition']/text()"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="表:拆分">
+ <xsl:attribute name="uof:locID">s0037</xsl:attribute>
+ <xsl:attribute name="uof:attrList">宽度 高度</xsl:attribute>
+ <xsl:attribute name="表:宽度"><xsl:choose><xsl:when test="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$name]/config:config-item[@config:name='HorizontalSplitMode']/text()='1'"><xsl:value-of select="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$name]/config:config-item[@config:name='HorizontalSplitPosition']/text()"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="表:高度"><xsl:choose><xsl:when test="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$name]/config:config-item[@config:name='VerticalSplitMode']/text()='1'"><xsl:value-of select="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$name]/config:config-item[@config:name='VerticalSplitPosition']/text()"/></xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:element name="表:最上行">
+ <xsl:attribute name="uof:locID">s0039</xsl:attribute>
+ <!--xsl:value-of select="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$table-name]/config:config-item[@config:name='PositionBottom']/text()+1"/-->
+ <xsl:choose>
+ <xsl:when test="$aaa/config:config-item-map-named/config:config-item-map-entry/config:config-item[@config:name='PositionBottom']/text()">
+ <xsl:value-of select="$aaa/config:config-item-map-named/config:config-item-map-entry/config:config-item[@config:name='PositionBottom']/text()"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="表:最左列">
+ <xsl:attribute name="uof:locID">s0040</xsl:attribute>
+ <!--xsl:value-of select="$aaa/config:config-item-map-named/config:config-item-map-entry[@config:name=$table-name]/config:config-item[@config:name='PositionLeft']/text() + 1"/-->
+ <xsl:choose>
+ <xsl:when test="$aaa/config:config-item-map-named/config:config-item-map-entry/config:config-item[@config:name='PositionRight']/text()">
+ <xsl:value-of select="$aaa/config:config-item-map-named/config:config-item-map-entry/config:config-item[@config:name='PositionRight']/text()"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="表:当前视图">
+ <xsl:attribute name="uof:locID">s0041</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="表:类型"><xsl:choose><xsl:when test="$aaa/config:config-item[@config:name='ShowPageBreakPreview']/text()='true'">page</xsl:when><xsl:otherwise>normal</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="表:网格">
+ <xsl:attribute name="uof:locID">s0043</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="表:值"><xsl:choose><xsl:when test="/*/office:settings/config:config-item-set[@config:name='ooo:view-settings']//config:config-item[@config:name='ShowGrid']/text()='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="表:网格颜色">
+ <xsl:attribute name="uof:locID">s0044</xsl:attribute>
+ <xsl:variable name="GridColor-text">
+ <xsl:value-of select="//config:config-item-set[@config:name='ooo:view-settings']//config:config-item[@config:name='GridColor']/text()"/>
+ </xsl:variable>
+ <xsl:variable name="R-color" select="floor($GridColor-text div 65536)"/>
+ <xsl:variable name="G-color" select="floor(($GridColor-text - ($R-color * 65536)) div 256)"/>
+ <xsl:variable name="B-color" select="$GridColor-text - ($R-color * 65536)- ($G-color * 256)"/>
+ <xsl:variable name="R-color-in-16">
+ <xsl:call-template name="transform-decimal-to-hexadecimal">
+ <xsl:with-param name="color-decimal" select="$R-color"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="G-color-in-16">
+ <xsl:call-template name="transform-decimal-to-hexadecimal">
+ <xsl:with-param name="color-decimal" select="$G-color"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="B-color-in-16">
+ <xsl:call-template name="transform-decimal-to-hexadecimal">
+ <xsl:with-param name="color-decimal" select="$B-color"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('#',$R-color-in-16,$G-color-in-16,$B-color-in-16)"/>
+ </xsl:element>
+ <xsl:if test="/*/office:settings/config:config-item-set[@config:name='ooo:view-settings']//config:config-item[@config:name='ZoomType']/text()=0">
+ <xsl:element name="表:缩放">
+ <xsl:attribute name="uof:locID">s0045</xsl:attribute>
+ <xsl:value-of select="/*/office:settings/config:config-item-set[@config:name='ooo:view-settings']//config:config-item[@config:name='ZoomValue']/text()"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="/*/office:settings/config:config-item-set[@config:name='ooo:view-settings']//config:config-item[@config:name='ZoomType']/text()=1">
+ <xsl:element name="表:分页缩放">
+ <xsl:attribute name="uof:locID">s0046</xsl:attribute>
+ <xsl:value-of select="/*/office:settings/config:config-item-set[@config:name='ooo:view-settings']//config:config-item[@config:name='ZoomValue']/text()"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="hexNumber2dec">
+ <xsl:param name="hex-value"/>
+ <xsl:choose>
+ <xsl:when test="$hex-value = 'A' or ($hex-value = 'a')">
+ <xsl:value-of select="10"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'B' or ($hex-value = 'b')">
+ <xsl:value-of select="11"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'C' or ($hex-value = 'c')">
+ <xsl:value-of select="12"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'D' or ($hex-value = 'd')">
+ <xsl:value-of select="13"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'E' or ($hex-value = 'e')">
+ <xsl:value-of select="14"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'F' or ($hex-value = 'f')">
+ <xsl:value-of select="15"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$hex-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="hex2decimal">
+ <xsl:param name="hex-number"/>
+ <xsl:param name="index"/>
+ <xsl:param name="str-length"/>
+ <xsl:param name="last-value"/>
+ <xsl:variable name="dec-char">
+ <xsl:call-template name="hexNumber2dec">
+ <xsl:with-param name="hex-value" select="substring($hex-number, $index ,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="current-value" select="$last-value * 16 + $dec-char"/>
+ <xsl:if test="$index &lt; $str-length">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="$hex-number"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ <xsl:with-param name="str-length" select="$str-length"/>
+ <xsl:with-param name="last-value" select="$current-value"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$index = $str-length">
+ <xsl:value-of select="$current-value"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="table:calculation-settings" mode="common">
+ <xsl:if test="@table:precision-as-shown">
+ <xsl:element name="表:精确度以显示值为准">
+ <xsl:attribute name="uof:locID">s0002</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="表:值"><xsl:value-of select="@table:precision-as-shown"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="表:日期系统-1904">
+ <xsl:attribute name="uof:locID">s0003</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="表:值"><xsl:choose><xsl:when test="table:null-date/@table:date-value='1904-01-01'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:if test="table:iteration/@table:status='enable'">
+ <表:计算设置 uof:locID="s0004" uof:attrList="迭代次数 偏差值">
+ <xsl:attribute name="表:迭代次数"><xsl:value-of select="table:iteration/@table:steps"/></xsl:attribute>
+ <xsl:attribute name="表:偏差值"><xsl:choose><xsl:when test="table:iteration/@table:maximum-difference"><xsl:value-of select="table:iteration/@table:maximum-difference"/></xsl:when><xsl:otherwise>0.001</xsl:otherwise></xsl:choose><!--xsl:value-of select="table:iteration/@table:maximum-difference"/--></xsl:attribute>
+ </表:计算设置>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="office:automatic-styles" mode="common">
+ <xsl:element name="表:条件格式化集">
+ <xsl:attribute name="uof:locID">s0016</xsl:attribute>
+ <xsl:variable name="temp-path" select="../office:automatic-styles/style:style"/>
+ <xsl:for-each select="$temp-path/style:map">
+ <xsl:element name="表:条件格式化">
+ <xsl:attribute name="uof:locID">s0017</xsl:attribute>
+ <xsl:element name="表:区域">
+ <xsl:attribute name="uof:locID">s0007</xsl:attribute>
+ <xsl:variable name="range-name">
+ <xsl:value-of select="substring-before(@style:base-cell-address,'.')"/>
+ </xsl:variable>
+ <xsl:variable name="range-value">
+ <xsl:value-of select="substring-after(@style:base-cell-address,'.')"/>
+ </xsl:variable>
+ <xsl:value-of select="concat(&quot;&apos;&quot;,$range-name,&quot;&apos;&quot;,'!$',substring($range-value,1,1),'$',substring($range-value,2))"/>
+ </xsl:element>
+ <xsl:element name="表:条件">
+ <xsl:attribute name="uof:locID">s0019</xsl:attribute>
+ <xsl:attribute name="表:类型"><xsl:choose><xsl:when test="contains(@style:condition,'formula')"><xsl:value-of select="'formula'"/></xsl:when><xsl:otherwise><xsl:value-of select="'cell value'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:element name="表:操作码">
+ <xsl:attribute name="uof:locID">s0009</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="contains(@style:condition,'!=')">
+ <xsl:value-of select="'not equal to'"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'&lt;=')">
+ <xsl:value-of select="'less than or equal to'"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'&gt;=')">
+ <xsl:value-of select="'greater than or equal to'"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'&lt;')">
+ <xsl:value-of select="'less than'"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'&gt;')">
+ <xsl:value-of select="'greater than'"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'=')">
+ <xsl:value-of select="'equal to'"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'not-between')">
+ <xsl:value-of select="'not-between'"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'between')">
+ <xsl:value-of select="'between'"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="表:第一操作数">
+ <xsl:attribute name="uof:locID">s0010</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="contains(@style:condition,'formula')">
+ <xsl:value-of select="substring-after(substring-before(@style:condition,')'),'(')"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'=')">
+ <xsl:value-of select="substring-after(@style:condition,'=')"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'&lt;') and not(contains(@style:condition,'&lt;='))">
+ <xsl:value-of select="substring-after(@style:condition,'&lt;')"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'&gt;') and not(contains(@style:condition,'&gt;='))">
+ <xsl:value-of select="substring-after(@style:condition,'&gt;')"/>
+ </xsl:when>
+ <xsl:when test="contains(@style:condition,'between')">
+ <xsl:value-of select="substring-before(substring-after(@style:condition,'('),',')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="contains(@style:condition,',')">
+ <xsl:element name="表:第二操作数">
+ <xsl:attribute name="uof:locID">s0011</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="contains(@style:condition,'between')">
+ <xsl:value-of select="substring-before(substring-after(@style:condition,','),')')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="表:格式">
+ <xsl:attribute name="uof:locID">s0023</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="表:式样引用"><xsl:value-of select="@style:apply-style-name"/></xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="table:content-validations" mode="common">
+ <xsl:element name="表:数据有效性集">
+ <xsl:attribute name="uof:locID">s0005</xsl:attribute>
+ <xsl:call-template name="create-validation-set">
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="create-validation-set">
+ <xsl:for-each select="//table:content-validation">
+ <xsl:element name="表:数据有效性">
+ <xsl:attribute name="uof:locID">s0006</xsl:attribute>
+ <xsl:variable name="conditiontext" select="@table:condition"/>
+ <xsl:variable name="operatortext" select="substring-after($conditiontext,'and ')"/>
+ <xsl:element name="表:区域">
+ <xsl:attribute name="uof:locID">s0007</xsl:attribute>
+ <xsl:variable name="left-top">
+ <xsl:call-template name="search-left-top-validation">
+ <xsl:with-param name="validation-name" select="@table:name"/>
+ <xsl:with-param name="tableslist" select="/*/office:body/office:spreadsheet/table:table"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="after-translated-left-top">
+ <xsl:call-template name="translate-left-top">
+ <xsl:with-param name="left-top" select="$left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="base" select="@table:base-cell-address"/>
+ <xsl:variable name="base-column-and-row" select="substring-after($base,'.')"/>
+ <xsl:variable name="dd" select="number(substring($base-column-and-row,2,1))"/>
+ <xsl:variable name="base-column">
+ <xsl:choose>
+ <xsl:when test="contains($dd,'NaN') ">
+ <xsl:value-of select="substring($base-column-and-row,1,2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring($base-column-and-row,1,1)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="base-row" select="substring-after($base,$base-column)"/>
+ <xsl:variable name="after-translated-base-left-top">
+ <xsl:value-of select="concat('$',substring-before($base,'.'),'.$',$base-column,'$',$base-row)"/>
+ </xsl:variable>
+ <xsl:value-of select="concat('$',$after-translated-left-top,':',$after-translated-base-left-top)"/>
+ </xsl:element>
+ <xsl:element name="表:校验类型">
+ <xsl:attribute name="uof:locID">s0008</xsl:attribute>
+ <xsl:variable name="listtest">cell-content-is-in-list("</xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($conditiontext,'cell-content-is-whole-number()')">whole number</xsl:when>
+ <xsl:when test="contains($conditiontext,'cell-content-is-decimal-number()')">decimal</xsl:when>
+ <xsl:when test="contains($conditiontext,'cell-content-is-date()')">date</xsl:when>
+ <xsl:when test="contains($conditiontext,'cell-content-is-time()')">time</xsl:when>
+ <xsl:when test="contains($conditiontext,'cell-content-is-in-list') and not(contains($conditiontext,$listtest))">cell range</xsl:when>
+ <xsl:when test="contains($conditiontext,'cell-content-is-in-list') and contains($conditiontext,$listtest)">list</xsl:when>
+ <xsl:when test="contains($conditiontext,'cell-content-text-length')">text length</xsl:when>
+ <xsl:otherwise>any value</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="表:操作码">
+ <xsl:attribute name="uof:locID">s0009</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="starts-with($operatortext,'cell-content()&lt;=')">less than or equal to</xsl:when>
+ <xsl:when test="starts-with($operatortext,'cell-content()&gt;=')">greater than or equal to</xsl:when>
+ <xsl:when test="starts-with($operatortext,'cell-content()&lt;')">less than</xsl:when>
+ <xsl:when test="starts-with($operatortext,'cell-content()&gt;')">greater than</xsl:when>
+ <xsl:when test="starts-with($operatortext,'cell-content()!=')">not equal to</xsl:when>
+ <xsl:when test="starts-with($operatortext,'cell-content()=')">equal to</xsl:when>
+ <xsl:when test="starts-with($conditiontext,'oooc:cell-content-text-length()')">
+ <xsl:variable name="operator" select="substring-after($conditiontext,'oooc:cell-content-text-length()')"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($operator,'&lt;=')">less than or equal to</xsl:when>
+ <xsl:when test="starts-with($operator,'&gt;=')">greater than or equal to</xsl:when>
+ <xsl:when test="starts-with($operator,'&lt;')">less than</xsl:when>
+ <xsl:when test="starts-with($operator,'&gt;')">greater than</xsl:when>
+ <xsl:when test="starts-with($operator,'!=')">not equal to</xsl:when>
+ <xsl:when test="starts-with($operator,'=')">equal to</xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="contains($conditiontext,'is-between')">between</xsl:when>
+ <xsl:when test="contains($conditiontext,'is-not-between')">not between</xsl:when>
+ <!-- 注意:uof有的另几种操作码在oo中没有,他们是contain,not contain,start with,not start with, end with,not end with-->
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="表:第一操作数">
+ <xsl:attribute name="uof:locID">s0010</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="starts-with($operatortext,'cell-content-is-between')">
+ <xsl:value-of select="substring-before(substring-after($operatortext,'cell-content-is-between('),',')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operatortext,'cell-content-is-not-between')">
+ <xsl:value-of select="substring-before(substring-after($operatortext,'cell-content-is-not-between('),',')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($conditiontext,'oooc:cell-content-text-length()')">
+ <xsl:variable name="operator" select="substring-after($conditiontext,'cell-content-text-length()')"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($operator,'&lt;=')">
+ <xsl:value-of select="substring-after($operator,'&lt;=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'&gt;=')">
+ <xsl:value-of select="substring-after($operator,'&gt;=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'&lt;')">
+ <xsl:value-of select="substring-after($operator,'&lt;')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'&gt;')">
+ <xsl:value-of select="substring-after($operator,'&gt;')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'!=')">
+ <xsl:value-of select="substring-after($operator,'!=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'=')">
+ <xsl:value-of select="substring-after($operator,'=')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with($conditiontext,'oooc:cell-content-is-in-list')">
+ <xsl:value-of select="substring-after($conditiontext,'oooc:cell-content-is-in-list')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($conditiontext,'oooc:cell-content-text-length-is-not-between')">
+ <xsl:value-of select="substring-before(substring-after($conditiontext,'oooc:cell-content-text-length-is-not-between('),',')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($conditiontext,'oooc:cell-content-text-length-is-between')">
+ <xsl:value-of select="substring-before(substring-after($conditiontext,'oooc:cell-content-text-length-is-between('),',')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operatortext,'cell-content()')">
+ <xsl:variable name="operator" select="substring-after($conditiontext,'oooc:cell-content()')"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($operator,'&lt;=')">
+ <xsl:value-of select="substring-after($operator,'&lt;=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'&gt;=')">
+ <xsl:value-of select="substring-after($operator,'&gt;=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'&lt;')">
+ <xsl:value-of select="substring-after($operator,'&lt;')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'&gt;')">
+ <xsl:value-of select="substring-after($operator,'&gt;')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'!=')">
+ <xsl:value-of select="substring-after($operator,'!=')"/>
+ </xsl:when>
+ <xsl:when test="starts-with($operator,'=')">
+ <xsl:value-of select="substring-after($operator,'=')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="starts-with($operatortext,'cell-content-is-between') or starts-with($operatortext,'cell-content-is-not-between')">
+ <xsl:element name="表:第二操作数">
+ <xsl:attribute name="uof:locID">s0011</xsl:attribute>
+ <xsl:value-of select="substring-before(substring-after($operatortext,','),')')"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="starts-with($conditiontext,'oooc:cell-content-text-length-is-not-between') or starts-with($conditiontext,'oooc:cell-content-text-length-is-between')">
+ <xsl:element name="表:第二操作数">
+ <xsl:attribute name="uof:locID">s0011</xsl:attribute>
+ <xsl:value-of select="substring-before(substring-after($conditiontext,','),')')"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="表:忽略空格">
+ <xsl:attribute name="uof:locID">s0012</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="表:值"><xsl:value-of select="@table:allow-empty-cell"/></xsl:attribute>
+ </xsl:element>
+ <xsl:if test="contains($conditiontext,'cell-content-is-in-list') ">
+ <xsl:element name="表:下拉箭头">
+ <xsl:attribute name="uof:locID">s0013</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="表:值">false</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="table:help-message">
+ <xsl:element name="表:输入提示">
+ <xsl:attribute name="uof:locID">s0014</xsl:attribute>
+ <xsl:attribute name="uof:attrList">显示 标题 内容</xsl:attribute>
+ <xsl:attribute name="表:显示"><xsl:value-of select="table:help-message/@table:display"/></xsl:attribute>
+ <xsl:attribute name="表:标题"><xsl:choose><xsl:when test="table:help-message/@table:title"><xsl:value-of select="table:help-message/@table:title"/></xsl:when><xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:variable name="content">
+ <xsl:call-template name="create-help-error-message-content">
+ <xsl:with-param name="text-p-set" select="table:help-message/text:p"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="表:内容"><xsl:value-of select="$content"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="table:error-message">
+ <xsl:element name="表:错误提示">
+ <xsl:attribute name="uof:locID">s0015</xsl:attribute>
+ <xsl:attribute name="uof:attrList">显示 类型 标题 内容</xsl:attribute>
+ <xsl:attribute name="表:显示"><xsl:value-of select="table:error-message/@table:display"/></xsl:attribute>
+ <xsl:attribute name="表:类型"><xsl:value-of select="table:error-message/@table:message-type"/></xsl:attribute>
+ <xsl:attribute name="表:标题"><xsl:choose><xsl:when test="table:error-message/@table:title"><xsl:value-of select="table:error-message/@table:title"/></xsl:when><xsl:otherwise><xsl:value-of select="''"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:variable name="content">
+ <xsl:call-template name="create-help-error-message-content">
+ <xsl:with-param name="text-p-set" select="table:error-message/text:p"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="表:内容"><xsl:value-of select="$content"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="search-left-top-validation">
+ <xsl:param name="validation-name"/>
+ <xsl:param name="tableslist"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$tableslist and $return=''">
+ <xsl:variable name="firsttablerows" select="$tableslist[1]//table:table-row"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-validation-inatable">
+ <xsl:with-param name="row-num" select="'1'"/>
+ <xsl:with-param name="firsttablerows" select="$firsttablerows"/>
+ <xsl:with-param name="validation-name" select="$validation-name"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-validation">
+ <xsl:with-param name="validation-name" select="$validation-name"/>
+ <xsl:with-param name="tableslist" select="$tableslist[position()!=1]"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top!=''">
+ <xsl:value-of select="$rest-left-top"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="translate-left-top">
+ <xsl:param name="left-top"/>
+ <xsl:variable name="column-number" select="substring-before(substring-after($left-top,'.'),' ')"/>
+ <xsl:variable name="column-number1">
+ <xsl:value-of select="floor( $column-number div 26 )"/>
+ </xsl:variable>
+ <xsl:variable name="column-number2">
+ <xsl:value-of select="$column-number mod 26"/>
+ </xsl:variable>
+ <xsl:variable name="column-character1">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="column-character2">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat(substring-before($left-top,'.'),'.','$',$column-character1,$column-character2,'$',substring-after($left-top,' '))"/>
+ </xsl:template>
+ <xsl:template name="create-help-error-message-content">
+ <xsl:param name="text-p-set"/>
+ <xsl:if test="$text-p-set">
+ <!--此处有问题!!!!应该是有一个模块调用等-->
+ <!--xsl:value-of select="'&#10;'"/-->
+ <xsl:value-of select="$text-p-set"/>
+ <xsl:call-template name="create-help-error-message-content">
+ <xsl:with-param name="text-p-set" select="$text-p-set[position()!=1]"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="search-left-top-validation-inatable">
+ <xsl:param name="row-num"/>
+ <xsl:param name="firsttablerows"/>
+ <xsl:param name="validation-name"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$firsttablerows and $return=''">
+ <xsl:variable name="firstcells" select="$firsttablerows[1]/table:table-cell"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-validation-inarow">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="column-num" select="'1'"/>
+ <xsl:with-param name="firstcells" select="$firstcells"/>
+ <xsl:with-param name="validation-name" select="$validation-name"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="row-num-p">
+ <xsl:choose>
+ <xsl:when test="$firsttablerows[1]/@table:number-rows-repeated">
+ <xsl:value-of select="$row-num+ $firsttablerows[1]/@table:number-rows-repeated"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$row-num+1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-validation-inatable">
+ <xsl:with-param name="row-num" select="$row-num-p"/>
+ <xsl:with-param name="firsttablerows" select="$firsttablerows[position()!=1]"/>
+ <xsl:with-param name="validation-name" select="$validation-name"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top !=''">
+ <xsl:value-of select="$rest-left-top "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="number-to-character">
+ <xsl:param name="number"/>
+ <xsl:choose>
+ <xsl:when test="$number = 0"/>
+ <xsl:when test="$number = 1">A</xsl:when>
+ <xsl:when test="$number = 2">B</xsl:when>
+ <xsl:when test="$number = 3">C</xsl:when>
+ <xsl:when test="$number = 4">D</xsl:when>
+ <xsl:when test="$number = 5">E</xsl:when>
+ <xsl:when test="$number = 6">F</xsl:when>
+ <xsl:when test="$number = 7">G</xsl:when>
+ <xsl:when test="$number = 8">H</xsl:when>
+ <xsl:when test="$number = 9">I</xsl:when>
+ <xsl:when test="$number = 10">J</xsl:when>
+ <xsl:when test="$number = 11">K</xsl:when>
+ <xsl:when test="$number = 12">L</xsl:when>
+ <xsl:when test="$number = 13">M</xsl:when>
+ <xsl:when test="$number = 14">N</xsl:when>
+ <xsl:when test="$number = 15">O</xsl:when>
+ <xsl:when test="$number = 16">P</xsl:when>
+ <xsl:when test="$number = 17">Q</xsl:when>
+ <xsl:when test="$number = 18">R</xsl:when>
+ <xsl:when test="$number = 19">S</xsl:when>
+ <xsl:when test="$number = 20">T</xsl:when>
+ <xsl:when test="$number = 21">U</xsl:when>
+ <xsl:when test="$number = 22">V</xsl:when>
+ <xsl:when test="$number = 23">W</xsl:when>
+ <xsl:when test="$number = 24">X</xsl:when>
+ <xsl:when test="$number = 25">Y</xsl:when>
+ <xsl:when test="$number = 26">Z</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="search-left-top-validation-inacell">
+ <xsl:param name="row-num"/>
+ <xsl:param name="column-num"/>
+ <xsl:param name="cell"/>
+ <xsl:param name="validation-name"/>
+ <xsl:choose>
+ <xsl:when test="$cell/@table:content-validation-name=$validation-name">
+ <xsl:value-of select="concat($cell/ancestor::table:table/@table:name,'.',$column-num,' ',$row-num)"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="search-left-top-validation-inarow">
+ <xsl:param name="row-num"/>
+ <xsl:param name="column-num"/>
+ <xsl:param name="firstcells"/>
+ <xsl:param name="validation-name"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$firstcells and $return=''">
+ <xsl:variable name="firstcell" select="$firstcells[1]"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-validation-inacell">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="column-num" select="$column-num"/>
+ <xsl:with-param name="cell" select="$firstcell"/>
+ <xsl:with-param name="validation-name" select="$validation-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="column-num-p">
+ <xsl:choose>
+ <xsl:when test="$firstcell/@table:number-columns-repeated">
+ <xsl:value-of select="$column-num+ $firstcell/@table:number-columns-repeated"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$column-num+ 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-validation-inarow">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="column-num" select="$column-num-p"/>
+ <xsl:with-param name="firstcells" select="$firstcells[position()!=1]"/>
+ <xsl:with-param name="validation-name" select="$validation-name"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top !=''">
+ <xsl:value-of select="$rest-left-top "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/uof/odf2uof_text.xsl b/filter/source/xslt/export/uof/odf2uof_text.xsl
new file mode 100644
index 000000000..4ca67c256
--- /dev/null
+++ b/filter/source/xslt/export/uof/odf2uof_text.xsl
@@ -0,0 +1,4456 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:图="http://schemas.uof.org/cn/2003/graph" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" office:version="1.0" exclude-result-prefixes="office style text table draw fo xlink dc meta number presentation svg chart dr3d math form script config ooo ooow oooc dom xforms smil anim">
+ <xsl:output method="xml" indent="no" encoding="UTF-8" version="1.0"/>
+ <!--xsl:key name="colWidth" match="/office:automatic/style:style/" use="@style:column-width"/-->
+ <xsl:variable name="swValueWithUnit">
+ <xsl:value-of select="/office:document/office:automatic-styles/style:page-layout/style:page-layout-properties/@fo:page-width"/>
+ </xsl:variable>
+ <xsl:variable name="uofUnit">
+ <xsl:choose>
+ <xsl:when test="contains($swValueWithUnit,'in')">inch</xsl:when>
+ <xsl:when test="contains($swValueWithUnit,'cm')">cm</xsl:when>
+ <xsl:when test="contains($swValueWithUnit,'mm')">mm</xsl:when>
+ <xsl:when test="contains($swValueWithUnit,'pt')">pt</xsl:when>
+ <xsl:otherwise>inch</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="ooUnit">
+ <xsl:choose>
+ <xsl:when test="contains($swValueWithUnit,'in')">inch</xsl:when>
+ <xsl:when test="contains($swValueWithUnit,'cm')">cm</xsl:when>
+ <xsl:when test="contains($swValueWithUnit,'mm')">mm</xsl:when>
+ <xsl:when test="contains($swValueWithUnit,'pt')">pt</xsl:when>
+ <xsl:otherwise>inch</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:template match="/">
+ <xsl:apply-templates select="office:document"/>
+ </xsl:template>
+ <xsl:template match="office:document">
+ <uof:UOF xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:图="http://schemas.uof.org/cn/2003/graph" uof:language="cn" uof:locID="u0000" uof:version="1.0" uof:mimetype="vnd.uof.text">
+ <xsl:apply-templates select="office:meta"/>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:bookmark-start|/office:document/office:body/office:text/text:p/text:bookmark">
+ <uof:书签集 uof:locID="u0027">
+ <xsl:for-each select="/office:document/office:body/office:text/text:p/text:bookmark-start|/office:document/office:body/office:text/text:p/text:bookmark">
+ <uof:书签 uof:locID="u0028" uof:attrList="名称">
+ <xsl:attribute name="uof:名称"><xsl:value-of select="@text:name"/></xsl:attribute>
+ <uof:文本位置 uof:locID="u0029" uof:attrList="区域引用">
+ <xsl:attribute name="字:区域引用"><xsl:value-of select="generate-id()"/></xsl:attribute>
+ </uof:文本位置>
+ </uof:书签>
+ </xsl:for-each>
+ </uof:书签集>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:a | /office:document/office:body/office:text/text:p/draw:a | /office:document/office:body/office:text/table:table/table:table-row/table:table-cell/text:p/text:a | /office:document/office:body/office:text/text:table-of-content/text:index-body/text:p/text:a">
+ <uof:链接集 uof:locID="u0031">
+ <xsl:for-each select="/office:document/office:body/office:text/text:p/text:a | /office:document/office:body/office:text/text:p/draw:a | /office:document/office:body/office:text/table:table/table:table-row/table:table-cell/text:p/text:a | /office:document/office:body/office:text/text:table-of-content/text:index-body/text:p/text:a">
+ <xsl:variable name="hyperStr" select="@xlink:href"/>
+ <uof:超级链接 uof:locID="u0032" uof:attrList="标识符 目标 书签 式样引用 已访问式样引用 提示 链源">
+ <xsl:if test="contains($hyperStr,'#')">
+ <xsl:attribute name="uof:书签"><xsl:value-of select="substring-after($hyperStr,'#')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="num">
+ <xsl:number from="/office:document/office:body/office:text" level="any" count="text:a | table:table/table:table-row/table:table-cell/text:a"/>
+ </xsl:variable>
+ <xsl:attribute name="uof:链源"><xsl:value-of select="concat('hlnk',$num)"/></xsl:attribute>
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat('hyk_','hlnk',$num)"/></xsl:attribute>
+ <xsl:if test="not(contains($hyperStr,'#'))">
+ <xsl:attribute name="uof:目标"><xsl:value-of select="$hyperStr"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@office:name">
+ <xsl:attribute name="uof:提示"><xsl:value-of select="@office:name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@text:style-name">
+ <xsl:attribute name="uof:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@text:visited-style-name">
+ <xsl:attribute name="uof:已访问式样引用"><xsl:value-of select="@text:visited-style-name"/></xsl:attribute>
+ </xsl:if>
+ </uof:超级链接>
+ </xsl:for-each>
+ </uof:链接集>
+ </xsl:if>
+ <uof:式样集 uof:locID="u0039">
+ <xsl:apply-templates select="office:font-face-decls"/>
+ <xsl:call-template name="自动编号集"/>
+ <xsl:call-template name="shiyang"/>
+ <xsl:apply-templates select="office:automatic-styles/style:style" mode="style"/>
+ </uof:式样集>
+ <uof:对象集 uof:locID="u0033">
+ <xsl:for-each select="/office:document/office:body/office:text/draw:*">
+ <xsl:variable name="nodename1">
+ <xsl:value-of select="name()"/>
+ </xsl:variable>
+ <xsl:call-template name="draw">
+ <xsl:with-param name="nodename1" select="$nodename1"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ <xsl:apply-templates select="/office:document/office:body/office:text//text:p" mode="styles"/>
+ <xsl:apply-templates select="/office:document/office:master-styles/style:master-page/style:header/text:p" mode="styles"/>
+ <xsl:apply-templates select="/office:document/office:master-styles/style:master-page/style:footer/text:p" mode="styles"/>
+ <xsl:for-each select="(/office:document/office:styles/style:style/style:paragraph-properties/style:background-image) | (/office:document/office:automatic-styles/style:style/style:paragraph-properties/style:background-image) | (/office:document/office:automatic-styles/style:page-layout/style:page-layout-properties/style:background-image) | /office:document/office:automatic-styles/style:style/style:table-cell-properties/style:background-image | /office:document/office:automatic-styles/style:style/style:table-properties/style:background-image | /office:document/office:automatic-styles/style:style/style:graphic-properties/style:background-image">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat('background-image_',count(preceding::style:background-image))"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="office:binary-data"/>
+ </uof:数据>
+ </uof:其他对象>
+ </xsl:for-each>
+ <xsl:for-each select="(/office:document/office:styles/text:list-style/text:list-level-style-image) | (/office:document/office:automatic-styles/text:list-style/text:list-level-style-image)">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat('image_numbering_',count(preceding::text:list-level-style-image))"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="office:binary-data"/>
+ </uof:数据>
+ </uof:其他对象>
+ </xsl:for-each>
+ <xsl:for-each select="/office:document/office:styles/draw:fill-image">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="@draw:name"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="office:binary-data"/>
+ </uof:数据>
+ </uof:其他对象>
+ </xsl:for-each>
+ <!--xsl:apply-templates select="/office:document/office:automatic-styles/style:style[@style:family = 'graphics']"/>
+ <xsl:apply-templates select="office:styles/style:style[@style:family = 'graphics']"/>
+ <xsl:apply-templates select="office:styles/style:default-style [@style:family = 'graphics']"/-->
+ </uof:对象集>
+ <uof:文字处理 uof:locID="u0047">
+ <字:公用处理规则 uof:locID="t0000">
+ <xsl:apply-templates select="office:settings"/>
+ <xsl:call-template name="GetUsers"/>
+ <xsl:call-template name="GetTrackChanges"/>
+ <xsl:call-template name="GetAnnotations"/>
+ </字:公用处理规则>
+ <字:主体 uof:locID="t0016">
+ <xsl:for-each select="office:automatic-styles/style:page-layout[@style:name='pm1']">
+ <xsl:call-template name="style:page-layout"/>
+ </xsl:for-each>
+ <!--xsl:call-template name="office:automatic-styles/style:page-layout[@style:name='pm1']"/-->
+ <!--xsl:apply-templates select="office:automatic-styles/style:page-layout[@style:name='pm1']"/-->
+ <xsl:apply-templates select="office:body/office:text"/>
+ <xsl:call-template name="logic-chapter"/>
+ </字:主体>
+ </uof:文字处理>
+ </uof:UOF>
+ </xsl:template>
+ <xsl:template name="logic-chapter">
+ <xsl:element name="字:逻辑章节">
+ <xsl:attribute name="uof:locID">t0050</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="GetAnnotations">
+ <xsl:if test="/*/office:body/office:text//office:annotation ">
+ <字:批注集 uof:locID="t0014">
+ <xsl:for-each select="/*/office:body/office:text//office:annotation">
+ <字:批注 uof:locID="t0015" uof:attrList="区域引用 作者 日期 作者缩写">
+ <xsl:attribute name="字:作者"><xsl:value-of select="generate-id()"/></xsl:attribute>
+ <xsl:attribute name="字:日期"><xsl:value-of select="dc:date"/></xsl:attribute>
+ <xsl:attribute name="字:区域引用">cmt<xsl:number from="/office:document/office:body/office:text" level="any" count="office:annotation"/></xsl:attribute>
+ <xsl:for-each select="./node()">
+ <xsl:choose>
+ <xsl:when test="name()='text:p'">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name()='table:table'">
+ <xsl:call-template name="exec_table"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </字:批注>
+ </xsl:for-each>
+ </字:批注集>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="GetTrackChanges">
+ <xsl:if test="/*/office:body/office:text/text:tracked-changes">
+ <字:修订信息集 uof:locID="t0012">
+ <xsl:for-each select="/*/office:body/office:text/text:tracked-changes/text:changed-region">
+ <字:修订信息 字:标识符="{@text:id}" 字:作者="{generate-id()}" 字:日期="{node()//office:change-info/dc:date}" uof:locID="t0013" uof:attrList="标识符 作者 日期"/>
+ </xsl:for-each>
+ </字:修订信息集>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="GetUsers">
+ <xsl:if test="/*/office:body/office:text/text:tracked-changes//office:change-info/dc:creator or //office:annotation/@office:author or //office:annotation/dc:creator">
+ <字:用户集 uof:locID="t0010">
+ <xsl:for-each select="/*/office:body/office:text/text:tracked-changes/text:changed-region">
+ <字:用户 字:标识符="{generate-id()}" 字:姓名="{node()//office:change-info/dc:creator}" uof:locID="t0011" uof:attrList="标识符 姓名"/>
+ </xsl:for-each>
+ <xsl:for-each select="//office:annotation">
+ <字:用户 字:标识符="{generate-id()}" 字:姓名="{dc:creator}" uof:locID="t0011" uof:attrList="标识符 姓名"/>
+ </xsl:for-each>
+ </字:用户集>
+ </xsl:if>
+ </xsl:template>
+ <xsl:key match="/office:document/office:automatic-styles/style:style | /office:document/office:styles/style:style" name="graphicset" use="@style:name"/>
+ <xsl:template match="text:p" mode="styles">
+ <xsl:for-each select="child::*">
+ <xsl:variable name="nodename1">
+ <xsl:value-of select="name()"/>
+ </xsl:variable>
+ <xsl:if test="(substring-before($nodename1,':') = 'draw')">
+ <xsl:call-template name="draw">
+ <xsl:with-param name="nodename1" select="$nodename1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="draw">
+ <xsl:param name="nodename1"/>
+ <xsl:choose>
+ <xsl:when test="substring-after($nodename1,':') = 'a'">
+ <xsl:for-each select="child::*">
+ <xsl:call-template name="draw">
+ <xsl:with-param name="nodename">
+ <xsl:value-of select="name()"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="substring-after($nodename1,':') = 'g'">
+ <xsl:call-template name="draw:g"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="draw:g">
+ <xsl:variable name="picnumber1">
+ <xsl:value-of select="count(preceding::draw:g)"/>
+ </xsl:variable>
+ <图:图形 uof:locID="g0000" uof:attrList="层次 标识符 组合列表 其他对象">
+ <xsl:attribute name="图:标识符"><xsl:value-of select="concat(@draw:style-name,'_',$picnumber1)"/></xsl:attribute>
+ <xsl:attribute name="图:层次"><xsl:choose><xsl:when test="name(parent::node())='draw:g'"><xsl:value-of select="position()"/></xsl:when><xsl:when test="@draw:z-index"><xsl:value-of select="@draw:z-index"/></xsl:when><xsl:otherwise><xsl:value-of select="position()"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:组合列表"><xsl:for-each select="child::*[1]"><xsl:variable name="node1"><xsl:value-of select="@draw:style-name"/></xsl:variable><xsl:variable name="picnumber2"><xsl:value-of select="count(preceding::*[@draw:style-name=$node1])"/></xsl:variable><xsl:call-template name="zuheliebiao"><xsl:with-param name="allnode"><xsl:value-of select="concat($node1,'_',$picnumber2)"/></xsl:with-param><xsl:with-param name="pos" select="2"/></xsl:call-template></xsl:for-each></xsl:attribute>
+ </图:图形>
+ <xsl:for-each select="child::*">
+ <xsl:choose>
+ <xsl:when test="name()='draw:g'">
+ <xsl:call-template name="draw:g"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="creategraphicstyles"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="zuheliebiao">
+ <xsl:param name="allnode"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="../child::*[$pos]">
+ <xsl:for-each select="../child::*[$pos]">
+ <xsl:variable name="nodepos">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="picnumber1">
+ <xsl:value-of select="count(preceding::*[@draw:style-name=$nodepos])"/>
+ </xsl:variable>
+ <xsl:variable name="pic-name1">
+ <xsl:value-of select="concat($nodepos,'_',$picnumber1)"/>
+ </xsl:variable>
+ <xsl:variable name="allnode1">
+ <xsl:value-of select="concat($allnode,',',$pic-name1)"/>
+ </xsl:variable>
+ <xsl:call-template name="zuheliebiao">
+ <xsl:with-param name="allnode" select="$allnode1"/>
+ <xsl:with-param name="pos" select="$pos+1"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$allnode"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="creategraphicstyles">
+ <xsl:variable name="nodename">
+ <xsl:value-of select="name()"/>
+ </xsl:variable>
+ <xsl:variable name="pic-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="pic-num">
+ <xsl:value-of select="count(/descendant::*[@draw:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:variable name="picnumber">
+ <xsl:value-of select="count(preceding::*[@draw:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:call-template name="pic-process">
+ <xsl:with-param name="pic-name" select="$pic-name"/>
+ <xsl:with-param name="nodename" select="$nodename"/>
+ <xsl:with-param name="picnumber" select="$picnumber"/>
+ </xsl:call-template>
+ </xsl:template>
+ <!--xsl:key match="/office:document/office:automatic-styles/style:style" name="graphicset" use="@style:name"/>
+
+ <xsl:template match="style:style[@style:family = 'graphics']">
+ <xsl:variable name="pic-name">
+ <xsl:value-of select="@style:name"/>
+ </xsl:variable>
+ <xsl:variable name="pic-num">
+ <xsl:value-of select="count(/descendant::*[@draw:style-name=$pic-name])"/>
+ </xsl:variable>
+ <xsl:call-template name="pic-process">
+ <xsl:with-param name="pic-name" select="$pic-name"/>
+ <xsl:with-param name="pic-num" select="$pic-num"/>
+ <xsl:with-param name="current-num" select="1"/>
+ </xsl:call-template>
+ </xsl:template-->
+ <xsl:template name="pic-process">
+ <xsl:param name="pic-name"/>
+ <xsl:param name="nodename"/>
+ <xsl:param name="picnumber"/>
+ <图:图形 uof:locID="g0000" uof:attrList="层次 标识符 组合列表 其他对象">
+ <xsl:attribute name="图:标识符"><xsl:value-of select="concat($pic-name,'_',$picnumber)"/></xsl:attribute>
+ <xsl:attribute name="图:层次"><xsl:value-of select="@draw:z-index"/></xsl:attribute>
+ <xsl:if test=".//office:binary-data">
+ <xsl:attribute name="图:其他对象"><xsl:choose><xsl:when test="@draw:name"><xsl:value-of select="@draw:name"/></xsl:when><xsl:otherwise><xsl:value-of select="concat($pic-name,'_b1')"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="arrow-sign">
+ <xsl:choose>
+ <xsl:when test="key('graphicset',$pic-name)/style:graphic-properties/@draw:marker-start or key('graphicset',$pic-name)/style:graphic-properties/@draw:marker-end">
+ <xsl:value-of select="'1'"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:line' or $nodename='draw:rect' or $nodename='draw:circle' or $nodename='draw:polygon' or $nodename='draw:polyline' or $nodename='draw:ellipse' or $nodename='draw:path'or $nodename='draw:g' or $nodename='draw:text-box' or child::draw:text-box">
+ <图:预定义图形 uof:locID="g0005">
+ <图:类别 uof:locID="g0006">
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:line' and $arrow-sign='1'">62</xsl:when>
+ <xsl:when test="$nodename='draw:rect'">11</xsl:when>
+ <xsl:when test="$nodename='draw:line'">61</xsl:when>
+ <xsl:when test="$nodename='draw:circle'">19</xsl:when>
+ <xsl:when test="$nodename='draw:polygon'">65</xsl:when>
+ <xsl:when test="$nodename='draw:polyline'">66</xsl:when>
+ <xsl:when test="$nodename='draw:ellipse'">19</xsl:when>
+ <xsl:when test="child::draw:text-box[@fo:min-height]">22</xsl:when>
+ <xsl:when test="child::draw:text-box">23</xsl:when>
+ </xsl:choose>
+ </图:类别>
+ <图:名称 uof:locID="g0007">
+ <xsl:choose>
+ <xsl:when test="$nodename='draw:rect'">Rectangle</xsl:when>
+ <xsl:when test="$nodename='draw:line'">Line</xsl:when>
+ <xsl:when test="$nodename='draw:circle'">Oval</xsl:when>
+ <xsl:when test="$nodename='draw:polygon'">Freeform</xsl:when>
+ <xsl:when test="$nodename='draw:polyline'">Scribble</xsl:when>
+ <xsl:when test="$nodename='draw:ellipse'">Oval</xsl:when>
+ <xsl:when test="$nodename='draw:frame' and child::draw:text-box[@fo:min-height]">排版框</xsl:when>
+ <xsl:when test="$nodename='draw:frame' and child::draw:text-box">排版框</xsl:when>
+ </xsl:choose>
+ </图:名称>
+ <图:生成软件 uof:locID="g0008">PNG</图:生成软件>
+ <xsl:if test="./@draw:points or ./@svg:d">
+ <图:关键点坐标 uof:locID="g0009" uof:attrList="路径">
+ <xsl:attribute name="图:路径"><xsl:choose><xsl:when test="@svg:d"><xsl:value-of select="@svg:d"/></xsl:when><xsl:when test="@draw:points"><xsl:call-template name="draw:points"><xsl:with-param name="point" select="@draw:points"/><xsl:with-param name="lujing"/></xsl:call-template></xsl:when></xsl:choose></xsl:attribute>
+ </图:关键点坐标>
+ </xsl:if>
+ <图:属性 uof:locID="g0011">
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$pic-name]) | (/office:document/office:automatic-styles/descendant::*[@style:name=$pic-name]) ">
+ <xsl:if test="style:graphic-properties/@draw:fill-color or style:graphic-properties/@fo:background-color or style:graphic-properties/@draw:fill-image-name or style:graphic-properties/@draw:fill-gradient-name">
+ <图:填充 uof:locID="g0012">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:fill='gradient'">
+ <xsl:variable name="gradient-name">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-gradient-name"/>
+ </xsl:variable>
+ <xsl:for-each select="/descendant::draw:gradient[@draw:name=$gradient-name]">
+ <图:渐变 uof:locID="g0037" uof:attrList="起始色 终止色 种子类型 起始浓度 终止浓度 渐变方向 边界 种子X位置 种子Y位置 类型">
+ <xsl:attribute name="图:起始色"><xsl:value-of select="@draw:start-color"/></xsl:attribute>
+ <xsl:attribute name="图:终止色"><xsl:value-of select="@draw:end-color"/></xsl:attribute>
+ <xsl:attribute name="图:种子类型"><xsl:choose><xsl:when test="@draw:style='linear' or @draw:style='axial'">linear</xsl:when><xsl:when test="@draw:style='radial'">radar</xsl:when><xsl:when test="@draw:style='ellipsoid'">oval</xsl:when><xsl:when test="@draw:style='square'">square</xsl:when><xsl:when test="@draw:style='rectangular'">rectangle</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:起始浓度"><xsl:value-of select="substring-before(@draw:start-intensity,'%')"/></xsl:attribute>
+ <xsl:attribute name="图:终止浓度"><xsl:value-of select="substring-before(@draw:end-intensity,'%')"/></xsl:attribute>
+ <xsl:variable name="angle">
+ <xsl:value-of select="@draw:angle div 10"/>
+ </xsl:variable>
+ <xsl:attribute name="图:渐变方向"><xsl:choose><xsl:when test="0&lt;$angle and $angle&lt;25">0</xsl:when><xsl:when test="25&lt;$angle and $angle&lt;70">45</xsl:when><xsl:when test="70&lt;$angle and $angle&lt;115">90</xsl:when><xsl:when test="115&lt;$angle and $angle&lt;160">135</xsl:when><xsl:when test="160&lt;$angle and $angle&lt;205">180</xsl:when><xsl:when test="205&lt;$angle and $angle&lt;250">225</xsl:when><xsl:when test="250&lt;$angle and $angle&lt;295">270</xsl:when><xsl:when test="295&lt;$angle and $angle&lt;340">315</xsl:when><xsl:when test="340&lt;$angle and $angle&lt;360">360</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:边界"><xsl:value-of select="substring-before(@draw:border,'%')"/></xsl:attribute>
+ <xsl:if test="@draw:cx">
+ <xsl:attribute name="图:种子X位置"><xsl:value-of select="substring-before(@draw:cx,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@draw:cy">
+ <xsl:attribute name="图:种子Y位置"><xsl:value-of select="substring-before(@draw:cy,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:类型">-2</xsl:attribute>
+ </图:渐变>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:fill-image-name or style:graphic-properties/style:background-image/office:binary-data">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:fill-image-name">
+ <图:图片 uof:locID="g0035" uof:attrList="位置 图形引用 类型 名称">
+ <xsl:attribute name="图:位置"><xsl:choose><xsl:when test="not(style:graphic-properties/@style:repeat)">tile</xsl:when><xsl:otherwise><xsl:choose><xsl:when test="style:graphic-properties/@style:repeat = 'stretch'">stretch</xsl:when><xsl:when test="style:graphic-properties/@style:repeat = 'repeat'">tile</xsl:when><xsl:when test="style:graphic-properties/@style:repeat = 'no-repeat'">center</xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:图形引用"><xsl:value-of select="concat($pic-name,'_b1')"/></xsl:attribute>
+ <xsl:attribute name="图:类型">png</xsl:attribute>
+ <xsl:attribute name="图:名称"><xsl:value-of select="style:graphic-properties/@draw:fill-image-name"/></xsl:attribute>
+ </图:图片>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/style:background-image/office:binary-data">
+ <xsl:for-each select="style:graphic-properties">
+ <xsl:call-template name="图:填充"/>
+ </xsl:for-each>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:fill='hatch'">
+ <图:图案 uof:locID="g0036" uof:attrList="类型 图形引用 前景色 背景色">
+ <xsl:attribute name="图:类型"><xsl:value-of select="/office:document/office:styles/draw:hatch/@draw:name"/></xsl:attribute>
+ <xsl:attribute name="图:图形引用"/>
+ <xsl:attribute name="图:前景色"><xsl:value-of select="/office:document/office:styles/draw:hatch/@draw:color"/></xsl:attribute>
+ <xsl:attribute name="图:背景色"><xsl:choose><xsl:when test="style:graphic-properties/@draw:fill-color"><xsl:value-of select="style:graphic-properties/@draw:fill-color"/></xsl:when><xsl:otherwise>#ffffff</xsl:otherwise></xsl:choose></xsl:attribute>
+ </图:图案>
+ </xsl:when>
+ <xsl:otherwise>
+ <图:颜色 uof:locID="g0034">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:fill-color">
+ <xsl:value-of select="style:graphic-properties/@draw:fill-color"/>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@fo:background-color">
+ <xsl:value-of select="style:graphic-properties/@fo:background-color"/>
+ </xsl:when>
+ <xsl:otherwise>#99ccff</xsl:otherwise>
+ </xsl:choose>
+ </图:颜色>
+ </xsl:otherwise>
+ </xsl:choose>
+ </图:填充>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@svg:stroke-color">
+ <图:线颜色 uof:locID="g0013">
+ <xsl:value-of select="style:graphic-properties/@svg:stroke-color"/>
+ </图:线颜色>
+ </xsl:if>
+ <图:线型 uof:locID="g0014">
+ <xsl:variable name="linetype" select="style:graphic-properties/@draw:stroke-dash"/>
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@fo:border='none'">none</xsl:when>
+ <xsl:when test="not(style:graphic-properties/@draw:stroke)">
+ <xsl:choose>
+ <xsl:when test="not(style:graphic-properties/@svg:stroke-width)">single</xsl:when>
+ <xsl:otherwise>thick</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:stroke = 'none'">none</xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$linetype='Fine_20_Dashed' and style:graphic-properties/@svg:stroke-width">dash-long-heavy</xsl:when>
+ <xsl:when test="$linetype='Fine_20_Dashed'">dash-long</xsl:when>
+ <xsl:when test="$linetype='2 Dots 1 Dash' and style:graphic-properties/@svg:stroke-width">dash-dot-dot-heavy</xsl:when>
+ <xsl:when test="$linetype='2 Dots 1 Dash'">dot-dot-dash</xsl:when>
+ <xsl:when test="$linetype='Ultrafine Dashed' and style:graphic-properties/@svg:stroke-width">dashed-heavy</xsl:when>
+ <xsl:when test="$linetype='Ultrafine Dotted (var)'and style:graphic-properties/@svg:stroke-width">dotted-heavy</xsl:when>
+ <xsl:when test="$linetype='Ultrafine Dotted (var)'">dotted</xsl:when>
+ <xsl:when test="$linetype='Line with Fine Dots'">double</xsl:when>
+ <xsl:when test="$linetype='3 Dashes 3 Dots (var)' and style:graphic-properties/@svg:stroke-width">dash-dot-heavy</xsl:when>
+ <xsl:when test="$linetype='3 Dashes 3 Dots (var)'">dot-dash</xsl:when>
+ <xsl:when test="$linetype='Ultrafine 2 Dots 3 Dashes'and style:graphic-properties/@svg:stroke-width">wavy-heavy</xsl:when>
+ <xsl:when test="$linetype='Ultrafine 2 Dots 3 Dashes'">wave</xsl:when>
+ <xsl:when test="$linetype='Fine Dashed (var)'">wavy-double</xsl:when>
+ <xsl:otherwise>dash</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </图:线型>
+ <xsl:if test="style:graphic-properties/@svg:stroke-width">
+ <图:线粗细 uof:locID="g0016">
+ <xsl:value-of select="substring-before(style:graphic-properties/@svg:stroke-width,$uofUnit)"/>
+ </图:线粗细>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:marker-start and string-length(style:graphic-properties/@draw:marker-start)&gt;0">
+ <图:前端箭头 uof:locID="g0017">
+ <图:式样 uof:locID="g0018">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Arrow'">normal</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Line Arrow'">open</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Arrow concave'">stealth</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Circle'">oval</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-start='Square 45'">diamond</xsl:when>
+ <xsl:otherwise>normal</xsl:otherwise>
+ </xsl:choose>
+ </图:式样>
+ <图:大小 uof:locID="g0019">
+ <xsl:choose>
+ <xsl:when test="not(style:graphic-properties/@draw:marker-start-width)">4</xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="graphsize">
+ <xsl:with-param name="width" select="substring-before(style:graphic-properties/@draw:marker-start-width,$uofUnit)"/>
+ <xsl:with-param name="Unitofsize" select="$uofUnit"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </图:大小>
+ </图:前端箭头>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:marker-end">
+ <图:后端箭头 uof:locID="g0017">
+ <图:式样 uof:locID="g0018">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Arrow'">normal</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Line Arrow'">open</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Arrow concave'">stealth</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Circle'">oval</xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:marker-end='Square 45'">diamond</xsl:when>
+ <xsl:otherwise>normal</xsl:otherwise>
+ </xsl:choose>
+ </图:式样>
+ <图:大小 uof:locID="g0022">
+ <xsl:choose>
+ <xsl:when test="not(style:properties/@draw:marker-start-width)">4</xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="width">
+ <xsl:value-of select="substring-before(style:graphic-properties/@draw:marker-end-width,$uofUnit)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="(not($width&gt;0.05) and 0&lt;$width) or $width=0.05">1</xsl:when>
+ <xsl:when test="(not($width&gt;0.10) and 0.05&lt;$width) or $width=0.10">2</xsl:when>
+ <xsl:when test="(not($width&gt;0.15) and 0.10&lt;$width) or $width=0.15">3</xsl:when>
+ <xsl:when test="(not($width&gt;0.20) and 0.15&lt;$width) or $width=0.20">4</xsl:when>
+ <xsl:when test="(not($width&gt;0.25) and 0.20&lt;$width) or $width=0.25">5</xsl:when>
+ <xsl:when test="(not($width&gt;0.30) and 0.25&lt;$width) or $width=0.30">6</xsl:when>
+ <xsl:when test="(not($width&gt;0.35) and 0.30&lt;$width) or $width=0.35">7</xsl:when>
+ <xsl:when test="(not($width&gt;0.40) and 0.35&lt;$width) or $width=0.40">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </图:大小>
+ </图:后端箭头>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:opacity or style:graphic-properties/@draw:transparency">
+ <图:透明度 uof:locID="g0038">
+ <xsl:choose>
+ <xsl:when test="style:graphic-properties/@draw:transparency">
+ <xsl:value-of select="substring-before(style:graphic-properties/@draw:transparency,'%')"/>
+ </xsl:when>
+ <xsl:when test="style:graphic-properties/@draw:opacity">
+ <xsl:value-of select="100 - substring-before(style:graphic-properties/@draw:opacity,'%')"/>
+ </xsl:when>
+ </xsl:choose>
+ </图:透明度>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="@svg:x1">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:x2,$uofUnit) - substring-before(@svg:x1,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:y2,$uofUnit) - substring-before(@svg:y1,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="@svg:x">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="child::draw:text-box/@fo:min-height">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(child::draw:text-box/@fo:min-height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ <xsl:when test="@svg:width">
+ <图:宽度 uof:locID="g0023">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </图:宽度>
+ <图:高度 uof:locID="g0024">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </图:高度>
+ </xsl:when>
+ </xsl:choose>
+ <图:旋转角度 uof:locID="g0025">
+ <xsl:choose>
+ <xsl:when test="@draw:transform">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="@draw:transform"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-temp">
+ <xsl:value-of select="substring-before(substring-after($rotate-angle,'rotate ('),')')"/>
+ </xsl:variable>
+ <xsl:value-of select="($rotate-temp * 360) div (2 * 3.14159265)"/>
+ </xsl:when>
+ <xsl:otherwise>0.0</xsl:otherwise>
+ </xsl:choose>
+ </图:旋转角度>
+ <图:X-缩放比例 uof:locID="g0026">1</图:X-缩放比例>
+ <图:Y-缩放比例 uof:locID="g0027">1</图:Y-缩放比例>
+ <图:锁定纵横比 uof:locID="g0028">0</图:锁定纵横比>
+ <图:相对原始比例 uof:locID="g0029">1</图:相对原始比例>
+ <图:打印对象 uof:locID="g0032">true</图:打印对象>
+ <图:Web文字 uof:locID="g0033"/>
+ </图:属性>
+ </图:预定义图形>
+ </xsl:when>
+ <xsl:when test="name()='draw:path'">
+ <图:svg图形对象 图:version="1.1" 图:xmlns_xlink="http://www.w3.org/1999/xlink">
+ <xsl:attribute name="图:x"><xsl:value-of select="@svg:x"/></xsl:attribute>
+ <xsl:attribute name="图:y"><xsl:value-of select="@svg:y"/></xsl:attribute>
+ <xsl:attribute name="图:width"><xsl:value-of select="@svg:width"/></xsl:attribute>
+ <xsl:attribute name="图:height"><xsl:value-of select="@svg:height"/></xsl:attribute>
+ <xsl:attribute name="图:viewBox"><xsl:value-of select="@svg:viewBox"/></xsl:attribute>
+ <图:path>
+ <xsl:attribute name="图:d"><xsl:value-of select="@svg:d"/></xsl:attribute>
+ </图:path>
+ </图:svg图形对象>
+ </xsl:when>
+ </xsl:choose>
+ <图:文本内容 uof:locID="g0002" uof:attrList="文本框 左边距 右边距 上边距 下边距 水平对齐 垂直对齐 文字排列方向 自动换行 大小适应文字 前一链接 后一链接">
+ <xsl:if test="./draw:text-box">
+ <xsl:attribute name="图:文本框">true</xsl:attribute>
+ <xsl:if test="./@draw:name = /office:document/office:body/office:text//draw:text-box/@draw:chain-next-name">
+ <xsl:attribute name="图:前一链接"><xsl:variable name="drawname"><xsl:value-of select="./@draw:name"/></xsl:variable><xsl:variable name="befor-link-name"><xsl:value-of select="/office:document/office:body/office:text//draw:text-box[@draw:name=$drawname]/@draw:style-name"/></xsl:variable><xsl:value-of select="concat($befor-link-name,'_',$picnumber)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="./@draw:chain-next-name">
+ <xsl:attribute name="图:后一链接"><xsl:variable name="next-link"><xsl:value-of select="./@draw:chain-next-name"/></xsl:variable><xsl:variable name="link-name"><xsl:value-of select="/office:document/office:body/office:text//draw:text-box[@draw:name=$next-link]/@draw:style-name"/></xsl:variable><xsl:value-of select="concat($link-name,'_',$picnumber)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$pic-name]) | (/office:document/office:automatic-styles/descendant::*[@style:name=$pic-name]) ">
+ <xsl:if test="style:text-properties/@fo:padding-left">
+ <xsl:attribute name="图:左边距"><xsl:value-of select="style:text-properties/@fo:padding-left"/></xsl:attribute>
+ <xsl:attribute name="图:右边距"><xsl:value-of select="style:text-properties/@fo:padding-right"/></xsl:attribute>
+ <xsl:attribute name="图:上边距"><xsl:value-of select="style:text-properties/@fo:padding-top"/></xsl:attribute>
+ <xsl:attribute name="图:下边距"><xsl:value-of select="style:text-properties/@fo:padding-bottom"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="图:文字排列方向"><xsl:choose><xsl:when test="style:paragraph-properties/@style:writing-mode"><xsl:choose><xsl:when test="style:paragraph-properties/@style:writing-mode='tb-lr'">vert-l2r</xsl:when><xsl:when test="style:paragraph-properties/@style:writing-mode='tb-rl'">vert-r2l</xsl:when></xsl:choose></xsl:when><xsl:when test="style:graphic-properties/@style:writing-mode='tb-lr'">vert-l2r</xsl:when><xsl:when test="style:graphic-properties/@style:writing-mode='tb-rl'">vert-r2l</xsl:when><xsl:when test="style:paragraph-properties/@draw:textarea-horizontal-align='right'">hori-r2l</xsl:when><xsl:otherwise>hori-l2r</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="style:text-properties/@fo:wrap-option">
+ <xsl:attribute name="图:自动换行">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:textarea-horizontal-align">
+ <xsl:attribute name="图:水平对齐"><xsl:value-of select="style:graphic-properties/@draw:textarea-horizontal-align"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:textarea-vertical-align">
+ <xsl:attribute name="图:垂直对齐"><xsl:value-of select="style:graphic-properties/@draw:textarea-vertical-align"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:graphic-properties/@draw:auto-grow-width='true' and style:graphic-properties/@draw:auto-grow-height='true'">
+ <xsl:attribute name="图:大小适应文字"><xsl:choose><xsl:when test="style:graphic-properties/@draw:auto-grow-width='true' and style:graphic-properties/@draw:auto-grow-height='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="text:p">
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <xsl:if test="style:paragraph-properties">
+ <字:段落属性 uof:locID="t0052" uof:attrList="式样引用">
+ <xsl:apply-templates select="style:paragraph-properties"/>
+ </字:段落属性>
+ </xsl:if>
+ <xsl:call-template name="textp"/>
+ </字:段落>
+ </xsl:for-each>
+ <xsl:for-each select="draw:text-box/text:p">
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <xsl:if test="style:paragraph-properties">
+ <字:段落属性 uof:locID="t0052" uof:attrList="式样引用">
+ <xsl:apply-templates select="style:paragraph-properties"/>
+ </字:段落属性>
+ </xsl:if>
+ <xsl:call-template name="textp"/>
+ </字:段落>
+ </xsl:for-each>
+ </图:文本内容>
+ <xsl:if test="@svg:x and @svg:y">
+ <图:控制点 uof:locID="g0003" uof:attrList="x坐标 y坐标">
+ <xsl:attribute name="图:x坐标"><xsl:value-of select="substring-before(@svg:x,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="图:y坐标"><xsl:value-of select="substring-before(@svg:y,$uofUnit)"/></xsl:attribute>
+ </图:控制点>
+ </xsl:if>
+ </图:图形>
+ <xsl:if test="name()='draw:frame' and ./draw:image">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat($pic-name,'_',$picnumber)"/></xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <xsl:variable name="pic">
+ <xsl:choose>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.png')">png</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.jpg')">jpg</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.gif')">gif</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.bmp')">bmp</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.pbm')">pbm</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.ras')">ras</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.txt')">text</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.xml')">xml</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.htm')">html</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.html')">html</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.wav')">wav</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.mid')">midi</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.ra')">ra</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.au')">au</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.mp3')">mp3</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.snd')">snd</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.svg')">svg</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.avi')">avi</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.mpeg')">mpeg4</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.qt')">qt</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.rm')">rm</xsl:when>
+ <xsl:when test="contains(./draw:image/@xlink:href,'.asf')">asf</xsl:when>
+ <xsl:otherwise>图片</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$pic!='图片'">
+ <xsl:attribute name="uof:公共类型"><xsl:value-of select="$pic"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="uof:私有类型">图片</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="./draw:image/office:binary-data">
+ <uof:数据 uof:locID="u0037">
+ <xsl:value-of select="./draw:image/office:binary-data"/>
+ </uof:数据>
+ </xsl:if>
+ <xsl:if test="./draw:image/@xlink:href">
+ <uof:路径 uof:locID="u0038">
+ <xsl:value-of select="./draw:image/@xlink:href"/>
+ </uof:路径>
+ </xsl:if>
+ </uof:其他对象>
+ </xsl:if>
+ <xsl:for-each select="(/office:document/office:styles/descendant::*[@style:name=$pic-name]) | (/office:document/office:automatic-styles/descendant::*[@style:name=$pic-name]) ">
+ <xsl:if test="style:text-properties/@draw:fill-image-name">
+ <uof:其他对象 uof:locID="u0036" uof:attrList="标识符 内嵌 公共类型 私有类型">
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="concat($pic-name,'-b1')"/></xsl:attribute>
+ <xsl:attribute name="uof:公共类型">png</xsl:attribute>
+ <xsl:attribute name="uof:内嵌">true</xsl:attribute>
+ <xsl:variable name="fill-name">
+ <xsl:value-of select="style:text-properties/@draw:fill-image-name"/>
+ </xsl:variable>
+ <uof:数据 uof:locID="u0037">
+ <xsl:for-each select="/office:document/office:styles/draw:fill-image[@draw:name=$fill-name]">
+ <xsl:value-of select="office:binary-data"/>
+ </xsl:for-each>
+ </uof:数据>
+ <uof:路径 uof:locID="u0038">
+ <xsl:value-of select="@xlink:href"/>
+ </uof:路径>
+ </uof:其他对象>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="draw:points">
+ <xsl:param name="point"/>
+ <xsl:param name="lujing"/>
+ <xsl:choose>
+ <xsl:when test="contains($point,' ' )">
+ <xsl:variable name="first-point" select="substring-before($point,' ')"/>
+ <xsl:variable name="other-point" select="substring-after($point,' ')"/>
+ <xsl:variable name="xzuobiao">
+ <xsl:value-of select="substring-before($first-point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:variable name="yzuobiao">
+ <xsl:value-of select="substring-after($first-point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:call-template name="draw:points">
+ <xsl:with-param name="point" select="$other-point"/>
+ <xsl:with-param name="lujing" select="concat($lujing,$xzuobiao,' ',$yzuobiao,'lineto')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="xzuobiao">
+ <xsl:value-of select="substring-before($point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:variable name="yzuobiao">
+ <xsl:value-of select="substring-after($point,',') div 1000"/>
+ </xsl:variable>
+ <xsl:value-of select="concat($lujing,$xzuobiao,' ',$yzuobiao)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="office:meta">
+ <uof:元数据 uof:locID="u0001">
+ <uof:标题 uof:locID="u0002">
+ <xsl:value-of select="dc:title"/>
+ </uof:标题>
+ <uof:创建应用程序 uof:locID="u0011">
+ <xsl:value-of select="meta:generator"/>
+ </uof:创建应用程序>
+ <uof:摘要 uof:locID="u0007">
+ <xsl:value-of select="dc:description"/>
+ </uof:摘要>
+ <uof:主题 uof:locID="u0003">
+ <xsl:value-of select="dc:subject"/>
+ </uof:主题>
+ <uof:创建者 uof:locID="u0004">
+ <xsl:value-of select="meta:initial-creator"/>
+ </uof:创建者>
+ <!--uof:作者 uof:locID="u0005">
+ <xsl:value-of select="meta:initial-creator"/>
+ </uof:作者-->
+ <uof:创建日期 uof:locID="u0008">
+ <xsl:value-of select="meta:creation-date"/>
+ </uof:创建日期>
+ <uof:最后作者 uof:locID="u0006">
+ <xsl:value-of select="dc:creator"/>
+ </uof:最后作者>
+ <uof:关键字集 uof:locID="u0014">
+ <xsl:for-each select=".">
+ <uof:关键字 uof:locID="u0015">
+ <xsl:value-of select="meta:keywords/@meta:keyword"/>
+ </uof:关键字>
+ </xsl:for-each>
+ </uof:关键字集>
+ <uof:编辑次数 uof:locID="u0009">
+ <xsl:value-of select="meta:editing-cycles"/>
+ </uof:编辑次数>
+ <xsl:if test="meta:editing-duration">
+ <uof:编辑时间 uof:locID="u0010">
+ <xsl:value-of select="meta:editing-duration"/>
+ </uof:编辑时间>
+ </xsl:if>
+ <xsl:if test="meta:template/@xlink:href">
+ <uof:文档模板 uof:locID="u0013">
+ <xsl:value-of select="meta:template/@xlink:href"/>
+ </uof:文档模板>
+ </xsl:if>
+ <xsl:if test="meta:user-defined/@meta:name">
+ <uof:用户自定义元数据集 uof:locID="u0016">
+ <xsl:for-each select="meta:user-defined">
+ <uof:用户自定义元数据 uof:locID="u0017" uof:attrList="名称 类型">
+ <xsl:attribute name="uof:名称"><xsl:value-of select="@meta:name"/></xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:value-of select="'string'"/></xsl:attribute>
+ </uof:用户自定义元数据>
+ </xsl:for-each>
+ </uof:用户自定义元数据集>
+ </xsl:if>
+ <!--xsl:if test="meta:document-statistic/@meta:page-count"-->
+ <uof:页数 uof:locID="u0020">
+ <xsl:value-of select="meta:document-statistic/@meta:page-count"/>
+ </uof:页数>
+ <!--/xsl:if-->
+ <!--xsl:if test="meta:document-statistic/@meta:paragraph-count"-->
+ <uof:段落数 uof:locID="u0025">
+ <xsl:value-of select="meta:document-statistic/@meta:paragraph-count"/>
+ </uof:段落数>
+ <!--/xsl:if-->
+ <!--xsl:if test="meta:document-statistic/@meta:object-count"-->
+ <uof:对象数 uof:locID="u0026">
+ <xsl:value-of select="meta:document-statistic/@meta:object-count"/>
+ </uof:对象数>
+ <!--/xsl:if-->
+ <!--xsl:if test="meta:document-statistic/@meta:character-count"-->
+ <uof:字数 uof:locID="u0021">
+ <xsl:value-of select="meta:document-statistic/@meta:character-count"/>
+ </uof:字数>
+ <!--/xsl:if-->
+ <!--xsl:if test="meta:document-statistic/@meta:word-count"-->
+ <uof:中文字符数 uof:locID="u0023">
+ <xsl:value-of select="meta:document-statistic/@meta:word-count"/>
+ </uof:中文字符数>
+ <!--/xsl:if-->
+ <uof:英文字符数 uof:locID="u0022">
+ <xsl:value-of select="meta:document-statistic/@meta:character-count - meta:document-statistic/@meta:word-count"/>
+ </uof:英文字符数>
+ <uof:行数 uof:locID="u0024">
+ <xsl:variable name="quzhi">
+ <xsl:value-of select="(meta:document-statistic/@meta:character-count div 39) + 0.9"/>
+ </xsl:variable>
+ <xsl:value-of select="substring-before($quzhi,'.')"/>
+ </uof:行数>
+ <uof:分类 uof:locID="u0012">
+ <xsl:value-of select="meta:user-defined[@meta:name='Category']"/>
+ </uof:分类>
+ <uof:经理名称 uof:locID="u0019">
+ <xsl:value-of select="meta:user-defined[meta:name='Manager']"/>
+ </uof:经理名称>
+ <uof:公司名称 uof:locID="u0018">
+ <xsl:value-of select="meta:user-defined[meta:name='Company']"/>
+ </uof:公司名称>
+ </uof:元数据>
+ </xsl:template>
+ <xsl:template match="office:font-face-decls">
+ <uof:字体集 uof:locID="u0040">
+ <xsl:for-each select="style:font-face">
+ <xsl:element name="uof:字体声明">
+ <xsl:attribute name="uof:attrList">标识符 名称 字体族</xsl:attribute>
+ <xsl:attribute name="uof:locID">u0041</xsl:attribute>
+ <xsl:attribute name="uof:名称"><xsl:value-of select="@svg:font-family"/></xsl:attribute>
+ <xsl:attribute name="uof:标识符"><xsl:value-of select="translate(@style:name,' ','_')"/></xsl:attribute>
+ <xsl:if test="@style:font-charset= '02'">
+ <xsl:attribute name="uof:字符集">x-symbol</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@style:font-family-generic">
+ <xsl:choose>
+ <xsl:when test="@style:font-family-generic = 'swiss'">
+ <xsl:attribute name="uof:字体族">Swiss</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='modern'">
+ <xsl:attribute name="uof:字体族">Modern</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic='roman'">
+ <xsl:attribute name="uof:字体族">Roman</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='script'">
+ <xsl:attribute name="uof:字体族">Script</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='decorative'">
+ <xsl:attribute name="uof:字体族">Decorative</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic ='system'">
+ <xsl:attribute name="uof:字体族">System</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="uof:字体族">System</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:apply-templates select="style:font-decl"/>
+ </uof:字体集>
+ </xsl:template>
+ <xsl:template name="自动编号集">
+ <xsl:element name="uof:自动编号集">
+ <xsl:attribute name="uof:locID">u0042</xsl:attribute>
+ <xsl:for-each select="/office:document//text:list-style">
+ <xsl:element name="字:自动编号">
+ <xsl:attribute name="uof:locID">t0169</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 父编号引用 多级编号</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:if test=".//@text:style-name">
+ <xsl:attribute name="字:名称"><xsl:value-of select=".//@text:style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="字:多级编号">true</xsl:attribute>
+ <xsl:for-each select="./* ">
+ <xsl:if test="not(number(@text:level)=10)">
+ <xsl:element name="字:级别">
+ <xsl:attribute name="uof:locID">t0159</xsl:attribute>
+ <xsl:attribute name="uof:attrList">级别值 编号对齐方式 尾随字符</xsl:attribute>
+ <xsl:attribute name="字:级别值"><xsl:value-of select="number(@text:level) - 1"/></xsl:attribute>
+ <xsl:if test="@style:num-suffix">
+ <xsl:attribute name="字:尾随字符"><xsl:choose><xsl:when test="@style:num-suffix=' '">space</xsl:when><xsl:when test="@style:num-suffix=' '">tab</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:list-level-properties/@fo:text-align">
+ <xsl:attribute name="字:编号对齐方式"><xsl:variable name="vv"><xsl:value-of select="style:list-level-properties/@fo:text-align"/></xsl:variable><xsl:choose><xsl:when test="$vv='center' ">center</xsl:when><xsl:when test="$vv='end' ">right</xsl:when><xsl:otherwise>left</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@text:bullet-char">
+ <xsl:element name="字:项目符号">
+ <xsl:attribute name="uof:locID">t0171</xsl:attribute>
+ <xsl:value-of select="@text:bullet-char"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@text:style-name">
+ <xsl:element name="字:符号字体">
+ <xsl:attribute name="uof:locID">t0160</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@style:num-format">
+ <xsl:choose>
+ <xsl:when test="string(@style:num-format)='a'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>lower-letter</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='A'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>upper-letter</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='i'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>lower-roman</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='I'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>upper-roman</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='①, ②, ③, ...'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>decimal-enclosed-circle</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='甲, 乙, 丙, ...'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>ideograph-traditional</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='子, 丑, 寅, ...'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>ideograph-zodiac</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='一, 二, 三, ...'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>chinese-counting</xsl:element>
+ </xsl:when>
+ <xsl:when test="string(@style:num-format)='壹, 贰, 叁, ...'">
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>chinese-legal-simplified</xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="字:编号格式">
+ <xsl:attribute name="uof:locID">t0162</xsl:attribute>decimal</xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:variable name="jibie">
+ <xsl:value-of select="position()"/>
+ </xsl:variable>
+ <xsl:variable name="xianshijibie">
+ <xsl:choose>
+ <xsl:when test="@text:display-levels">
+ <xsl:value-of select="@text:display-levels"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="字:编号格式表示">
+ <xsl:attribute name="uof:locID">t0163</xsl:attribute>
+ <xsl:call-template name="字:编号格式表示">
+ <xsl:with-param name="bubianjibie" select="$jibie"/>
+ <xsl:with-param name="jibie" select="$jibie"/>
+ <xsl:with-param name="xianshijibie" select="$xianshijibie"/>
+ <xsl:with-param name="biaoshi" select="concat(string(@style:num-prefix),'%',$jibie,string(@style:num-suffix))"/>
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:if test="office:binary-data">
+ <xsl:element name="字:图片符号引用">
+ <xsl:attribute name="uof:locID">t0164</xsl:attribute>
+ <xsl:attribute name="uof:attrList">宽度 高度</xsl:attribute>
+ <xsl:if test="style:list-level-properties/@fo:width">
+ <xsl:attribute name="字:宽度"><xsl:value-of select="substring-before(style:list-level-properties/@fo:width,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:list-level-properties/@fo:height">
+ <xsl:attribute name="字:高度"><xsl:value-of select="substring-before(style:list-level-properties/@fo:height,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:value-of select="concat('image_numbering_',count(preceding::text:list-level-style-image))"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:margin-left or style:paragraph-properties/@fo:margin-right or style:paragraph-properties/@fo:text-indent">
+ <xsl:element name="字:缩进">
+ <xsl:attribute name="uof:locID">t0165</xsl:attribute>
+ <xsl:for-each select="style:paragraph-properties">
+ <xsl:call-template name="字:缩进类型"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:list-level-properties/@text:min-label-width">
+ <xsl:element name="字:制表符位置">
+ <xsl:attribute name="uof:locID">t0166</xsl:attribute>
+ <xsl:value-of select="substring-before(style:list-level-properties/@text:min-label-width,$uofUnit)"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@text:start-value">
+ <xsl:element name="字:起始编号">
+ <xsl:attribute name="uof:locID">t0167</xsl:attribute>
+ <xsl:value-of select="@text:start-value"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@text:num-regular-exp">
+ <xsl:element name="字:正规格式">
+ <xsl:attribute name="uof:locID">t0168</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="@text:num-regular-exp"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="shiyang">
+ <xsl:for-each select="office:styles/style:style">
+ <xsl:choose>
+ <xsl:when test="@style:family='text'">
+ <xsl:element name="uof:句式样">
+ <xsl:attribute name="uof:locID">u0043</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用 后继式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">auto</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@style:parent-style-name">
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="@style:name"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:for-each select="office:automatic-styles/style:style">
+ <xsl:choose>
+ <xsl:when test="@style:family='text'">
+ <xsl:element name="uof:句式样">
+ <xsl:attribute name="uof:locID">u0043</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用 后继式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">custom</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@style:parent-style-name">
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@style:parent-style-name and not(@style:parent-style-name='Standard')">
+ <xsl:variable name="stylename" select="@style:parent-style-name"/>
+ <xsl:for-each select="/office:document/office:styles/style:style[@style:name=$stylename]">
+ <xsl:call-template name="字:句属性"/>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:for-each select="office:styles/style:style">
+ <xsl:choose>
+ <xsl:when test="@style:family='paragraph'">
+ <xsl:element name="uof:段落式样">
+ <xsl:attribute name="uof:locID">u0044</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用 后继式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">auto</xsl:attribute>
+ <xsl:if test="@style:parent-style-name">
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:if test="@style:display-name">
+ <xsl:attribute name="字:别名"><xsl:value-of select="@style:display-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ <xsl:call-template name="ParaAttribute"/>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:for-each select="office:automatic-styles/style:style">
+ <xsl:choose>
+ <xsl:when test="@style:family='paragraph'">
+ <xsl:element name="uof:段落式样">
+ <xsl:attribute name="uof:locID">u0044</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用 后继式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">custom</xsl:attribute>
+ <xsl:if test="@style:parent-style-name">
+ <xsl:attribute name="字:基式样引用"><xsl:value-of select="@style:parent-style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ <xsl:call-template name="ParaAttribute"/>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="字:编号格式表示">
+ <xsl:param name="bubianjibie"/>
+ <xsl:param name="jibie"/>
+ <xsl:param name="xianshijibie"/>
+ <xsl:param name="biaoshi"/>
+ <xsl:choose>
+ <xsl:when test="number($xianshijibie)= 1">
+ <xsl:value-of select="$biaoshi"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="num-prefix">
+ <xsl:value-of select="preceding-sibling::*[number($bubianjibie -$jibie +1)]/@style:num-prefix"/>
+ </xsl:variable>
+ <xsl:variable name="num-suffix">
+ <xsl:value-of select="preceding-sibling::*[number($bubianjibie -$jibie +1)]/@style:num-suffix"/>
+ </xsl:variable>
+ <xsl:call-template name="字:编号格式表示">
+ <xsl:with-param name="bubianjibie" select="$bubianjibie"/>
+ <xsl:with-param name="jibie" select="$jibie -1"/>
+ <xsl:with-param name="xianshijibie" select="$xianshijibie -1"/>
+ <xsl:with-param name="biaoshi" select="concat($num-prefix,'%',number($jibie -1),$num-suffix,'.',$biaoshi)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="style:style[ancestor::office:automatic-styles]" mode="style">
+ <xsl:for-each select=".">
+ <xsl:choose>
+ <xsl:when test="@style:family='table' ">
+ <xsl:element name="uof:文字表式样">
+ <xsl:attribute name="uof:locID">u0045</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型 别名 基式样引用 后继式样引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:别名"><xsl:value-of select="@style:name"/></xsl:attribute>
+ <xsl:attribute name="字:类型">auto</xsl:attribute>
+ <xsl:if test="style:table-properties">
+ <xsl:element name="字:宽度">
+ <xsl:attribute name="字:绝对宽度"><xsl:value-of select="substring-before(style:table-properties/@style:width,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0130</xsl:attribute>
+ <xsl:attribute name="uof:attrList">绝对宽度 相对宽度</xsl:attribute>
+ </xsl:element>
+ <字:对齐 uof:locID="t0133">
+ <xsl:choose>
+ <xsl:when test="style:table-properties/@table:align='right'">right</xsl:when>
+ <xsl:when test="style:table-properties/@table:align='center'">center</xsl:when>
+ <xsl:otherwise>left</xsl:otherwise>
+ </xsl:choose>
+ </字:对齐>
+ </xsl:if>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="office:settings">
+ <字:文档设置 uof:locID="t0001">
+ <字:度量单位 uof:locID="t0006">
+ <xsl:value-of select="$ooUnit"/>
+ </字:度量单位>
+ <字:默认制表位位置 uof:locID="t0004">
+ <xsl:variable name="aa" select="substring-before(/office:document/office:styles/style:default-style[@style:family='paragraph']/style:paragraph-properties/@style:tab-stop-distance,$ooUnit)"/>
+ <xsl:variable name="bb" select="$aa - 0.74"/>
+ <xsl:value-of select="substring($bb,1,4)"/>
+ </字:默认制表位位置>
+ <字:当前视图 uof:locID="t0002">
+ <xsl:choose>
+ <xsl:when test="config:config-item-set[@config:name='ooo:view-settings']/config:config-item[@config:name='InBrowseMode']='false'">page</xsl:when>
+ <xsl:when test="config:config-item-set[@config:name='ooo:view-settings']/config:config-item[@config:name='InBrowseMode']='true'">web</xsl:when>
+ <xsl:otherwise>page</xsl:otherwise>
+ </xsl:choose>
+ </字:当前视图>
+ <xsl:if test="config:config-item-set[@config:name='ooo:view-settings']/config:config-item-map-indexed[@config:name='Views']/config:config-item-map-entry/config:config-item[@config:name='ZoomFactor']">
+ <字:缩放 uof:locID="t0003">
+ <xsl:value-of select="config:config-item-set[@config:name='ooo:view-settings']/config:config-item-map-indexed[@config:name='Views']/config:config-item-map-entry/config:config-item[@config:name='ZoomFactor']"/>
+ </字:缩放>
+ </xsl:if>
+ <字:修订 uof:locID="t0005">
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="/office:document/office:body/office:text/text:tracked-changes">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </字:修订>
+ <xsl:if test="config:config-item-set[@config:name='configuration-settings']/config:config-item-map-indexed[@config:name='ForbiddenCharacters']/config:config-item-map-entry[config:config-item='CN']">
+ <字:标点禁则 uof:locID="t0007">
+ <字:行首字符 uof:locID="t0008">
+ <xsl:value-of select="config:config-item-set[@config:name='configuration-settings']/config:config-item-map-indexed[@config:name='ForbiddenCharacters']/config:config-item-map-entry[config:config-item='CN']/config:config-item[@config:name='BeginLine']"/>
+ </字:行首字符>
+ <字:行尾字符 uof:locID="t0009">
+ <xsl:value-of select="config:config-item-set[@config:name='configuration-settings']/config:config-item-map-indexed[@config:name='ForbiddenCharacters']/config:config-item-map-entry[config:config-item='CN']/config:config-item[@config:name='EndLine']"/>
+ </字:行尾字符>
+ </字:标点禁则>
+ <xsl:if test="/office:document/office:styles/text:notes-configuration[@text:note-class='endnote']">
+ <字:尾注位置 uof:locID="t0210" uof:attrList="位置">
+ <xsl:attribute name="字:位置">doc-end</xsl:attribute>
+ </字:尾注位置>
+ </xsl:if>
+ </xsl:if>
+ </字:文档设置>
+ </xsl:template>
+ <xsl:template name="style:page-layout">
+ <字:分节 uof:locID="t0017" uof:attrList="名称">
+ <xsl:attribute name="字:名称"><xsl:variable name="stylename"><xsl:value-of select="@style:name"/></xsl:variable><xsl:value-of select="/office:document/office:master-styles/style:master-page[@style:page-layout-name=$stylename]/@style:name"/></xsl:attribute>
+ <字:节属性 uof:locID="t0018">
+ <字:节类型 uof:locID="t0020">new-page</字:节类型>
+ <xsl:element name="字:页边距">
+ <xsl:attribute name="uof:locID">t0021</xsl:attribute>
+ <xsl:attribute name="uof:attrList">左 上 右 下</xsl:attribute>
+ <xsl:attribute name="uof:上"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:margin-top,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:左"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:margin-left,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:下"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:margin-bottom,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:右"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:margin-right,$ooUnit)"/></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:纸张">
+ <xsl:attribute name="uof:locID">t0022</xsl:attribute>
+ <xsl:attribute name="uof:attrList">纸型 宽度 高度</xsl:attribute>
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:page-width,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:高度"><xsl:value-of select="substring-before(style:page-layout-properties/@fo:page-height,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="uof:纸型"><xsl:variable name="height"><xsl:value-of select="style:page-layout-properties/@fo:page-height"/></xsl:variable><xsl:variable name="width"><xsl:value-of select="style:page-layout-properties/@fo:page-width"/></xsl:variable><xsl:choose><xsl:when test="$width='29.702cm' and $height='42cm'">A3</xsl:when><xsl:when test="$width='21.001cm' and $height='29.7cm'">A4</xsl:when><xsl:when test="$width='14.799cm' and $height='20.999cm'">A5</xsl:when><xsl:when test="$width='25cm' and $height='35.3cm'">B4</xsl:when><xsl:when test="$width='17.598cm' and $height='25cm'">B5</xsl:when><xsl:when test="$width='12.5cm' and $height='17.6cm'">B6</xsl:when><xsl:otherwise>使用者</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:if test="/office:document/office:master-styles/style:master-page/style:header-left">
+ <xsl:element name="字:奇偶页页眉页脚不同">
+ <xsl:attribute name="uof:locID">t0023</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:首页页眉页脚不同">
+ <xsl:attribute name="uof:locID">t0024</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">false</xsl:attribute>
+ </xsl:element>
+ <xsl:if test="style:header-style/style:header-footer-properties">
+ <xsl:element name="字:页眉位置">
+ <xsl:attribute name="uof:locID">t0025</xsl:attribute>
+ <xsl:attribute name="uof:attrList">距边界 距版芯</xsl:attribute>
+ <xsl:attribute name="字:距边界"><xsl:value-of select="substring-before(style:header-style/style:header-footer-properties/@fo:margin-bottom,$ooUnit)"/></xsl:attribute>
+ <xsl:variable name="long1" select="substring-before(style:header-style/style:header-footer-properties/@fo:margin-bottom,$ooUnit)"/>
+ <xsl:variable name="long2" select="substring-before(style:header-style/style:header-footer-properties/@svg:height,$ooUnit)"/>
+ <xsl:attribute name="字:距版芯"><xsl:value-of select="$long2 - $long1"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:footer-style/style:header-footer-properties">
+ <xsl:element name="字:页脚位置">
+ <xsl:attribute name="uof:locID">t0026</xsl:attribute>
+ <xsl:attribute name="uof:attrList">距边界 距版芯</xsl:attribute>
+ <xsl:attribute name="字:距边界"><xsl:value-of select="substring-before(style:footer-style/style:header-footer-properties/@fo:margin-top,$ooUnit)"/></xsl:attribute>
+ <xsl:variable name="long1" select="substring-before(style:footer-style/style:header-footer-properties/@fo:margin-top,$ooUnit)"/>
+ <xsl:variable name="long2" select="substring-before(style:footer-style/style:header-footer-properties/@svg:height,$ooUnit)"/>
+ <xsl:attribute name="字:距版芯"><xsl:value-of select="$long2 - $long1"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:variable name="masterPages" select="'Standard'"/>
+ <xsl:variable name="mp">
+ <xsl:value-of select="@style:name"/>
+ </xsl:variable>
+ <xsl:for-each select="/office:document/office:master-styles/style:master-page[@style:page-layout-name=$mp and @style:name=$masterPages]">
+ <xsl:if test="style:header-left or style:header">
+ <字:页眉 uof:locID="t0027">
+ <xsl:choose>
+ <xsl:when test="style:header-left">
+ <xsl:for-each select="style:header">
+ <字:首页页眉 uof:locID="t0030">
+ <xsl:if test="text:p">
+ <xsl:for-each select="text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="table:table">
+ <xsl:for-each select="table:table">
+ <xsl:call-template name="exec_table"/>
+ </xsl:for-each>
+ </xsl:if>
+ </字:首页页眉>
+ </xsl:for-each>
+ <xsl:for-each select="style:header-left">
+ <字:偶数页页眉 uof:locID="t0029">
+ <xsl:if test="text:p">
+ <xsl:for-each select="text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="table:table">
+ <xsl:for-each select="table:table">
+ <xsl:call-template name="exec_table"/>
+ </xsl:for-each>
+ </xsl:if>
+ </字:偶数页页眉>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="style:header">
+ <字:奇数页页眉 uof:locID="t0028">
+ <xsl:if test="text:p">
+ <xsl:for-each select="text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="table:table">
+ <xsl:for-each select="table:table">
+ <xsl:call-template name="exec_table"/>
+ </xsl:for-each>
+ </xsl:if>
+ </字:奇数页页眉>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:页眉>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="/office:document/office:master-styles/style:master-page[@style:page-layout-name=$mp and @style:name=$masterPages]">
+ <xsl:if test="style:footer-left or style:footer">
+ <字:页脚 uof:locID="t0031">
+ <xsl:choose>
+ <xsl:when test="style:footer-left">
+ <xsl:for-each select="style:footer">
+ <字:首页页脚 uof:locID="t0034">
+ <xsl:if test="text:p">
+ <xsl:for-each select="text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="table:table">
+ <xsl:for-each select="table:table">
+ <xsl:call-template name="exec_table"/>
+ </xsl:for-each>
+ </xsl:if>
+ </字:首页页脚>
+ </xsl:for-each>
+ <xsl:for-each select="style:footer-left">
+ <字:偶数页页脚 uof:locID="t0033">
+ <xsl:if test="text:p">
+ <xsl:for-each select="text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="table:table">
+ <xsl:for-each select="table:table">
+ <xsl:call-template name="exec_table"/>
+ </xsl:for-each>
+ </xsl:if>
+ </字:偶数页页脚>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="style:footer">
+ <字:奇数页页脚 uof:locID="t0032">
+ <xsl:if test="text:p">
+ <xsl:for-each select="text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="table:table">
+ <xsl:for-each select="table:table">
+ <xsl:call-template name="exec_table"/>
+ </xsl:for-each>
+ </xsl:if>
+ </字:奇数页页脚>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:页脚>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="@style:page-usage">
+ <字:对称页边距 uof:locID="t0036" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@style:page-usage='mirrored'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </字:对称页边距>
+ </xsl:if>
+ <xsl:if test="@style:page-usage='mirrored'">
+ <xsl:element name="字:拼页">
+ <xsl:attribute name="uof:locID">t0037</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">1</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:纸张方向">
+ <xsl:attribute name="uof:locID">t0038</xsl:attribute>
+ <xsl:value-of select="style:page-layout-properties/@style:print-orientation"/>
+ </xsl:element>
+ <xsl:if test="style:page-layout-properties/@style:paper-tray-name">
+ <字:纸张来源 uof:locID="t0039" uof:attrList="首页 其他页" 字:首页="false" 字:其他页="style:page-layout-properties/@style:paper-tray-name"/>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@style:num-format">
+ <xsl:element name="字:页码设置">
+ <xsl:attribute name="uof:locID">t0042</xsl:attribute>
+ <xsl:attribute name="uof:attrList">首页显示 格式 包含章节号 章节起始样式引用 分隔符 起始编号</xsl:attribute>
+ <xsl:attribute name="字:首页显示">1</xsl:attribute>
+ <xsl:attribute name="字:格式"><xsl:variable name="format"><xsl:value-of select="style:page-layout-properties/@style:num-format"/></xsl:variable><xsl:call-template name="oo数字格式"><xsl:with-param name="oo_format" select="$format"/></xsl:call-template></xsl:attribute>
+ <xsl:if test="style:text-properties/@style:first-page-number">
+ <xsl:attribute name="字:起始编号"><xsl:value-of select="style:text-properties/@style:first-page-number"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="字:包含章节号">false</xsl:attribute>
+ <!--xsl:attribute name="字:章节起始样式引用">false</xsl:attribute-->
+ <xsl:attribute name="字:分隔符">hyphen</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="/office:document/office:styles/text:notes-configuration[@text:note-class='footnote']">
+ <xsl:element name="字:脚注设置">
+ <xsl:attribute name="uof:locID">t0040</xsl:attribute>
+ <xsl:attribute name="uof:attrList">位置 格式 起始编号 编号方式</xsl:attribute>
+ <xsl:for-each select="/office:document/office:styles/text:notes-configuration[@text:note-class='footnote']">
+ <xsl:attribute name="字:位置"><xsl:choose><xsl:when test="@text:footnotes-position='page'">page-bottom</xsl:when><xsl:when test="@text:footnotes-position='document'">below-text</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="字:编号方式"><xsl:choose><xsl:when test="@text:start-numbering-at='document'">continuous</xsl:when><xsl:when test="@text:start-numbering-at='chapter'">section</xsl:when><xsl:when test="@text:start-numbering-at='page'">page</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="字:起始编号"><xsl:value-of select="@text:start-value + 1"/></xsl:attribute>
+ <xsl:attribute name="字:格式"><xsl:variable name="format"><xsl:value-of select="@style:num-format"/></xsl:variable><xsl:call-template name="oo数字格式"><xsl:with-param name="oo_format" select="$format"/></xsl:call-template></xsl:attribute>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="/office:document/office:styles/text:notes-configuration[@text:note-class='endnote']">
+ <字:尾注设置 uof:locID="t0041" uof:attrList="格式 起始编号 编号方式">
+ <xsl:for-each select="/office:document/office:styles/text:notes-configuration[@text:note-class='endnote']">
+ <xsl:attribute name="字:格式"><xsl:variable name="format"><xsl:value-of select="@style:num-format"/></xsl:variable><xsl:call-template name="oo数字格式"><xsl:with-param name="oo_format" select="$format"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="字:起始编号"><xsl:value-of select="@text:start-value + 1"/></xsl:attribute>
+ </xsl:for-each>
+ </字:尾注设置>
+ </xsl:if>
+ <xsl:if test="/office:document/office:styles/text:linenumbering-configuration">
+ <字:行号设置 uof:locID="t0043" uof:attrList="使用行号 编号方式 起始编号 距边界 行号间隔">
+ <xsl:for-each select="/office:document/office:styles/text:linenumbering-configuration">
+ <xsl:choose>
+ <xsl:when test="@text:number-lines='false'">
+ <xsl:attribute name="字:使用行号">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:使用行号">true</xsl:attribute>
+ <xsl:attribute name="字:编号方式"><xsl:choose><xsl:when test="@text:count-in-floating-frames='true'">section</xsl:when><xsl:when test="@text:restart-on-page='true'">page</xsl:when><xsl:when test="@text:count-empty-lines='false'"/><xsl:otherwise>continuous</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@style:num-format">
+ <xsl:attribute name="字:起始编号"><xsl:value-of select="@style:num-format"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@text:offset">
+ <xsl:attribute name="字:距边界"><xsl:value-of select="substring-before(@text:offset,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@text:increment">
+ <xsl:attribute name="字:行号间隔"><xsl:value-of select="@text:increment"/></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ </字:行号设置>
+ </xsl:if>
+ <xsl:variable name="aa">
+ <xsl:value-of select="substring-before(style:page-layout-properties/@style:layout-grid-ruby-height,$ooUnit)"/>
+ </xsl:variable>
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-display and $aa='0' ">
+ <字:网格设置 uof:locID="t0044" uof:attrList="网格类型 宽度 高度 显示网格 打印网格">
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-mode">
+ <xsl:attribute name="字:网格类型"><xsl:choose><xsl:when test="style:page-layout-properties/@style:layout-grid-mode='both-nosnap'">line-char</xsl:when><xsl:when test="style:page-layout-properties/@style:layout-grid-mode='both'">char</xsl:when><xsl:when test="style:page-layout-properties/@style:layout-grid-mode='line'">line</xsl:when><xsl:when test="style:page-layout-properties/@style:layout-grid-mode='none'">none</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-base-width">
+ <xsl:attribute name="字:宽度"><xsl:value-of select="substring-before(style:page-layout-properties/@style:layout-grid-base-width,$ooUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-base-height">
+ <xsl:attribute name="字:高度"><xsl:value-of select="substring-before(style:page-layout-properties/@style:layout-grid-base-height,$ooUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-display">
+ <xsl:attribute name="字:显示网格"><xsl:choose><xsl:when test="style:page-layout-properties/@style:layout-grid-display='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-print">
+ <xsl:attribute name="字:打印网格"><xsl:choose><xsl:when test="style:page-layout-properties/@style:layout-grid-print='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </字:网格设置>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-display and not($aa = '0')">
+ <字:稿纸设置 uof:locID="t0211" uof:attrList="类型 格式 线型 颜色 方向">
+ <xsl:variable name="mode">
+ <xsl:value-of select="style:page-layout-properties/@style:layout-grid-mode"/>
+ </xsl:variable>
+ <xsl:variable name="ruby">
+ <xsl:value-of select="substring-before(style:page-layout-properties/@style:layout-grid-ruby-height,$ooUnit)"/>
+ </xsl:variable>
+ <xsl:variable name="width">
+ <xsl:value-of select="substring-before(style:page-layout-properties/@style:layout-grid-base-width,$ooUnit)"/>
+ </xsl:variable>
+ <xsl:variable name="height">
+ <xsl:value-of select="substring-before(style:page-layout-properties/@style:layout-grid-base-height,$ooUnit)"/>
+ </xsl:variable>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test="style:page-layout-properties/@style:layout-grid-mode='line'">letter-paper</xsl:when><xsl:when test="style:page-layout-properties/@style:layout-grid-mode='both'">draft-paper</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-mode">
+ <xsl:attribute name="字:格式"><xsl:choose><xsl:when test="$mode='both' and $width='0.728' and $height='0.728' and $ruby='0.496' ">fourth-gear</xsl:when><xsl:when test="$mode='both' and $width='0.584' and $height='0.584' and $ruby='0.64' ">third-gear</xsl:when><xsl:when test="$mode='both' and $width='0.728' and $height='0.728' and $ruby='0.905' ">second-gear</xsl:when><xsl:when test="$mode='both' and $width='0.728' and $height='0.728' and $ruby='1.633' ">first-gear</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@style:layout-grid-color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select="style:page-layout-properties/@style:layout-grid-color"/></xsl:attribute>
+ </xsl:if>
+ </字:稿纸设置>
+ </xsl:if>
+ <xsl:if test="/office:document/office:automatic-styles/style:page-layout/style:page-layout-properties/@style:writing-mode='lr-tb' or style:text-properties/@style:writing-mode='rl-tb'">
+ <字:垂直对齐方式 uof:locID="t0045">
+ <xsl:variable name="path" select="/office:document/office:automatic-styles/style:style/style:paragraph-properties"/>
+ <xsl:choose>
+ <xsl:when test="$path/@fo:text-align='start'">top</xsl:when>
+ <xsl:when test="$path/@fo:text-align='end'">bottom</xsl:when>
+ <xsl:when test="$path/@fo:text-align='center'">center</xsl:when>
+ <xsl:otherwise>justified</xsl:otherwise>
+ </xsl:choose>
+ </字:垂直对齐方式>
+ </xsl:if>
+ <字:文字排列方向 uof:locID="t0046">
+ <xsl:variable name="writing_mode">
+ <xsl:value-of select="style:page-layout-properties/@style:writing-mode"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$writing_mode='lr-tb' or $writing_mode='lr'">hori-l2r</xsl:when>
+ <xsl:when test="$writing_mode='rl-tb' or $writing_mode='rl'">hori-r2l</xsl:when>
+ <xsl:when test="$writing_mode='tb-rl'">vert-r2l</xsl:when>
+ <xsl:when test="$writing_mode='tb-lr'">vert-l2r</xsl:when>
+ <xsl:otherwise>hori-l2r</xsl:otherwise>
+ </xsl:choose>
+ </字:文字排列方向>
+ <xsl:if test="style:page-layout-properties/@fo:border or style:page-layout-properties/@fo:border-top or style:page-layout-properties/@fo:border-bottom or style:page-layout-properties/@fo:border-left or style:page-layout-properties/@fo:border-right or style:page-layout-properties/@style:shadow[.!='none']">
+ <xsl:element name="字:边框">
+ <xsl:attribute name="uof:locID">t0047</xsl:attribute>
+ <xsl:for-each select="style:page-layout-properties">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@fo:background-color">
+ <xsl:element name="字:填充">
+ <xsl:attribute name="uof:locID">t0048</xsl:attribute>
+ <xsl:for-each select="style:page-layout-properties">
+ <xsl:call-template name="图:填充"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/style:columns">
+ <xsl:element name="字:分栏">
+ <xsl:attribute name="uof:locID">t0049</xsl:attribute>
+ <xsl:attribute name="uof:attrList">栏数 等宽 分隔线 分隔线宽度 分隔线颜色</xsl:attribute>
+ <xsl:if test="//@fo:column-count">
+ <xsl:attribute name="字:栏数"><xsl:choose><xsl:when test="//@fo:column-count='0'">1</xsl:when><xsl:otherwise><xsl:value-of select="//@fo:column-count"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="第一宽度">
+ <xsl:value-of select="style:page-layout-properties/style:columns/style:column/@style:rel-width"/>
+ </xsl:variable>
+ <xsl:variable name="dkm">
+ <xsl:for-each select="style:page-layout-properties/style:columns/style:column">
+ <xsl:if test="$第一宽度 != @style:rel-width">
+ <xsl:value-of select="boolean($第一宽度 = @style:rel-width)"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="style:page-layout-properties/style:columns/@fo:column-gap">
+ <xsl:attribute name="字:等宽">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:等宽">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="style:page-layout-properties/style:columns/style:column-sep">
+ <xsl:attribute name="字:分隔线宽度"><xsl:value-of select="substring-before(style:page-layout-properties/style:columns/style:column-sep/@style:width,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:分隔线颜色"><xsl:value-of select="style:page-layout-properties/style:columns/style:column-sep/@style:color"/></xsl:attribute>
+ <xsl:attribute name="字:分隔线">single</xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="style:page-layout-properties/style:columns/style:column">
+ <xsl:element name="字:栏">
+ <xsl:variable name="left">
+ <xsl:value-of select="substring-before(@fo:start-indent,$uofUnit)"/>
+ </xsl:variable>
+ <xsl:variable name="right">
+ <xsl:value-of select="substring-before(@fo:end-indent,$uofUnit)"/>
+ </xsl:variable>
+ <xsl:if test="@style:rel-width">
+ <xsl:attribute name="字:宽度"><xsl:value-of select="substring-before(@style:rel-width,'*')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@fo:start-indent or @fo:end-indent">
+ <xsl:choose>
+ <xsl:when test="parent::style:columns/@fo:column-gap">
+ <xsl:attribute name="字:间距"><xsl:choose><xsl:when test="$left - $right &gt;0 "><xsl:value-of select="$left - $right"/></xsl:when><xsl:when test="$right - $left &gt; 0 "><xsl:value-of select="$right - $left"/></xsl:when><xsl:otherwise><xsl:value-of select="$right"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:间距"><xsl:value-of select="$right"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:attribute name="uof:locID">t0050</xsl:attribute>
+ <xsl:attribute name="uof:attrList">宽度 间距</xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ </字:节属性>
+ </字:分节>
+ </xsl:template>
+ <xsl:template match="office:text">
+ <xsl:for-each select="node( )">
+ <xsl:choose>
+ <xsl:when test="name()='text:list'or name()='text:ordered-list'">
+ <xsl:call-template name="unordered-ordered-list">
+ <xsl:with-param name="currlistlvl" select="number('1')"/>
+ <xsl:with-param name="liststylename" select="@text:style-name"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name()='text:p'or name()='text:h'">
+ <xsl:variable name="bs" select="./@text:style-name"/>
+ <xsl:if test="/office:document/office:automatic-styles/style:style[@style:name=$bs]/@style:master-page-name">
+ <xsl:variable name="bs1" select="/office:document/office:automatic-styles/style:style[@style:name=$bs]/@style:master-page-name"/>
+ <xsl:if test="/office:document/office:master-styles/style:master-page[@style:name=$bs1]/@style:page-layout-name">
+ <xsl:variable name="bs2" select="/office:document/office:master-styles/style:master-page[@style:name=$bs1]/@style:page-layout-name"/>
+ <xsl:for-each select="/office:document/office:automatic-styles/style:page-layout[@style:name=$bs2]">
+ <xsl:call-template name="style:page-layout"/>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:if>
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name()='table:table'">
+ <xsl:variable name="tbs" select="./@table:style-name"/>
+ <xsl:if test="/office:document/office:automatic-styles/style:style[@style:name=$tbs]/@style:master-page-name">
+ <xsl:variable name="tbs1" select="/office:document/office:automatic-styles/style:style[@style:name=$tbs]/@style:master-page-name"/>
+ <xsl:if test="/office:document/office:master-styles/style:master-page[@style:name=$tbs1]/@style:page-layout-name">
+ <xsl:variable name="tbs2" select="/office:document/office:master-styles/style:master-page[@style:name=$tbs1]/@style:page-layout-name"/>
+ <xsl:for-each select="/office:document/office:automatic-styles/style:page-layout[@style:name=$tbs2]">
+ <xsl:call-template name="style:page-layout"/>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:if>
+ <xsl:call-template name="exec_table"/>
+ </xsl:when>
+ <xsl:when test="name()='text:table-of-content'">
+ <xsl:call-template name="text:table-of-content"/>
+ </xsl:when>
+ <xsl:when test="name()='text:alphabetical-index'">
+ <xsl:call-template name="text:alphabetical-index"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="jiaozhu">
+ <字:脚注 uof:locID="t0107" uof:attrList="引文体">
+ <xsl:for-each select="text:note-citation">
+ <xsl:attribute name="字:引文体"><xsl:value-of select="."/></xsl:attribute>
+ </xsl:for-each>
+ <xsl:for-each select="text:note-body/text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </字:脚注>
+ </xsl:template>
+ <xsl:template name="weizhu">
+ <字:尾注 uof:locID="t0108" uof:attrList="引文体">
+ <xsl:for-each select="text:note-citation">
+ <xsl:attribute name="字:引文体"><xsl:value-of select="."/></xsl:attribute>
+ </xsl:for-each>
+ <xsl:for-each select="text:note-body/text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </字:尾注>
+ </xsl:template>
+ <xsl:template name="unordered-ordered-list">
+ <xsl:param name="currlistlvl"/>
+ <xsl:param name="liststylename"/>
+ <xsl:for-each select="text:list-item">
+ <xsl:if test="text:p">
+ <xsl:for-each select="text:p">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="$currlistlvl"/>
+ <xsl:with-param name="liststylename" select="$liststylename"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:for-each select="node( )">
+ <xsl:if test="name()='text:list'">
+ <xsl:call-template name="unordered-ordered-list">
+ <xsl:with-param name="currlistlvl" select="$currlistlvl +1"/>
+ <xsl:with-param name="liststylename" select="$liststylename"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="execParagraph">
+ <xsl:param name="currlistlvl"/>
+ <xsl:param name="liststylename"/>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:if test="@text:style-name">
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(number($currlistlvl) =number('0'))">
+ <xsl:variable name="parent-position">
+ <xsl:number from="/office:document/office:body/office:text/text:list" level="any" count="text:list-item/text:p" format="1"/>
+ </xsl:variable>
+ <xsl:element name="字:自动编号信息">
+ <xsl:attribute name="uof:locID">t0059</xsl:attribute>
+ <xsl:attribute name="uof:attrList">编号引用 编号级别 重新编号 起始编号</xsl:attribute>
+ <xsl:attribute name="字:编号引用"><xsl:value-of select="$liststylename"/></xsl:attribute>
+ <xsl:attribute name="字:编号级别"><xsl:value-of select="$currlistlvl - 1"/></xsl:attribute>
+ <xsl:attribute name="字:重新编号"><xsl:choose><xsl:when test="number($parent-position)=number('1')">1</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="字:起始编号"><xsl:for-each select="/office:document//text:list-style[$liststylename=@style:name]/*[number($currlistlvl)=number(@text:level)]"><xsl:choose><xsl:when test="@text:start-value"><xsl:value-of select="@text:start-value"/></xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:for-each></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:variable name="stylename">
+ <xsl:value-of select="@text:style-name"/>
+ </xsl:variable>
+ <xsl:for-each select="/office:document//style:style">
+ <xsl:if test="@style:name=$stylename">
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="$stylename"/></xsl:attribute>
+ <xsl:call-template name="字:句属性"/>
+ </xsl:element>
+ <xsl:call-template name="ParaAttribute">
+ <xsl:with-param name="text-style-name" select="@style:name"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:call-template name="textp"/>
+ <xsl:if test="parent::office:text and not(preceding-sibling::text:p) and preceding-sibling::*[substring-before(name(),':')='draw']">
+ <xsl:for-each select="preceding-sibling::*[substring-before(name(),':')='draw']">
+ <字:句 uof:locID="t0085">
+ <xsl:call-template name="字:锚点"/>
+ </字:句>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="draw:frame/draw:text-box/text:p">
+ <xsl:for-each select="draw:frame/draw:text-box/text:p">
+ <xsl:for-each select="child::*[substring-before(name(),':')='draw']">
+ <字:句 uof:locID="t0085">
+ <xsl:call-template name="字:锚点"/>
+ </字:句>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:variable name="aa">
+ <xsl:value-of select="@text:style-name"/>
+ </xsl:variable>
+ <xsl:if test="//office:document/office:automatic-styles/style:style[@style:name=$aa]/style:paragraph-properties/@fo:break-before='column'">
+ <字:句 uof:locID="t0085">
+ <xsl:element name="字:分栏符">
+ <xsl:attribute name="uof:locID">t0125</xsl:attribute>
+ </xsl:element>
+ </字:句>
+ </xsl:if>
+ <xsl:if test="//office:document/office:automatic-styles/style:style[@style:name=$aa]/style:paragraph-properties/@fo:break-before='page'">
+ <字:句 uof:locID="t0085">
+ <xsl:element name="字:分页符">
+ <xsl:attribute name="uof:locID">t0127</xsl:attribute>
+ </xsl:element>
+ </字:句>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:initial-creator">
+ <xsl:apply-templates select="text:initial-creator"/>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:title">
+ <xsl:apply-templates select="text:title"/>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:subject">
+ <xsl:apply-templates select="text:subject"/>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:file-name">
+ <xsl:apply-templates select="text:file-name"/>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:author-name">
+ <xsl:apply-templates select="text:author-name"/>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:author-initials">
+ <xsl:apply-templates select="text:author-initials"/>
+ </xsl:if>
+ <xsl:if test="/office:document/office:body/office:text/text:p/text:span/text:date">
+ <xsl:apply-templates select="text:date"/>
+ </xsl:if>
+ </字:段落>
+ </xsl:template>
+ <xsl:template name="ParaAttribute">
+ <xsl:param name="text-style-name"/>
+ <xsl:if test="substring-after(@style:display-name,'Heading')">
+ <xsl:element name="字:大纲级别">
+ <xsl:attribute name="uof:locID">t0054</xsl:attribute>
+ <xsl:value-of select="substring-after(@style:display-name,'Heading ')"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:text-align or style:paragraph-properties/@style:vertical-align">
+ <xsl:element name="字:对齐">
+ <xsl:attribute name="uof:locID">t0055</xsl:attribute>
+ <xsl:attribute name="uof:attrList">水平对齐 文字对齐</xsl:attribute>
+ <xsl:attribute name="字:水平对齐"><xsl:choose><xsl:when test="style:paragraph-properties/@fo:text-align='end'">right</xsl:when><xsl:when test="style:paragraph-properties/@fo:text-align='center'">center</xsl:when><xsl:when test="style:paragraph-properties/@fo:text-align='justify' and not(style:paragraph-properties/@fo:text-align-last='justify')">justified</xsl:when><xsl:when test="style:paragraph-properties/@fo:text-align='justify' and style:paragraph-properties/@fo:text-align-last='justify'">distributed</xsl:when><xsl:otherwise>left</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="字:文字对齐"><xsl:choose><xsl:when test="style:paragraph-properties/@style:vertical-align='baseline'">base</xsl:when><xsl:when test="style:paragraph-properties/@style:vertical-align='top'">top</xsl:when><xsl:when test="style:paragraph-properties/@style:vertical-align='middle'">center</xsl:when><xsl:when test="style:paragraph-properties/@style:vertical-align='bottom'">bottom</xsl:when><xsl:otherwise>auto</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:margin-left or style:paragraph-properties/@fo:margin-right or style:paragraph-properties/@fo:text-indent">
+ <xsl:element name="字:缩进">
+ <xsl:attribute name="uof:locID">t0056</xsl:attribute>
+ <xsl:for-each select="style:paragraph-properties">
+ <xsl:call-template name="字:缩进类型"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:行距">
+ <xsl:attribute name="uof:locID">t0057</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 值</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="contains(style:paragraph-properties/@fo:line-height,$ooUnit)">
+ <xsl:attribute name="字:类型">fixed</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:paragraph-properties/@fo:line-height,$ooUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(style:paragraph-properties/@fo:line-height,'%')">
+ <xsl:attribute name="字:类型">multi-lines</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:paragraph-properties/@fo:line-height,'%') div 100"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="style:paragraph-properties/@style:line-height-at-least">
+ <xsl:attribute name="字:类型">at-least</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:paragraph-properties/@style:line-height-at-least,$ooUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="style:paragraph-properties/@style:line-spacing">
+ <xsl:attribute name="字:类型">line-space</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:paragraph-properties/@style:line-spacing,$ooUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:类型">multi-lines</xsl:attribute>
+ <xsl:attribute name="字:值">1.0</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="style:paragraph-properties/@fo:widows">
+ <xsl:element name="字:孤行控制">
+ <xsl:attribute name="uof:locID">t0060</xsl:attribute>
+ <xsl:value-of select="style:paragraph-properties/@fo:widows"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:orphans">
+ <xsl:element name="字:寡行控制">
+ <xsl:attribute name="uof:locID">t0061</xsl:attribute>
+ <xsl:value-of select="style:paragraph-properties/@fo:orphans"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:段中不分页">
+ <xsl:attribute name="uof:locID">t0062</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:paragraph-properties/@fo:keep-together='always'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:if test="style:paragraph-properties/@fo:keep-with-next">
+ <xsl:element name="字:与下段同页">
+ <xsl:attribute name="uof:locID">t0063</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:break-before">
+ <xsl:element name="字:段前分页">
+ <xsl:attribute name="uof:locID">t0064</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@style:snap-to-layout-grid">
+ <xsl:element name="字:对齐网格">
+ <xsl:attribute name="uof:locID">t0069</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:paragraph-properties/@style:snap-to-layout-grid='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/style:drop-cap/@style:lines">
+ <xsl:element name="字:首字下沉">
+ <xsl:attribute name="uof:locID">t0070</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 字体引用 字符数 行数 间距</xsl:attribute>
+ <xsl:attribute name="字:类型">dropped</xsl:attribute>
+ <xsl:if test="style:paragraph-properties/style:drop-cap/@style:style-name">
+ <xsl:attribute name="字:字体引用"><xsl:value-of select="translate(style:paragraph-properties/style:drop-cap/@style:style-name,' ','_')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="字:间距"><xsl:choose><xsl:when test="style:paragraph-properties/style:drop-cap/@style:distance"><xsl:value-of select="substring-before(style:paragraph-properties/style:drop-cap/@style:distance,$ooUnit)"/></xsl:when><xsl:otherwise>0.00</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="style:paragraph-properties/style:drop-cap/@style:length">
+ <xsl:attribute name="字:字符数"><xsl:value-of select="style:paragraph-properties/style:drop-cap/@style:length"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/style:drop-cap/@style:lines">
+ <xsl:attribute name="字:行数"><xsl:value-of select="style:paragraph-properties/style:drop-cap/@style:lines"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:取消断字">
+ <xsl:attribute name="uof:locID">t0071</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:paragraph-properties/@fo:hyphenate"><xsl:value-of select="style:paragraph-properties/@fo:hyphenate"/></xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:取消行号">
+ <xsl:attribute name="uof:locID">t0072</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:variable name="aa">
+ <xsl:value-of select="style:paragraph-properties/@text:number-lines"/>
+ </xsl:variable>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="$aa='false'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:允许单词断字">
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0073</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ <xsl:if test="style:paragraph-properties/@style:punctuation-wrap">
+ <xsl:element name="字:行首尾标点控制">
+ <xsl:attribute name="uof:locID">t0074</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:paragraph-properties/@style:punctuation-wrap='hanging'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:是否行首标点压缩">
+ <xsl:attribute name="uof:locID">t0075</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">false</xsl:attribute>
+ </xsl:element>
+ <xsl:if test="style:paragraph-properties/@style:line-break ">
+ <xsl:element name="字:中文习惯首尾字符">
+ <xsl:attribute name="uof:locID">t0076</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:paragraph-properties/@style:line-break='strict'">true</xsl:when><xsl:when test="style:paragraph-properties/@style:line-break='normal'">false</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@style:text-autospace">
+ <xsl:element name="字:自动调整中英文字符间距">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:paragraph-properties/@style:text-autospace='ideograph-alpha'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0077</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@style:text-autospace">
+ <xsl:element name="字:自动调整中文与数字间距">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:paragraph-properties/@style:text-autospace='ideograph-alpha'">true </xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0078</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:有网格自动调整右缩进">
+ <xsl:attribute name="字:值">false</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0195</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ <xsl:if test="style:paragraph-properties/@fo:border or style:paragraph-properties/@fo:border-top or style:paragraph-properties/@fo:border-bottom or style:paragraph-properties/@fo:border-left or style:paragraph-properties/@fo:border-right or style:paragraph-properties/@style:shadow[.!='none']">
+ <xsl:element name="字:边框">
+ <xsl:attribute name="uof:locID">t0065</xsl:attribute>
+ <xsl:for-each select="style:paragraph-properties">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:background-color">
+ <xsl:element name="字:填充">
+ <xsl:attribute name="uof:locID">t0066</xsl:attribute>
+ <xsl:for-each select="style:paragraph-properties">
+ <xsl:call-template name="图:填充"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:margin-top or style:paragraph-properties/@fo:margin-bottom">
+ <字:段间距 uof:locID="t0058">
+ <xsl:if test="style:paragraph-properties/@fo:margin-top">
+ <字:段前距 uof:locID="t0196">
+ <字:绝对值 uof:locID="t0199" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:paragraph-properties/@fo:margin-top,$ooUnit)"/></xsl:attribute>
+ </字:绝对值>
+ </字:段前距>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/@fo:margin-bottom">
+ <字:段后距 uof:locID="t0197">
+ <字:绝对值 uof:locID="t0202" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(style:paragraph-properties/@fo:margin-bottom,$ooUnit)"/></xsl:attribute>
+ </字:绝对值>
+ </字:段后距>
+ </xsl:if>
+ </字:段间距>
+ </xsl:if>
+ <xsl:if test="style:paragraph-properties/style:tab-stops">
+ <xsl:element name="字:制表位设置">
+ <xsl:attribute name="uof:locID">t0067</xsl:attribute>
+ <xsl:for-each select="style:paragraph-properties/style:tab-stops/style:tab-stop">
+ <xsl:element name="字:制表位">
+ <xsl:attribute name="uof:locID">t0068</xsl:attribute>
+ <xsl:attribute name="uof:attrList">位置 类型 前导符 制表位字符</xsl:attribute>
+ <xsl:attribute name="字:位置"><xsl:value-of select="substring-before(@style:position,$ooUnit)"/></xsl:attribute>
+ <xsl:variable name="aa">
+ <xsl:value-of select="@style:type"/>
+ </xsl:variable>
+ <xsl:variable name="zbflx">
+ <xsl:choose>
+ <xsl:when test="$aa='right'">right</xsl:when>
+ <xsl:when test="$aa='center'">center</xsl:when>
+ <xsl:when test="$aa='char'and @style:char!=''">decimal</xsl:when>
+ <xsl:otherwise>left</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="字:类型"><xsl:value-of select="$zbflx"/></xsl:attribute>
+ <xsl:attribute name="字:制表位字符"><xsl:value-of select="@style:leader-text"/></xsl:attribute>
+ <xsl:if test="@style:leader-style">
+ <xsl:attribute name="字:前导符"><xsl:value-of select="@style:leader-style"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="text:s">
+ <xsl:param name="bText"/>
+ <xsl:choose>
+ <xsl:when test="$bText='0'">
+ <xsl:variable name="count">
+ <xsl:choose>
+ <xsl:when test="not(@text:c)">1</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@text:c"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <字:句 uof:locID="t0085">
+ <字:空格符 uof:locID="t0126" uof:attrList="个数" 字:个数="{$count}"/>
+ </字:句>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:空格符 uof:locID="t0126" uof:attrList="个数" 字:个数="{@text:c}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="textp" match="text:p">
+ <xsl:variable name="parentstyle">
+ <xsl:value-of select="@text:style-name"/>
+ </xsl:variable>
+ <xsl:for-each select="node( )">
+ <xsl:choose>
+ <xsl:when test="self::node()[name(.)='text:span']">
+ <xsl:call-template name="textspan"/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:sequence']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()/draw:text-box/text:p/text:sequence">
+ <xsl:for-each select="draw:text-box/text:p/node()">
+ <xsl:choose>
+ <xsl:when test="self::node()[name(.)='text:sequence']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="not(self::node()[substring-before(name(.),':')='draw'])">
+ <xsl:call-template name="字:句">
+ <xsl:with-param name="parentstyle" select="$parentstyle"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:date']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:time']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:s']">
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="bText" select="0"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:file-name']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:chapter']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:editing-duration']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:creation-time']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:creation-date']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:character-count']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:page-count']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:page-number']">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="substring-before(name(.),':')='draw' and not(name(.)='draw:a')">
+ <字:句 uof:locID="t0085">
+ <xsl:call-template name="字:锚点"/>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:note']/@text:note-class='footnote'">
+ <字:句 uof:locID="t0085">
+ <xsl:call-template name="jiaozhu"/>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:note']/@text:note-class='endnote'">
+ <字:句 uof:locID="t0085">
+ <xsl:call-template name="weizhu"/>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="name(.)='text:alphabetical-index-mark-start'">
+ <xsl:element name="字:句">
+ <xsl:element name="字:区域开始">
+ <xsl:attribute name="uof:locId">t0121</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型</xsl:attribute>
+ <xsl:attribute name="字:类型">user-data</xsl:attribute>
+ <xsl:attribute name="字:名称"><xsl:value-of select="@text:string-value-phonetic"/></xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="name(.)='text:alphabetical-index-mark-end'">
+ <xsl:element name="字:句">
+ <xsl:element name="字:区域结束" uof:locID="t0122" uof:attrList="标识符引用">
+ <xsl:attribute name="字:标识符引用"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="name(.)='text:bookmark' ">
+ <字:句 uof:locID="t0085">
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ </xsl:element>
+ <字:区域开始 uof:locID="t0121" uof:attrList="标识符 名称 类型" 字:名称="{@text:name}" 字:类型="bookmark" 字:标识符="{generate-id()}"/>
+ <字:区域结束 uof:locID="t0122" uof:attrList="标识符引用" 字:标识符引用="{generate-id()}"/>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="name(.)='text:a'">
+ <字:句 uof:locID="t0085">
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:区域开始">
+ <xsl:attribute name="字:标识符">hlnk<xsl:number from="/office:document/office:body/office:text" level="any" count="text:a"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Hyperlink</xsl:attribute>
+ <xsl:attribute name="字:类型">hyperlink</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0121</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="."/>
+ </xsl:element>
+ <xsl:element name="字:区域结束">
+ <xsl:attribute name="字:标识符引用">hlnk<xsl:number from="/office:document/office:body/office:text" level="any" count="text:a"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0122</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符引用</xsl:attribute>
+ </xsl:element>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="name(.)='office:annotation'">
+ <字:句 uof:locID="t0085">
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:区域开始">
+ <xsl:attribute name="字:标识符">cmt<xsl:number from="/office:document/office:body/office:text" level="any" count="office:annotation"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Comment</xsl:attribute>
+ <xsl:attribute name="字:类型">annotation</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0121</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:区域结束">
+ <xsl:attribute name="字:标识符引用">cmt<xsl:number from="/office:document/office:body/office:text" level="any" count="office:annotation"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0122</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符引用</xsl:attribute>
+ </xsl:element>
+ </字:句>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:change-start'] or self::node()[name(.)='text:change'] or self::node()[name(.)='text:change-end']">
+ <xsl:call-template name="xiuding"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="字:句">
+ <xsl:with-param name="parentstyle" select="$parentstyle"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="xiuding">
+ <xsl:choose>
+ <xsl:when test="self::node()[name(.)='text:change-start']or self::node()[name(.)='text:change']">
+ <xsl:variable name="changeID">
+ <xsl:value-of select="@text:change-id"/>
+ </xsl:variable>
+ <xsl:for-each select="/office:document/office:body/office:text/text:tracked-changes/text:changed-region">
+ <xsl:if test="$changeID=@text:id">
+ <xsl:choose>
+ <xsl:when test="text:insertion">
+ <xsl:element name="字:修订开始">
+ <xsl:attribute name="uof:locID">t0206</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 类型 修订信息引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@text:id"/></xsl:attribute>
+ <xsl:attribute name="字:类型">insert</xsl:attribute>
+ <xsl:attribute name="字:修订信息引用"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="text:format-change">
+ <xsl:element name="字:修订开始">
+ <xsl:attribute name="uof:locID">t0206</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 类型 修订信息引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@text:id"/></xsl:attribute>
+ <xsl:attribute name="字:类型">format</xsl:attribute>
+ <xsl:attribute name="字:修订信息引用"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="text:deletion">
+ <xsl:element name="字:修订开始">
+ <xsl:attribute name="uof:locID">t0206</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 类型 修订信息引用</xsl:attribute>
+ <xsl:attribute name="字:标识符"><xsl:value-of select="@text:id"/></xsl:attribute>
+ <xsl:attribute name="字:类型">delete</xsl:attribute>
+ <xsl:attribute name="字:修订信息引用"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="self::node()[name(.)='text:change-end']">
+ <xsl:variable name="changeendID">
+ <xsl:value-of select="@text:change-id"/>
+ </xsl:variable>
+ <xsl:for-each select="/office:document/office:body/office:text/text:tracked-changes/text:changed-region">
+ <xsl:if test="$changeendID=@text:id">
+ <xsl:choose>
+ <xsl:when test="text:insertion">
+ <xsl:element name="字:修订结束">
+ <xsl:attribute name="uof:locID">t0207</xsl:attribute>
+ <xsl:attribute name="uof:attrList">开始标识引用</xsl:attribute>
+ <xsl:attribute name="字:开始标识引用"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="text:deletion">
+ <xsl:element name="字:修订结束">
+ <xsl:attribute name="uof:locID">t0207</xsl:attribute>
+ <xsl:attribute name="uof:attrList">开始标识引用</xsl:attribute>
+ <xsl:attribute name="字:开始标识引用"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="text:format-change">
+ <xsl:element name="字:修订结束">
+ <xsl:attribute name="uof:locID">t0207</xsl:attribute>
+ <xsl:attribute name="uof:attrList">开始标识引用</xsl:attribute>
+ <xsl:attribute name="字:开始标识引用"><xsl:value-of select="@text:id"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="字:句">
+ <xsl:param name="parentstyle"/>
+ <xsl:if test="not(name(.)='text:bookmark-start' or name(.)='text:bookmark-end' or name(.)='draw:image' or name(.)='office:binary-data' or name(.)='text:page-number' or name(.)='text:page-count' or name(.)='text:initial-creator' or name(.)='text:author-name' or name(.)='text:author-initials' or name(.)='text:creation-time' or name(.)='text:creation-date' or name(.)='text:title' or name(.)='text:subject' or name(.)='text:file-name' or name(.)='text:editing-duration' or name(.)='text:character-count' or name(.)='text:chapter')">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用">
+ <xsl:choose>
+ <xsl:when test="@text:style-name">
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="parent::text:h/@text:outline-level">
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="concat('Heading_20_',parent::text:h/@text:outline-level)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="parent::node()/@text:style-name">
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="parent::node( )/@text:style-name"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </字:句属性>
+ <xsl:if test="ancestor::text:note-body">
+ <字:引文符号>
+ <xsl:value-of select="ancestor::text:note/text:note-citation"/>
+ </字:引文符号>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="(preceding-sibling::text:bookmark-start) and (following-sibling::text:bookmark-end)">
+ <字:区域开始 uof:locID="t0121" uof:attrList="标识符 名称 类型">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="preceding-sibling::text:bookmark-start/@text:name"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Bookmark</xsl:attribute>
+ <xsl:attribute name="字:类型">bookmark</xsl:attribute>
+ </字:区域开始>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </xsl:element>
+ <字:区域结束 uof:locID="t0122" uof:attrList="标识符引用">
+ <xsl:attribute name="字:标识符引用"><xsl:value-of select="following-sibling::text:bookmark-end/@text:name"/></xsl:attribute>
+ </字:区域结束>
+ </xsl:when>
+ <xsl:when test="name(.)='draw:a'">
+ <xsl:variable name="link-name">
+ <xsl:value-of select="substring-after(@xlink:href,'#')"/>
+ </xsl:variable>
+ <字:区域开始 uof:locID="t0121" uof:attrList="标识符 名称 类型">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="$link-name"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Bookmark</xsl:attribute>
+ <xsl:attribute name="字:类型">bookmark</xsl:attribute>
+ </字:区域开始>
+ <xsl:call-template name="字:锚点"/>
+ <字:区域结束 uof:locID="t0122" uof:attrList="标识符引用">
+ <xsl:attribute name="字:标识符引用"><xsl:value-of select="$link-name"/></xsl:attribute>
+ </字:区域结束>
+ </xsl:when>
+ <xsl:when test="self::node( )[name(.)='text:tab']">
+ <xsl:element name="字:制表符">
+ <xsl:attribute name="uof:locID">t0123</xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="self::node( )[name(.)='text:line-break']">
+ <xsl:element name="字:换行符">
+ <xsl:attribute name="uof:locID">t0124</xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="name(.)='text:bookmark-start' or name(.)='text:bookmark-end' or name(.)='draw:image' or name(.)='office:binary-data'">
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:句>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="draw:text-box">
+ <xsl:apply-templates/>
+ </xsl:template>
+ <xsl:template name="text">
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="parent::node( )/@text:style-name"/></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="textspan">
+ <字:句 uof:locID="t0085">
+ <xsl:choose>
+ <xsl:when test="./text:note/@text:note-class='footnote'">
+ <xsl:for-each select="text:note">
+ <xsl:call-template name="jiaozhu"/>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="./text:note/@text:note-class='endnote'">
+ <xsl:for-each select="text:note">
+ <xsl:call-template name="weizhu"/>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="字:句属性">
+ <xsl:attribute name="uof:locID">t0086</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:variable name="textstyle">
+ <xsl:value-of select="@text:style-name"/>
+ </xsl:variable>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ <xsl:for-each select="/office:document/office:automatic-styles//style:style[@style:family='text']">
+ <xsl:if test="@style:name=$textstyle and not(@style:parent-style-name='Standard')">
+ <xsl:if test="@style:parent-style-name=/office:document/office:styles/style:style/@style:name">
+ <xsl:call-template name="SentenceXD">
+ <xsl:with-param name="Sentencestyle" select="@style:parent-style-name"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="/office:document/office:automatic-styles//style:style[@style:family='text']">
+ <xsl:if test="@style:name=$textstyle">
+ <xsl:call-template name="SentenceXD">
+ <xsl:with-param name="Sentencestyle" select="@style:name"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:句>
+ </xsl:template>
+ <xsl:template name="SentenceXD">
+ <xsl:param name="Sentencestyle"/>
+ </xsl:template>
+ <xsl:template name="字:锚点">
+ <xsl:if test="not(name(.)='draw:glue-point')">
+ <xsl:variable name="name">
+ <xsl:value-of select="name(.)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="name='draw:a'">
+ <xsl:for-each select="child::node( )">
+ <xsl:call-template name="字:锚点"/>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$name = 'draw:g'">
+ <xsl:for-each select="child::*">
+ <xsl:call-template name="字:锚点"/>
+ </xsl:for-each>
+ </xsl:if>
+ <字:锚点 uof:locID="t0110" uof:attrList="标识符 类型">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='as-char'">
+ <xsl:attribute name="字:类型">inline</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:类型">normal</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <字:锚点属性 uof:locID="t0111">
+ <字:宽度 uof:locID="t0112">
+ <xsl:choose>
+ <xsl:when test="@svg:width">
+ <xsl:value-of select="substring-before(@svg:width,$uofUnit)"/>
+ </xsl:when>
+ <xsl:when test="@svg:x1">
+ <xsl:value-of select="substring-before(@svg:x2,$uofUnit) - substring-before(@svg:x1,$uofUnit)"/>
+ </xsl:when>
+ </xsl:choose>
+ </字:宽度>
+ <字:高度 uof:locID="t0113">
+ <xsl:choose>
+ <xsl:when test="@svg:height">
+ <xsl:value-of select="substring-before(@svg:height,$uofUnit)"/>
+ </xsl:when>
+ <xsl:when test="@svg:x1">
+ <xsl:value-of select="substring-before(@svg:y2,$uofUnit) - substring-before(@svg:y1,$uofUnit)"/>
+ </xsl:when>
+ <xsl:when test="child::draw:text-box/@fo:min-height">
+ <xsl:value-of select="substring-before(child::draw:text-box/@fo:min-height,$uofUnit)"/>
+ </xsl:when>
+ </xsl:choose>
+ </字:高度>
+ <xsl:if test="not(@text:anchor-type='as-char')">
+ <字:位置 uof:locID="t0114">
+ <字:水平 uof:locID="t0176" uof:attrList="相对于">
+ <xsl:for-each select="key('graphicset',@draw:style-name)/style:graphic-properties">
+ <xsl:attribute name="字:相对于"><xsl:choose><xsl:when test="@style:horizontal-rel='page'">page</xsl:when><xsl:when test="@style:horizontal-rel='paragraph'">margin</xsl:when><xsl:when test="@style:horizontal-rel='page-content'">margin</xsl:when><xsl:when test="@style:horizontal-rel='paragraph-content'">margin</xsl:when><xsl:when test="@style:horizontal-rel='char'">char</xsl:when><xsl:otherwise>paragraph</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="@svg:x or @svg:x1">
+ <字:绝对 uof:locID="t0177" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@svg:x"><xsl:value-of select="substring-before(@svg:x,$uofUnit)"/></xsl:when><xsl:when test="@svg:x1"><xsl:value-of select="substring-before(@svg:x1,$uofUnit)"/></xsl:when></xsl:choose></xsl:attribute>
+ </字:绝对>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:相对 uof:locID="t0178" uof:attrList="参考点 值">
+ <xsl:for-each select="key('graphicset',@draw:style-name)/style:graphic-properties">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@style:horizontal-pos='left'">left</xsl:when><xsl:when test="@style:horizontal-pos='right'">right</xsl:when><xsl:when test="@style:horizontal-pos='center'">center</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ </字:相对>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:水平>
+ <字:垂直 uof:locID="t0179" uof:attrList="相对于">
+ <xsl:for-each select="key('graphicset',@draw:style-name)/style:graphic-properties">
+ <xsl:attribute name="字:相对于"><xsl:choose><xsl:when test="@style:vertical-rel='page'">page</xsl:when><xsl:when test="@style:vertical-rel='paragraph'">paragraph</xsl:when><xsl:when test="@style:vertical-rel='page-content'">margin</xsl:when><xsl:when test="@style:vertical-rel='paragraph-content'">margin</xsl:when><xsl:when test="@style:vertical-rel='line'">line</xsl:when><xsl:otherwise>paragraph</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="@svg:y or @svg:y1">
+ <字:绝对 uof:locID="t0180" uof:attrList="值">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@svg:y"><xsl:value-of select="substring-before(@svg:y,$uofUnit)"/></xsl:when><xsl:when test="@svg:y1"><xsl:value-of select="substring-before(@svg:y1,$uofUnit)"/></xsl:when></xsl:choose></xsl:attribute>
+ </字:绝对>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:相对 uof:locID="t0181" uof:attrList="参考点 值">
+ <xsl:for-each select="key('graphicset',@draw:style-name)/style:graphic-properties">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@style:vertical-pos='bottom'">bottom</xsl:when><xsl:when test="@style:vertical-pos='top'">top</xsl:when><xsl:when test="@style:vertical-pos='middle'">center</xsl:when><xsl:when test="@style:vertical-pos='below'">inside</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ </字:相对>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:垂直>
+ </字:位置>
+ </xsl:if>
+ <xsl:for-each select="key('graphicset',@draw:style-name)/style:graphic-properties">
+ <字:绕排 uof:locID="t0115" uof:attrList="绕排方式 环绕文字 绕排顶点">
+ <xsl:variable name="wrap_type1">
+ <xsl:value-of select="@style:wrap"/>
+ </xsl:variable>
+ <xsl:variable name="wrap_type2">
+ <xsl:value-of select="@style:run-through"/>
+ </xsl:variable>
+ <xsl:variable name="a">
+ <xsl:value-of select="@style:number-wrapped-paragraphs"/>
+ </xsl:variable>
+ <xsl:if test="$wrap_type1">
+ <xsl:attribute name="字:绕排方式"><xsl:choose><xsl:when test="$wrap_type1='run-through' and $wrap_type2='background' ">behindtext</xsl:when><xsl:when test="$wrap_type1='run-through' and $a='1'">infrontoftext</xsl:when><xsl:when test="$wrap_type1='run-through'">through</xsl:when><xsl:when test="$wrap_type1='dynamic' ">top-bottom</xsl:when><xsl:when test="$wrap_type1='parallel' ">square</xsl:when><xsl:when test="$wrap_type1='left' or $wrap_type1='right'">tight</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$wrap_type1='left' or $wrap_type1='right'">
+ <xsl:attribute name="字:环绕文字"><xsl:choose><xsl:when test="$wrap_type1='left'">left</xsl:when><xsl:when test="$wrap_type1='right'">right</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </字:绕排>
+ <字:边距 uof:locID="t0116" uof:attrList="上 左 右 下">
+ <xsl:choose>
+ <xsl:when test="@fo:margin-top">
+ <xsl:attribute name="字:上"><xsl:value-of select="substring-before(@fo:margin-top,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:下"><xsl:value-of select="substring-before(@fo:margin-bottom,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:上">0.0</xsl:attribute>
+ <xsl:attribute name="字:下">0.0</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@fo:margin-right">
+ <xsl:attribute name="字:右"><xsl:value-of select="substring-before(@fo:margin-right,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:左"><xsl:value-of select="substring-before(@fo:margin-left,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:右">0.0</xsl:attribute>
+ <xsl:attribute name="字:左">0.0</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:边距>
+ <字:锁定 uof:attrList="值" uof:locID="t0117">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@draw:move-protect='false'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </字:锁定>
+ <字:保护 uof:locID="t0118" uof:attrList="值">
+ <xsl:choose>
+ <xsl:when test="$name='draw:image' or $name='draw:text-box'">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@style:protect = 'content size position' or @style:protect = 'content' or @style:protect = 'content size' or @style:protect = 'size position' or @style:protect = 'size' or @style:protect = 'position' or @style:protect = 'content position' and @draw:size-protect= 'true'and @draw:move-protect= 'true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@style:protect = 'position size'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:保护>
+ </xsl:for-each>
+ <字:允许重叠 uof:locID="t0119" uof:attrList="值" 字:值="true"/>
+ </字:锚点属性>
+ <字:图形 uof:locID="t0120" uof:attrList="图形引用">
+ <xsl:variable name="refpicname">
+ <xsl:if test="@draw:style-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="picnumber">
+ <xsl:if test="@draw:style-name">
+ <xsl:value-of select="count(preceding::*[@draw:style-name=$refpicname])"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:attribute name="字:图形引用"><xsl:value-of select="concat($refpicname,'_',$picnumber)"/></xsl:attribute>
+ </字:图形>
+ </字:锚点>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="liekuan">
+ <xsl:param name="count"/>
+ <xsl:param name="width"/>
+ <xsl:if test="$count &gt; 0">
+ <字:列宽 uof:locID="t0132">
+ <xsl:value-of select="$width"/>
+ </字:列宽>
+ <xsl:call-template name="liekuan">
+ <xsl:with-param name="count" select="$count -1"/>
+ <xsl:with-param name="width" select="$width"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="exec_table" match="table:table">
+ <xsl:param name="tabletype"/>
+ <字:文字表 uof:locID="t0128" uof:attrList="类型">
+ <xsl:choose>
+ <xsl:when test="@table:is-sub-table='true'">
+ <xsl:attribute name="字:类型">sub-table</xsl:attribute>
+ <xsl:element name="字:文字表属性">
+ <xsl:attribute name="uof:locID">t0129</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:element name="字:列宽集">
+ <xsl:attribute name="uof:locID">t0131</xsl:attribute>
+ <xsl:for-each select="table:table-column">
+ <xsl:variable name="tableColName" select="@table:style-name"/>
+ <xsl:variable name="colWidth" select="substring-before(//style:style[@style:name=$tableColName and @style:family='table-column']/style:table-column-properties/@style:column-width,$ooUnit)"/>
+ <xsl:choose>
+ <xsl:when test="@table:number-columns-repeated">
+ <xsl:call-template name="liekuan">
+ <xsl:with-param name="count" select="@table:number-columns-repeated"/>
+ <xsl:with-param name="width" select="$colWidth"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:列宽 uof:locID="t0132">
+ <xsl:value-of select="$colWidth"/>
+ </字:列宽>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:类型">table</xsl:attribute>
+ <xsl:element name="字:文字表属性">
+ <xsl:attribute name="uof:locID">t0129</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@table:style-name"/></xsl:attribute>
+ <xsl:variable name="tableName" select="@table:style-name"/>
+ <xsl:element name="字:列宽集">
+ <xsl:attribute name="uof:locID">t0131</xsl:attribute>
+ <xsl:for-each select="table:table-column">
+ <xsl:variable name="tableColName" select="@table:style-name"/>
+ <xsl:variable name="colWidth" select="substring-before(//style:style[@style:name=$tableColName and @style:family='table-column']/style:table-column-properties/@style:column-width,$ooUnit)"/>
+ <xsl:choose>
+ <xsl:when test="@table:number-columns-repeated">
+ <xsl:call-template name="liekuan">
+ <xsl:with-param name="count" select="@table:number-columns-repeated"/>
+ <xsl:with-param name="width" select="$colWidth"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <字:列宽 uof:locID="t0132">
+ <xsl:value-of select="$colWidth"/>
+ </字:列宽>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:for-each select="key('set_styleStyle',$tableName)">
+ <xsl:element name="字:宽度">
+ <xsl:attribute name="uof:locID">t0130</xsl:attribute>
+ <xsl:attribute name="uof:attrList">绝对宽度 相对宽度</xsl:attribute>
+ <xsl:attribute name="字:绝对宽度"><xsl:value-of select="substring-before(style:table-properties/@style:width,$ooUnit)"/></xsl:attribute>
+ <xsl:if test="style:table-properties/@style:rel-width">
+ <xsl:attribute name="字:相对宽度"><xsl:value-of select="substring-before(style:table-properties/@style:rel-width,'%') div 100"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="字:对齐">
+ <xsl:attribute name="uof:locID">t0133</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="style:table-properties/@table:align='right'">right</xsl:when>
+ <xsl:when test="style:table-properties/@table:align='center'">center</xsl:when>
+ <xsl:otherwise>left</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="style:table-properties/@fo:margin-left">
+ <xsl:element name="字:左缩进">
+ <xsl:attribute name="uof:locID">t0134</xsl:attribute>
+ <xsl:value-of select="substring-before(style:table-properties/@fo:margin-left,$ooUnit)"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:绕排">
+ <xsl:attribute name="uof:locID">t0135</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">around</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:边框">
+ <xsl:attribute name="uof:locID">t0137</xsl:attribute>
+ <xsl:for-each select="style:table-properties">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:if test="style:table-properties/style:background-image/office:binary-data or style:table-properties/@fo:background-color or style:page-layout-properties/@fo:background-color">
+ <字:填充 uof:locID="t0138">
+ <xsl:for-each select="style:table-properties">
+ <xsl:call-template name="图:填充">
+ <xsl:with-param name="style-name" select="$tableName"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </字:填充>
+ </xsl:if>
+ <xsl:element name="字:绕排边距">
+ <xsl:attribute name="uof:locID">t0139</xsl:attribute>
+ <xsl:attribute name="uof:attrList">上 左 右 下</xsl:attribute>
+ <xsl:if test="style:table-properties/@fo:margin-top">
+ <xsl:attribute name="字:上"><xsl:value-of select="substring-before(style:table-properties/@fo:margin-top,$ooUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:table-properties/@fo:margin-left">
+ <xsl:attribute name="字:左"><xsl:value-of select="substring-before(style:table-properties/@fo:margin-left,$ooUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:table-properties/@fo:margin-right">
+ <xsl:attribute name="字:右"><xsl:value-of select="substring-before(style:table-properties/@fo:margin-right,$ooUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:table-properties/@fo:margin-bottom">
+ <xsl:attribute name="字:下"><xsl:value-of select="substring-before(style:table-properties/@fo:margin-bottom,$ooUnit)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="字:自动调整大小">
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0140</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:默认单元格边距">
+ <xsl:attribute name="uof:locID">t0141</xsl:attribute>
+ <xsl:attribute name="uof:attrList">上 左 右 下</xsl:attribute>
+ <xsl:attribute name="字:上">0.10</xsl:attribute>
+ <xsl:attribute name="字:左">0.10</xsl:attribute>
+ <xsl:attribute name="字:右">0.10</xsl:attribute>
+ <xsl:attribute name="字:下">0.10</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:默认单元格间距">
+ <xsl:attribute name="uof:locID">t0142</xsl:attribute>
+ <xsl:value-of select="'0.00'"/>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates select="table:table-header-rows/table:table-row"/>
+ <xsl:apply-templates select="table:table-row"/>
+ </字:文字表>
+ </xsl:template>
+ <xsl:key name="set_colWidth" match="//office:automatic-styles/style:style[@style:family='table-column']" use="@style:name"/>
+ <xsl:key name="set_styleStyle" match="//office:automatic-styles/style:style" use="@style:name"/>
+ <xsl:template match="table:table-row">
+ <xsl:element name="字:行">
+ <xsl:attribute name="uof:locID">t0143</xsl:attribute>
+ <xsl:variable name="rowStyleName" select="@table:style-name|table:table-row/@table:style-name"/>
+ <xsl:element name="字:表行属性">
+ <xsl:attribute name="uof:locID">t0144</xsl:attribute>
+ <xsl:for-each select="key('set_styleStyle',$rowStyleName)/style:table-row-properties[@style:row-height or @style:min-row-height]">
+ <xsl:element name="字:高度">
+ <xsl:if test="@style:row-height">
+ <xsl:attribute name="字:固定值"><xsl:value-of select="substring-before(@style:row-height,$ooUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@style:min-row-height">
+ <xsl:attribute name="字:最小值"><xsl:value-of select="substring-before(@style:min-row-height,$ooUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="uof:locID">t0145</xsl:attribute>
+ <xsl:attribute name="uof:attrList">固定值 最小值</xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:if test="key('set_styleStyle',$rowStyleName)/style:table-row-properties[@style:keep-together]">
+ <xsl:element name="字:跨页">
+ <xsl:attribute name="uof:locID">t0146</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:for-each select="key('set_styleStyle',$rowStyleName)/style:table-row-properties[@style:keep-together]">
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="@style:keep-together='false'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="name(..)='table:table-header-rows'">
+ <xsl:element name="字:表头行">
+ <xsl:attribute name="uof:locID">t0147</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name()='table:table-cell'">
+ <xsl:element name="字:单元格">
+ <xsl:attribute name="uof:locID">t0148</xsl:attribute>
+ <xsl:call-template name="execTableCellAttribute"/>
+ <xsl:for-each select="node( )">
+ <xsl:choose>
+ <xsl:when test="name()='text:p'">
+ <xsl:call-template name="execParagraph">
+ <xsl:with-param name="currlistlvl" select="number('0')"/>
+ <xsl:with-param name="liststylename" select="string('00000')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name()='table:table' or name()='table:sub-table' or self::node()/@table:is-sub-table='true'">
+ <xsl:call-template name="exec_table">
+ <xsl:with-param name="tabletype" select="name()"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="execTableCellAttribute">
+ <xsl:element name="字:单元格属性">
+ <xsl:attribute name="uof:locID">t0149</xsl:attribute>
+ <xsl:variable name="StyleName" select="@table:style-name"/>
+ <xsl:element name="字:宽度">
+ <xsl:attribute name="uof:locID">t0150</xsl:attribute>
+ <xsl:attribute name="uof:attrList">绝对值 相对值</xsl:attribute>
+ <xsl:variable name="sn">
+ <xsl:number from="/office:document/office:body/office:text" level="single" count="table:table-cell" format="1"/>
+ </xsl:variable>
+ <xsl:variable name="sn1">
+ <xsl:choose>
+ <xsl:when test="../../table:table-column[number($sn)]/@table:style-name">
+ <xsl:value-of select="$sn"/>
+ </xsl:when>
+ <xsl:when test=" name(../..)='table:table-header-rows' and ../../../table:table-column[number($sn)]/@table:style-name">
+ <xsl:value-of select="$sn"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'1'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="KuanDu">
+ <xsl:choose>
+ <xsl:when test=" name(../..)='table:table-header-rows' and ../../../table:table-column[number($sn)]/@table:style-name">
+ <xsl:value-of select="../../../table:table-column[number($sn1)]/@table:style-name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="../../table:table-column[number($sn1)]/@table:style-name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="字:绝对值"><xsl:value-of select="substring-before(key('set_colWidth',$KuanDu)/style:table-column-properties/@style:column-width,$ooUnit)"/></xsl:attribute>
+ <xsl:if test="key('set_colWidth',$KuanDu)/style:table-column-properties/@style:rel-column-width">
+ <xsl:attribute name="字:相对值"><xsl:value-of select="substring-before(key('set_colWidth',$KuanDu)/style:table-column-properties/@style:rel-column-width,'*')"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="@table:number-columns-spanned">
+ <xsl:element name="字:跨列">
+ <xsl:attribute name="uof:locID">t0156</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="@table:number-columns-spanned"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:for-each select="key('set_styleStyle',$StyleName)">
+ <xsl:element name="字:单元格边距">
+ <xsl:attribute name="uof:locID">t0151</xsl:attribute>
+ <xsl:attribute name="uof:attrList">上 左 右 下</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="style:table-cell-properties/@fo:padding">
+ <xsl:attribute name="字:上"><xsl:value-of select="substring-before(style:table-cell-properties/@fo:padding,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:左"><xsl:value-of select="substring-before(style:table-cell-properties/@fo:padding,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:右"><xsl:value-of select="substring-before(style:table-cell-properties/@fo:padding,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:下"><xsl:value-of select="substring-before(style:table-cell-properties/@fo:padding,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:上"><xsl:value-of select="substring-before(style:table-cell-properties/@fo:padding-top,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:左"><xsl:value-of select="substring-before(style:table-cell-properties/@fo:padding-left,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:右"><xsl:value-of select="substring-before(style:table-cell-properties/@fo:padding-right,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:下"><xsl:value-of select="substring-before(style:table-cell-properties/@fo:padding-bottom,$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="style:table-cell-properties/@fo:border or style:table-cell-properties/@fo:border-top or style:table-cell-properties/@fo:border-bottom or style:table-cell-properties/@fo:border-left or style:table-cell-properties/@fo:border-right or style:table-cell-properties/@style:shadow">
+ <xsl:element name="字:边框">
+ <xsl:attribute name="uof:locID">t0152</xsl:attribute>
+ <xsl:for-each select="style:table-cell-properties">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:table-cell-properties/style:background-image/office:binary-data or style:table-cell-properties/@fo:background-color">
+ <字:填充 uof:locID="t0153">
+ <xsl:for-each select="style:table-cell-properties">
+ <xsl:call-template name="图:填充"/>
+ </xsl:for-each>
+ </字:填充>
+ </xsl:if>
+ <字:垂直对齐方式 uof:locID="t0154">
+ <xsl:choose>
+ <xsl:when test="style:table-cell-properties/@style:vertical-align='middle'">center</xsl:when>
+ <xsl:when test="style:table-cell-properties/@style:vertical-align='bottom'">bottom</xsl:when>
+ <xsl:otherwise>top</xsl:otherwise>
+ </xsl:choose>
+ </字:垂直对齐方式>
+ <xsl:element name="字:自动换行">
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0157</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:适应文字">
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0158</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:key name="bpath" match="//office:document/office:body/office:text/text:p/text:span" use="@text:style-name"/>
+ <xsl:template name="字:句属性">
+ <xsl:element name="字:字体">
+ <xsl:attribute name="uof:locID">t0088</xsl:attribute>
+ <xsl:attribute name="uof:attrList">西文字体引用 中文字体引用 特殊字体引用 西文绘制 字号 相对字号 颜色</xsl:attribute>
+ <xsl:if test="contains(@style:parent-style-name,'Header') or contains(@style:parent-style-name,'Foot') or contains(@style:parent-style-name,'Endnote')">
+ <xsl:attribute name="字:字号">9</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:font-size or style:text-properties/@style:font-size-asian or style:text-properties/@style:font-size-complex">
+ <xsl:choose>
+ <xsl:when test="contains(style:text-properties/@fo:font-size,'%') or contains(style:text-properties/@style:font-size-asian,'%')">
+ <xsl:attribute name="字:相对字号"><xsl:choose><xsl:when test="style:text-properties/@fo:font-size"><xsl:value-of select="substring-before(style:text-properties/@fo:font-size,'%')"/></xsl:when><xsl:when test="style:text-properties/@style:font-size-asian"><xsl:value-of select="substring-before(style:text-properties/@style:font-size-asian,'%')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:字号"><xsl:choose><xsl:when test="style:text-properties/@fo:font-size"><xsl:value-of select="substring-before(style:text-properties/@fo:font-size,'pt')"/></xsl:when><xsl:when test="style:text-properties/@style:font-size-asian"><xsl:value-of select="substring-before(style:text-properties/@style:font-size-asian,'pt')"/></xsl:when><xsl:when test="style:text-properties/@style:font-size-complex"><xsl:value-of select="substring-before(style:text-properties/@style:font-size-complex,'pt')"/></xsl:when></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:font-name">
+ <xsl:variable name="xiwen" select="style:text-properties/@style:font-name"/>
+ <xsl:attribute name="字:西文字体引用"><xsl:value-of select="translate($xiwen,' ','_')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:font-name-asian">
+ <xsl:attribute name="字:中文字体引用"><xsl:value-of select="style:text-properties/@style:font-name-asian"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select="style:text-properties/@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="style:text-properties/@fo:background-color and not(style:text-properties/@style:text-background-color='transparent')">
+ <xsl:element name="字:填充">
+ <xsl:attribute name="uof:locID">t0093</xsl:attribute>
+ <xsl:element name="图:图案">
+ <xsl:attribute name="uof:locID">g0036</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 图形引用 前景色 背景色</xsl:attribute>
+ <xsl:if test="style:text-properties/@fo:background-color">
+ <xsl:attribute name="图:前景色"><xsl:choose><xsl:when test="style:text-properties/@fo:background-color='transparent'">auto</xsl:when><xsl:otherwise><xsl:value-of select="style:text-properties/@fo:background-color"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:font-weight or style:text-properties/@style:font-weight-asian">
+ <xsl:element name="字:粗体">
+ <xsl:attribute name="uof:locID">t0089</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@style:font-weight-asian='bold' or style:text-properties/@fo:font-weight='bold'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:font-style or style:text-properties/@style:font-style-asian">
+ <xsl:element name="字:斜体">
+ <xsl:attribute name="uof:locID">t0090</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@fo:font-style='italic' or style:text-properties/@style:font-style-asian='italic'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:background-color|style:text-properties/@style:text-background-color">
+ <xsl:element name="字:突出显示">
+ <xsl:attribute name="字:颜色"><xsl:choose><xsl:when test="style:text-properties/@fo:background-color='transparent' or style:text-properties/@style:text-background-color='transparent'">auto</xsl:when><xsl:otherwise><xsl:value-of select="style:text-properties/@fo:background-color|style:text-properties/@style:text-background-color"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0091</xsl:attribute>
+ <xsl:attribute name="uof:attrList">颜色</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-line-through-style">
+ <xsl:element name="字:删除线">
+ <xsl:attribute name="uof:locID">t0094</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:删除线类型"><xsl:with-param name="lineType" select="style:text-properties/@style:text-line-through-style"/></xsl:call-template></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-underline-style">
+ <xsl:element name="字:下划线">
+ <xsl:attribute name="uof:locID">t0095</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 颜色 字下划线</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:线型类型"/></xsl:attribute>
+ <xsl:if test="style:text-properties/@style:text-underline-color">
+ <xsl:attribute name="字:颜色"><xsl:choose><xsl:when test="style:text-properties/@style:text-underline-color='font-color'">auto</xsl:when><xsl:otherwise><xsl:value-of select="style:text-properties/@style:text-underline-color"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:text-shadow">
+ <xsl:element name="字:阴影">
+ <xsl:attribute name="uof:locID">t0100</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:choose><xsl:when test="style:text-properties/@fo:text-shadow='none'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-emphasize">
+ <xsl:element name="字:着重号">
+ <xsl:attribute name="uof:locID">t0096</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 颜色 字着重号</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:call-template name="uof:着重号类型"><xsl:with-param name="te" select="style:text-properties/@style:text-emphasize"/></xsl:call-template></xsl:attribute>
+ <xsl:if test="style:text-properties/@fo:color">
+ <xsl:attribute name="字:颜色"><xsl:value-of select="style:text-properties/@fo:color"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@text:display">
+ <xsl:element name="字:隐藏文字">
+ <xsl:attribute name="uof:locID">t0097</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-outline">
+ <xsl:element name="字:空心">
+ <xsl:attribute name="uof:locID">t0098</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值"><xsl:value-of select="style:text-properties/@style:text-outline"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:font-relief">
+ <xsl:element name="字:浮雕">
+ <xsl:attribute name="uof:locID">t0099</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test="style:text-properties/@style:font-relief='embossed'">emboss</xsl:when><xsl:when test="style:text-properties/@style:font-relief='engraved'">engrave</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:text-transform or style:text-properties/@fo:font-variant">
+ <xsl:element name="字:醒目字体">
+ <xsl:attribute name="uof:locID">t0101</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型</xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:choose><xsl:when test="style:text-properties/@fo:text-transform='uppercase'">uppercase</xsl:when><xsl:when test="style:text-properties/@fo:text-transform='lowercase'">lowercase</xsl:when><xsl:when test="style:text-properties/@fo:text-transform='capitalize'">capital</xsl:when><xsl:when test="style:text-properties/@fo:font-variant='small-caps'">small-caps</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-position">
+ <xsl:element name="字:位置">
+ <xsl:attribute name="uof:locID">t0102</xsl:attribute>
+ <xsl:variable name="aa">
+ <xsl:value-of select="style:text-properties/@style:text-position"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($aa,'sub')">
+ <xsl:value-of select="substring-before($aa,' ')"/>
+ </xsl:when>
+ <xsl:when test="contains($aa,'super')">
+ <xsl:value-of select="substring-before($aa,' ')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate($aa,'%','')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:text-scale">
+ <xsl:element name="字:缩放">
+ <xsl:attribute name="uof:locID">t0103</xsl:attribute>
+ <xsl:variable name="scale" select="style:text-properties/@style:text-scale"/>
+ <xsl:choose>
+ <xsl:when test="contains($scale,'%')">
+ <xsl:value-of select="substring-before($scale,'%')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="style:text-properties/@style:text-scale"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@fo:letter-spacing">
+ <xsl:element name="字:字符间距">
+ <xsl:attribute name="uof:locID">t0104</xsl:attribute>
+ <xsl:value-of select="substring-before(style:text-properties/@fo:letter-spacing,$uofUnit)"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="style:text-properties/@style:letter-kerning">
+ <xsl:element name="字:调整字间距">
+ <xsl:variable name="tt" select="style:text-properties/@style:letter-kerning"/>
+ <xsl:attribute name="uof:locID">t0105</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$tt='true'">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="字:字符对齐网格">
+ <xsl:attribute name="字:值">false</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0106</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="uof:线型类型">
+ <xsl:variable name="spath" select="style:text-properties/@style:text-underline-style"/>
+ <xsl:variable name="wpath" select="style:text-properties/@style:text-underline-width"/>
+ <xsl:variable name="tpath" select="style:text-properties/@style:text-underline-type"/>
+ <xsl:choose>
+ <xsl:when test="$spath='solid' and not($tpath='double' ) and $wpath='auto' ">single</xsl:when>
+ <xsl:when test="$spath='solid' and $tpath='double' and $wpath='auto' ">double</xsl:when>
+ <xsl:when test="$spath='solid' and not($tpath='double' )and $wpath='bold' ">thick</xsl:when>
+ <xsl:when test="$spath='dotted' and not($tpath='double' )and $wpath='auto' ">dotted</xsl:when>
+ <xsl:when test="$spath='dotted' and not($tpath='double' )and $wpath='bold' ">dotted-heavy</xsl:when>
+ <xsl:when test="$spath='dash' and not($tpath='double' )and $wpath='auto' ">dash</xsl:when>
+ <xsl:when test="$spath='dash' and not($tpath='double' )and $wpath='bold' ">dashed-heavy</xsl:when>
+ <xsl:when test="$spath='long-dash' and not($tpath='double' )and $wpath='auto' ">dash-long</xsl:when>
+ <xsl:when test="$spath='long-dash' and not($tpath='double' )and $wpath='bold' ">dash-long-heavy</xsl:when>
+ <xsl:when test="$spath='dot-dash' and not($tpath='double' )and $wpath='auto' ">dot-dash</xsl:when>
+ <xsl:when test="$spath='dot-dash' and not($tpath='double' )and $wpath='bold' ">dash-dot-heavy</xsl:when>
+ <xsl:when test="$spath='dot-dot-dash' and not($tpath='double' )and $wpath='auto' ">dot-dot-dash</xsl:when>
+ <xsl:when test="$spath='dot-dot-dash' and not($tpath='double' )and $wpath='bold' ">dash-dot-dot-heavy</xsl:when>
+ <xsl:when test="$spath='wave' and not($tpath='double' )and $wpath='auto' ">wave</xsl:when>
+ <xsl:when test="$spath='wave' and not($tpath='double' )and $wpath='bold' ">wavy-heavy</xsl:when>
+ <xsl:when test="$spath='wave' and $tpath='double' and $wpath='auto' ">wavy-double</xsl:when>
+ <xsl:otherwise>none</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="uof:删除线类型">
+ <xsl:param name="lineType"/>
+ <xsl:variable name="tw" select="style:text-properties/@style:text-line-through-width"/>
+ <xsl:variable name="tt" select="style:text-properties/@style:text-line-through-text"/>
+ <xsl:variable name="ttp" select="style:text-properties/@style:text-line-through-type"/>
+ <xsl:choose>
+ <xsl:when test="$lineType='solid'and $ttp='double'">double</xsl:when>
+ <xsl:when test="$lineType='solid'and $tw='bold'">bold</xsl:when>
+ <xsl:when test="$lineType='solid'and $tt='X'">xl</xsl:when>
+ <xsl:when test="$lineType='solid'and $tt='/'">/l</xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="not($lineType='none') ">single</xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="uof:着重号类型">
+ <xsl:param name="te"/>
+ <xsl:choose>
+ <xsl:when test="$te='disc above' ">disc above</xsl:when>
+ <xsl:when test="$te='circle above' ">circle above</xsl:when>
+ <xsl:when test="$te='dot above' ">dot above</xsl:when>
+ <xsl:when test="$te='accent above' ">accent above</xsl:when>
+ <xsl:when test="$te='dot below' ">dot</xsl:when>
+ <xsl:when test="$te='circle below' ">circle below</xsl:when>
+ <xsl:when test="$te='disc below' ">disc below</xsl:when>
+ <xsl:when test="$te='accent below' ">accent below</xsl:when>
+ <xsl:otherwise>none</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="uof:边框">
+ <xsl:choose>
+ <xsl:when test="@fo:border">
+ <xsl:call-template name="uof:左边框">
+ <xsl:with-param name="border" select="@fo:border"/>
+ </xsl:call-template>
+ <xsl:call-template name="uof:上边框">
+ <xsl:with-param name="border" select="@fo:border"/>
+ </xsl:call-template>
+ <xsl:call-template name="uof:右边框">
+ <xsl:with-param name="border" select="@fo:border"/>
+ </xsl:call-template>
+ <xsl:call-template name="uof:下边框">
+ <xsl:with-param name="border" select="@fo:border"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="@fo:border-left or contains(substring-before(substring-after(@style:shadow,' '),' '),'-')">
+ <xsl:call-template name="uof:左边框">
+ <xsl:with-param name="border" select="@fo:border-left"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="@fo:border-top or contains(substring-after(substring-after(@style:shadow,' '),' '),'-')">
+ <xsl:call-template name="uof:上边框">
+ <xsl:with-param name="border" select="@fo:border-top"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="@fo:border-right or substring-before(substring-before(substring-after(@style:shadow,' '),' '),$ooUnit) &gt;0 or contains(substring-before(substring-after(@style:shadow,' '),' '),'+')">
+ <xsl:call-template name="uof:右边框">
+ <xsl:with-param name="border" select="@fo:border-right"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="@fo:border-bottom or substring-before(substring-after(substring-after(@style:shadow,' '),' '),$ooUnit) &gt;0 or contains(substring-after(substring-after(@style:shadow,' '),' '),'+')">
+ <xsl:call-template name="uof:下边框">
+ <xsl:with-param name="border" select="@fo:border-bottom"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="uof:左边框">
+ <xsl:param name="border"/>
+ <xsl:element name="uof:左">
+ <xsl:attribute name="uof:locID">u0057</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($border,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='double'">double</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dashed'">dash</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dotted'">dotted</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$border!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($border,' '),substring($ooUnit,1,2))"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($border,' '),' ')"/></xsl:attribute>
+ <xsl:if test="@fo:padding or @fo:padding-left">
+ <xsl:attribute name="uof:边距"><xsl:choose><xsl:when test="@fo:padding-left"><xsl:value-of select="substring-before(@fo:padding-left,$ooUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="substring-before(@fo:padding,$ooUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="contains(substring-before(substring-after(@style:shadow,' '),' '),'-')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="uof:上边框">
+ <xsl:param name="border"/>
+ <xsl:element name="uof:上">
+ <xsl:attribute name="uof:locID">u0058</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($border,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='double'">double</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dashed'">dash</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dotted'">dotted</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$border!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($border,' '),substring($ooUnit,1,2))"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($border,' '),' ')"/></xsl:attribute>
+ <xsl:if test="@fo:padding or @fo:padding-top">
+ <xsl:attribute name="uof:边距"><xsl:choose><xsl:when test="@fo:padding-top"><xsl:value-of select="substring-before(@fo:padding-top,$ooUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="substring-before(@fo:padding,$ooUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="contains(substring-after(substring-after(@style:shadow,' '),' '),'-')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="uof:右边框">
+ <xsl:param name="border"/>
+ <xsl:element name="uof:右">
+ <xsl:attribute name="uof:locID">u0059</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($border,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='double'">double</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dashed'">dash</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dotted'">dotted</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$border!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($border,' '),substring($ooUnit,1,2))"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($border,' '),' ')"/></xsl:attribute>
+ <xsl:if test="@fo:padding or @fo:padding-right">
+ <xsl:attribute name="uof:边距"><xsl:choose><xsl:when test="@fo:padding-right"><xsl:value-of select="substring-before(@fo:padding-right,$ooUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="substring-before(@fo:padding,$ooUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="substring-before(substring-before(substring-after(@style:shadow,' '),' '),$ooUnit) &gt;0 or contains(substring-before(substring-after(@style:shadow,' '),' '),'+')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="uof:下边框">
+ <xsl:param name="border"/>
+ <xsl:element name="uof:下">
+ <xsl:attribute name="uof:locID">u0060</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 宽度 边距 颜色 阴影</xsl:attribute>
+ <xsl:attribute name="uof:类型"><xsl:choose><xsl:when test="$border!='none'"><xsl:choose><xsl:when test="substring-before(substring-after($border,' '),' ')='solid'">single</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='double'">double</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dashed'">dash</xsl:when><xsl:when test="substring-before(substring-after($border,' '),' ')='dotted'">dotted</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$border!='none'">
+ <xsl:attribute name="uof:宽度"><xsl:value-of select="substring-before(substring-before($border,' '),substring($ooUnit,1,2))"/></xsl:attribute>
+ <xsl:attribute name="uof:颜色"><xsl:value-of select="substring-after(substring-after($border,' '),' ')"/></xsl:attribute>
+ <xsl:if test="@fo:padding or @fo:padding-bottom">
+ <xsl:attribute name="uof:边距"><xsl:choose><xsl:when test="@fo:padding-bottom"><xsl:value-of select="substring-before(@fo:padding-bottom,$ooUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="substring-before(@fo:padding,$ooUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="substring-before(substring-after(substring-after(@style:shadow,' '),' '),$ooUnit) &gt;0 or contains(substring-after(substring-after(@style:shadow,' '),' '),'+')">
+ <xsl:attribute name="uof:阴影">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:key name="geshi" match="//office:document/office:automatic-styles/number:date-style | //office:document/office:automatic-styles/number:time-style" use="@style:name"/>
+ <xsl:template name="inline-text">
+ <xsl:param name="pStyleName"/>
+ <xsl:param name="bText"/>
+ <xsl:apply-templates select="text()|textspan|jiaozhu|weizhu|office:annotation|text:sequence|text:date|text:time|text:page-number|text:page-count|text:subject|text:title|text:initial-creator|text:author-name|text:author-initials|text:file-name|text:change-start|text:change-end|text:change">
+ <xsl:with-param name="pStyleName" select="$pStyleName"/>
+ <xsl:with-param name="bText" select="$bText"/>
+ </xsl:apply-templates>
+ </xsl:template>
+ <xsl:template match="text:sequence">
+ <xsl:param name="tStyle"/>
+ <xsl:if test="@text:name='Illustration' or @text:name='Text' or @text:name='Drawing' or @text:name='Table'">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'seq'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <xsl:if test="$tStyle!=''">
+ <字:句属性 字:式样引用="{$tStyle}" uof:locID="t0086" uof:attrList="式样引用"/>
+ </xsl:if>
+ <xsl:variable name="fmt">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="@style:num-format"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="concat('SEQ ',@text:name,' \* ',$fmt,' \f ',@text:formula)"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="text:time">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'time'"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <xsl:variable name="timefmt">
+ <xsl:variable name="aa" select="@style:data-style-name"/>
+ <xsl:for-each select="key('geshi',$aa)/number:hours | key('geshi',$aa)/number:minutes | key('geshi',$aa)/number:am-pm | key('geshi',$aa)/number:seconds | key('geshi',$aa)/number:text">
+ <xsl:choose>
+ <xsl:when test="@number:style='long' ">
+ <xsl:if test="self::node( )[name(.)='number:hours']">HH</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:minutes']">MM</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:seconds']">SS</xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="self::node( )[name(.)='number:text']">
+ <xsl:value-of select="."/>
+ </xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:hours']">H</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:minutes']">M</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:seconds']">S</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:am-pm']">am/pm</xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="quote">"</xsl:variable>
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="concat('TIME \@ ',$quote,$timefmt,$quote)"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:date">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'date'"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <xsl:variable name="datefmt">
+ <xsl:variable name="bb" select="@style:data-style-name"/>
+ <xsl:for-each select="key('geshi',$bb)/number:year | key('geshi',$bb)/number:month | key('geshi',$bb)/number:day | key('geshi',$bb)/number:hours | key('geshi',$bb)/number:minutes | key('geshi',$bb)/number:seconds | key('geshi',$bb)/number:quarter | key('geshi',$bb)/number:day-of-week | key('geshi',$bb)/number:week-of-year | key('geshi',$bb)/number:text | key('geshi',$bb)/number:am-pm">
+ <xsl:choose>
+ <xsl:when test="@number:style='long' ">
+ <xsl:if test="self::node( )[name(.)='number:year']">yyyy</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:month']">MM</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:day']">dd</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:hours']">hh</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:minutes']">mm</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:seconds']">ss</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:quarter']">第QQ季度</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:day-of-week']">星期N</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:week-of-year']">WW</xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="self::node( )[name(.)='number:text']">
+ <xsl:value-of select="."/>
+ </xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:year']">yy</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:month']">M</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:day']">d</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:hours']">h</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:minutes']">m</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:seconds']">s</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:quarter']">Q季</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:day-of-week']">星期N</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:week-of-year']">WW</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:am-pm']">am/pm</xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="quote">"</xsl:variable>
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="concat('CREATEDATE \@ ',$quote,$datefmt,$quote)"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="oo数字格式域开关">
+ <xsl:param name="oo_format"/>
+ <xsl:choose>
+ <xsl:when test="$oo_format='1'">Arabic</xsl:when>
+ <xsl:when test="$oo_format='I'">ROMAN</xsl:when>
+ <xsl:when test="$oo_format='i'">roman</xsl:when>
+ <xsl:when test="$oo_format='A'">ALPHABETIC</xsl:when>
+ <xsl:when test="$oo_format='a'">alphabetic</xsl:when>
+ <xsl:when test="$oo_format='1, 2, 3, ...'">GB1</xsl:when>
+ <xsl:when test="$oo_format='①, ②, ③, ...'">GB3</xsl:when>
+ <xsl:when test="$oo_format='一, 二, 三, ...'">CHINESENUM3</xsl:when>
+ <xsl:when test="$oo_format='壹, 贰, 叁, ...'">CHINESENUM2</xsl:when>
+ <xsl:when test="$oo_format='甲, 乙, 丙, ...'">ZODIAC1</xsl:when>
+ <xsl:when test="$oo_format='子, 丑, 寅, ...'">ZODIAC2</xsl:when>
+ <xsl:otherwise>Arabic</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="text:page-number">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'page'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <xsl:variable name="fmt">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="@style:num-format"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@style:num-format">
+ <xsl:value-of select="concat('PAGE \* ',$fmt)"/>
+ </xsl:when>
+ <xsl:otherwise>PAGE</xsl:otherwise>
+ </xsl:choose>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:page-count">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'numpages'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <xsl:variable name="fmt">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="@style:num-format"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@style:num-format">
+ <xsl:value-of select="concat('NumPages \* ',$fmt,' \* Upper')"/>
+ </xsl:when>
+ <xsl:otherwise>NumPages</xsl:otherwise>
+ </xsl:choose>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:initial-creator">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'author'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <!--xsl:value-of select="concat('AUTHOR \* ','Caps',' \* MERGEFORMAT')"/-->
+ <xsl:value-of select="'AUTHOR'"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="string(.)"/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:author-name">
+ <xsl:param name="tStyle"/>
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'username'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <xsl:if test="$tStyle!=''">
+ <字:句属性 字:式样引用="{$tStyle}" uof:locID="t0086" uof:attrList="式样引用"/>
+ </xsl:if>
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">AUTHOR</字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:author-initials">
+ <xsl:param name="tStyle"/>
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'userinitials'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <xsl:if test="$tStyle!=''">
+ <字:句属性 字:式样引用="{$tStyle}" uof:locID="t0086" uof:attrList="式样引用"/>
+ </xsl:if>
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">AUTHOR</字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:title">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'title'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <xsl:variable name="titlename" select="/office:document/office:meta/dc:title"/>
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="concat('TITLE',' \* Upper')"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:subject">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'subject'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="concat('SUBJECT \* ','Caps',' \* MERGEFORMAT')"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:file-name">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'filename'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <!--xsl:value-of select="concat('FILENAME \* ','Caps',' \* MERGEFORMAT')"/-->
+ <xsl:value-of select="concat('FILENAME',' \p')"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="text:editing-duration">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'edittime'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <xsl:variable name="timefmt">
+ <xsl:variable name="aa" select="@style:data-style-name"/>
+ <xsl:for-each select="key('geshi',$aa)/number:hours | key('geshi',$aa)/number:minutes | key('geshi',$aa)/number:am-pm | key('geshi',$aa)/number:seconds | key('geshi',$aa)/number:text">
+ <xsl:choose>
+ <xsl:when test="@number:style='long' ">
+ <xsl:if test="self::node( )[name(.)='number:hours']">HH</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:minutes']">MM</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:seconds']">SS</xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="self::node( )[name(.)='number:text']">
+ <xsl:value-of select="."/>
+ </xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:hours']">H</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:minutes']">M</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:seconds']">S</xsl:if>
+ <xsl:if test="self::node( )[name(.)='number:am-pm']">am/pm</xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="quote">"</xsl:variable>
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="concat('EDITTIME \@ ',$quote,$timefmt,$quote,' \* MERGEFORMAT ')"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:key name="path" match="//office:document/office:automatic-styles/style:style" use="@style:name"/>
+ <xsl:template name="text:table-of-content">
+ <xsl:element name="字:段落">
+ <xsl:attribute name="uof:locID">t0051</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="text:index-body/text:p/@text:style-name"/></xsl:attribute>
+ <xsl:element name="字:制表位设置">
+ <xsl:attribute name="uof:locID">t0067</xsl:attribute>
+ <xsl:element name="字:制表位">
+ <xsl:attribute name="uof:locID">t0068</xsl:attribute>
+ <xsl:attribute name="uof:attrList">位置 类型 前导符 制表位字符</xsl:attribute>
+ <xsl:variable name="aa" select="text:index-body/text:p/@text:style-name"/>
+ <xsl:attribute name="字:位置"><xsl:value-of select="substring-before(key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:position,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:type"/></xsl:attribute>
+ <xsl:attribute name="字:制表位字符"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-text"/></xsl:attribute>
+ <xsl:if test="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-style">
+ <xsl:attribute name="字:前导符"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-style"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="字:是否行首标点压缩">
+ <xsl:attribute name="uof:locID">t0075</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:中文习惯首尾字符">
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0076</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'REF'"/></xsl:attribute>
+ <xsl:if test="@text:protected">
+ <xsl:attribute name="字:锁定"><xsl:value-of select="@text:protected"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="'TOC \o 1-10 \h \z'"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ <xsl:for-each select="text:index-body/text:index-title/text:p">
+ <xsl:element name="字:段落" uof:locID="t0051" uof:attrList="标识符">
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:句">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用">
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </字:句属性>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="self::node()"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="text:index-body/text:p">
+ <xsl:element name="字:段落" uof:locID="t0051" uof:attrList="标识符">
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ <xsl:element name="字:制表位设置">
+ <xsl:attribute name="uof:locID">t0067</xsl:attribute>
+ <xsl:element name="字:制表位">
+ <xsl:attribute name="uof:locID">t0068</xsl:attribute>
+ <xsl:attribute name="uof:attrList">位置 类型 前导符</xsl:attribute>
+ <xsl:variable name="aa" select="@text:style-name"/>
+ <xsl:attribute name="字:位置"><xsl:value-of select="substring-before(key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:position,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:type"/></xsl:attribute>
+ <xsl:attribute name="字:制表位字符"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-text"/></xsl:attribute>
+ <xsl:if test="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-style">
+ <xsl:attribute name="字:前导符"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-style"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="字:是否行首标点压缩">
+ <xsl:attribute name="uof:locID">t0075</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:中文习惯首尾字符">
+ <xsl:attribute name="字:值">true</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0076</xsl:attribute>
+ <xsl:attribute name="uof:attrList">值</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ <xsl:if test="self::node()/text:a">
+ <字:句 uof:locID="t0085">
+ <xsl:variable name="num">
+ <xsl:number from="/office:document/office:body/office:text" level="any" count="text:a"/>
+ </xsl:variable>
+ <xsl:element name="字:区域开始">
+ <xsl:attribute name="字:标识符"><xsl:value-of select="concat('hlnk',$num + 1)"/></xsl:attribute>
+ <xsl:attribute name="字:名称">Hyperlink</xsl:attribute>
+ <xsl:attribute name="字:类型">hyperlink</xsl:attribute>
+ <xsl:attribute name="uof:locID">t0121</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符 名称 类型</xsl:attribute>
+ </xsl:element>
+ <xsl:for-each select="text:a/node()">
+ <xsl:choose>
+ <xsl:when test="name(.)='text:tab-stop' or name(.)='text:tab'">
+ <xsl:element name="字:制表符" uof:locID="t0123"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ <xsl:element name="字:区域结束">
+ <xsl:attribute name="字:标识符引用"><xsl:value-of select="concat('hlnk',$num + 1)"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0122</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符引用</xsl:attribute>
+ </xsl:element>
+ <xsl:variable name="stt">
+ <xsl:value-of select="./text:a"/>
+ </xsl:variable>
+ <xsl:variable name="end">
+ <xsl:value-of select="."/>
+ </xsl:variable>
+ <xsl:variable name="bijiao">
+ <xsl:value-of select="substring-after($end,$stt)"/>
+ </xsl:variable>
+ <xsl:if test="not($bijiao='')">
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="$bijiao"/>
+ </xsl:element>
+ </xsl:if>
+ </字:句>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="text:alphabetical-index">
+ <xsl:element name="字:段落">
+ <xsl:attribute name="uof:locID">t0051</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="text:index-body/text:p/@text:style-name"/></xsl:attribute>
+ <xsl:element name="字:制表位设置">
+ <xsl:attribute name="uof:locID">t0067</xsl:attribute>
+ <xsl:element name="字:制表位">
+ <xsl:attribute name="uof:locID">t0068</xsl:attribute>
+ <xsl:attribute name="uof:attrList">位置 类型 前导符 制表位字符</xsl:attribute>
+ <xsl:variable name="aa" select="text:index-body/text:p/@text:style-name"/>
+ <xsl:attribute name="字:位置"><xsl:value-of select="substring-before(key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:position,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:type"/></xsl:attribute>
+ <xsl:attribute name="字:制表位字符"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-text"/></xsl:attribute>
+ <xsl:if test="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-style">
+ <xsl:attribute name="字:前导符"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-style"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'INDEX'"/></xsl:attribute>
+ <xsl:if test="@text:protected">
+ <xsl:attribute name="字:锁定"><xsl:value-of select="@text:protected"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:文本串>
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="'TOC \o 1-10 \h \z'"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ <xsl:for-each select="text:index-body/text:index-title/text:p">
+ <xsl:element name="字:段落" uof:locID="t0051" uof:attrList="标识符">
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="字:句">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用">
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ </字:句属性>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="self::node()"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="text:index-body/text:p">
+ <xsl:element name="字:段落" uof:locID="t0051" uof:attrList="标识符">
+ <xsl:element name="字:段落属性">
+ <xsl:attribute name="uof:locID">t0052</xsl:attribute>
+ <xsl:attribute name="uof:attrList">式样引用</xsl:attribute>
+ <xsl:attribute name="字:式样引用"><xsl:value-of select="@text:style-name"/></xsl:attribute>
+ <xsl:element name="字:制表位设置">
+ <xsl:attribute name="uof:locID">t0067</xsl:attribute>
+ <xsl:element name="字:制表位">
+ <xsl:attribute name="uof:locID">t0068</xsl:attribute>
+ <xsl:attribute name="uof:attrList">位置 类型 前导符 制表位字符</xsl:attribute>
+ <xsl:variable name="aa" select="@text:style-name"/>
+ <xsl:attribute name="字:位置"><xsl:value-of select="substring-before(key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:position,$ooUnit)"/></xsl:attribute>
+ <xsl:attribute name="字:类型"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:type"/></xsl:attribute>
+ <xsl:attribute name="字:制表位字符"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-text"/></xsl:attribute>
+ <xsl:if test="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-style">
+ <xsl:attribute name="字:前导符"><xsl:value-of select="key('path',$aa)/style:paragraph-properties/style:tab-stops/style:tab-stop/@style:leader-style"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ <xsl:for-each select="node()">
+ <字:句 uof:locID="t0085">
+ <xsl:choose>
+ <xsl:when test="name(.)='text:tab-stop' or name(.)='text:tab'">
+ <xsl:element name="字:制表符" uof:locID="t0123"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="字:文本串">
+ <xsl:attribute name="uof:locID">t0109</xsl:attribute>
+ <xsl:attribute name="uof:attrList">标识符</xsl:attribute>
+ <xsl:value-of select="."/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </字:句>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="oo数字格式">
+ <xsl:param name="oo_format"/>
+ <xsl:choose>
+ <xsl:when test="$oo_format='1'">decimal</xsl:when>
+ <xsl:when test="$oo_format='I'">upper-roman</xsl:when>
+ <xsl:when test="$oo_format='i'">lower-roman</xsl:when>
+ <xsl:when test="$oo_format='A'">upper-letter</xsl:when>
+ <xsl:when test="$oo_format='a'">lower-letter</xsl:when>
+ <xsl:when test="$oo_format='1, 2, 3, ...'">decimal-full-width</xsl:when>
+ <xsl:when test="$oo_format='①, ②, ③, ...'">decimal-enclosed-circle</xsl:when>
+ <xsl:when test="$oo_format='一, 二, 三, ...'">chinese-counting</xsl:when>
+ <xsl:when test="$oo_format='壹, 贰, 叁, ...'">chinese-legal-simplified</xsl:when>
+ <xsl:when test="$oo_format='甲, 乙, 丙, ...'">ideograph-traditional</xsl:when>
+ <xsl:when test="$oo_format='子, 丑, 寅, ...'">ideograph-zodiac</xsl:when>
+ <xsl:otherwise>decimal</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="图:填充">
+ <xsl:param name="style-name"/>
+ <xsl:choose>
+ <xsl:when test="style:background-image/office:binary-data">
+ <图:图片 uof:locID="g0035" uof:attrList="位置 图形引用 类型 名称">
+ <xsl:attribute name="图:位置"><xsl:choose><xsl:when test="not(style:background-image/@style:repeat)">tile</xsl:when><xsl:otherwise><xsl:choose><xsl:when test="style:background-image/@style:repeat = 'stretch'">stretch</xsl:when><xsl:when test="style:background-image/@style:repeat = 'repeat'">tile</xsl:when><xsl:when test="style:background-image/@style:repeat = 'no-repeat'">center</xsl:when></xsl:choose></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="图:图形引用"><xsl:value-of select="concat('background-image_',count(preceding::style:background-image))"/></xsl:attribute>
+ <xsl:attribute name="图:类型">png</xsl:attribute>
+ <xsl:attribute name="图:名称">background-image</xsl:attribute>
+ </图:图片>
+ </xsl:when>
+ <xsl:when test="@fo:background-color">
+ <图:颜色 uof:locID="g0034">
+ <xsl:choose>
+ <xsl:when test="@fo:background-color='transparent' ">auto</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@fo:background-color"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </图:颜色>
+ </xsl:when>
+ <xsl:when test="@draw:fill='gradient'">
+ </xsl:when>
+ <xsl:when test="@draw:fill='hatch'">
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="字:缩进类型">
+ <xsl:if test="@text:space-before or @fo:margin-left">
+ <字:左 uof:locID="t0182">
+ <字:绝对 uof:locID="t0185" uof:attrList="值">
+ <xsl:if test="@text:space-before">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(@text:space-before,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@fo:margin-left">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(@fo:margin-left,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </字:绝对>
+ </字:左>
+ </xsl:if>
+ <xsl:if test="@text:min-label-width or @fo:margin-right">
+ <字:右 uof:locID="t0183">
+ <字:绝对 uof:locID="t0187" uof:attrList="值">
+ <xsl:if test="@text:min-label-width">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(@text:min-label-width,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@fo:margin-right">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(@fo:margin-right,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </字:绝对>
+ </字:右>
+ </xsl:if>
+ <xsl:if test="@text:min-label-distance or @fo:text-indent">
+ <字:首行 uof:locID="t0184">
+ <字:绝对 uof:locID="t0189" uof:attrList="值">
+ <xsl:if test="@text:min-label-distance">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(@text:min-label-distance,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@fo:text-indent">
+ <xsl:attribute name="字:值"><xsl:value-of select="substring-before(@fo:text-indent,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </字:绝对>
+ </字:首行>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="graphsize">
+ <xsl:param name="width"/>
+ <xsl:param name="Unitofsize"/>
+ <xsl:if test="$Unitofsize='pt'">
+ <xsl:choose>
+ <xsl:when test="(not($width&gt;1.42) and 0&lt;$width)">1</xsl:when>
+ <xsl:when test="(not($width&gt;2.84) and 1.42&lt;$width)">2</xsl:when>
+ <xsl:when test="(not($width&gt;4.26) and 2.84&lt;$width)">3</xsl:when>
+ <xsl:when test="(not($width&gt;5.68) and 4.26&lt;$width)">4</xsl:when>
+ <xsl:when test="(not($width&gt;7.10) and 5.68&lt;$width)">5</xsl:when>
+ <xsl:when test="(not($width&gt;8.52) and 7.10&lt;$width)">6</xsl:when>
+ <xsl:when test="(not($width&gt;9.94) and 8.52&lt;$width)">7</xsl:when>
+ <xsl:when test="(not($width&gt;11.36) and 9.94&lt;$width)">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$uofUnit='in'">
+ <xsl:choose>
+ <xsl:when test="(not($width&gt;0.02) and 0&lt;$width)">1</xsl:when>
+ <xsl:when test="(not($width&gt;0.04) and 0.02&lt;$width)">2</xsl:when>
+ <xsl:when test="(not($width&gt;0.06) and 0.04&lt;$width)">3</xsl:when>
+ <xsl:when test="(not($width&gt;0.08) and 0.06&lt;$width)">4</xsl:when>
+ <xsl:when test="(not($width&gt;0.10) and 0.08&lt;$width)">5</xsl:when>
+ <xsl:when test="(not($width&gt;0.12) and 0.10&lt;$width)">6</xsl:when>
+ <xsl:when test="(not($width&gt;0.14) and 0.12&lt;$width)">7</xsl:when>
+ <xsl:when test="(not($width&gt;0.16) and 0.14&lt;$width)">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$uofUnit='mm'">
+ <xsl:choose>
+ <xsl:when test="(not($width&gt;0.5) and 0&lt;$width) or $width=0.5">1</xsl:when>
+ <xsl:when test="(not($width&gt;1.0) and 0.5&lt;$width) or $width=1.0">2</xsl:when>
+ <xsl:when test="(not($width&gt;1.5) and 0.10&lt;$width) or $width=1.5">3</xsl:when>
+ <xsl:when test="(not($width&gt;2.0) and 1.5&lt;$width) or $width=2.0">4</xsl:when>
+ <xsl:when test="(not($width&gt;2.5) and 2.0&lt;$width) or $width=2.5">5</xsl:when>
+ <xsl:when test="(not($width&gt;3.0) and 2.5&lt;$width) or $width=3.0">6</xsl:when>
+ <xsl:when test="(not($width&gt;3.5) and 3.0&lt;$width) or $width=3.5">7</xsl:when>
+ <xsl:when test="(not($width&gt;4.0) and 3.5&lt;$width) or $width=4.0">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$uofUnit='cm'">
+ <xsl:choose>
+ <xsl:when test="(not($width&gt;0.05) and 0&lt;$width) or $width=0.05">1</xsl:when>
+ <xsl:when test="(not($width&gt;0.10) and 0.05&lt;$width) or $width=0.10">2</xsl:when>
+ <xsl:when test="(not($width&gt;0.15) and 0.10&lt;$width) or $width=0.15">3</xsl:when>
+ <xsl:when test="(not($width&gt;0.20) and 0.15&lt;$width) or $width=0.20">4</xsl:when>
+ <xsl:when test="(not($width&gt;0.25) and 0.20&lt;$width) or $width=0.25">5</xsl:when>
+ <xsl:when test="(not($width&gt;0.30) and 0.25&lt;$width) or $width=0.30">6</xsl:when>
+ <xsl:when test="(not($width&gt;0.35) and 0.30&lt;$width) or $width=0.35">7</xsl:when>
+ <xsl:when test="(not($width&gt;0.40) and 0.35&lt;$width) or $width=0.40">8</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="text:character-count">
+ <xsl:element name="字:域开始">
+ <xsl:attribute name="字:类型"><xsl:value-of select="'numchars'"/></xsl:attribute>
+ <xsl:attribute name="uof:locID">t0079</xsl:attribute>
+ <xsl:attribute name="uof:attrList">类型 锁定</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="text:fixed='1'or text:fixed='true'">
+ <xsl:attribute name="字:锁定">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="字:锁定">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="字:域代码">
+ <xsl:attribute name="uof:locID">t0080</xsl:attribute>
+ <字:段落 uof:locID="t0051" uof:attrList="标识符">
+ <字:句 uof:locID="t0085">
+ <字:句属性 uof:locID="t0086" uof:attrList="式样引用"/>
+ <xsl:variable name="quote" select="'&quot;'"/>
+ <xsl:variable name="fmt">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="@style:num-format"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="concat('NUMCHARS \* ',$fmt,' \# ',$quote,0,$quote)"/>
+ </字:文本串>
+ </字:句>
+ </字:段落>
+ </xsl:element>
+ <字:句 uof:locID="t0085">
+ <字:文本串 uof:locID="t0109" uof:attrList="标识符">
+ <xsl:value-of select="."/>
+ </字:文本串>
+ </字:句>
+ <xsl:element name="字:域结束">
+ <xsl:attribute name="uof:locID">t0081</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <!-- measure_conversion.xsl Begin-->
+ <!--xsl:param name="dpi" select="111"/>
+ <xsl:param name="centimeter-in-mm" select="10"/>
+ <xsl:param name="inch-in-mm" select="25.4"/>
+ <xsl:param name="didot-point-in-mm" select="0.376065"/>
+ <xsl:param name="pica-in-mm" select="4.2333333"/>
+ <xsl:param name="point-in-mm" select="0.3527778"/>
+ <xsl:param name="twip-in-mm" select="0.017636684"/>
+ <xsl:param name="pixel-in-mm" select="$inch-in-mm div $dpi"/-->
+ <!-- ***** MEASUREMENT CONVERSIONS *****
+ PARAM 'value'
+ The measure to be converted.
+ The current measure is judged by a substring (e.g. 'mm', 'cm', 'in', 'pica'...)
+ directly added to the number.
+
+ PARAM 'rounding-factor'
+ Is used for the rounding of decimal places.
+ The parameter number is the product of 1 and some '10', where
+ every zero represents a decimal place.
+
+ For example, providing as parameter:
+ <xsl:param name="rounding-factor" select="10000" />
+ Gives by default four decimal places.
+
+ To round two decimal places, basically the following is done:
+ <xsl:value-of select="round(100 * value) div 100"/>
+
+ RETURN The converted number, by default rounded to four decimal places.
+ In case the input measure could not be matched the same value is
+ returned and a warning message is written out.
+
+
+
+ MEASURE LIST:
+ * 1 millimeter (mm), the basic measure
+
+ * 1 centimeter (cm) = 10 mm
+
+ * 1 inch (in) = 25.4 mm
+ While the English have already seen the light (read: the metric system), the US
+ remains loyal to this medieval system.
+
+ * 1 point (pt) = 0.35277777.. mm
+ Sometimes called PostScript point (ppt), as when Adobe created PostScript, they added their own system of points.
+ There are exactly 72 PostScript points in 1 inch.
+
+ * 1 twip = twentieth of a (PostScript) point
+ A twip (twentieth of a point) is a 1/20th of a PostScript point, a traditional measure in printing.
+
+ * 1 didot point (dpt) = 0.376065 mm
+ Didot point after the French typographer Firmin Didot (1764-1836).
+
+ More details under
+ http://www.unc.edu/~rowlett/units/dictP.html:
+ "A unit of length used by typographers and printers. When printing was done
+ from hand-set metal type, one point represented the smallest element of type
+ that could be handled, roughly 1/64 inch. Eventually, the point was standardized
+ in Britain and America as exactly 1/72.27 = 0.013 837 inch, which is
+ about 0.35 mm (351.46 micrometers). In continental Europe, typographers
+ traditionally used a slightly larger point of 0.014 83 inch (about
+ 1/72 pouce, 0.377 mm, or roughly 1/67 English inch), called a Didot point
+ after the French typographer Firmin Didot (1764-1836). In the U.S.,
+ Adobe software defines the point to be exactly 1/72 inch (0.013 888 9 inch
+ or 0.352 777 8 millimeters) and TeX software uses a slightly smaller point
+ of 0.351 459 8035 mm. The German standards agency DIN has proposed that
+ all these units be replaced by multiples of 0.25 millimeters (1/101.6 inch).
+
+ * 1 pica = 4.233333 mm
+ 1/6 inch or 12 points
+
+ * 1 pixel (px) = 0.26458333.. mm (relative to 'DPI', here: 96 dpi)
+ Most pictures have the 96 dpi resolution, but the dpi variable may vary by stylesheet parameter
+
+
+ -->
+ <!-- changing measure to mm -->
+ <!--xsl:template name="convert2cm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, $uofUnit)">
+ <xsl:value-of select="substring-before($value, $uofUnit)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $centimeter-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $centimeter-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $centimeter-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $centimeter-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $centimeter-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $centimeter-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'cm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template-->
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml.xsl b/filter/source/xslt/export/wordml/ooo2wordml.xsl
new file mode 100644
index 000000000..6cebb3ca5
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml.xsl
@@ -0,0 +1,209 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:output method="xml" indent="no" encoding="UTF-8" version="1.0" standalone="yes"/>
+ <xsl:include href="../../common/measure_conversion.xsl"/>
+ <xsl:include href="../common/ooo2ms_docpr.xsl"/>
+ <xsl:include href="ooo2wordml_settings.xsl"/>
+ <xsl:include href="ooo2wordml_border.xsl"/>
+ <xsl:include href="ooo2wordml_page.xsl"/>
+ <xsl:include href="ooo2wordml_text.xsl"/>
+ <xsl:include href="ooo2wordml_list.xsl"/>
+ <xsl:include href="ooo2wordml_field.xsl"/>
+ <xsl:include href="ooo2wordml_table.xsl"/>
+ <xsl:include href="ooo2wordml_draw.xsl"/>
+ <xsl:include href="ooo2wordml_path.xsl"/>
+ <xsl:key name="paragraph-style" match="style:style[@style:family='paragraph']" use="@style:name"/>
+ <xsl:key name="text-style" match="style:style[@style:family='text']" use="@style:name"/>
+ <xsl:key name="section-style" match="style:style[@style:family='section']" use="@style:name"/>
+ <xsl:key name="master-page" match="style:master-page" use="@style:name"/>
+ <xsl:key name="page-layout" match="style:page-layout" use="@style:name"/>
+ <xsl:key name="slave-style" match="style:style[string-length(normalize-space(@style:master-page-name)) &gt; 0]" use="@style:name"/>
+ <xsl:key name="list-style" match="office:styles/text:list-style | office:automatic-styles/text:list-style" use="@style:name"/>
+ <xsl:key name="graphics-style" match="style:style[@style:family='graphic']" use="@style:name"/>
+ <xsl:template match="/">
+ <xsl:apply-templates select="office:document"/>
+ </xsl:template>
+ <xsl:template match="office:document">
+ <xsl:processing-instruction name="mso-application">progid="Word.Document"</xsl:processing-instruction>
+ <xsl:variable name="embeddedObjPresent">
+ <xsl:choose>
+ <xsl:when test="//draw:object-ole[1]">yes</xsl:when>
+ <xsl:otherwise>no</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <w:wordDocument xml:space="preserve" w:embeddedObjPresent="{$embeddedObjPresent}">
+ <xsl:apply-templates select="office:meta"/>
+ <xsl:apply-templates select="office:font-face-decls"/>
+ <xsl:if test="office:styles/text:outline-style | office:styles/text:list-style | office:automatic-styles/text:list-style">
+ <xsl:call-template name="ListStyles"/>
+ </xsl:if>
+ <w:styles>
+ <xsl:apply-templates select="office:styles"/>
+ <xsl:apply-templates select="office:automatic-styles"/>
+ <xsl:call-template name="add_hyperlink_style"/>
+ <!--add for hyperlink character style G.Y.-->
+ <xsl:call-template name="add_comments_style"/>
+ <!--add for comments style G.Y.-->
+ </w:styles>
+ <xsl:call-template name="export-oledata"/>
+ <xsl:apply-templates select="office:settings"/>
+ <xsl:apply-templates select="office:body"/>
+ </w:wordDocument>
+ </xsl:template>
+ <xsl:template match="office:body">
+ <xsl:call-template name="page-background"/>
+ <xsl:apply-templates select="office:text"/>
+ </xsl:template>
+ <xsl:template match="office:font-face-decls">
+ <!-- get default font from default paragraph properties -->
+ <w:fonts>
+ <xsl:variable name="default-paragraph-properties" select="/office:document/office:styles/style:default-style[@style:family = 'paragraph']/style:paragraph-properties"/>
+ <w:defaultFonts w:ascii="{$default-paragraph-properties/@style:font-name}" w:h-ansi="{$default-paragraph-properties/@style:font-name}" w:fareast="{$default-paragraph-properties/@style:font-name-asian}" w:cs="{$default-paragraph-properties/@style:font-name-complex}"/>
+ <xsl:for-each select="style:font-face">
+ <w:font w:name="{@style:name}">
+ <xsl:if test="@style:font-charset = 'x-symbol'">
+ <w:charset w:val="02"/>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@style:font-family-generic = 'swiss'">
+ <w:family w:val="Swiss"/>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic = 'modern'">
+ <w:family w:val="Modern"/>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic = 'roman'">
+ <w:family w:val="Roman"/>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic = 'script'">
+ <w:family w:val="Script"/>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic = 'decorative'">
+ <w:family w:val="Decorative"/>
+ </xsl:when>
+ <xsl:when test="@style:font-family-generic = 'system'">
+ <w:family w:val="System"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:family w:val="System"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <w:pitch w:val="{@style:font-pitch}"/>
+ </w:font>
+ </xsl:for-each>
+ </w:fonts>
+ </xsl:template>
+ <xsl:template match="office:styles | office:automatic-styles">
+ <xsl:for-each select="*[(name()='style:style' or name()='style:default-style') and (@style:family= 'paragraph' or @style:family= 'text' or @style:family='table')]">
+ <xsl:variable name="style-name">
+ <xsl:choose>
+ <xsl:when test="name() = 'style:default-style'">
+ <xsl:value-of select="concat('default-', @style:family, '-style')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@style:name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <w:style w:styleId="{$style-name}">
+ <xsl:choose>
+ <xsl:when test="@style:family = 'paragraph'">
+ <xsl:attribute name="w:type">paragraph</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:family = 'text'">
+ <xsl:attribute name="w:type">character</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:family = 'table'">
+ <xsl:attribute name="w:type">table</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="name() = 'style:default-style'">
+ <xsl:attribute name="w:default">on</xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@style:parent-style-name">
+ <w:basedOn w:val="{@style:parent-style-name}"/>
+ </xsl:when>
+ <xsl:when test="name() = 'style:style' and @style:family= 'paragraph'">
+ <w:basedOn w:val="{concat('default-', @style:family, '-style')}"/>
+ </xsl:when>
+ </xsl:choose>
+ <w:name w:val="{$style-name}"/>
+ <xsl:if test="parent::office:automatic-styles">
+ <w:hidden w:val="on"/>
+ </xsl:if>
+ <xsl:if test="@style:next-style-name">
+ <w:next w:val="{@style:next-style-name}"/>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@style:family = 'paragraph'">
+ <xsl:apply-templates select="style:paragraph-properties" mode="paragraph"/>
+ </xsl:when>
+ <xsl:when test="@style:family = 'table'">
+ <w:tblPr>
+ <xsl:apply-templates select="style:table-properties" mode="table"/>
+ </w:tblPr>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:apply-templates select="style:text-properties" mode="character"/>
+ </w:style>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="office:text">
+ <w:body>
+ <xsl:apply-templates select="text:p | text:h | text:section | text:unordered-list | text:ordered-list | text:list |table:table"/>
+ <xsl:variable name="paragraph-heading-table" select=".//*[name() = 'text:p' or name() = 'text:h' or name() = 'table:table']"/>
+ <xsl:variable name="page" select="$paragraph-heading-table[key( 'slave-style', @*[name()='text:style-name' or name()='table:style-name'])]"/>
+ <w:sectPr>
+ <!--w:type w:val="continuous"/ -->
+ <xsl:apply-templates select="/office:document/office:styles/text:footnotes-configuration">
+ <xsl:with-param name="within-section" select="'yes'"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="/office:document/office:styles/text:endnotes-configuration">
+ <xsl:with-param name="within-section" select="'yes'"/>
+ </xsl:apply-templates>
+ <xsl:choose>
+ <xsl:when test="count($page) &gt; 0">
+ <xsl:apply-templates select="key('master-page', key( 'slave-style', $page[last()]/@*[name()='text:style-name' or name()='table:style-name'])/@style:master-page-name)"/>
+ <xsl:if test="key( 'slave-style', $page[last()]/@*[name()='text:style-name' or name()='table:style-name'])/style:paragraph-properties/@style:page-number">
+ <!-- in M$ word the header and footer associate with the w:sectPr, but in StarOffice writer the header and footer associate with the style:master-page -->
+ <xsl:variable name="pagenumber_start">
+ <xsl:value-of select=" key( 'slave-style', $page[last()]/@*[name()='text:style-name' or name()='table:style-name'])/style:paragraph-properties/@style:page-number"/>
+ </xsl:variable>
+ <xsl:if test=" number($pagenumber_start) &gt; 0 ">
+ <w:pgNumType w:start="{$pagenumber_start}"/>
+ </xsl:if>
+ <!-- comment out the below line to enable the header and footer display normally when style:page-number =0 -->
+ <!-- w:pgNumType w:start="{key( 'slave-style', $page[last()]/@*[name()='text:style-name' or name()='table:style-name'])/style:paragraph-properties/@style:page-number}"/-->
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="/office:document/office:master-styles/style:master-page[1]"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$paragraph-heading-table[last()]/ancestor::text:section">
+ <xsl:apply-templates select="key('section-style',$paragraph-heading-table[last()]/ancestor::text:section[1]/@text:style-name)" mode="section"/>
+ </xsl:if>
+ </w:sectPr>
+ </w:body>
+ </xsl:template>
+ <xsl:template match="text:section">
+ <xsl:apply-templates select="text:p | text:h | text:section | text:unordered-list | text:ordered-list | text:list | table:table"/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_border.xsl b/filter/source/xslt/export/wordml/ooo2wordml_border.xsl
new file mode 100644
index 000000000..9ca50dc64
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_border.xsl
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <!-- multiple usage: get size, type, color of table-cell, paragraph, and page borders. -->
+ <xsl:template name="get-border-size">
+ <xsl:param name="border"/>
+ <xsl:param name="border-line-width"/>
+ <xsl:choose>
+ <xsl:when test="$border = 'none' or $border = 'hidden'">
+ <xsl:text>none;0</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="border-value">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$border"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="border-style">
+ <xsl:choose>
+ <xsl:when test="contains($border,'solid')">solid</xsl:when>
+ <xsl:when test="contains($border,'double')">double</xsl:when>
+ <xsl:otherwise>none</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- MS word and SO writer borders Mapping
+ MS word Borders SO borders
+ w:val="single" w:sz="0" 0.05pt(0.002cm);solid
+ w:val="single" w:sz="12" 1.00pt(0.035cm);solid
+ w:val="single" w:sz="18" 2.50pt(0.088cm);solid
+ w:val="single" w:sz="36" 4.00pt(0.141cm);solid
+ w:val="single" w:sz="48" 5.00pt(0.176cm);solid
+ w:val="double" w:sz="2" 1.10pt(0.039cm);double
+ w:val="double" w:sz="6" 2.60pt(0.092cm);double
+ w:val="thin-thick-small-gap" w:sz="12" 3.00pt(0.105cm);double
+ w:val="thin-thick-large-gap" w:sz="18" 3.55pt(0.125cm);double
+ w:val="thick-thin-medium-gap" w:sz="24" 4.50pt(0.158cm);double
+ w:val="thin-thick-medium-gap" w:sz="24" 5.05pt(0.178cm);double
+ w:val="thin-thick-small-gap" w:sz="24" 6.00pt(0.211cm);double
+ w:val="thin-thick-medium-gap" w:sz="36" 6.55pt(0.231cm);double
+ w:val="double" w:sz="18" 7.50pt(0.264cm);double
+ w:val="thin-thick-medium-gap" w:sz="48" 9.00pt(0.317cm);double;style:border-line-width="0.088cm 0.088cm 0.141cm"
+ w:val="double" w:sz="24" 9.00pt(0.317cm);double;style:border-line-width="0.141cm 0.088cm 0.088cm"
+ we adjust the criteria by adding about 1/2 range of this current criteria and next criteria. Gary. Yang -->
+ <xsl:variable name="microsoft-border-style-size">
+ <xsl:choose>
+ <xsl:when test=" $border-style = 'solid'">
+ <xsl:choose>
+ <xsl:when test="$border-value &lt;= 0.018">single;0</xsl:when>
+ <xsl:when test="$border-value &lt;= 0.055">single;12</xsl:when>
+ <xsl:when test="$border-value &lt;= 0.110">single;18</xsl:when>
+ <xsl:when test="$border-value &lt;= 0.155">single;36</xsl:when>
+ <xsl:when test="$border-value &lt;= 0.198">single;48</xsl:when>
+ <xsl:otherwise>single;48</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'double'">
+ <xsl:choose>
+ <xsl:when test="$border-value &lt; 0.064">double;2</xsl:when>
+ <xsl:when test="$border-value &lt; 0.098">double;6</xsl:when>
+ <xsl:when test="$border-value &lt; 0.115">thin-thick-small-gap;12</xsl:when>
+ <xsl:when test="$border-value &lt; 0.135">thin-thick-large-gap;18</xsl:when>
+ <xsl:when test="$border-value &lt; 0.168">thick-thin-medium-gap;24</xsl:when>
+ <xsl:when test="$border-value &lt; 0.190">thin-thick-medium-gap;24</xsl:when>
+ <xsl:when test="$border-value &lt; 0.221">thin-thick-small-gap;24</xsl:when>
+ <xsl:when test="$border-value &lt; 0.241">thin-thick-medium-gap;36</xsl:when>
+ <xsl:when test="$border-value &lt; 0.300">double;18</xsl:when>
+ <xsl:when test="$border-value &lt; 0.430">
+ <xsl:variable name="border-inner-line-value">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$border-line-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$border-inner-line-value &lt; 0.10">thin-thick-medium-gap;48</xsl:if>
+ <xsl:if test="$border-inner-line-value &gt; 0.10">double;24</xsl:if>
+ </xsl:when>
+ <xsl:otherwise>double;24</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>none;0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$microsoft-border-style-size"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- get bottom and right border style, size, color -->
+ <xsl:template name="get-border">
+ <xsl:param name="so-border"/>
+ <xsl:param name="so-border-line-width"/>
+ <xsl:param name="so-border-position"/>
+ <xsl:variable name="ms-style-width">
+ <xsl:call-template name="get-border-size">
+ <xsl:with-param name="border" select="$so-border"/>
+ <xsl:with-param name="border-line-width" select="$so-border-line-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$so-border-position = 'bottom' or $so-border-position = 'right'">
+ <!-- if border style is bottom or right border we need to change the thin-thick to thick-thin; Vice Versa -->
+ <xsl:choose>
+ <xsl:when test="substring-before($ms-style-width, '-')='thin'">
+ <xsl:attribute name="w:val"><xsl:value-of select="concat( 'thick-thin', substring-after(substring-before($ms-style-width, ';'), 'k' ))"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="substring-before($ms-style-width, '-')='thick'">
+ <xsl:attribute name="w:val"><xsl:value-of select="concat( 'thin-thick', substring-after(substring-before($ms-style-width, ';'), 'n' ))"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:val"><xsl:value-of select="substring-before($ms-style-width, ';')"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="w:sz"><xsl:value-of select="substring-after($ms-style-width,';')"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$so-border-position = 'top' or $so-border-position = 'left'">
+ <xsl:attribute name="w:val"><xsl:value-of select="substring-before($ms-style-width,';')"/></xsl:attribute>
+ <xsl:attribute name="w:sz"><xsl:value-of select="substring-after($ms-style-width,';')"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <!--get border color -->
+ <xsl:choose>
+ <xsl:when test="contains($so-border,'#')">
+ <xsl:attribute name="w:color"><xsl:value-of select="substring-after($so-border, '#')"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:color">auto</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_custom_draw.xsl b/filter/source/xslt/export/wordml/ooo2wordml_custom_draw.xsl
new file mode 100644
index 000000000..923b19a9e
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_custom_draw.xsl
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:template name="ooo_custom_draw2ms_word_draw_map">
+ <xsl:param name="ooo_predefined_type"/>
+ <!-- all ooo draw names are get from EnhancedCustomShapeGeometry.idl-->
+ <xsl:choose>
+ <xsl:when test="$ooo_predefined_type = 'isosceles-triangle' ">
+ <xsl:value-of select=" '#_x0000_t5' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'right-triangle' ">
+ <xsl:value-of select=" '#_x0000_t6' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'trapezoid' ">
+ <xsl:value-of select=" '#_x0000_t8' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'diamond' ">
+ <xsl:value-of select=" '#_x0000_t4' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'hexagon' ">
+ <xsl:value-of select=" '#_x0000_t9' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'parallelogram' ">
+ <xsl:value-of select=" '#_x0000_t7' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'pentagon' ">
+ <xsl:value-of select=" '#_x0000_t56' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'octagon' ">
+ <xsl:value-of select=" '#_x0000_t10' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'cross' ">
+ <xsl:value-of select=" '#_x0000_t11' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'ring' ">
+ <xsl:value-of select=" '#_x0000_t23' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'block-arc' ">
+ <xsl:value-of select=" '#_x0000_t95' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'can' ">
+ <xsl:value-of select=" '#_x0000_t22' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'cube' ">
+ <xsl:value-of select=" '#_x0000_t16' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'paper' ">
+ <xsl:value-of select=" '#_x0000_t65' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'smiley' ">
+ <xsl:value-of select=" '#_x0000_t96' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'sun' ">
+ <xsl:value-of select=" '#_x0000_t183' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'moon' ">
+ <xsl:value-of select=" '#_x0000_t184' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'heart' ">
+ <xsl:value-of select=" '#_x0000_t74' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'forbidden' ">
+ <xsl:value-of select=" '#_x0000_t57' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'left-bracket' ">
+ <xsl:value-of select=" '#_x0000_t85' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'right-bracket' ">
+ <xsl:value-of select=" '#_x0000_t86' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'left-brace' ">
+ <xsl:value-of select=" '#_x0000_t87' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'right-brace' ">
+ <xsl:value-of select=" '#_x0000_t88' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'bracket-pair' ">
+ <xsl:value-of select=" '#_x0000_t185' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'brace-pair' ">
+ <xsl:value-of select=" '#_x0000_t186' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'quad-bevel' ">
+ <xsl:value-of select=" '#_x0000_t189' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'left-arrow' ">
+ <xsl:value-of select=" '#_x0000_t66' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'down-arrow' ">
+ <xsl:value-of select=" '#_x0000_t67' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'up-arrow' ">
+ <xsl:value-of select=" '#_x0000_t68' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'right-arrow' ">
+ <xsl:value-of select=" '#_x0000_t13' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'left-right-arrow' ">
+ <xsl:value-of select=" '#_x0000_t69' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'up-down-arrow' ">
+ <xsl:value-of select=" '#_x0000_t70' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'mso-spt89' ">
+ <xsl:value-of select=" '#_x0000_t89' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'quad-arrow' ">
+ <xsl:value-of select=" '#_x0000_t76' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'notched-right-arrow' ">
+ <xsl:value-of select=" '#_x0000_t94' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'pentagon-right' ">
+ <xsl:value-of select=" '#_x0000_t177' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'chevron' ">
+ <xsl:value-of select=" '#_x0000_t55' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'up-arrow-callout' ">
+ <xsl:value-of select=" '#_x0000_t79' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'down-arrow-callout' ">
+ <xsl:value-of select=" '#_x0000_t80' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'up-down-arrow-callout' ">
+ <xsl:value-of select=" '#_x0000_t82' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'circular-arrow' ">
+ <xsl:value-of select=" '#_x0000_t103' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-process' ">
+ <xsl:value-of select=" '#_x0000_t109' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-alternate-process' ">
+ <xsl:value-of select=" '#_x0000_t116' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-decision' ">
+ <xsl:value-of select=" '#_x0000_t110' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-data' ">
+ <xsl:value-of select=" '#_x0000_t111' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-predefined-process' ">
+ <xsl:value-of select=" '#_x0000_t112' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-internal-storage' ">
+ <xsl:value-of select=" '#_x0000_t113' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-document' ">
+ <xsl:value-of select=" '#_x0000_t114' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-multidocument' ">
+ <xsl:value-of select=" '#_x0000_t115' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-terminator' ">
+ <xsl:value-of select=" '#_x0000_t116' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-preparation' ">
+ <xsl:value-of select=" '#_x0000_t117' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-manual-input' ">
+ <xsl:value-of select=" '#_x0000_t118' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-manual-operation' ">
+ <xsl:value-of select=" '#_x0000_t119' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-connector' ">
+ <xsl:value-of select=" '#_x0000_t120' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-off-page-connector' ">
+ <xsl:value-of select=" '#_x0000_t177' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-card' ">
+ <xsl:value-of select=" '#_x0000_t121' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-punched-tape' ">
+ <xsl:value-of select=" '#_x0000_t122' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-summing-junction' ">
+ <xsl:value-of select=" '#_x0000_t123' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-or' ">
+ <xsl:value-of select=" '#_x0000_t124' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-collate' ">
+ <xsl:value-of select=" '#_x0000_t125' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-sort' ">
+ <xsl:value-of select=" '#_x0000_t126' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-extract' ">
+ <xsl:value-of select=" '#_x0000_t127' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-merge' ">
+ <xsl:value-of select=" '#_x0000_t128' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-stored-data' ">
+ <xsl:value-of select=" '#_x0000_t130' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-delay' ">
+ <xsl:value-of select=" '#_x0000_t135' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-sequential-access' ">
+ <xsl:value-of select=" '#_x0000_t131' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-magnetic-disk' ">
+ <xsl:value-of select=" '#_x0000_t132' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-direct-access-storage' ">
+ <xsl:value-of select=" '#_x0000_t133' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'flowchart-display' ">
+ <xsl:value-of select=" '#_x0000_t134' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'rectangular-callout' ">
+ <xsl:value-of select=" '#_x0000_t61' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'round-rectangular-callout' ">
+ <xsl:value-of select=" '#_x0000_t62' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'round-callout' ">
+ <xsl:value-of select=" '#_x0000_t63' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'cloud-callout' ">
+ <xsl:value-of select=" '#_x0000_t106' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'line-callout-1' ">
+ <xsl:value-of select=" '#_x0000_t50' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'line-callout-2' ">
+ <xsl:value-of select=" '#_x0000_t51' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'line-callout-3' ">
+ <xsl:value-of select=" '#_x0000_t47' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'bang' ">
+ <xsl:value-of select=" '#_x0000_t72' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'star4' ">
+ <xsl:value-of select=" '#_x0000_t187' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'star5' ">
+ <xsl:value-of select=" '#_x0000_t12' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'star8' ">
+ <xsl:value-of select=" '#_x0000_t58' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'star24' ">
+ <xsl:value-of select=" '#_x0000_t92' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'vertical-scroll' ">
+ <xsl:value-of select=" '#_x0000_t97' "/>
+ </xsl:when>
+ <xsl:when test="$ooo_predefined_type = 'horizontal-scroll' ">
+ <xsl:value-of select=" '#_x0000_t98' "/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_draw.xsl b/filter/source/xslt/export/wordml/ooo2wordml_draw.xsl
new file mode 100644
index 000000000..1e68ffe38
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_draw.xsl
@@ -0,0 +1,1760 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:ole="http://libreoffice.org/2011/xslt/ole" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow ole">
+ <xsl:include href="ooo2wordml_custom_draw.xsl"/>
+
+ <xsl:key name="stroke-dash-style" match="draw:stroke-dash" use="@draw:name"/>
+ <xsl:key name="fill-image" match="draw:fill-image" use="@draw:name"/>
+ <xsl:key name="draw-gradient" match="draw:gradient " use="@draw:name"/>
+ <xsl:template name="PageLevelGraphic">
+ <xsl:for-each select="//draw:*[@text:anchor-type='page']">
+ <xsl:apply-templates select="."/>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="draw:*">
+ <xsl:param name="TargetMeasure" select="'pt'"/>
+ <xsl:param name="x-adjust" select="0"/>
+ <xsl:param name="y-adjust" select="0"/>
+ <xsl:param name="force-draw" select="'false'"/>
+ <xsl:variable name="MeasureMark">
+ <xsl:choose>
+ <xsl:when test="$TargetMeasure = 'twip'"/>
+ <xsl:otherwise>
+ <xsl:value-of select="$TargetMeasure"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <!--
+ deal with captions and frames first. draw:text-box is a powerful element in OOo, its GUI name is frame. And OOo use it to contain Captions
+ Since there is not a corresponding object in word, so we draw the text-box itself and its children separately. If it look like a Caption only frame
+ we'll adjust the text-box position to make it look pretty
+ -->
+ <!-- skip all not force draw children , must be first case -->
+ <xsl:when test="ancestor::draw:text-box and $force-draw='false' "/>
+ <xsl:when test="name() = 'draw:text-box'">
+ <!-- draw the text-box itself -->
+ <w:r>
+ <w:pict>
+ <xsl:variable name="text-y-adjust">
+ <xsl:choose>
+ <xsl:when test="count(text:p/draw:*) = 1 and (string-length(text:p/draw:*[position()=1]/@svg:x) =0 or number(concat('0',translate(text:p/draw:*[position()=1]/@svg:x,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ','') ))=0) and (string-length(text:p/draw:*[position()=1]/@svg:y)=0 or number(concat('0',translate(text:p/draw:*[position()=1]/@svg:x,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ','') ))=0 ) ">
+ <xsl:variable name="pic-height">
+ <xsl:choose>
+ <xsl:when test="name(text:p/draw:*[position()=1]) = 'draw:g' or name(text:p/draw:*[position()=1]) = 'draw:a'">
+ <xsl:variable name="BigestWindow">
+ <xsl:call-template name="GetWindowSize">
+ <xsl:with-param name="nodeSet" select="text:p/draw:*[position()=1]/draw:*"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="number(substring-after($BigestWindow,'y2:')) - number(substring-after(substring-before($BigestWindow,';x2'), 'y1:')) + number(concat('0',translate($y-adjust,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ','')))"/>
+ </xsl:when>
+ <xsl:when test="text:p/draw:*[position()=1]/@svg:height">
+ <xsl:call-template name="Add-With-Measure">
+ <xsl:with-param name="value1" select="text:p/draw:*[position()=1]/@svg:height"/>
+ <xsl:with-param name="value2" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="text:p/draw:*[position()=1]/@fo:min-height">
+ <xsl:call-template name="Add-With-Measure">
+ <xsl:with-param name="value1" select="text:p/draw:*[position()=1]/@fo:min-height"/>
+ <xsl:with-param name="value2" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="ancestor::draw:frame">
+ <xsl:call-template name="Add-With-Measure">
+ <xsl:with-param name="value1" select="ancestor::draw:frame/@svg:height"/>
+ <xsl:with-param name="value2" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="min-height">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="@fo:min-height"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$min-height - $pic-height &lt; 0.001">
+ <!-- If control goes here, it much like that this text-box is used for contain graphic caption only -->
+ <xsl:value-of select="$pic-height - 0.1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$y-adjust"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$y-adjust"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="shape-type">
+ <xsl:choose>
+ <xsl:when test="$text-y-adjust = $y-adjust">
+ <xsl:value-of select="'#_x0000_t202'"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="DrawElements">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$text-y-adjust"/>
+ <xsl:with-param name="force-draw" select="'true'"/>
+ <xsl:with-param name="shape-type" select="$shape-type"/>
+ </xsl:call-template>
+ </w:pict>
+ </w:r>
+ <!-- draw the real object first -->
+ <xsl:if test="./text:p/draw:*">
+ <xsl:apply-templates select="./text:p/draw:*">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="x-adjust">
+ <xsl:call-template name="Add-With-Measure">
+ <xsl:with-param name="value1" select="@svg:x"/>
+ <xsl:with-param name="value2" select="$x-adjust"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="y-adjust">
+ <xsl:call-template name="Add-With-Measure">
+ <xsl:with-param name="value1" select="@svg:y"/>
+ <xsl:with-param name="value2" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="force-draw" select="'true'"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:when>
+ <!-- end deal with captions and frames -->
+ <xsl:when test=" name() = 'draw:frame' ">
+ <xsl:variable name="BigestWindow">
+ <xsl:call-template name="GetWindowSize">
+ <xsl:with-param name="nodeSet" select="."/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:apply-templates select="draw:* ">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="x-adjust" select="concat(substring-after(substring-before($BigestWindow,';y1'), 'x1:'), 'in')"/>
+ <xsl:with-param name="y-adjust" select="concat(substring-after(substring-before($BigestWindow,';x2'), 'y1:') , 'in')"/>
+ <xsl:with-param name="force-draw" select="$force-draw"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="name() = 'draw:g'">
+ <w:r>
+ <w:pict>
+ <xsl:element name="v:group">
+ <xsl:variable name="BigestWindow">
+ <xsl:choose>
+ <xsl:when test="name() = 'draw:g'">
+ <xsl:call-template name="GetWindowSize">
+ <xsl:with-param name="nodeSet" select="draw:*"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'draw:frame'">
+ <xsl:call-template name="GetWindowSize">
+ <xsl:with-param name="nodeSet" select="."/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="x">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="concat(substring-after(substring-before($BigestWindow,';y1'), 'x1:'), 'in')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="y">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="concat(substring-after(substring-before($BigestWindow,';x2'), 'y1:') , 'in')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="width">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="concat(number(substring-after(substring-before($BigestWindow,';y2'), 'x2:')) - number(substring-after(substring-before($BigestWindow,';y1'), 'x1:')) , 'in')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="height">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="concat(number(substring-after($BigestWindow,'y2:')) - number(substring-after(substring-before($BigestWindow,';x2'), 'y1:')), 'in')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="id">
+ <xsl:value-of select="generate-id()"/>
+ </xsl:attribute>
+ <xsl:variable name="absolute">
+ <xsl:choose>
+ <xsl:when test="ancestor::draw:a"/>
+ <xsl:when test="@text:anchor-type = 'as-char' or @text:anchor-type = 'to-char'"/>
+ <xsl:otherwise>position:absolute</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$TargetMeasure= 'pt'">
+ <xsl:attribute name="style">
+ <xsl:if test="string-length($absolute) &gt; 0">
+ <xsl:value-of select="concat($absolute, ';')"/>
+ </xsl:if>
+ <xsl:value-of select="concat('margin-left:',$x ,$MeasureMark,';margin-top:', $y,$MeasureMark ,';width:', $width ,$MeasureMark , ';height:', $height,$MeasureMark)"/>
+ </xsl:attribute>
+ <xsl:attribute name="coordorigin">
+ <xsl:choose>
+ <!-- if we are in a text-box then oo will use comparative positions on us-->
+ <xsl:when test="name() = 'draw:frame' ">
+ <xsl:value-of select=" '0 0' "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat(round($x * 20), ',' , round($y * 20))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="coordsize">
+ <xsl:value-of select="concat(round($width * 20),',', round($height * 20) )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$TargetMeasure= 'twip' ">
+ <xsl:attribute name="style">
+ <xsl:if test="string-length($absolute) &gt; 0">
+ <xsl:value-of select="concat($absolute, ';')"/>
+ </xsl:if>
+ <xsl:value-of select="concat('left:',$x ,$MeasureMark,';top:', $y,$MeasureMark ,';width:', $width ,$MeasureMark , ';height:', $height,$MeasureMark)"/>
+ </xsl:attribute>
+ <xsl:attribute name="coordorigin">
+ <xsl:choose>
+ <!-- if we are in a text-box then oo will use comparative positions on us-->
+ <xsl:when test="name() = 'draw:frame' ">
+ <xsl:value-of select=" '0 0' "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($x , ',' , $y)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="coordsize">
+ <xsl:value-of select="concat($width,',', $height )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <!-- if we are in a text-box then oo will use comparative positions on us-->
+ <xsl:when test="ancestor::draw:text-box">
+ <xsl:apply-templates select="draw:*">
+ <xsl:with-param name="TargetMeasure" select="'twip'"/>
+ <xsl:with-param name="x-adjust" select="concat(substring-after(substring-before($BigestWindow,';y1'), 'x1:'), 'in')"/>
+ <xsl:with-param name="y-adjust" select="concat(substring-after(substring-before($BigestWindow,';x2'), 'y1:') , 'in')"/>
+ <xsl:with-param name="force-draw" select="$force-draw"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="draw:*">
+ <xsl:with-param name="TargetMeasure" select="'twip'"/>
+ <xsl:with-param name="force-draw" select="$force-draw"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </w:pict>
+ </w:r>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="name() = 'draw:a'">
+ <xsl:call-template name="export_hyoerlink">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ <xsl:with-param name="force-draw" select="$force-draw"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:r>
+ <w:pict>
+ <xsl:call-template name="DrawElements">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ <xsl:with-param name="force-draw" select="$force-draw"/>
+ </xsl:call-template>
+ </w:pict>
+ </w:r>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="GetWindowSize">
+ <xsl:param name="CurrPos" select="1"/>
+ <xsl:param name="nodeSet"/>
+ <xsl:param name="x-adjust" select="0"/>
+ <xsl:param name="y-adjust" select="0"/>
+ <xsl:variable name="CurrNodeWindow">
+ <xsl:call-template name="GetNodeWindow">
+ <xsl:with-param name="CurrNode" select=" $nodeSet[ $CurrPos ]"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <!-- if we got to the last node, return it directly, or return the max window of current one and following ones -->
+ <xsl:when test="$CurrPos = count($nodeSet)">
+ <xsl:value-of select="$CurrNodeWindow"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="CurrentWindow">
+ <xsl:variable name="FollowingWindow">
+ <xsl:call-template name="GetWindowSize">
+ <xsl:with-param name="nodeSet" select="$nodeSet"/>
+ <xsl:with-param name="CurrPos" select="$CurrPos + 1"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="GetBigestWindows">
+ <xsl:with-param name="Window1" select="$CurrNodeWindow"/>
+ <xsl:with-param name="Window2" select="$FollowingWindow"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$CurrentWindow"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="GetNodeWindow">
+ <xsl:param name="CurrNode"/>
+ <xsl:param name="x-adjust" select="0"/>
+ <xsl:param name="y-adjust" select="0"/>
+ <xsl:choose>
+ <xsl:when test="name($CurrNode)='draw:g'">
+ <xsl:call-template name="GetWindowSize">
+ <xsl:with-param name="nodeSet" select="$CurrNode/draw:*"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="x">
+ <xsl:call-template name="Add-With-Measure">
+ <xsl:with-param name="value1" select="$CurrNode/@svg:x"/>
+ <xsl:with-param name="value2" select="$x-adjust"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="y">
+ <xsl:call-template name="Add-With-Measure">
+ <xsl:with-param name="value1" select="$CurrNode/@svg:y"/>
+ <xsl:with-param name="value2" select="$y-adjust"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="width">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="$CurrNode/@svg:width"/>
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="height">
+ <xsl:choose>
+ <xsl:when test="$CurrNode/@svg:height">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="$CurrNode/@svg:height"/>
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$CurrNode/@fo:min-height">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="$CurrNode/@fo:min-height"/>
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat('x1:' , $x, ';y1:' , $y, ';x2:' , string($x + $width), ';y2:', string($y + $height) ) "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="GetBigestWindows">
+ <xsl:param name="Window1"/>
+ <xsl:param name="Window2"/>
+ <xsl:variable name="w1x1" select="substring-after( substring-before($Window1,';y1'),'x1:') "/>
+ <xsl:variable name="w2x1" select="substring-after( substring-before($Window2,';y1'),'x1:') "/>
+ <xsl:variable name="w1y1" select="substring-after( substring-before($Window1,';x2'),'y1:') "/>
+ <xsl:variable name="w2y1" select="substring-after( substring-before($Window2,';x2'),'y1:') "/>
+ <xsl:variable name="w1x2" select="substring-after( substring-before($Window1,';y2'),'x2:') "/>
+ <xsl:variable name="w2x2" select="substring-after( substring-before($Window2,';y2'),'x2:') "/>
+ <xsl:variable name="w1y2" select="substring-after( $Window1,';y2:') "/>
+ <xsl:variable name="w2y2" select="substring-after( $Window2,';y2:') "/>
+ <xsl:variable name="x1">
+ <xsl:choose>
+ <xsl:when test="$w1x1 &gt; $w2x1">
+ <xsl:value-of select="$w2x1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$w1x1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="y1">
+ <xsl:choose>
+ <xsl:when test="$w1y1 &gt; $w2y1">
+ <xsl:value-of select="$w2y1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$w1y1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="x2">
+ <xsl:choose>
+ <xsl:when test="$w1x2 &gt; $w2x2">
+ <xsl:value-of select="$w1x2"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$w2x2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="y2">
+ <xsl:choose>
+ <xsl:when test="$w1y2 &gt; $w2y2">
+ <xsl:value-of select="$w1y2"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$w2y2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat('x1:' , $x1 , ';y1:' , $y1 , ';x2:' , $x2, ';y2:' , $y2)"/>
+ </xsl:template>
+ <!-- convert percent value to x% numeric x/100 -->
+ <xsl:template name="ValueOfPercent">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, '%')">
+ <xsl:value-of select="substring-before($value, '%') div 100"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="points2points">
+ <xsl:param name="input_points"/>
+ <xsl:param name="input_x"/>
+ <xsl:param name="input_y"/>
+ <xsl:param name="input_width"/>
+ <xsl:param name="input_height"/>
+ <xsl:param name="input_boxwidth"/>
+ <xsl:param name="input_boxheight"/>
+ <xsl:variable name="onepoint" select="substring($input_points,1,string-length($input_points) - string-length(substring-after($input_points,' ')) )"/>
+ <xsl:if test="substring-before($input_points,' ')">
+ <xsl:value-of select="round($input_x + (($input_boxwidth - number(substring-before($onepoint,','))) ) * $input_width div $input_boxwidth)"/>
+ <xsl:value-of select="'pt,'"/>
+ <xsl:value-of select="round($input_y + ((number(substring-after($onepoint,',')) ) ) * $input_height div $input_boxheight)"/>
+ <xsl:value-of select="'pt'"/>
+ </xsl:if>
+ <xsl:if test="string-length(substring($input_points,string-length($onepoint) + 1)) &gt; 0">
+ <xsl:value-of select="','"/>
+ <xsl:call-template name="points2points">
+ <xsl:with-param name="input_points" select="substring($input_points,string-length($onepoint) + 1)"/>
+ <xsl:with-param name="input_x" select="$input_x"/>
+ <xsl:with-param name="input_y" select="$input_y"/>
+ <xsl:with-param name="input_width" select="$input_width"/>
+ <xsl:with-param name="input_height" select="$input_height"/>
+ <xsl:with-param name="input_boxwidth" select="$input_boxwidth"/>
+ <xsl:with-param name="input_boxheight" select="$input_boxheight"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="path2path">
+ <xsl:param name="input_points"/>
+ <xsl:param name="x_or_y" select="'x'"/>
+ <xsl:param name="input_x"/>
+ <xsl:param name="input_y"/>
+ <xsl:param name="input_width"/>
+ <xsl:param name="input_height"/>
+ <xsl:param name="input_boxwidth"/>
+ <xsl:param name="input_boxheight"/>
+ <xsl:variable name="space-pos" select="string-length($input_points) - string-length(substring-after($input_points,' '))"/>
+ <xsl:variable name="minus-pos" select="string-length($input_points) - string-length(substring-after($input_points,'-'))"/>
+ <xsl:variable name="m-pos" select="string-length($input_points) - string-length(substring-after($input_points,'m'))"/>
+ <xsl:variable name="c-pos" select="string-length($input_points) - string-length(substring-after($input_points,'c'))"/>
+ <xsl:variable name="e-pos" select="string-length($input_points) - string-length(substring-after($input_points,'e'))"/>
+ <xsl:variable name="min1">
+ <xsl:choose>
+ <xsl:when test="$space-pos &lt; $minus-pos">
+ <xsl:value-of select="$space-pos"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$minus-pos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="min2">
+ <xsl:choose>
+ <xsl:when test="$m-pos &lt; $min1">
+ <xsl:value-of select="$m-pos"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$min1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="min3">
+ <xsl:choose>
+ <xsl:when test="$c-pos &lt; $min2">
+ <xsl:value-of select="$c-pos"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$min2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="min4">
+ <xsl:choose>
+ <xsl:when test="$e-pos &lt; $min3">
+ <xsl:value-of select="$e-pos"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$min3"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="min-special-char-pos" select="$min4"/>
+ <xsl:variable name="special-char" select="substring($input_points,$min-special-char-pos,1)"/>
+ <xsl:variable name="one-value" select="substring($input_points,1,$min-special-char-pos - 1)"/>
+ <xsl:variable name="left-points" select="substring($input_points,$min-special-char-pos + 1)"/>
+ <xsl:if test="not($special-char = 'm')">
+ <xsl:if test="$x_or_y = 'x'">
+ <xsl:value-of select="round($input_x + $one-value * $input_width div $input_boxwidth)"/>
+ </xsl:if>
+ <xsl:if test="$x_or_y = 'y'">
+ <xsl:value-of select="round($input_y + $one-value * $input_height div $input_boxheight)"/>
+ </xsl:if>
+ </xsl:if>
+ <!-- output the separator-->
+ <xsl:choose>
+ <xsl:when test="$special-char = '-' or $special-char = ' ' ">
+ <xsl:value-of select="','"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$special-char"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:variable name="next-xy">
+ <xsl:if test="$x_or_y = 'x'">
+ <xsl:value-of select="'y'"/>
+ </xsl:if>
+ <xsl:if test="$x_or_y = 'y'">
+ <xsl:value-of select="'x'"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:if test="string-length($left-points) &gt; 0">
+ <xsl:call-template name="path2path">
+ <xsl:with-param name="input_points" select="$left-points"/>
+ <xsl:with-param name="x_or_y" select="$next-xy"/>
+ <xsl:with-param name="input_x" select="$input_x"/>
+ <xsl:with-param name="input_y" select="$input_y"/>
+ <xsl:with-param name="input_width" select="$input_width"/>
+ <xsl:with-param name="input_height" select="$input_height"/>
+ <xsl:with-param name="input_boxwidth" select="$input_boxwidth"/>
+ <xsl:with-param name="input_boxheight" select="$input_boxheight"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="get_dashstyle">
+ <xsl:param name="stroke-width" select="0.1"/>
+ <xsl:param name="style-name" select="@draw:style-name"/>
+ <xsl:variable name="graph-style" select="key('graphics-style', $style-name)/style:graphic-properties"/>
+ <xsl:variable name="dash-style" select="key('stroke-dash-style', $graph-style/@draw:stroke-dash)"/>
+ <xsl:variable name="stroke">
+ <xsl:choose>
+ <xsl:when test="$graph-style/@draw:stroke">
+ <xsl:value-of select="$graph-style/@draw:stroke"/>
+ </xsl:when>
+ <xsl:when test="$dash-style/@draw:stroke">
+ <xsl:value-of select="$dash-style/@draw:stroke"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$stroke = 'solid' ">
+ <xsl:value-of select="$stroke"/>
+ </xsl:when>
+ <xsl:when test="$stroke = 'dash'">
+ <xsl:variable name="dots1">
+ <xsl:choose>
+ <xsl:when test="$graph-style/@draw:dots1">
+ <xsl:value-of select="$graph-style/@draw:dots1"/>
+ </xsl:when>
+ <xsl:when test="$dash-style/@draw:dots1">
+ <xsl:value-of select="$dash-style/@draw:dots1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="dots2">
+ <xsl:choose>
+ <xsl:when test="$graph-style/@draw:dots1">
+ <xsl:value-of select="$graph-style/@draw:dots2"/>
+ </xsl:when>
+ <xsl:when test="$dash-style/@draw:dots1">
+ <xsl:value-of select="$dash-style/@draw:dots2"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="dots1-length">
+ <xsl:choose>
+ <xsl:when test="$graph-style/@draw:dots1-length">
+ <xsl:value-of select="$graph-style/@draw:dots1-length"/>
+ </xsl:when>
+ <xsl:when test="$dash-style/@draw:dots1-length">
+ <xsl:value-of select="$dash-style/@draw:dots1-length"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="dots2-length">
+ <xsl:choose>
+ <xsl:when test="$graph-style/@draw:dots2-length">
+ <xsl:value-of select="$graph-style/@draw:dots2-length"/>
+ </xsl:when>
+ <xsl:when test="$dash-style/@draw:dots2-length">
+ <xsl:value-of select="$dash-style/@draw:dots2-length"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="distance">
+ <xsl:choose>
+ <xsl:when test="$graph-style/@draw:distance">
+ <xsl:value-of select="$graph-style/@draw:distance"/>
+ </xsl:when>
+ <xsl:when test="$dash-style/@draw:distance">
+ <xsl:value-of select="$dash-style/@draw:distance"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="dot1-step">
+ <xsl:choose>
+ <xsl:when test="contains($dots1-length,'%')">
+ <xsl:variable name="dots-percent">
+ <xsl:call-template name="ValueOfPercent">
+ <xsl:with-param name="value" select="$dots1-length"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="round($dots-percent)"/>
+ </xsl:when>
+ <xsl:when test="contains($dots1-length , 'in' ) and $stroke-width &gt; 0">
+ <xsl:value-of select="round( number(substring-before($dots1-length,'in' )) div $stroke-width )"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="dot2-step">
+ <xsl:choose>
+ <xsl:when test="contains($dots2-length,'%')">
+ <xsl:variable name="dots-percent">
+ <xsl:call-template name="ValueOfPercent">
+ <xsl:with-param name="value" select="$dots2-length"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="round($dots-percent)"/>
+ </xsl:when>
+ <xsl:when test="contains($dots2-length,'in') and $stroke-width &gt; 0">
+ <xsl:value-of select="round(number(substring-before($dots2-length,'in')) div $stroke-width)"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="distance-step">
+ <xsl:choose>
+ <xsl:when test="contains($distance,'%')">
+ <xsl:variable name="dots-percent">
+ <xsl:call-template name="ValueOfPercent">
+ <xsl:with-param name="value" select="$distance"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="round($dots-percent)"/>
+ </xsl:when>
+ <xsl:when test="contains($distance,'in') and $stroke-width &gt; 0">
+ <xsl:value-of select="round(number(substring-before($distance,'in')) div $stroke-width)"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="dashstyle">
+ <xsl:choose>
+ <xsl:when test="$dots1 = 1 and $dots2 = 1 and $dot1-step = 0 and $dot2-step = 0 and $distance-step = 0">
+ <xsl:value-of select="'ShortDot'"/>
+ </xsl:when>
+ <xsl:when test="$dots2 = 0 and $dot1-step = 0 and $dot2-step = 0 and $distance-step &gt; 0">
+ <xsl:value-of select="concat('0 ', $distance-step)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create_dashstyle">
+ <xsl:with-param name="dot-count" select="$dots1"/>
+ <xsl:with-param name="dot-step" select="$dot1-step"/>
+ <xsl:with-param name="distance-step" select="$distance-step"/>
+ </xsl:call-template>
+ <xsl:value-of select="' '"/>
+ <xsl:call-template name="create_dashstyle">
+ <xsl:with-param name="dot-count" select="$dots2"/>
+ <xsl:with-param name="dot-step" select="$dot2-step"/>
+ <xsl:with-param name="distance-step" select="$distance-step"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$dashstyle"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create_dashstyle">
+ <xsl:param name="dot-count"/>
+ <xsl:param name="dot-step"/>
+ <xsl:param name="distance-step"/>
+ <xsl:if test="$dot-count &gt; 0">
+ <xsl:value-of select="concat($dot-step, ' ' , $distance-step )"/>
+ <xsl:if test="$dot-count - 1 &gt; 0">
+ <xsl:value-of select="' '"/>
+ <xsl:call-template name="create_dashstyle">
+ <xsl:with-param name="dot-count" select="$dot-count - 1"/>
+ <xsl:with-param name="dot-step" select="$dot-step"/>
+ <xsl:with-param name="distance-step" select="$distance-step"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="get_borderstyle">
+ <xsl:param name="border"/>
+ <xsl:param name="border-line-width"/>
+ <xsl:choose>
+ <xsl:when test="contains($border,'solid')">
+ <xsl:variable name="strokeweight">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="substring-before($border, ' ')"/>
+ <xsl:with-param name="TargetMeasure" select="'pt'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat ( 'strokeweight:', $strokeweight)"/>
+ </xsl:when>
+ <xsl:when test="contains($border,'double')">
+ <xsl:variable name="outside">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="substring-after(substring-after($border-line-width, ' ') , ' ')"/>
+ <xsl:with-param name="TargetMeasure" select="'pt'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="inside">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="substring-before($border-line-width, ' ')"/>
+ <xsl:with-param name="TargetMeasure" select="'pt'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="space">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="substring-before(substring-after($border-line-width, ' ') , ' ')"/>
+ <xsl:with-param name="TargetMeasure" select="'pt'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="linestyle">
+ <xsl:choose>
+ <xsl:when test="$outside = $inside">
+ <xsl:value-of select="'thinThin'"/>
+ </xsl:when>
+ <xsl:when test="$outside &gt; $inside">
+ <xsl:value-of select="'thickThin'"/>
+ </xsl:when>
+ <xsl:when test="$outside &lt; $inside">
+ <xsl:value-of select="'thinThick'"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="strokeweight" select="$inside + $outside + $space"/>
+ <xsl:value-of select="concat( 'linestyle:' , $linestyle , ';' , 'strokeweight:' , $strokeweight )"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="DrawElements">
+ <xsl:param name="TargetMeasure" select="pt"/>
+ <xsl:param name="x-adjust" select="0"/>
+ <xsl:param name="y-adjust" select="0"/>
+ <xsl:param name="force-draw" select="'false'"/>
+ <xsl:param name="shape-type"/>
+ <xsl:variable name="MeasureMark">
+ <xsl:choose>
+ <xsl:when test="$TargetMeasure = 'twip'"/>
+ <xsl:otherwise>
+ <xsl:value-of select="$TargetMeasure"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="drawtextstyle" select="@draw:text-style-name"/>
+ <xsl:variable name="org-z-index">
+ <xsl:choose>
+ <xsl:when test="@draw:z-index">
+ <xsl:value-of select="number(concat('0',@draw:z-index))"/>
+ </xsl:when>
+ <xsl:when test="parent::draw:frame/@draw:z-index">
+ <xsl:value-of select="number(concat('0',parent::draw:frame/@draw:z-index))"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="run-though" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@style:run-through"/>
+ <xsl:variable name="org-wrap" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@style:wrap"/>
+ <xsl:variable name="draw-name">
+ <xsl:choose>
+ <xsl:when test="string-length(@draw:name) = 0">
+ <xsl:value-of select="translate(ancestor::draw:frame[1]/@draw:name, ':/', '__')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(@draw:name, ':/', '__')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="style_name2key">
+ <xsl:choose>
+ <xsl:when test="@draw:style-name">
+ <xsl:value-of select="@draw:style-name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="ancestor::draw:frame/@draw:style-name">
+ <xsl:value-of select="ancestor::draw:frame/@draw:style-name"/>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="draw-fill-type" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fill"/>
+ <xsl:variable name="draw-gradient-name" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fill-gradient-name"/>
+ <xsl:variable name="horizontal-pos" select="key('graphics-style', $style_name2key)/style:graphic-properties/@style:horizontal-pos"/>
+ <!--horizontal-pos attribute is for the placement of all the drawing elements-->
+ <xsl:variable name="fill-image-name" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fill-image-name"/>
+ <xsl:if test="$draw-fill-type = 'bitmap' ">
+ <xsl:element name="w:binData">
+ <xsl:attribute name="w:name">
+ <xsl:value-of select="concat( 'wordml://', $fill-image-name)"/>
+ </xsl:attribute>
+ <xsl:value-of select="translate(key('fill-image',$fill-image-name)/office:binary-data/text(),'&#9;&#10;&#13;&#32;','' ) "/>
+ <!-- xsl:value-of select="office:binary-data/text()"/ -->
+ </xsl:element>
+ </xsl:if>
+ <xsl:variable name="z-index">
+ <xsl:choose>
+ <xsl:when test="$run-though='foreground'">
+ <!-- make sure z-index >=0 -->
+ <xsl:choose>
+ <xsl:when test="$org-z-index &lt; 0">0</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$org-z-index"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$run-though='background'">
+ <!-- make sure z-index < 0 -->
+ <xsl:choose>
+ <xsl:when test="$org-z-index &lt; 0">
+ <xsl:value-of select="$org-z-index"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$org-z-index - 10"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="wrap">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='as-char' ">none</xsl:when>
+ <xsl:when test="$org-wrap='dynamic'">tight</xsl:when>
+ <xsl:when test="$org-wrap='parallel'">square</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="ooshapename" select="substring-after(name(),':')"/>
+ <xsl:variable name="element-name">
+ <xsl:choose>
+ <xsl:when test="$ooshapename='rect'">v:rect</xsl:when>
+ <xsl:when test="$ooshapename='ellipse' and not(string-length(@draw:kind) &gt; 0)">v:oval</xsl:when>
+ <xsl:when test="$ooshapename='ellipse' and string-length(@draw:kind) &gt; 0">v:arc</xsl:when>
+ <xsl:when test="$ooshapename='circle' and string-length(@draw:kind) &gt; 0">v:arc</xsl:when>
+ <xsl:when test="$ooshapename='line'">v:line</xsl:when>
+ <xsl:when test="$ooshapename='polyline'">v:polyline</xsl:when>
+ <xsl:when test="$ooshapename='polygon'">v:polyline</xsl:when>
+ <xsl:when test="$ooshapename='text-box'">v:shape</xsl:when>
+ <xsl:when test="$ooshapename='image'">v:shape</xsl:when>
+ <xsl:when test="$ooshapename='frame'">v:shape</xsl:when>
+ <xsl:when test="$ooshapename='path'">v:shape</xsl:when>
+ <!-- This caption is not the "Caption", it's GUI name is Callouts-->
+ <xsl:when test="$ooshapename='caption'">v:shape</xsl:when>
+ <xsl:when test="$ooshapename='custom-shape' and draw:enhanced-geometry[1]/@draw:predefined-type = 'non-primitive' ">v:shape</xsl:when>
+ <xsl:when test="$ooshapename='custom-shape' and draw:enhanced-geometry[1]/@draw:predefined-type = 'round-rectangle' ">v:roundrect</xsl:when>
+ <xsl:when test="$ooshapename='custom-shape' and draw:enhanced-geometry[1]/@draw:predefined-type = 'rectangle' ">v:rect</xsl:when>
+ <xsl:when test="$ooshapename='custom-shape' and draw:enhanced-geometry[1]/@draw:predefined-type = 'ellipse' ">v:oval</xsl:when>
+ <xsl:when test="$ooshapename='custom-shape'">v:shape</xsl:when>
+ <!-- some wild guess -->
+ <xsl:otherwise>v:shape</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="ms-shape-type">
+ <xsl:choose>
+ <xsl:when test="string-length($shape-type) &gt; 0">
+ <xsl:value-of select="$shape-type"/>
+ </xsl:when>
+ <xsl:when test="$ooshapename='custom-shape' ">
+ <xsl:call-template name="ooo_custom_draw2ms_word_draw_map">
+ <xsl:with-param name="ooo_predefined_type" select="draw:enhanced-geometry[1]/@draw:predefined-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="real-x-adjust">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="concat($x-adjust,'in')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="real-y-adjust">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="concat($y-adjust,'in')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="org-x">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="@svg:x"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="org-y">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="@svg:y"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="pagemaster" select="key('master-page','Standard')/@style:page-layout-name"/>
+ <xsl:variable name="leftmargin-pt">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="key('page-layout',$pagemaster)/style:page-layout-properties/@fo:margin-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="topmargin-pt">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="key('page-layout',$pagemaster)/style:page-layout-properties/@fo:margin-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- adjust the x and y values of the page archored objects-->
+ <xsl:variable name="x">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='page' or ancestor::draw:*/@text:anchor-type='page'">
+ <xsl:value-of select="$org-x + $real-x-adjust - $leftmargin-pt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$org-x + $real-x-adjust"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="y">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='page' or ancestor::draw:*/@text:anchor-type='page'">
+ <xsl:value-of select="$org-y + $real-y-adjust - $topmargin-pt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$org-y + $real-y-adjust"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="width">
+ <xsl:variable name="width-tmp">
+ <xsl:choose>
+ <xsl:when test="@svg:width">
+ <xsl:value-of select="@svg:width"/>
+ </xsl:when>
+ <xsl:when test="not(string-length(parent::draw:frame/@svg:width) = 0)">
+ <xsl:value-of select="parent::draw:frame/@svg:width"/>
+ </xsl:when>
+ <xsl:when test="string-length(@svg:width) = 0 and ancestor::draw:frame">
+ <xsl:value-of select="ancestor::draw:frame/@svg:width"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@svg:width"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="$width-tmp"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="height">
+ <xsl:choose>
+ <xsl:when test="@svg:height">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="@svg:height"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="not(string-length(parent::draw:frame/@svg:height) = 0)">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="parent::draw:frame/@svg:height"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="@fo:min-height and string-length(text:p/text()) = 0 and not(text:p/draw:*)">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="@fo:min-height"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="borderstyle">
+ <xsl:call-template name="get_borderstyle">
+ <xsl:with-param name="border" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@fo:border"/>
+ <xsl:with-param name="border-line-width" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@style:border-line-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="stroke-weight-in-inch" select="number(concat('0',translate(key('graphics-style', @draw:style-name)/style:graphic-properties/@svg:stroke-width ,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ','') ))"/>
+ <xsl:variable name="stroke-weight">
+ <xsl:choose>
+ <xsl:when test="contains($borderstyle , 'strokeweight')">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="concat( substring-after($borderstyle, 'strokeweight:') , 'pt')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@svg:stroke-width"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="linestyle">
+ <xsl:if test="contains($borderstyle , 'strokeweight')">
+ <xsl:value-of select="substring-before( substring-after($borderstyle, 'linestyle:') , ';strokeweight')"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="stroked">
+ <xsl:if test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:stroke = 'none'">
+ <xsl:value-of select="'f'"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="dashstyle">
+ <xsl:call-template name="get_dashstyle">
+ <xsl:with-param name="stroke-width" select="$stroke-weight-in-inch"/>
+ <xsl:with-param name="style-name" select="@draw:style-name"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="start-arrow">
+ <xsl:choose>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-end">
+ <xsl:call-template name="MapArrowStyle">
+ <xsl:with-param name="arrow-name" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-end"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="end-arrow">
+ <xsl:choose>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-start">
+ <xsl:call-template name="MapArrowStyle">
+ <xsl:with-param name="arrow-name" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-start"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="start-arrow-length">
+ <xsl:choose>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-end">
+ <xsl:call-template name="GetArrowLength">
+ <xsl:with-param name="arrow-name" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-end"/>
+ <xsl:with-param name="arrow-width" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-end-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="start-arrow-width">
+ <xsl:choose>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-end">
+ <xsl:call-template name="GetArrowWidth">
+ <xsl:with-param name="arrow-name" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-end"/>
+ <xsl:with-param name="arrow-width" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-end-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="end-arrow-length">
+ <xsl:choose>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-start">
+ <xsl:call-template name="GetArrowLength">
+ <xsl:with-param name="arrow-name" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-start"/>
+ <xsl:with-param name="arrow-width" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-start-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="end-arrow-width">
+ <xsl:choose>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-start">
+ <xsl:call-template name="GetArrowWidth">
+ <xsl:with-param name="arrow-name" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-start"/>
+ <xsl:with-param name="arrow-width" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:marker-start-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="stroke-color">
+ <xsl:choose>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@svg:stroke-color">
+ <xsl:value-of select="key('graphics-style', @draw:style-name)/style:graphic-properties/@svg:stroke-color"/>
+ </xsl:when>
+ <xsl:when test="contains(key('graphics-style', @draw:style-name)/style:graphic-properties/@fo:border, '#')">
+ <xsl:value-of select="concat('#', substring-after(key('graphics-style', @draw:style-name)/style:graphic-properties/@fo:border, '#') )"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="stroke-opacity">
+ <xsl:call-template name="ValueOfPercent">
+ <xsl:with-param name="value" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@svg:stroke-opacity"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="fill-color">
+ <xsl:choose>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fill-color">
+ <xsl:value-of select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fill-color"/>
+ </xsl:when>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fontwork-style">black</xsl:when>
+ <xsl:when test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fill = 'none'"/>
+ <xsl:when test="$draw-fill-type = 'gradient' ">
+ <xsl:value-of select="key('draw-gradient',$draw-gradient-name)/@draw:end-color "/>
+ </xsl:when>
+ <!-- for these need fill, set the default color we used in oo-->
+ <xsl:when test="name()='draw:polygon' or name()='draw:custom-shape' or name() = 'draw:rect' or (name() = 'draw:ellipse' and not( @draw:kind='arc') )">#00B8FF</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="position">
+ <xsl:value-of select="concat('left:', $x ,$MeasureMark , ';top:' , $y ,$MeasureMark , ';width:', $width ,$MeasureMark )"/>
+ <xsl:if test="not($height = 0)">
+ <xsl:value-of select="concat(';height:', $height ,$MeasureMark )"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="flip">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='as-char' and $ooshapename='line'"/>
+ <xsl:when test="$ooshapename='image'"/>
+ <xsl:when test="$ooshapename='path'"/>
+ <xsl:when test="$ooshapename='caption'"/>
+ <xsl:when test="@draw:kind = 'arc' or @draw:kind = 'cut' or @draw:kind = 'section'"/>
+ <xsl:when test="$ooshapename='custom-shape'"/>
+ <xsl:otherwise>flip:x</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="absolute">
+ <xsl:choose>
+ <xsl:when test="ancestor::draw:a"/>
+ <xsl:when test="@text:anchor-type = 'as-char' or @text:anchor-type = 'to-char'"/>
+ <xsl:when test="parent::draw:frame/@text:anchor-type = 'as-char' or parent::draw:frame/@text:anchor-type = 'to-char'"/>
+ <xsl:otherwise>position:absolute</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="anchorlock">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type = 'as-char' or @text:anchor-type = 'to-char'">has</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- start line special -->
+ <xsl:variable name="org-x1">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="@svg:x1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="org-y1">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="@svg:y1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="org-x2">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="@svg:x2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="org-y2">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="value" select="@svg:y2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="x1">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='page' or ancestor::draw:*/@text:anchor-type='page'">
+ <xsl:value-of select="$org-x1 + $real-x-adjust - $leftmargin-pt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$org-x1 + $real-x-adjust"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="y1">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='page' or ancestor::draw:*/@text:anchor-type='page'">
+ <xsl:value-of select="$org-y1 + $real-y-adjust - $topmargin-pt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$org-y1 + $real-y-adjust"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="x2">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='page' or ancestor::draw:*/@text:anchor-type='page'">
+ <xsl:value-of select="$org-x2 + $real-x-adjust - $leftmargin-pt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$org-x2 + $real-x-adjust"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="y2">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='page' or ancestor::draw:*/@text:anchor-type='page'">
+ <xsl:value-of select="$org-y2 + $real-y-adjust - $topmargin-pt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$org-y2 + $real-y-adjust"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- end line special -->
+ <xsl:variable name="relative">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type = 'as-char' or @text:anchor-type = 'to-char'">mso-position-horizontal-relative:char;mso-position-vertical-relative:line</xsl:when>
+ <xsl:when test="parent::draw:frame/@text:anchor-type = 'as-char' or parent::draw:frame/@text:anchor-type = 'to-char'">mso-position-horizontal-relative:char;mso-position-vertical-relative:line</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="style">
+ <xsl:choose>
+ <xsl:when test="$wrap='none'"/>
+ <xsl:otherwise>
+ <xsl:if test="string-length($absolute) &gt; 0">
+ <xsl:value-of select="concat($absolute, ';')"/>
+ </xsl:if>
+ <xsl:value-of select="concat('z-index:', $z-index, ';')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="string-length($flip) &gt; 0">
+ <xsl:value-of select="concat($flip,';')"/>
+ </xsl:if>
+ <xsl:if test="not($ooshapename = 'line')">
+ <xsl:value-of select="concat($position,';')"/>
+ </xsl:if>
+ <xsl:if test="ancestor::draw:frame and name()='draw:text-box'">
+ <xsl:if test="string-length($horizontal-pos) &gt; 0">
+ <xsl:value-of select="concat('mso-position-horizontal:',$horizontal-pos,';')"/>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="string-length($relative) &gt; 0">
+ <xsl:value-of select="concat($relative,';')"/>
+ </xsl:if>
+ </xsl:variable>
+ <!-- image special: convert oo base64 binary data (77char/line) to word base64 binary data(73char/line) , a workthrough is removing all line breaks -->
+ <xsl:if test="$ooshapename = 'image'">
+ <xsl:element name="w:binData">
+ <xsl:attribute name="w:name">
+ <xsl:value-of select="concat( 'wordml://', $draw-name )"/>
+ </xsl:attribute>
+ <xsl:value-of select="translate(office:binary-data/text(),'&#9;&#10;&#13;&#32;','' ) "/>
+ <!-- xsl:value-of select="office:binary-data/text()"/ -->
+ </xsl:element>
+ </xsl:if>
+ <!-- all element goes here -->
+ <xsl:variable name="id">
+ <xsl:choose>
+ <xsl:when test="$ooshapename='line'">
+ <xsl:value-of select="concat('_x',$x1 , '_' ,$y1, '_' , $x2, '_' ,$y2 )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('_x',$x , '_' ,$y, '_' , $width, '_' ,$height )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="{$element-name}">
+ <xsl:attribute name="id">
+ <xsl:value-of select="$id"/>
+ </xsl:attribute>
+ <xsl:if test="string-length($ms-shape-type) &gt; 0">
+ <xsl:attribute name="type">
+ <xsl:value-of select="$ms-shape-type"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style">
+ <xsl:value-of select="$style"/>
+ </xsl:attribute>
+ <xsl:if test="$stroke-weight &gt; 0">
+ <xsl:attribute name="strokeweight">
+ <xsl:value-of select="concat($stroke-weight,$MeasureMark)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($stroked) &gt; 0">
+ <xsl:attribute name="stroked">
+ <xsl:value-of select="$stroked"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($stroke-color) &gt; 0">
+ <xsl:attribute name="strokecolor">
+ <xsl:value-of select="$stroke-color"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($fill-color) &gt; 0">
+ <xsl:attribute name="fillcolor">
+ <xsl:value-of select="$fill-color"/>
+ </xsl:attribute>
+ <xsl:attribute name="filled">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="parent::draw:frame/draw:object-ole[1]">
+ <xsl:attribute name="filled">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($stroke-opacity) &gt; 0">
+ <xsl:attribute name="opacity">
+ <xsl:value-of select="$stroke-opacity"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- arc special attribute -->
+ <xsl:if test="@draw:kind = 'arc' or @draw:kind = 'cut' or @draw:kind = 'section'">
+ <xsl:choose>
+ <xsl:when test="@draw:start-angle &gt; @draw:end-angle">
+ <xsl:attribute name="startangle">
+ <xsl:value-of select="round( 450 - (@draw:end-angle + 360) )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="startangle">
+ <xsl:value-of select="round( 450 - @draw:end-angle )"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="endangle">
+ <xsl:value-of select="round(450 - @draw:start-angle)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@draw:kind = 'cut'">
+ <xsl:attribute name="fill">
+ <xsl:value-of select="'true'"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- end arc special attribute -->
+ <!-- line special attribute-->
+ <xsl:if test="$ooshapename='line'">
+ <xsl:attribute name="from">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='as-char'">0,0</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($x1,$MeasureMark, ',',$y2,$MeasureMark )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="to">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='as-char'">
+ <xsl:value-of select="concat($x2,$MeasureMark ,',',$y2,$MeasureMark )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($x2,$MeasureMark ,',' ,$y1,$MeasureMark)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- end line special attribute-->
+ <!-- polyline and polygon special attribute-->
+ <xsl:if test="$ooshapename='polyline' or $ooshapename='polygon' ">
+ <!-- translate ' ' to in ' translate ',' to 'in,' -->
+ <xsl:variable name="points">
+ <xsl:call-template name="points2points">
+ <xsl:with-param name="input_x" select="$x"/>
+ <xsl:with-param name="input_y" select="$y"/>
+ <xsl:with-param name="input_width" select="$width"/>
+ <xsl:with-param name="input_height" select="$height"/>
+ <xsl:with-param name="input_boxwidth" select="substring-before(substring-after(@svg:viewBox,'0 0 '),' ')"/>
+ <xsl:with-param name="input_boxheight" select="substring-after(substring-after(@svg:viewBox,'0 0 '),' ')"/>
+ <xsl:with-param name="input_points" select="concat(@draw:points,' ')"/>
+ <!-- add a space to the end of input_points -->
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="points">
+ <xsl:value-of select="$points"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- end polyline and polygon special attribute-->
+ <!-- callouts special attribute-->
+ <xsl:if test="$ooshapename='caption'">
+ <xsl:variable name="caption-point-x">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'twip'"/>
+ <xsl:with-param name="value" select="@draw:caption-point-x"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="caption-point-y">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'twip'"/>
+ <xsl:with-param name="value" select="@draw:caption-point-y"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="type">
+ <!-- map to word line label 3-->
+ <xsl:value-of select="'#_x0000_t48'"/>
+ </xsl:attribute>
+ <xsl:attribute name="adj">
+ <xsl:value-of select=" concat($caption-point-x * 20 , ',' , $caption-point-y * 20 , ',' , $caption-point-x * 10 , ',,,,' , $caption-point-x * 20, ',' , $caption-point-y * 20) "/>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- end callouts special attribute-->
+ <!-- path special attribute-->
+ <xsl:if test="$ooshapename='path' or string-length(@svg:d) &gt; 0 or ( $ooshapename='custom-shape' and draw:enhanced-geometry[1]/@draw:predefined-type = 'non-primitive') ">
+ <xsl:variable name="path">
+ <xsl:choose>
+ <xsl:when test="$ooshapename='path' or string-length(@svg:d) &gt; 0 ">
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="@svg:d"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="draw:enhanced-geometry[1]/@draw:enhanced-path"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="coordorigin">
+ <xsl:value-of select=" '0 0' "/>
+ </xsl:attribute>
+ <xsl:attribute name="coordsize">
+ <xsl:choose>
+ <xsl:when test="string-length(@svg:viewBox) &gt; 0 ">
+ <xsl:value-of select="substring-after(@svg:viewBox,'0 0 ')"/>
+ </xsl:when>
+ <xsl:when test="string-length(draw:enhanced-geometry[1]/@svg:viewBox) &gt; 0 ">
+ <xsl:value-of select="substring-after(draw:enhanced-geometry[1]/@svg:viewBox,'0 0 ')"/>
+ </xsl:when>
+ <!-- for custom shape use a default viewbox. right? -->
+ <xsl:otherwise>
+ <xsl:value-of select=" '21600 21600' "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="path">
+ <xsl:value-of select="$path"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- end path special attribute-->
+ <!-- image special element -->
+ <xsl:if test="$ooshapename='image'">
+ <xsl:element name="v:imagedata">
+ <xsl:attribute name="src">
+ <xsl:value-of select="concat('wordml://', $draw-name)"/>
+ </xsl:attribute>
+ <xsl:attribute name="o:title">
+ <xsl:value-of select="$draw-name"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <!-- end image special element -->
+ <!-- start dash style , line style and arrow style-->
+ <xsl:if test="string-length($dashstyle) &gt; 0 or string-length($linestyle) &gt; 0 or string-length($start-arrow) &gt; 0 or string-length($end-arrow) &gt; 0 ">
+ <xsl:element name="v:stroke">
+ <xsl:if test="string-length($dashstyle) &gt; 0">
+ <xsl:attribute name="dashstyle">
+ <xsl:value-of select="$dashstyle"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($linestyle) &gt; 0">
+ <xsl:attribute name="linestyle">
+ <xsl:value-of select="$linestyle"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($start-arrow) &gt; 0 ">
+ <xsl:attribute name="startarrow">
+ <xsl:value-of select="$start-arrow"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($end-arrow) &gt; 0 ">
+ <xsl:attribute name="endarrow">
+ <xsl:value-of select="$end-arrow"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($start-arrow-length) &gt; 0 ">
+ <xsl:attribute name="startarrowlength">
+ <xsl:value-of select="$start-arrow-length"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($start-arrow-width) &gt; 0 ">
+ <xsl:attribute name="startarrowwidth">
+ <xsl:value-of select="$start-arrow-width"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($end-arrow-length) &gt; 0 ">
+ <xsl:attribute name="endarrowlength">
+ <xsl:value-of select="$end-arrow-length"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($end-arrow-width) &gt; 0 ">
+ <xsl:attribute name="endarrowwidth">
+ <xsl:value-of select="$end-arrow-width"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <!-- end dash style , line style and arrow style -->
+ <!-- start wrap type -->
+ <xsl:if test="string-length($wrap) &gt; 0">
+ <xsl:element name="w10:wrap">
+ <xsl:attribute name="type">
+ <xsl:value-of select="$wrap"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <!-- end wrap type -->
+ <!-- start anchor to char specific element -->
+ <xsl:if test="string-length($anchorlock) &gt; 0">
+ <xsl:element name="w10:anchorlock"/>
+ </xsl:if>
+ <!-- end wrap type -->
+ <!-- start fill image -->
+ <xsl:if test="string-length($draw-fill-type ) &gt; 0">
+ <xsl:element name="v:fill">
+ <xsl:choose>
+ <xsl:when test="$draw-fill-type = 'bitmap'">
+ <xsl:attribute name="src">
+ <xsl:value-of select="concat( 'wordml://', $fill-image-name)"/>
+ </xsl:attribute>
+ <xsl:attribute name="o:title">
+ <xsl:value-of select="$fill-image-name"/>
+ </xsl:attribute>
+ <xsl:attribute name="recolor">
+ <xsl:value-of select=" 'true' "/>
+ </xsl:attribute>
+ <xsl:attribute name="rotate">
+ <xsl:value-of select=" 'true' "/>
+ </xsl:attribute>
+ <xsl:attribute name="type">
+ <xsl:value-of select=" 'frame' "/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$draw-fill-type = 'gradient'">
+ <xsl:attribute name="type">
+ <xsl:value-of select=" 'gradient' "/>
+ </xsl:attribute>
+ <xsl:attribute name="color2">
+ <xsl:value-of select="key('draw-gradient',$draw-gradient-name)/@draw:start-color "/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <!-- end fill image -->
+ <xsl:if test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fontwork-style">
+ <xsl:call-template name="FontWork"/>
+ </xsl:if>
+ <xsl:if test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:shadow = 'visible'">
+ <xsl:call-template name="Shadow"/>
+ </xsl:if>
+ <!-- only draw:g can have child graphic -->
+ <xsl:choose>
+ <xsl:when test="name() = 'draw:g'">
+ <xsl:apply-templates select="draw:*">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ <xsl:with-param name="force-draw" select="$force-draw"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="text:*/* | text:*/text()">
+ <xsl:element name="v:textbox">
+ <xsl:if test="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:writing-mode = 'tb-rl'">
+ <xsl:attribute name="style">
+ <xsl:value-of select="'layout-flow:vertical'"/>
+ </xsl:attribute>
+ </xsl:if>
+ <w:txbxContent>
+ <xsl:apply-templates select="text() | text:*"/>
+ </w:txbxContent>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:apply-templates select="parent::draw:frame/draw:object-ole" mode="output">
+ <xsl:with-param name="ShapeID" select="$id"/>
+ </xsl:apply-templates>
+ </xsl:template>
+ <xsl:template name="Shadow">
+ <xsl:element name="v:shadow">
+ <xsl:variable name="key-node" select="key('graphics-style', @draw:style-name)/style:graphic-properties"/>
+ <xsl:attribute name="on">true</xsl:attribute>
+ <xsl:attribute name="offset">
+ <xsl:value-of select="concat($key-node/@draw:shadow-offset-x,',' , $key-node/@draw:shadow-offset-y)"/>
+ </xsl:attribute>
+ <xsl:attribute name="color">
+ <xsl:value-of select="$key-node/@draw:shadow-color"/>
+ </xsl:attribute>
+ <xsl:attribute name="opacity">
+ <xsl:value-of select="$key-node/@draw:shadow-opacity"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="FontWork">
+ <xsl:element name="v:path">
+ <xsl:attribute name="textpathok">true</xsl:attribute>
+ </xsl:element>
+ <xsl:if test="not(key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fontwork-shadow) or not(key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fontwork-shadow = 'normal')">
+ <xsl:element name="v:shadow">
+ <xsl:attribute name="on">true</xsl:attribute>
+ <xsl:attribute name="type">perspective</xsl:attribute>
+ <xsl:attribute name="color">
+ <xsl:value-of select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fontwork-shadow-color"/>
+ </xsl:attribute>
+ <xsl:variable name="offset-x">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'twip'"/>
+ <xsl:with-param name="value" select="key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fontwork-shadow-offset-x"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="offset-y" select="substring-before(key('graphics-style', @draw:style-name)/style:graphic-properties/@draw:fontwork-shadow-offset-y, 'in')"/>
+ <xsl:attribute name="matrix">
+ <xsl:value-of select="concat(',,,' , round($offset-y div 0.000693) div 100, ',,')"/>
+ </xsl:attribute>
+ <xsl:attribute name="origin">-30%, -30%</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="v:textpath">
+ <xsl:attribute name="on">true</xsl:attribute>
+ <xsl:attribute name="fitpath">true</xsl:attribute>
+ <xsl:attribute name="fitshape">true</xsl:attribute>
+ <xsl:attribute name="style">
+ <xsl:choose>
+ <xsl:when test="key('paragraph-style', text:p[1]/@text:style-name )/style:graphic-properties/@svg:font-family">
+ <xsl:value-of select="concat('font-family:&quot;' , key('paragraph-style', text:p[1]/@text:style-name )/style:graphic-properties/@svg:font-family , '&quot;') "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="default-graphics-properties" select="/office:document/office:styles/style:default-style[@style:family = 'graphics']/style:graphic-properties"/>
+ <xsl:value-of select="concat('font-family:&quot;' , $default-graphics-properties/@style:font-name , '&quot;') "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="string">
+ <xsl:value-of select="text:p"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="MapArrowStyle">
+ <xsl:param name="arrow-name"/>
+ <xsl:choose>
+ <xsl:when test="$arrow-name = 'Arrow' ">Block</xsl:when>
+ <xsl:when test="$arrow-name = 'Square' ">Diamond</xsl:when>
+ <xsl:when test="$arrow-name = 'Small arrow' ">Block</xsl:when>
+ <xsl:when test="$arrow-name = 'Dimension lines' ">Diamond</xsl:when>
+ <xsl:when test="$arrow-name = 'Double Arrow' ">Block</xsl:when>
+ <xsl:when test="$arrow-name = 'Rounded short arrow' ">Block</xsl:when>
+ <xsl:when test="$arrow-name = 'Symmetric arrow' ">Block</xsl:when>
+ <xsl:when test="$arrow-name = 'Line Arrow' ">Open</xsl:when>
+ <xsl:when test="$arrow-name = 'Rounded large arrow' ">Block</xsl:when>
+ <xsl:when test="$arrow-name = 'Circle' ">Oval</xsl:when>
+ <xsl:when test="$arrow-name = 'Square 45' ">Diamond</xsl:when>
+ <xsl:when test="$arrow-name = 'Arrow concave' ">Classic</xsl:when>
+ <xsl:otherwise>Block</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="GetArrowLength">
+ <xsl:param name="arrow-name"/>
+ <xsl:param name="arrow-width"/>
+ <xsl:variable name="arrow-size">
+ <xsl:choose>
+ <xsl:when test="$arrow-width">
+ <xsl:value-of select="round(number(substring-before($arrow-width, 'in')) div 0.02) "/>
+ </xsl:when>
+ <xsl:otherwise>3</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$arrow-size &gt; 2">Long</xsl:when>
+ <xsl:when test="$arrow-size &gt; 1">Medium</xsl:when>
+ <xsl:when test="$arrow-size &gt; 0">Short</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="GetArrowWidth">
+ <xsl:param name="arrow-name"/>
+ <xsl:param name="arrow-width"/>
+ <xsl:variable name="arrow-size">
+ <xsl:choose>
+ <xsl:when test="$arrow-width">
+ <xsl:value-of select="round(number(substring-before($arrow-width, 'in')) div 0.02) "/>
+ </xsl:when>
+ <xsl:otherwise>3</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$arrow-size &gt; 2">Wide</xsl:when>
+ <xsl:when test="$arrow-size &gt; 1">Medium</xsl:when>
+ <xsl:when test="$arrow-size &gt; 0">Narrow</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="export-oledata">
+ <xsl:if test="//draw:object-ole[1]">
+ <xsl:apply-templates select="//draw:object-ole" mode="oledata.mso"/>
+ <w:docOleData>
+ <w:binData w:name="oledata.mso">
+ <xsl:if test="function-available('ole:getByName')">
+ <xsl:value-of select="translate(ole:getByName('oledata.mso'),'&#10;&#13;&#32;','')"/>
+ </xsl:if>
+ </w:binData>
+ </w:docOleData>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="draw:object-ole" mode="oledata.mso">
+ <xsl:variable name="stream-name">
+ <xsl:apply-templates select="." mode="get-number"/>
+ </xsl:variable>
+ <xsl:variable name="tmp" select="ole:insertByName($stream-name, translate(office:binary-data/text(),'&#10;&#13;&#32;','' ) )"/>
+ </xsl:template>
+ <xsl:template match="draw:object-ole" mode="output">
+ <xsl:param name="ShapeID"/>
+ <xsl:variable name="stream-name">
+ <xsl:apply-templates select="." mode="get-number"/>
+ </xsl:variable>
+ <o:OLEObject Type="Embed" DrawAspect="Content" ObjectID="{$stream-name}" ShapeID="{$ShapeID}" ProgID=""/>
+ </xsl:template>
+ <xsl:template match="draw:object-ole" mode="get-number">
+ <xsl:number from="/office:document" level="any" count="draw:object-ole" format="1"/>
+ </xsl:template>
+ <xsl:template match="draw:object-ole"/>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_field.xsl b/filter/source/xslt/export/wordml/ooo2wordml_field.xsl
new file mode 100644
index 000000000..349a07e0e
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_field.xsl
@@ -0,0 +1,726 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <!-- the following are common used fields -->
+ <xsl:template match="text:page-number | text:page-count | text:subject | text:initial-creator | text:title | text:date
+ | text:time | text:page-variable-get | text:author-name | text:author-initials | text:file-name | text:sender-company
+ | text:sender-initials | text:sender-phone-work | text:word-count | text:paragraph-count | text:character-count
+ | text:description | text:creation-time | text:creation-date | text:editing-cycles | text:editing-duration
+ | text:keywords | text:print-time | text:print-date | text:creator | text:modification-time | text:modification-date
+ | text:user-defined | text:variable-get | text:user-field-get | text:sequence | text:database-name ">
+ <w:fldSimple>
+ <xsl:variable name="attribute_value1">
+ <xsl:choose>
+ <xsl:when test="name() = 'text:page-number' or name() = 'text:page-variable-get' ">
+ <xsl:text> PAGE </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:page-count' ">
+ <xsl:text> NUMPAGES </xsl:text>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:subject' ">
+ <xsl:text> SUBJECT </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:initial-creator' ">
+ <xsl:text> AUTHOR </xsl:text>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:title' ">
+ <xsl:text> TITLE </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:date' ">
+ <xsl:text> DATE </xsl:text>
+ <!-- ATM, this template just return null date format, it might be developed in the future -->
+ <xsl:call-template name="field_get_date_format">
+ <xsl:with-param name="field_date_stylename" select="@style:data-style-name"/>
+ <xsl:with-param name="field_date_value" select="@text:date-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:time' ">
+ <xsl:text> TIME </xsl:text>
+ <!-- ATM, this template just return null time format, it might be developed in the future -->
+ <xsl:call-template name="field_get_time_format">
+ <xsl:with-param name="field_time_stylename" select="@style:data-style-name"/>
+ <xsl:with-param name="field_time_value" select="@text:time-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'text:author-name' ">
+ <xsl:text> AUTHOR </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:author-initials' ">
+ <xsl:text> USERINITIALS </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:file-name' ">
+ <xsl:choose>
+ <xsl:when test="@text:display='name-and-extension' or @text:display='name' ">
+ <xsl:text> FILENAME </xsl:text>
+ </xsl:when>
+ <xsl:when test=" @text:display='full' or @text:display='path' ">
+ <xsl:text>FILENAME \p </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:sender-company' ">
+ <xsl:text> DOCPROPERTY Company </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:sender-initials' ">
+ <xsl:text> USERINITIALS </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:sender-phone-work' ">
+ <xsl:text> DOCPROPERTY &quot;Telephone number&quot; </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:word-count' ">
+ <xsl:text> DOCPROPERTY Words </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:paragraph-count' ">
+ <xsl:text> DOCPROPERTY Paragraphs </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:character-count' ">
+ <xsl:text> DOCPROPERTY CharactersWithSpaces </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:description' ">
+ <xsl:text> COMMENTS </xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:creation-time' ">
+ <xsl:text> DOCPROPERTY CreateTime </xsl:text>
+ <!-- ATM, this template just return null time format, it might be developed in the future -->
+ <xsl:call-template name="field_get_time_format">
+ <xsl:with-param name="field_time_stylename" select="@style:data-style-name"/>
+ <xsl:with-param name="field_time_value" select="@text:time-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" name()= 'text:creation-date' ">
+ <xsl:text> CREATEDATE </xsl:text>
+ <!-- ATM, this template just return null date format, it might be developed in the future -->
+ <xsl:call-template name="field_get_date_format">
+ <xsl:with-param name="field_date_stylename" select="@style:data-style-name"/>
+ <xsl:with-param name="field_date_value" select="@text:date-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:editing-cycles' ">
+ <xsl:text> REVNUM \* Arabic </xsl:text>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:editing-duration' ">
+ <xsl:text> EDITTIME </xsl:text>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:keywords' ">
+ <xsl:text> KEYWORDS </xsl:text>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:print-time' ">
+ <xsl:text>DOCPROPERTY LastPrinted </xsl:text>
+ <!-- ATM, this template just return null time format, it might be developed in the future -->
+ <xsl:call-template name="field_get_time_format">
+ <xsl:with-param name="field_time_stylename" select="@style:data-style-name"/>
+ <xsl:with-param name="field_time_value" select="@text:time-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:print-date' ">
+ <xsl:text>DOCPROPERTY LastPrinted </xsl:text>
+ <!-- ATM, this template just return null date format, it might be developed in the future -->
+ <xsl:call-template name="field_get_date_format">
+ <xsl:with-param name="field_date_stylename" select="@style:data-style-name"/>
+ <xsl:with-param name="field_date_value" select="@text:date-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:creator' ">
+ <xsl:text> LASTSAVEDBY </xsl:text>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:modification-time' ">
+ <xsl:text> DOCPROPERTY LastSavedTime </xsl:text>
+ <!-- ATM, this template just return null time format, it might be developed in the future -->
+ <xsl:call-template name="field_get_time_format">
+ <xsl:with-param name="field_time_stylename" select="@style:data-style-name"/>
+ <xsl:with-param name="field_time_value" select="@text:time-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:modification-date' ">
+ <xsl:text> SAVEDATE </xsl:text>
+ <!-- ATM, this template just return null date format, it might be developed in the future -->
+ <xsl:call-template name="field_get_date_format">
+ <xsl:with-param name="field_date_stylename" select="@style:data-style-name"/>
+ <xsl:with-param name="field_date_value" select="@text:date-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:user-defined' ">
+ <xsl:text> DOCPROPERTY </xsl:text>
+ <xsl:text>&quot;</xsl:text>
+ <xsl:value-of select="translate(string(@text:name), ' ', '')"/>
+ <xsl:text>&quot;</xsl:text>
+ </xsl:when>
+ <xsl:when test="name() = 'text:variable-get' or name() = 'text:user-field-get' ">
+ <xsl:value-of select="concat ('DOCVARIABLE ', @text:name)"/>
+ </xsl:when>
+ <xsl:when test=" name() = 'text:sequence' ">
+ <xsl:value-of select="concat(' SEQ &quot;',@text:name, '&quot;') "/>
+ </xsl:when>
+ <xsl:when test="name() = 'text:database-name' ">
+ <xsl:value-of select="concat (' DATABASE ', @text:database-name, '.' , @text:table-name)"/>
+ </xsl:when>
+ </xsl:choose>
+ <!-- Get number style format for number fields -->
+ <xsl:if test="@style:num-format">
+ <xsl:call-template name="field_get_number_format">
+ <xsl:with-param name="field_number_format_style" select="@style:num-format"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:text> \* MERGEFORMAT </xsl:text>
+ </xsl:variable>
+ <xsl:attribute name="w:instr">
+ <xsl:value-of select="$attribute_value1"/>
+ </xsl:attribute>
+ <w:r>
+ <w:rPr>
+ <xsl:choose>
+ <xsl:when test="@style:num-format = '가, 나, 다, ...' or @style:num-format ='일, 이, 삼, ...' or @style:num-format ='ㄱ, ㄴ, ㄷ, ...' ">
+ <w:rFonts w:fareast="Batang" w:hint="fareast"/>
+ <!--wx:font wx:val="Batang"/ -->
+ <w:lang w:fareast="KO"/>
+ </xsl:when>
+ <xsl:when test="@style:num-format = 'ア, イ, ウ, ...' or @style:num-format = 'ア, イ, ウ, ...' or @style:num-format = 'イ, ロ, ハ, ...' or @style:num-format = 'イ, ロ, ハ, ...' or @style:num-format ='壱, 弐, 参, ...' ">
+ <w:rFonts w:fareast="MS Mincho" w:hint="fareast"/>
+ <!--wx:font wx:val="MS Mincho"/ -->
+ <w:lang w:fareast="JA"/>
+ </xsl:when>
+ <xsl:when test=" @style:num-format ='壹, 貳, 參, ...' or @style:num-format ='壹, 貳, 參, ...' or @style:num-format ='壹, 贰, 叁, ...'or @style:num-format = '一, 二, 三, ...' ">
+ <w:rFonts w:hint="fareast"/>
+ <!--wx:font wx:val="宋体"/ -->
+ </xsl:when>
+ </xsl:choose>
+ <w:noProof/>
+ </w:rPr>
+ <w:t>
+ <xsl:value-of select="."/>
+ </w:t>
+ </w:r>
+ </w:fldSimple>
+ </xsl:template>
+ <xsl:template name="field_get_number_format">
+ <!-- this template get the various of number formats for number type field-->
+ <xsl:param name="field_number_format_style"/>
+ <xsl:choose>
+ <xsl:when test=" $field_number_format_style = '1, 2, 3, ...' or $field_number_format_style = '1' ">
+ <xsl:text> \* Arabic </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = '①, ②, ③, ...' ">
+ <xsl:text> \* CircleNum </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = 'i' ">
+ <xsl:text> \* roman </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = 'I' ">
+ <xsl:text> \* ROMAN </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = '一, 二, 三, ...'">
+ <xsl:text> \* CHINESENUM3 </xsl:text>
+ </xsl:when>
+ <xsl:when test=" $field_number_format_style ='壹, 貳, 參, ...' or $field_number_format_style ='壹, 貳, 參, ...' or $field_number_format_style ='壹, 贰, 叁, ...' ">
+ <xsl:text> \* CHINESENUM2 </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = '壱, 弐, 参, ...' ">
+ <xsl:text> \* DBNUM3 </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = '子, 丑, 寅, ...' ">
+ <xsl:text> \* ZODIAC2 </xsl:text>
+ </xsl:when>
+ <xsl:when test=" $field_number_format_style ='甲, 乙, 丙, ...' ">
+ <xsl:text> \* ZODIAC1 </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = 'イ, ロ, ハ, ...' or $field_number_format_style = 'イ, ロ, ハ, ...' ">
+ <xsl:text> \* Iroha </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style ='ア, イ, ウ, ...' or $field_number_format_style ='ア, イ, ウ, ...' ">
+ <xsl:text> \* Aiueo </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = '일, 이, 삼, ...' ">
+ <xsl:text> \* DBNUM1 </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style ='ㄱ, ㄴ, ㄷ, ...' or $field_number_format_style = '㉠, ㉡, ㉢, ...' ">
+ <xsl:text> \* Chosung </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = '가, 나, 다, ...' or $field_number_format_style = '㉮, ㉯, ㉰, ...' ">
+ <xsl:text> \* Ganada </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = 'ア, イ, ウ, ...' or $field_number_format_style = 'ア, イ, ウ, ...' ">
+ <xsl:text> \* Aiueo </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style ='a' ">
+ <xsl:text> \* alphabetic </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style ='A' ">
+ <xsl:text> \* ALPHABETIC </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = 'א, י, ק, ...' ">
+ <xsl:text> \* hebrew1 </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = 'א, ב, ג, ...' ">
+ <xsl:text> \* hebrew2 </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = 'أ, ب, ت, ...' ">
+ <xsl:text> \* ArabicAlpha </xsl:text>
+ </xsl:when>
+ <xsl:when test="$field_number_format_style = 'ก, ข, ฃ, ...' ">
+ <xsl:text> \* ThaiLetter </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="field_get_date_format">
+ <xsl:param name="field_date_stylename"/>
+ <xsl:param name="field_date_value"/>
+ <!-- this template return null date format ATM-->
+ <xsl:text/>
+ </xsl:template>
+ <xsl:template name="field_get_time_format">
+ <xsl:param name="field_time_stylename"/>
+ <xsl:param name="field_time_value"/>
+ <!-- this template return null date format ATM-->
+ <xsl:text/>
+ </xsl:template>
+ <xsl:template match="text:template-name">
+ <xsl:choose>
+ <xsl:when test="@text:display='title' or @text:display= 'area' ">
+ <!-- directly export the content -->
+ <w:r>
+ <w:rPr>
+ <w:noProof/>
+ </w:rPr>
+ <w:t>
+ <xsl:value-of select="."/>
+ </w:t>
+ </w:r>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:fldSimple>
+ <xsl:variable name="template_attribute_value">
+ <xsl:choose>
+ <xsl:when test="@text:display='name-and-extension' or @text:display= 'name' ">
+ <xsl:text> TEMPLATE </xsl:text>
+ </xsl:when>
+ <xsl:when test=" @text:display='full' or @text:display='path' ">
+ <xsl:text>TEMPLATE \p </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:text>\* MERGEFORMAT </xsl:text>
+ </xsl:variable>
+ <xsl:attribute name="w:instr">
+ <xsl:value-of select="$template_attribute_value"/>
+ </xsl:attribute>
+ <w:r>
+ <w:rPr>
+ <w:noProof/>
+ </w:rPr>
+ <w:t>
+ <xsl:value-of select="."/>
+ </w:t>
+ </w:r>
+ </w:fldSimple>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="text:text-input | text:variable-input | text:user-field-input">
+ <w:fldSimple>
+ <xsl:variable name="text-input-attribute">
+ <xsl:text>FILLIN </xsl:text>
+ <xsl:if test="@text:description">
+ <xsl:value-of select="@text:description"/>
+ </xsl:if>
+ <xsl:text> \* MERGEFORMAT</xsl:text>
+ </xsl:variable>
+ <xsl:attribute name="w:instr">
+ <xsl:value-of select="$text-input-attribute"/>
+ </xsl:attribute>
+ <w:r>
+ <w:rPr>
+ <w:noProof/>
+ </w:rPr>
+ <xsl:call-template name="field_convert_linebreak">
+ <xsl:with-param name="field_input_text" select="text()"/>
+ </xsl:call-template>
+ </w:r>
+ </w:fldSimple>
+ </xsl:template>
+ <xsl:template name="field_convert_linebreak">
+ <!-- this template convert the linebreak (&#x0A; and &#x0D;) in continuous text to Ms word element<w:br/> -->
+ <xsl:param name="field_input_text"/>
+ <xsl:if test="not (contains($field_input_text,'&#x0A;'))">
+ <w:t>
+ <xsl:value-of select="$field_input_text"/>
+ </w:t>
+ </xsl:if>
+ <xsl:if test="contains($field_input_text,'&#x0A;')">
+ <w:t>
+ <xsl:value-of select="translate(substring-before($field_input_text,'&#x0A;'),'&#x0D;','')"/>
+ </w:t>
+ <w:br/>
+ <xsl:call-template name="field_convert_linebreak">
+ <xsl:with-param name="field_input_text" select="substring-after($field_input_text,'&#x0A;')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="field_declare">
+ <!-- this template export the field declaration to w:docpr -->
+ <xsl:param name="simple_field_variable_declares"/>
+ <xsl:param name="user_field_variable_declares"/>
+ <xsl:param name="field_sequence_declares"/>
+ <w:docVars>
+ <xsl:if test="$simple_field_variable_declares/text:variable-decl">
+ <xsl:for-each select="$simple_field_variable_declares/text:variable-decl">
+ <w:docVar w:name="{@text:name}" w:val="default value"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="$user_field_variable_declares/text:user-field-decl">
+ <xsl:for-each select="$user_field_variable_declares/text:user-field-decl">
+ <w:docVar w:name="{@text:name}" w:val="{@text:string-value}"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="$field_sequence_declares/text:sequence-decl">
+ <!-- do nothing for sequence declares when exporting to MS word-->
+ </xsl:if>
+ </w:docVars>
+ </xsl:template>
+ <xsl:template match="text:reference-ref | text:bookmark-ref | text:footnote-ref
+ | text:endnote-ref ">
+ <!-- this template is for reference fields -->
+ <w:r>
+ <w:fldChar w:fldCharType="begin"/>
+ </w:r>
+ <xsl:variable name="complicate_field_instruction">
+ <xsl:choose>
+ <xsl:when test=" name() = 'text:reference-ref' ">
+ <xsl:choose>
+ <xsl:when test=" string(@text:reference-format) = 'page' ">
+ <xsl:value-of select="concat(' PAGEREF ', @text:ref-name, '\h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'chapter' ">
+ <xsl:value-of select="concat(' REF ', @text:ref-name, '\n \h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'text' ">
+ <xsl:value-of select="concat ( ' REF ' , @text:ref-name, ' \h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'direction' ">
+ <xsl:value-of select="concat(' REF ', @text:ref-name, ' \p \h' ) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat ( ' PAGEREF ', @text:ref-name, '\h')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name() = 'text:footnote-ref' or name() = 'text:endnote-ref' ">
+ <xsl:choose>
+ <xsl:when test=" string(@text:reference-format) = 'page' ">
+ <xsl:value-of select="concat(' PAGEREF ', @text:ref-name, '\h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'chapter' ">
+ <xsl:value-of select="concat(' REF ', @text:ref-name, '\n \h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'text' ">
+ <xsl:value-of select="concat ( ' NOTEREF ' , @text:ref-name, ' \h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'direction' ">
+ <xsl:value-of select="concat(' PAGEREF ', @text:ref-name, ' \p \h' ) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat ( ' PAGEREF ', @text:ref-name, '\h')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="name() = 'text:bookmark-ref' ">
+ <xsl:choose>
+ <xsl:when test=" string(@text:reference-format) = 'page' ">
+ <xsl:value-of select="concat(' PAGEREF ', @text:ref-name, '\h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'chapter' ">
+ <xsl:value-of select="concat(' PAGEREF ', @text:ref-name, ' \h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'text' ">
+ <xsl:value-of select="concat ( ' REF ' , @text:ref-name, ' \h') "/>
+ </xsl:when>
+ <xsl:when test="string(@text:reference-format) = 'direction' ">
+ <xsl:value-of select="concat(' REF ', @text:ref-name, ' \p \h' ) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat ( ' PAGEREF ', @text:ref-name, '\h')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <!--start to combine the complicate field instruction -->
+ <w:r>
+ <w:instrText>
+ <xsl:value-of select="$complicate_field_instruction"/>
+ </w:instrText>
+ </w:r>
+ <w:r>
+ <w:fldChar w:fldCharType="separate"/>
+ </w:r>
+ <w:r>
+ <w:rPr>
+ <w:noProof/>
+ </w:rPr>
+ <w:t>
+ <xsl:value-of select="."/>
+ </w:t>
+ </w:r>
+ <w:r>
+ <w:fldChar w:fldCharType="end"/>
+ </w:r>
+ </xsl:template>
+ <xsl:template match="text:chapter | text:sender-firstname | text:sender-lastname
+ | text:sender-street | text:sender-country | text:sender-postal-code
+ | text:sender-city | text:sender-title | text:sender-position
+ | text:sender-phone-private | text:sender-email | text:sender-fax
+ | text:sender-state-or-province | text:table-count | text:image-count
+ | text:object-count | text:printed-by | text:hidden-paragraph
+ | text:placeholder | text:drop-down | text:conditional-text
+ | text:variable-set | text:table-formula | text:database-display
+ | text:database-next | text:database-select | text:database-row-number
+ | text:sequence-ref | text:expression | text:sheet-name | text:dde-connection">
+ <!-- this template just export content of staroffice fields that do not have the corresponding fields in MS word ATM -->
+ <w:r>
+ <w:rPr>
+ <w:noProof/>
+ </w:rPr>
+ <w:t>
+ <xsl:value-of select="."/>
+ </w:t>
+ </w:r>
+ </xsl:template>
+ <xsl:template match="text:execute-macro | text:variable-decls | text:variable-decl | text:user-field-decls | text:variable-decl | text:sequence-decls | text:sequence-decl | text:page-variable-set | text:bibliography-mark | text:script | text:page-continuation ">
+ <!-- this template is to ignore matched elements when exporting writer to word -->
+ </xsl:template>
+ <xsl:template match="text:a ">
+ <xsl:call-template name="export_hyoerlink"/>
+ </xsl:template>
+ <xsl:template name="export_hyoerlink">
+ <!-- all params are used by draw -->
+ <xsl:param name="TargetMeasure"/>
+ <xsl:param name="x-adjust"/>
+ <xsl:param name="y-adjust"/>
+ <xsl:param name="force-draw"/>
+ <!-- this template processes the hyperlink in writer -->
+ <xsl:variable name="hyperlink_filename">
+ <xsl:choose>
+ <xsl:when test="contains(@xlink:href, '#')">
+ <xsl:value-of select="substring-before(@xlink:href, '#')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@xlink:href"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="hyperlink_bookmark">
+ <xsl:if test="contains(@xlink:href, '#')">
+ <xsl:choose>
+ <xsl:when test="contains(@xlink:href, '%7C')">
+ <xsl:call-template name="translate_string">
+ <xsl:with-param name="t_input_string" select="substring-before( substring-after(@xlink:href, '#'), '%7C')"/>
+ <xsl:with-param name="t_pattern_string" select=" '%20' "/>
+ <xsl:with-param name="t_substitute_string" select=" ' ' "/>
+ <xsl:with-param name="t_output_string" select=" '' "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="translate_string">
+ <xsl:with-param name="t_input_string" select="substring-after(@xlink:href, '#')"/>
+ <xsl:with-param name="t_pattern_string" select=" '%20' "/>
+ <xsl:with-param name="t_substitute_string" select=" ' ' "/>
+ <xsl:with-param name="t_output_string" select=" '' "/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:variable>
+ <w:hlink>
+ <xsl:if test="@xlink:href">
+ <xsl:attribute name="w:dest">
+ <xsl:value-of select="$hyperlink_filename"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains(@xlink:href, '#')">
+ <xsl:attribute name="w:bookmark">
+ <xsl:value-of select="$hyperlink_bookmark"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@office:target-frame-name">
+ <xsl:attribute name="w:target">
+ <xsl:value-of select="@office:target-frame-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@office:name">
+ <xsl:attribute name="w:screenTip">
+ <xsl:value-of select="@office:name"/>
+ </xsl:attribute>
+ </xsl:if>
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="Hyperlink"/>
+ </w:rPr>
+ <!--apply inline-text-elements, many many many ... -->
+ <xsl:apply-templates select="text:a | text:span | text() | text:hidden-text
+ | text:line-break | text:tab-stop | text:s | text:page-number | text:page-count | text:subject
+ | text:initial-creator | text:title | text:date | text:time | text:author-name
+ | text:author-initials | text:chapter | text:file-name | text:sender-company
+ | text:sender-firstname | text:sender-lastname | text:sender-initials | text:sender-street
+ | text:sender-country | text:sender-postal-code | text:sender-city | text:sender-title
+ | text:sender-position | text:sender-phone-private | text:sender-phone-work
+ | text:sender-email | text:sender-fax | text:sender-state-or-province | text:word-count
+ | text:paragraph-count | text:character-count | text:table-count | text:image-count
+ | text:object-count | text:template-name | text:description | text:creation-time
+ | text:creation-date | text:editing-cycles | text:editing-duration | text:keywords
+ | text:print-time | text:print-date | text:creator | text:modification-time
+ | text:modification-date | text:user-defined | text:printed-by | text:hidden-paragraph
+ | text:placeholder | text:drop-down | text:conditional-text | text:text-input
+ | text:execute-macro | text:variable-set | text:variable-input
+ | text:user-field-input | text:variable-get | text:user-field-get | text:sequence
+ | text:page-variable-set | text:page-variable-get | text:table-formula
+ | text:database-display | text:database-next| text:database-select
+ | text:database-row-number | text:database-name | text:reference-ref
+ | text:bookmark-ref | text:footnote-ref | text:endnote-ref | text:sequence-ref
+ | text:expression | text:measure | text:dde-connection | text:sheet-name
+ | text:bibliography-mark | text:script | text:page-continuation | office:annotation
+ | draw:*">
+ <xsl:with-param name="TargetMeasure" select="$TargetMeasure"/>
+ <xsl:with-param name="x-adjust" select="$x-adjust"/>
+ <xsl:with-param name="y-adjust" select="$y-adjust"/>
+ <xsl:with-param name="force-draw" select="$force-draw"/>
+ </xsl:apply-templates>
+ </w:r>
+ </w:hlink>
+ </xsl:template>
+ <xsl:template name="translate_string">
+ <!-- this template is to replace the substring matched t_pattern_string in t_t_input_string with t_substitute_string G.Y.-->
+ <xsl:param name="t_input_string"/>
+ <xsl:param name="t_pattern_string"/>
+ <xsl:param name="t_substitute_string"/>
+ <xsl:param name="t_output_string"/>
+ <xsl:variable name="t_temp_output_string">
+ <xsl:if test="contains($t_input_string, $t_pattern_string) ">
+ <xsl:value-of select="concat($t_output_string, substring-before($t_input_string,$t_pattern_string), $t_substitute_string) "/>
+ </xsl:if>
+ <xsl:if test="not (contains($t_input_string, $t_pattern_string)) ">
+ <xsl:value-of select="$t_output_string"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:if test="contains($t_input_string, $t_pattern_string) ">
+ <xsl:call-template name="translate_string">
+ <xsl:with-param name="t_input_string" select="substring-after($t_input_string,$t_pattern_string)"/>
+ <xsl:with-param name="t_pattern_string" select="$t_pattern_string"/>
+ <xsl:with-param name="t_substitute_string" select="$t_substitute_string"/>
+ <xsl:with-param name="t_output_string" select="$t_temp_output_string"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not (contains($t_input_string, $t_pattern_string))">
+ <xsl:value-of select="concat($t_temp_output_string, $t_input_string)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="add_hyperlink_style">
+ <!--this template is to add the hyperlink related style -->
+ <w:style w:type="character" w:styleId="Hyperlink">
+ <w:name w:val="Hyperlink"/>
+ <w:rsid w:val="006A55B0"/>
+ <w:rPr>
+ <w:color w:val="000080"/>
+ <w:u w:val="single"/>
+ </w:rPr>
+ </w:style>
+ <w:style w:type="character" w:styleId="FollowedHyperlink">
+ <w:name w:val="FollowedHyperlink"/>
+ <w:rsid w:val="006A55B0"/>
+ <w:rPr>
+ <w:color w:val="800000"/>
+ <w:u w:val="single"/>
+ </w:rPr>
+ </w:style>
+ </xsl:template>
+ <xsl:template match="office:annotation">
+ <!-- this template export writer note to word comments -->
+ <xsl:variable name="comments_aml_id">
+ <xsl:call-template name="unique_amlid_generator"/>
+ </xsl:variable>
+ <aml:annotation w:type="Word.Comment.Start">
+ <xsl:attribute name="aml:id">
+ <xsl:value-of select="$comments_aml_id"/>
+ </xsl:attribute>
+ </aml:annotation>
+ <aml:annotation w:type="Word.Comment.End">
+ <xsl:attribute name="aml:id">
+ <xsl:value-of select="$comments_aml_id"/>
+ </xsl:attribute>
+ </aml:annotation>
+ <!-- export aml:annotation content-->
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="CommentReference"/>
+ </w:rPr>
+ <aml:annotation aml:author="{@office:author}" aml:createdate="{@office:create-date}" w:type="Word.Comment" w:initials="{@office:author}">
+ <xsl:attribute name="aml:id">
+ <xsl:value-of select="$comments_aml_id"/>
+ </xsl:attribute>
+ <aml:content>
+ <xsl:apply-templates select="text:p"/>
+ </aml:content>
+ </aml:annotation>
+ </w:r>
+ <!-- end of export aml:annotation content-->
+ </xsl:template>
+ <xsl:template name="unique_amlid_generator">
+ <!-- this template generate unique id for aml:id, ATM it only counts the office:annotation, some other elements might be added later -->
+ <xsl:number count="office:annotation" from="/office:document/office:body" level="any" format="1"/>
+ </xsl:template>
+ <xsl:template name="add_comments_style">
+ <w:style w:type="character" w:styleId="CommentReference">
+ <w:name w:val="annotation reference"/>
+ <w:basedOn w:val="DefaultParagraphFont"/>
+ <w:semiHidden/>
+ <w:rsid w:val="007770B7"/>
+ <w:rPr>
+ <w:sz w:val="16"/>
+ <w:sz-cs w:val="16"/>
+ </w:rPr>
+ </w:style>
+ <w:style w:type="paragraph" w:styleId="CommentText">
+ <w:name w:val="annotation text"/>
+ <w:basedOn w:val="Normal"/>
+ <w:semiHidden/>
+ <w:rsid w:val="007770B7"/>
+ <w:pPr>
+ <w:pStyle w:val="CommentText"/>
+ </w:pPr>
+ <w:rPr>
+ <w:sz w:val="20"/>
+ <w:sz-cs w:val="20"/>
+ </w:rPr>
+ </w:style>
+ <w:style w:type="paragraph" w:styleId="CommentSubject">
+ <w:name w:val="annotation subject"/>
+ <w:basedOn w:val="CommentText"/>
+ <w:next w:val="CommentText"/>
+ <w:semiHidden/>
+ <w:rsid w:val="007770B7"/>
+ <w:pPr>
+ <w:pStyle w:val="CommentSubject"/>
+ </w:pPr>
+ <w:rPr>
+ <w:b/>
+ <w:b-cs/>
+ </w:rPr>
+ </w:style>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_list.xsl b/filter/source/xslt/export/wordml/ooo2wordml_list.xsl
new file mode 100644
index 000000000..5ebf0e6ac
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_list.xsl
@@ -0,0 +1,349 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:template name="ListStyles">
+ <w:lists>
+ <xsl:if test="descendant::text:list-level-style-image">
+ <xsl:call-template name="PicLists"/>
+ </xsl:if>
+ <xsl:apply-templates select="office:styles/text:outline-style | office:styles/text:list-style | office:automatic-styles/text:list-style" mode="style"/>
+ <xsl:for-each select="office:styles/text:outline-style | office:styles/text:list-style | office:automatic-styles/text:list-style">
+ <w:list w:ilfo="{position()}">
+ <w:ilst w:val="{position()-1}"/>
+ </w:list>
+ </xsl:for-each>
+ </w:lists>
+ </xsl:template>
+ <xsl:template match="text:list-style | text:outline-style" mode="style">
+ <w:listDef w:listDefId="{position()-1}">
+ <xsl:if test="name(..)='office:styles' and name()!='text:outline-style'">
+ <w:styleLink w:val="{@style:name}"/>
+ </xsl:if>
+ <xsl:for-each select="text:list-level-style-number | text:list-level-style-bullet | text:list-level-style-image | text:outline-level-style">
+ <xsl:if test="@text:level &lt; 10">
+ <w:lvl w:ilvl="{ @text:level - 1 }">
+ <xsl:if test="name()='text:outline-level-style'">
+ <xsl:variable name="headinglevel">
+ <xsl:value-of select="@text:level"/>
+ </xsl:variable>
+ <xsl:if test="/office:document/office:body//text:h[@text:level=$headinglevel and @text:style-name]">
+ <xsl:element name="w:pStyle">
+ <xsl:attribute name="w:val"><xsl:value-of select="/office:document/office:body//text:h[@text:level=$headinglevel]/@text:style-name"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@text:start-value">
+ <w:start w:val="{@text:start-value}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:start w:val="1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@text:bullet-char">
+ <w:nfc w:val="23"/>
+ </xsl:when>
+ <xsl:when test="@style:num-format">
+ <xsl:call-template name="convert_list_number">
+ <xsl:with-param name="number-format" select="@style:num-format"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="name()='text:list-level-style-image'">
+ <w:lvlText w:val="."/>
+ <w:lvlPicBulletId>
+ <xsl:attribute name="w:val"><xsl:value-of select="count(preceding::text:list-level-style-image)"/></xsl:attribute>
+ </w:lvlPicBulletId>
+ </xsl:when>
+ <xsl:when test="@text:bullet-char">
+ <w:lvlText w:val="{@text:bullet-char}"/>
+ </xsl:when>
+ <xsl:when test="@text:display-levels and not(../@text:consecutive-numbering='true')">
+ <xsl:variable name="levelText">
+ <xsl:call-template name="displaylevel">
+ <xsl:with-param name="number" select="@text:display-levels"/>
+ <xsl:with-param name="textlevel" select="@text:level"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <w:lvlText w:val="{concat(@style:num-prefix, substring-after($levelText, '.'), @style:num-suffix)}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:lvlText w:val="{concat(@style:num-prefix, '%', @text:level, @style:num-suffix)}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="style:list-level-properties/@fo:text-align = 'end'">
+ <w:lvlJc w:val="right"/>
+ </xsl:when>
+ <xsl:when test="style:list-level-properties/@fo:text-align = 'center'">
+ <w:lvlJc w:val="center"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:lvlJc w:val="left"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="style:list-level-properties/@text:space-before | style:list-level-properties/@text:min-label-width | style:list-level-properties/@text:min-label-distance">
+ <xsl:call-template name="list_position"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:suff w:val="Nothing"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates select="key('text-style',@text:style-name)/style:text-properties" mode="character"/>
+ <xsl:apply-templates select="style:text-properties" mode="character"/>
+ </w:lvl>
+ </xsl:if>
+ </xsl:for-each>
+ </w:listDef>
+ </xsl:template>
+ <xsl:template match="text:list-style" mode="count">
+ <xsl:value-of select="count(preceding::text:list-style | preceding::text:outline-style)+1"/>
+ </xsl:template>
+ <xsl:template match="text:unordered-list | text:ordered-list | text:list">
+ <xsl:apply-templates select="text:unordered-list | text:ordered-list | text:list-item | text:list-header | text:list"/>
+ </xsl:template>
+ <xsl:template match="text:list-item | text:list-header">
+ <xsl:apply-templates select="text:unordered-list | text:ordered-list | text:list | text:p | text:h"/>
+ </xsl:template>
+ <xsl:template name="displaylevel">
+ <xsl:param name="number"/>
+ <xsl:param name="textlevel"/>
+ <xsl:if test="$number &gt; 1">
+ <xsl:call-template name="displaylevel">
+ <xsl:with-param name="number" select="$number -1"/>
+ <xsl:with-param name="textlevel" select="number($textlevel)-1"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:value-of select="concat('.','%',$textlevel)"/>
+ </xsl:template>
+ <xsl:template name="list_position">
+ <xsl:variable name="spacebefore">
+ <xsl:choose>
+ <xsl:when test="style:list-level-properties/@text:space-before">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:list-level-properties/@text:space-before"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="space2text">
+ <xsl:choose>
+ <xsl:when test="style:list-level-properties/@text:min-label-width">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:list-level-properties/@text:min-label-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="spacedistance">
+ <xsl:choose>
+ <xsl:when test="style:list-level-properties/@text:min-label-distance">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:list-level-properties/@text:min-label-distance"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$spacedistance='0' and $space2text='0'">
+ <w:suff w:val="Nothing"/>
+ </xsl:if>
+ <w:pPr>
+ <xsl:if test="$spacedistance!='0' or $space2text!='0'">
+ <w:tabs>
+ <w:tab>
+ <xsl:attribute name="w:val">list</xsl:attribute>
+ <xsl:attribute name="w:pos"><xsl:choose><xsl:when test="number($spacedistance) &gt; number($space2text)"><xsl:value-of select="number($spacebefore)+number($spacedistance)+150"/></xsl:when><xsl:otherwise><xsl:value-of select="number($spacebefore)+number($space2text)+150"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <!-- Since SO MinSpaceDistance is width after number or bullet, MS TabSpaceAfter include the number or bullet width. So +150 -->
+ </w:tab>
+ </w:tabs>
+ </xsl:if>
+ <w:ind w:left="{number($space2text)+number($spacebefore)}" w:hanging="{$space2text}"/>
+ <!-- w:pos(MS TabSpaceAfter) = text:space-before + MAX(text:min-label-distance,text:min-label-width) + ( Symbol width ); w:left(MS IndentAt)= text:space-before + text:min-label-width; w:hanging(MS IndentAt - MS AlignedAt)=text:min-label-width -->
+ </w:pPr>
+ </xsl:template>
+ <xsl:template name="PicLists">
+ <xsl:for-each select="descendant::text:list-level-style-image">
+ <w:listPicBullet w:listPicBulletId="{position()-1}">
+ <w:pict>
+ <v:shape>
+ <xsl:variable name="Picwidth">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="style:list-level-properties/@fo:width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="Picheight">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="style:list-level-properties/@fo:height"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style"><xsl:value-of select="concat('width:', number($Picwidth*1), 'pt;height:', number($Picheight*1), 'pt')"/></xsl:attribute>
+ <xsl:attribute name="o:bullet">t</xsl:attribute>
+ <v:stroke joinstyle="miter"/>
+ <w:binData w:name="{concat('wordml://SOpicbullet', position(), '.gif')}">
+ <xsl:value-of select="office:binary-data"/>
+ </w:binData>
+ <v:imagedata src="{concat('wordml://SOpicbullet', position(), '.gif')}" o:title="{concat('SOpicbullet', position())}"/>
+ </v:shape>
+ </w:pict>
+ </w:listPicBullet>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="convert_list_number">
+ <xsl:param name="number-format"/>
+ <xsl:choose>
+ <xsl:when test="$number-format = 'a'">
+ <!-- nfcLCLetter: Lowercase alpha -->
+ <w:nfc w:val="4"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'A'">
+ <!-- nfcUCLetter: Uppercase alpha -->
+ <w:nfc w:val="3"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'i'">
+ <!-- nfcLCRoman: Lowercase roman -->
+ <w:nfc w:val="2"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'I'">
+ <!-- nfcUCRoman: Uppercase roman -->
+ <w:nfc w:val="1"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '1st'">
+ <!-- nfcUCOrdinal: Ordinal indicator -->
+ <w:nfc w:val="5"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'One'">
+ <!-- nfcCardText: Cardinal -->
+ <w:nfc w:val="6"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'First'">
+ <!-- nfcOrdText: Ordinal -->
+ <w:nfc w:val="7"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '1, 2, 3, ...'">
+ <!-- '1, 2, 3, ...' also seems: decimal-full-width2 -->
+ <w:nfc w:val="14"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '①, ②, ③, ...'">
+ <w:nfc w:val="18"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '一, 二, 三, ...'">
+ <!-- '一, 二, 三, ...' also seems: ideograph-digital, japanese-counting, japanese-digital-ten-thousand,
+ taiwanese-counting, taiwanese-counting-thousand, taiwanese-digital, chinese-counting, korean-digital2 -->
+ <w:nfc w:val="10"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '壹, 贰, 叁, ...'">
+ <w:nfc w:val="38"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '壹, 貳, 參, ...'">
+ <w:nfc w:val="34"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '甲, 乙, 丙, ...'">
+ <w:nfc w:val="30"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '子, 丑, 寅, ...'">
+ <w:nfc w:val="31"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '壱, 弐, 参, ...'">
+ <w:nfc w:val="16"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ア, イ, ウ, ...'">
+ <w:nfc w:val="12"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ア, イ, ウ, ...'">
+ <w:nfc w:val="20"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'イ, ロ, ハ, ...'">
+ <w:nfc w:val="13"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'イ, ロ, ハ, ...'">
+ <w:nfc w:val="21"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '일, 이, 삼, ...'">
+ <w:nfc w:val="42"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '하나, 둘, 셋, ...'">
+ <w:nfc w:val="43"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ㄱ, ㄴ, ㄷ, ...' or $number-format = '㉠, ㉡, ㉢, ...'">
+ <!-- mapping circled to uncircled -->
+ <w:nfc w:val="25"/>
+ </xsl:when>
+ <xsl:when test='$number-format = "가, 나, 다, ..." or $number-format = "㉮, ㉯, ㉰, ..."'>
+ <!-- mapping circled to uncircled -->
+ <w:nfc w:val="24"/>
+ </xsl:when>
+ <xsl:when test="$number-format ='أ, ب, ت, ...'">
+ <!-- 46. arabic-alpha-->
+ <w:nfc w:val="46"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ก, ข, ฃ, ...'">
+ <!--53. thai-letters not match well !-->
+ <w:nfc w:val="53"/>
+ </xsl:when>
+ <xsl:when test="$number-format='א, י, ק, ...'">
+ <!--45. hebrew-1-->
+ <w:nfc w:val="45"/>
+ </xsl:when>
+ <xsl:when test="$number-format='א, ב, ג, ...'">
+ <!--47. hebrew-2-->
+ <w:nfc w:val="47"/>
+ </xsl:when>
+ <xsl:when test="string-length($number-format)=0">
+ <w:nfc w:val="255"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'Native Numbering'">
+ <xsl:variable name="locale" select="/office:document/office:meta/dc:language"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($locale, 'th-')">
+ <!-- for Thai, mapping thai-numbers, thai-counting to thai-numbers -->
+ <w:nfc w:val="54"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'hi-')">
+ <!-- for Hindi, mapping hindi-vowels, hindi-consonants, hindi-counting to hindi-numbers -->
+ <w:nfc w:val="51"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'ar-')">
+ <!-- for Arabic, mapping arabic-abjad to arabic-alpha -->
+ <w:nfc w:val="45"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'he-')">
+ <!-- for Hebrew, mapping hebrew-2 to -->
+ <w:nfc w:val="46"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'ru-')">
+ <!-- for Russian, mapping russian-upper to russian-lower -->
+ <w:nfc w:val="58"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'vi-')">
+ <!-- for Vietnamese -->
+ <w:nfc w:val="56"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <!-- unsupported: hex, chicago, bullet, ideograph-zodiac-traditional,
+ chinese-not-impl, korean-legal, none -->
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_page.xsl b/filter/source/xslt/export/wordml/ooo2wordml_page.xsl
new file mode 100644
index 000000000..d32874e23
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_page.xsl
@@ -0,0 +1,392 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:template name="page-background">
+ <xsl:choose>
+ <xsl:when test="/office:document/office:automatic-styles/style:page-layout/style:page-layout-properties/style:background-image[string-length(office:binary-data/text()) &gt; 0]">
+ <w:bgPict>
+ <xsl:apply-templates select="/office:document/office:automatic-styles/style:page-layout/style:page-layout-properties/style:background-image[string-length(office:binary-data/text()) &gt; 0]" mode="bgPict"/>
+ </w:bgPict>
+ </xsl:when>
+ <xsl:when test="/office:document/office:automatic-styles/style:page-layout/style:page-layout-properties[string-length(@fo:background-color) &gt; 0]">
+ <w:bgPict>
+ <xsl:apply-templates select="/office:document/office:automatic-styles/style:page-layout/style:page-layout-properties[string-length(@fo:background-color) &gt; 0]" mode="bgPict"/>
+ </w:bgPict>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="style:background-image" mode="bgPict">
+ <xsl:variable name="binName" select="concat('wordml://',generate-id(.))"/>
+ <w:binData w:name="{$binName}">
+ <xsl:value-of select="translate(office:binary-data/text(),'&#9;&#10;&#13;&#32;','' ) "/>
+ </w:binData>
+ <w:background w:bgcolor="{parent::style:page-layout-properties/@fo:background-color}" w:background="{$binName}"/>
+ </xsl:template>
+ <xsl:template match="style:page-layout-properties" mode="bgPict">
+ <w:background w:bgcolor="{@fo:background-color}"/>
+ </xsl:template>
+ <xsl:template match="style:master-page">
+ <xsl:apply-templates select="key( 'page-layout', @style:page-layout-name)"/>
+ <xsl:if test="style:header">
+ <w:hdr w:type="odd">
+ <xsl:apply-templates select="style:header/text:p | style:header/table:table"/>
+ <!-- change style:header//text:p to style:header/text:p and add table:table here, fix for Issue 32035 -->
+ </w:hdr>
+ </xsl:if>
+ <xsl:if test="style:header-left">
+ <w:hdr w:type="even">
+ <xsl:apply-templates select="style:header-left/text:p | style:header-left/table:table"/>
+ <!-- change style:header//text:p to style:header/text:p and add table:table here, fix for Issue 32035 -->
+ </w:hdr>
+ </xsl:if>
+ <xsl:if test="style:footer">
+ <w:ftr w:type="odd">
+ <xsl:apply-templates select="style:footer/text:p | style:footer/table:table"/>
+ <!-- change style:header//text:p to style:header/text:p and add table:table here, fix for Issue 32035 -->
+ </w:ftr>
+ </xsl:if>
+ <xsl:if test="style:footer-left">
+ <w:ftr w:type="even">
+ <xsl:apply-templates select="style:footer-left/text:p | style:footer-left/table:table"/>
+ <!-- change style:header//text:p to style:header/text:p and add table:table here, fix for Issue 32035 -->
+ </w:ftr>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="style:page-layout">
+ <xsl:choose>
+ <xsl:when test="@style:page-usage = 'left'">
+ <w:type w:val="even-page"/>
+ </xsl:when>
+ <xsl:when test="@style:page-usage = 'right'">
+ <w:type w:val="odd-page"/>
+ </xsl:when>
+ <xsl:when test="@style:page-usage = 'all'">
+ <w:type w:val="next-page"/>
+ </xsl:when>
+ <!-- for mirrored, and default -->
+ <xsl:otherwise>
+ <w:type w:val="next-page"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:variable name="page-width">
+ <xsl:if test="style:page-layout-properties/@fo:page-width">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:page-layout-properties/@fo:page-width"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="margin-left">
+ <xsl:if test="style:page-layout-properties/@fo:margin-left">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:page-layout-properties/@fo:margin-left"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="margin-right">
+ <xsl:if test="style:page-layout-properties/@fo:margin-right">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:page-layout-properties/@fo:margin-right"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <w:pgSz>
+ <xsl:if test="style:page-layout-properties/@fo:page-width">
+ <xsl:attribute name="w:w">
+ <xsl:value-of select="$page-width"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@fo:page-height">
+ <xsl:attribute name="w:h">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:page-layout-properties/@fo:page-height"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@style:print-orientation">
+ <xsl:attribute name="w:orient">
+ <xsl:value-of select="style:page-layout-properties/@style:print-orientation"/>
+ </xsl:attribute>
+ </xsl:if>
+ </w:pgSz>
+ <w:pgMar>
+ <xsl:if test="style:page-layout-properties/@fo:margin-top">
+ <xsl:variable name="top-margin">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:page-layout-properties/@fo:margin-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:top">
+ <xsl:value-of select="$top-margin"/>
+ </xsl:attribute>
+ <xsl:if test="style:header-style/style:page-layout-properties/@fo:min-height">
+ <xsl:variable name="header-height">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:header-style/style:page-layout-properties/@fo:min-height"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:header">
+ <xsl:value-of select="$top-margin - $header-height"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@fo:margin-bottom">
+ <xsl:variable name="bottom-margin">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:page-layout-properties/@fo:margin-bottom"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:bottom">
+ <xsl:value-of select="$bottom-margin"/>
+ </xsl:attribute>
+ <xsl:if test="style:footer-style/style:page-layout-properties/@fo:min-height">
+ <xsl:variable name="footer-height">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="style:footer-style/style:page-layout-properties/@fo:min-height"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:footer">
+ <xsl:value-of select="$bottom-margin - $footer-height"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@fo:margin-left">
+ <xsl:attribute name="w:left">
+ <xsl:value-of select="$margin-left"/>
+ </xsl:attribute>
+ <xsl:attribute name="w:gutter">
+ <xsl:value-of select="'0'"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:page-layout-properties/@fo:margin-right">
+ <xsl:attribute name="w:right">
+ <xsl:value-of select="$margin-right"/>
+ </xsl:attribute>
+ </xsl:if>
+ </w:pgMar>
+ <xsl:variable name="border-top" select="style:page-layout-properties/@fo:border-top | style:page-layout-properties/@fo:border"/>
+ <xsl:variable name="border-bottom" select="style:page-layout-properties/@fo:border-bottom | style:page-layout-properties/@fo:border"/>
+ <xsl:variable name="border-left" select="style:page-layout-properties/@fo:border-left | style:page-layout-properties/@fo:border"/>
+ <xsl:variable name="border-right" select="style:page-layout-properties/@fo:border-right | style:page-layout-properties/@fo:border"/>
+ <xsl:variable name="border-line-width-top" select="style:page-layout-properties/@style:border-line-width-top | style:page-layout-properties/@style:border-line-width "/>
+ <xsl:variable name="border-line-width-bottom" select="style:page-layout-properties/@style:border-line-width-bottom | style:page-layout-properties/@style:border-line-width"/>
+ <xsl:variable name="border-line-width-left" select="style:page-layout-properties/@style:border-line-width-left | style:page-layout-properties/@style:border-line-width"/>
+ <xsl:variable name="border-line-width-right" select="style:page-layout-properties/@style:border-line-width-right | style:page-layout-properties/@style:border-line-width"/>
+ <xsl:variable name="padding-top" select="style:page-layout-properties/@fo:padding-top | style:page-layout-properties/@fo:padding"/>
+ <xsl:variable name="padding-bottom" select="style:page-layout-properties/@fo:padding-bottom | style:page-layout-properties/@fo:padding"/>
+ <xsl:variable name="padding-left" select="style:page-layout-properties/@fo:padding-left | style:page-layout-properties/@fo:padding"/>
+ <xsl:variable name="padding-right" select="style:page-layout-properties/@fo:padding-right | style:page-layout-properties/@fo:padding"/>
+ <w:pgBorders w:offset-from="text">
+ <xsl:if test="$border-top">
+ <xsl:element name="w:top">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-top"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-top"/>
+ <xsl:with-param name="so-border-position" select=" 'top' "/>
+ </xsl:call-template>
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$padding-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="style:page-layout-properties/@style:shadow!='none'">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-bottom">
+ <xsl:element name="w:bottom">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-bottom"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-bottom"/>
+ <xsl:with-param name="so-border-position" select=" 'bottom' "/>
+ </xsl:call-template>
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$padding-bottom"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="style:page-layout-properties/@style:shadow!='none'">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-left">
+ <xsl:element name="w:left">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-left"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-left"/>
+ <xsl:with-param name="so-border-position" select=" 'left' "/>
+ </xsl:call-template>
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$padding-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="style:page-layout-properties/@style:shadow!='none'">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-right">
+ <xsl:element name="w:right">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-right"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-right"/>
+ <xsl:with-param name="so-border-position" select=" 'right' "/>
+ </xsl:call-template>
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$padding-right"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="style:page-layout-properties/@style:shadow!='none'">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </w:pgBorders>
+ <xsl:variable name="valid-width">
+ <xsl:value-of select="$page-width - $margin-left - $margin-right"/>
+ </xsl:variable>
+ <xsl:apply-templates select="style:page-layout-properties/style:columns">
+ <xsl:with-param name="page-width" select="$valid-width"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="/office:document/office:styles/text:linenumbering-configuration"/>
+ </xsl:template>
+ <xsl:template match="text:linenumbering-configuration">
+ <xsl:if test="not(@text:number-lines = 'false')">
+ <xsl:element name="w:lnNumType">
+ <xsl:if test="@text:increment">
+ <xsl:attribute name="w:count-by">
+ <xsl:value-of select="@text:increment"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@text:offset">
+ <xsl:attribute name="w:distance">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@text:offset"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="w:restart">continuous</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="style:style" mode="section">
+ <xsl:param name="master-page"/>
+ <xsl:variable name="page-width">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$master-page/style:page-layout-properties/@fo:page-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="margin-left">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$master-page/style:page-layout-properties/@fo:margin-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="margin-right">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$master-page/style:page-layout-properties/@fo:margin-right"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="valid-width">
+ <xsl:value-of select="$page-width - $margin-left - $margin-right"/>
+ </xsl:variable>
+ <w:type w:val="continuous"/>
+ <xsl:apply-templates select="style:section-properties/style:columns">
+ <xsl:with-param name="page-width" select="$valid-width"/>
+ </xsl:apply-templates>
+ </xsl:template>
+ <xsl:template match="style:columns">
+ <xsl:param name="page-width"/>
+ <w:cols w:num="{@fo:column-count}">
+ <xsl:if test="@fo:column-gap">
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:column-gap"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="style:column-sep">
+ <xsl:attribute name="w:sep">on</xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="not(style:column)">
+ <xsl:attribute name="w:equalWidth">on</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:equalWidth">off</xsl:attribute>
+ <xsl:variable name="column-relative-width">
+ <xsl:call-template name="get-sum-column-width">
+ <xsl:with-param name="current-column" select="style:column[1]"/>
+ <xsl:with-param name="current-width" select="'0'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:for-each select="style:column">
+ <xsl:element name="w:col">
+ <xsl:attribute name="w:w">
+ <xsl:value-of select="floor(substring-before(@style:rel-width,'*') * $page-width div $column-relative-width)"/>
+ </xsl:attribute>
+ <xsl:if test="@fo:margin-right">
+ <xsl:variable name="margin-right">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:margin-right"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="following-sibling::style:column">
+ <xsl:variable name="margin-left">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:margin-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:space">
+ <xsl:value-of select="$margin-right + $margin-left"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:space">
+ <xsl:value-of select="$margin-right"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:cols>
+ </xsl:template>
+ <xsl:template name="get-sum-column-width">
+ <xsl:param name="current-column"/>
+ <xsl:param name="current-width"/>
+ <xsl:variable name="new-width" select="$current-width + substring-before($current-column/@style:rel-width,'*')"/>
+ <xsl:choose>
+ <xsl:when test="$current-column/following-sibling::style:column">
+ <xsl:call-template name="get-sum-column-width">
+ <xsl:with-param name="current-column" select="$current-column/following-sibling::style:column[1]"/>
+ <xsl:with-param name="current-width" select="$new-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$new-width"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_path.xsl b/filter/source/xslt/export/wordml/ooo2wordml_path.xsl
new file mode 100644
index 000000000..5eafe99ae
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_path.xsl
@@ -0,0 +1,849 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:include href="../../common/math.xsl"/>
+ <xsl:template name="test-arc">
+ <xsl:call-template name="svg-arc2vml-arc">
+ <!-- M 125,75 a100,50 0 ?,? 100,50 -->
+ <xsl:with-param name="x0" select="125"/>
+ <xsl:with-param name="y0" select="75"/>
+ <xsl:with-param name="rx" select="100"/>
+ <xsl:with-param name="ry" select="50"/>
+ <xsl:with-param name="x-axis-rotation" select="0"/>
+ <xsl:with-param name="large-arc-flag" select="0"/>
+ <xsl:with-param name="sweep-flag" select="0"/>
+ <xsl:with-param name="x" select="225"/>
+ <xsl:with-param name="y" select="125"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="test">
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="'M 36.0 162.0 C 38.0 168.0 39.0-172.0 40.0 176.0 S 42.0 184.0 144.0 188.0'"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="svgpath2vmlpath">
+ <xsl:param name="svg-path"/>
+ <xsl:param name="vml-path" select="''"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="last-command" select="'M'"/>
+ <xsl:param name="current-x" select="'0'"/>
+ <xsl:param name="current-y" select="'0'"/>
+ <xsl:variable name="command-and-newpos">
+ <xsl:call-template name="get-path-command">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="last-command" select="$last-command"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="command" select="substring-before($command-and-newpos , ':')"/>
+ <xsl:variable name="newpos" select="substring-after($command-and-newpos , ':')"/>
+ <xsl:choose>
+ <xsl:when test="$command = 'M' ">
+ <!-- absolute moveto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' m ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="'L'"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'm' ">
+ <!-- relative moveto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' t ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="'l'"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x"/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'L' ">
+ <!-- absolute lineto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'l' ">
+ <!-- relative lineto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' r ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'H' ">
+ <!-- absolute horizontal lineto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $num-and-pos , ':') , ' ' , $current-y , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( $num-and-pos , ':') "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'h' ">
+ <!-- relative horizontal lineto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $num-and-pos , ':') + $current-x , ' ' , $current-y , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( $num-and-pos , ':') + $current-x"/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'V' ">
+ <!-- absolute vertical lineto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , $current-x , ' ' , substring-before( $num-and-pos , ':') , ' ' ) "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x"/>
+ <xsl:with-param name="current-y" select=" substring-before( $num-and-pos , ':') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'v' ">
+ <!-- relative horizontal lineto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , $current-x , ' ' , substring-before( $num-and-pos , ':') + $current-y , ' ' ) "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x"/>
+ <xsl:with-param name="current-y" select=" substring-before( $num-and-pos , ':') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'C' ">
+ <!-- absolute curveto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' c ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="4"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'c' ">
+ <!-- relative curveto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' v ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="4"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'S' ">
+ <!-- absolute shorthand/smooth curveto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' c ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="control-1">
+ <xsl:choose>
+ <xsl:when test="string-length(translate($last-command, 'CcSs','') )= 0 ">
+ <xsl:variable name="previous-control-2">
+ <xsl:call-template name="get-number-before">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="count" select="2"/>
+ <xsl:with-param name="skipcount" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="substring-before($previous-control-2 , ':') "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($control-and-pos, ':') "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , $control-1 , ' ' , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 's' ">
+ <!-- absolute shorthand/smooth curveto -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' v ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="control-1">
+ <xsl:choose>
+ <xsl:when test="string-length(translate($last-command, 'CcSs' , '')) = 0 ">
+ <xsl:variable name="previous-control-2">
+ <xsl:call-template name="get-number-before">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="count" select="2"/>
+ <xsl:with-param name="skipcount" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="substring-before($previous-control-2 , ':') "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($control-and-pos, ':') "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , $control-1 , ' ' , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'Q' ">
+ <!-- absolute quadratic bézier curves -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' qb ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'q' ">
+ <!-- relative quadratic bézier curves -->
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="control" select="substring-before( $control-and-pos , ':') "/>
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' qb ' , substring-before($control,' ') + $current-x , ' ' , substring-after($control , ' ') + $current-y ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="number" select="substring-before($num-and-pos, ':')"/>
+ <xsl:variable name="absolute-number" select="concat(substring-before($number, ' ') + $current-x , ' ' , substring-after($number, ' ') + $current-y)"/>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , ' ' , $absolute-number , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( $absolute-number , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( $absolute-number , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'Z' or $command = 'z' ">
+ <!-- closepath -->
+ <xsl:variable name="new-vml-path" select="concat($vml-path ,' x ' ) "/>
+ <xsl:call-template name="svgpath2vmlpath">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="vml-path" select=" concat($new-vml-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$vml-path"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number-before">
+ <!-- get $count number of number before current position , output format:number1 number2 ... numberN:newposition
+ skip $skipcount of numbers
+ -->
+ <xsl:param name="svg-path"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="count" select="1"/>
+ <xsl:param name="skipcount" select="0"/>
+ <xsl:param name="number" select="''"/>
+ <xsl:choose>
+ <xsl:when test="$count = 0">
+ <xsl:value-of select=" concat($number , ':' , $position) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="num-pos">
+ <xsl:call-template name="get-number-position">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="direction" select="-1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="previous-num-and-pos">
+ <xsl:call-template name="get-previous-number">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$num-pos"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$skipcount &gt; 0">
+ <xsl:call-template name="get-number-before">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after($previous-num-and-pos , ':')"/>
+ <xsl:with-param name="count" select="$count"/>
+ <xsl:with-param name="skipcount" select="$skipcount - 1"/>
+ <xsl:with-param name="number" select="$number"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$skipcount = 0">
+ <xsl:variable name="new-number">
+ <xsl:if test="not($count = 1)">
+ <xsl:value-of select="' '"/>
+ </xsl:if>
+ <xsl:value-of select=" concat( substring-before($previous-num-and-pos , ':') , $number ) "/>
+ </xsl:variable>
+ <xsl:call-template name="get-number-before">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after($previous-num-and-pos , ':')"/>
+ <xsl:with-param name="count" select="$count - 1"/>
+ <xsl:with-param name="skipcount" select="0"/>
+ <xsl:with-param name="number" select="$new-number"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number-after">
+ <!-- get $count number of number after current position, output format:number1 number2 ... numberN:newposition
+ skip $skipcount of numbers
+ -->
+ <xsl:param name="svg-path"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="count" select="1"/>
+ <xsl:param name="skipcount" select="0"/>
+ <xsl:param name="number" select="''"/>
+ <xsl:choose>
+ <xsl:when test="$count = 0">
+ <xsl:value-of select=" concat($number , ':' , $position) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="num-pos">
+ <xsl:call-template name="get-number-position">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="direction" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="next-num-and-pos">
+ <xsl:call-template name="get-next-number">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$num-pos"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$skipcount &gt; 0">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after($next-num-and-pos , ':')"/>
+ <xsl:with-param name="count" select="$count"/>
+ <xsl:with-param name="skipcount" select="$skipcount - 1"/>
+ <xsl:with-param name="number" select="$number"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$skipcount = 0">
+ <xsl:variable name="new-number">
+ <xsl:value-of select=" concat( $number , substring-before($next-num-and-pos , ':') ) "/>
+ <xsl:if test="not($count = 1)">
+ <xsl:value-of select="' '"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="substring-after($next-num-and-pos , ':')"/>
+ <xsl:with-param name="count" select="$count - 1"/>
+ <xsl:with-param name="skipcount" select="0"/>
+ <xsl:with-param name="number" select="$new-number"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number-position">
+ <!-- get the next number start position, direction should be 1 or -1-->
+ <xsl:param name="svg-path"/>
+ <xsl:param name="position"/>
+ <xsl:param name="direction" select="1"/>
+ <xsl:choose>
+ <xsl:when test="$direction = 1 and $position &gt; string-length($svg-path) ">0</xsl:when>
+ <xsl:when test="$direction = -1 and not($position &gt; 0)">0</xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char">
+ <xsl:if test="$direction = 1">
+ <xsl:value-of select="substring($svg-path, $position , 1)"/>
+ </xsl:if>
+ <xsl:if test="$direction = -1">
+ <xsl:value-of select="substring($svg-path, $position -1 , 1)"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length(translate($curr-char , '+-.0123456789' ,'')) = 0 ">
+ <!-- number start-->
+ <xsl:value-of select="$position"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-number-position">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position + $direction"/>
+ <xsl:with-param name="direction" select="$direction"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-next-number">
+ <!-- get the next number from current position-->
+ <xsl:param name="svg-path"/>
+ <xsl:param name="position"/>
+ <xsl:param name="number" select="''"/>
+ <xsl:choose>
+ <xsl:when test="$position &gt; string-length($svg-path) ">
+ <xsl:value-of select=" concat(round($number) , ':' , $position) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char" select="substring($svg-path, $position , 1)"/>
+ <xsl:choose>
+ <xsl:when test="string-length(translate($curr-char , '.0123456789' ,'')) = 0 ">
+ <!-- is number -->
+ <xsl:call-template name="get-next-number">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position +1"/>
+ <xsl:with-param name="number" select="concat( $number, $curr-char) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '+-' ,'') ) = 0 and string-length($number) = 0">
+ <!-- is number -->
+ <xsl:call-template name="get-next-number">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position +1"/>
+ <xsl:with-param name="number" select="concat( $number, $curr-char) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat( round($number) , ':' , $position)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-previous-number">
+ <!-- get the previous number from current position-->
+ <xsl:param name="svg-path"/>
+ <xsl:param name="position"/>
+ <xsl:param name="number" select="''"/>
+ <xsl:choose>
+ <xsl:when test="not($position &gt; 0)">
+ <xsl:value-of select="concat( round($number ), ':0')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char" select="substring($svg-path, $position -1 , 1)"/>
+ <xsl:choose>
+ <xsl:when test="string-length(translate($curr-char , '.0123456789' ,'')) = 0 ">
+ <!-- is number -->
+ <xsl:call-template name="get-previous-number">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position -1"/>
+ <xsl:with-param name="number" select="concat($curr-char , $number) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '+-' ,'') ) = 0 and string-length($number) = 0">
+ <!-- skip it -->
+ <xsl:call-template name="get-previous-number">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position -1"/>
+ <xsl:with-param name="number" select="$number "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '+-' ,'') ) = 0 and string-length($number) &gt; 0">
+ <!-- finish it with +/- -->
+ <xsl:value-of select="concat( round( concat( $curr-char, $number)) , ':' , $position)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat( round($number) , ':' , $position)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-path-command">
+ <xsl:param name="svg-path"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="last-command"/>
+ <xsl:choose>
+ <xsl:when test="$position &gt; string-length($svg-path) "/>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char" select="substring($svg-path, $position , 1)"/>
+ <xsl:choose>
+ <xsl:when test="string-length(translate($curr-char , 'MmZzLlHhVvCcSsQqTtAa' ,'')) = 0 ">
+ <!-- "MmZzLlHhVvCcSsQqTtAa" are all possible command chars -->
+ <xsl:value-of select="concat( $curr-char , ':' , $position +1)"/>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '+-.0123456789' ,'')) = 0 ">
+ <!-- number start, use last command -->
+ <xsl:if test="string-length($last-command) = 0">
+ <xsl:message>ooo2wordml_path.xsl: Find undefined command</xsl:message>
+ </xsl:if>
+ <xsl:value-of select="concat( $last-command , ':' , $position )"/>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , ',&#9;&#10;&#13;&#32;' ,'')) = 0 ">
+ <!-- space or ',' should be skip -->
+ <xsl:call-template name="get-path-command">
+ <xsl:with-param name="svg-path" select="$svg-path"/>
+ <xsl:with-param name="position" select="$position +1"/>
+ <xsl:with-param name="last-command" select="$last-command"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>ooo2wordml_path.xsl: Find undefined command:<xsl:value-of select="$curr-char"/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="svg-arc2vml-arc">
+ <xsl:param name="x0"/>
+ <xsl:param name="y0"/>
+ <xsl:param name="rx"/>
+ <xsl:param name="ry"/>
+ <xsl:param name="x-axis-rotation" select="0"/>
+ <xsl:param name="large-arc-flag" select="0"/>
+ <xsl:param name="sweep-flag" select="0"/>
+ <xsl:param name="x"/>
+ <xsl:param name="y"/>
+ <!-- Compute 1/2 distance between current and final point -->
+ <xsl:variable name="dx2" select="($x0 - $x) div 2"/>
+ <xsl:variable name="dy2" select="($y0 - $y) div 2"/>
+ <!-- Convert from degrees to radians -->
+ <xsl:variable name="rotation-radian" select="$x-axis-rotation * $pi div 180"/>
+ <!-- Compute (x1, y1). What are x1,y1?-->
+ <xsl:variable name="cos-rotation">
+ <xsl:call-template name="cos">
+ <xsl:with-param name="x" select="$rotation-radian"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="sin-rotation">
+ <xsl:call-template name="sin">
+ <xsl:with-param name="x" select="$rotation-radian"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="x1" select="$cos-rotation * $dx2 + $sin-rotation * $dy2"/>
+ <xsl:variable name="y1" select="-1 * $sin-rotation * $dx2 + $cos-rotation * $dy2"/>
+ <!-- Make sure radii are large enough -->
+ <xsl:variable name="rx-abs">
+ <xsl:call-template name="abs">
+ <xsl:with-param name="x" select="$rx"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="ry-abs">
+ <xsl:call-template name="abs">
+ <xsl:with-param name="x" select="$ry"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="rx-sq" select="$rx-abs * $rx-abs"/>
+ <xsl:variable name="ry-sq" select="$ry-abs * $ry-abs"/>
+ <xsl:variable name="x1-sq" select="$x1 * $x1"/>
+ <xsl:variable name="y1-sq" select="$y1 * $y1"/>
+ <xsl:variable name="radius-check" select=" $x1-sq div $rx-sq + $y1-sq div $ry-sq "/>
+ <xsl:variable name="radius-check-sqrt">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="$radius-check"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="new-rx">
+ <xsl:choose>
+ <xsl:when test="$radius-check &gt; 1">
+ <xsl:value-of select="$rx-abs * $radius-check-sqrt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$rx-abs"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="new-ry">
+ <xsl:choose>
+ <xsl:when test="$radius-check &gt; 1">
+ <xsl:value-of select="$ry-abs * $radius-check-sqrt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$ry-abs"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="new-ry-sq">
+ <xsl:choose>
+ <xsl:when test="$radius-check &gt; 1">
+ <xsl:value-of select="$new-ry * $new-ry"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$ry-sq"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="new-rx-sq">
+ <xsl:choose>
+ <xsl:when test="$radius-check &gt; 1">
+ <xsl:value-of select="$new-rx * $new-rx"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$rx-sq"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- Step 2: Compute (cx1, cy1) -->
+ <xsl:variable name="sign">
+ <xsl:choose>
+ <xsl:when test="$large-arc-flag = $sweep-flag">-1</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="unchecked-sq" select=" (($new-rx-sq * $new-ry-sq) - ($new-rx-sq * $y1-sq) - ($new-ry-sq * $x1-sq)) div (($new-rx-sq * $y1-sq) + ($new-ry-sq * $x1-sq)) "/>
+ <xsl:variable name="sq">
+ <xsl:choose>
+ <xsl:when test=" $unchecked-sq &lt; 0">0</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$unchecked-sq"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="sq-sqrt">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="$sq"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="coef" select="$sign * $sq-sqrt "/>
+ <xsl:variable name="cx1" select="$coef * $new-rx * $y1 div $new-ry"/>
+ <xsl:variable name="cy1" select=" -1 * $coef * $new-ry * $x1 div $new-rx"/>
+ <!-- Step 3: Compute (cx, cy) from (cx1, cy1) -->
+ <xsl:variable name="sx2" select="($x0 +$x) div 2 "/>
+ <xsl:variable name="sy2" select="($y0 +$y) div 2 "/>
+ <xsl:variable name="tmp1" select="$cos-rotation * $cx1 "/>
+ <xsl:variable name="tmp2" select="$cos-rotation * $cx1 "/>
+ <xsl:variable name="cx" select=" $sx2 + ( $cos-rotation * $cx1 - $sin-rotation * $cy1 ) "/>
+ <xsl:variable name="cy" select=" $sy2 + ( $sin-rotation * $cx1 + $cos-rotation * $cy1 ) "/>
+ <!-- Step 4: Compute angle start and angle extent -->
+ <xsl:variable name="ux" select="( $x1 - $cx1) div $new-rx"/>
+ <xsl:variable name="uy" select="( $y1 - $cy1) div $new-ry"/>
+ <xsl:variable name="vx" select="( - 1 * $x1 - $cx1) div $new-rx"/>
+ <xsl:variable name="vy" select="(- 1 * $y1 - $cy1) div $new-ry"/>
+ <xsl:variable name="n">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select=" ($ux * $ux) + ($uy * $uy) "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- 1 * ux + 0 * uy -->
+ <xsl:variable name="p" select="$ux"/>
+ <xsl:variable name="uy-sign">
+ <xsl:choose>
+ <xsl:when test=" $uy &lt; 0 ">-1</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="acos-pn">
+ <xsl:call-template name="acos">
+ <xsl:with-param name="x" select="$p div $n"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="theta" select="( $uy-sign * $acos-pn * 180 div $pi ) mod 360 "/>
+ <xsl:variable name="n-delta">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="($ux * $ux + $uy * $uy) * ($vx * $vx + $vy * $vy)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="p-delta" select="$ux * $vx + $uy * $vy"/>
+ <xsl:variable name="vy-sign">
+ <xsl:choose>
+ <xsl:when test="($ux * $vy - $uy * $vx) &lt; 0 ">-1</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="acos-pn-delta">
+ <xsl:call-template name="acos">
+ <xsl:with-param name="x" select="$p-delta div $n-delta"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="unchecked-delta" select="$vy-sign * $acos-pn-delta * 180 div $pi "/>
+ <xsl:variable name="delta">
+ <xsl:choose>
+ <xsl:when test=" $sweep-flag = 0 and $unchecked-delta &gt; 0 ">
+ <xsl:value-of select=" ($unchecked-delta - 360) mod 360 "/>
+ </xsl:when>
+ <xsl:when test=" $sweep-flag = 1 and $unchecked-delta &lt; 0 ">
+ <xsl:value-of select=" ($unchecked-delta + 360) mod 360 "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" $unchecked-delta mod 360 "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat ($cx, ' ' , $cy, ' ' , $rx, ' ' , $ry, ' ' , $theta, ' ' , $delta, ' ' , $x-axis-rotation) "/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_settings.xsl b/filter/source/xslt/export/wordml/ooo2wordml_settings.xsl
new file mode 100644
index 000000000..2130db508
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_settings.xsl
@@ -0,0 +1,308 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:template match="office:settings">
+ <w:docPr>
+ <w:displayBackgroundShape/>
+ <xsl:variable name="view-settings" select="config:config-item-set[@config:name = 'view-settings']"/>
+ <xsl:choose>
+ <xsl:when test="$view-settings/config:config-item[@config:name = 'InBrowseMode'] = 'true'">
+ <w:view w:val="outline"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:view w:val="print"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:variable name="views" select="$view-settings/config:config-item-map-indexed[@config:name = 'Views']"/>
+ <w:zoom w:percent="{$views/config:config-item-map-entry/config:config-item[@config:name = 'ZoomFactor']}">
+ <xsl:variable name="zoom-type" select="$views/config:config-item-map-entry/config:config-item[@config:name = 'ZoomType']"/>
+ <xsl:choose>
+ <xsl:when test="$zoom-type = '3'">
+ <xsl:attribute name="w:val">best-fit</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$zoom-type = '2'">
+ <xsl:attribute name="w:val">full-page</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$zoom-type = '1'">
+ <xsl:attribute name="w:val">text-fit</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </w:zoom>
+ <w:defaultTabStop>
+ <xsl:attribute name="w:val"><xsl:call-template name="convert2twip"><xsl:with-param name="value" select="/office:document/office:styles/style:default-style[@style:family='paragraph']/style:paragraph-properties/@style:tab-stop-distance"/></xsl:call-template></xsl:attribute>
+ </w:defaultTabStop>
+ <xsl:if test="../office:master-styles/style:master-page/style:header-left">
+ <w:evenAndOddHeaders/>
+ </xsl:if>
+ <xsl:apply-templates select="/office:document/office:styles/text:footnotes-configuration"/>
+ <xsl:apply-templates select="/office:document/office:styles/text:endnotes-configuration"/>
+ <!-- add the variables declaration in w:docpr G.Y. Begin-->
+ <xsl:if test="/office:document/office:body/office:text/text:variable-decls | /office:document/office:body/office:text/text:user-field-decls |/office:document/office:body/office:text/text:sequence-decls ">
+ <xsl:call-template name="field_declare">
+ <xsl:with-param name="simple_field_variable_declares" select="/office:document/office:body/office:text/text:variable-decls"/>
+ <xsl:with-param name="user_field_variable_declares" select=" /office:document/office:body/office:text/text:user-field-decls"/>
+ <xsl:with-param name="field_sequence_declares" select="/office:document/office:body/office:text/text:sequence-decls"/>
+ </xsl:call-template>
+ </xsl:if>
+ <!--add the variables declaration in w:docpr G.Y. End-->
+ </w:docPr>
+ </xsl:template>
+ <xsl:template match="text:footnotes-configuration">
+ <xsl:param name="within-section"/>
+ <w:footnotePr>
+ <xsl:choose>
+ <xsl:when test="@text:footnotes-position = 'document'">
+ <w:pos w:val="beneath-text"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:pos w:val="page-bottom"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@text:start-value">
+ <w:numStart w:val="{@text:start-value + 1}"/>
+ </xsl:if>
+ <xsl:if test="@style:num-format">
+ <xsl:call-template name="convert-number-format">
+ <xsl:with-param name="number-format" select="@style:num-format"/>
+ <xsl:with-param name="number-prefix" select="@style:num-prefix"/>
+ <xsl:with-param name="number-suffix" select="@style:num-suffix"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="@text:start-numbering-at">
+ <xsl:choose>
+ <xsl:when test="@text:start-numbering-at = 'document'">
+ <w:numRestart w:val="continuous"/>
+ </xsl:when>
+ <xsl:when test="@text:start-numbering-at = 'page'">
+ <w:numRestart w:val="each-page"/>
+ </xsl:when>
+ <!-- convert "chapter" to "section" -->
+ <xsl:otherwise>
+ <w:numRestart w:val="each-sect"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$within-section != 'yes'">
+ <!-- because in SO/OOo footnote-sep is defined within every page-layout, but in Word XML footnote separator
+ is defined solely in docPr, so not trouble to find the proper footnote-sep definition. -->
+ <w:footnote w:type="separator">
+ <w:p>
+ <w:r>
+ <w:separator/>
+ </w:r>
+ </w:p>
+ </w:footnote>
+ <w:footnote w:type="continuation-separator">
+ <w:p>
+ <w:r>
+ <w:continuationSeparator/>
+ <xsl:if test="text:footnote-continuation-notice-backward">
+ <w:t>
+ <xsl:value-of select="text:footnote-continuation-notice-backward"/>
+ </w:t>
+ </xsl:if>
+ </w:r>
+ </w:p>
+ </w:footnote>
+ <xsl:if test="text:footnote-continuation-notice-forward">
+ <w:footnote w:type="continuation-notice">
+ <w:p>
+ <w:r>
+ <w:t>
+ <xsl:value-of select="text:footnote-continuation-notice-forward"/>
+ </w:t>
+ </w:r>
+ </w:p>
+ </w:footnote>
+ </xsl:if>
+ </xsl:if>
+ </w:footnotePr>
+ </xsl:template>
+ <xsl:template match="text:endnotes-configuration">
+ <xsl:param name="within-section"/>
+ <w:endnotePr>
+ <w:pos w:val="sect-end"/>
+ <xsl:if test="@text:start-value">
+ <w:numStart w:val="{@text:start-value + 1}"/>
+ </xsl:if>
+ <xsl:if test="@style:num-format">
+ <xsl:call-template name="convert-number-format">
+ <xsl:with-param name="number-format" select="@style:num-format"/>
+ <xsl:with-param name="number-prefix" select="@style:num-prefix"/>
+ <xsl:with-param name="number-suffix" select="@style:num-suffix"/>
+ </xsl:call-template>
+ </xsl:if>
+ <w:numRestart w:val="each-sect"/>
+ <xsl:if test="$within-section != 'yes'">
+ <w:endnote w:type="separator">
+ <w:p>
+ <w:r>
+ <w:separator/>
+ </w:r>
+ </w:p>
+ </w:endnote>
+ <w:endnote w:type="continuation-separator">
+ <w:p>
+ <w:r>
+ <w:continuationSeparator/>
+ </w:r>
+ </w:p>
+ </w:endnote>
+ </xsl:if>
+ </w:endnotePr>
+ </xsl:template>
+ <xsl:template name="convert-number-format">
+ <xsl:param name="number-format"/>
+ <xsl:param name="number-prefix"/>
+ <xsl:param name="number-suffix"/>
+ <xsl:choose>
+ <xsl:when test="$number-format = '1' and normalize-space($number-prefix) = '0'">
+ <w:numFmt w:val="decimal-zero"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '1' and normalize-space($number-suffix) = '.'">
+ <w:numFmt w:val="decimal-enclosed-fullstop"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '1' and normalize-space($number-prefix) = '(' and normalize-space($number-prefix) = ')'">
+ <w:numFmt w:val="decimal-enclosed-paren"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '1' and normalize-space($number-prefix) = '-' and normalize-space($number-prefix) = '-'">
+ <w:numFmt w:val="number-in-dash"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '1'">
+ <!-- '1' also seems: decimal-half-width -->
+ <w:numFmt w:val="decimal"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'a'">
+ <w:numFmt w:val="lower-letter"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'A'">
+ <w:numFmt w:val="upper-letter"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'i'">
+ <w:numFmt w:val="lower-roman"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'I'">
+ <w:numFmt w:val="upper-roman"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '1, 2, 3, ...'">
+ <!-- '1, 2, 3, ...' also seems: decimal-full-width2 -->
+ <w:numFmt w:val="decimal-full-width"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '①, ②, ③, ...'">
+ <!-- decimal-enclosed-circle seems same -->
+ <w:numFmt w:val="decimal-enclosed-circle-chinese"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '一, 二, 三, ...' and normalize-space($number-prefix) = '(' and normalize-space($number-suffix) = ')'">
+ <w:numFmt w:val="ideograph-enclosed-circle"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '一, 二, 三, ...'">
+ <!-- '一, 二, 三, ...' also seems: ideograph-digital, japanese-counting, japanese-digital-ten-thousand,
+ taiwanese-counting, taiwanese-counting-thousand, taiwanese-digital, chinese-counting, korean-digital2 -->
+ <w:numFmt w:val="chinese-counting-thousand"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '壹, 贰, 叁, ...'">
+ <w:numFmt w:val="chinese-legal-simplified"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '壹, 貳, 參, ...'">
+ <w:numFmt w:val="ideograph-legal-traditional"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '甲, 乙, 丙, ...'">
+ <w:numFmt w:val="ideograph-traditional"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '子, 丑, 寅, ...'">
+ <w:numFmt w:val="ideograph-zodiac"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '壱, 弐, 参, ...'">
+ <w:numFmt w:val="japanese-legal"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ア, イ, ウ, ...'">
+ <w:numFmt w:val="aiueo-full-width"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ア, イ, ウ, ...'">
+ <w:numFmt w:val="aiueo"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'イ, ロ, ハ, ...'">
+ <w:numFmt w:val="iroha-full-width"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'イ, ロ, ハ, ...'">
+ <w:numFmt w:val="iroha"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '일, 이, 삼, ...'">
+ <w:numFmt w:val="korean-counting"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '하나, 둘, 셋, ...'">
+ <w:numFmt w:val="korean-legal"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ㄱ, ㄴ, ㄷ, ...' or $number-format = '㉠, ㉡, ㉢, ...'">
+ <!-- mapping circled to uncircled -->
+ <w:numFmt w:val="chosung"/>
+ </xsl:when>
+ <xsl:when test="$number-format = '가, 나, 다, ...' or $number-format = '㉮, ㉯, ㉰, ...'">
+ <!-- mapping circled to uncircled -->
+ <w:numFmt w:val="ganada"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'أ, ب, ت, ...'">
+ <w:numFmt w:val="arabic-alpha"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ก, ข, ฃ, ...'">
+ <w:numFmt w:val="thai-letters"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'א, י, ק, ...'">
+ <w:numFmt w:val="hebrew-1"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'א, ב, ג, ...'">
+ <w:numFmt w:val="hebrew-2"/>
+ </xsl:when>
+ <xsl:when test="$number-format = 'Native Numbering'">
+ <xsl:variable name="locale" select="/office:document/office:meta/dc:language"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($locale, 'th-')">
+ <!-- for Thai, mapping thai-numbers, thai-counting to thai-letters -->
+ <w:numFmt w:val="thai-letters"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'hi-')">
+ <!-- for Hindi, mapping hindi-vowels, hindi-consonants, hindi-counting to hindi-numbers -->
+ <w:numFmt w:val="hindi-numbers"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'ar-')">
+ <!-- for Arabic, mapping arabic-abjad to arabic-alpha -->
+ <w:numFmt w:val="arabic-alpha"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'he-')">
+ <!-- for Hebrew, mapping hebrew-2 to -->
+ <w:numFmt w:val="hebrew-1"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'ru-')">
+ <!-- for Russian, mapping russian-upper to russian-lower -->
+ <w:numFmt w:val="russian-lower"/>
+ </xsl:when>
+ <xsl:when test="starts-with($locale, 'vi-')">
+ <!-- for Vietnamese -->
+ <w:numFmt w:val="vietnamese-counting"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <!-- unsupported: ordinal, cardinal-text, ordinal-text, hex, chicago, bullet, ideograph-zodiac-traditional,
+ chinese-not-impl -->
+ <xsl:otherwise>
+ <w:numFmt w:val="decimal"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_table.xsl b/filter/source/xslt/export/wordml/ooo2wordml_table.xsl
new file mode 100644
index 000000000..6812b8dee
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_table.xsl
@@ -0,0 +1,407 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:key name="table-style" match="style:style[@style:family='table']" use="@style:name"/>
+ <xsl:key name="table-column-style" match="style:style[@style:family='table-column']" use="@style:name"/>
+ <xsl:key name="table-row-style" match="style:style[@style:family='table-row']" use="@style:name"/>
+ <xsl:key name="table-cell-style" match="style:style[@style:family='table-cell']" use="@style:name"/>
+ <xsl:template match="style:table-properties" mode="table">
+ <xsl:param name="within-body"/>
+ <xsl:if test="$within-body = 'yes'">
+ <w:tblW>
+ <xsl:choose>
+ <xsl:when test="@style:rel-width">
+ <xsl:attribute name="w:w"><xsl:value-of select="substring-before(@style:rel-width, '%') * 50"/></xsl:attribute>
+ <xsl:attribute name="w:type">pct</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:width">
+ <xsl:attribute name="w:w"><xsl:call-template name="convert2twip"><xsl:with-param name="value" select="@style:width"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="w:type">dxa</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:w">0</xsl:attribute>
+ <xsl:attribute name="w:type">auto</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:tblW>
+ </xsl:if>
+ <w:tblInd>
+ <xsl:choose>
+ <xsl:when test="@fo:margin-left">
+ <xsl:attribute name="w:w"><xsl:call-template name="convert2twip"><xsl:with-param name="value" select="@fo:margin-left"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="w:type">dxa</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:w">0</xsl:attribute>
+ <xsl:attribute name="w:type">auto</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:tblInd>
+ <xsl:if test="@table:align">
+ <w:jc>
+ <xsl:choose>
+ <xsl:when test="@table:align = 'left' or @table:align= 'center' or @table:align = 'right'">
+ <xsl:attribute name="w:val"><xsl:value-of select="@table:align"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:val">left</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:jc>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="table:table">
+ <!--fix for issue i32030 pagebreak before-->
+ <xsl:if test="key('table-style', @table:style-name)/style:table-properties/@fo:break-before">
+ <xsl:variable name="table-break-before" select="key('table-style', @table:style-name)/style:table-properties/@fo:break-before"/>
+ <xsl:choose>
+ <xsl:when test="$table-break-before = 'page' ">
+ <w:p>
+ <w:r>
+ <w:br w:type="page"/>
+ </w:r>
+ </w:p>
+ </xsl:when>
+ <xsl:when test="$table-break-before = 'column' ">
+ <w:p>
+ <w:r>
+ <w:br w:type="column"/>
+ </w:r>
+ </w:p>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <w:tbl>
+ <w:tblPr>
+ <xsl:if test="not (@table:is-sub-table) or (@table:is-sub-table = 'false' )">
+ <w:tblStyle w:val="{@table:style-name}"/>
+ <xsl:apply-templates select="key('table-style', @table:style-name)/style:table-properties" mode="table">
+ <xsl:with-param name="within-body" select="'yes'"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ <xsl:if test="@table:is-sub-table ='true' ">
+ <w:tblW w:type="dxa">
+ <xsl:variable name="sub-table-width">
+ <xsl:call-template name="calculate-sub-table-width">
+ <xsl:with-param name="sub-table-column-node" select="table:table-column[1]"/>
+ <xsl:with-param name="total-sub-table-width" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:w"><xsl:value-of select="$sub-table-width"/></xsl:attribute>
+ </w:tblW>
+ <!--w:tblLayout w:type="Fixed"/-->
+ </xsl:if>
+ </w:tblPr>
+ <w:tblGrid>
+ <xsl:apply-templates select="table:table-column"/>
+ </w:tblGrid>
+ <xsl:apply-templates select="table:table-header-rows/table:table-row | table:table-row"/>
+ </w:tbl>
+ <!--fix for issue i32030 pagebreak after-->
+ <xsl:if test="key('table-style', @table:style-name)/style:table-properties/@fo:break-after">
+ <xsl:variable name="table-break-after" select=" key('table-style', @table:style-name)/style:table-properties/@fo:break-after"/>
+ <xsl:choose>
+ <xsl:when test="$table-break-after = 'page' ">
+ <w:p>
+ <w:r>
+ <w:br w:type="page"/>
+ </w:r>
+ </w:p>
+ </xsl:when>
+ <xsl:when test="$table-break-after = 'column' ">
+ <w:p>
+ <w:r>
+ <w:br w:type="column"/>
+ </w:r>
+ </w:p>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="name(..)= 'table:table-cell' ">
+ <w:p/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="calculate-sub-table-width">
+ <xsl:param name="sub-table-column-node"/>
+ <xsl:param name="total-sub-table-width"/>
+ <xsl:variable name="column-width" select="key('table-column-style', $sub-table-column-node/@table:style-name)/style:table-column-properties/@style:column-width"/>
+ <xsl:variable name="column-width-in-twip">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$column-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$sub-table-column-node/following-sibling::table:table-column">
+ <xsl:choose>
+ <xsl:when test="$sub-table-column-node/@table:number-columns-repeated">
+ <xsl:call-template name="calculate-sub-table-width">
+ <xsl:with-param name="sub-table-column-node" select="$sub-table-column-node/following-sibling::table:table-column[ 1]"/>
+ <xsl:with-param name="total-sub-table-width" select="$total-sub-table-width + $column-width-in-twip * $sub-table-column-node/@table:number-columns-repeated"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="calculate-sub-table-width">
+ <xsl:with-param name="sub-table-column-node" select="$sub-table-column-node/following-sibling::table:table-column[1]"/>
+ <xsl:with-param name="total-sub-table-width" select="$total-sub-table-width + $column-width-in-twip "/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$sub-table-column-node/@table:number-columns-repeated">
+ <xsl:value-of select="$total-sub-table-width + $column-width-in-twip * $sub-table-column-node/@table:number-columns-repeated"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$total-sub-table-width + $column-width-in-twip "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="table:table-column">
+ <xsl:variable name="column-width" select="key('table-column-style', @table:style-name)/style:table-column-properties/@style:column-width"/>
+ <xsl:variable name="column-width-in-twip">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$column-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <!-- if table:table-column has attribute table:number-columns-repeated, then call the recursion
+ temple repeat-gridcol to produce multiple w:gridCol in MS word. Gary.Yang -->
+ <xsl:when test="@table:number-columns-repeated">
+ <xsl:call-template name="repeat-gridcol">
+ <xsl:with-param name="grid-repeat-count" select="@table:number-columns-repeated"/>
+ <xsl:with-param name="column-width" select="$column-width-in-twip"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:gridCol w:w="{$column-width-in-twip}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--recursion template for produce multiple w:gridCol Gary.Yang-->
+ <xsl:template name="repeat-gridcol">
+ <xsl:param name="grid-repeat-count"/>
+ <xsl:param name="column-width"/>
+ <xsl:if test="$grid-repeat-count &gt; 0">
+ <w:gridCol w:w="{$column-width}"/>
+ <xsl:call-template name="repeat-gridcol">
+ <xsl:with-param name="grid-repeat-count" select="$grid-repeat-count - 1"/>
+ <xsl:with-param name="column-width" select="$column-width"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="table:table-row">
+ <xsl:element name="w:tr">
+ <xsl:element name="w:trPr">
+ <xsl:if test="parent::table:table-header-rows">
+ <!-- fix for Issue 32034-->
+ <w:tblHeader>on</w:tblHeader>
+ </xsl:if>
+ <xsl:variable name="row-height" select="key('table-row-style', @table:style-name)/style:table-row-properties/@style:row-height"/>
+ <xsl:if test="$row-height">
+ <w:trHeight>
+ <xsl:attribute name="w:val"><xsl:call-template name="convert2twip"><xsl:with-param name="value" select="$row-height"/></xsl:call-template></xsl:attribute>
+ </w:trHeight>
+ </xsl:if>
+ </xsl:element>
+ <!--end of w:trPr-->
+ <xsl:apply-templates select="table:table-cell "/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="table:table-cell ">
+ <xsl:element name="w:tc">
+ <xsl:element name="w:tcPr">
+ <!-- to calculate the table-cell width Gary.Yang -->
+ <xsl:choose>
+ <!--when the table-cell contains the sub-table -->
+ <xsl:when test="table:table/@table:is-sub-table= 'true' ">
+ <xsl:variable name="table-cell-width">
+ <xsl:call-template name="calculate-sub-table-width">
+ <xsl:with-param name="sub-table-column-node" select="table:table/table:table-column[1]"/>
+ <xsl:with-param name="total-sub-table-width" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <w:tcW w:type="dxa">
+ <xsl:attribute name="w:w"><xsl:value-of select="$table-cell-width"/></xsl:attribute>
+ </w:tcW>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- when the table-cell doesn't contain the sub-table -->
+ <xsl:variable name="table-cell-width">
+ <xsl:call-template name="calculate-table-cell-width">
+ <xsl:with-param name="table-cell-position" select="position()"/>
+ <xsl:with-param name="table-column" select="ancestor::table:table[1]/table:table-column[1]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <w:tcW w:type="dxa">
+ <xsl:attribute name="w:w"><xsl:value-of select="$table-cell-width"/></xsl:attribute>
+ </w:tcW>
+ <!-- for performance issue, we can set w:type to auto that makes the cell width auto fit the content. -->
+ <!--w:tcW w:w="0" w:type="auto"/-->
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@table:number-columns-spanned">
+ <w:gridSpan w:val="{@table:number-columns-spanned}"/>
+ </xsl:if>
+ <xsl:variable name="cell-style-properties" select="key('table-cell-style', @table:style-name)/style:table-cell-properties"/>
+ <xsl:if test="$cell-style-properties/@fo:background-color">
+ <w:shd w:val="solid" w:color="{substring-after($cell-style-properties/@fo:background-color,'#')}"/>
+ </xsl:if>
+ <xsl:if test="$cell-style-properties/@fo:vertical-align">
+ <xsl:choose>
+ <xsl:when test="$cell-style-properties/@fo:vertical-align = 'middle'">
+ <w:vAlign w:val="center"/>
+ </xsl:when>
+ <xsl:when test="$cell-style-properties/@fo:vertical-align = 'Automatic'">
+ <w:vAlign w:val="both"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:vAlign w:val="{$cell-style-properties/@fo:vertical-align}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <w:tcMar>
+ <xsl:if test="$cell-style-properties/@fo:padding-top">
+ <w:top w:type="dxa">
+ <xsl:attribute name="w:w"><xsl:call-template name="convert2twip"><xsl:with-param name="value" select="$cell-style-properties/@fo:padding-top"/></xsl:call-template></xsl:attribute>
+ </w:top>
+ </xsl:if>
+ <xsl:if test="$cell-style-properties/@fo:padding-bottom">
+ <w:bottom w:type="dxa">
+ <xsl:attribute name="w:w"><xsl:call-template name="convert2twip"><xsl:with-param name="value" select="$cell-style-properties/@fo:padding-bottom"/></xsl:call-template></xsl:attribute>
+ </w:bottom>
+ </xsl:if>
+ <xsl:if test="$cell-style-properties/@fo:padding-left">
+ <w:left w:type="dxa">
+ <xsl:attribute name="w:w"><xsl:call-template name="convert2twip"><xsl:with-param name="value" select="$cell-style-properties/@fo:padding-left"/></xsl:call-template></xsl:attribute>
+ </w:left>
+ </xsl:if>
+ <xsl:if test="$cell-style-properties/@fo:padding-right">
+ <w:right w:type="dxa">
+ <xsl:attribute name="w:w"><xsl:call-template name="convert2twip"><xsl:with-param name="value" select="$cell-style-properties/@fo:padding-right"/></xsl:call-template></xsl:attribute>
+ </w:right>
+ </xsl:if>
+ </w:tcMar>
+ <!-- the following code is to get the cell borders if they exist -->
+ <xsl:variable name="border-top" select="$cell-style-properties/@fo:border-top | $cell-style-properties/@fo:border"/>
+ <xsl:variable name="border-bottom" select="$cell-style-properties/@fo:border-bottom | $cell-style-properties/@fo:border"/>
+ <xsl:variable name="border-left" select="$cell-style-properties/@fo:border-left | $cell-style-properties/@fo:border"/>
+ <xsl:variable name="border-right" select="$cell-style-properties/@fo:border-right | $cell-style-properties/@fo:border"/>
+ <xsl:variable name="border-line-width-top" select="$cell-style-properties/@style:border-line-width-top | $cell-style-properties/@style:border-line-width "/>
+ <xsl:variable name="border-line-width-bottom" select="$cell-style-properties/@style:border-line-width-bottom | $cell-style-properties/@style:border-line-width"/>
+ <xsl:variable name="border-line-width-left" select="$cell-style-properties/@style:border-line-width-left | $cell-style-properties/@style:border-line-width"/>
+ <xsl:variable name="border-line-width-right" select="$cell-style-properties/@style:border-line-width-right | $cell-style-properties/@style:border-line-width"/>
+ <xsl:element name="w:tcBorders">
+ <xsl:if test="$border-top">
+ <xsl:element name="w:top">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-top"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-top"/>
+ <xsl:with-param name="so-border-position" select=" 'top' "/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-bottom">
+ <xsl:element name="w:bottom">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-bottom"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-bottom"/>
+ <xsl:with-param name="so-border-position" select=" 'bottom' "/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-left">
+ <xsl:element name="w:left">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-left"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-left"/>
+ <xsl:with-param name="so-border-position" select=" 'left' "/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-right">
+ <xsl:element name="w:right">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-right"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-right"/>
+ <xsl:with-param name="so-border-position" select=" 'right' "/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ <xsl:if test="not (*) ">
+ <w:p/>
+ </xsl:if>
+ <xsl:apply-templates select=" text:p | table:table | text:h | office:annotation"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="calculate-table-cell-width">
+ <xsl:param name="table-cell-position"/>
+ <xsl:param name="table-column"/>
+ <xsl:choose>
+ <xsl:when test="$table-column/@table:number-columns-repeated">
+ <xsl:choose>
+ <xsl:when test="($table-cell-position - $table-column/@table:number-columns-repeated) &lt;= 0">
+ <xsl:variable name="table-cell-width" select="key('table-column-style', $table-column/@table:style-name)/style:table-column-properties/@style:column-width"/>
+ <xsl:variable name="table-cell-width-in-twip">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$table-cell-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$table-cell-width-in-twip"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="calculate-table-cell-width">
+ <xsl:with-param name="table-cell-position" select="$table-cell-position - $table-column/@table:number-columns-repeated"/>
+ <xsl:with-param name="table-column" select="$table-column/following-sibling::table:table-column[1]"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- if the $table-column doesn't contain the table:number-columns-repeated attribute -->
+ <xsl:choose>
+ <xsl:when test="($table-cell-position - 1) = 0">
+ <xsl:variable name="table-cell-width" select="key('table-column-style', $table-column/@table:style-name)/style:table-column-properties/@style:column-width"/>
+ <xsl:variable name="table-cell-width-in-twip">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$table-cell-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$table-cell-width-in-twip"/>
+ </xsl:when>
+ <xsl:when test="($table-cell-position - 1) &gt; 0">
+ <xsl:call-template name="calculate-table-cell-width">
+ <xsl:with-param name="table-cell-position" select=" $table-cell-position - 1 "/>
+ <xsl:with-param name="table-column" select="$table-column/following-sibling::table:table-column[1]"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>
+ <xsl:value-of select=" 'calculate table cell width wrong ' "/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/export/wordml/ooo2wordml_text.xsl b/filter/source/xslt/export/wordml/ooo2wordml_text.xsl
new file mode 100644
index 000000000..406c8cb91
--- /dev/null
+++ b/filter/source/xslt/export/wordml/ooo2wordml_text.xsl
@@ -0,0 +1,1270 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="office table style text draw svg dc config xlink meta oooc dom ooo chart math dr3d form script ooow draw">
+ <xsl:template match="style:paragraph-properties" mode="paragraph">
+ <w:pPr>
+ <w:adjustRightInd w:val="off"/>
+ <xsl:if test="@fo:break-before = 'page'">
+ <w:pageBreakBefore w:val="on"/>
+ </xsl:if>
+ <xsl:if test="contains(@style:writing-mode, 'rl')">
+ <w:bidi/>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@fo:text-align-last = 'start'">
+ <xsl:choose>
+ <xsl:when test="contains(@style:writing-mode, 'rl')">
+ <w:jc w:val="right"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:jc w:val="left"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@fo:text-align-last = 'justify'">
+ <w:jc w:val="distribute"/>
+ </xsl:when>
+ <xsl:when test="@fo:text-align-last = 'center'">
+ <w:jc w:val="center"/>
+ </xsl:when>
+ <xsl:when test="@fo:text-align = 'start'">
+ <xsl:choose>
+ <xsl:when test="contains(@style:writing-mode, 'rl')">
+ <w:jc w:val="right"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:jc w:val="left"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@fo:text-align = 'end'">
+ <xsl:choose>
+ <xsl:when test="contains(@style:writing-mode, 'rl')">
+ <w:jc w:val="left"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:jc w:val="right"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@fo:text-align = 'justify'">
+ <w:jc w:val="distribute"/>
+ </xsl:when>
+ <xsl:when test="@fo:text-align = 'center'">
+ <w:jc w:val="center"/>
+ </xsl:when>
+ </xsl:choose>
+ <w:spacing>
+ <xsl:choose>
+ <xsl:when test="@fo:line-height">
+ <xsl:choose>
+ <xsl:when test="contains(@fo:line-height, '%')">
+ <xsl:attribute name="w:line-rule">auto</xsl:attribute>
+ <xsl:attribute name="w:line">
+ <xsl:value-of select="round(substring-before(@fo:line-height, '%') div 100 * 240)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:line-rule">exact</xsl:attribute>
+ <xsl:attribute name="w:line">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:line-height"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@style:line-height-at-least">
+ <xsl:attribute name="w:line-rule">at-least</xsl:attribute>
+ <xsl:attribute name="w:line">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@style:line-height-at-least"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:line-spacing">
+ <xsl:attribute name="w:line-rule">auto</xsl:attribute>
+ <xsl:variable name="spacing">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@style:line-spacing"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:line">
+ <xsl:value-of select="round($spacing div 0.567)"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="@fo:margin-top">
+ <xsl:choose>
+ <xsl:when test="contains(@fo:margin-top, '%')">
+ <xsl:if test="../@style:parent-style-name">
+ <xsl:variable name="parent-size">
+ <xsl:value-of select="key('paragraph-style', ../@style:parent-style-name)/style:paragraph-properties/@fo:margin-top"/>
+ </xsl:variable>
+ <xsl:variable name="w-number">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$parent-size"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:before">
+ <xsl:value-of select="round($w-number div 100 * substring-before(@fo:margin-top, '%'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:before">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:margin-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@fo:margin-bottom">
+ <xsl:choose>
+ <xsl:when test="contains(@fo:margin-bottom, '%')">
+ <xsl:if test="../@style:parent-style-name">
+ <xsl:variable name="parent-size">
+ <xsl:value-of select="key('paragraph-style', ../@style:parent-style-name)/style:paragraph-properties/@fo:margin-bottom"/>
+ </xsl:variable>
+ <xsl:variable name="w-number">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$parent-size"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:after">
+ <xsl:value-of select="round($w-number div 100 * substring-before(@fo:margin-bottom, '%'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:after">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:margin-bottom"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </w:spacing>
+ <w:ind>
+ <xsl:if test="@fo:margin-left">
+ <xsl:choose>
+ <xsl:when test="contains(@fo:margin-left, '%')">
+ <xsl:if test="../@style:parent-style-name">
+ <xsl:variable name="parent-size">
+ <xsl:value-of select="key('paragraph-style', ../@style:parent-style-name)/style:paragraph-properties/@fo:margin-left"/>
+ </xsl:variable>
+ <xsl:variable name="w-number">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$parent-size"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:left">
+ <xsl:value-of select="round($w-number div 100 * substring-before(@fo:margin-left, '%'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:left">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:margin-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@fo:margin-right">
+ <xsl:choose>
+ <xsl:when test="contains(@fo:margin-right, '%')">
+ <xsl:if test="../@style:parent-style-name">
+ <xsl:variable name="parent-size">
+ <xsl:value-of select="key('paragraph-style', ../@style:parent-style-name)/style:paragraph-properties/@fo:margin-right"/>
+ </xsl:variable>
+ <xsl:variable name="w-number">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$parent-size"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:right">
+ <xsl:value-of select="round($w-number div 100 * substring-before(@fo:margin-right, '%'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:right">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:margin-right"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@fo:text-indent">
+ <xsl:choose>
+ <!-- When @style:auto-text-indent='true' @fo:text-indent ignored, use 283 for all font size -->
+ <xsl:when test="@style:auto-text-indent='true'">
+ <xsl:attribute name="w:first-line">283</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(@fo:text-indent, '%')">
+ <xsl:if test="../@style:parent-style-name">
+ <xsl:variable name="parent-size">
+ <xsl:value-of select="key('paragraph-style', ../@style:parent-style-name)/style:paragraph-properties/@fo:text-indent"/>
+ </xsl:variable>
+ <xsl:variable name="w-number">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$parent-size"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$w-number &lt; 0">
+ <xsl:attribute name="w:hanging">
+ <xsl:value-of select="round($w-number div -100 * substring-before(@fo:text-indent, '%'))"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:first-line">
+ <xsl:value-of select="round($w-number div 100 * substring-before(@fo:text-indent, '%'))"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="starts-with(@fo:text-indent,'-')">
+ <xsl:attribute name="w:hanging">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="substring-after(@fo:text-indent,'-')"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:first-line">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:text-indent"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </w:ind>
+ <xsl:if test="contains(@fo:background-color, '#')">
+ <w:shd w:val="clear" w:color="auto" w:fill="{substring-after(@fo:background-color, '#')}"/>
+ </xsl:if>
+ <xsl:if test="@fo:keep-with-next='true'">
+ <w:keepNext/>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@fo:widows | @fo:orphans">
+ <w:widowControl w:val="on"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:widowControl w:val="off"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@style:break-inside = 'avoid'">
+ <w:keepLines/>
+ </xsl:if>
+ <xsl:if test="@fo:hyphenate = 'false'">
+ <w:suppressAutoHyphens/>
+ </xsl:if>
+ <xsl:if test="@style:snap-to-layout-grid='false'">
+ <w:snapToGrid w:val="off"/>
+ </xsl:if>
+ <xsl:if test="style:tab-stops">
+ <w:tabs>
+ <xsl:for-each select="style:tab-stops/style:tab-stop">
+ <w:tab>
+ <xsl:choose>
+ <xsl:when test="@style:type='char'">
+ <xsl:attribute name="w:val">decimal</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:type">
+ <xsl:attribute name="w:val">
+ <xsl:value-of select="@style:type"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:val">left</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@style:leader-char">
+ <xsl:choose>
+ <xsl:when test="@style:leader-char='-'">
+ <xsl:attribute name="w:leader">hyphen</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:leader-char='_'">
+ <xsl:attribute name="w:leader">underscore</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@style:leader-char='.'">
+ <xsl:attribute name="w:leader">dot</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:leader">dot</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@style:position">
+ <xsl:attribute name="w:pos">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@style:position"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ </w:tab>
+ </xsl:for-each>
+ </w:tabs>
+ </xsl:if>
+ <xsl:if test="@style:line-break='normal'">
+ <w:kinsoku w:val="off"/>
+ </xsl:if>
+ <xsl:if test="@style:punctuation-wrap='simple'">
+ <w:overflowPunct w:val="off"/>
+ </xsl:if>
+ <xsl:if test="@style:text-autospace='none'">
+ <w:autoSpaceDE w:val="off"/>
+ <w:autoSpaceDN w:val="off"/>
+ </xsl:if>
+ <xsl:if test="@style:vertical-align">
+ <xsl:element name="w:textAlignment">
+ <xsl:choose>
+ <xsl:when test="@style:vertical-align='middle'">
+ <xsl:attribute name="w:val">center</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:val">
+ <xsl:value-of select="@style:vertical-align"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@text:number-lines='false'">
+ <w:suppressLineNumbers/>
+ </xsl:if>
+ <xsl:variable name="border-top" select="@fo:border-top | @fo:border"/>
+ <xsl:variable name="border-bottom" select="@fo:border-bottom | @fo:border"/>
+ <xsl:variable name="border-left" select="@fo:border-left | @fo:border"/>
+ <xsl:variable name="border-right" select="@fo:border-right | @fo:border"/>
+ <xsl:variable name="border-line-width-top" select="@style:border-line-width-top | @style:border-line-width "/>
+ <xsl:variable name="border-line-width-bottom" select="@style:border-line-width-bottom | @style:border-line-width"/>
+ <xsl:variable name="border-line-width-left" select="@style:border-line-width-left | @style:border-line-width"/>
+ <xsl:variable name="border-line-width-right" select="@style:border-line-width-right | @style:border-line-width"/>
+ <xsl:variable name="padding-top" select="@fo:padding-top | @fo:padding"/>
+ <xsl:variable name="padding-bottom" select="@fo:padding-bottom | @fo:padding"/>
+ <xsl:variable name="padding-left" select="@fo:padding-left | @fo:padding"/>
+ <xsl:variable name="padding-right" select="@fo:padding-right | @fo:padding"/>
+ <w:pBdr>
+ <xsl:if test="$border-top">
+ <xsl:element name="w:top">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-top"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-top"/>
+ <xsl:with-param name="so-border-position" select=" 'top' "/>
+ </xsl:call-template>
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$padding-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="@style:shadow!='none'">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-bottom">
+ <xsl:element name="w:bottom">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-bottom"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-bottom"/>
+ <xsl:with-param name="so-border-position" select=" 'bottom' "/>
+ </xsl:call-template>
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$padding-bottom"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="@style:shadow!='none'">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-left">
+ <xsl:element name="w:left">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-left"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-left"/>
+ <xsl:with-param name="so-border-position" select=" 'left' "/>
+ </xsl:call-template>
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$padding-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="@style:shadow!='none'">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$border-right">
+ <xsl:element name="w:right">
+ <xsl:call-template name="get-border">
+ <xsl:with-param name="so-border" select="$border-right"/>
+ <xsl:with-param name="so-border-line-width" select="$border-line-width-right"/>
+ <xsl:with-param name="so-border-position" select=" 'right' "/>
+ </xsl:call-template>
+ <xsl:attribute name="w:space">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$padding-right"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="@style:shadow!='none'">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="@style:shadow!='none' and not(@fo:border-top | @fo:border-bottom | @fo:border-left | @fo:border-right | @fo:border)">
+ <xsl:element name="w:right">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ <xsl:attribute name="w:val">single</xsl:attribute>
+ <xsl:variable name="shadow-size">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="substring-after(substring-after(@style:shadow, ' '), ' ')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:sz">
+ <xsl:choose>
+ <xsl:when test="$shadow-size &lt;= 0.08">12</xsl:when>
+ <xsl:when test="$shadow-size &lt;= 0.14">18</xsl:when>
+ <xsl:when test="$shadow-size &lt;= 0.20">24</xsl:when>
+ <xsl:when test="$shadow-size &lt;= 0.25">36</xsl:when>
+ <xsl:otherwise>48</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+ <xsl:element name="w:bottom">
+ <xsl:attribute name="w:shadow">on</xsl:attribute>
+ <xsl:attribute name="w:val">single</xsl:attribute>
+ <xsl:variable name="shadow-size">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="substring-after(substring-after(@style:shadow, ' '), ' ')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="w:sz">
+ <xsl:choose>
+ <xsl:when test="$shadow-size &lt;= 0.08">12</xsl:when>
+ <xsl:when test="$shadow-size &lt;= 0.14">18</xsl:when>
+ <xsl:when test="$shadow-size &lt;= 0.20">24</xsl:when>
+ <xsl:when test="$shadow-size &lt;= 0.25">36</xsl:when>
+ <xsl:otherwise>48</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </w:pBdr>
+ <w:ind>
+ <xsl:if test="$padding-left!=''">
+ <xsl:attribute name="w:left">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$padding-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$padding-right!='' ">
+ <xsl:attribute name="w:right">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="$padding-right"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ </w:ind>
+ <xsl:variable name="stylename">
+ <xsl:value-of select="../@style:name"/>
+ </xsl:variable>
+ <xsl:if test="/office:document/office:body//text:h[@text:style-name = $stylename]">
+ <xsl:variable name="headinglevel">
+ <xsl:value-of select="/office:document/office:body//text:h[@text:style-name = $stylename]/@text:level"/>
+ </xsl:variable>
+ <xsl:if test="/office:document/office:styles/text:outline-style/text:outline-level-style[@text:level = $headinglevel]">
+ <w:listPr>
+ <w:ilvl w:val="{$headinglevel -1}"/>
+ <w:ilfo w:val="1"/>
+ </w:listPr>
+ </xsl:if>
+ </xsl:if>
+ </w:pPr>
+ </xsl:template>
+ <xsl:template match="style:text-properties" mode="character">
+ <w:rPr>
+ <xsl:if test="@svg:font-family | @style:font-name | @style:font-name-asian | @style:font-name-complex">
+ <w:rFonts>
+ <xsl:variable name="fontname">
+ <xsl:choose>
+ <xsl:when test='starts-with(@svg:font-family,"&apos;")'>
+ <xsl:value-of select='substring-before(substring-after(@svg:font-family,"&apos;"),"&apos;")'/>
+ </xsl:when>
+ <xsl:when test="@svg:font-family">
+ <xsl:value-of select="@svg:font-family"/>
+ </xsl:when>
+ <xsl:when test="@style:font-name">
+ <xsl:value-of select="@style:font-name"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="string-length($fontname)!=0">
+ <xsl:attribute name="w:ascii">
+ <xsl:value-of select="$fontname"/>
+ </xsl:attribute>
+ <xsl:attribute name="w:h-ansi">
+ <xsl:value-of select="$fontname"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@style:font-name-asian">
+ <xsl:attribute name="w:fareast">
+ <xsl:value-of select="@style:font-name-asian"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@style:font-name-complex">
+ <xsl:attribute name="w:cs">
+ <xsl:value-of select="@style:font-name-complex"/>
+ </xsl:attribute>
+ </xsl:if>
+ </w:rFonts>
+ </xsl:if>
+ <!-- relative font sizes not supported yet. -->
+ <xsl:if test="contains(@fo:font-size, 'pt')">
+ <w:sz w:val="{substring-before(@fo:font-size,'pt') * 2}"/>
+ </xsl:if>
+ <xsl:if test="contains(@fo:font-size-complex, 'pt')">
+ <w:sz-cs w:val="{substring-before(@fo:font-size-complex, 'pt') * 2}"/>
+ </xsl:if>
+ <xsl:if test="@fo:font-style = 'italic' or @fo:font-style-asian = 'italic'">
+ <w:i/>
+ </xsl:if>
+ <xsl:if test="@fo:font-style-complex = 'italic'">
+ <w:i-cs/>
+ </xsl:if>
+ <xsl:if test="@fo:font-weight = 'bold' or @fo:font-weight-asian = 'bold'">
+ <w:b/>
+ </xsl:if>
+ <xsl:if test="@fo:font-weight-complex = 'bold'">
+ <w:b-cs/>
+ </xsl:if>
+ <xsl:if test="@style:text-underline-style">
+ <w:u>
+ <xsl:variable name="w-u">
+ <xsl:choose>
+ <xsl:when test="@style:text-underline-style = 'solid'">
+ <xsl:choose>
+ <xsl:when test="@style:text-underline-type = 'double'">double</xsl:when>
+ <xsl:when test="@style:text-underline-width = 'bold'">thick</xsl:when>
+ <xsl:otherwise>single</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@style:text-underline-style = 'dotted'">
+ <xsl:choose>
+ <xsl:when test="@style:text-underline-type = 'double'">dotted-double</xsl:when>
+ <xsl:when test="@style:text-underline-width = 'bold'">dotted-heavy</xsl:when>
+ <xsl:otherwise>dotted</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@style:text-underline-style = 'dash'">
+ <xsl:choose>
+ <xsl:when test="@style:text-underline-type = 'double'">dashed-double</xsl:when>
+ <xsl:when test="@style:text-underline-width = 'bold'">dashed-heavy</xsl:when>
+ <xsl:otherwise>dash</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@style:text-underline-style = 'long-dash'">
+ <xsl:choose>
+ <xsl:when test="@style:text-underline-type = 'double'">dash-long-double</xsl:when>
+ <xsl:when test="@style:text-underline-width = 'bold'">dash-long-heavy</xsl:when>
+ <xsl:otherwise>dash-long</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@style:text-underline-style = 'dot-dash'">
+ <xsl:choose>
+ <xsl:when test="@style:text-underline-type = 'double'">dot-dash-double</xsl:when>
+ <xsl:when test="@style:text-underline-width = 'bold'">dash-dot-heavy</xsl:when>
+ <xsl:otherwise>dot-dash</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@style:text-underline-style = 'dot-dot-dash'">
+ <xsl:choose>
+ <xsl:when test="@style:text-underline-type = 'double'">dot-dot-dash-double</xsl:when>
+ <xsl:when test="@style:text-underline-width = 'bold'">dash-dot-dot-heavy</xsl:when>
+ <xsl:otherwise>dot-dot-dash</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@style:text-underline-style = 'wave'">
+ <xsl:choose>
+ <xsl:when test="@style:text-underline-type = 'double'">wavy-double</xsl:when>
+ <xsl:when test="@style:text-underline-width = 'bold'">wavy-heavy</xsl:when>
+ <xsl:otherwise>wave</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@style:text-underline-style"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="w:val">
+ <xsl:value-of select="$w-u"/>
+ </xsl:attribute>
+ <xsl:if test="contains(@style:text-underline-color,'#')">
+ <xsl:attribute name="w:color">
+ <xsl:value-of select="substring-after(@style:text-underline-color,'#')"/>
+ </xsl:attribute>
+ </xsl:if>
+ </w:u>
+ </xsl:if>
+ <xsl:if test="@style:text-shadow | @fo:text-shadow">
+ <w:shadow/>
+ </xsl:if>
+ <xsl:if test="string-length(@style:text-line-through-style) &gt; 0">
+ <xsl:choose>
+ <xsl:when test="@style:text-line-through-type = 'double'">
+ <w:dstrike/>
+ </xsl:when>
+ <xsl:when test="@style:text-line-through-style = 'solid'">
+ <w:strike/>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:strike/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@fo:color">
+ <w:color>
+ <xsl:choose>
+ <xsl:when test="@fo:color != '#000000'">
+ <xsl:attribute name="w:val">
+ <xsl:value-of select="substring-after(@fo:color,'#')"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="w:val">auto</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:color>
+ </xsl:if>
+ <xsl:if test="@fo:font-variant = 'small-caps'">
+ <w:smallCaps/>
+ </xsl:if>
+ <xsl:if test="@fo:text-transform = 'uppercase'">
+ <w:caps/>
+ </xsl:if>
+ <xsl:if test="@style:font-relief = 'engraved'">
+ <w:imprint/>
+ </xsl:if>
+ <xsl:if test="@style:font-relief = 'embossed'">
+ <w:emboss/>
+ </xsl:if>
+ <xsl:if test="@style:text-outline = 'true'">
+ <w:outline/>
+ </xsl:if>
+ <xsl:if test="contains(@style:text-scale,'%')">
+ <w:w w:val="{substring-before(@style:text-scale,'%')}"/>
+ </xsl:if>
+ <xsl:if test="@style:text-emphasize">
+ <w:em>
+ <xsl:choose>
+ <xsl:when test="contains(@style:text-emphasize, 'accent')">
+ <xsl:attribute name="w:val">comma</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(@style:text-emphasize, 'disc')">
+ <xsl:attribute name="w:val">under-dot</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(@style:text-emphasize, 'none')">
+ <xsl:attribute name="w:val">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(@style:text-emphasize, 'dot below')">
+ <xsl:attribute name="w:val">under-dot</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(@style:text-emphasize, 'dot above')">
+ <xsl:attribute name="w:val">dot</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(@style:text-emphasize, 'circle')">
+ <xsl:attribute name="w:val">dot</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </w:em>
+ </xsl:if>
+ <xsl:if test="@fo:letter-spacing != 'normal'">
+ <w:spacing>
+ <xsl:attribute name="w:val">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="@fo:letter-spacing"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </w:spacing>
+ </xsl:if>
+ <xsl:if test="@style:text-blinking = 'true'">
+ <w:effect w:val="blink-background"/>
+ </xsl:if>
+ <xsl:if test="@fo:language | @fo:language-asian | @fo:language-complex">
+ <w:lang>
+ <xsl:if test="@fo:language and @fo:country">
+ <xsl:attribute name="w:val">
+ <xsl:value-of select="concat(@fo:language, '-', @fo:country)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@fo:language-asian and @fo:country-asian">
+ <xsl:attribute name="w:fareast">
+ <xsl:value-of select="concat(@fo:language-asian, '-', @fo:country-asian)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@fo:language-complex and @fo:language-complex">
+ <xsl:attribute name="w:bidi">
+ <xsl:value-of select="concat(@fo:language-complex, '-', @fo:language-complex)"/>
+ </xsl:attribute>
+ </xsl:if>
+ </w:lang>
+ </xsl:if>
+ <xsl:if test="@style:text-position">
+ <xsl:variable name="position">
+ <xsl:choose>
+ <xsl:when test="starts-with(@style:text-position, 'super')">superscript_0</xsl:when>
+ <xsl:when test="starts-with(@style:text-position, 'sub')">subscript_0</xsl:when>
+ <xsl:when test="starts-with(@style:text-position, '-')">
+ <xsl:value-of select="concat('subscript_', substring-before(@style:text-position,'%'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('superscript_', substring-before(@style:text-position,'%'))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <w:vertAlign>
+ <xsl:attribute name="w:val">
+ <xsl:value-of select="substring-before($position,'_')"/>
+ </xsl:attribute>
+ </w:vertAlign>
+ <!-- Raised/Lowed position is difficult to map to MSWord w:position, Writer use %, but Word use half-point(not relative position). Since it's difficult to get font-size, use 12pt as default font-size -->
+ <w:position>
+ <xsl:attribute name="w:val">
+ <xsl:choose>
+ <xsl:when test="substring-after($position, '_') = 0">0</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="round(substring-after($position, '_') div 6)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </w:position>
+ </xsl:if>
+ <xsl:if test="@text:display = 'true'">
+ <w:vanish/>
+ </xsl:if>
+ <xsl:if test="contains(@fo:background-color, '#')">
+ <w:shd w:val="clear" w:color="auto" w:fill="{substring-after(@fo:background-color, '#')}"/>
+ </xsl:if>
+ </w:rPr>
+ </xsl:template>
+ <xsl:template match="text:p | text:h">
+ <w:p>
+ <w:pPr>
+ <xsl:if test="@text:style-name">
+ <w:pStyle w:val="{@text:style-name}"/>
+ </xsl:if>
+ <xsl:if test="@text:level">
+ <w:outlineLvl w:val="{@text:level - 1}"/>
+ </xsl:if>
+ <xsl:variable name="following-paragraph-heading-table" select="following::*[(name()= 'text:p' or name()= 'text:h' or name()= 'table:table')]"/>
+ <xsl:variable name="following-section" select="following::text:section[1]"/>
+ <xsl:variable name="ancestor-section" select="ancestor::text:section"/>
+ <!-- if the following neighbour paragraph/heading are slave of one master style, or new section starts,
+ then a new page will start -->
+ <xsl:variable name="next-is-new-page" select="boolean(key( 'slave-style', $following-paragraph-heading-table[1]/@*[name()='text:style-name' or name()='table:style-name']))"/>
+ <xsl:variable name="next-is-new-section">
+ <xsl:if test="$following-section and generate-id($following-section/descendant::*[(name()= 'text:p' or name()= 'text:h' or name()= 'table:table') and position() =1]) = generate-id($following-paragraph-heading-table[1])">
+ <xsl:value-of select="'yes'"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="next-is-section-end">
+ <xsl:if test="$ancestor-section and generate-id($ancestor-section[1]/following::*[(name()= 'text:p' or name()= 'text:h' or name()= 'table:table') and position() =1]) = generate-id($following-paragraph-heading-table[1])">
+ <xsl:value-of select="'yes'"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:if test="ancestor::office:body and not(ancestor::text:footnote or ancestor::text:endnote) and ($next-is-new-page or $next-is-new-section = 'yes' or $next-is-section-end = 'yes')">
+ <w:sectPr>
+ <xsl:apply-templates select="/office:document/office:styles/text:footnotes-configuration">
+ <xsl:with-param name="within-section" select="'yes'"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="/office:document/office:styles/text:endnotes-configuration">
+ <xsl:with-param name="within-section" select="'yes'"/>
+ </xsl:apply-templates>
+ <xsl:choose>
+ <xsl:when test="key( 'slave-style', @*[name()='text:style-name' or name()='table:style-name'])">
+ <xsl:apply-templates select="key('master-page', key( 'slave-style', @*[name()='text:style-name' or name()='table:style-name'])[1]/@style:master-page-name)"/>
+ <xsl:if test="$ancestor-section">
+ <xsl:apply-templates select="key('section-style',$ancestor-section[1]/@text:style-name)" mode="section">
+ <xsl:with-param name="master-page" select="key( 'page-layout', key('master-page', key( 'slave-style', @*[name()='text:style-name' or name()='table:style-name'])[1]/@style:master-page-name)/@style:page-layout-name)"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ <xsl:if test="key( 'slave-style', @*[name()='text:style-name' or name()='table:style-name'])/style:paragraph-properties/@style:page-number">
+ <!-- in M$ word the header and footer associate with the w:sectPr, but in StarOffice writer the header and footer associate with the style:master-page -->
+ <xsl:variable name="pagenumber_start">
+ <xsl:value-of select=" key( 'slave-style', @*[name()='text:style-name' or name()='table:style-name'])/style:paragraph-properties/@style:page-number"/>
+ </xsl:variable>
+ <xsl:if test=" number($pagenumber_start) &gt; 0 ">
+ <w:pgNumType w:start="{$pagenumber_start}"/>
+ </xsl:if>
+ <!-- comment out the below line to enable the header and footer display normally when style:page-number =0 -->
+ <!--w:pgNumType w:start="{key( 'slave-style', @*[name()='text:style-name' or name()='table:style-name'])/style:paragraph-properties/@style:page-number}"/ -->
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="preceding-style" select="preceding::*[(name()= 'text:p' or name()= 'text:h' or name()= 'table:table') and key( 'slave-style', @*[name()='text:style-name' or name()='table:style-name'])]"/>
+ <xsl:choose>
+ <xsl:when test="$preceding-style">
+ <xsl:apply-templates select="key('master-page', key( 'slave-style', $preceding-style[1]/@*[name()='text:style-name' or name()='table:style-name'])[1]/@style:master-page-name)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="/office:document/office:master-styles/style:master-page[1]"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$ancestor-section">
+ <xsl:choose>
+ <xsl:when test="$preceding-style">
+ <xsl:apply-templates select="key('section-style',$ancestor-section[1]/@text:style-name)" mode="section">
+ <xsl:with-param name="master-page" select="key( 'page-layout', key('master-page', key( 'slave-style', $preceding-style[1]/@*[name()='text:style-name' or name()='table:style-name'])[1]/@style:master-page-name)/@style:page-layout-name)"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="key('section-style',$ancestor-section[1]/@text:style-name)" mode="section">
+ <xsl:with-param name="master-page" select="/office:document/office:automatic-styles/style:page-layout[1]"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:sectPr>
+ </xsl:if>
+ <!-- add for office:annotation style G.Y. -->
+ <xsl:if test="name(..)= 'office:annotation' ">
+ <w:pStyle w:val="CommentText"/>
+ </xsl:if>
+ <!-- add by wym for listPr -->
+ <xsl:if test="ancestor::text:ordered-list | ancestor::text:unordered-list | ancestor::text:list">
+ <xsl:variable name="listname">
+ <xsl:value-of select="ancestor::text:ordered-list/@text:style-name | ancestor::text:unordered-list/@text:style-name | ancestor::text:list/@text:style-name"/>
+ </xsl:variable>
+ <xsl:variable name="currlevel">
+ <xsl:value-of select="count(ancestor::text:list-item|ancestor::text:list-header)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($listname)!=0 and $currlevel &lt; 10">
+ <xsl:variable name="currlist">
+ <xsl:apply-templates select="key('list-style', $listname)" mode="count"/>
+ </xsl:variable>
+ <w:listPr>
+ <w:ilvl w:val="{number($currlevel)-1}"/>
+ <w:ilfo w:val="{$currlist}"/>
+ </w:listPr>
+ </xsl:when>
+ <xsl:when test="string-length($listname)!=0">
+ <xsl:for-each select="key('list-style', $listname)">
+ <xsl:variable name="spacebefore">
+ <xsl:choose>
+ <xsl:when test="*[@text:level=$currlevel]/style:list-level-properties/@text:space-before">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="*[@text:level=$currlevel]/style:list-level-properties/@text:space-before"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="space2text">
+ <xsl:choose>
+ <xsl:when test="*[@text:level=$currlevel]/style:list-level-properties/@text:min-label-width">
+ <xsl:call-template name="convert2twip">
+ <xsl:with-param name="value" select="*[@text:level=$currlevel]/style:list-level-properties/@text:min-label-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <w:ind w:left="{number($space2text)+number($spacebefore)}" w:hanging="{$space2text}"/>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:listPr>
+ <w:ilvl w:val="{number($currlevel)-1}"/>
+ <w:ilfo w:val="1"/>
+ </w:listPr>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <!-- end of listPr -->
+ </w:pPr>
+ <!-- get break column from style -->
+ <xsl:variable name="style" select="key('paragraph-style', @text:style-name)/style:paragraph-properties"/>
+ <xsl:if test="$style/@fo:break-before = 'column'">
+ <w:r>
+ <w:br w:type="column"/>
+ </w:r>
+ </xsl:if>
+ <xsl:if test="parent::office:text and not(preceding-sibling::text:p)">
+ <xsl:call-template name="PageLevelGraphic"/>
+ </xsl:if>
+ <xsl:if test="parent::text:footnote-body and not(preceding-sibling::*)">
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="{/office:document/office:styles/text:footnotes-configuration/@text:citation-style-name}"/>
+ </w:rPr>
+ <xsl:choose>
+ <xsl:when test="../../text:footnote-citation/@text:label">
+ <w:t>
+ <xsl:value-of select="../../text:footnote-citation/@text:label"/>
+ </w:t>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:footnoteRef/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:r>
+ <w:r>
+ <w:tab/>
+ </w:r>
+ </xsl:if>
+ <xsl:if test="parent::text:endnote-body and not(preceding-sibling::*)">
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="{/office:document/office:styles/text:endnotes-configuration/@text:citation-style-name}"/>
+ </w:rPr>
+ <xsl:choose>
+ <xsl:when test="../../text:endnote-citation/@text:label">
+ <w:t>
+ <xsl:value-of select="../../text:endnote-citation/@text:label"/>
+ </w:t>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:endnoteRef/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:r>
+ <w:r>
+ <w:tab/>
+ </w:r>
+ </xsl:if>
+ <!-- newly added the endnote , footnote templates -->
+ <xsl:if test="../../@text:note-class='endnote' and not(preceding-sibling::*)">
+ <xsl:message>
+ <xsl:value-of select=" 'enter into ext:note-class= endnote' "/>
+ </xsl:message>
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="Endnote_20_Symbol"/>
+ </w:rPr>
+ <xsl:choose>
+ <xsl:when test="../../text:note-citation/@text:label">
+ <w:t>
+ <xsl:value-of select="../../text:note-citation/@text:label"/>
+ </w:t>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:footnoteRef/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:r>
+ <w:r>
+ <w:tab/>
+ </w:r>
+ </xsl:if>
+ <xsl:if test="../../@text:note-class='footnote' and not(preceding-sibling::*)">
+ <xsl:message>
+ <xsl:value-of select=" 'enter into ext:note-class= footnote' "/>
+ </xsl:message>
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="Footnote_20_Symbol"/>
+ </w:rPr>
+ <xsl:choose>
+ <xsl:when test="../../text:note-citation/@text:label">
+ <w:t>
+ <xsl:value-of select="../../text:note-citation/@text:label"/>
+ </w:t>
+ </xsl:when>
+ <xsl:otherwise>
+ <w:footnoteRef/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </w:r>
+ <w:r>
+ <w:tab/>
+ </w:r>
+ </xsl:if>
+ <!-- apply inline-text-elements, many many many ... :( glu -->
+ <xsl:apply-templates select="text:a | text:span | text() | text:hidden-text | text:line-break | text:tab-stop
+ | text:s | text:note | draw:*
+ | text:page-number | text:page-count | text:subject | text:initial-creator | text:title | text:date | text:time
+ | text:author-name | text:author-initials | text:chapter | text:file-name | text:sender-company
+ | text:sender-firstname | text:sender-lastname | text:sender-initials | text:sender-street
+ | text:sender-country | text:sender-postal-code | text:sender-city | text:sender-title | text:sender-position
+ | text:sender-phone-private | text:sender-phone-work | text:sender-email | text:sender-fax
+ | text:sender-state-or-province | text:word-count | text:paragraph-count | text:character-count
+ | text:table-count | text:image-count | text:object-count | text:template-name | text:description
+ | text:creation-time | text:creation-date | text:editing-cycles | text:editing-duration | text:keywords
+ | text:print-time | text:print-date | text:creator | text:modification-time | text:modification-date
+ | text:user-defined | text:printed-by | text:hidden-paragraph | text:placeholder | text:drop-down
+ | text:conditional-text | text:text-input | text:execute-macro | text:variable-set | text:variable-input
+ | text:user-field-input | text:variable-get | text:user-field-get | text:sequence | text:page-variable-set
+ | text:page-variable-get | text:table-formula | text:database-display | text:database-next
+ | text:database-select | text:database-row-number | text:database-name | text:reference-ref
+ | text:bookmark-ref | text:footnote-ref | text:endnote-ref | text:sequence-ref | text:expression
+ | text:measure | text:dde-connection | text:sheet-name | text:bibliography-mark | text:script
+ | text:page-continuation | office:annotation | text:bookmark-start | text:bookmark-end | text:bookmark
+ "/>
+ <!-- comment out the following line to replace the text:footnote , text:endnote with text:note in OASIS format -->
+ <!--xsl:apply-templates select="text:a | text:span | text() | text:hidden-text | text:line-break | text:tab-stop
+ | text:s | text:footnote | text:endnote | draw:*
+ | text:page-number | text:page-count | text:subject | text:initial-creator | text:title | text:date | text:time
+ | text:author-name | text:author-initials | text:chapter | text:file-name | text:sender-company
+ | text:sender-firstname | text:sender-lastname | text:sender-initials | text:sender-street
+ | text:sender-country | text:sender-postal-code | text:sender-city | text:sender-title | text:sender-position
+ | text:sender-phone-private | text:sender-phone-work | text:sender-email | text:sender-fax
+ | text:sender-state-or-province | text:word-count | text:paragraph-count | text:character-count
+ | text:table-count | text:image-count | text:object-count | text:template-name | text:description
+ | text:creation-time | text:creation-date | text:editing-cycles | text:editing-duration | text:keywords
+ | text:print-time | text:print-date | text:creator | text:modification-time | text:modification-date
+ | text:user-defined | text:printed-by | text:hidden-paragraph | text:placeholder | text:drop-down
+ | text:conditional-text | text:text-input | text:execute-macro | text:variable-set | text:variable-input
+ | text:user-field-input | text:variable-get | text:user-field-get | text:sequence | text:page-variable-set
+ | text:page-variable-get | text:table-formula | text:database-display | text:database-next
+ | text:database-select | text:database-row-number | text:database-name | text:reference-ref
+ | text:bookmark-ref | text:footnote-ref | text:endnote-ref | text:sequence-ref | text:expression
+ | text:measure | text:dde-connection | text:sheet-name | text:bibliography-mark | text:script
+ | text:page-continuation | office:annotation | text:bookmark-start | text:bookmark-end | text:bookmark
+ "/-->
+ <xsl:if test="$style/@fo:break-after">
+ <w:r>
+ <w:br w:type="{$style/@fo:break-after}"/>
+ </w:r>
+ </xsl:if>
+ </w:p>
+ </xsl:template>
+ <xsl:template match="text:span">
+ <!-- apply inline-text-elements, many many many ... :( glu -->
+ <xsl:apply-templates select="text:a | text() | text:hidden-text | text:line-break | text:tab-stop | text:s
+ | text:note
+ | text:page-number | text:page-count | text:subject | text:initial-creator | text:title | text:date | text:time
+ | text:author-name | text:author-initials | text:chapter | text:file-name | text:sender-company
+ | text:sender-firstname | text:sender-lastname | text:sender-initials | text:sender-street
+ | text:sender-country | text:sender-postal-code | text:sender-city | text:sender-title | text:sender-position
+ | text:sender-phone-private | text:sender-phone-work | text:sender-email | text:sender-fax
+ | text:sender-state-or-province | text:word-count | text:paragraph-count | text:character-count
+ | text:table-count | text:image-count | text:object-count | text:template-name | text:description
+ | text:creation-time | text:creation-date | text:editing-cycles | text:editing-duration | text:keywords
+ | text:print-time | text:print-date | text:creator | text:modification-time | text:modification-date
+ | text:user-defined | text:printed-by | text:hidden-paragraph | text:placeholder | text:drop-down
+ | text:conditional-text | text:text-input | text:execute-macro | text:variable-set | text:variable-input
+ | text:user-field-input | text:variable-get | text:user-field-get | text:sequence | text:page-variable-set
+ | text:page-variable-get | text:table-formula | text:database-display | text:database-next
+ | text:database-select | text:database-row-number | text:database-name | text:reference-ref
+ | text:bookmark-ref | text:footnote-ref | text:endnote-ref | text:sequence-ref | text:expression
+ | text:measure | text:dde-connection | text:sheet-name | text:bibliography-mark | text:script
+ | text:page-continuation | office:annotation | text:bookmark-start | text:bookmark-end | text:bookmark
+"/>
+ <!-- comment out the following line to replace the text:footnote , text:endnote with text:note in OASIS format -->
+ <!-- xsl:apply-templates select="text:a | text() | text:hidden-text | text:line-break | text:tab-stop | text:s
+ | text:footnote | text:endnote
+ | text:page-number | text:page-count | text:subject | text:initial-creator | text:title | text:date | text:time
+ | text:author-name | text:author-initials | text:chapter | text:file-name | text:sender-company
+ | text:sender-firstname | text:sender-lastname | text:sender-initials | text:sender-street
+ | text:sender-country | text:sender-postal-code | text:sender-city | text:sender-title | text:sender-position
+ | text:sender-phone-private | text:sender-phone-work | text:sender-email | text:sender-fax
+ | text:sender-state-or-province | text:word-count | text:paragraph-count | text:character-count
+ | text:table-count | text:image-count | text:object-count | text:template-name | text:description
+ | text:creation-time | text:creation-date | text:editing-cycles | text:editing-duration | text:keywords
+ | text:print-time | text:print-date | text:creator | text:modification-time | text:modification-date
+ | text:user-defined | text:printed-by | text:hidden-paragraph | text:placeholder | text:drop-down
+ | text:conditional-text | text:text-input | text:execute-macro | text:variable-set | text:variable-input
+ | text:user-field-input | text:variable-get | text:user-field-get | text:sequence | text:page-variable-set
+ | text:page-variable-get | text:table-formula | text:database-display | text:database-next
+ | text:database-select | text:database-row-number | text:database-name | text:reference-ref
+ | text:bookmark-ref | text:footnote-ref | text:endnote-ref | text:sequence-ref | text:expression
+ | text:measure | text:dde-connection | text:sheet-name | text:bibliography-mark | text:script
+ | text:page-continuation | office:annotation | text:bookmark-start | text:bookmark-end | text:bookmark
+"/-->
+ </xsl:template>
+ <xsl:template match="text()">
+ <xsl:if test="string-length(normalize-space(.)) &gt; 0">
+ <w:r>
+ <xsl:if test="parent::text:span">
+ <w:rPr>
+ <w:rStyle w:val="{parent::text:span/@text:style-name}"/>
+ </w:rPr>
+ </xsl:if>
+ <w:t>
+ <xsl:value-of select="."/>
+ </w:t>
+ </w:r>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="text:hidden-text">
+ <w:r>
+ <w:rPr>
+ <xsl:if test="parent::text:span">
+ <w:rStyle w:val="{parent::text:span/@text:style-name}"/>
+ </xsl:if>
+ <w:vanish/>
+ </w:rPr>
+ <w:t>
+ <xsl:value-of select="@text:string-value"/>
+ </w:t>
+ </w:r>
+ </xsl:template>
+ <xsl:template match="text:line-break">
+ <w:r>
+ <xsl:if test="parent::text:span">
+ <w:rPr>
+ <w:rStyle w:val="{parent::text:span/@text:style-name}"/>
+ </w:rPr>
+ </xsl:if>
+ <w:br w:type="text-wrapping" w:clear="all"/>
+ </w:r>
+ </xsl:template>
+ <xsl:template match="text:tab-stop">
+ <w:r>
+ <xsl:if test="parent::text:span">
+ <w:rPr>
+ <w:rStyle w:val="{parent::text:span/@text:style-name}"/>
+ </w:rPr>
+ </xsl:if>
+ <w:tab/>
+ </w:r>
+ </xsl:template>
+ <xsl:template match="text:s">
+ <w:r>
+ <xsl:if test="parent::text:span">
+ <w:rPr>
+ <w:rStyle w:val="{parent::text:span/@text:style-name}"/>
+ </w:rPr>
+ </xsl:if>
+ <w:t>
+ <xsl:if test="@text:c">
+ <xsl:call-template name="add-space">
+ <xsl:with-param name="number" select="@text:c"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:text> </xsl:text>
+ </w:t>
+ </w:r>
+ </xsl:template>
+ <xsl:template name="add-space">
+ <xsl:param name="number"/>
+ <xsl:if test="$number &gt; 1">
+ <xsl:call-template name="add-space">
+ <xsl:with-param name="number" select="$number - 1"/>
+ </xsl:call-template>
+ <xsl:text> </xsl:text>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="text:footnote">
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="{/office:document/office:styles/text:footnotes-configuration/@text:citation-body-style-name}"/>
+ </w:rPr>
+ <xsl:apply-templates select="text:footnote-body"/>
+ </w:r>
+ </xsl:template>
+ <xsl:template match="text:footnote-body">
+ <w:footnote>
+ <xsl:if test="../text:footnote-citation/@text:label">
+ <xsl:attribute name="w:suppressRef">on</xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="text:h | text:p | text:ordered-list | text:unordered-list | text:list"/>
+ </w:footnote>
+ </xsl:template>
+ <xsl:template match="text:endnote">
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="{/office:document/office:styles/text:endnotes-configuration/@text:citation-body-style-name}"/>
+ </w:rPr>
+ <xsl:apply-templates select="text:endnote-body"/>
+ </w:r>
+ </xsl:template>
+ <xsl:template match="text:endnote-body">
+ <w:endnote>
+ <xsl:if test="../text:endnote-citation/@text:label">
+ <xsl:attribute name="w:suppressRef">on</xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="text:h | text:p | text:ordered-list | text:unordered-list | text:list"/>
+ </w:endnote>
+ </xsl:template>
+ <xsl:template match="text:bookmark-start">
+ <xsl:variable name="bookmark-id">
+ <xsl:number from="/office:document/office:body" count="text:bookmark | text:bookmark-start" level="any" format="1"/>
+ </xsl:variable>
+ <aml:annotation aml:id="{$bookmark-id}" w:type="Word.Bookmark.Start" w:name="{@text:name}"/>
+ </xsl:template>
+ <xsl:template match="text:bookmark-end">
+ <xsl:variable name="bookmark-id">
+ <xsl:number from="/office:document/office:body" count="text:bookmark | text:bookmark-start" level="any" format="1"/>
+ </xsl:variable>
+ <aml:annotation aml:id="{$bookmark-id}" w:type="Word.Bookmark.End"/>
+ </xsl:template>
+ <xsl:template match="text:bookmark">
+ <xsl:variable name="bookmark-id">
+ <xsl:number from="/office:document/office:body" count="text:bookmark | text:bookmark-start" level="any" format="1"/>
+ </xsl:variable>
+ <aml:annotation aml:id="{$bookmark-id}" w:type="Word.Bookmark.Start" w:name="{@text:name}"/>
+ <aml:annotation aml:id="{$bookmark-id}" w:type="Word.Bookmark.End"/>
+ </xsl:template>
+ <!-- newly added the endnote , footnote templates -->
+ <xsl:template match="text:note">
+ <xsl:choose>
+ <xsl:when test="@text:note-class = 'endnote' ">
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="Endnote"/>
+ </w:rPr>
+ <xsl:apply-templates select="text:note-body"/>
+ </w:r>
+ </xsl:when>
+ <xsl:when test="@text:note-class = 'footnote' ">
+ <w:r>
+ <w:rPr>
+ <w:rStyle w:val="Footnote"/>
+ </w:rPr>
+ <xsl:apply-templates select="text:note-body"/>
+ </w:r>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="text:note-body">
+ <xsl:choose>
+ <xsl:when test="../@text:note-class='endnote' ">
+ <w:endnote>
+ <xsl:if test="../text:note-citation/@text:label">
+ <xsl:attribute name="w:suppressRef">on</xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="text:h | text:p | text:ordered-list | text:unordered-list | text:list"/>
+ </w:endnote>
+ </xsl:when>
+ <xsl:when test="../@text:note-class='footnote' ">
+ <w:footnote>
+ <xsl:if test="../text:note-citation/@text:label">
+ <xsl:attribute name="w:suppressRef">on</xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="text:h | text:p | text:ordered-list | text:unordered-list | text:list"/>
+ </w:footnote>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/common/ms2ooo_docpr.xsl b/filter/source/xslt/import/common/ms2ooo_docpr.xsl
new file mode 100644
index 000000000..6a10f93f7
--- /dev/null
+++ b/filter/source/xslt/import/common/ms2ooo_docpr.xsl
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt fo v">
+ <xsl:template match="o:DocumentProperties">
+ <office:meta>
+ <meta:generator>Microsoft Word 2003</meta:generator>
+ <dc:title>
+ <xsl:value-of select="o:Title"/>
+ </dc:title>
+ <dc:description>
+ <xsl:value-of select="o:Description"/>
+ </dc:description>
+ <dc:subject>
+ <xsl:value-of select="o:Subject"/>
+ </dc:subject>
+ <meta:initial-creator>
+ <xsl:value-of select="o:Author"/>
+ </meta:initial-creator>
+ <meta:creation-date>
+ <xsl:value-of select="substring-before( o:Created, 'Z')"/>
+ </meta:creation-date>
+ <dc:creator>
+ <xsl:value-of select="o:LastAuthor"/>
+ </dc:creator>
+ <xsl:if test="string-length(substring-before( o:LastSaved, 'Z')) &gt; 0">
+ <dc:date>
+ <xsl:value-of select="substring-before( o:LastSaved, 'Z')"/>
+ </dc:date>
+ </xsl:if>
+ <!-- comment out the below line now because Oasis format doesn't allow the meta:print-by to be empty element -->
+ <!--meta:printed-by /-->
+ <xsl:if test="string-length(substring-before( o:LastPrinted, 'Z')) &gt; 0">
+ <!--
+ <meta:print-date>
+ <xsl:value-of select="substring-before( o:LastPrinted, 'Z')"/>
+ </meta:print-date>
+ -->
+ </xsl:if>
+ <meta:keyword>
+ <xsl:value-of select="o:Keywords"/>
+ </meta:keyword>
+ <meta:editing-cycles>
+ <xsl:value-of select="o:Revision"/>
+ </meta:editing-cycles>
+ <meta:editing-duration>
+ <xsl:if test="o:TotalTime">
+ <xsl:value-of select="concat('PT', floor(o:TotalTime div 60), 'H', o:TotalTime mod 60, 'M0S')"/>
+ </xsl:if>
+ </meta:editing-duration>
+ <meta:user-defined meta:name="Category" meta:value-type="string">
+ <xsl:value-of select="o:Category"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Manager" meta:value-type="string">
+ <xsl:value-of select="o:Manager"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Company" meta:value-type="string">
+ <xsl:value-of select="o:Company"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Version" meta:value-type="string">
+ <xsl:value-of select="o:Version"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="HyperlinkBase" meta:value-type="string">
+ <xsl:value-of select="o:HyperlinkBase"/>
+ </meta:user-defined>
+ <xsl:apply-templates select="../o:CustomDocumentProperties"/>
+ <meta:document-statistic meta:page-count="{o:Pages}" meta:paragraph-count="{o:Paragraphs}" meta:word-count="{o:Words}" meta:character-count="{o:Characters}"/>
+ </office:meta>
+ </xsl:template>
+ <xsl:template match="o:CustomDocumentProperties">
+ <xsl:for-each select="node()[@dt:dt]">
+ <meta:user-defined meta:name="{local-name()}" meta:value-type="{@dt:dt}">
+ <xsl:value-of select="."/>
+ </meta:user-defined>
+ </xsl:for-each>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/spreadsheetml/adorowset2ods.xsl b/filter/source/xslt/import/spreadsheetml/adorowset2ods.xsl
new file mode 100644
index 000000000..0d36494d2
--- /dev/null
+++ b/filter/source/xslt/import/spreadsheetml/adorowset2ods.xsl
@@ -0,0 +1,216 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
+ xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
+ xmlns:rs="urn:schemas-microsoft-com:rowset"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
+ xmlns:z="#RowsetSchema">
+ <xsl:output indent="no" version="1.0" encoding="UTF-8" method="xml"/>
+ <xsl:template match="/">
+ <office:document office:mimetype="application/vnd.oasis.opendocument.spreadsheet" office:version="1.0">
+ <xsl:element name="office:body">
+ <xsl:element name="office:spreadsheet">
+ <!-- Just a single table (sheet) with default name -->
+ <xsl:element name="table:table">
+ <!-- declare columns -->
+ <xsl:for-each select="./xml/s:Schema/s:ElementType[@name='row']/s:AttributeType">
+ <xsl:element name="table:table-column"/>
+ </xsl:for-each>
+ <!-- header row from Schema -->
+ <xsl:element name="table:table-row">
+ <xsl:for-each select="./xml/s:Schema/s:ElementType[@name='row']/s:AttributeType">
+ <xsl:element name="table:table-cell">
+ <xsl:attribute name="office:value-type">string</xsl:attribute>
+ <xsl:attribute name="calcext:value-type">string</xsl:attribute>
+ <xsl:element name="text:p">
+ <!-- User-readable field name may be defined in optional @rs:name -->
+ <xsl:choose>
+ <xsl:when test="./@rs:name">
+ <xsl:value-of select="./@rs:name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ <!-- Now add data itself -->
+ <xsl:apply-templates select="./xml/rs:data"/>
+ </xsl:element>
+ <!-- Add autofilter to the whole range -->
+ <xsl:element name="table:database-ranges">
+ <xsl:element name="table:database-range">
+ <xsl:attribute name="table:target-range-address">
+ <xsl:call-template name="RangeName">
+ <xsl:with-param name="rowStartNum" select="1"/>
+ <xsl:with-param name="colStartNum" select="1"/>
+ <xsl:with-param name="rowEndNum" select="count(/xml/rs:data/row)+1"/>
+ <xsl:with-param name="colEndNum" select="count(/xml/s:Schema/s:ElementType[@name='row']/s:AttributeType)"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="table:display-filter-buttons">true</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </office:document>
+ </xsl:template>
+ <xsl:template match="rs:data">
+ <xsl:apply-templates select="./row"/>
+ <xsl:apply-templates select="./z:row"/>
+ </xsl:template>
+ <xsl:template match="row|z:row">
+ <xsl:element name="table:table-row">
+ <!-- Store current row in a variable -->
+ <xsl:variable name="thisRow" select="."/>
+ <!-- Get column order from Schema -->
+ <xsl:for-each select="/xml/s:Schema/s:ElementType[@name='row']/s:AttributeType">
+ <xsl:element name="table:table-cell">
+ <xsl:variable name="thisColName" select="./@name"/>
+ <xsl:variable name="thisCellValue">
+ <xsl:value-of select="$thisRow/@*[local-name()=$thisColName]"/>
+ </xsl:variable>
+ <xsl:if test="string-length($thisCellValue) &gt; 0">
+ <xsl:variable name="thisColType">
+ <xsl:call-template name="ValTypeFromAttributeType">
+ <xsl:with-param name="AttributeTypeNode" select="."/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="office:value-type"><xsl:value-of select="$thisColType"/></xsl:attribute>
+ <xsl:attribute name="calcext:value-type"><xsl:value-of select="$thisColType"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$thisColType='float'">
+ <xsl:attribute name="office:value"><xsl:value-of select="$thisCellValue"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$thisColType='date'">
+ <!-- We need to convert '2017-04-06 00:40:40' to '2017-04-06T00:40:40', so replace space with 'T' -->
+ <xsl:attribute name="office:date-value"><xsl:value-of select="translate($thisCellValue,' ','T')"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$thisColType='time'">
+ <xsl:attribute name="office:time-value"><xsl:value-of select="$thisCellValue"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$thisColType='boolean'">
+ <xsl:attribute name="office:boolean-value">
+ <xsl:choose>
+ <xsl:when test="$thisCellValue=0">false</xsl:when>
+ <xsl:otherwise>true</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:element name="text:p">
+ <xsl:value-of select="$thisCellValue"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <!-- https://msdn.microsoft.com/en-us/library/ms675943 -->
+ <xsl:template name="ValTypeFromAttributeType">
+ <xsl:param name="AttributeTypeNode"/>
+ <xsl:variable name="thisDataType">
+ <xsl:choose>
+ <xsl:when test="$AttributeTypeNode/@dt:type"><xsl:value-of select="$AttributeTypeNode/@dt:type"/></xsl:when>
+ <xsl:when test="$AttributeTypeNode/s:datatype"><xsl:value-of select="$AttributeTypeNode/s:datatype/@dt:type"/></xsl:when>
+ <xsl:otherwise>string</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="XMLDataType2ValType">
+ <xsl:with-param name="XMLDataType" select="$thisDataType"/>
+ </xsl:call-template>
+ </xsl:template>
+ <!-- https://www.w3.org/TR/1998/NOTE-XML-data-0105/#API -->
+ <xsl:template name="XMLDataType2ValType">
+ <xsl:param name="XMLDataType"/>
+ <xsl:choose>
+ <xsl:when test="$XMLDataType='number'">float</xsl:when>
+ <xsl:when test="$XMLDataType='int'">float</xsl:when>
+ <xsl:when test="starts-with($XMLDataType, 'float')">float</xsl:when>
+ <xsl:when test="starts-with($XMLDataType, 'fixed')">float</xsl:when>
+ <xsl:when test="$XMLDataType='i1'">float</xsl:when>
+ <xsl:when test="$XMLDataType='i2'">float</xsl:when>
+ <xsl:when test="$XMLDataType='i4'">float</xsl:when>
+ <xsl:when test="$XMLDataType='i8'">float</xsl:when>
+ <xsl:when test="$XMLDataType='ui1'">float</xsl:when>
+ <xsl:when test="$XMLDataType='ui2'">float</xsl:when>
+ <xsl:when test="$XMLDataType='ui4'">float</xsl:when>
+ <xsl:when test="$XMLDataType='ui8'">float</xsl:when>
+ <xsl:when test="$XMLDataType='r4'">float</xsl:when>
+ <xsl:when test="$XMLDataType='r8'">float</xsl:when>
+ <xsl:when test="$XMLDataType='datetime'">date</xsl:when>
+ <xsl:when test="starts-with($XMLDataType, 'dateTime')">date</xsl:when>
+ <xsl:when test="starts-with($XMLDataType, 'date')">date</xsl:when>
+ <xsl:when test="starts-with($XMLDataType, 'time')">time</xsl:when>
+ <xsl:when test="$XMLDataType='boolean'">boolean</xsl:when>
+ <xsl:otherwise>string</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- A utility to convert a column number (e.g. 27; 1-based) to column name (like AA) -->
+ <xsl:template name="ColNum2Name">
+ <xsl:param name="num"/>
+ <xsl:if test="$num > 0">
+ <xsl:call-template name="ColNum2Name">
+ <xsl:with-param name="num" select="floor($num div 26)"/>
+ </xsl:call-template>
+ <xsl:choose>
+ <xsl:when test="$num mod 26 = 1">A</xsl:when>
+ <xsl:when test="$num mod 26 = 2">B</xsl:when>
+ <xsl:when test="$num mod 26 = 3">C</xsl:when>
+ <xsl:when test="$num mod 26 = 4">D</xsl:when>
+ <xsl:when test="$num mod 26 = 5">E</xsl:when>
+ <xsl:when test="$num mod 26 = 6">F</xsl:when>
+ <xsl:when test="$num mod 26 = 7">G</xsl:when>
+ <xsl:when test="$num mod 26 = 8">H</xsl:when>
+ <xsl:when test="$num mod 26 = 9">I</xsl:when>
+ <xsl:when test="$num mod 26 = 10">J</xsl:when>
+ <xsl:when test="$num mod 26 = 11">K</xsl:when>
+ <xsl:when test="$num mod 26 = 12">L</xsl:when>
+ <xsl:when test="$num mod 26 = 13">M</xsl:when>
+ <xsl:when test="$num mod 26 = 14">N</xsl:when>
+ <xsl:when test="$num mod 26 = 15">O</xsl:when>
+ <xsl:when test="$num mod 26 = 16">P</xsl:when>
+ <xsl:when test="$num mod 26 = 17">Q</xsl:when>
+ <xsl:when test="$num mod 26 = 18">R</xsl:when>
+ <xsl:when test="$num mod 26 = 19">S</xsl:when>
+ <xsl:when test="$num mod 26 = 20">T</xsl:when>
+ <xsl:when test="$num mod 26 = 21">U</xsl:when>
+ <xsl:when test="$num mod 26 = 22">V</xsl:when>
+ <xsl:when test="$num mod 26 = 23">W</xsl:when>
+ <xsl:when test="$num mod 26 = 24">X</xsl:when>
+ <xsl:when test="$num mod 26 = 25">Y</xsl:when>
+ <xsl:otherwise>Z</xsl:otherwise><!-- 0 -->
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <!-- A utility to convert a cell address (e.g. row 2, column 27) to cell name (like AA2) -->
+ <xsl:template name="CellName">
+ <xsl:param name="rowNum"/>
+ <xsl:param name="colNum"/>
+ <xsl:call-template name="ColNum2Name">
+ <xsl:with-param name="num" select="$colNum"/>
+ </xsl:call-template>
+ <xsl:value-of select="$rowNum"/>
+ </xsl:template>
+ <!-- A utility to convert a range given in terms of numbers (e.g. row 1, column 1 to row 2, column 27) to range name (like A1:AA2) -->
+ <xsl:template name="RangeName">
+ <xsl:param name="rowStartNum"/>
+ <xsl:param name="colStartNum"/>
+ <xsl:param name="rowEndNum"/>
+ <xsl:param name="colEndNum"/>
+ <xsl:call-template name="CellName">
+ <xsl:with-param name="rowNum" select="$rowStartNum"/>
+ <xsl:with-param name="colNum" select="$colStartNum"/>
+ </xsl:call-template>
+ <xsl:text>:</xsl:text>
+ <xsl:call-template name="CellName">
+ <xsl:with-param name="rowNum" select="$rowEndNum"/>
+ <xsl:with-param name="colNum" select="$colEndNum"/>
+ </xsl:call-template>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/spreadsheetml/spreadsheetml2ooo.xsl b/filter/source/xslt/import/spreadsheetml/spreadsheetml2ooo.xsl
new file mode 100644
index 000000000..09b01a360
--- /dev/null
+++ b/filter/source/xslt/import/spreadsheetml/spreadsheetml2ooo.xsl
@@ -0,0 +1,9152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:SL="http://schemas.microsoft.com/schemaLibrary/2003/core" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:exsl="http://exslt.org/common" xmlns:set="http://exslt.org/sets" extension-element-prefixes="set exsl" exclude-result-prefixes="aml dt html o ss SL v w10 w wx x set exsl">
+ <!--+++++ INCLUDED XSL MODULES +++++-->
+ <!-- helper collection, to convert measures (e.g. inch to pixel using DPI (dots per inch) parameter)-->
+ <xsl:import href="../../common/measure_conversion.xsl"/>
+ <xsl:output indent="no" version="1.0" encoding="UTF-8" method="xml"/>
+ <xsl:template match="/">
+ <office:document office:mimetype="application/vnd.oasis.opendocument.spreadsheet" office:version="1.0">
+ <xsl:apply-templates select="ss:Workbook/o:DocumentProperties"/>
+ <xsl:apply-templates select="ss:Workbook/x:ExcelWorkbook"/>
+ <xsl:call-template name="font-declaration"/>
+ <xsl:apply-templates select="ss:Workbook/ss:Worksheet[1]" mode="styles"/>
+ <xsl:element name="office:body">
+ <xsl:element name="office:spreadsheet">
+ <xsl:call-template name="set-calculation"/>
+ <!-- for DataValidation -->
+ <xsl:if test="ss:Workbook/ss:Worksheet/x:DataValidation">
+ <xsl:element name="table:content-validations">
+ <xsl:apply-templates select="ss:Workbook/ss:Worksheet/x:DataValidation"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:apply-templates select="ss:Workbook/ss:Worksheet"/>
+ <xsl:call-template name="Names"/>
+ <xsl:element name="table:database-ranges">
+ <!-- these descriptions located in every Worksheet in Excel, but at the same path in Calc -->
+ <xsl:for-each select="ss:Workbook/ss:Worksheet">
+ <xsl:apply-templates select="./x:Sorting"/>
+ <xsl:apply-templates select="./x:AutoFilter"/>
+ <!-- for Advanced Filter.the position is same as AutoFilter -->
+ <xsl:if test="./ss:Names/ss:NamedRange and ./ss:Names/ss:NamedRange/@ss:Name='_FilterDatabase'">
+ <xsl:call-template name="transform-advanced-filter">
+ <xsl:with-param name="target-value" select="substring-after(./ss:Names/ss:NamedRange[@ss:Name='_FilterDatabase']/@ss:RefersTo, '=')"/>
+ <xsl:with-param name="condition-pos" select="substring-after(./ss:Names/ss:NamedRange[@ss:Name='Criteria']/@ss:RefersTo, '=')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </office:document>
+ </xsl:template>
+ <xsl:template match="o:DocumentProperties">
+ <office:meta>
+ <meta:generator>Microsoft Excel 2003</meta:generator>
+ <xsl:if test="o:Title">
+ <dc:title>
+ <xsl:value-of select="o:Title"/>
+ </dc:title>
+ </xsl:if>
+ <xsl:if test="o:Description">
+ <dc:description>
+ <xsl:value-of select="o:Description"/>
+ </dc:description>
+ </xsl:if>
+ <xsl:if test="o:Subject">
+ <dc:subject>
+ <xsl:value-of select="o:Subject"/>
+ </dc:subject>
+ </xsl:if>
+ <xsl:if test="o:Author">
+ <meta:initial-creator>
+ <xsl:value-of select="o:Author"/>
+ </meta:initial-creator>
+ </xsl:if>
+ <xsl:if test="o:Created">
+ <meta:creation-date>
+ <xsl:value-of select="substring-before( o:Created, 'Z')"/>
+ </meta:creation-date>
+ </xsl:if>
+ <xsl:if test="o:LastAuthor">
+ <dc:creator>
+ <xsl:value-of select="o:LastAuthor"/>
+ </dc:creator>
+ </xsl:if>
+ <xsl:if test="o:LastSaved">
+ <dc:date>
+ <xsl:value-of select="substring-before( o:LastSaved, 'Z')"/>
+ </dc:date>
+ </xsl:if>
+ <!--
+ <meta:printed-by/>
+ <meta:print-date/>
+ <!~~ removed in OASIS Open Office XML
+ <meta:keywords>
+ <meta:keyword>
+ <xsl:value-of select="o:Keywords" />
+ </meta:keyword>
+ </meta:keywords>
+ ~~>
+ <dc:language/>
+ -->
+ <xsl:if test="o:Revision">
+ <meta:editing-cycles>
+ <xsl:value-of select="o:Revision"/>
+ </meta:editing-cycles>
+ </xsl:if>
+ <xsl:if test="o:TotalTime">
+ <meta:editing-duration>
+ <xsl:value-of select="concat('PT', floor(o:TotalTime div 60), 'H', o:TotalTime mod 60, 'M0S')"/>
+ </meta:editing-duration>
+ </xsl:if>
+ <xsl:if test="o:Category">
+ <meta:user-defined meta:name="Category">
+ <xsl:value-of select="o:Category"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="o:Manager">
+ <meta:user-defined meta:name="Manager">
+ <xsl:value-of select="o:Manager"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="o:Company">
+ <meta:user-defined meta:name="Company">
+ <xsl:value-of select="o:Company"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="o:Version">
+ <meta:user-defined meta:name="Version">
+ <xsl:value-of select="o:Version"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="o:HyperlinkBase">
+ <meta:user-defined meta:name="HyperlinkBase">
+ <xsl:value-of select="o:HyperlinkBase"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:apply-templates select="../o:CustomDocumentProperties"/>
+ <!--Note: <meta:document-statistic/>-->
+ </office:meta>
+ </xsl:template>
+ <xsl:template match="o:CustomDocumentProperties">
+ <xsl:for-each select="node()[@dt:dt]">
+ <meta:user-defined meta:name="{name()}">
+ <xsl:value-of select="."/>
+ </meta:user-defined>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="x:ExcelWorkbook">
+ <!-- Configuration in 'ooo:view-settings' and 'ooo:configuration-settings'
+ "GridColor"
+ "HasColumnRowHeaders"
+ "HasSheetTabs"
+ "IsOutlineSymbolsSet"
+ "IsRasterAxisSynchronized"
+ "IsSnapToRaster"
+ "RasterIsVisible"
+ "RasterResolutionX"
+ "RasterResolutionY"
+ "RasterSubdivisionX"
+ "RasterSubdivisionY"
+ "ShowGrid"
+ "ShowNotes"
+ "ShowPageBreaks"
+ "ShowZeroValues"
+ -->
+ <xsl:variable name="sharedConfiguration">
+ <xsl:if test="../ss:Worksheet/x:WorksheetOptions/x:GridlineColor">
+ <config:config-item config:name="GridColor" config:type="long">
+ <xsl:variable name="temp-code" select="substring-after(normalize-space(../ss:Worksheet/x:WorksheetOptions/x:GridlineColor), '#')"/>
+ <xsl:variable name="temp-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="$temp-code"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="string-length($temp-code)"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$temp-value"/>
+ </config:config-item>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="../ss:Worksheet/x:WorksheetOptions/x:DoNotDisplayHeadings">
+ <config:config-item config:name="HasColumnRowHeaders" config:type="boolean">false</config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="HasColumnRowHeaders" config:type="boolean">true</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="x:HideWorkbookTabs">
+ <config:config-item config:name="HasSheetTabs" config:type="boolean">false</config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="HasSheetTabs" config:type="boolean">true</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="../ss:Worksheet/x:WorksheetOptions/x:DoNotDisplayOutline">
+ <config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">false</config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="IsOutlineSymbolsSet" config:type="boolean">true</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="../ss:Worksheet/x:WorksheetOptions/x:DoNotDisplayGridlines">
+ <config:config-item config:name="ShowGrid" config:type="boolean">false</config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="ShowGrid" config:type="boolean">true</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="../ss:Worksheet/x:WorksheetOptions/x:DoNotDisplayZeros">
+ <config:config-item config:name="ShowZeroValues" config:type="boolean">false</config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="ShowZeroValues" config:type="boolean">true</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <office:settings>
+ <config:config-item-set config:name="ooo:view-settings">
+ <config:config-item config:type="int" config:name="VisibleAreaTop">
+ <xsl:value-of select="x:WindowTopY"/>
+ </config:config-item>
+ <config:config-item config:name="VisibleAreaLeft" config:type="int">
+ <xsl:value-of select="x:WindowTopX"/>
+ </config:config-item>
+ <config:config-item config:name="VisibleAreaWidth" config:type="int">
+ <xsl:value-of select="x:WindowWidth"/>
+ </config:config-item>
+ <config:config-item config:name="VisibleAreaHeight" config:type="int">
+ <xsl:value-of select="x:WindowHeight"/>
+ </config:config-item>
+ <xsl:variable name="ratio" select="15"/>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <config:config-item config:name="ViewId" config:type="string">View1</config:config-item>
+ <config:config-item-map-named config:name="Tables">
+ <!-- The panes of a table is like 3 | 1 or 3 | 1, or 3 , while 3 is the default one. glu
+ - - - - - - -
+ 2 | 0 2 -->
+ <xsl:for-each select="../ss:Worksheet">
+ <config:config-item-map-entry config:name="{@ss:Name}">
+ <xsl:variable name="active-pane">
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:ActivePane">
+ <xsl:value-of select="x:WorksheetOptions/x:ActivePane"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="not( $active-pane = '' ) and ( x:WorksheetOptions/x:SplitVertical or x:WorksheetOptions/x:SplitHorizontal )">
+ <config:config-item config:name="ActiveSplitRange" config:type="short">
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:SplitVertical and not(x:WorksheetOptions/x:SplitHorizontal)">
+ <xsl:value-of select="'3'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$active-pane"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="not( $active-pane = '')">
+ <config:config-item config:name="CursorPositionX" config:type="int">
+ <xsl:value-of select="x:WorksheetOptions/x:Panes/x:Pane[x:Number = $active-pane ]/x:ActiveCol"/>
+ </config:config-item>
+ <config:config-item config:name="CursorPositionY" config:type="int">
+ <xsl:value-of select="x:WorksheetOptions/x:Panes/x:Pane[x:Number = $active-pane ]/x:ActiveRow"/>
+ </config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="CursorPositionX" config:type="int">
+ <xsl:value-of select="x:WorksheetOptions/x:Panes/x:Pane/x:ActiveCol"/>
+ </config:config-item>
+ <config:config-item config:name="CursorPositionY" config:type="int">
+ <xsl:value-of select="x:WorksheetOptions/x:Panes/x:Pane/x:ActiveRow"/>
+ </config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:variable name="position-left">
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:LeftColumnVisible">
+ <xsl:value-of select="x:WorksheetOptions/x:LeftColumnVisible"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <config:config-item config:name="PositionLeft" config:type="int">
+ <xsl:value-of select="$position-left"/>
+ </config:config-item>
+ <xsl:variable name="position-top">
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:TopRowVisible">
+ <xsl:value-of select="x:WorksheetOptions/x:TopRowVisible"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:SplitVertical and not(x:WorksheetOptions/x:SplitHorizontal)">
+ <config:config-item config:name="PositionBottom" config:type="int">
+ <xsl:value-of select="$position-top"/>
+ </config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="PositionTop" config:type="int">
+ <xsl:value-of select="$position-top"/>
+ </config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:SplitVertical">
+ <config:config-item config:name="HorizontalSplitMode" config:type="short">
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:FreezePanes">2</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ <config:config-item config:name="HorizontalSplitPosition" config:type="int">
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:FreezePanes">
+ <xsl:value-of select="x:WorksheetOptions/x:SplitVertical + $position-left"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="floor( x:WorksheetOptions/x:SplitVertical div $ratio )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ <config:config-item config:name="PositionRight" config:type="int">
+ <xsl:value-of select="x:WorksheetOptions/x:LeftColumnRightPane"/>
+ </config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="HorizontalSplitMode" config:type="short">0</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:SplitHorizontal">
+ <config:config-item config:name="VerticalSplitMode" config:type="short">
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:FreezePanes">2</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ <config:config-item config:name="VerticalSplitPosition" config:type="int">
+ <xsl:choose>
+ <xsl:when test="x:WorksheetOptions/x:FreezePanes">
+ <xsl:value-of select="x:WorksheetOptions/x:SplitHorizontal + $position-top"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="floor( x:WorksheetOptions/x:SplitHorizontal div $ratio )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ <config:config-item config:name="PositionBottom" config:type="int">
+ <xsl:value-of select="x:WorksheetOptions/x:TopRowBottomPane"/>
+ </config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="VerticalSplitMode" config:type="short">0</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:copy-of select="$sharedConfiguration"/>
+ <xsl:if test="x:WorksheetOptions/x:TabColorIndex">
+ <config:config-item config:name="TabColor" config:type="int">
+ <xsl:variable name="temp-value">
+ <xsl:call-template name="colorindex2decimal">
+ <xsl:with-param name="colorindex" select="x:WorksheetOptions/x:TabColorIndex"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$temp-value"/>
+ </config:config-item>
+ </xsl:if>
+ </config:config-item-map-entry>
+ </xsl:for-each>
+ </config:config-item-map-named>
+ <xsl:if test="x:ActiveSheet">
+ <config:config-item config:name="ActiveTable" config:type="string">
+ <xsl:value-of select="../ss:Worksheet[/ss:Workbook/x:ExcelWorkbook/x:ActiveSheet+1]/@ss:Name"/>
+ </config:config-item>
+ </xsl:if>
+ <config:config-item config:name="HorizontalScrollbarWidth" config:type="int">555</config:config-item>
+ <!-- following are some table setting from Excel, but transformed to global setting, due to limit of Calc -->
+ <xsl:if test="../ss:Worksheet/x:WorksheetOptions/x:ShowPageBreakZoom">
+ <config:config-item config:name="ShowPageBreakPreview" config:type="boolean">true</config:config-item>
+ </xsl:if>
+ <xsl:if test="../ss:Worksheet/x:WorksheetOptions/x:PageBreakZoom">
+ <config:config-item config:name="PageViewZoomValue" config:type="int">
+ <xsl:value-of select="../ss:Worksheet/x:WorksheetOptions/x:PageBreakZoom"/>
+ </config:config-item>
+ </xsl:if>
+ <xsl:if test="../ss:Worksheet/x:WorksheetOptions/x:Zoom">
+ <config:config-item config:name="ZoomValue" config:type="int">
+ <xsl:value-of select="../ss:Worksheet/x:WorksheetOptions/x:Zoom"/>
+ </config:config-item>
+ </xsl:if>
+ <!-- several properties are not saved in Calc XML but setting, whereas vice versa. :( So just to be expanded, glu -->
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ <config:config-item-set config:name="ooo:configuration-settings">
+ <xsl:copy-of select="$sharedConfiguration"/>
+ </config:config-item-set>
+ <!-- printer setting, not finished yet. glu
+ <config:config-item-set config:name="configuration-settings" />
+ -->
+ </office:settings>
+ </xsl:template>
+
+ <xsl:variable name="allFontDefs"><xsl:for-each select="/ss:Workbook/ss:Styles/ss:Style/ss:Font[@ss:FontName or @x:Family]|/ss:Workbook/ss:Worksheet/ss:Table/ss:Row/ss:Cell/descendant::html:Font[@html:Face or @x:Family]"><f><xsl:copy-of select="@ss:FontName |@html:Face | @x:Family"/><xsl:value-of select="concat(@ss:FontName, @html:Face, '&#9;', @x:Family)"/></f></xsl:for-each></xsl:variable>
+
+ <xsl:template name="font-declaration">
+ <xsl:variable name="distinctFontDefs">
+ <xsl:choose>
+ <!-- saxon dropped support for exslt:sets#distinct() in version 8.2, but is capable of executing XPath 2.0 functions -->
+ <xsl:when test="function-available('set:distinct')"><xsl:copy-of select="set:distinct(exsl:node-set($allFontDefs)/*)"/></xsl:when>
+ <xsl:otherwise><xsl:call-template name="set:distinct"><xsl:with-param name="nodes" select="$allFontDefs"></xsl:with-param></xsl:call-template></xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <office:font-face-decls>
+ <xsl:if test="count(exsl:node-set($distinctFontDefs))">
+ <xsl:for-each select="exsl:node-set($distinctFontDefs)/*">
+ <style:font-face>
+ <xsl:if test="@ss:FontName or @html:Face">
+ <xsl:attribute name="style:name">
+ <xsl:value-of select="@ss:FontName | @html:Face"/>
+ </xsl:attribute>
+ <xsl:attribute name="svg:font-family">
+ <xsl:value-of select="@ss:FontName | @html:Face "/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@x:Family">
+ <xsl:attribute name="style:font-family-generic">
+ <xsl:call-template name="translate-font-family-generic">
+ <xsl:with-param name="family" select="@x:Family"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ </style:font-face>
+ </xsl:for-each>
+ </xsl:if>
+ </office:font-face-decls>
+ </xsl:template>
+ <xsl:template name="translate-font-family-generic">
+ <xsl:param name="family"/>
+ <xsl:choose>
+ <xsl:when test="$family='Swiss'">swiss</xsl:when>
+ <xsl:when test="$family='Modern'">modern</xsl:when>
+ <xsl:when test="$family='Roman'">roman</xsl:when>
+ <xsl:when test="$family='Script'">script</xsl:when>
+ <xsl:when test="$family='Decorative'">decorative</xsl:when>
+ <!-- change 'System' to 'Automatic' for Excel -->
+ <xsl:when test="$family='Automatic'">system</xsl:when>
+ <xsl:otherwise>system</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="ss:Workbook/ss:Worksheet" mode="styles">
+ <office:styles>
+ <xsl:apply-templates select="/ss:Workbook/ss:Styles/ss:Style[@ss:Name]"/>
+ <xsl:apply-templates select="/ss:Workbook/ss:Styles/ss:Style/ss:NumberFormat[@ss:Format]"/>
+ <!-- if ConditionalFormatting exists,it should generate some styles for style:style -->
+ <xsl:if test="/ss:Workbook/ss:Worksheet/x:ConditionalFormatting">
+ <xsl:call-template name="CondFormat_office_style"/>
+ </xsl:if>
+ </office:styles>
+ <office:automatic-styles>
+ <xsl:apply-templates select="/ss:Workbook/ss:Worksheet/ss:Table"/>
+ <xsl:apply-templates select="/ss:Workbook/ss:Styles/ss:Style[not(@ss:Name)]"/>
+ <xsl:apply-templates select="/ss:Workbook/ss:Styles/ss:Style/ss:Font[@ss:VerticalAlign]"/>
+ <!-- applying to ss:Data (but *, as also ss:Data nested in ss:Comments -->
+ <xsl:apply-templates select="/ss:Workbook/ss:Worksheet/ss:Table/ss:Row/ss:Cell/*[descendant-or-self::*]"/>
+ <xsl:apply-templates select="/ss:Workbook/ss:Worksheet/x:WorksheetOptions/x:PageSetup//@x:Data"/>
+ <!-- if ConditionalFormatting exists,transforing the styles -->
+ <xsl:if test="/ss:Workbook/ss:Worksheet/x:ConditionalFormatting">
+ <xsl:call-template name="CondFormat_automatic_style"/>
+ </xsl:if>
+ <xsl:call-template name="create-page-master">
+ <xsl:with-param name="worksheetoptions" select="/ss:Workbook/ss:Worksheet/x:WorksheetOptions"/>
+ </xsl:call-template>
+ </office:automatic-styles>
+ <office:master-styles>
+ <xsl:call-template name="create-master-styles">
+ <xsl:with-param name="worksheetoptions" select="/ss:Workbook/ss:Worksheet/x:WorksheetOptions"/>
+ </xsl:call-template>
+ </office:master-styles>
+ </xsl:template>
+ <xsl:template name="CondFormat_office_style">
+ <!-- translate the ConditionalFormatting style,including font,size,color,etc -->
+ <xsl:for-each select="/ss:Workbook/ss:Worksheet/x:ConditionalFormatting">
+ <xsl:variable name="table-pos" select="count(../preceding-sibling::ss:Worksheet)+1"/>
+ <xsl:variable name="conditions" select="count(preceding-sibling::x:ConditionalFormatting)+1"/>
+ <!-- Matching multiple styles, but automatic styles are not allowed to inherit from another automatic style
+ <xsl:for-each select="key('tableStyleIDs', key('tableWithConditional', .))
+ [generate-id(.) =
+ generate-id(key('styleId', .)[1])] ">
+ <xsl:sort select="." />
+
+ <xsl:apply-templates select="/ss:Workbook/ss:Styles/ss:Style[@ss:ID = current()/.]"/>
+ </xsl:for-each>
+ -->
+ <xsl:for-each select="x:Condition">
+ <xsl:variable name="condition-number" select="count(preceding-sibling::x:Condition)+1"/>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string" select="concat('Excel_CondFormat_',$table-pos,'_',$conditions,'_',$condition-number)"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">table-cell</xsl:attribute>
+ <xsl:apply-templates select="@ss:Name" />
+ <xsl:element name="style:table-cell-properties">
+ <xsl:choose>
+ <xsl:when test="x:Format/@Style">
+ <xsl:variable name="stylevalue" select="./x:Format/@Style"/>
+ <xsl:call-template name="recursion-condformat-style-table-cell">
+ <xsl:with-param name="style-value-t">
+ <xsl:choose>
+ <xsl:when test="substring($stylevalue,string-length($stylevalue),1) != ';'">
+ <xsl:value-of select="concat($stylevalue,';')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$stylevalue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:choose>
+ <xsl:when test="x:Format/@Style">
+ <xsl:variable name="stylevalue" select="./x:Format/@Style"/>
+ <xsl:call-template name="recursion-condformat-style-text">
+ <xsl:with-param name="style-value-t">
+ <xsl:choose>
+ <xsl:when test="substring($stylevalue,string-length($stylevalue),1) != ';'">
+ <xsl:value-of select="concat($stylevalue,';')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$stylevalue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:font-style">
+ <xsl:value-of select="'italic'"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:text-underline-type">
+ <xsl:value-of select="'single'"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:text-underline-color">
+ <xsl:value-of select="'font-color'"/>
+ </xsl:attribute>
+ <xsl:attribute name="fo:font-weight">
+ <xsl:value-of select="'bold'"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="@ss:Name">
+ <xsl:attribute name="style:display-name">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:template>
+ <xsl:template name="recursion-condformat-style-table-cell">
+ <!-- generates style:style for ConditionalFormatting -->
+ <xsl:param name="style-value-t"/>
+ <xsl:variable name="style-value" select="normalize-space($style-value-t)"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($style-value,'background')">
+ <xsl:choose>
+ <xsl:when test="contains($style-value,'mso-pattern')">
+ <xsl:variable name="color-value">
+ <xsl:call-template name="translate-color-style">
+ <xsl:with-param name="source-str" select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="mso-value">
+ <xsl:call-template name="translate-color-style">
+ <xsl:with-param name="source-str" select="normalize-space(substring-after($style-value,'mso-pattern'))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="mso-color" select="substring-after($mso-value,'#')"/>
+ <xsl:variable name="pattern-color-value" select="substring($mso-color,1,6)"/>
+ <xsl:variable name="pattern" select="concat('0.',normalize-space(substring-before(substring-after($mso-color,'gray-'),';')))"/>
+ <xsl:variable name="pattern-color">
+ <xsl:call-template name="cell-pattern-color">
+ <xsl:with-param name="pattern" select="$pattern"/>
+ <xsl:with-param name="color-value" select="$color-value"/>
+ <xsl:with-param name="pattern-color-value" select="concat('#',$pattern-color-value)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:background-color">
+ <xsl:value-of select="normalize-space($pattern-color)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:background-color">
+ <xsl:call-template name="translate-color-style">
+ <xsl:with-param name="source-str" select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with($style-value,'border')">
+ <xsl:attribute name="fo:border">
+ <xsl:value-of select="'0.002cm solid #000000'"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="contains($style-value,':')">
+ <xsl:call-template name="recursion-condformat-style-table-cell">
+ <xsl:with-param name="style-value-t" select="substring-after($style-value,';')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="recursion-condformat-style-text">
+ <!-- generates style:style for ConditionalFormatting -->
+ <xsl:param name="style-value-t"/>
+ <xsl:variable name="style-value" select="normalize-space($style-value-t)"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($style-value,'color')">
+ <xsl:attribute name="fo:color">
+ <xsl:call-template name="translate-color-style">
+ <xsl:with-param name="source-str" select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="starts-with($style-value,'font-style')">
+ <xsl:attribute name="fo:font-style">
+ <xsl:value-of select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="starts-with($style-value,'font-weight')">
+ <xsl:variable name="font-weight" select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/>
+ <xsl:attribute name="fo:font-weight">
+ <xsl:choose>
+ <xsl:when test="($font-weight &gt; 300) and ($font-weight &lt; 500)">
+ <xsl:value-of select="'normal'"/>
+ </xsl:when>
+ <xsl:when test="($font-weight &gt; 500) or ($font-weight = 500)">
+ <xsl:value-of select="'bold'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'0'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="starts-with($style-value,'text-underline-style')">
+ <xsl:attribute name="style:text-underline-type">
+ <xsl:value-of select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:text-underline-color">
+ <xsl:value-of select="'#000000'"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="contains($style-value,':')">
+ <xsl:call-template name="recursion-condformat-style-text">
+ <xsl:with-param name="style-value-t" select="substring-after($style-value,';')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="translate-color-style">
+ <!-- translate the word of color to hex code of color -->
+ <xsl:param name="source-str"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($source-str,'#')">
+ <xsl:value-of select="$source-str"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="starts-with($source-str,'black')">
+ <xsl:value-of select="'#000000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'maroon')">
+ <xsl:value-of select="'#800000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'red')">
+ <xsl:value-of select="'#FF0000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'fuchsia')">
+ <xsl:value-of select="'#FF00FF'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'olive')">
+ <xsl:value-of select="'#808000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'yellow')">
+ <xsl:value-of select="'#FFFF00'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'green')">
+ <xsl:value-of select="'#008000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'lime')">
+ <xsl:value-of select="'#00FF00'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'teal')">
+ <xsl:value-of select="'#008080'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'aqua')">
+ <xsl:value-of select="'#00FFFF'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'navy')">
+ <xsl:value-of select="'#000080'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'blue')">
+ <xsl:value-of select="'#0000FF'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'purple')">
+ <xsl:value-of select="'#800080'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'gray')">
+ <xsl:value-of select="'#808080'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'silver')">
+ <xsl:value-of select="'#C0C0C0'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'white')">
+ <xsl:value-of select="'#FFFFFF'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'#FFFFFF'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:key name="definedStyleIds" match="/ss:Workbook/ss:Styles/ss:Style/@ss:ID" use="string(.)"/>
+ <xsl:variable name="defaultStyle" select="/ss:Workbook/ss:Styles/ss:Style[@ss:ID='Default']/@ss:ID"></xsl:variable>
+ <xsl:key name="styleId" match="@ss:StyleID" use="."/>
+ <xsl:template name="CondFormat_automatic_style">
+ <!-- For each conditionalFormatting We inject a new style, which is a child of the current found style -->
+ <xsl:for-each select="/ss:Workbook/ss:Worksheet[x:ConditionalFormatting]">
+ <xsl:variable name="table-pos" select="count(preceding-sibling::ss:Worksheet)+1"/>
+ <xsl:variable name="styleIdsUsedByTable" select="$defaultStyle | key('definedStyleIds', ss:Table/ss:Row/ss:Cell/@ss:StyleID)"/>
+ <xsl:for-each select="x:ConditionalFormatting">
+ <xsl:variable name="conditions" select="position()"/>
+ <xsl:variable name="conditionalFormatting" select="."/>
+ <!-- we want to loop over the distinct styleId attribute values of all cells within the table related to the current conditional formatting. -->
+ <!-- We'd need to add the anonymous style id "Default" to the mix. -->
+ <!-- for all 'ssStyle/@ss:ID's, which are in tables connected within this conditional formatting -->
+ <!-- <xsl:for-each select="key('tableStyleIDs', generate-id(preceding-sibling::ss:Table)) [generate-id(.) = generate-id(key('styleId', .)[1])] "> -->
+ <xsl:for-each select="$styleIdsUsedByTable">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string" select="concat(.,'-ce',$table-pos,'-',$conditions)"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">table-cell</xsl:attribute>
+ <xsl:variable name="style" select="key('Style', .)" />
+ <xsl:choose>
+ <xsl:when test="$style/@ss:Name">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string" select="."/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:when>
+ <!-- as we create an automatic style, the parent is not allowed to be an automatic style as well
+ if the parent would be an automatic (unnamed) style, the style information have to be embedded to this style -->
+ <xsl:otherwise>
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string" select="$style/@ss:Parent"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="$style/ss:NumberFormat/@ss:Format">
+ <xsl:attribute name="style:data-style-name">
+ <xsl:value-of select="concat($style/@ss:ID, 'F')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="$style" mode="style-style-content"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:for-each select="$conditionalFormatting/x:Condition">
+ <xsl:variable name="condition-number" select="count(preceding-sibling::x:Condition)+1"/>
+ <xsl:variable name="base-address">
+ <xsl:choose>
+ <xsl:when test="contains(../x:Range,',')">
+ <xsl:choose>
+ <xsl:when test="contains(substring-before(../x:Range,','),':')">
+ <xsl:value-of select="substring-before(substring-after(../x:Range,':'),',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(../x:Range,',')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="../x:Range"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="columnNumber">
+ <xsl:choose>
+ <xsl:when test="contains($base-address, ':')">
+ <xsl:value-of select="substring-after(substring-after($base-address, ':'),'C')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($base-address,'C')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="rowNumber">
+ <xsl:choose>
+ <xsl:when test="contains($base-address, ':')">
+ <xsl:value-of select="substring-before(substring-after(substring-after($base-address, ':'),'R'),'C')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(substring-after($base-address,'R'),'C')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="base-cell-address">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="$columnNumber"/>
+ <xsl:with-param name="row-number" select="$rowNumber"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="condition-value">
+ <xsl:call-template name="translate-condition">
+ <xsl:with-param name="cell-column-pos" select="$columnNumber"/>
+ <xsl:with-param name="cell-row-pos" select="$rowNumber"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="style:map">
+ <xsl:attribute name="style:condition">
+ <xsl:value-of select="$condition-value"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:apply-style-name">
+ <xsl:value-of select="concat('Excel_CondFormat_',$table-pos,'_',$conditions,'_',$condition-number)"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:base-cell-address">
+ <xsl:value-of select="concat(../../@ss:Name,'.',$base-cell-address)"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="translate-condition">
+ <xsl:param name="cell-row-pos"/>
+ <xsl:param name="cell-column-pos"/>
+ <!-- translates the condition to generate formula -->
+ <xsl:variable name="address-value">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="x:Value1"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="x:Qualifier">
+ <xsl:variable name="qualifier" select="x:Qualifier"/>
+ <xsl:variable name="first-value" select="x:Value1"/>
+ <xsl:choose>
+ <xsl:when test="$qualifier = 'Between'">
+ <xsl:variable name="second-value">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="x:Value2"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('cell-content-is-between(',$address-value,',',$second-value,')')"/>
+ </xsl:when>
+ <xsl:when test="$qualifier = 'NotBetween'">
+ <xsl:variable name="second-value">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="x:Value2"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('cell-content-is-not-between(',$address-value,',',$second-value,')')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="translatedQualifier">
+ <xsl:choose>
+ <xsl:when test="$qualifier = 'Equal'">=</xsl:when>
+ <xsl:when test="$qualifier = 'Less'">&lt;</xsl:when>
+ <xsl:when test="$qualifier = 'Greater'">&gt;</xsl:when>
+ <xsl:when test="$qualifier = 'LessOrEqual'">&lt;=</xsl:when>
+ <xsl:when test="$qualifier = 'GreaterOrEqual'">&gt;=</xsl:when>
+ <xsl:when test="$qualifier = 'NotEqual'">!=</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat('cell-content()', $translatedQualifier, $address-value)"/>
+ </xsl:otherwise>
+
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('is-true-formula(',$address-value,')')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- Used in case of 'style:map', conditional formatting, where a style references to another -->
+ <xsl:key match="/ss:Workbook/ss:Worksheet/ss:Table/ss:Row/ss:Cell" name="cells" use="@ss:StyleID"/>
+ <xsl:template match="ss:NumberFormat">
+ <xsl:variable name="unit-count" select="string-length(@ss:Format) - string-length(translate(@ss:Format,';','')) + 1"/>
+ <xsl:variable name="proto-style-id" select="../@ss:ID"/>
+ <xsl:call-template name="process-number-format-unit">
+ <xsl:with-param name="number-format-unit" select="@ss:Format"/>
+ <xsl:with-param name="style-id" select="concat($proto-style-id,'F')"/>
+ <xsl:with-param name="format-type" select="key('cells', $proto-style-id)/ss:Data/@ss:Type"/>
+ <xsl:with-param name="total-unit" select="$unit-count"/>
+ <xsl:with-param name="current-unit" select="0"/>
+ </xsl:call-template>
+ </xsl:template>
+ <!-- Note: conditions appearing only once at the beginning are mixed with others -->
+ <xsl:template name="process-number-format-unit">
+ <xsl:param name="number-format-unit"/>
+ <xsl:param name="style-id"/>
+ <xsl:param name="format-type"/>
+ <xsl:param name="total-unit"/>
+ <xsl:param name="current-unit"/>
+ <xsl:choose>
+ <!-- if total-unit > 1 and the last unit is just @, delete it -->
+ <xsl:when test="$current-unit = 0 and $total-unit &gt; 1 and substring( $number-format-unit, string-length($number-format-unit) - 1) = ';@'">
+ <xsl:call-template name="process-number-format-unit">
+ <xsl:with-param name="number-format-unit" select="substring( $number-format-unit, 1, string-length($number-format-unit) - 2)"/>
+ <xsl:with-param name="style-id" select="$style-id"/>
+ <xsl:with-param name="format-type" select="$format-type"/>
+ <xsl:with-param name="total-unit" select="$total-unit - 1"/>
+ <xsl:with-param name="current-unit" select="0"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- $number-format-unit enum values: General, General Number, General Date, Long Date, Medium Date, Short Date, Long Time,
+ Medium Time, Short Time, Currency, Euro Currency, Fixed, Standard, Percent, Scientific, Yes/No, True/False, On/Off -->
+ <xsl:when test="$number-format-unit = 'Currency'">
+ <number:currency-style style:name="{concat( $style-id, 'P1')}" style:volatile="true">
+ <number:text>$</number:text>
+ <number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
+ </number:currency-style>
+ <number:currency-style style:name="{$style-id}">
+ <style:text-properties fo:color="#ff0000"/>
+ <number:text>$-</number:text>
+ <number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
+ <style:map style:condition="value()&gt;=0" style:apply-style-name="{concat( $style-id, 'P1')}"/>
+ </number:currency-style>
+ </xsl:when>
+ <xsl:when test="$number-format-unit = 'Euro Currency'">
+ <number:currency-style style:name="{concat( $style-id, 'P1')}" style:volatile="true">
+ <number:text>€ </number:text>
+ <number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
+ </number:currency-style>
+ <number:currency-style style:name="{$style-id}">
+ <style:text-properties fo:color="#ff0000"/>
+ <number:text>(€ </number:text>
+ <number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
+ <number:text>)</number:text>
+ <style:map style:condition="value()&gt;=0" style:apply-style-name="{concat( $style-id, 'P1')}"/>
+ </number:currency-style>
+ </xsl:when>
+ <xsl:when test="$number-format-unit = 'Yes/No' or $number-format-unit = 'True/False' or $number-format-unit = 'On/Off'">
+ <xsl:variable name="left-code" select="substring-before( $number-format-unit, '/')"/>
+ <xsl:variable name="right-code" select="substring-after( $number-format-unit, '/')"/>
+ <number:number-style style:name="{concat( $style-id, 'P1')}" style:volatile="true">
+ <number:text>
+ <xsl:value-of select="$left-code"/>
+ </number:text>
+ </number:number-style>
+ <number:number-style style:name="{concat( $style-id, 'P2')}" style:volatile="true">
+ <number:text>
+ <xsl:value-of select="$left-code"/>
+ </number:text>
+ </number:number-style>
+ <number:number-style style:name="{$style-id}">
+ <number:text>
+ <xsl:value-of select="$right-code"/>
+ </number:text>
+ <style:map style:condition="value()&gt;0" style:apply-style-name="{concat( $style-id, 'P1')}"/>
+ <style:map style:condition="value()&lt;0" style:apply-style-name="{concat( $style-id, 'P2')}"/>
+ </number:number-style>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$total-unit &gt; 1 and $current-unit = 0">
+ <!-- still complete number format string of multiple sub-formats, split them out -->
+ <xsl:call-template name="process-number-format-unit">
+ <xsl:with-param name="number-format-unit" select="substring-before($number-format-unit,';')"/>
+ <xsl:with-param name="style-id" select="concat($style-id,'P1')"/>
+ <xsl:with-param name="format-type" select="$format-type"/>
+ <xsl:with-param name="total-unit" select="$total-unit"/>
+ <xsl:with-param name="current-unit" select="1"/>
+ </xsl:call-template>
+ <xsl:if test="$total-unit &gt; 2">
+ <xsl:call-template name="process-number-format-unit">
+ <xsl:with-param name="number-format-unit" select="substring-before(substring-after($number-format-unit,';'),';')"/>
+ <xsl:with-param name="style-id" select="concat($style-id,'P2')"/>
+ <xsl:with-param name="format-type" select="$format-type"/>
+ <xsl:with-param name="total-unit" select="$total-unit"/>
+ <xsl:with-param name="current-unit" select="2"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$total-unit &gt; 3">
+ <!-- four sub number format -->
+ <xsl:call-template name="process-number-format-unit">
+ <xsl:with-param name="number-format-unit" select="substring-before(substring-after(substring-after($number-format-unit,';'),';'),';')"/>
+ <xsl:with-param name="style-id" select="concat($style-id,'P3')"/>
+ <xsl:with-param name="format-type" select="$format-type"/>
+ <xsl:with-param name="total-unit" select="$total-unit"/>
+ <xsl:with-param name="current-unit" select="3"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ <!-- symbol number format converted, below deal with ordinary number formatting -->
+ <xsl:variable name="current-number-format-unit">
+ <xsl:choose>
+ <xsl:when test="$total-unit = 1 and $current-unit = 0">
+ <xsl:value-of select="$number-format-unit"/>
+ </xsl:when>
+ <xsl:when test="$total-unit = 2 and $current-unit = 0">
+ <xsl:value-of select="substring-after($number-format-unit,';')"/>
+ </xsl:when>
+ <xsl:when test="$total-unit = 3 and $current-unit = 0">
+ <xsl:value-of select="substring-after(substring-after($number-format-unit,';'),';')"/>
+ </xsl:when>
+ <xsl:when test="$current-unit = 0">
+ <!-- the forth sub number format -->
+ <xsl:value-of select="substring-after(substring-after(substring-after($number-format-unit,';'),';'),';')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- not the default sub number format, glu -->
+ <xsl:value-of select="$number-format-unit"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="style-type-name">
+ <xsl:choose>
+ <xsl:when test="($format-type = 'Number' and contains($current-number-format-unit,'[$') and not(contains($current-number-format-unit,'[$-') ) ) or contains($current-number-format-unit,'Currency') ">number:currency-style</xsl:when>
+ <xsl:when test="($format-type = 'Number' and (contains($current-number-format-unit,'%') or contains($current-number-format-unit, 'Percent') ) ) or contains($current-number-format-unit,'Percent') ">number:percentage-style</xsl:when>
+ <xsl:when test="($format-type = 'DateTime' or $format-type = 'String') and (contains($current-number-format-unit,'y') or contains($current-number-format-unit,'g') or contains($current-number-format-unit,'d') or contains($current-number-format-unit, 'Date') )">number:date-style</xsl:when>
+ <xsl:when test="($format-type = 'DateTime' or $format-type = 'String') and ( contains($current-number-format-unit,'h') or contains($current-number-format-unit,'m') or contains($current-number-format-unit,'s') or contains($current-number-format-unit, 'Time') )">number:time-style</xsl:when>
+ <xsl:when test="contains($current-number-format-unit, 'Number') or contains($current-number-format-unit, 'General') or contains($current-number-format-unit, 'Fixed') or contains($current-number-format-unit, 'Standard') or contains($current-number-format-unit, 'Scientific') or ( contains($current-number-format-unit,'#') or contains($current-number-format-unit,'0') or contains($current-number-format-unit,'?') )">number:number-style</xsl:when>
+ <xsl:when test="$format-type = 'Boolean'">number:boolean-style</xsl:when>
+ <xsl:otherwise>number:text-style</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="{$style-type-name}">
+ <xsl:attribute name="style:name">
+ <xsl:value-of select="$style-id"/>
+ </xsl:attribute>
+ <xsl:apply-templates select="@ss:Name" />
+ <!-- removed in OASIS XML
+ <xsl:attribute name="style:family">data-style</xsl:attribute>-->
+ <xsl:if test="$current-unit &gt; 0">
+ <xsl:attribute name="style:volatile">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains ( $current-number-format-unit, '[h]') or contains ( $current-number-format-unit, '[m]') or contains ( $current-number-format-unit, '[s]')">
+ <xsl:attribute name="number:truncate-on-overflow">false</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains($current-number-format-unit,'[$') or contains($current-number-format-unit, '[DBNum')">
+ <xsl:call-template name="create-language-country-attribute">
+ <xsl:with-param name="attribute-code" select="substring-before(substring-after(substring-after($current-number-format-unit,'[$'),'-'),']')"/>
+ <xsl:with-param name="number-code-style" select="substring-before( substring-after($current-number-format-unit,'[DBNum'),']')"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="contains( $current-number-format-unit, '[')">
+ <xsl:element name="style:text-properties">
+ <xsl:choose>
+ <xsl:when test="contains( $current-number-format-unit, '[Red')">
+ <xsl:attribute name="fo:color">#ff0000</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $current-number-format-unit, '[Black')">
+ <xsl:attribute name="fo:color">#000000</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $current-number-format-unit, '[Blue')">
+ <xsl:attribute name="fo:color">#0000ff</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $current-number-format-unit, '[Cyan')">
+ <xsl:attribute name="fo:color">#00ffff</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $current-number-format-unit, '[Green')">
+ <xsl:attribute name="fo:color">#00ff00</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $current-number-format-unit, '[Magenta')">
+ <xsl:attribute name="fo:color">#ff00ff</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $current-number-format-unit, '[White')">
+ <xsl:attribute name="fo:color">#ffffff</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $current-number-format-unit, '[Yellow')">
+ <xsl:attribute name="fo:color">#ffff00</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <!-- the type of condition-pos:1,the former third part of General; 2, the last General. the methods handling different -->
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$current-number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="1"/>
+ <xsl:with-param name="condition-pos">
+ <xsl:choose>
+ <xsl:when test="$current-unit = 1 or $current-unit = 2 or $current-unit = 3">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:when test="$current-unit = 0 and not(contains($number-format-unit, ';'))">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ <!-- create style:map for other sub number formats -->
+ <xsl:if test="$current-unit = 0 and $total-unit &gt; 1">
+ <xsl:variable name="style-condition1">
+ <xsl:call-template name="get-number-format-condition">
+ <xsl:with-param name="number-format-unit" select="substring-before($number-format-unit,';')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($style-condition1) &gt; 0">
+ <style:map style:condition="{concat('value()',$style-condition1)}" style:apply-style-name="{concat($style-id,'P1')}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$total-unit = 2">
+ <style:map style:condition="value()&gt;=0" style:apply-style-name="{concat($style-id,'P1')}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <style:map style:condition="value()&gt;0" style:apply-style-name="{concat($style-id,'P1')}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$total-unit &gt; 2">
+ <xsl:variable name="style-condition2">
+ <xsl:call-template name="get-number-format-condition">
+ <xsl:with-param name="number-format-unit" select="substring-before(substring-after($number-format-unit,';'),';')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($style-condition2) &gt; 0">
+ <style:map style:condition="{concat('value()',$style-condition2)}" style:apply-style-name="{concat($style-id,'P2')}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <style:map style:condition="value()&lt;0" style:apply-style-name="{concat($style-id,'P2')}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$total-unit &gt; 3">
+ <!-- four sub number formats, glu -->
+ <xsl:variable name="style-condition3">
+ <xsl:call-template name="get-number-format-condition">
+ <xsl:with-param name="number-format-unit" select="substring-before(substring-after(substring-after($number-format-unit,';'),';'),';')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($style-condition3) &gt; 0">
+ <style:map style:condition="{concat('value()',$style-condition3)}" style:apply-style-name="{concat($style-id,'P3')}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <style:map style:condition="value()=0" style:apply-style-name="{concat($style-id,'P3')}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:if>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-language-country-attribute">
+ <xsl:param name="attribute-code"/>
+ <xsl:param name="number-code-style"/>
+ <!-- convert Microsoft List of Locale ID (LCID) to language and country codes according to ISO-639 and ISO-3166.
+ Reference:
+ http://www.loc.gov/standards/iso639-2/langcodes.html
+ http://etext.lib.virginia.edu/tei/iso639.html
+ http://nl.ijs.si/gnusl/cee/std/ISO_3166.html
+ http://xml.coverpages.org/ripe3166.txt
+ http://www.worldlanguage.com/
+ http://www.ethnologue.com/
+ glu -->
+ <!-- the variables of language-country-code and number-shape-code transformed to decimal format -->
+ <xsl:variable name="language-country-code">
+ <xsl:variable name="temp-code">
+ <xsl:choose>
+ <xsl:when test="string-length($attribute-code) &lt;= 4">
+ <xsl:value-of select="$attribute-code"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring($attribute-code,string-length($attribute-code) - 3)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="$temp-code"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="string-length($temp-code)"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="string-length($attribute-code) &gt; 4 or string-length($number-code-style) &gt; 0">
+ <xsl:variable name="number-shape-code">
+ <xsl:variable name="temp-code">
+ <xsl:choose>
+ <xsl:when test="string-length($attribute-code) &gt; 4">
+ <xsl:value-of select="substring($attribute-code, 1, string-length($attribute-code) - 6)"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="$temp-code"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="string-length($temp-code)"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="number:transliteration-style">long</xsl:attribute>
+ <xsl:choose>
+ <!-- Western, #01 -->
+ <xsl:when test="$number-shape-code = 1"/>
+ <!-- Arabic Indic, #02 -->
+ <xsl:when test="$number-shape-code = 2"/>
+ <!-- Extended Arabic Indic, #03 -->
+ <xsl:when test="$number-shape-code = 3"/>
+ <!-- Devanagari (Sanskrit - India), #04-->
+ <xsl:when test="$number-shape-code = 4">
+ <xsl:attribute name="number:transliteration-language">sa</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Bengali (India), #05 -->
+ <xsl:when test="$number-shape-code = 5">
+ <xsl:attribute name="number:transliteration-language">bn</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Gurmukhi (Punjabi - India), #06 -->
+ <xsl:when test="$number-shape-code = 6">
+ <xsl:attribute name="number:transliteration-language">pa</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Gujarati (India), #07 -->
+ <xsl:when test="$number-shape-code = 7">
+ <xsl:attribute name="number:transliteration-language">gu</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Odia (India), #08 -->
+ <xsl:when test="$number-shape-code = 8">
+ <xsl:attribute name="number:transliteration-language">or</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Tamil (India), #09 -->
+ <xsl:when test="$number-shape-code = 9">
+ <xsl:attribute name="number:transliteration-language">ta</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Telugu (India), #0a -->
+ <xsl:when test="$number-shape-code = 10">
+ <xsl:attribute name="number:transliteration-language">te</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Kannada (India), #0b -->
+ <xsl:when test="$number-shape-code = 11">
+ <xsl:attribute name="number:transliteration-language">kn</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Malayalam (India), #0c -->
+ <xsl:when test="$number-shape-code = 12">
+ <xsl:attribute name="number:transliteration-language">ml</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">IN</xsl:attribute>
+ </xsl:when>
+ <!-- Thai, #0d -->
+ <xsl:when test="$number-shape-code = 13">
+ <xsl:attribute name="number:transliteration-language">th</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">TH</xsl:attribute>
+ </xsl:when>
+ <!-- Lao, #0e -->
+ <xsl:when test="$number-shape-code = 14">
+ <xsl:attribute name="number:transliteration-language">lo</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">LA</xsl:attribute>
+ </xsl:when>
+ <!-- Tibetan (China), #0f -->
+ <xsl:when test="$number-shape-code = 15">
+ <xsl:attribute name="number:transliteration-language">bo</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">CN</xsl:attribute>
+ </xsl:when>
+ <!-- Myanmar (Burma), #10 -->
+ <xsl:when test="$number-shape-code = 16">
+ <xsl:attribute name="number:transliteration-language">my</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">MM</xsl:attribute>
+ </xsl:when>
+ <!-- Ethiopic (Geez), #11 -->
+ <xsl:when test="$number-shape-code = 17">
+ <xsl:attribute name="number:transliteration-language">gez</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">ET</xsl:attribute>
+ </xsl:when>
+ <!-- Khmer (Cambodian), #12-->
+ <xsl:when test="$number-shape-code = 18">
+ <xsl:attribute name="number:transliteration-language">km</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">KH</xsl:attribute>
+ </xsl:when>
+ <!-- Mongolian, #13 -->
+ <xsl:when test="$number-shape-code = 19">
+ <xsl:attribute name="number:transliteration-language">mn</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">CN</xsl:attribute>
+ </xsl:when>
+ <!-- Japanese 1 ([DBNum1]) , #1b, #0411 -->
+ <xsl:when test="$number-shape-code = 27 or ($number-code-style = '1' and $language-country-code = 1041)">
+ <xsl:attribute name="number:transliteration-format">一</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">ja</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">JP</xsl:attribute>
+ </xsl:when>
+ <!-- Japanese 2 ([DBNum2]) ,#1c, #0411 -->
+ <xsl:when test="$number-shape-code = 28 or ($number-code-style = '2' and $language-country-code = 1041 )">
+ <xsl:attribute name="number:transliteration-format">壹</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">ja</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">JP</xsl:attribute>
+ </xsl:when>
+ <!-- Japanese 3 ([DBNum3]), #1d, #0411 -->
+ <xsl:when test="$number-shape-code = 29 or ($number-code-style = '3' and $language-country-code = 1041 )">
+ <xsl:attribute name="number:transliteration-format">1</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">ja</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">JP</xsl:attribute>
+ </xsl:when>
+ <!-- Simplified Chinese 1 ([DBNum1]), #1e, #0804 -->
+ <xsl:when test="$number-shape-code = 30 or ($number-code-style = '1' and $language-country-code = 2052 )">
+ <xsl:attribute name="number:transliteration-format">一</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">zh</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">CN</xsl:attribute>
+ </xsl:when>
+ <!-- Simplified Chinese 2 ([DBNum2]),#1f,#0804 -->
+ <xsl:when test="$number-shape-code = 31 or ($number-code-style = '2' and $language-country-code = 2052 )">
+ <xsl:attribute name="number:transliteration-format">壹</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">zh</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">CN</xsl:attribute>
+ </xsl:when>
+ <!-- Simplified Chinese 3 ([DBNum3]), #20,#0804 -->
+ <xsl:when test="$number-shape-code = 32 or ($number-code-style = '3' and $language-country-code = 2052 )">
+ <xsl:attribute name="number:transliteration-format">1</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">zh</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">CN</xsl:attribute>
+ </xsl:when>
+ <!-- Traditional Chinese 1 ([DBNum1]), #21, #0404 -->
+ <xsl:when test="$number-shape-code = 33 or ($number-code-style = '1' and $language-country-code = 1028 )">
+ <xsl:attribute name="number:transliteration-format">一</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">zh</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">TW</xsl:attribute>
+ </xsl:when>
+ <!-- Traditional Chinese 2 ([DBNum2]), #22, #0404 -->
+ <xsl:when test="$number-shape-code = 34 or ($number-code-style = '2' and $language-country-code = 1028 )">
+ <xsl:attribute name="number:transliteration-format">壹</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">zh</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">TW</xsl:attribute>
+ </xsl:when>
+ <!-- Traditional Chinese 3 ([DBNum3]),#23, #0404 -->
+ <xsl:when test="$number-shape-code = 35 or ($number-code-style = '3' and $language-country-code = 1028 )">
+ <xsl:attribute name="number:transliteration-format">1</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">zh</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">TW</xsl:attribute>
+ </xsl:when>
+ <!-- Korean 1 ([DBNum1]), #24, #0412 -->
+ <xsl:when test="$number-shape-code = 36 or ($number-code-style = '1' and $language-country-code = 1042 )">
+ <xsl:attribute name="number:transliteration-format">一</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">ko</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">KR</xsl:attribute>
+ </xsl:when>
+ <!-- Korean 2 ([DBNum2]), #25, #0412 -->
+ <xsl:when test="$number-shape-code = 37 or ($number-code-style = '2' and $language-country-code = 1042 )">
+ <xsl:attribute name="number:transliteration-format">壹</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">ko</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">KR</xsl:attribute>
+ </xsl:when>
+ <!-- Korean 3 ([DBNum3]), #26, #0412 -->
+ <xsl:when test="$number-shape-code = 38 or ($number-code-style = '3' and $language-country-code = 1042 )">
+ <xsl:attribute name="number:transliteration-format">1</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">ko</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">KR</xsl:attribute>
+ </xsl:when>
+ <!-- Korean 4 ([DBNum4]), #27, #0412 -->
+ <xsl:when test="$number-shape-code = 39 or ($number-code-style = '4' and $language-country-code = 1042 )">
+ <xsl:attribute name="number:transliteration-format">1</xsl:attribute>
+ <xsl:attribute name="number:transliteration-language">ko</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">KR</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <!-- components of a format code: two digits for number shape codes, two for calendar types, four for LCID -->
+ <xsl:choose>
+ <!-- totally 223 language-country LCID codes, manually created, among which MS Office 2003 supports 134, OOo supports 91 -->
+ <xsl:when test="$language-country-code = 1078">
+ <!-- Afrikaans - South Africa, #0436 -->
+ <xsl:attribute name="number:language">af</xsl:attribute>
+ <xsl:attribute name="number:country">ZA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1052">
+ <!-- Albanian - Albania, #041c -->
+ <xsl:attribute name="number:language">sq</xsl:attribute>
+ <xsl:attribute name="number:country">AL</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1118">
+ <!-- Amharic - Ethiopia, #045e -->
+ <xsl:attribute name="number:language">am</xsl:attribute>
+ <xsl:attribute name="number:country">ET</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1025">
+ <!-- Arabic - Saudi Arabia, #0401 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">SA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 5121">
+ <!-- Arabic - Algeria, #1401 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">DZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 15361">
+ <!-- Arabic - Bahrain, #3c01 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">BH</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 3073">
+ <!-- Arabic - Egypt, #0c01 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">EG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2049">
+ <!-- Arabic - Iraq, #0801 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">IQ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 11265">
+ <!-- Arabic - Jordan, #2c01 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">JO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 13313">
+ <!-- Arabic - Kuwait, #3401 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">KW</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 12289">
+ <!-- Arabic - Lebanon, #3001 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">LB</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 4097">
+ <!-- Arabic - Libya, #1001 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">LY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 6145">
+ <!-- Arabic - Morocco, #1801 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">MA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 8193">
+ <!-- Arabic - Oman, #2001 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">OM</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 16385">
+ <!-- Arabic - Qatar, #4001 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">QA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 10241">
+ <!-- Arabic - Syria, #2801 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">SY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 7169">
+ <!-- Arabic - Tunisia, #1c01 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">TN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 14337">
+ <!-- Arabic - U.A.E., #3801 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">AE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 9217">
+ <!-- Arabic - Yemen, #2401 -->
+ <xsl:attribute name="number:language">ar</xsl:attribute>
+ <xsl:attribute name="number:country">YE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1067">
+ <!-- Armenian - Armenia, #042b -->
+ <xsl:attribute name="number:language">hy</xsl:attribute>
+ <xsl:attribute name="number:country">AM</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1101">
+ <!-- Assamese, #044d -->
+ <xsl:attribute name="number:language">as</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2092">
+ <!-- Azeri - Cyrillic, #082c -->
+ <xsl:attribute name="number:language">az</xsl:attribute>
+ <xsl:attribute name="number:country">AZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1068">
+ <!-- Azeri - Latin, #042c -->
+ <xsl:attribute name="number:language">az</xsl:attribute>
+ <xsl:attribute name="number:country">AZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1069">
+ <!-- Basque - France/Spain, #042d -->
+ <xsl:attribute name="number:language">eu</xsl:attribute>
+ <xsl:attribute name="number:country">ES</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1059">
+ <!-- Belarusian - Belarus, #0423 -->
+ <xsl:attribute name="number:language">be</xsl:attribute>
+ <xsl:attribute name="number:country">BY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1093">
+ <!-- Bengali (India), #0445 -->
+ <xsl:attribute name="number:language">bn</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2117">
+ <!-- Bengali (Bangladesh), #0845 -->
+ <xsl:attribute name="number:language">bn</xsl:attribute>
+ <xsl:attribute name="number:country">BD</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 5146">
+ <!-- Bosnian (Bosnia/Herzegovina), #141a -->
+ <xsl:attribute name="number:language">bs</xsl:attribute>
+ <xsl:attribute name="number:country">BA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1026">
+ <!-- Bulgarian, #0402 -->
+ <xsl:attribute name="number:language">bg</xsl:attribute>
+ <xsl:attribute name="number:country">BG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1109">
+ <!-- Burmese (Burma/Myanmar), #0455 -->
+ <xsl:attribute name="number:language">my</xsl:attribute>
+ <xsl:attribute name="number:country">MM</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1027">
+ <!-- Catalan - Spain, #0403 -->
+ <xsl:attribute name="number:language">ca</xsl:attribute>
+ <xsl:attribute name="number:country">ES</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1116">
+ <!-- Cherokee - United States, #045c -->
+ <xsl:attribute name="number:language">chr</xsl:attribute>
+ <xsl:attribute name="number:country">US</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2052">
+ <!-- Chinese - People's Republic of China, #0804 -->
+ <xsl:attribute name="number:language">zh</xsl:attribute>
+ <xsl:attribute name="number:country">CN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 4100">
+ <!-- Chinese - Singapore, #1004 -->
+ <xsl:attribute name="number:language">zh</xsl:attribute>
+ <xsl:attribute name="number:country">SG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1028">
+ <!-- Chinese - Taiwan, #0404 -->
+ <xsl:attribute name="number:language">zh</xsl:attribute>
+ <xsl:attribute name="number:country">TW</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 3076">
+ <!-- Chinese - Hong Kong SAR, #0c04 -->
+ <xsl:attribute name="number:language">zh</xsl:attribute>
+ <xsl:attribute name="number:country">HK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 5124">
+ <!-- Chinese - Macao SAR, #1404 -->
+ <xsl:attribute name="number:language">zh</xsl:attribute>
+ <xsl:attribute name="number:country">MO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1050">
+ <!-- Croatian (Croatia), #041a -->
+ <xsl:attribute name="number:language">hr</xsl:attribute>
+ <xsl:attribute name="number:country">HR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 4122">
+ <!-- Croatian (Bosnia/Herzegovina), #101a -->
+ <xsl:attribute name="number:language">hr</xsl:attribute>
+ <xsl:attribute name="number:country">BA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1029">
+ <!-- Czech, #0405 -->
+ <xsl:attribute name="number:language">cs</xsl:attribute>
+ <xsl:attribute name="number:country">CZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1030">
+ <!-- Danish, #0406 -->
+ <xsl:attribute name="number:language">da</xsl:attribute>
+ <xsl:attribute name="number:country">DK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1125">
+ <!-- Divehi, #0465 -->
+ <xsl:attribute name="number:language">dv</xsl:attribute>
+ <xsl:attribute name="number:country">MV</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1043">
+ <!-- Dutch - Netherlands, #0413 -->
+ <xsl:attribute name="number:language">nl</xsl:attribute>
+ <xsl:attribute name="number:country">NL</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2067">
+ <!-- Dutch - Belgium, #0813 -->
+ <xsl:attribute name="number:language">nl</xsl:attribute>
+ <xsl:attribute name="number:country">BE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1126">
+ <!-- Edo (Bini - Nigeria), #0466 -->
+ <xsl:attribute name="number:language">bin</xsl:attribute>
+ <xsl:attribute name="number:country">NG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1033">
+ <!-- English - United States, #0409 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">US</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2057">
+ <!-- English - United Kingdom, #0809 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">GB</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 3081">
+ <!-- English - Australia, #0c09 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">AU</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 10249">
+ <!-- English - Belize, #2809 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">BZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 4105">
+ <!-- English - Canada, #1009 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">CA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 9225">
+ <!-- English - Caribbean (Cuba), #2409 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">CU</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 15369">
+ <!-- English - Hong Kong SAR, #3c09 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">HK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 16393">
+ <!-- English - India, #4009 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 14345">
+ <!-- English - Indonesia, #3809 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">ID</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 6153">
+ <!-- English - Ireland, #1809 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">IE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 8201">
+ <!-- English - Jamaica, #2009 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">JM</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 17417">
+ <!-- English - Malaysia, #4409 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">MY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 5129">
+ <!-- English - New Zealand, #1409 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">NZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 13321">
+ <!-- English - Philippines, #3409 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">PH</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 18441">
+ <!-- English - Singapore, #4809 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">SG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 7177">
+ <!-- English - South Africa, #1c09 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">ZA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 11273">
+ <!-- English - Trinidad, #2c09 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">TT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 12297">
+ <!-- English - Zimbabwe, #3009 -->
+ <xsl:attribute name="number:language">en</xsl:attribute>
+ <xsl:attribute name="number:country">ZW</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1061">
+ <!-- Estonian (Estonia), #0425 -->
+ <xsl:attribute name="number:language">et</xsl:attribute>
+ <xsl:attribute name="number:country">EE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1080">
+ <!-- Faroese (Faroe Islands), #0438 -->
+ <xsl:attribute name="number:language">fo</xsl:attribute>
+ <xsl:attribute name="number:country">FO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1065">
+ <!-- Farsi (Persian/Iran), #0429 -->
+ <xsl:attribute name="number:language">fa</xsl:attribute>
+ <xsl:attribute name="number:country">IR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1124">
+ <!-- Filipino (Philippine), #0464 -->
+ <xsl:attribute name="number:language">phi</xsl:attribute>
+ <xsl:attribute name="number:country">PH</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1035">
+ <!-- Finnish, #040b -->
+ <xsl:attribute name="number:language">fi</xsl:attribute>
+ <xsl:attribute name="number:country">FI</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1036">
+ <!-- French - France, #040c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">FR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2060">
+ <!-- French - Belgium, #080c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">BE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 11276">
+ <!-- French - Cameroon, #2c0c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">CM</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 3084">
+ <!-- French - Canada, #0c0c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">CA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 9228">
+ <!-- French - Congo, #240c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">CG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 12300">
+ <!-- French - Cote d'Ivoire, #300c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">CI</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 15372">
+ <!-- French - Haiti, #3c0c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">HT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 5132">
+ <!-- French - Luxembourg, #140c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">LU</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 13324">
+ <!-- French - Mali, #340c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">ML</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 6156">
+ <!-- French - Monaco, #180c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">MC</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 14348">
+ <!-- French - Morocco, #380c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">MA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 58380">
+ <!-- French - North Africa (Algeria), #e40c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">DZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 8204">
+ <!-- French - Reunion, #200c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">RE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 10252">
+ <!-- French - Senegal, #280c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">SN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 4108">
+ <!-- French - Switzerland, #100c -->
+ <xsl:attribute name="number:language">fr</xsl:attribute>
+ <xsl:attribute name="number:country">CH</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1122">
+ <!-- Frisian - Netherlands, #0462 -->
+ <xsl:attribute name="number:language">fy</xsl:attribute>
+ <xsl:attribute name="number:country">NL</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1127">
+ <!-- Fulfude (Fulah) - Nigeria, #0467 -->
+ <xsl:attribute name="number:language">ff</xsl:attribute>
+ <xsl:attribute name="number:country">NG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1071">
+ <!-- FYRO Macedonian, #042f -->
+ <xsl:attribute name="number:language">mk</xsl:attribute>
+ <xsl:attribute name="number:country">MK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2108">
+ <!-- Gaelic (Ireland), #083c -->
+ <xsl:attribute name="number:language">gd</xsl:attribute>
+ <xsl:attribute name="number:country">IE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1084">
+ <!-- Gaelic (Scotland), #043c -->
+ <xsl:attribute name="number:language">gd</xsl:attribute>
+ <xsl:attribute name="number:country">GB</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1110">
+ <!-- Galician (Gallegan) - Spain, #0456 -->
+ <xsl:attribute name="number:language">gl</xsl:attribute>
+ <xsl:attribute name="number:country">ES</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1079">
+ <!-- Georgian - Georgia, #0437 -->
+ <xsl:attribute name="number:language">ka</xsl:attribute>
+ <xsl:attribute name="number:country">GE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1031">
+ <!-- German - Germany, #0407 -->
+ <xsl:attribute name="number:language">de</xsl:attribute>
+ <xsl:attribute name="number:country">DE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 3079">
+ <!-- German - Austria, #0c07 -->
+ <xsl:attribute name="number:language">de</xsl:attribute>
+ <xsl:attribute name="number:country">AT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 5127">
+ <!-- German - Liechtenstein, #1407 -->
+ <xsl:attribute name="number:language">de</xsl:attribute>
+ <xsl:attribute name="number:country">LI</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 4103">
+ <!-- German - Luxembourg, #1007 -->
+ <xsl:attribute name="number:language">de</xsl:attribute>
+ <xsl:attribute name="number:country">LU</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2055">
+ <!-- German - Switzerland, #0807 -->
+ <xsl:attribute name="number:language">de</xsl:attribute>
+ <xsl:attribute name="number:country">CH</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1032">
+ <!-- Greek, #0408 -->
+ <xsl:attribute name="number:language">el</xsl:attribute>
+ <xsl:attribute name="number:country">GR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1140">
+ <!-- Guarani - Paraguay, #0474 -->
+ <xsl:attribute name="number:language">gn</xsl:attribute>
+ <xsl:attribute name="number:country">PY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1095">
+ <!-- Gujarati - India, #0447 -->
+ <xsl:attribute name="number:language">gu</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1128">
+ <!-- Hausa - Nigeria, #0468 -->
+ <xsl:attribute name="number:language">ha</xsl:attribute>
+ <xsl:attribute name="number:country">NG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1141">
+ <!-- Hawaiian - US, #0475 -->
+ <xsl:attribute name="number:language">haw</xsl:attribute>
+ <xsl:attribute name="number:country">US</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1037">
+ <!-- Hebrew, #040d -->
+ <xsl:attribute name="number:language">he</xsl:attribute>
+ <xsl:attribute name="number:country">IL</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1081">
+ <!-- Hindi (India), #0439 -->
+ <xsl:attribute name="number:language">hi</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1038">
+ <!-- Hungarian - Hungary, #040e -->
+ <xsl:attribute name="number:language">hu</xsl:attribute>
+ <xsl:attribute name="number:country">HU</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1129">
+ <!-- Ibibio (Niger-Kordofanian) - Nigeria, #0469 -->
+ <xsl:attribute name="number:language">nic</xsl:attribute>
+ <xsl:attribute name="number:country">NG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1039">
+ <!-- Icelandic, #040f -->
+ <xsl:attribute name="number:language">is</xsl:attribute>
+ <xsl:attribute name="number:country">IS</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1136">
+ <!-- Igbo - Nigeria, #0470 -->
+ <xsl:attribute name="number:language">ig</xsl:attribute>
+ <xsl:attribute name="number:country">NG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1057">
+ <!-- Indonesian, #0421 -->
+ <xsl:attribute name="number:language">id</xsl:attribute>
+ <xsl:attribute name="number:country">ID</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1117">
+ <!-- Inuktitut - US, #045d -->
+ <xsl:attribute name="number:language">iu</xsl:attribute>
+ <xsl:attribute name="number:country">US</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1040">
+ <!-- Italian - Italy, #0410 -->
+ <xsl:attribute name="number:language">it</xsl:attribute>
+ <xsl:attribute name="number:country">IT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2064">
+ <!-- Italian - Switzerland, #0810 -->
+ <xsl:attribute name="number:language">it</xsl:attribute>
+ <xsl:attribute name="number:country">CH</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1041">
+ <!-- Japanese, #0411 -->
+ <xsl:attribute name="number:language">ja</xsl:attribute>
+ <xsl:attribute name="number:country">JP</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1099">
+ <!-- Kannada (India), #044b -->
+ <xsl:attribute name="number:language">kn</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1137">
+ <!-- Kanuri - Nigeria, #0471 -->
+ <xsl:attribute name="number:language">kr</xsl:attribute>
+ <xsl:attribute name="number:country">NG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2144">
+ <!-- Kashmiri (India), #0860 -->
+ <xsl:attribute name="number:language">ks</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1120">
+ <!-- Kashmiri (Arabic), #0460 -->
+ <xsl:attribute name="number:language">ks</xsl:attribute>
+ <xsl:attribute name="number:country">PK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1087">
+ <!-- Kazakh, #043f -->
+ <xsl:attribute name="number:language">kk</xsl:attribute>
+ <xsl:attribute name="number:country">KZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1107">
+ <!-- Khmer (Cambodian), #0453 -->
+ <xsl:attribute name="number:language">km</xsl:attribute>
+ <xsl:attribute name="number:country">KH</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1111">
+ <!-- Konkani (India), #0457 -->
+ <xsl:attribute name="number:language">kok</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1042">
+ <!-- Korean, #0412 -->
+ <xsl:attribute name="number:language">ko</xsl:attribute>
+ <xsl:attribute name="number:country">KR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1088">
+ <!-- Kyrgyz ( Kirgiz / Cyrillic), #0440 -->
+ <xsl:attribute name="number:language">ky</xsl:attribute>
+ <xsl:attribute name="number:country">KG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1108">
+ <!-- Lao, #0454 -->
+ <xsl:attribute name="number:language">lo</xsl:attribute>
+ <xsl:attribute name="number:country">LA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1142">
+ <!-- Latin, #0476 -->
+ <xsl:attribute name="number:language">la</xsl:attribute>
+ <xsl:attribute name="number:country">IT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1062">
+ <!-- Latvian, #0426 -->
+ <xsl:attribute name="number:language">lv</xsl:attribute>
+ <xsl:attribute name="number:country">LV</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1063">
+ <!-- Lithuanian, #0427 -->
+ <xsl:attribute name="number:language">lt</xsl:attribute>
+ <xsl:attribute name="number:country">LT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1086">
+ <!-- Malay - Malaysia, #043e -->
+ <xsl:attribute name="number:language">ms</xsl:attribute>
+ <xsl:attribute name="number:country">MY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2110">
+ <!-- Malay - Brunei Darussalam, #083e -->
+ <xsl:attribute name="number:language">ms</xsl:attribute>
+ <xsl:attribute name="number:country">BN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1071">
+ <!-- Macedonian (FYROM), #042f -->
+ <xsl:attribute name="number:language">mk</xsl:attribute>
+ <xsl:attribute name="number:country">MK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1100">
+ <!-- Malayalam (India), #044c -->
+ <xsl:attribute name="number:language">ml</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1082">
+ <!-- Maltese, #043a -->
+ <xsl:attribute name="number:language">mt</xsl:attribute>
+ <xsl:attribute name="number:country">MT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1112">
+ <!-- Manipuri (India), #0458 -->
+ <xsl:attribute name="number:language">mni</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1153">
+ <!-- Maori - New Zealand, #0481 -->
+ <xsl:attribute name="number:language">mi</xsl:attribute>
+ <xsl:attribute name="number:country">NZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1102">
+ <!-- Marathi (India), #044e -->
+ <xsl:attribute name="number:language">mr</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1104">
+ <!-- Mongolian (Cyrillic), #0450 -->
+ <xsl:attribute name="number:language">mn</xsl:attribute>
+ <xsl:attribute name="number:country">MN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2128">
+ <!-- Mongolian (Mongolian), #0850 -->
+ <xsl:attribute name="number:language">mn</xsl:attribute>
+ <xsl:attribute name="number:country">CN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1121">
+ <!-- Nepali, #0461 -->
+ <xsl:attribute name="number:language">ne</xsl:attribute>
+ <xsl:attribute name="number:country">NP</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2145">
+ <!-- Nepali (India), #0861 -->
+ <xsl:attribute name="number:language">ne</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1044">
+ <!-- Norwegian (Bokmal), #0414 -->
+ <xsl:attribute name="number:language">nb</xsl:attribute>
+ <xsl:attribute name="number:country">NO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2068">
+ <!-- Norwegian (Nynorsk), #0814 -->
+ <xsl:attribute name="number:language">nn</xsl:attribute>
+ <xsl:attribute name="number:country">NO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1096">
+ <!-- Odia (India), #0448 -->
+ <xsl:attribute name="number:language">or</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1138">
+ <!-- Oromo (Ethiopia), #0472 -->
+ <xsl:attribute name="number:language">om</xsl:attribute>
+ <xsl:attribute name="number:country">ET</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1145">
+ <!-- Papiamentu (Netherlands Antilles), #0479 -->
+ <xsl:attribute name="number:language">pap</xsl:attribute>
+ <xsl:attribute name="number:country">AN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1123">
+ <!-- Pashto (Afghanistan), #0463 -->
+ <xsl:attribute name="number:language">ps</xsl:attribute>
+ <xsl:attribute name="number:country">AF</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1045">
+ <!-- Polish, #0415 -->
+ <xsl:attribute name="number:language">pl</xsl:attribute>
+ <xsl:attribute name="number:country">PL</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1046">
+ <!-- Portuguese - Brazil, #0416 -->
+ <xsl:attribute name="number:language">pt</xsl:attribute>
+ <xsl:attribute name="number:country">BR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2070">
+ <!-- Portuguese - Portugal, #0816 -->
+ <xsl:attribute name="number:language">pt</xsl:attribute>
+ <xsl:attribute name="number:country">PT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1094">
+ <!-- Punjabi, #0446 -->
+ <xsl:attribute name="number:language">pa</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2118">
+ <!-- Punjabi (Pakistan), #0846 -->
+ <xsl:attribute name="number:language">pa</xsl:attribute>
+ <xsl:attribute name="number:country">PK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1131">
+ <!-- Quecha - Blivia, #046b -->
+ <xsl:attribute name="number:language">qu</xsl:attribute>
+ <xsl:attribute name="number:country">BO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2155">
+ <!-- Quecha - Ecuador, #086b -->
+ <xsl:attribute name="number:language">qu</xsl:attribute>
+ <xsl:attribute name="number:country">EC</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 3179">
+ <!-- Quecha - peru, #0c6b -->
+ <xsl:attribute name="number:language">qu</xsl:attribute>
+ <xsl:attribute name="number:country">PE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1047">
+ <!-- Rhaeto-Romanic (Italy), #0417 -->
+ <xsl:attribute name="number:language">rm</xsl:attribute>
+ <xsl:attribute name="number:country">IT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1048">
+ <!-- Romanian, #0418 -->
+ <xsl:attribute name="number:language">ro</xsl:attribute>
+ <xsl:attribute name="number:country">RO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2072">
+ <!-- Romanian - Moldova, #0818 -->
+ <xsl:attribute name="number:language">ro</xsl:attribute>
+ <xsl:attribute name="number:country">MD</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1049">
+ <!-- Russian, #0419 -->
+ <xsl:attribute name="number:language">ru</xsl:attribute>
+ <xsl:attribute name="number:country">RU</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2073">
+ <!-- Russian - Moldova, #0819 -->
+ <xsl:attribute name="number:language">ru</xsl:attribute>
+ <xsl:attribute name="number:country">MD</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1083">
+ <!-- Sami (Lappish), # (Northern Sami - Sweden), #043b -->
+ <xsl:attribute name="number:language">se</xsl:attribute>
+ <xsl:attribute name="number:country">SE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1103">
+ <!-- Sanskrit (India), #044f -->
+ <xsl:attribute name="number:language">sa</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1132">
+ <!-- Sepedi (Northern Sotho - South Africa), #046c -->
+ <xsl:attribute name="number:language">nso</xsl:attribute>
+ <xsl:attribute name="number:country">ZA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 3098">
+ <!-- Serbian (Cyrillic - Serbia Yugoslavia), #0c1a -->
+ <xsl:attribute name="number:language">sr</xsl:attribute>
+ <xsl:attribute name="number:country">YU</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2074">
+ <!-- Serbian (Latin - Croatia), #081a -->
+ <xsl:attribute name="number:language">sr</xsl:attribute>
+ <xsl:attribute name="number:country">HR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1113">
+ <!-- Sindhi - India,#0459 -->
+ <xsl:attribute name="number:language">sd</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2137">
+ <!-- Sindhi - Pakistan, #0859 -->
+ <xsl:attribute name="number:language">sd</xsl:attribute>
+ <xsl:attribute name="number:country">PK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1115">
+ <!-- Sinhalese - Sri Lanka, #045b -->
+ <xsl:attribute name="number:language">si</xsl:attribute>
+ <xsl:attribute name="number:country">LK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1051">
+ <!-- Slovak, #041b -->
+ <xsl:attribute name="number:language">sk</xsl:attribute>
+ <xsl:attribute name="number:country">SK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1060">
+ <!-- Slovenian, #0424 -->
+ <xsl:attribute name="number:language">sl</xsl:attribute>
+ <xsl:attribute name="number:country">SI</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1143">
+ <!-- Somali, #0477 -->
+ <xsl:attribute name="number:language">so</xsl:attribute>
+ <xsl:attribute name="number:country">SO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1070">
+ <!-- Sorbian, #042e -->
+ <xsl:attribute name="number:language">wen</xsl:attribute>
+ <xsl:attribute name="number:country">DE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 3082">
+ <!-- Spanish - Spain (Modern/International Sort), #0c0a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">ES</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1034">
+ <!-- Spanish - Spain (Traditional Sort), #040a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">ES</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 11274">
+ <!-- Spanish - Argentina, #2c0a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">AR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 16394">
+ <!-- Spanish - Bolivia, #400a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">BO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 13322">
+ <!-- Spanish - Chile, #340a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">CL</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 9226">
+ <!-- Spanish - Colombia, #240a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">CO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 5130">
+ <!-- Spanish - Costa Rica, #140a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">CR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 7178">
+ <!-- Spanish - Dominican Republic, #1c0a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">DO</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 12298">
+ <!-- Spanish - Ecuador, #300a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">EC</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 17418">
+ <!-- Spanish - EL Salvador, #440a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">SV</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 4106">
+ <!-- Spanish - Guatemala, #100a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">GT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 18442">
+ <!-- Spanish - Honduras, #480a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">HN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 58378">
+ <!-- Spanish - Latin America (Argentina), #e40a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">AR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2058">
+ <!-- Spanish - Mexico, #080a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">MX</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 19466">
+ <!-- Spanish - Nicaragua, #4c0a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">NI</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 6154">
+ <!-- Spanish - Panama, #180a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">PA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 15370">
+ <!-- Spanish - Paraguay, #3c0a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">PY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 10250">
+ <!-- Spanish - Peru, #280a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">PE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 20490">
+ <!-- Spanish - Puerto Rico, #500a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">PR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 21514">
+ <!-- Spanish - US, #540a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">US</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 14346">
+ <!-- Spanish - Uruguay, #380a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">UY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 8202">
+ <!-- Spanish - Venezuela, #200a -->
+ <xsl:attribute name="number:language">es</xsl:attribute>
+ <xsl:attribute name="number:country">VE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1072">
+ <!-- Sutu (Ngoni - Tanzania), #0430 -->
+ <xsl:attribute name="number:language">bnt</xsl:attribute>
+ <xsl:attribute name="number:country">TZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1089">
+ <!-- Swahili (Tanzania), #0441 -->
+ <xsl:attribute name="number:language">sw</xsl:attribute>
+ <xsl:attribute name="number:country">TZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1053">
+ <!-- Swedish (Sweden), #041d -->
+ <xsl:attribute name="number:language">sv</xsl:attribute>
+ <xsl:attribute name="number:country">SE</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2077">
+ <!-- Swedish - Finland, #081d -->
+ <xsl:attribute name="number:language">sv</xsl:attribute>
+ <xsl:attribute name="number:country">FI</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1114">
+ <!-- Syriac (Syria), #045a -->
+ <xsl:attribute name="number:language">syr</xsl:attribute>
+ <xsl:attribute name="number:country">SY</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1064">
+ <!-- Tajik, #0428 -->
+ <xsl:attribute name="number:language">tg</xsl:attribute>
+ <xsl:attribute name="number:country">TJ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1119">
+ <!-- Tamazight (Arabic), #045f -->
+ <xsl:attribute name="number:language">ber</xsl:attribute>
+ <xsl:attribute name="number:country">ML</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2143">
+ <!-- Tamazight (Latin), #085f -->
+ <xsl:attribute name="number:language">ber</xsl:attribute>
+ <xsl:attribute name="number:country">MA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1097">
+ <!-- Tamil (India), #0449 -->
+ <xsl:attribute name="number:language">ta</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1092">
+ <!-- Tatar (Russia), #0444 -->
+ <xsl:attribute name="number:language">tt</xsl:attribute>
+ <xsl:attribute name="number:country">RU</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1098">
+ <!-- Telugu (India), #044a -->
+ <xsl:attribute name="number:language">te</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1054">
+ <!-- Thai, #041e -->
+ <xsl:attribute name="number:language">th</xsl:attribute>
+ <xsl:attribute name="number:country">TH</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2129">
+ <!-- Tibetan - Bhutan, #0851 -->
+ <xsl:attribute name="number:language">bo</xsl:attribute>
+ <xsl:attribute name="number:country">BT</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1105">
+ <!-- Tibetan - People's Republic of China, #0451 -->
+ <xsl:attribute name="number:language">bo</xsl:attribute>
+ <xsl:attribute name="number:country">CN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2163">
+ <!-- Tigrigna (Tigrinya) - Eritrea, #0873 -->
+ <xsl:attribute name="number:language">ti</xsl:attribute>
+ <xsl:attribute name="number:country">ER</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1139">
+ <!-- Tigrigna (Tigrinya) - Ethiopia, #0473 -->
+ <xsl:attribute name="number:language">ti</xsl:attribute>
+ <xsl:attribute name="number:country">ET</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1073">
+ <!-- Tsonga (South Africa), #0431 -->
+ <xsl:attribute name="number:language">ts</xsl:attribute>
+ <xsl:attribute name="number:country">ZA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1074">
+ <!-- Tswana (South Africa), #0432 -->
+ <xsl:attribute name="number:language">tn</xsl:attribute>
+ <xsl:attribute name="number:country">ZA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1055">
+ <!-- Turkish, #041f -->
+ <xsl:attribute name="number:language">tr</xsl:attribute>
+ <xsl:attribute name="number:country">TR</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1090">
+ <!-- Turkmen, #0442 -->
+ <xsl:attribute name="number:language">tk</xsl:attribute>
+ <xsl:attribute name="number:country">TM</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1152">
+ <!-- Uighur - China, #0480 -->
+ <xsl:attribute name="number:language">ug</xsl:attribute>
+ <xsl:attribute name="number:country">CN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1058">
+ <!-- Ukrainian, #0422 -->
+ <xsl:attribute name="number:language">uk</xsl:attribute>
+ <xsl:attribute name="number:country">UA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1056">
+ <!-- Urdu (Pakistan), #0420 -->
+ <xsl:attribute name="number:language">ur</xsl:attribute>
+ <xsl:attribute name="number:country">PK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2080">
+ <!-- Urdu - India, #0820 -->
+ <xsl:attribute name="number:language">ur</xsl:attribute>
+ <xsl:attribute name="number:country">IN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 2115">
+ <!-- Uzbek (Cyrillic), #0843 -->
+ <xsl:attribute name="number:language">uz</xsl:attribute>
+ <xsl:attribute name="number:country">UZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1091">
+ <!-- Uzbek (Latin), #0443 -->
+ <xsl:attribute name="number:language">uz</xsl:attribute>
+ <xsl:attribute name="number:country">UZ</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1075">
+ <!-- Venda (South Africa), #0433 -->
+ <xsl:attribute name="number:language">ve</xsl:attribute>
+ <xsl:attribute name="number:country">ZA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1066">
+ <!-- Vietnamese, #042a -->
+ <xsl:attribute name="number:language">vi</xsl:attribute>
+ <xsl:attribute name="number:country">VN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1106">
+ <!-- Welsh (UK), #0452 -->
+ <xsl:attribute name="number:language">cy</xsl:attribute>
+ <xsl:attribute name="number:country">UK</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1076">
+ <!-- Xhosa (South Africa), #0434 -->
+ <xsl:attribute name="number:language">xh</xsl:attribute>
+ <xsl:attribute name="number:country">ZA</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1144">
+ <!-- Yi (Sino-Tibetan - China), #0478 -->
+ <xsl:attribute name="number:language">sit</xsl:attribute>
+ <xsl:attribute name="number:country">CN</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1085">
+ <!-- Yiddish (Jews - Israel), #043d -->
+ <xsl:attribute name="number:language">yi</xsl:attribute>
+ <xsl:attribute name="number:country">IL</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1130">
+ <!-- Yoruba (Nigeria), #046a -->
+ <xsl:attribute name="number:language">yo</xsl:attribute>
+ <xsl:attribute name="number:country">NG</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$language-country-code = 1077">
+ <!-- Zulu (South Africa), #0435 -->
+ <xsl:attribute name="number:language">zu</xsl:attribute>
+ <xsl:attribute name="number:country">ZA</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number-format-condition">
+ <xsl:param name="number-format-unit"/>
+ <xsl:choose>
+ <xsl:when test="contains($number-format-unit, '[&gt;')">
+ <xsl:value-of select="concat('&gt;', substring-before( substring-after($number-format-unit,'[&gt;'), ']'))"/>
+ </xsl:when>
+ <xsl:when test="contains($number-format-unit, '[&lt;')">
+ <xsl:value-of select="concat('&lt;', substring-before( substring-after($number-format-unit,'[&lt;'), ']'))"/>
+ </xsl:when>
+ <xsl:when test="contains($number-format-unit, '[=')">
+ <xsl:value-of select="concat('=', substring-before( substring-after($number-format-unit,'[='), ']'))"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="add-number-text-value">
+ <xsl:param name="style-type-name"/>
+ <xsl:param name="number-format-unit"/>
+ <xsl:param name="unit-pos"/>
+ <xsl:param name="condition-pos"/>
+ <xsl:param name="isNumberTextElementOpened" select="false()"/>
+ <xsl:param name="numberTextValue"/>
+ <xsl:param name="posed-number-format-unit"/>
+ <xsl:param name="finished" select="false()"/>
+ <xsl:choose>
+ <xsl:when test="not($finished)">
+ <xsl:choose>
+<!-- <xsl:when test="$style-type-name='number:text-style' or $style-type-name='number:date-style'"> -->
+ <xsl:when test="$style-type-name='number:text-style'">
+ <xsl:choose>
+ <xsl:when test="$isNumberTextElementOpened">
+ <number:text-content/>
+ <number:text>
+ <xsl:copy-of select="$numberTextValue"/>
+ </number:text>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="true()"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <number:text>
+ <xsl:copy-of select="$numberTextValue"/>
+ </number:text>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="true()"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ </xsl:call-template>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="finished" select="true()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$style-type-name='number:number-style'">
+ <xsl:choose>
+ <xsl:when test="$isNumberTextElementOpened">
+ <xsl:copy-of select="$numberTextValue"/>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="true()"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <number:text>
+ <xsl:copy-of select="$numberTextValue"/>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="true()"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ </xsl:call-template>
+ </number:text>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="finished" select="true()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <number:text>
+ <xsl:copy-of select="$numberTextValue"/>
+ </number:text>
+ <xsl:choose>
+ <xsl:when test="starts-with($posed-number-format-unit, '\')">
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="finished" select="false()" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="finished" select="true()" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number-text-content">
+ <xsl:param name="style-type-name"/>
+ <xsl:param name="number-format-unit"/>
+ <xsl:param name="unit-pos"/>
+ <xsl:param name="condition-pos"/>
+ <xsl:param name="isNumberTextElementOpened" select="false()"/>
+ <xsl:param name="finished" select="false()"/>
+ <xsl:param name="posed-number-format-unit"/>
+ <!-- process number-format-unit by character string parser -->
+ <xsl:choose>
+ <xsl:when test="starts-with( $posed-number-format-unit, '\') or starts-with( $posed-number-format-unit, '*')">
+ <xsl:choose>
+ <xsl:when test="not($finished)">
+ <xsl:call-template name="add-number-text-value">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="$isNumberTextElementOpened"/>
+ <xsl:with-param name="posed-number-format-unit" select="substring($number-format-unit,$unit-pos + 2)"/>
+ <!-- place '*' temporarily here, because now StarCalc doesn't support variable filling character definition -->
+ <xsl:with-param name="numberTextValue" select="substring($posed-number-format-unit,2,1)"/>
+ <xsl:with-param name="finished" select="$finished"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="substring($number-format-unit,$unit-pos +2)"/>
+ <xsl:with-param name="finished" select="true()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '_')">
+ <xsl:choose>
+ <xsl:when test="not($finished)">
+ <xsl:call-template name="add-number-text-value">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="$isNumberTextElementOpened"/>
+ <xsl:with-param name="posed-number-format-unit" select="substring($number-format-unit,$unit-pos + 2)"/>
+ <!-- adding an empty string -->
+ <xsl:with-param name="numberTextValue" select="' '"/>
+ <xsl:with-param name="finished" select="$finished"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="substring($number-format-unit,$unit-pos + 2)"/>
+ <xsl:with-param name="finished" select="true()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '&quot;')">
+ <xsl:choose>
+ <xsl:when test="not($finished)">
+ <!-- creating a pre-character string -->
+ <xsl:variable name="pre-character-string" select="substring-before(substring($posed-number-format-unit,2), '&quot;')"/>
+ <xsl:call-template name="add-number-text-value">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + string-length($pre-character-string) + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="substring($number-format-unit,$unit-pos + string-length($pre-character-string) + 2)"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="$isNumberTextElementOpened"/>
+ <xsl:with-param name="numberTextValue" select="$pre-character-string"/>
+ <xsl:with-param name="finished" select="$finished"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- creating a pre-character string -->
+ <xsl:variable name="pre-character-string" select="substring-before(substring($posed-number-format-unit,2), '&quot;')"/>
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + string-length($pre-character-string) + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="substring($number-format-unit,$unit-pos + string-length($pre-character-string) + 2)"/>
+ <xsl:with-param name="finished" select="true()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$finished">
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-number-format-content">
+ <xsl:param name="style-type-name"/>
+ <xsl:param name="number-format-unit"/>
+ <xsl:param name="unit-pos"/>
+ <xsl:param name="condition-pos"/>
+ <xsl:param name="isNumberTextElementOpened" select="false()"/>
+ <xsl:variable name="posed-number-format-unit" select="substring($number-format-unit,$unit-pos)"/>
+ <xsl:variable name="calendar-type-name">
+ <xsl:if test="contains( $number-format-unit, '[$')">
+ <xsl:variable name="format-code" select="substring-before( substring-after( substring-after( $number-format-unit, '[$'), '-'), ']')"/>
+ <xsl:if test="string-length( $format-code) &gt; 4">
+ <xsl:call-template name="get-calendar-type-name">
+ <xsl:with-param name="calendar-type" select="substring( $format-code, string-length($format-code) -5, 2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:variable>
+ <!-- process number-format-unit by character string parser -->
+ <xsl:choose>
+ <xsl:when test="starts-with( $posed-number-format-unit, '[$') and (not(starts-with($posed-number-format-unit, '[$-') ) )">
+ <xsl:element name="number:currency-symbol">
+ <xsl:call-template name="create-language-country-attribute">
+ <xsl:with-param name="attribute-code" select="substring-before(substring-after(substring-after($posed-number-format-unit,'[$'),'-'),']')"/>
+ </xsl:call-template>
+ <xsl:value-of select="substring-before( substring-after( $posed-number-format-unit, '[$'), '-')"/>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + string-length( substring-before( $posed-number-format-unit, ']') ) + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '\') or starts-with( $posed-number-format-unit, '*') or starts-with( $posed-number-format-unit, '_') or starts-with( $posed-number-format-unit, '&quot;')">
+ <xsl:call-template name="get-number-text-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="(starts-with( $posed-number-format-unit, '0') or starts-with( $posed-number-format-unit, '#') or starts-with( $posed-number-format-unit, '?') ) and (not ( contains( $posed-number-format-unit, 's.00') ) )">
+ <xsl:variable name="valid-number-format-string">
+ <xsl:call-template name="get-valid-number-format-string">
+ <xsl:with-param name="number-format-unit" select="$posed-number-format-unit"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains( $valid-number-format-string, '/')">
+ <xsl:element name="number:fraction">
+ <xsl:attribute name="number:min-integer-digits">
+ <xsl:value-of select="string-length( substring-before($valid-number-format-string, '/') ) - string-length(translate( substring-before($valid-number-format-string, '/'), '0', '') )"/>
+ </xsl:attribute>
+ <xsl:if test="contains( $valid-number-format-string, ',')">
+ <xsl:attribute name="number:grouping">true</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="number:min-numerator-digits">
+ <xsl:value-of select="string-length( substring-before($valid-number-format-string, '/') ) - string-length(translate( substring-before($valid-number-format-string,'/'), '?', '') )"/>
+ </xsl:attribute>
+ <xsl:attribute name="number:min-denominator-digits">
+ <xsl:value-of select="string-length(substring-after($valid-number-format-string, '/') )"/>
+ </xsl:attribute>
+ <!-- deal with number:embedded-text (removed, as SCHEMA demands element to be empty)
+ <xsl:call-template name="create-number-format-embedded-text">
+ <xsl:with-param name="adapted-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ -->
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="contains( $valid-number-format-string, '%')">
+ <xsl:element name="number:number">
+ <xsl:choose>
+ <xsl:when test="contains( $valid-number-format-string, '.')">
+ <xsl:attribute name="number:decimal-places">
+ <xsl:value-of select="string-length( substring-before( substring-after( $valid-number-format-string, '.'), '%') ) - string-length( translate( substring-before( substring-after( $valid-number-format-string, '.'), '%'), '0', '') )"/>
+ </xsl:attribute>
+ <xsl:attribute name="number:min-integer-digits">
+ <xsl:value-of select="string-length( substring-before($valid-number-format-string, '.') ) - string-length(translate( substring-before($valid-number-format-string, '.'), '0', '') )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="number:decimal-places">0</xsl:attribute>
+ <xsl:attribute name="number:min-integer-digits">
+ <xsl:value-of select="string-length( substring-before($valid-number-format-string, '%') ) - string-length(translate( substring-before($valid-number-format-string, '%'), '0', '') )"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="contains( $valid-number-format-string, ',') and (substring( $valid-number-format-string,string-length($valid-number-format-string)) = ',')">
+ <xsl:variable name="display-factor">
+ <xsl:call-template name="get-display-factor">
+ <xsl:with-param name="start-number" select="1"/>
+ <xsl:with-param name="thousand-count" select="string-length($valid-number-format-string) - string-length( translate($valid-number-format-string, ',', '') )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="number:display-factor">
+ <xsl:value-of select="$display-factor"/>
+ </xsl:attribute>
+ <xsl:attribute name="number:grouping">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $valid-number-format-string, ',')">
+ <xsl:attribute name="number:grouping">true</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <!-- deal with number:embedded-text -->
+ <xsl:call-template name="create-number-format-embedded-text">
+ <xsl:with-param name="adapted-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:element>
+ <number:text>%</number:text>
+ </xsl:when>
+ <xsl:when test="contains( $valid-number-format-string, 'E') or contains ($valid-number-format-string, 'e')">
+ <xsl:element name="number:scientific-number">
+ <xsl:choose>
+ <xsl:when test="contains( $valid-number-format-string, '.')">
+ <xsl:attribute name="number:decimal-places">
+ <xsl:value-of select="string-length( substring-before( substring-after( $valid-number-format-string, '.'), 'E') ) - string-length( translate( substring-before( substring-after( $valid-number-format-string, '.'), 'E'), '0', '') )"/>
+ </xsl:attribute>
+ <xsl:attribute name="number:min-integer-digits">
+ <xsl:value-of select="string-length( substring-before($valid-number-format-string, '.') ) - string-length(translate( substring-before($valid-number-format-string, '.'), '0', '') )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="number:decimal-places">0</xsl:attribute>
+ <xsl:attribute name="number:min-integer-digits">
+ <xsl:value-of select="string-length( substring-before($valid-number-format-string, 'E') ) - string-length(translate( substring-before($valid-number-format-string, 'E'), '0', '') )"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="number:min-exponent-digits">
+ <xsl:value-of select="string-length( substring-after( $valid-number-format-string, 'E') ) - string-length( translate( substring-after( $valid-number-format-string, 'E'), '0', '') )"/>
+ </xsl:attribute>
+ <!-- deal with number:embedded-text -->
+ <xsl:call-template name="create-number-format-embedded-text">
+ <xsl:with-param name="adapted-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- -normal number format, currency, and accounting, e.g -->
+ <xsl:element name="number:number">
+ <xsl:choose>
+ <xsl:when test="contains( $valid-number-format-string, '.')">
+ <xsl:attribute name="number:decimal-places">
+ <xsl:value-of select="string-length( substring-after( $valid-number-format-string, '.') ) - string-length( translate( substring-after( $valid-number-format-string, '.'), '0', '') )"/>
+ </xsl:attribute>
+ <xsl:attribute name="number:min-integer-digits">
+ <xsl:value-of select="string-length( substring-before($valid-number-format-string, '.') ) - string-length(translate( substring-before($valid-number-format-string, '.'), '0', '') )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="number:decimal-places">0</xsl:attribute>
+ <xsl:attribute name="number:min-integer-digits">
+ <xsl:value-of select="string-length( $valid-number-format-string ) - string-length(translate( $valid-number-format-string, '0', '') )"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="contains( $valid-number-format-string, ',') and (substring( $valid-number-format-string,string-length($valid-number-format-string)) = ',')">
+ <xsl:variable name="display-factor">
+ <xsl:call-template name="get-display-factor">
+ <xsl:with-param name="start-number" select="1"/>
+ <xsl:with-param name="thousand-count">
+ <xsl:call-template name="thousand-count-temp">
+ <xsl:with-param name="format-unit" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="number:display-factor">
+ <xsl:value-of select="$display-factor"/>
+ </xsl:attribute>
+ <xsl:attribute name="number:grouping">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $valid-number-format-string, ',')">
+ <xsl:attribute name="number:grouping">true</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <!-- deal with number:embedded-text -->
+ <xsl:call-template name="create-number-format-embedded-text">
+ <xsl:with-param name="adapted-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- deal with post number:text -->
+ <xsl:variable name="post-number-format-text">
+ <xsl:call-template name="get-post-number-format-text">
+ <xsl:with-param name="adapted-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$post-number-format-text"/>
+ <xsl:with-param name="unit-pos" select="1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'ggg')">
+ <xsl:element name="number:era">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 3"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'gg')">
+ <xsl:element name="number:era">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'g')">
+ <xsl:element name="number:era">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'ee')">
+ <xsl:element name="number:year">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'r')">
+ <xsl:element name="number:year">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'yyyy')">
+ <xsl:element name="number:year">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 4"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'yy')">
+ <xsl:element name="number:year">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'e') or starts-with( $posed-number-format-unit, 'y')">
+ <xsl:element name="number:year">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'mmmmm')">
+ <xsl:element name="number:month">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:attribute name="number:textual">true</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 5"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'mmmm')">
+ <xsl:element name="number:month">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:attribute name="number:textual">true</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 4"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'mmm')">
+ <xsl:element name="number:month">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:attribute name="number:textual">true</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 3"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '[mm]')">
+ <xsl:element name="number:minutes">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 4"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '[m]')">
+ <xsl:element name="number:minutes">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 3"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'mm') and ( contains( $number-format-unit, 'h') or contains( $posed-number-format-unit, 's') )">
+ <xsl:element name="number:minutes">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'mm')">
+ <xsl:element name="number:month">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'm') and ( contains( $number-format-unit, 'h') or contains( $posed-number-format-unit, 's') )">
+ <xsl:element name="number:minutes">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'm')">
+ <xsl:element name="number:month">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'dddd') or starts-with( $posed-number-format-unit, 'aaaa')">
+ <xsl:element name="number:day-of-week">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 4"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'ddd') or starts-with( $posed-number-format-unit, 'aaa')">
+ <xsl:element name="number:day-of-week">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 3"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'dd')">
+ <xsl:element name="number:day">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'd')">
+ <xsl:element name="number:day">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:if test="string-length($calendar-type-name) &gt; 0">
+ <xsl:attribute name="number:calendar">
+ <xsl:value-of select="$calendar-type-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'hh')">
+ <xsl:element name="number:hours">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 2"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '[hh]')">
+ <xsl:element name="number:hours">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 4"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'h')">
+ <xsl:element name="number:hours">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '[h]')">
+ <xsl:element name="number:hours">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 3"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'AM/PM') or starts-with( $posed-number-format-unit, 'am/pm')">
+ <number:am-pm/>
+ <!-- long: am-pm doesn't support long style yet -->
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 5"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'a/p'or starts-with( $posed-number-format-unit, 'A/P'))">
+ <number:am-pm/>
+ <!-- short: am-pm doesn't support short style yet -->
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 3"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'ss')">
+ <xsl:variable name="decimal-places">
+ <xsl:choose>
+ <xsl:when test="starts-with( $posed-number-format-unit, 'ss.0')">
+ <xsl:value-of select="string-length( $posed-number-format-unit) - string-length( translate( $posed-number-format-unit, '0', '') )"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="number:seconds">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ <xsl:if test="$decimal-places &gt; 0">
+ <xsl:attribute name="number:decimal-places">
+ <xsl:value-of select="$decimal-places"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:variable name="second-length">
+ <xsl:choose>
+ <xsl:when test="$decimal-places &gt; 0">
+ <xsl:value-of select="$decimal-places + 3"/>
+ </xsl:when>
+ <xsl:otherwise>2</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + $second-length"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '[ss]')">
+ <xsl:element name="number:seconds">
+ <xsl:attribute name="number:style">long</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 4"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, 's')">
+ <xsl:variable name="decimal-places">
+ <xsl:choose>
+ <xsl:when test="starts-with( $posed-number-format-unit, 's.0')">
+ <xsl:value-of select="string-length( $posed-number-format-unit) - string-length( translate( $posed-number-format-unit, '0', '') )"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="number:seconds">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ <xsl:if test="$decimal-places &gt; 0">
+ <xsl:attribute name="number:decimal-places">
+ <xsl:value-of select="$decimal-places"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:variable name="second-length">
+ <xsl:choose>
+ <xsl:when test="$decimal-places &gt; 0">
+ <xsl:value-of select="$decimal-places + 2"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + $second-length"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '[s]')">
+ <xsl:element name="number:seconds">
+ <xsl:attribute name="number:style">short</xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 3"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '@')">
+ <number:text-content/>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'General Number'">
+ <number:number number:decimal-places="0" number:min-integer-digits="1"/>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'General Date'">
+ <number:year number:style="long"/>
+ <number:text>-</number:text>
+ <number:month number:style="short"/>
+ <number:text>-</number:text>
+ <number:day number:style="short"/>
+ <number:text>
+ <xsl:text> </xsl:text>
+ </number:text>
+ <number:hours number:style="short"/>
+ <number:text>:</number:text>
+ <number:minutes number:style="long"/>
+ </xsl:when>
+ <!-- special for General number:text-content output -->
+ <xsl:when test="starts-with($posed-number-format-unit , 'General')">
+ <xsl:choose>
+ <xsl:when test="$posed-number-format-unit = 'General' and $condition-pos = 1">
+ <number:number number:decimal-places="0" number:min-integer-digits="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="8"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Fixed'">
+ <number:number number:decimal-places="2" number:min-integer-digits="1"/>
+ <number:text/>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Standard'">
+ <number:number number:decimal-places="2" number:min-integer-digits="1" number:grouping="true"/>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Long Date'">
+ <number:year number:style="long"/>
+ <number:text>-</number:text>
+ <number:month number:style="long"/>
+ <number:text>-</number:text>
+ <number:day number:style="long"/>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Medium Date'">
+ <number:day number:style="short"/>
+ <number:text>-</number:text>
+ <number:month number:textual="true"/>
+ <number:text>-</number:text>
+ <number:year number:style="short"/>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Short Date'">
+ <number:day number:style="short"/>
+ <number:text>-</number:text>
+ <number:month number:style="short"/>
+ <number:text>-</number:text>
+ <number:year number:style="short"/>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Long Time'">
+ <number:hours number:style="long"/>
+ <number:text>:</number:text>
+ <number:minutes number:style="long"/>
+ <number:text>:</number:text>
+ <number:seconds number:style="long"/>
+ <number:text>
+ <xsl:text> </xsl:text>
+ </number:text>
+ <number:am-pm/>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Medium Time'">
+ <number:hours number:style="short"/>
+ <number:text>:</number:text>
+ <number:minutes number:style="long"/>
+ <number:text>
+ <xsl:text> </xsl:text>
+ </number:text>
+ <number:am-pm/>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Short Time'">
+ <number:hours number:style="short"/>
+ <number:text>:</number:text>
+ <number:minutes number:style="long"/>
+ <number:text>
+ <xsl:text> </xsl:text>
+ </number:text>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Percent'">
+ <number:number number:decimal-places="2" number:min-integer-digits="1"/>
+ <number:text>%</number:text>
+ </xsl:when>
+ <xsl:when test="$posed-number-format-unit = 'Scientific'">
+ <number:scientific-number number:decimal-places="2" number:min-integer-digits="1" number:min-exponent-digits="2"/>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '[')">
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + string-length( substring-before( $posed-number-format-unit, ']') ) + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="$isNumberTextElementOpened"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, '/')">
+ <number:text>/</number:text>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( $posed-number-format-unit, ':')">
+ <number:text>:</number:text>
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="string-length( $posed-number-format-unit ) &gt; 0">
+ <xsl:call-template name="create-number-format-content">
+ <xsl:with-param name="style-type-name" select="$style-type-name"/>
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ <xsl:with-param name="unit-pos" select="$unit-pos + 1"/>
+ <xsl:with-param name="condition-pos" select="$condition-pos"/>
+ <xsl:with-param name="isNumberTextElementOpened" select="$isNumberTextElementOpened"/>
+ <xsl:with-param name="posed-number-format-unit" select="$posed-number-format-unit"/>
+ <xsl:with-param name="numberTextValue" select="substring( $posed-number-format-unit, 1, 1)"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="thousand-count-temp">
+ <!-- thousand count for char ',' at the latter of format-unit by recursion -->
+ <xsl:param name="format-unit"/>
+ <xsl:choose>
+ <xsl:when test="contains($format-unit, ',#')">
+ <xsl:call-template name="thousand-count-temp">
+ <xsl:with-param name="format-unit" select="substring-after($format-unit, ',#')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($format-unit, ',0')">
+ <xsl:call-template name="thousand-count-temp">
+ <xsl:with-param name="format-unit" select="substring-after($format-unit, ',0')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length($format-unit) - string-length( translate($format-unit, ',', ''))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-calendar-type-name">
+ <xsl:param name="calendar-type"/>
+ <xsl:variable name="temp-type">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="$calendar-type"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="string-length($calendar-type)"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <!-- Japanese (Emperor era), #03 -->
+ <xsl:when test="$temp-type = 3">gengou</xsl:when>
+ <!-- Taiwanese, #04 -->
+ <xsl:when test="$temp-type = 4">ROC</xsl:when>
+ <!-- Korean (Tangun era) hanja_yoil is ok too. #05 -->
+ <xsl:when test="$temp-type = 5">hanja</xsl:when>
+ <!-- Hijri (Arabic lunar), #06 -->
+ <xsl:when test="$temp-type = 6">hijri</xsl:when>
+ <!-- Thai, #07 -->
+ <xsl:when test="$temp-type = 7">buddhist</xsl:when>
+ <!-- 01: Gregorian (Localized), 02: Gregorian (United States), 09: Gregorian (Middle East French), 0A: Gregorian (Arabic), 0B: Gregorian (Transliterated English) -->
+ <xsl:otherwise>gregorian</xsl:otherwise>
+ <!-- not found jewish yet -->
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-valid-number-format-string">
+ <xsl:param name="number-format-unit"/>
+ <xsl:choose>
+ <xsl:when test="contains( $number-format-unit, '\')">
+ <xsl:call-template name="get-valid-number-format-string">
+ <xsl:with-param name="number-format-unit" select="concat( substring-before( $number-format-unit, '\'), substring( substring-after( $number-format-unit, '\'), 2) )"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $number-format-unit, '*')">
+ <xsl:call-template name="get-valid-number-format-string">
+ <xsl:with-param name="number-format-unit" select="concat( substring-before( $number-format-unit, '*'), substring( substring-after( $number-format-unit, '*'), 2) )"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $number-format-unit, '_')">
+ <xsl:call-template name="get-valid-number-format-string">
+ <xsl:with-param name="number-format-unit" select="concat( substring-before( $number-format-unit, '_'), substring( substring-after( $number-format-unit, '_'), 2) )"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $number-format-unit, '&quot;')">
+ <xsl:call-template name="get-valid-number-format-string">
+ <xsl:with-param name="number-format-unit" select="concat( substring-before( $number-format-unit, '&quot;'), substring-after( substring-after( $number-format-unit, '&quot;'), '&quot;') )"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$number-format-unit"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-display-factor">
+ <xsl:param name="start-number"/>
+ <xsl:param name="thousand-count"/>
+ <xsl:choose>
+ <xsl:when test="$thousand-count = 0">
+ <xsl:value-of select="$start-number"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-display-factor">
+ <xsl:with-param name="start-number" select="$start-number * 1000"/>
+ <xsl:with-param name="thousand-count" select="$thousand-count -1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-post-number-format-text">
+ <xsl:param name="adapted-number-format-unit"/>
+ <xsl:param name="valid-number-format-string"/>
+ <xsl:variable name="first-embedded-character-pos">
+ <xsl:choose>
+ <xsl:when test="contains( $adapted-number-format-unit, '\')">
+ <xsl:value-of select="string-length( substring-before($adapted-number-format-unit, '\') ) + 1"/>
+ </xsl:when>
+ <xsl:when test="contains( $adapted-number-format-unit, '_')">
+ <xsl:value-of select="string-length( substring-before($adapted-number-format-unit, '_') ) + 1"/>
+ </xsl:when>
+ <xsl:when test="contains( $adapted-number-format-unit, '*')">
+ <xsl:value-of select="string-length( substring-before($adapted-number-format-unit, '*') ) + 1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="first-embedded-string-pos">
+ <xsl:choose>
+ <xsl:when test="contains( $adapted-number-format-unit, '&quot;')">
+ <xsl:value-of select="string-length( substring-before($adapted-number-format-unit, '&quot;') ) + 1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="first-embedded-text-pos">
+ <xsl:choose>
+ <xsl:when test="$first-embedded-character-pos &lt; $first-embedded-string-pos and $first-embedded-character-pos &gt; 0">
+ <xsl:value-of select="$first-embedded-character-pos"/>
+ </xsl:when>
+ <xsl:when test="$first-embedded-character-pos &lt; $first-embedded-string-pos and $first-embedded-character-pos = 0">
+ <xsl:value-of select="$first-embedded-string-pos"/>
+ </xsl:when>
+ <xsl:when test="$first-embedded-character-pos &gt; $first-embedded-string-pos and $first-embedded-string-pos &gt; 0">
+ <xsl:value-of select="$first-embedded-string-pos"/>
+ </xsl:when>
+ <xsl:when test="$first-embedded-character-pos &gt; $first-embedded-string-pos and $first-embedded-string-pos = 0">
+ <xsl:value-of select="$first-embedded-character-pos"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-embedded-text-pos &gt; string-length( $valid-number-format-string )">
+ <xsl:value-of select="substring( $adapted-number-format-unit, $first-embedded-text-pos)"/>
+ </xsl:when>
+ <xsl:when test="$first-embedded-text-pos &gt; 0 and $first-embedded-text-pos &lt; string-length( $valid-number-format-string )">
+ <xsl:choose>
+ <xsl:when test="starts-with( substring( $adapted-number-format-unit, $first-embedded-text-pos, 1), '\')">
+ <xsl:call-template name="get-post-number-format-text">
+ <xsl:with-param name="adapted-number-format-unit" select="concat( substring-before( $adapted-number-format-unit, '\'), substring( $adapted-number-format-unit, $first-embedded-text-pos + 2) )"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( substring( $adapted-number-format-unit, $first-embedded-text-pos, 1), '_')">
+ <xsl:call-template name="get-post-number-format-text">
+ <xsl:with-param name="adapted-number-format-unit" select="concat( substring-before( $adapted-number-format-unit, '_'), substring( $adapted-number-format-unit, $first-embedded-text-pos + 2) )"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( substring( $adapted-number-format-unit, $first-embedded-text-pos, 1), '*')">
+ <xsl:call-template name="get-post-number-format-text">
+ <xsl:with-param name="adapted-number-format-unit" select="concat( substring-before( $adapted-number-format-unit, '*'), substring( $adapted-number-format-unit, $first-embedded-text-pos + 2) )"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( substring( $adapted-number-format-unit, $first-embedded-text-pos, 1), '&quot;')">
+ <xsl:call-template name="get-post-number-format-text">
+ <xsl:with-param name="adapted-number-format-unit" select="concat( substring-before( $adapted-number-format-unit, '&quot;'), substring-after( substring-after( $adapted-number-format-unit, '&quot;'), '&quot;') )"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-number-format-embedded-text">
+ <xsl:param name="adapted-number-format-unit"/>
+ <xsl:param name="valid-number-format-string"/>
+ <xsl:variable name="first-embedded-character-pos">
+ <xsl:choose>
+ <xsl:when test="contains( $adapted-number-format-unit, '\')">
+ <xsl:value-of select="string-length( substring-before($adapted-number-format-unit, '\') ) + 1"/>
+ </xsl:when>
+ <xsl:when test="contains( $adapted-number-format-unit, '_')">
+ <xsl:value-of select="string-length( substring-before($adapted-number-format-unit, '_') ) + 1"/>
+ </xsl:when>
+ <xsl:when test="contains( $adapted-number-format-unit, '*')">
+ <xsl:value-of select="string-length( substring-before($adapted-number-format-unit, '*') ) + 1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="first-embedded-string-pos">
+ <xsl:choose>
+ <xsl:when test="contains( $adapted-number-format-unit, '&quot;')">
+ <xsl:value-of select="string-length( substring-before($adapted-number-format-unit, '&quot;') ) + 1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="first-embedded-text-pos">
+ <xsl:choose>
+ <xsl:when test="$first-embedded-character-pos &lt; $first-embedded-string-pos and $first-embedded-character-pos &gt; 0">
+ <xsl:value-of select="$first-embedded-character-pos"/>
+ </xsl:when>
+ <xsl:when test="$first-embedded-character-pos &lt; $first-embedded-string-pos and $first-embedded-character-pos = 0">
+ <xsl:value-of select="$first-embedded-string-pos"/>
+ </xsl:when>
+ <xsl:when test="$first-embedded-character-pos &gt; $first-embedded-string-pos and $first-embedded-string-pos &gt; 0">
+ <xsl:value-of select="$first-embedded-string-pos"/>
+ </xsl:when>
+ <xsl:when test="$first-embedded-character-pos &gt; $first-embedded-string-pos and $first-embedded-string-pos = 0">
+ <xsl:value-of select="$first-embedded-character-pos"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$first-embedded-text-pos &gt; 0 and $first-embedded-text-pos &lt; string-length( $valid-number-format-string )">
+ <xsl:variable name="text-pos">
+ <xsl:choose>
+ <xsl:when test="contains( $valid-number-format-string, '.')">
+ <xsl:variable name="right-text-pos" select="substring( substring-before( $valid-number-format-string, '.'), $first-embedded-text-pos)"/>
+ <xsl:value-of select="string-length($right-text-pos) - string-length( translate( $right-text-pos, '0#?', '') )"/>
+ </xsl:when>
+ <xsl:when test="contains( $valid-number-format-string, '/')">
+ <xsl:variable name="right-text-pos" select="substring( substring-before( $valid-number-format-string, '/'), $first-embedded-text-pos)"/>
+ <xsl:value-of select="string-length($right-text-pos) - string-length( translate( $right-text-pos, '0#?', '') )"/>
+ </xsl:when>
+ <xsl:when test="contains( $valid-number-format-string, '%')">
+ <xsl:variable name="right-text-pos" select="substring( substring-before( $valid-number-format-string, '%'), $first-embedded-text-pos)"/>
+ <xsl:value-of select="string-length($right-text-pos) - string-length( translate( $right-text-pos, '0#?', '') )"/>
+ </xsl:when>
+ <xsl:when test="contains( $valid-number-format-string, 'E')">
+ <xsl:variable name="right-text-pos" select="substring( substring-before( $valid-number-format-string, 'E'), $first-embedded-text-pos)"/>
+ <xsl:value-of select="string-length($right-text-pos) - string-length( translate( $right-text-pos, '0#?', '') )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="right-text-pos" select="substring( $valid-number-format-string, $first-embedded-text-pos)"/>
+ <xsl:value-of select="string-length($right-text-pos) - string-length( translate( $right-text-pos, '0#?', '') )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="starts-with( substring( $adapted-number-format-unit, $first-embedded-text-pos, 1), '\')">
+ <number:embedded-text number:position="{$text-pos}">
+ <xsl:value-of select="substring( $adapted-number-format-unit, $first-embedded-text-pos + 1, 1)"/>
+ </number:embedded-text>
+ <xsl:call-template name="create-number-format-embedded-text">
+ <xsl:with-param name="adapted-number-format-unit" select="concat( substring-before( $adapted-number-format-unit, '\'), substring( $adapted-number-format-unit, $first-embedded-text-pos + 2) )"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( substring( $adapted-number-format-unit, $first-embedded-text-pos, 1), '_')">
+ <number:embedded-text number:position="{$text-pos}">
+ <xsl:value-of select="substring( $adapted-number-format-unit, $first-embedded-text-pos + 1, 1)"/>
+ </number:embedded-text>
+ <xsl:call-template name="create-number-format-embedded-text">
+ <xsl:with-param name="adapted-number-format-unit" select="concat( substring-before( $adapted-number-format-unit, '_'), substring( $adapted-number-format-unit, $first-embedded-text-pos + 2) )"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( substring( $adapted-number-format-unit, $first-embedded-text-pos, 1), '*')">
+ <number:embedded-text number:position="{$text-pos}">
+ <xsl:value-of select="substring( $adapted-number-format-unit, $first-embedded-text-pos + 1, 1)"/>
+ </number:embedded-text>
+ <xsl:call-template name="create-number-format-embedded-text">
+ <xsl:with-param name="adapted-number-format-unit" select="concat( substring-before( $adapted-number-format-unit, '*'), substring( $adapted-number-format-unit, $first-embedded-text-pos + 2) )"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with( substring( $adapted-number-format-unit, $first-embedded-text-pos, 1), '&quot;')">
+ <number:embedded-text number:position="{$text-pos}">
+ <xsl:value-of select="substring-before( substring( $adapted-number-format-unit, $first-embedded-text-pos + 1), '&quot;')"/>
+ </number:embedded-text>
+ <xsl:call-template name="create-number-format-embedded-text">
+ <xsl:with-param name="adapted-number-format-unit" select="concat( substring-before( $adapted-number-format-unit, '&quot;'), substring-after( substring-after( $adapted-number-format-unit, '&quot;'), '&quot;') )"/>
+ <xsl:with-param name="valid-number-format-string" select="$valid-number-format-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-master-styles">
+ <xsl:param name="worksheetoptions"/>
+ <xsl:for-each select="$worksheetoptions">
+ <xsl:element name="style:master-page">
+ <xsl:attribute name="style:name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string" select="concat( 'TAB_', ../@ss:Name)"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="style:display-name">
+ <xsl:value-of select="concat( 'PageStyle_', ../@ss:Name)"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:page-layout-name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string" select="concat( 'pm_', ../@ss:Name)"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="x:PageSetup/x:Header/@x:Data">
+ <style:header>
+ <xsl:call-template name="translate-header-footer">
+ <xsl:with-param name="content" select="x:PageSetup/x:Header/@x:Data"/>
+ <xsl:with-param name="style-name-header" select="concat(../@ss:Name, substring(name(x:PageSetup/x:Header),1,1))"/>
+ </xsl:call-template>
+ </style:header>
+ </xsl:when>
+ <xsl:otherwise>
+ <style:header style:display="false"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="x:PageSetup/x:Footer/@x:Data">
+ <style:footer>
+ <xsl:call-template name="translate-header-footer">
+ <xsl:with-param name="content" select="x:PageSetup/x:Footer/@x:Data"/>
+ <xsl:with-param name="style-name-header" select="concat(../@ss:Name, substring(name(x:PageSetup/x:Footer),1,1))"/>
+ </xsl:call-template>
+ </style:footer>
+ </xsl:when>
+ <xsl:otherwise>
+ <style:footer style:display="false"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="translate-header-footer">
+ <xsl:param name="content"/>
+ <xsl:param name="style-name-header"/>
+ <style:region-left>
+ <text:p>
+ <xsl:variable name="left-content">
+ <xsl:call-template name="get-pos-content">
+ <xsl:with-param name="content" select="$content"/>
+ <xsl:with-param name="pos" select="'left'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="locate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="$left-content"/>
+ <xsl:with-param name="style-name-header" select="concat($style-name-header,'L')"/>
+ <xsl:with-param name="index" select="0"/>
+ <xsl:with-param name="current-pos" select="1"/>
+ </xsl:call-template>
+ </text:p>
+ </style:region-left>
+ <style:region-center>
+ <text:p>
+ <xsl:variable name="center-content">
+ <xsl:call-template name="get-pos-content">
+ <xsl:with-param name="content" select="$content"/>
+ <xsl:with-param name="pos" select="'center'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="locate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="$center-content"/>
+ <xsl:with-param name="style-name-header" select="concat($style-name-header,'C')"/>
+ <xsl:with-param name="index" select="0"/>
+ <xsl:with-param name="current-pos" select="1"/>
+ </xsl:call-template>
+ </text:p>
+ </style:region-center>
+ <style:region-right>
+ <text:p>
+ <xsl:variable name="right-content">
+ <xsl:call-template name="get-pos-content">
+ <xsl:with-param name="content" select="$content"/>
+ <xsl:with-param name="pos" select="'right'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="locate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="$right-content"/>
+ <xsl:with-param name="style-name-header" select="concat($style-name-header,'R')"/>
+ <xsl:with-param name="index" select="0"/>
+ <xsl:with-param name="current-pos" select="1"/>
+ </xsl:call-template>
+ </text:p>
+ </style:region-right>
+ </xsl:template>
+ <xsl:template name="locate-header-footer-data">
+ <xsl:param name="header-footer-data"/>
+ <xsl:param name="style-name-header"/>
+ <xsl:param name="index"/>
+ <xsl:param name="current-pos"/>
+ <xsl:variable name="current-style-data">
+ <xsl:value-of select="substring($header-footer-data,$current-pos)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="starts-with($current-style-data,'&amp;X') or starts-with($current-style-data,'&amp;Y') or starts-with($current-style-data,'&amp;S') or starts-with($current-style-data,'&amp;U') or starts-with($current-style-data,'&amp;E') or starts-with($current-style-data,'&amp;B')">
+ <xsl:call-template name="locate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="$header-footer-data"/>
+ <xsl:with-param name="style-name-header" select="$style-name-header"/>
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="current-pos" select="$current-pos+2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;0') or starts-with($current-style-data,'&amp;1') or starts-with($current-style-data,'&amp;2') or starts-with($current-style-data,'&amp;3') or starts-with($current-style-data,'&amp;4') or starts-with($current-style-data,'&amp;5') or starts-with($current-style-data,'&amp;6') or starts-with($current-style-data,'&amp;7') or starts-with($current-style-data,'&amp;8') or starts-with($current-style-data,'&amp;9')">
+ <xsl:variable name="font-size-length">
+ <xsl:call-template name="get-digit-length">
+ <xsl:with-param name="complexive-string" select="substring-after($current-style-data,'&amp;')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="locate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="$header-footer-data"/>
+ <xsl:with-param name="style-name-header" select="$style-name-header"/>
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="current-pos" select="$current-pos+1+$font-size-length"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;&quot;')">
+ <xsl:call-template name="locate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="$header-footer-data"/>
+ <xsl:with-param name="style-name-header" select="$style-name-header"/>
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="current-pos" select="string-length(substring-before(substring($header-footer-data,$current-pos+2),'&quot;'))+$current-pos+3"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="current-content-last-pos">
+ <xsl:call-template name="get-current-content-last-pos">
+ <xsl:with-param name="style-data" select="$header-footer-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$current-pos &gt; 1">
+ <text:span text:style-name="{concat($style-name-header,$index)}">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring($header-footer-data,$current-pos,$current-content-last-pos+1-$current-pos)"/>
+ </xsl:call-template>
+ </text:span>
+ <xsl:if test="$current-content-last-pos &lt; string-length($header-footer-data)">
+ <xsl:call-template name="locate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="$header-footer-data"/>
+ <xsl:with-param name="style-name-header" select="$style-name-header"/>
+ <xsl:with-param name="index" select="$index+1"/>
+ <xsl:with-param name="current-pos" select="$current-content-last-pos+1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring($header-footer-data,$current-pos,$current-content-last-pos+1-$current-pos)"/>
+ </xsl:call-template>
+ <xsl:if test="$current-content-last-pos &lt; string-length($header-footer-data)">
+ <xsl:call-template name="locate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="$header-footer-data"/>
+ <xsl:with-param name="style-name-header" select="$style-name-header"/>
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="current-pos" select="$current-content-last-pos+1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-current-content-last-pos">
+ <xsl:param name="style-data"/>
+ <xsl:param name="current-pos"/>
+ <xsl:variable name="current-style-data">
+ <xsl:value-of select="substring($style-data,$current-pos)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="starts-with($current-style-data,'&amp;&quot;') or starts-with($current-style-data,'&amp;X') or starts-with($current-style-data,'&amp;Y') or starts-with($current-style-data,'&amp;S') or starts-with($current-style-data,'&amp;U') or starts-with($current-style-data,'&amp;E') or starts-with($current-style-data,'&amp;B')or starts-with($current-style-data,'&amp;0') or starts-with($current-style-data,'&amp;1') or starts-with($current-style-data,'&amp;2') or starts-with($current-style-data,'&amp;3') or starts-with($current-style-data,'&amp;4') or starts-with($current-style-data,'&amp;5') or starts-with($current-style-data,'&amp;6') or starts-with($current-style-data,'&amp;7') or starts-with($current-style-data,'&amp;8') or starts-with($current-style-data,'&amp;9')">
+ <xsl:value-of select="$current-pos - 1"/>
+ </xsl:when>
+ <xsl:when test="contains($current-style-data,'&amp;&quot;') or contains($current-style-data,'&amp;X') or contains($current-style-data,'&amp;Y') or contains($current-style-data,'&amp;S') or contains($current-style-data,'&amp;U') or contains($current-style-data,'&amp;E') or contains($current-style-data,'&amp;B')or contains($current-style-data,'&amp;0') or contains($current-style-data,'&amp;1') or contains($current-style-data,'&amp;2') or contains($current-style-data,'&amp;3') or contains($current-style-data,'&amp;4') or contains($current-style-data,'&amp;5') or contains($current-style-data,'&amp;6') or contains($current-style-data,'&amp;7') or contains($current-style-data,'&amp;8') or contains($current-style-data,'&amp;9')">
+ <xsl:variable name="temp" select="substring-before(substring($current-style-data,2),'&amp;')"/>
+ <xsl:variable name="next-amp-pos">
+ <xsl:value-of select="$current-pos+string-length($temp)+1"/>
+ </xsl:variable>
+ <xsl:call-template name="get-current-content-last-pos">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$next-amp-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length($style-data)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="translate-header-footer-data">
+ <xsl:param name="header-footer-data"/>
+ <xsl:choose>
+ <xsl:when test="contains( $header-footer-data, '&amp;D')">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-before( $header-footer-data, '&amp;D')"/>
+ </xsl:call-template>
+ <text:date/>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-after( $header-footer-data, '&amp;D')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $header-footer-data, '&amp;T')">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-before( $header-footer-data, '&amp;T')"/>
+ </xsl:call-template>
+ <text:time/>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-after( $header-footer-data, '&amp;T')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $header-footer-data, '&amp;P')">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-before( $header-footer-data, '&amp;P')"/>
+ </xsl:call-template>
+ <text:page-number/>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-after( $header-footer-data, '&amp;P')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $header-footer-data, '&amp;N')">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-before( $header-footer-data, '&amp;N')"/>
+ </xsl:call-template>
+ <text:page-count/>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-after( $header-footer-data, '&amp;N')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $header-footer-data, '&amp;A')">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-before( $header-footer-data, '&amp;A')"/>
+ </xsl:call-template>
+ <text:sheet-name/>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-after( $header-footer-data, '&amp;A')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $header-footer-data, '&amp;Z&amp;F')">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-before( $header-footer-data, '&amp;Z&amp;F')"/>
+ </xsl:call-template>
+ <text:file-name text:display="full"/>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-after( $header-footer-data, '&amp;Z&amp;F')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $header-footer-data, '&amp;Z')">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-before( $header-footer-data, '&amp;Z')"/>
+ </xsl:call-template>
+ <text:file-name text:display="path"/>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-after( $header-footer-data, '&amp;Z')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains( $header-footer-data, '&amp;F')">
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-before( $header-footer-data, '&amp;F')"/>
+ </xsl:call-template>
+ <text:file-name text:display="name"/>
+ <xsl:call-template name="translate-header-footer-data">
+ <xsl:with-param name="header-footer-data" select="substring-after( $header-footer-data, '&amp;F')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$header-footer-data"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-page-master">
+ <xsl:param name="worksheetoptions"/>
+ <xsl:for-each select="$worksheetoptions">
+ <xsl:element name="style:page-layout">
+ <xsl:attribute name="style:name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string" select="concat( 'pm_', ../@ss:Name)"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:element name="style:page-layout-properties">
+ <xsl:choose>
+ <xsl:when test="x:PageSetup/x:Layout/@x:Orientation = 'Landscape'">
+ <xsl:attribute name="style:print-orientation">landscape</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:print-orientation">portrait</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="x:PageSetup/x:Layout/@x:StartPageNumber">
+ <xsl:attribute name="style:first-page-number">
+ <xsl:value-of select="x:PageSetup/x:Layout/@x:StartPageNumber"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:first-page-number">continue</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="x:PageSetup/x:PageMargins">
+ <xsl:attribute name="fo:margin-top">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(x:PageSetup/x:PageMargins/@x:Top,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="fo:margin-bottom">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(x:PageSetup/x:PageMargins/@x:Bottom,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="fo:margin-left">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(x:PageSetup/x:PageMargins/@x:Left,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="fo:margin-right">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(x:PageSetup/x:PageMargins/@x:Right,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="x:PageSetup/x:Header">
+ <style:header-style>
+ <xsl:element name="style:header-footer-properties">
+ <xsl:attribute name="fo:min-height">0.75cm</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="x:PageSetup/x:Header/@x:Margin">
+ <xsl:attribute name="fo:margin-bottom">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(x:PageSetup/x:Header/@x:Margin,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-bottom">0.25cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </style:header-style>
+ </xsl:if>
+ <xsl:if test="x:PageSetup/x:Footer">
+ <style:footer-style>
+ <xsl:element name="style:header-footer-properties">
+ <xsl:attribute name="fo:min-height">0.75cm</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="x:PageSetup/x:Footer/@x:Margin">
+ <xsl:attribute name="fo:margin-top">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(x:PageSetup/x:Footer/@x:Margin,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-top">0.25cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </style:footer-style>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="ss:Style" name="style-style-content" mode="style-style-content">
+ <xsl:element name="style:table-cell-properties">
+ <xsl:if test="ss:Alignment">
+ <xsl:if test="ss:Alignment/@ss:Vertical">
+ <xsl:variable name="vertical-align">
+ <xsl:choose>
+ <xsl:when test="ss:Alignment/@ss:Vertical = 'Top'">top</xsl:when>
+ <xsl:when test="ss:Alignment/@ss:Vertical = 'Center'">middle</xsl:when>
+ <xsl:when test="ss:Alignment/@ss:Vertical = 'Bottom'">bottom</xsl:when>
+ <xsl:when test="ss:Alignment/@ss:Vertical = 'Automatic'">middle</xsl:when>
+ <!-- actually for vertical written characters, not supported by StarOffice/OpenOffice now yet -->
+ <xsl:otherwise>middle</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:vertical-align">
+ <xsl:value-of select="$vertical-align"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ss:Alignment/@ss:WrapText = '1'">
+ <xsl:attribute name="fo:wrap-option">wrap</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ss:Alignment/@ss:Indent">
+ <xsl:attribute name="fo:padding-left"><!-- Indent is ten times of a point -->
+ <xsl:variable name="indent" select="ss:Alignment/@ss:Indent * 10"/>
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat($indent,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ss:Alignment/@ss:Rotate">
+ <xsl:attribute name="style:rotation-angle">
+ <xsl:choose>
+ <xsl:when test="ss:Alignment/@ss:Rotate &lt; 0">
+ <xsl:value-of select="360 + ss:Alignment/@ss:Rotate"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="ss:Alignment/@ss:Rotate"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="style:rotation-align">none</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ss:Alignment/@ss:VerticalText = '1'">
+ <xsl:attribute name="style:direction">ttb</xsl:attribute>
+ <!-- The horizontal align default for vertical text in Excel is 'center' -->
+ <xsl:if test="not(ss:Alignment/@ss:Horizontal)">
+ <!-- OASIS XML removal
+ <xsl:attribute name="fo:text-align">center</xsl:attribute>-->
+ <xsl:attribute name="style:text-align-source">fix</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="ss:Borders">
+ <xsl:if test="ss:Borders/ss:Border">
+ <xsl:apply-templates select="ss:Borders/ss:Border"/>
+ </xsl:if>
+ </xsl:if>
+ <xsl:apply-templates select="ss:Interior" mode="style-style-content"/>
+ <xsl:if test="ss:Protection">
+ <xsl:choose>
+ <xsl:when test="ss:Protection/@ss:Protected = '0'">
+ <xsl:choose>
+ <xsl:when test="ss:Protection/@ss:HideFormula = '1'">
+ <xsl:attribute name="style:cell-protect">hidden-and-protected</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:cell-protect">none</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="ss:Protection/@x:HideFormula = '1'">
+ <xsl:attribute name="style:cell-protect">protected formula-hidden</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:cell-protect">none</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <!-- fix means the horizontal alignment is dependent on ss:Horizontal,
+ but set on paragraph properties not cell paragraphs -->
+ <xsl:if test="ss:Alignment/@ss:Horizontal">
+ <xsl:attribute name="style:text-align-source">fix</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:choose>
+ <xsl:when test="ss:Alignment/@ss:Horizontal">
+ <xsl:element name="style:paragraph-properties">
+ <xsl:variable name="text-align">
+ <xsl:choose>
+ <xsl:when test="ss:Alignment/@ss:Horizontal = 'Left'">start</xsl:when>
+ <xsl:when test="ss:Alignment/@ss:Horizontal = 'Center'">center</xsl:when>
+ <xsl:when test="ss:Alignment/@ss:Horizontal = 'Right'">end</xsl:when>
+ <xsl:when test="ss:Alignment/@ss:Horizontal = 'Justify'">justify</xsl:when>
+ <!-- many other text-align not supported yet -->
+ <xsl:otherwise>start</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="fo:text-align">
+ <xsl:value-of select="$text-align"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- The horizontal align default for vertical text in Excel is 'center' -->
+ <xsl:element name="style:paragraph-properties">
+ <xsl:if test="ss:Alignment/@ss:VerticalText = '1'">
+ <xsl:attribute name="fo:text-align">center</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="ss:Font">
+ <xsl:element name="style:text-properties">
+ <xsl:choose>
+ <xsl:when test="ss:Font/@ss:FontName">
+ <xsl:attribute name="style:font-name">
+ <xsl:value-of select="ss:Font/@ss:FontName"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-name-asian">
+ <xsl:value-of select="ss:Font/@ss:FontName"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-name-complex">
+ <xsl:value-of select="ss:Font/@ss:FontName"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:font-name">Arial</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- "ss:Font/@x:Family" is useless here, so can't map to "svg:font-family" attribute -->
+ <xsl:if test="ss:Font/@ss:Bold = '1'">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-complex">bold</xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="ss:Font/@ss:Color">
+ <xsl:attribute name="fo:color">
+ <xsl:value-of select="ss:Font/@ss:Color"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-window-font-color">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="ss:Font/@ss:Italic = '1'">
+ <!-- omit font-style oblique -->
+ <xsl:attribute name="fo:font-style">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-complex">italic</xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="ss:Font/@ss:Size">
+ <xsl:attribute name="fo:font-size">
+ <xsl:value-of select="concat( ss:Font/@ss:Size, 'pt')"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-size-asian">
+ <xsl:value-of select="concat( ss:Font/@ss:Size, 'pt')"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-size-complex">
+ <xsl:value-of select="concat( ss:Font/@ss:Size, 'pt')"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:font-size">10pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian">10pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex">10pt</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="ss:Font/@ss:Outline = '1'">
+ <xsl:attribute name="style:text-outline">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ss:Font/@ss:Shadow = '1'">
+ <!-- Not in DTD nor in docu <xsl:attribute name="style:text-shadow">shadow</xsl:attribute> -->
+ <xsl:attribute name="fo:text-shadow">1pt 1pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ss:Font/@ss:StrikeThrough = '1'">
+ <xsl:attribute name="style:text-line-through-style">solid</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ss:Font/@ss:Underline">
+ <xsl:choose>
+ <xsl:when test="ss:Font/@ss:Underline = 'None'">
+ <xsl:attribute name="style:text-underline-type">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ss:Font/@ss:Underline = 'Single'">
+ <xsl:attribute name="style:text-underline-type">single</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ss:Font/@ss:Underline = 'Double'">
+ <xsl:attribute name="style:text-underline-type">double</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ss:Font/@ss:Underline = 'SingleAccounting'">
+ <xsl:attribute name="style:text-underline-type">single</xsl:attribute>"</xsl:when>
+ <xsl:when test="ss:Font/@ss:Underline = 'DoubleAccounting'">
+ <xsl:attribute name="style:text-underline-type">double</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:text-underline-type">none</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="ss:Font/@x:Charset">
+ <!-- quite unclear till now, -->
+ <xsl:attribute name="style:font-charset">x-symbol</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="ss:Interior" mode="style-style-content">
+ <xsl:choose>
+ <xsl:when test="@ss:Pattern = 'Solid'">
+ <xsl:if test="@ss:Color">
+ <xsl:attribute name="fo:background-color">
+ <xsl:value-of select="@ss:Color"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="@ss:PatternColor">
+ <xsl:variable name="pattern-value">
+ <xsl:call-template name="cell-pattern-color">
+ <xsl:with-param name="pattern" select="concat('0.',substring-after(@ss:Pattern,'y'))"/>
+ <xsl:with-param name="color-value" select="@ss:Color"/>
+ <xsl:with-param name="pattern-color-value" select="@ss:PatternColor"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:background-color">
+ <xsl:value-of select="$pattern-value"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template match="ss:Style">
+ <!-- style:default-style is meant for application defaults
+ <xsl:when test="@ss:ID = 'Default'">
+ <xsl:element name="style:default-style">
+ <xsl:call-template name="style-style-content" />
+ </xsl:element>
+ </xsl:when> -->
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">
+ <xsl:value-of select="@ss:ID"/>
+ </xsl:attribute>
+ <xsl:apply-templates select="@ss:Name" />
+ <xsl:choose>
+ <xsl:when test="@ss:Parent">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select="@ss:Parent"/>
+ </xsl:attribute>
+ </xsl:when>
+ <!-- no parent, but automatic style are automatically inheriting from a style called 'Default'
+ not necessary named style -->
+ <xsl:when test="not(key('Style', @ss:ID)/@ss:Name)">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:text>Default</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="ss:NumberFormat/@ss:Format">
+ <xsl:attribute name="style:data-style-name">
+ <xsl:value-of select="concat( @ss:ID, 'F')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style:family">table-cell</xsl:attribute>
+ <xsl:call-template name="style-style-content"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="cell-pattern-color">
+ <!-- generates a new color from cell-pattern-color -->
+ <xsl:param name="pattern"/>
+ <xsl:param name="color-value"/>
+ <xsl:param name="pattern-color-value"/>
+ <xsl:variable name="rev-pattern" select="1 - $pattern"/>
+ <xsl:variable name="color-R-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($color-value,2,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="color-G-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($color-value,4,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="color-B-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($color-value,6,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="pattern-R-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($pattern-color-value,2,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="pattern-G-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($pattern-color-value,4,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="pattern-B-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($pattern-color-value,6,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="R-value">
+ <xsl:variable name="combined-R-value">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="floor($color-R-value * $rev-pattern + $pattern-R-value * $pattern)"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($combined-R-value) = 1">
+ <xsl:value-of select="concat('0',$combined-R-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$combined-R-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="G-value">
+ <xsl:variable name="combined-G-value">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="floor($color-G-value * $rev-pattern + $pattern-G-value * $pattern)"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($combined-G-value) = 1">
+ <xsl:value-of select="concat('0',$combined-G-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$combined-G-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="B-value">
+ <xsl:variable name="combined-B-value">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="floor($color-B-value * $rev-pattern + $pattern-B-value * $pattern)"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($combined-B-value) = 1">
+ <xsl:value-of select="concat('0',$combined-B-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$combined-B-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat('#',$R-value,$G-value,$B-value)"/>
+ </xsl:template>
+ <xsl:template name="colorindex2decimal">
+ <xsl:param name="colorindex"/>
+ <xsl:variable name="colorIndexLookup">
+ <xsl:value-of select="$colorindex - 8"/>
+ </xsl:variable>
+ <xsl:variable name="tempColorValue">
+ <xsl:choose>
+ <!-- Grab the color from the custom color index if it exists... -->
+ <xsl:when test="/ss:Workbook/o:OfficeDocumentSettings/o:Colors/o:Color/o:Index=$colorIndexLookup">
+ <xsl:value-of select="substring-after(normalize-space(/ss:Workbook/o:OfficeDocumentSettings/o:Colors/o:Color/o:RGB[/ss:Workbook/o:OfficeDocumentSettings/o:Colors/o:Color/o:Index=$colorIndexLookup]), '#')"/>
+ </xsl:when >
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$colorindex=8">
+ <xsl:value-of select="'000000'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=9">
+ <xsl:value-of select="'FFFFFF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=10">
+ <xsl:value-of select="'FF0000'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=11">
+ <xsl:value-of select="'00FF00'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=12">
+ <xsl:value-of select="'0000FF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=13">
+ <xsl:value-of select="'FFFF00'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=14">
+ <xsl:value-of select="'FF00FF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=15">
+ <xsl:value-of select="'00FFFF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=16">
+ <xsl:value-of select="'800000'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=17">
+ <xsl:value-of select="'008000'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=18">
+ <xsl:value-of select="'000080'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=19">
+ <xsl:value-of select="'808000'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=20">
+ <xsl:value-of select="'800080'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=21">
+ <xsl:value-of select="'008080'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=22">
+ <xsl:value-of select="'C0C0C0'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=23">
+ <xsl:value-of select="'808080'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=24">
+ <xsl:value-of select="'9999FF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=25">
+ <xsl:value-of select="'993366'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=26">
+ <xsl:value-of select="'FFFFCC'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=27">
+ <xsl:value-of select="'CCFFFF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=28">
+ <xsl:value-of select="'660066'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=29">
+ <xsl:value-of select="'FF8080'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=30">
+ <xsl:value-of select="'0066CC'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=31">
+ <xsl:value-of select="'CCCCFF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=32">
+ <xsl:value-of select="'000080'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=33">
+ <xsl:value-of select="'FF00FF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=34">
+ <xsl:value-of select="'FFFF00'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=35">
+ <xsl:value-of select="'00FFFF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=36">
+ <xsl:value-of select="'800080'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=37">
+ <xsl:value-of select="'800000'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=38">
+ <xsl:value-of select="'008080'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=39">
+ <xsl:value-of select="'0000FF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=40">
+ <xsl:value-of select="'00CCFF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=41">
+ <xsl:value-of select="'CCFFFF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=42">
+ <xsl:value-of select="'CCFFCC'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=43">
+ <xsl:value-of select="'FFFF99'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=44">
+ <xsl:value-of select="'99CCFF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=45">
+ <xsl:value-of select="'FF99CC'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=46">
+ <xsl:value-of select="'CC99FF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=47">
+ <xsl:value-of select="'FFCC99'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=48">
+ <xsl:value-of select="'3366FF'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=49">
+ <xsl:value-of select="'33CCCC'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=50">
+ <xsl:value-of select="'99CC00'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=51">
+ <xsl:value-of select="'FFCC00'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=52">
+ <xsl:value-of select="'FF9900'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=53">
+ <xsl:value-of select="'FF6600'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=54">
+ <xsl:value-of select="'666699'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=55">
+ <xsl:value-of select="'969696'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=56">
+ <xsl:value-of select="'003366'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=57">
+ <xsl:value-of select="'339966'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=58">
+ <xsl:value-of select="'003300'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=59">
+ <xsl:value-of select="'333300'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=60">
+ <xsl:value-of select="'993300'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=61">
+ <xsl:value-of select="'993366'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=62">
+ <xsl:value-of select="'333399'"/>
+ </xsl:when>
+ <xsl:when test="$colorindex=63">
+ <xsl:value-of select="'333333'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'NOTFOUND'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="tempColorDecimal">
+ <xsl:choose>
+ <xsl:when test="not($tempColorValue = 'NOTFOUND')">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="$tempColorValue"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="6"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="4294967295"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$tempColorDecimal"/>
+ </xsl:template>
+ <xsl:template name="hex2decimal">
+ <!-- transforms a hex number to a decimal number.parses the string from left to right -->
+ <xsl:param name="hex-number"/>
+ <xsl:param name="index"/>
+ <xsl:param name="str-length"/>
+ <xsl:param name="last-value"/>
+ <xsl:variable name="dec-char">
+ <xsl:call-template name="hexNumber2dec">
+ <xsl:with-param name="hex-value" select="substring($hex-number, $index ,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="current-value" select="$last-value * 16 + $dec-char"/>
+ <xsl:if test="$index &lt; $str-length">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="$hex-number"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ <xsl:with-param name="str-length" select="$str-length"/>
+ <xsl:with-param name="last-value" select="$current-value"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$index = $str-length">
+ <xsl:value-of select="$current-value"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="hexNumber2dec">
+ <!-- return a decimal number for a hex character -->
+ <xsl:param name="hex-value"/>
+ <xsl:choose>
+ <xsl:when test="$hex-value = 'A' or ($hex-value = 'a')">
+ <xsl:value-of select="10"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'B' or ($hex-value = 'b')">
+ <xsl:value-of select="11"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'C' or ($hex-value = 'c')">
+ <xsl:value-of select="12"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'D' or ($hex-value = 'd')">
+ <xsl:value-of select="13"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'E' or ($hex-value = 'e')">
+ <xsl:value-of select="14"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'F' or ($hex-value = 'f')">
+ <xsl:value-of select="15"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$hex-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="decimal2hex">
+ <!-- transforms a decimal number to a hex number,only for two-bit hex(less than 256 in decimal) currently -->
+ <xsl:param name="dec-number"/>
+ <xsl:param name="last-value"/>
+ <xsl:variable name="current-value">
+ <xsl:call-template name="decNumber2hex">
+ <xsl:with-param name="dec-value">
+ <xsl:if test="$dec-number &gt; 15">
+ <xsl:value-of select="floor($dec-number div 16)"/>
+ </xsl:if>
+ <xsl:if test="$dec-number &lt; 16">
+ <xsl:value-of select="$dec-number"/>
+ </xsl:if>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$dec-number &gt; 15">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="$dec-number mod 16"/>
+ <xsl:with-param name="last-value" select="concat($last-value,$current-value)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$dec-number &lt; 16">
+ <xsl:value-of select="substring-after(concat($last-value,$current-value),'H')"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="decNumber2hex">
+ <!-- return a hex number for a decimal character -->
+ <xsl:param name="dec-value"/>
+ <xsl:choose>
+ <xsl:when test="$dec-value = 10">
+ <xsl:value-of select="'A'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 11">
+ <xsl:value-of select="'B'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 12">
+ <xsl:value-of select="'C'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 13">
+ <xsl:value-of select="'D'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 14">
+ <xsl:value-of select="'E'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 15">
+ <xsl:value-of select="'F'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$dec-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="ss:Border">
+ <xsl:variable name="position">
+ <xsl:choose>
+ <xsl:when test="@ss:Position = 'Top'">fo:border-top</xsl:when>
+ <xsl:when test="@ss:Position = 'Bottom'">fo:border-bottom</xsl:when>
+ <xsl:when test="@ss:Position = 'Left'">fo:border-left</xsl:when>
+ <xsl:when test="@ss:Position = 'Right'">fo:border-right</xsl:when>
+ <!-- DiagonalLeft & DiagonalRight are not supported yet, -->
+ <xsl:otherwise>fo:border-left</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="width">
+ <xsl:choose>
+ <!-- 0: Hairline -->
+ <xsl:when test="@ss:Weight = '0'">0.002cm</xsl:when>
+ <!-- 1: Thin -->
+ <xsl:when test="@ss:Weight = '1'">0.035cm</xsl:when>
+ <!-- 2: Medium -->
+ <xsl:when test="@ss:Weight = '2'">0.088cm</xsl:when>
+ <!-- 3: Thick -->
+ <xsl:when test="@ss:Weight = '3'">
+ <xsl:choose>
+ <xsl:when test="@ss:LineStyle = 'Double'">0.105cm</xsl:when>
+ <xsl:otherwise>0.141cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- invalid value, or parameter not exist at all -->
+ <xsl:otherwise>0.002cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="linestyle">
+ <xsl:choose>
+ <xsl:when test="@ss:LineStyle = 'None'">none</xsl:when>
+ <xsl:when test="@ss:LineStyle = 'Continuous'">solid</xsl:when>
+ <xsl:when test="@ss:LineStyle = 'Double'">double</xsl:when>
+ <!-- Dash, Dot, DashDot, DashDotDot, SlantDashDot are not supported yet -->
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="color">
+ <xsl:choose>
+ <xsl:when test="@ss:Color">
+ <xsl:value-of select="@ss:Color"/>
+ </xsl:when>
+ <!-- default border color is black -->
+ <xsl:otherwise>#000000</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="{$position}">
+ <xsl:value-of select="concat( $width, ' ', $linestyle, ' ', $color)"/>
+ </xsl:attribute>
+ <xsl:if test="@ss:LineStyle = 'Double'">
+ <xsl:variable name="widthposition">
+ <xsl:choose>
+ <xsl:when test="@ss:Position = 'Top'">style:border-line-width-top</xsl:when>
+ <xsl:when test="@ss:Position = 'Bottom'">style:border-line-width-bottom</xsl:when>
+ <xsl:when test="@ss:Position = 'Left'">style:border-line-width-left</xsl:when>
+ <xsl:when test="@ss:Position = 'Right'">style:border-line-width-right</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="{$widthposition}">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="ss:Font">
+ <xsl:choose>
+ <xsl:when test="@ss:VerticalAlign = 'Superscript'">
+ <style:style style:name="{concat(../@ss:ID,'T0')}" style:family="text">
+ <style:text-properties style:text-position="33% 58%"/>
+ </style:style>
+ </xsl:when>
+ <xsl:when test="@ss:VerticalAlign = 'Subscript'">
+ <style:style style:name="{concat(../@ss:ID,'T0')}" style:family="text">
+ <style:text-properties style:text-position="-33% 58%"/>
+ </style:style>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="ss:Table">
+ <xsl:variable name="default-column-width">
+ <xsl:choose>
+ <xsl:when test="@ss:DefaultColumnWidth">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(@ss:DefaultColumnWidth,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:when>
+ <!-- Note: Specify where this value come from... -->
+ <xsl:otherwise>2.096cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="table-pos">
+ <xsl:value-of select="count(../preceding-sibling::ss:Worksheet)+1"/>
+ </xsl:variable>
+ <!-- naming convention the default column style is name co<NumberOfSheet> e.g. co1 for the first sheet -->
+ <style:style style:family="table-column" style:name="{concat('co', $table-pos)}">
+ <style:table-column-properties fo:break-before="auto" style:column-width="{$default-column-width}"/>
+ </style:style>
+ <xsl:variable name="columnCount" select="count(ss:Column)"/>
+ <xsl:for-each select="ss:Column">
+ <xsl:apply-templates select="." mode="create-column-style">
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="currentCount" select="position()"/>
+ <xsl:with-param name="table-pos" select="$table-pos"/>
+ <xsl:with-param name="default-column-width" select="$default-column-width"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ <xsl:if test="../x:PageBreaks/x:ColBreaks">
+ <style:style style:name="{concat('cob',$table-pos)}" style:family="table-column">
+ <xsl:element name="style:table-column-properties">
+ <xsl:attribute name="style:column-width">
+ <xsl:value-of select="$default-column-width"/>
+ </xsl:attribute>
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:element>
+ </style:style>
+ </xsl:if>
+ <xsl:variable name="default-row-height">
+ <xsl:choose>
+ <xsl:when test="@ss:DefaultRowHeight">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(@ss:DefaultRowHeight,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:when>
+ <!-- Note: This is the default row height value in spec it is written 255 point, this seems wrong -->
+ <!-- <xsl:otherwise>0.503cm</xsl:otherwise> -->
+ <xsl:otherwise>0.45cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <style:style style:family="table-row" style:name="{concat('ro', $table-pos)}">
+ <style:table-row-properties style:row-height="{$default-row-height}" style:use-optimal-row-height="false"/>
+ </style:style>
+ <xsl:variable name="rowCount" select="count(ss:Row)"/>
+ <xsl:for-each select="ss:Row">
+ <xsl:apply-templates select="." mode="create-row-style">
+ <xsl:with-param name="rowNodeCount" select="$rowCount"/>
+ <xsl:with-param name="rowNodeIndex" select="position()"/>
+ <xsl:with-param name="table-pos" select="$table-pos"/>
+ <xsl:with-param name="default-row-height" select="$default-row-height"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ <xsl:if test="../x:PageBreaks/x:RowBreaks">
+ <style:style style:name="{concat('rob',$table-pos)}" style:family="table-row">
+ <xsl:element name="style:table-row-properties">
+ <xsl:attribute name="style:row-height">
+ <xsl:value-of select="$default-row-height"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:use-optimal-row-height">false</xsl:attribute>
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:element>
+ </style:style>
+ </xsl:if>
+ <!-- create table-style -->
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">
+ <xsl:value-of select="concat( 'ta', $table-pos)"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">table</xsl:attribute>
+ <!-- ss:Name have to be from type 'NCNameChar' ::= Letter | Digit | '.' | '-' | '_' | CombiningChar | Extender -->
+ <xsl:attribute name="style:master-page-name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string" select="../@ss:Name"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:element name="style:table-properties">
+ <xsl:choose>
+ <xsl:when test="../x:WorksheetOptions/x:Visible = 'SheetHidden'">
+ <xsl:attribute name="table:display">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:display">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="ss:Column" mode="create-column-style">
+ <!-- generate stylename of colbreak after matching the column number and the colbreak number -->
+ <xsl:param name="columnCount"/>
+ <xsl:param name="currentCount"/>
+ <xsl:param name="table-pos"/>
+ <xsl:param name="default-column-width"/>
+ <xsl:variable name="span-value" select="@ss:Span + count(@ss:Span)"/>
+ <xsl:variable name="finishedColumns">
+ <xsl:choose>
+ <xsl:when test="@ss:Index">
+ <xsl:value-of select="@ss:Index -1 + $span-value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="recent-index"
+ select="preceding-sibling::ss:Column[@ss:Index][last()]"/>
+ <xsl:choose>
+ <xsl:when test="$recent-index">
+ <xsl:variable name="nodes-up-to-current"
+ select="set:intersection(preceding-sibling::ss:Column, $recent-index/following-sibling::ss:Column)"/>
+ <xsl:variable name="allSpans" select="$nodes-up-to-current/@ss:Span"/>
+ <xsl:value-of
+ select="$recent-index/@ss:Index + count($nodes-up-to-current) + sum($allSpans) + count($allSpans)"
+ />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="allSpans" select="preceding-sibling::ss:Column/@ss:Span"/>
+
+ <xsl:value-of select="$currentCount + sum($allSpans) + count($allSpans)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="current-index">
+ <xsl:choose>
+ <xsl:when test="@ss:Index">
+ <xsl:value-of select="@ss:Index - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$finishedColumns"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="column-break">
+ <xsl:choose>
+ <xsl:when test="$span-value = 0">
+ <xsl:if test="../x:PageBreaks/x:ColBreaks/x:ColBreak/x:Column = $current-index">
+ <xsl:value-of select="1"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if
+ test="../x:PageBreaks/x:ColBreaks[(x:ColBreak/x:Column &gt; $finishedColumns) and (x:ColBreak/x:Column &lt; ($finishedColumns + $span-value))]">
+ <xsl:value-of select="1"/>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$column-break = 1">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">
+ <xsl:call-template name="encode-as-nc-name">
+ <xsl:with-param name="string"
+ select="concat('cob', $table-pos, '-',$currentCount)"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">table-column</xsl:attribute>
+ <xsl:element name="style:table-column-properties">
+ <xsl:choose>
+ <xsl:when test="@ss:Width">
+ <xsl:attribute name="style:column-width">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value"
+ select="concat(@ss:Width,'pt')"
+ />
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:column-width">
+ <xsl:value-of select="$default-column-width"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when
+ test="@ss:AutoFitWidth = '0'">
+ <xsl:attribute name="style:use-optimal-column-width"
+ >false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when
+ test="@ss:Width &gt; 0">
+ <xsl:attribute name="style:use-optimal-column-width"
+ >false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-optimal-column-width"
+ >true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ <style:style style:name="{concat('co', $table-pos, '-',$currentCount)}"
+ style:family="table-column">
+ <xsl:element name="style:table-column-properties">
+ <xsl:choose>
+ <xsl:when test="@ss:Width">
+ <xsl:attribute name="style:column-width">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value"
+ select="concat(@ss:Width,'pt')"
+ />
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:column-width">
+ <xsl:value-of select="$default-column-width"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:break-before">auto</xsl:attribute>
+ </xsl:element>
+ </style:style>
+ </xsl:template>
+
+ <xsl:template match="ss:Row" mode="create-row-style">
+ <!-- generate stylename of rowbreak after matching the row number and the rowbreak number -->
+ <xsl:param name="rowNodeCount"/>
+ <xsl:param name="rowNodeIndex" select="position()"/>
+ <xsl:param name="table-pos"/>
+ <xsl:param name="default-row-height"/>
+ <xsl:variable name="simple-span-value" select="@ss:Span + count(@ss:Span)"/>
+
+ <xsl:variable name="earlierRowNo">
+ <xsl:choose>
+ <xsl:when test="@ss:Index"><xsl:value-of select="@ss:Index -1 + $simple-span-value"/></xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="recent-index" select="preceding-sibling::ss:Row[@ss:Index][last()]"></xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$recent-index">
+ <xsl:variable name="nodes-up-to-current" select="set:intersection(preceding-sibling::ss:Row, $recent-index/following-sibling::ss:Row)"></xsl:variable>
+ <xsl:variable name="allSpans" select="$nodes-up-to-current/@ss:Span"/>
+ <xsl:value-of select="$recent-index/@ss:Index + count($nodes-up-to-current) + sum($allSpans) + count($allSpans)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="allSpans" select="preceding-sibling::ss:Row/@ss:Span"/>
+ <xsl:value-of select="position() + sum($allSpans) + count($allSpans)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="span-value">
+ <xsl:choose>
+ <xsl:when test="@ss:Index">
+ <xsl:choose>
+ <xsl:when test="@ss:Span">
+ <xsl:value-of select="@ss:Index - $earlierRowNo + @ss:Span"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@ss:Span">
+ <xsl:value-of select="@ss:Span + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="current-index">
+ <xsl:choose>
+ <xsl:when test="@ss:Index">
+ <xsl:value-of select="@ss:Index - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$earlierRowNo"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="row-break">
+ <xsl:choose>
+ <xsl:when test="$span-value = 0">
+ <xsl:if test="../x:PageBreaks/x:RowBreaks/x:RowBreak/x:Row = $current-index">
+ <xsl:value-of select="1"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="../x:PageBreaks/x:RowBreaks[(x:RowBreak/x:Row &gt; $earlierRowNo) and (x:RowBreak/x:Row &lt; ($earlierRowNo + $span-value))]">
+ <xsl:value-of select="1"/>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$row-break = 1">
+ <xsl:element name="style:style">
+ <xsl:choose>
+ <xsl:when test="@ss:StyleID">
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('ro', $table-pos, '-',$rowNodeIndex,'-',@ss:StyleID)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('ro', $table-pos, '-',$rowNodeIndex)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="style:family">table-row</xsl:attribute>
+
+
+ <xsl:element name="style:table-row-properties">
+ <xsl:choose>
+ <xsl:when test="@ss:Height">
+ <xsl:attribute name="style:row-height">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(@ss:Height,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:row-height">
+ <xsl:value-of select="$default-row-height"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@ss:AutoFitHeight = '0'">
+ <xsl:attribute name="style:use-optimal-row-height">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@ss:Height &gt; 0">
+ <xsl:attribute name="style:use-optimal-row-height">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-optimal-row-height">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ <xsl:apply-templates select="key('Style', @ss:StyleID)/ss:Interior" mode="style-style-content"/>
+ </xsl:element>
+ <!--
+ <xsl:apply-templates select="key('Style', @ss:StyleID)" mode="style-style-content" />
+ -->
+ </xsl:element>
+ </xsl:if>
+ <!--
+ <style:style style:name="{concat('ro', $table-pos, '-',$rowNodeIndex)}" style:family="table-row">
+ -->
+ <xsl:element name="style:style">
+ <xsl:choose>
+ <xsl:when test="@ss:StyleID">
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('ro', $table-pos, '-',$rowNodeIndex,'-',@ss:StyleID)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('ro', $table-pos, '-',$rowNodeIndex)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="style:family">table-row</xsl:attribute>
+
+
+ <xsl:element name="style:table-row-properties">
+ <xsl:choose>
+ <xsl:when test="@ss:Height">
+ <xsl:attribute name="style:row-height">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(@ss:Height,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:row-height">
+ <xsl:value-of select="$default-row-height"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@ss:AutoFitHeight">
+ <xsl:choose>
+ <xsl:when test="@ss:AutoFitHeight = '0'">
+ <xsl:attribute name="style:use-optimal-row-height">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-optimal-row-height">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@ss:Height &gt; 0">
+ <xsl:attribute name="style:use-optimal-row-height">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-optimal-row-height">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:break-before">auto</xsl:attribute>
+ <!-- apply to background -->
+ <xsl:apply-templates select="key('Style', @ss:StyleID)/ss:Interior" mode="style-style-content"/>
+ </xsl:element>
+ <!--
+ <xsl:apply-templates select="key('Style', ss:Row[position() = $rowNodeIndex]/@ss:StyleID)" mode="style-style-content" />
+ -->
+ </xsl:element>
+
+
+ </xsl:template>
+
+ <xsl:template name="count-spanned-columns">
+ <xsl:param name="expandedColumnCount" select="0"/>
+ <xsl:param name="columns"/>
+ <xsl:param name="columnsCount" select="count($columns)"/>
+ <xsl:param name="columnIndex" select="1"/>
+ <xsl:choose>
+ <xsl:when test="$columnIndex &lt;= $columnsCount">
+ <xsl:call-template name="count-spanned-columns">
+ <xsl:with-param name="columns" select="$columns"/>
+ <xsl:with-param name="columnsCount" select="$columnsCount"/>
+ <xsl:with-param name="columnIndex" select="$columnIndex + 1"/>
+ <xsl:with-param name="expandedColumnCount" select="$expandedColumnCount + $columns[$columnIndex]/@ss:Span"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$expandedColumnCount"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="ss:Worksheet">
+ <xsl:element name="table:table">
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="@ss:Name"/>
+ </xsl:attribute>
+ <!-- other attributes aren't suitable to apply yet -->
+ <xsl:if test="ss:Table">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat( 'ta', count(preceding-sibling::ss:Worksheet)+1)"/>
+ </xsl:attribute>
+ <xsl:if test="@ss:Protected = '1'">
+ <xsl:attribute name="table:protected">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="descendant::ss:NamedRange[@ss:Name = 'Print_Area' and contains( @ss:RefersTo, '!R')]">
+ <xsl:variable name="referto">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="descendant::ss:NamedRange/@ss:RefersTo"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="table:print-ranges">
+ <xsl:value-of select="translate( $referto, '=', '$')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="table-pos">
+ <xsl:value-of select="count(../preceding-sibling::ss:Worksheet)+1"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="ss:Table/@ss:ExpandedColumnCount">
+ <xsl:choose>
+ <xsl:when test="not(ss:Table/ss:Column)">
+ <!-- no columns exist -->
+ <xsl:call-template name="create-columns-without-input">
+ <xsl:with-param name="table-pos" select="$table-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="ss:Table/@ss:ExpandedColumnCount"/>
+ <xsl:with-param name="currentColumnNode" select="ss:Table/ss:Column[1]"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="ss:Table/ss:Column/@ss:Span">
+ <!-- No absolute column number (ss:ExpandedColumnCount) is add the nodes and spanned columns -->
+ <xsl:variable name="spannedColumns">
+ <xsl:call-template name="count-spanned-columns">
+ <xsl:with-param name="columns" select="ss:Table/ss:Column[@ss:Span]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="count(ss:Table/ss:Column) + number($spannedColumns)"/>
+ <xsl:with-param name="currentColumnNode" select="ss:Table/ss:Column[1]"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- No absolute column number (ss:ExpandedColumnCount) is add the nodes -->
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="count(ss:Table/ss:Column)"/>
+ <xsl:with-param name="currentColumnNode" select="ss:Table/ss:Column[1]"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- generates the string of row\column position if ConditionalFormatting exists -->
+ <xsl:variable name="condition-pos-str1">
+ <xsl:if test="./x:ConditionalFormatting">
+ <xsl:call-template name="condition-row-column-string">
+ <xsl:with-param name="last" select="''"/>
+ <xsl:with-param name="total" select="count(./x:ConditionalFormatting)"/>
+ <xsl:with-param name="index" select="1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="condition-pos-str2">
+ <xsl:if test="./x:DataValidation">
+ <xsl:call-template name="validation-row-column-string">
+ <xsl:with-param name="last" select="''"/>
+ <xsl:with-param name="total" select="count(./x:DataValidation)"/>
+ <xsl:with-param name="index" select="1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="condition-pos-str" select="concat($condition-pos-str1, $condition-pos-str2)"/>
+ <xsl:choose>
+ <xsl:when test="./ss:Table/ss:Row">
+ <xsl:variable name="worksheetNo" select="count(preceding-sibling::ss:Worksheet)+1"/>
+ <xsl:variable name="rowNodeCount" select="count(ss:Table/ss:Row)"/>
+ <xsl:variable name="expandedRowCount">
+ <xsl:call-template name="get-expanded-row-count"/>
+ </xsl:variable>
+ <xsl:variable name="expandedColumnCount">
+ <xsl:call-template name="get-expanded-column-count"/>
+ </xsl:variable>
+ <xsl:for-each select="ss:Table/ss:Row">
+ <xsl:apply-templates select="." mode="create-rows">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ <xsl:with-param name="rowNodeCount" select="$rowNodeCount"/>
+ <xsl:with-param name="rowNodeIndex" select="position()"/>
+ <xsl:with-param name="expandedRowCount" select="$expandedRowCount"/>
+ <xsl:with-param name="expandedRowCountIndex" select="1"/>
+ <xsl:with-param name="expandedColumnCount" select="$expandedColumnCount"/>
+ </xsl:apply-templates>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./x:PageBreaks/x:RowBreaks">
+ <xsl:for-each select="./x:PageBreaks/x:RowBreaks/x:RowBreak">
+ <xsl:variable name="number-repeated">
+ <xsl:choose>
+ <xsl:when test="position() = 1">
+ <xsl:value-of select="./x:Row"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=". - preceding::x:RowBreak[position()=count(.)]/x:Row - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$number-repeated &gt; 0">
+ <xsl:element name="table:table-row">
+ <xsl:if test="@ss:Hidden = '1'">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('ro',$table-pos)"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:number-rows-repeated">
+ <xsl:value-of select="$number-repeated"/>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="ss:Table/@ss:ExpandedColumnCount">
+ <table:table-cell table:number-columns-repeated="{ss:Table/@ss:ExpandedColumnCount}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- OASIS XML row can not be empty -->
+ <table:table-cell table:number-columns-repeated="256"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="table:table-row">
+ <xsl:if test="@ss:Hidden = '1'">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('rob',$table-pos)"/>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="ss:Table/@ss:ExpandedColumnCount">
+ <table:table-cell table:number-columns-repeated="{ss:Table/@ss:ExpandedColumnCount}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- OASIS XML row can not be empty -->
+ <table:table-cell table:number-columns-repeated="256"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- in case no table row exists (empty spreadsheet) -->
+ <xsl:element name="table:table-row">
+ <xsl:choose>
+ <xsl:when test="ss:Table/@ss:StyleID">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="ss:Table/@ss:StyleID"/>
+ </xsl:attribute>
+ <xsl:element name="table:table-cell">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="ss:Table/@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('ro',$table-pos)"/>
+ </xsl:attribute>
+ <xsl:element name="table:table-cell"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="./x:ConditionalFormatting">
+ <xsl:variable name="condition-row-max">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'R'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="condition-col-max">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'C'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="break-row-max">
+ <xsl:call-template name="break-row-beyond-max">
+ <xsl:with-param name="pos" select="1"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="count-value" select="count(./x:PageBreaks/x:RowBreaks/x:RowBreak)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="end-value">
+ <xsl:choose>
+ <xsl:when test="$condition-row-max &lt; $break-row-max">
+ <xsl:value-of select="$break-row-max"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$condition-row-max"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="get-row-beyond-last">
+ <xsl:with-param name="index-value" select="1"/>
+ <xsl:with-param name="worksheetNo" select="count(preceding-sibling::ss:Worksheet)+1"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="end-pos" select="$end-value"/>
+ <xsl:with-param name="total-col" select="$condition-col-max"/>
+ </xsl:call-template>
+ </xsl:if>
+ <!-- if exists attribute of StyleID in tag of ss:Table but no Row/Column -->
+ <xsl:if test="./ss:Table/@ss:StyleID">
+ <table:table-row table:style-name="{concat('ro',$table-pos)}" table:number-rows-repeated="65564">
+ <table:table-cell table:number-columns-repeated="256"/>
+ </table:table-row>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <!-- Note: Need to be refactored -->
+ <xsl:template name="create-columns-without-input">
+ <xsl:param name="table-pos"/>
+ <xsl:choose>
+ <xsl:when test="./x:PageBreaks/x:ColBreaks">
+ <xsl:for-each select="./x:PageBreaks/x:ColBreaks/x:ColBreak">
+ <xsl:variable name="number-repeated">
+ <xsl:choose>
+ <xsl:when test="position() = 1">
+ <xsl:value-of select="./x:Column"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=". - preceding::x:ColBreak[position()=count(.)]/x:Column - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$number-repeated &gt; 0">
+ <xsl:element name="table:table-column">
+ <xsl:if test="ancestor::ss:Worksheet/ss:Table/@ss:StyleID">
+ <xsl:attribute name="table:default-cell-style-name">
+ <xsl:value-of select="ancestor::ss:Worksheet/ss:Table/@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@ss:Hidden = '1'">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('co',$table-pos)"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="$number-repeated"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="table:table-column">
+ <!-- column style be made out beforehead -->
+ <xsl:if test="ancestor::ss:Worksheet/ss:Table/@ss:StyleID">
+ <xsl:attribute name="table:default-cell-style-name">
+ <xsl:value-of select="ancestor::ss:Worksheet/ss:Table/@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@ss:Hidden = '1'">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('cob',$table-pos)"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="table:table-column">
+ <xsl:choose>
+ <xsl:when test="ss:Table/@ss:StyleID">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="ss:Table/@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name">
+ <xsl:text>co1</xsl:text>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="ss:Table/@ss:ExpandedColumnCount and ss:Table/@ss:ExpandedColumnCount > 0">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="ss:Table/@ss:ExpandedColumnCount"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:default-cell-style-name">
+ <xsl:text>Default</xsl:text>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--
+ Example:
+ <ss:Table>
+ <ss:Column ss:Index="4" ss:Width="500" ss:Span="3" />
+ <ss:Column ss:Width="200" />
+ </ss:Table>
+
+ Prior column (ss:Index - 1) is written
+ The given fourth cell (ss:Index="4") is handled as repeated three times (ss:Span="3").
+ The eight column got a width of "200"
+
+ ContextNode: ss:Worksheet
+ -->
+ <xsl:key match="/ss:Workbook/ss:Worksheet/x:PageBreaks/x:ColBreaks/x:ColBreak" name="ColBreak" use="Column"/>
+ <xsl:template name="create-columns">
+ <xsl:param name="columnCount"/>
+ <xsl:param name="currentColumn" select="1"/>
+ <xsl:param name="finishedColumns" select="0"/>
+ <xsl:param name="worksheetNo" select="count(preceding-sibling::ss:Worksheet)+1"/>
+ <xsl:param name="currentColumnNode"/>
+ <xsl:choose>
+ <xsl:when test="$finishedColumns &lt; $columnCount">
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode">
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode/@ss:Index - $finishedColumns &gt; 1">
+ <!-- found column with index.
+ filling up table with empty columns until Index is reached -->
+ <xsl:call-template name="create-default-column">
+ <xsl:with-param name="currentColumn" select="$currentColumn"/>
+ <xsl:with-param name="currentColumnNode" select="$currentColumnNode"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="currentColumn" select="$currentColumn"/>
+ <xsl:with-param name="currentColumnNode" select="$currentColumnNode"/>
+ <xsl:with-param name="finishedColumns" select="$finishedColumns + 1"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="table:table-column">
+ <xsl:if test="$currentColumnNode/@ss:Hidden = '1'">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$currentColumnNode/@ss:Span">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="$currentColumnNode/@ss:Span + 1"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="key('ColBreak', $currentColumn)">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('cob', $worksheetNo, '-', $currentColumn)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('co', $worksheetNo, '-', $currentColumn)"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode/@ss:StyleID">
+ <xsl:attribute name="table:default-cell-style-name">
+ <xsl:value-of select="$currentColumnNode/@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:default-cell-style-name">
+ <xsl:text>Default</xsl:text>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="currentColumn" select="$currentColumn + 1"/>
+ <xsl:with-param name="finishedColumns">
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode/@ss:Span">
+ <xsl:value-of select="$finishedColumns + $currentColumnNode/@ss:Span + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$finishedColumns + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="currentColumnNode" select="ss:Table/ss:Column[$currentColumn + 1]"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- <xsl:if test="not($finishedColumns + 1 = $columnCount)"> -->
+ <xsl:call-template name="create-default-column">
+ <xsl:with-param name="currentColumn" select="$currentColumn"/>
+ <xsl:with-param name="currentColumnNode" select="$currentColumnNode"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="currentColumn" select="$currentColumn"/>
+ <xsl:with-param name="finishedColumns" select="$finishedColumns + 1"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$currentColumn = $columnCount">
+ <!-- Note: name test document for this case and refactor the template -->
+ <xsl:if test="x:PageBreaks/x:ColBreaks/x:ColBreak/x:Column &gt; $finishedColumns">
+ <xsl:call-template name="get-column-beyond-last">
+ <xsl:with-param name="index-value" select="$finishedColumns"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ </xsl:if>
+ <!--Note: Test Scenario for this case: generates some special tags for whole row style
+ <xsl:if test="(./ss:Table[@ss:StyleID] or ./ss:Table/ss:Row[@ss:StyleID]) and (256 - $finishedColumns &gt; 0)">
+ <xsl:element name="table:table-column">
+ <xsl:attribute name="table:default-cell-style-name"><xsl:choose><xsl:when test="./ss:Table[@ss:StyleID]"><xsl:value-of select="./ss:Table/@ss:StyleID" /></xsl:when><xsl:otherwise><xsl:value-of select="'Default'" /></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="'co1'" /></xsl:attribute>
+ <xsl:attribute name="table:number-columns-repeated"><xsl:value-of select="256 - $finishedColumns" /></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ -->
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-default-column">
+ <xsl:param name="currentColumn"/>
+ <xsl:param name="currentColumnNode"/>
+ <xsl:param name="worksheetNo"/>
+ <xsl:param name="nextColumnNo"/>
+ <xsl:element name="table:table-column">
+ <xsl:attribute name="table:default-cell-style-name">
+ <xsl:call-template name="get-default-cell-style">
+ <xsl:with-param name="currentColumnNode" select="$currentColumnNode"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <!-- <xsl:attribute name="table:default-cell-style-name"><xsl:value-of select="$nextColumnNo - $currentColumn"/></xsl:attribute> -->
+ <xsl:choose>
+ <xsl:when test="key('ColBreak', $currentColumn)">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('cob',$worksheetNo)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('co',$worksheetNo)"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="create-rows">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:apply-templates select="ss:Table/ss:Row[1]" mode="create-rows">
+ <xsl:with-param name="worksheetNo" select="count(preceding-sibling::ss:Worksheet)+1"/>
+ <xsl:with-param name="rowNodeCount" select="count(ss:Table/ss:Row)"/>
+ <xsl:with-param name="rowNodeIndex" select="1"/>
+ <xsl:with-param name="expandedRowCount">
+ <xsl:call-template name="get-expanded-row-count"/>
+ </xsl:with-param>
+ <xsl:with-param name="expandedRowCountIndex" select="1"/>
+ <xsl:with-param name="expandedColumnCount">
+ <xsl:call-template name="get-expanded-column-count"/>
+ </xsl:with-param>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:apply-templates>
+ </xsl:template>
+ <xsl:template match="ss:Row" mode="create-rows">
+ <xsl:param name="worksheetNo"/>
+ <xsl:param name="rowNodeCount"/>
+ <xsl:param name="rowNodeIndex"/>
+ <xsl:param name="expandedRowCount"/>
+ <xsl:param name="expandedColumnCount"/>
+ <xsl:param name="condition-pos-str"/>
+ <xsl:variable name="simple-span-value" select="@ss:Span + count(@ss:Span)"/>
+ <xsl:variable name="expandedRowCountIndex">
+ <xsl:choose>
+ <xsl:when test="@ss:Index"><xsl:value-of select="@ss:Index -1 + $simple-span-value"/></xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="recent-index" select="preceding-sibling::ss:Row[@ss:Index][last()]"></xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$recent-index">
+ <xsl:variable name="nodes-up-to-current" select="set:intersection(preceding-sibling::ss:Row, $recent-index/following-sibling::ss:Row)"></xsl:variable>
+ <xsl:variable name="allSpans" select="$nodes-up-to-current/@ss:Span"/>
+ <xsl:value-of select="$recent-index/@ss:Index + count($nodes-up-to-current) + sum($allSpans) + count($allSpans)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="allSpans" select="preceding-sibling::ss:Row/@ss:Span"/>
+ <xsl:value-of select="$rowNodeIndex + sum($allSpans) + count($allSpans)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="currentRowNo">
+ <xsl:choose>
+ <xsl:when test="@ss:Index">
+ <xsl:value-of select="@ss:Index"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$expandedRowCountIndex"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="@ss:Index - $expandedRowCountIndex &gt; 0">
+ <!-- create the preceding missing rows -->
+ <xsl:element name="table:table-row">
+ <!-- fill the preceding gap with rows without a cell -->
+ <xsl:attribute name="table:number-rows-repeated">
+ <xsl:value-of select="@ss:Index - $expandedRowCountIndex"/>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$expandedColumnCount != 0">
+ <table:table-cell table:number-columns-repeated="{$expandedColumnCount}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- OASIS XML row can not be empty -->
+ <table:table-cell table:number-columns-repeated="256"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="table:table-row">
+ <xsl:attribute name="table:style-name">
+ <xsl:choose>
+ <xsl:when test="@ss:StyleID">
+ <xsl:value-of select="concat('ro',$worksheetNo, '-',$rowNodeIndex,'-', @ss:StyleID)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('ro',$worksheetNo,'-',$rowNodeIndex)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:if test="@ss:Hidden = '1'">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@ss:Span">
+ <xsl:attribute name="table:number-rows-repeated">
+ <xsl:value-of select="@ss:Span + 1"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <!-- Excel row without content -->
+ <xsl:when test="not(*)">
+ <!-- OASIS OpenDocument Format does not allow rows without a cell -->
+ <xsl:choose>
+ <xsl:when test="$expandedColumnCount != 0">
+ <table:table-cell table:number-columns-repeated="{$expandedColumnCount}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- OASIS XML row can not be empty -->
+ <table:table-cell table:number-columns-repeated="256"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-cells">
+ <xsl:with-param name="row-pos" select="$currentRowNo"/>
+ <xsl:with-param name="expandedColumnCount" select="$expandedColumnCount"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+
+ </xsl:template>
+
+ <xsl:template name="get-expanded-column-count">
+ <xsl:choose>
+ <xsl:when test="ss:Table/@ss:ExpandedColumnCount">
+ <xsl:value-of select="ss:Table/@ss:ExpandedColumnCount"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="ss:Table/ss:Column/@ss:Span">
+ <!-- No absolute column number (ss:ExpandedColumnCount) is add the nodes and spanned columns -->
+ <xsl:variable name="spannedColumns">
+ <xsl:call-template name="count-spanned-columns">
+ <xsl:with-param name="columns" select="ss:Table/ss:Column[@ss:Span]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="count(ss:Table/ss:Column) + number($spannedColumns)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- No absolute column number (ss:ExpandedColumnCount) is add the nodes -->
+ <xsl:value-of select="count(ss:Table/ss:Column)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-expanded-row-count">
+ <xsl:choose>
+ <xsl:when test="ss:Table/@ss:ExpandedRowCount">
+ <xsl:value-of select="ss:Table/@ss:ExpandedRowCount"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="ss:Table/ss:Row/@ss:Index and not(ss:Table/ss:Row/@ss:Span)">
+ <xsl:variable name="lastIndexedRow" select="ss:Table/ss:Row[@ss:Index][last()]"/>
+ <xsl:value-of select="number($lastIndexedRow/@ss:Index) + count($lastIndexedRow/following-sibling::ss:Row)"/>
+ </xsl:when>
+ <xsl:when test="ss:Table/ss:Row/@ss:Index and ss:Table/ss:Row/@ss:Span">
+ <xsl:variable name="lastIndexedRow" select="ss:Table/ss:Row[@ss:Index][last()]"/>
+ <xsl:variable name="spannedRows">
+ <xsl:call-template name="count-spanned-rows">
+ <xsl:with-param name="rows" select="$lastIndexedRow/following-sibling::ss:Row[@ss:Span]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="number($lastIndexedRow/@ss:Index) + count($lastIndexedRow/following-sibling::ss:Row) + number($spannedRows)"/>
+ </xsl:when>
+ <xsl:when test="not(ss:Table/ss:Row/@ss:Index) and ss:Table/ss:Row/@ss:Span">
+ <xsl:variable name="spannedRows">
+ <xsl:call-template name="count-spanned-rows">
+ <xsl:with-param name="rows" select="ss:Table/ss:Rows[@ss:Span]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="count(ss:Table/ss:Row + number($spannedRows))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="count(ss:Table/ss:Row)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="count-spanned-rows">
+ <xsl:param name="expandedRowCount" select="0"/>
+ <xsl:param name="rows"/>
+ <xsl:param name="rowsCount" select="count($rows)"/>
+ <xsl:param name="rowIndex" select="1"/>
+ <xsl:choose>
+ <xsl:when test="$rowIndex &lt;= $rowsCount">
+ <xsl:call-template name="count-spanned-rows">
+ <xsl:with-param name="rows" select="$rows"/>
+ <xsl:with-param name="rowsCount" select="$rowsCount"/>
+ <xsl:with-param name="rowIndex" select="$rowIndex + 1"/>
+ <xsl:with-param name="expandedRowCount" select="$expandedRowCount + $rows[$rowIndex]/@ss:Span"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$expandedRowCount"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-default-cell-style">
+ <xsl:param name="currentColumnNode"/>
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode">
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode/@ss:StyleID">
+ <xsl:value-of select="$currentColumnNode/@ss:StyleID"/>
+ </xsl:when>
+ <xsl:otherwise>Default</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./ss:Table[@ss:StyleID]">
+ <xsl:value-of select="./ss:Table/@ss:StyleID"/>
+ </xsl:when>
+ <xsl:otherwise>Default</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-row-beyond-last">
+ <!-- dealing the RowBreak after last row by recursion -->
+ <xsl:param name="index-value"/>
+ <xsl:param name="worksheetNo"/>
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="end-pos"/>
+ <xsl:param name="total-col"/>
+ <xsl:variable name="current" select="concat('R',$index-value)"/>
+ <xsl:element name="table:table-row">
+ <xsl:choose>
+ <xsl:when test="./x:PageBreaks/x:RowBreaks/x:RowBreak/x:Row = ($index-value - 1)">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('rob',$worksheetNo)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('ro',$worksheetNo)"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <!-- Note: 2 be refactored
+ <xsl:when test="./ss:Table/ss:Column[@ss:StyleID] or ./ss:Table[@ss:StyleID]">
+ <xsl:if test="256 - count(ss:Table/ss:Column) &gt; 0">
+ <table:table-cell table:number-columns-repeated="{256 - count(ss:Table/ss:Column)}" />
+ </xsl:if>
+ </xsl:when>-->
+ <xsl:when test="contains($condition-pos-str,$current)">
+ <xsl:call-template name="create-spanning-cells">
+ <xsl:with-param name="row-pos" select="$index-value"/>
+ <xsl:with-param name="c-start" select="1"/>
+ <xsl:with-param name="c-end" select="$total-col"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- OASIS XML does not allow rows without a cell -->
+ <table:table-cell/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="$index-value &lt; ($end-pos + 1)">
+ <xsl:call-template name="get-row-beyond-last">
+ <xsl:with-param name="index-value" select="$index-value + 1"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="end-pos" select="$end-pos"/>
+ <xsl:with-param name="total-col" select="$total-col"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="break-row-beyond-max">
+ <!-- returns the max position of the row from condition-pos-str -->
+ <xsl:param name="pos"/>
+ <xsl:param name="last-value"/>
+ <xsl:param name="count-value"/>
+ <xsl:variable name="pre-value" select="./x:PageBreaks/x:RowBreaks/x:RowBreak[position() = $pos]/x:Row"/>
+ <xsl:variable name="end-value">
+ <xsl:choose>
+ <xsl:when test="$last-value &lt; $pre-value">
+ <xsl:value-of select="$pre-value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$last-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$pos &lt; $count-value">
+ <xsl:call-template name="break-row-beyond-max">
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ <xsl:with-param name="last-value" select="$end-value"/>
+ <xsl:with-param name="count-value" select="$count-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$end-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-column-beyond-last">
+ <!-- dealing the ColBreak after last column by recursion -->
+ <xsl:param name="index-value"/>
+ <xsl:param name="worksheetNo"/>
+ <xsl:for-each select="./x:PageBreaks/x:ColBreaks/x:ColBreak">
+ <xsl:variable name="each-column-value" select="./x:Column"/>
+ <xsl:choose>
+ <xsl:when test="$each-column-value + 1 &gt; $index-value">
+ <xsl:variable name="number-repeated">
+ <xsl:choose>
+ <xsl:when test="preceding-sibling::x:ColBreak[position()=count(.)]/x:Column + 1 = $index-value">
+ <xsl:value-of select="$each-column-value - preceding-sibling::x:ColBreak[position()=count(.)]/x:Column - 1"/>
+ </xsl:when>
+ <xsl:when test="preceding-sibling::x:ColBreak[position()=count(.)]/x:Column + 1 &gt; $index-value">
+ <xsl:value-of select="$each-column-value - preceding-sibling::x:ColBreak[position()=count(.)]/x:Column - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$each-column-value - $index-value + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$number-repeated &gt; 0">
+ <xsl:element name="table:table-column">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="'co1'"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="$number-repeated"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="table:table-column">
+ <xsl:if test="./../../../ss:Table[@ss:StyleID]">
+ <xsl:attribute name="table:default-cell-style-name">
+ <xsl:value-of select="./ss:Table/@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('cob',$worksheetNo)"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="$each-column-value + 1 = $index-value">
+ <xsl:element name="table:table-column">
+ <xsl:if test="./../../../ss:Table[@ss:StyleID]">
+ <xsl:attribute name="table:default-cell-style-name">
+ <xsl:value-of select="./../../../ss:Table/@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="concat('cob',$worksheetNo)"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="create-spanning-cells">
+ <!-- judge the position of the Cell in the condition-pos-str -->
+ <xsl:param name="row-pos"/>
+ <xsl:param name="c-start"/>
+ <xsl:param name="c-end"/>
+ <xsl:param name="condition-pos-str"/>
+
+ <xsl:variable name="current" select="concat('R',$row-pos,'C',$c-start,',')"/>
+ <xsl:variable name="style-name">
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str,$current)">
+ <xsl:variable name="temp-str">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-before($condition-pos-str,$current)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="starts-with($temp-str, 'c')">
+ <xsl:value-of select="concat('ce', substring-after($temp-str, 'c'))"/>
+ </xsl:when>
+ <xsl:when test="starts-with($temp-str, 'v')">
+ <xsl:value-of select="concat('val', substring-after($temp-str, 'v'))"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- as for the spanned cells no style is taken... -->
+ <xsl:choose>
+ <!-- inherit style from parent row style-->
+ <xsl:when test="../@ss:StyleID">
+ <xsl:value-of select="../@ss:StyleID"/>
+ </xsl:when>
+ <!-- if no correspondent column style exists... -->
+ <!-- inherit style from parent table style -->
+ <xsl:when test="../../@ss:StyleID">
+ <!-- function to give in col-pos and get back column style -->
+ <xsl:variable name="relatedColumnStyle">
+ <xsl:call-template name="get-related-column-style">
+ <!-- the given position of the cell in the table, a column style is searched -->
+ <xsl:with-param name="calculatedCellPosition" select="$c-start" />
+ <!-- all columns in XML -->
+ <xsl:with-param name="columnXMLNodes" select="../../ss:Column"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$relatedColumnStyle = ''">
+ <xsl:value-of select="../../@ss:StyleID"/>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="table:table-cell">
+ <xsl:if test="not($style-name = '')">
+ <xsl:choose>
+ <xsl:when test="starts-with($style-name, 'val')">
+ <xsl:attribute name="table:content-validation-name">
+ <xsl:value-of select="$style-name"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="starts-with($style-name, 'ce')">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="$style-name"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="$style-name"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$c-start &lt; $c-end">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="$c-end - $c-start + 1"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="condition-row-col-pos-max">
+ <!-- returns the max position of the column or row from condition-pos-str -->
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="last-value"/>
+ <xsl:param name="div-value"/>
+ <xsl:variable name="pre-value">
+ <xsl:choose>
+ <xsl:when test="$div-value = 'R'">
+ <xsl:value-of select="substring-before(substring-after($condition-pos-str,$div-value),'C')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(substring-after($condition-pos-str,$div-value),',')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="end-value">
+ <xsl:choose>
+ <xsl:when test="$last-value &lt; $pre-value">
+ <xsl:value-of select="$pre-value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$last-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str,$div-value)">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="substring-after($condition-pos-str,$div-value)"/>
+ <xsl:with-param name="last-value" select="$end-value"/>
+ <xsl:with-param name="div-value" select="$div-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$end-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="condition-str">
+ <!-- returns the string of style name of condition-pos-str -->
+ <xsl:param name="param-str"/>
+ <xsl:choose>
+ <xsl:when test="contains($param-str,'(')">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-after($param-str,'(')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($param-str,':')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:key name="Style" match="/ss:Workbook/ss:Styles/ss:Style" use="@ss:ID"/>
+ <xsl:template name="create-cells">
+ <xsl:param name="row-pos"/>
+ <xsl:param name="expandedColumnCount"/>
+ <xsl:param name="condition-pos-str"/>
+ <xsl:choose>
+ <xsl:when test="ss:Cell">
+ <xsl:apply-templates select="ss:Cell[1]" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$expandedColumnCount"/>
+ <!--
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str" />
+ <xsl:with-param name="last-value" select="0" />
+ <xsl:with-param name="div-value" select="'C'" />
+ </xsl:call-template>
+ </xsl:with-param> -->
+ <xsl:with-param name="col-pos-written" select="0"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="current" select="concat('R',$row-pos,'C')"/>
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str,$current)">
+ <xsl:call-template name="create-spanning-cells">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="c-start" select="1"/>
+ <xsl:with-param name="c-end">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'C'"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos" select="1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- OASIS XML does not allow an empty row -->
+ <xsl:choose>
+ <xsl:when test="$expandedColumnCount != 0">
+ <table:table-cell table:number-columns-repeated="{$expandedColumnCount}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- OASIS XML row can not be empty -->
+ <table:table-cell table:number-columns-repeated="256"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="ss:Cell" name="ss:Cell" mode="selected">
+ <!-- Contains the max position of the column or row from the concatenation from
+ x:ConditionalFormatting
+ and
+ x:DataValidation -->
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="col-pos-max"/>
+ <xsl:param name="col-pos-written" select="0"/>
+ <xsl:param name="col-pos-current" select="0"/>
+ <xsl:param name="row-pos"/>
+ <xsl:param name="col-repeated" select="1"/>
+
+ <!-- The column position of the cell (might jumped by ss:Index) -->
+ <xsl:variable name="col-pos">
+ <xsl:choose>
+ <xsl:when test="@ss:Index">
+ <xsl:choose>
+ <xsl:when test="@ss:MergeAcross">
+ <xsl:value-of select="@ss:MergeAcross + @ss:Index"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@ss:Index"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@ss:MergeAcross">
+ <xsl:value-of select="1 + @ss:MergeAcross + $col-pos-current"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="1 + $col-pos-current"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="nextCell" select="following-sibling::ss:Cell[1]"/>
+ <!-- Multiple empty cells with the same or no style will be moved to one cell with a 'table:number-columns-repeated' attribute -->
+ <xsl:variable name="cell-is-repeatable" select="
+ not(current()/*)
+ and
+ not(current()/text())
+ and
+ (
+ not($nextCell)
+ and $col-pos &gt; $col-pos-written + 1
+ or
+ (
+ $nextCell
+ and
+ not($nextCell/*)
+ and
+ not($nextCell/text())
+ and
+ (
+ (current()/@ss:StyleID = $nextCell/@ss:StyleID)
+ or
+ (not(current()/@ss:StyleID) and not($nextCell/@ss:StyleID))
+ )
+ and
+ (
+ not($nextCell/@ss:Index)
+ or
+ ($nextCell/@ss:Index = $col-pos + 1)
+ )
+ )
+ ) "/>
+ <xsl:choose>
+ <!-- Scenario: The missing cells skipped by using the ss:Index attribute will be added -->
+ <xsl:when test="@ss:Index and @ss:Index &gt; $col-pos-written + 1">
+ <!-- In Open Document nothing comparable to Index exists,
+ the missing cells might have to be created, if they had content as only style will be repeated-->
+ <xsl:call-template name="create-spanning-cells">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="c-start" select="$col-pos-current + 1"/>
+ <xsl:with-param name="c-end" select="@ss:Index - 1"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ <xsl:call-template name="ss:Cell">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-written" select="@ss:Index - 1"/>
+ <xsl:with-param name="col-pos-current" select="$col-pos"/>
+ <xsl:with-param name="col-repeated" select="$col-repeated"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- Scenario: A sequence of cells can be put together as one cell -->
+ <xsl:when test="$cell-is-repeatable">
+ <xsl:apply-templates select="$nextCell" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-written" select="$col-pos-written"/>
+ <xsl:with-param name="col-pos-current" select="$col-pos"/>
+ <xsl:with-param name="col-repeated" select="$col-repeated"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- if the cell wasn't repeated yet, created first -->
+ <xsl:if test="$col-repeated = 1">
+ <xsl:element name="table:table-cell">
+ <!-- in case the cell has an Index and is repeatable (s.above) and therefore has not been repeated earlier -->
+ <xsl:choose>
+ <xsl:when test="@ss:MergeAcross">
+ <xsl:if test="$col-pos - @ss:MergeAcross &gt; $col-pos-written + 1">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="$col-pos - $col-pos-written"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$col-pos &gt; $col-pos-written + 1">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="$col-pos - $col-pos-written"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="create-table-cell-attributes">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos" select="$col-pos"/>
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ </xsl:call-template>
+ <xsl:call-template name="create-table-cell-content">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos" select="$col-pos"/>
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ </xsl:call-template>
+ </xsl:element>
+ <!-- ss:MergeAcross (column spanned) indicates a covered table-cell in Open Document XML-->
+ <xsl:if test="@ss:MergeAcross">
+ <xsl:element name="table:covered-table-cell">
+ <xsl:if test="@ss:MergeAcross &gt; 1">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="@ss:MergeAcross"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ <xsl:choose>
+ <!-- the following block is not used, if the cell had been repeated earlier -->
+ <xsl:when test="$nextCell and not($cell-is-repeatable and $col-repeated = 1)">
+ <xsl:choose>
+ <!-- After cells can no longer be repeated write out the attribute -->
+ <xsl:when test="not($cell-is-repeatable) and $col-repeated > 1">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="$col-repeated"/>
+ </xsl:attribute>
+ </xsl:when>
+ <!-- At the end of the row -->
+ <xsl:when test="not($nextCell)">
+ <xsl:if test="../../../x:ConditionalFormatting">
+ <!-- at the last position of the Cell tag,inspecting the following cell before condition-row-col-pos-max -->
+ <xsl:call-template name="create-spanning-cells">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="c-start" select="$col-pos"/>
+ <xsl:with-param name="c-end" select="$col-pos-max"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <!-- If the cells can not be repeated (default) -->
+ <xsl:when test="not($cell-is-repeatable)">
+ <!-- Traverse the following Cell -->
+ <xsl:apply-templates select="$nextCell" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-written" select="$col-pos"/>
+ <xsl:with-param name="col-pos-current" select="$col-pos"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <!-- Go on with started repetition -->
+ <xsl:otherwise>
+ <xsl:apply-templates select="$nextCell" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-written" select="$col-pos"/>
+ <xsl:with-param name="col-pos-current" select="$col-pos"/>
+ <xsl:with-param name="col-repeated" select="$col-repeated + 1"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="not($nextCell)">
+ <xsl:choose>
+ <xsl:when test="$col-repeated = 1 and ($col-pos &lt; $col-pos-max)">
+ <table:table-cell table:number-columns-repeated="{$col-pos-max - $col-pos}"/>
+ </xsl:when>
+ <xsl:when test="$col-repeated &gt; 1">
+ <xsl:attribute name="table:number-columns-repeated">
+ <xsl:value-of select="$col-repeated"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$nextCell" mode="skip">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-written" select="$col-pos"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="ss:Cell" mode="skip">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="col-pos-max"/>
+ <xsl:param name="col-pos-written"/>
+ <xsl:param name="row-pos"/>
+
+ <xsl:variable name="nextCell" select="following-sibling::ss:Cell[1]"/>
+ <!-- Multiple empty cells with the same style will be moved to one cell with a 'table:number-columns-repeated' attribute -->
+ <xsl:variable name="cell-is-repeatable" select="not($nextCell/*) and not($nextCell/text()) and ((current()/@ss:StyleID = $nextCell/@ss:StyleID) or (not(current()/@ss:StyleID) and not($nextCell/@ss:StyleID))) and not($nextCell/@ss:Index)"/>
+ <xsl:choose>
+ <xsl:when test="$cell-is-repeatable">
+ <xsl:apply-templates select="$nextCell" mode="skip">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-written" select="$col-pos-written + 1"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$nextCell" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-written" select="$col-pos-written + 1"/>
+ <xsl:with-param name="col-pos-current" select="$col-pos-written + 1"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-table-cell-attributes">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="col-pos-max"/>
+ <xsl:param name="col-pos"/>
+ <xsl:param name="row-pos"/>
+
+ <xsl:choose>
+ <xsl:when test="$condition-pos-str">
+ <xsl:call-template name="get-condition-dependent-cell-attributes">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="current-pos-str" select="concat('R',$row-pos,'C',$col-pos,',')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@ss:StyleID">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:when>
+ <!-- inherit style from parent row style-->
+ <xsl:when test="../@ss:StyleID">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="../@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:when>
+ <!-- if no correspondent column style exists... -->
+ <!-- inherit style from parent table style -->
+ <xsl:when test="../../@ss:StyleID">
+ <!-- function to give in col-pos and get back column style -->
+ <xsl:variable name="relatedColumnStyle">
+ <xsl:call-template name="get-related-column-style">
+ <!-- the given position of the cell in the table, a column style is searched -->
+ <xsl:with-param name="calculatedCellPosition" select="$col-pos" />
+ <!-- all columns in XML -->
+ <xsl:with-param name="columnXMLNodes" select="../../ss:Column"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$relatedColumnStyle = ''">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="../../@ss:StyleID"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@ss:MergeAcross or @ss:MergeDown">
+ <xsl:choose>
+ <xsl:when test="@ss:MergeAcross">
+ <xsl:attribute name="table:number-columns-spanned">
+ <xsl:value-of select="@ss:MergeAcross + 1"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:number-columns-spanned">1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@ss:MergeDown">
+ <xsl:attribute name="table:number-rows-spanned">
+ <xsl:value-of select="@ss:MergeDown+1"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:number-rows-spanned">1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@ss:Formula">
+ <!-- formula translation from Excel to Calc -->
+ <xsl:variable name="calc-formula">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$col-pos"/>
+ <xsl:with-param name="expression" select="@ss:Formula"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="table:formula">
+ <xsl:value-of select="$calc-formula"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ss:Data">
+ <xsl:variable name="data-format">
+ <xsl:value-of select="key('Style', @ss:StyleID)/ss:NumberFormat/@ss:Format"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="ss:Data/@ss:Type = 'Number'">
+ <xsl:choose>
+ <xsl:when test="$data-format = 'Percent' or contains( $data-format, '%')">
+ <xsl:attribute name="office:value-type">percentage</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(key('Style', @ss:StyleID)/ss:NumberFormat/@ss:Format, 'Currency')">
+ <xsl:attribute name="office:value-type">currency</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="office:value-type">float</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="office:value">
+ <xsl:value-of select="ss:Data"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ss:Data/@ss:Type = 'DateTime'">
+ <xsl:choose>
+ <xsl:when test="(contains( $data-format, 'Date') or contains($data-format,'y') or contains($data-format,'g') or contains($data-format,'d') or contains($data-format,'e') or starts-with( substring( ss:Data, 11), 'T00:00:00.000' ) ) and (not (contains( $data-format, 'Time') ) )">
+ <xsl:attribute name="office:value-type">date</xsl:attribute>
+ <xsl:attribute name="office:date-value">
+ <xsl:value-of select="substring-before(ss:Data, 'T')"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="office:value-type">time</xsl:attribute>
+ <xsl:attribute name="office:time-value">
+ <xsl:value-of select="concat('P',substring(ss:Data, 11, 3), 'H', substring(ss:Data, 15, 2), 'M', substring(ss:Data, 18,2), 'S')"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="ss:Data/@ss:Type = 'Boolean'">
+ <xsl:attribute name="office:value-type">boolean</xsl:attribute>
+ <xsl:attribute name="office:boolean-value">
+ <xsl:choose>
+ <xsl:when test="ss:Data = '1'">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ss:Data/@ss:Type = 'String'">
+ <xsl:attribute name="office:value-type">string</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="get-related-column-style">
+ <!-- the given position of the cell in the table, a column style is searched -->
+ <xsl:param name="calculatedCellPosition" />
+ <!-- the current position of the column as XML node -->
+ <xsl:param name="columnXMLPosition" select="1" />
+ <!-- all columns in XML -->
+ <xsl:param name="columnXMLNodes" />
+ <!-- the ending column position of the earlier column style in the table -->
+ <xsl:param name="earlierCalculatedColumnEnd" select="0" />
+
+ <!-- the current column as XML node -->
+ <xsl:variable name="columnXMLNode" select="$columnXMLNodes[1]" />
+ <xsl:if test="$columnXMLNodes and count($columnXMLNodes) > 0">
+ <!-- the starting column position of the style in the table -->
+ <xsl:variable name="calculatedColumnStart">
+ <!-- if ss:Index exists, this is the start of the column -->
+ <xsl:choose>
+ <xsl:when test="$columnXMLNode/@ss:Index">
+ <xsl:value-of select="$columnXMLNode/@ss:Index" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$earlierCalculatedColumnEnd + 1" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- the ending column position of the style in the table -->
+ <xsl:variable name="calculatedColumnEnd">
+ <xsl:choose>
+ <xsl:when test="$columnXMLNode/@ss:Span">
+ <xsl:value-of select="$calculatedColumnStart + $columnXMLNode/@ss:Span" />
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$calculatedColumnStart" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$calculatedColumnStart &gt;= $calculatedCellPosition and $calculatedCellPosition &lt;= $calculatedColumnEnd">
+ <xsl:value-of select="$columnXMLNode/@ss:StyleID"/>
+ </xsl:when>
+ <xsl:when test="$calculatedColumnEnd &lt;= $calculatedCellPosition">
+ <xsl:call-template name="get-related-column-style">
+ <!-- the given position of the cell in the table, a column style is searched -->
+ <xsl:with-param name="calculatedCellPosition" select="$calculatedCellPosition" />
+ <!-- all columns in XML -->
+ <xsl:with-param name="columnXMLNodes" select="$columnXMLNodes[position() != 1]"/>
+ <!-- the ending column position of the style in the table -->
+ <xsl:with-param name="earlierCalculatedColumnEnd" select="$calculatedColumnEnd" />
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="create-table-cell-content">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="col-pos-max"/>
+ <xsl:param name="col-pos"/>
+ <xsl:param name="row-pos"/>
+ <xsl:apply-templates select="ss:Comment" mode="body"/>
+ <xsl:if test="ss:Data">
+ <text:p>
+ <xsl:call-template name="create-data-content">
+ <xsl:with-param name="style-id" select="@ss:StyleID"/>
+ </xsl:call-template>
+ </text:p>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-data-content">
+ <xsl:param name="style-id" select="@ss:StyleID"/>
+ <xsl:choose>
+ <xsl:when test="ss:Data//text()[string-length(.) != 0] and ss:Data[count(*)>0]">
+ <xsl:for-each select="ss:Data//text()[string-length(.) != 0]">
+ <xsl:sort select="position( )" order="ascending" data-type="number"/>
+ <text:span text:style-name="{concat($style-id, 'T', count(preceding::ss:Data[child::html:*]), '_', position())}">
+ <xsl:value-of select="."/>
+ </text:span>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="contains(key('Style', $style-id)/ss:Font/@ss:VerticalAlign, 'script')">
+ <text:span text:style-name="{concat($style-id, 'T0')}">
+ <xsl:choose>
+ <xsl:when test="@ss:HRef">
+ <text:a xlink:href="{@ss:HRef}">
+ <xsl:value-of select="ss:Data"/>
+ </text:a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="ss:Data"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </text:span>
+ </xsl:when>
+ <xsl:when test="@ss:HRef">
+ <text:a xlink:href="{@ss:HRef}">
+ <xsl:value-of select="ss:Data"/>
+ </text:a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="ss:Data"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-condition-dependent-cell-attributes">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="current-pos-str"/>
+ <xsl:variable name="temp-str">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-before($condition-pos-str,$current-pos-str)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="base-style-name">
+ <xsl:choose>
+ <xsl:when test="@ss:StyleID">
+ <xsl:value-of select="@ss:StyleID"/>
+ </xsl:when>
+ <xsl:when test="../@ss:StyleID">
+ <xsl:value-of select="../@ss:StyleID"/>
+ </xsl:when>
+ <xsl:when test="../../@ss:StyleID">
+ <xsl:value-of select="../../@ss:StyleID"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="style-name">
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str, $current-pos-str) and starts-with($temp-str, 'c')">
+ <xsl:choose>
+ <xsl:when test="string-length($base-style-name) &gt; 0"><xsl:value-of select="concat($base-style-name, '-ce', substring-after($temp-str, 'c'))"/></xsl:when>
+ <xsl:otherwise><xsl:value-of select="concat('Default-ce', substring-after($temp-str, 'c'))"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$base-style-name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="starts-with($style-name, 'val')">
+ <xsl:attribute name="table:content-validation-name">
+ <xsl:value-of select="$style-name"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="not($style-name = '')">
+ <xsl:attribute name="table:style-name">
+ <xsl:value-of select="$style-name"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <!-- maybe multi functions occur at the same time in the same Cell, such as ConditionalFormatting and DataValidation -->
+ <xsl:if test="contains($condition-pos-str, $current-pos-str)">
+ <xsl:choose>
+ <xsl:when test="starts-with($temp-str, 'v')">
+ <xsl:attribute name="table:content-validation-name">
+ <xsl:value-of select="concat('val', substring-after($temp-str, 'v'))"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="after-str" select="substring-after($condition-pos-str, $current-pos-str)"/>
+ <xsl:if test="contains( $after-str, $current-pos-str)">
+ <xsl:variable name="temp-str-2">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-before( $after-str,$current-pos-str)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="starts-with( $temp-str-2, 'v')">
+ <xsl:attribute name="table:content-validation-name">
+ <xsl:value-of select="concat('val', substring-after($temp-str-2, 'v'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="validation-row-column-string">
+ <!-- returns a string with structure, including row/column position by extraction from x:DataValidation -->
+ <xsl:param name="last"/>
+ <xsl:param name="total"/>
+ <xsl:param name="index"/>
+ <xsl:variable name="table-pos" select="count(preceding-sibling::ss:Worksheet)+1"/>
+ <xsl:variable name="current">
+ <xsl:call-template name="parse-range">
+ <xsl:with-param name="range-value" select="./x:DataValidation[position() = $index]/x:Range"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="current-value" select="concat('(v',$index,':', $current,');')"/>
+ <xsl:if test="$index &lt; $total">
+ <xsl:call-template name="validation-row-column-string">
+ <xsl:with-param name="last" select="concat($last, $current-value)"/>
+ <xsl:with-param name="total" select="$total"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$index = $total">
+ <xsl:value-of select="concat($last, $current-value)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="condition-row-column-string">
+ <!-- returns a string with structure, including row/column position by extraction from x:ConditionalFormatting -->
+ <xsl:param name="last"/>
+ <xsl:param name="total"/>
+ <xsl:param name="index"/>
+ <xsl:variable name="table-pos" select="count(preceding-sibling::ss:Worksheet)+1"/>
+ <xsl:variable name="current">
+ <xsl:call-template name="parse-range">
+ <xsl:with-param name="range-value" select="./x:ConditionalFormatting[position() = $index]/x:Range"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="current-value" select="concat('(c',$table-pos,'-',$index,':', $current,');')"/>
+ <xsl:if test="$index &lt; $total">
+ <xsl:call-template name="condition-row-column-string">
+ <xsl:with-param name="last" select="concat($last, $current-value)"/>
+ <xsl:with-param name="total" select="$total"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$index = $total">
+ <xsl:value-of select="concat($last, $current-value)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="parse-range">
+ <!-- returns a string,input param:the value of x:Range -->
+ <xsl:param name="range-value"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="first-pit">
+ <xsl:choose>
+ <xsl:when test="contains($range-value,',')">
+ <xsl:value-of select="substring-before($range-value,',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$range-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="current">
+ <xsl:choose>
+ <xsl:when test="contains($first-pit,':')">
+ <xsl:variable name="R-start" select="substring-before(substring-after($first-pit,'R'),'C')"/>
+ <xsl:variable name="C-start" select="substring-before(substring-after($first-pit,'C'),':')"/>
+ <xsl:variable name="second-pit" select="substring-after($first-pit,':')"/>
+ <xsl:variable name="R-end" select="substring-before(substring-after($second-pit,'R'),'C')"/>
+ <xsl:variable name="C-end" select="substring-after($second-pit,'C')"/>
+ <xsl:variable name="the-str">
+ <xsl:call-template name="condition-rc-str">
+ <xsl:with-param name="r-start" select="$R-start"/>
+ <xsl:with-param name="r-end" select="$R-end"/>
+ <xsl:with-param name="c-start" select="$C-start"/>
+ <xsl:with-param name="c-end" select="$C-end"/>
+ <xsl:with-param name="last" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$the-str"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($first-pit,',')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($range-value,',')">
+ <xsl:call-template name="parse-range">
+ <xsl:with-param name="range-value" select="substring-after($range-value,',')"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="condition-rc-str">
+ <!-- dealing the range of row\column -->
+ <xsl:param name="r-start"/>
+ <xsl:param name="r-end"/>
+ <xsl:param name="c-start"/>
+ <xsl:param name="c-end"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="current">
+ <xsl:call-template name="condition-c-str">
+ <xsl:with-param name="rc-str" select="concat('R',$r-start)"/>
+ <xsl:with-param name="start" select="$c-start"/>
+ <xsl:with-param name="end" select="$c-end"/>
+ <xsl:with-param name="last" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$r-start &lt; $r-end">
+ <xsl:call-template name="condition-rc-str">
+ <xsl:with-param name="r-start" select="$r-start + 1"/>
+ <xsl:with-param name="r-end" select="$r-end"/>
+ <xsl:with-param name="c-start" select="$c-start"/>
+ <xsl:with-param name="c-end" select="$c-end"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$r-start = $r-end">
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="condition-c-str">
+ <!-- return value for the template condition-rc-str -->
+ <xsl:param name="rc-str"/>
+ <xsl:param name="start"/>
+ <xsl:param name="end"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="current" select="concat($rc-str,'C',$start,',')"/>
+ <xsl:if test="$start &lt; $end">
+ <xsl:call-template name="condition-c-str">
+ <xsl:with-param name="rc-str" select="$rc-str"/>
+ <xsl:with-param name="start" select="$start + 1"/>
+ <xsl:with-param name="end" select="$end"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$start = $end">
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="ss:Data[count(*)>0]">
+ <xsl:for-each select=".//text()[string-length(.) != 0]">
+ <style:style style:name="{concat(ancestor::ss:Cell/@ss:StyleID,'T',count(preceding::ss:Data[child::html:*]), '_', position())}" style:family="text">
+ <xsl:element name="style:text-properties">
+ <xsl:if test="ancestor-or-self::html:Font/@html:Face">
+ <xsl:attribute name="style:font-name">
+ <xsl:value-of select="ancestor-or-self::html:Font/@html:Face"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::html:Font/@html:Size">
+ <xsl:attribute name="fo:font-size">
+ <xsl:value-of select="concat(ancestor-or-self::html:Font/@html:Size,'pt')"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-size-asian">
+ <xsl:value-of select="concat(ancestor-or-self::html:Font/@html:Size,'pt')"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-size-complex">
+ <xsl:value-of select="concat(ancestor-or-self::html:Font/@html:Size,'pt')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::html:Font/@html:Color">
+ <xsl:attribute name="fo:color">
+ <xsl:value-of select="ancestor-or-self::html:Font/@html:Color"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::html:B">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-complex">bold</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::html:I">
+ <xsl:attribute name="fo:font-style">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-complex">italic</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::html:U">
+ <xsl:attribute name="style:text-underline-type">single</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::html:S">
+ <xsl:attribute name="style:text-line-through-style">solid</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::html:Sup">
+ <xsl:attribute name="style:text-position">33% 58%</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="ancestor-or-self::html:Sub">
+ <xsl:attribute name="style:text-position">-33% 58%</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </style:style>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="get-pos-content">
+ <xsl:param name="content"/>
+ <xsl:param name="pos"/>
+ <xsl:choose>
+ <xsl:when test="$pos = 'left'">
+ <xsl:choose>
+ <xsl:when test="contains($content,'&amp;C')">
+ <xsl:value-of select="substring-before( substring-after( $content, '&amp;L'), '&amp;C')"/>
+ </xsl:when>
+ <xsl:when test="contains($content,'&amp;R')">
+ <xsl:value-of select="substring-before( substring-after( $content, '&amp;L'), '&amp;R')"/>
+ </xsl:when>
+ <xsl:when test="contains($content,'&amp;L')">
+ <xsl:value-of select="substring-after( $content, '&amp;L')"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$pos = 'center'">
+ <xsl:choose>
+ <xsl:when test="contains($content,'&amp;R')">
+ <xsl:value-of select="substring-before( substring-after( $content, '&amp;C'), '&amp;R')"/>
+ </xsl:when>
+ <xsl:when test="contains($content,'&amp;C')">
+ <xsl:value-of select="substring-after( $content, '&amp;C')"/>
+ </xsl:when>
+ <xsl:when test="contains($content,'&amp;L')"/>
+ <xsl:otherwise>
+ <xsl:value-of select="$content"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$pos = 'right'">
+ <xsl:value-of select="substring-after( $content, '&amp;R')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="@x:Data">
+ <xsl:variable name="style-name-header">
+ <xsl:value-of select="concat(ancestor::ss:Worksheet/@ss:Name, substring(name(..),1,1))"/>
+ </xsl:variable>
+ <xsl:variable name="left-style-data">
+ <xsl:call-template name="get-pos-content">
+ <xsl:with-param name="content" select="."/>
+ <xsl:with-param name="pos" select="'left'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="string-length($left-style-data)&gt;0 and contains($left-style-data,'&amp;')">
+ <xsl:call-template name="create-header-footer-style">
+ <xsl:with-param name="style-name-header" select="concat($style-name-header,'L')"/>
+ <xsl:with-param name="style-data" select="$left-style-data"/>
+ <xsl:with-param name="index" select="0"/>
+ <xsl:with-param name="current-pos" select="1"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:variable name="center-style-data">
+ <xsl:call-template name="get-pos-content">
+ <xsl:with-param name="content" select="."/>
+ <xsl:with-param name="pos" select="'center'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="string-length($center-style-data)&gt;0 and contains($center-style-data,'&amp;')">
+ <xsl:call-template name="create-header-footer-style">
+ <xsl:with-param name="style-name-header" select="concat($style-name-header,'C')"/>
+ <xsl:with-param name="style-data" select="$center-style-data"/>
+ <xsl:with-param name="index" select="0"/>
+ <xsl:with-param name="current-pos" select="1"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:variable name="right-style-data">
+ <xsl:call-template name="get-pos-content">
+ <xsl:with-param name="content" select="."/>
+ <xsl:with-param name="pos" select="'right'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="string-length($right-style-data)&gt;0 and contains($right-style-data,'&amp;')">
+ <xsl:call-template name="create-header-footer-style">
+ <xsl:with-param name="style-name-header" select="concat($style-name-header,'R')"/>
+ <xsl:with-param name="style-data" select="$right-style-data"/>
+ <xsl:with-param name="index" select="0"/>
+ <xsl:with-param name="current-pos" select="1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-header-footer-style">
+ <xsl:param name="style-name-header"/>
+ <xsl:param name="style-data"/>
+ <xsl:param name="index"/>
+ <xsl:param name="current-pos"/>
+ <xsl:variable name="current-style-data">
+ <xsl:value-of select="substring($style-data,$current-pos)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="starts-with($current-style-data,'&amp;D') or starts-with($current-style-data,'&amp;T') or starts-with($current-style-data,'&amp;P') or starts-with($current-style-data,'&amp;N') or starts-with($current-style-data,'&amp;A') or starts-with($current-style-data,'&amp;F') or starts-with($current-style-data,'&amp;Z')">
+ <xsl:call-template name="create-header-footer-style">
+ <xsl:with-param name="style-name-header" select="$style-name-header"/>
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="current-pos" select="$current-pos +2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;')">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">
+ <xsl:value-of select="concat($style-name-header,$index)"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ <xsl:element name="style:text-properties">
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ <xsl:variable name="next-style-header-pos">
+ <xsl:call-template name="get-current-content-pos">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="create-header-footer-style">
+ <xsl:with-param name="style-name-header" select="$style-name-header"/>
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="index" select="$index+1"/>
+ <xsl:with-param name="current-pos" select="$next-style-header-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains($current-style-data,'&amp;')">
+ <xsl:variable name="temp" select="substring-before($current-style-data,'&amp;')"/>
+ <xsl:call-template name="create-header-footer-style">
+ <xsl:with-param name="style-name-header" select="$style-name-header"/>
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="index" select="$index"/>
+ <xsl:with-param name="current-pos" select="string-length($temp)+$current-pos"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="process-header-footer-style-properties">
+ <xsl:param name="style-data"/>
+ <xsl:param name="current-pos"/>
+ <xsl:variable name="current-style-data">
+ <xsl:value-of select="substring($style-data,$current-pos)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <!-- stack operations necessary -->
+ <xsl:when test="starts-with($current-style-data,'&amp;&quot;')">
+ <xsl:attribute name="style:font-name">
+ <xsl:value-of select="substring-before(substring-after($current-style-data,'&amp;&quot;'),',')"/>
+ </xsl:attribute>
+ <xsl:if test="contains(substring-before(substring-after($current-style-data,','),'&quot;'),'Bold')">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-complex">bold</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains(substring-before(substring-after($current-style-data,','),'&quot;'),'Italic')">
+ <xsl:attribute name="fo:font-style">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-complex">italic</xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="temp" select="substring-before(substring($style-data,$current-pos+2),'&quot;')"/>
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="string-length($temp)+$current-pos+3"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;0') or starts-with($current-style-data,'&amp;1') or starts-with($current-style-data,'&amp;2') or starts-with($current-style-data,'&amp;3') or starts-with($current-style-data,'&amp;4') or starts-with($current-style-data,'&amp;5') or starts-with($current-style-data,'&amp;6') or starts-with($current-style-data,'&amp;7') or starts-with($current-style-data,'&amp;8') or starts-with($current-style-data,'&amp;9')">
+ <xsl:variable name="font-size-length">
+ <xsl:call-template name="get-digit-length">
+ <xsl:with-param name="complexive-string" select="substring-after($current-style-data,'&amp;')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:font-size">
+ <xsl:value-of select="concat(substring($current-style-data,2,$font-size-length),'pt')"/>
+ </xsl:attribute>
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos + 1 + $font-size-length"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- don't consider tangled or adjoined '&X' and '&Y', '&U' & '&E', processing-check is necessary, too complex. :( -->
+ <xsl:when test="starts-with($current-style-data,'&amp;X')">
+ <xsl:variable name="superscript-count-before">
+ <xsl:call-template name="get-substyle-count-in-data">
+ <xsl:with-param name="style-data" select="substring($style-data,1,$current-pos)"/>
+ <xsl:with-param name="substyle" select="'&amp;X'"/>
+ <xsl:with-param name="count" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$superscript-count-before mod 2 = 0">
+ <xsl:attribute name="style:text-position">33% 58%</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos + 2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;B')">
+ <xsl:variable name="subscript-count-before">
+ <xsl:call-template name="get-substyle-count-in-data">
+ <xsl:with-param name="style-data" select="substring($style-data,1,$current-pos)"/>
+ <xsl:with-param name="substyle" select="'&amp;B'"/>
+ <xsl:with-param name="count" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$subscript-count-before mod 2 = 0">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-complex">bold</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos + 2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;Y')">
+ <xsl:variable name="subscript-count-before">
+ <xsl:call-template name="get-substyle-count-in-data">
+ <xsl:with-param name="style-data" select="substring($style-data,1,$current-pos)"/>
+ <xsl:with-param name="substyle" select="'&amp;Y'"/>
+ <xsl:with-param name="count" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$subscript-count-before mod 2 = 0">
+ <xsl:attribute name="style:text-position">-33% 58%</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos + 2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;S')">
+ <xsl:variable name="strikethrough-count-before">
+ <xsl:call-template name="get-substyle-count-in-data">
+ <xsl:with-param name="style-data" select="substring($style-data,1,$current-pos)"/>
+ <xsl:with-param name="substyle" select="'&amp;S'"/>
+ <xsl:with-param name="count" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$strikethrough-count-before mod 2 = 0">
+ <xsl:attribute name="style:text-line-through-style">solid</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos + 2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;U')">
+ <xsl:variable name="single-underline-count-before">
+ <xsl:call-template name="get-substyle-count-in-data">
+ <xsl:with-param name="style-data" select="substring($style-data,1,$current-pos)"/>
+ <xsl:with-param name="substyle" select="'&amp;U'"/>
+ <xsl:with-param name="count" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$single-underline-count-before mod 2 = 0">
+ <xsl:attribute name="style:text-underline-type">single</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos + 2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;E')">
+ <xsl:variable name="double-underline-count-before">
+ <xsl:call-template name="get-substyle-count-in-data">
+ <xsl:with-param name="style-data" select="substring($style-data,1,$current-pos)"/>
+ <xsl:with-param name="substyle" select="'&amp;E'"/>
+ <xsl:with-param name="count" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$double-underline-count-before mod 2 = 0">
+ <xsl:attribute name="style:text-underline-type">double</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-header-footer-style-properties">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos + 2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-substyle-count-in-data">
+ <xsl:param name="style-data"/>
+ <xsl:param name="substyle"/>
+ <xsl:param name="count"/>
+ <xsl:choose>
+ <xsl:when test="contains($style-data,$substyle)">
+ <xsl:call-template name="get-substyle-count-in-data">
+ <xsl:with-param name="style-data" select="substring-after($style-data,$substyle)"/>
+ <xsl:with-param name="substyle" select="$substyle"/>
+ <xsl:with-param name="count" select="$count+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$count"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-current-content-pos">
+ <xsl:param name="style-data"/>
+ <xsl:param name="current-pos"/>
+ <xsl:variable name="current-style-data">
+ <xsl:value-of select="substring($style-data,$current-pos)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="starts-with($current-style-data,'&amp;X') or starts-with($current-style-data,'&amp;Y') or starts-with($current-style-data,'&amp;S') or starts-with($current-style-data,'&amp;U') or starts-with($current-style-data,'&amp;E') or starts-with($current-style-data,'&amp;B')">
+ <xsl:call-template name="get-current-content-pos">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos+2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;0') or starts-with($current-style-data,'&amp;1') or starts-with($current-style-data,'&amp;2') or starts-with($current-style-data,'&amp;3') or starts-with($current-style-data,'&amp;4') or starts-with($current-style-data,'&amp;5') or starts-with($current-style-data,'&amp;6') or starts-with($current-style-data,'&amp;7') or starts-with($current-style-data,'&amp;8') or starts-with($current-style-data,'&amp;9')">
+ <xsl:variable name="font-size-length">
+ <xsl:call-template name="get-digit-length">
+ <xsl:with-param name="complexive-string" select="substring-after($current-style-data,'&amp;')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="get-current-content-pos">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="$current-pos+1+$font-size-length"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data,'&amp;&quot;')">
+ <xsl:variable name="temp" select="substring-before(substring($style-data,$current-pos+2),'&quot;')"/>
+ <xsl:call-template name="get-current-content-pos">
+ <xsl:with-param name="style-data" select="$style-data"/>
+ <xsl:with-param name="current-pos" select="string-length($temp)+$current-pos+3"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="starts-with($current-style-data, '&amp;')">
+ <xsl:value-of select="$current-pos + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$current-pos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- OASIS OpenDocument Format change:
+ Excel "=RC4*6"
+ OOoXML "=$D22*6"
+ OASIS XML "oooc:=[.$D22]*6" -->
+ <xsl:template name="translate-expression">
+ <!-- return position or range for formula or other -->
+ <xsl:param name="cell-row-pos"/>
+ <!-- the position in row (vertical) of cell -->
+ <xsl:param name="cell-column-pos"/>
+ <!-- the position in column (horizontal of cell -->
+ <xsl:param name="expression"/>
+ <!-- recomposed expression containing cell positions after every conversion -->
+ <xsl:param name="is-range-mode" select="false()"/>
+ <!-- as mode changes a '[.' resp. ']' is written out -->
+ <xsl:param name="return-value"/>
+ <!-- expression of table:cell-range-address is different than formula (e.g. no prefix) -->
+ <xsl:param name="isRangeAddress"/>
+ <!-- determines if the currently processed expression is relative -->
+ <xsl:param name="isRelative" select="false()" />
+
+ <!-- value to be given out later -->
+ <!-- to judge whether this input expression contains any cell position to convert -->
+ <xsl:variable name="temp-range">
+ <xsl:choose>
+ <xsl:when test="$expression != ''">
+ <xsl:call-template name="parse-range-name">
+ <xsl:with-param name="expression" select="$expression"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- if $range-type = 1, then range is representing a sheet, function's name or separated symbol, but not cell position,
+ or if $range-type = 2, range should be handled because it contains certain cell position.
+ The first character marks the type of that expression. -->
+ <xsl:variable name="range-type">
+ <xsl:choose>
+ <xsl:when test="substring($temp-range, 1, 1) = '1'">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:when test="substring($temp-range, 1, 1) = '2'">
+ <xsl:value-of select="2"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- remove that added range type token -->
+ <xsl:variable name="current-range">
+ <xsl:value-of select="substring($temp-range, 2)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$range-type = 1">
+ <!-- Nothing to convert, so just join the front and behind strings. -->
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression">
+ <!-- get current converting position from $temp-token or $current-range, then join the expression. -->
+ <xsl:choose>
+ <xsl:when test="contains($current-range, '#$')">
+ <!-- because of recomposing of string, the $current-range may not be the pit
+ of $expression, so the char #$ should not be used for nominal -->
+ <xsl:variable name="temp-token">
+ <xsl:choose>
+ <xsl:when test="contains($current-range, '\')">
+ <xsl:value-of select="concat(']', substring-after($current-range, '#$'), &quot;&apos;&quot;)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($current-range, '#$')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="substring-after($expression, $temp-token)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($expression, $current-range)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="return-value">
+ <!-- react on range mode change (when to insert closing ']' or in case of '!' change the mode to RANGE and create open '[' -->
+ <xsl:choose>
+ <xsl:when test="$current-range = '=' and $return-value = '' and not($isRangeAddress)">
+ <xsl:text>oooc:=</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($current-range, '!') and not($isRangeAddress)">
+ <xsl:value-of select="concat($return-value, '[', $current-range)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$is-range-mode = 'true' and $current-range != ':' and not($isRangeAddress)">
+ <xsl:value-of select="concat($return-value, ']', substring-before($expression, $current-range), $current-range)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($return-value, substring-before($expression, $current-range), $current-range)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="is-range-mode">
+ <xsl:choose>
+ <!-- ! is the separator of worksheet and range
+ : is the separator for a cell range -->
+ <xsl:when test="contains($current-range, '!') or $current-range = ':'">
+ <xsl:value-of select="true()"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="false()"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="isRangeAddress" select="$isRangeAddress"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- types of range to handle in $current-range, i.e. the cell position expression to convert
+ 1: special cell including row and column; e.g. R4C5
+ 2: whole row; e.g. R3
+ 3: whole column; e.g. C5
+ 4: other name not for cell or row/column; e.g. RANDOM() or something unknown
+ -->
+ <xsl:variable name="handle-type">
+ <xsl:choose>
+ <xsl:when test="starts-with($current-range, 'R')">
+ <!-- It's type 1 or type 2 or 4/unknown cell position. -->
+ <xsl:choose>
+ <xsl:when test="contains($current-range, 'C')">
+ <!-- It's type 1, specifying the cell position or 4/unknown -->
+ <xsl:variable name="part-type-r">
+ <xsl:call-template name="handle-type-number">
+ <xsl:with-param name="t-part" select="substring-before( substring-after($current-range, 'R'), 'C')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="part-type-c">
+ <xsl:call-template name="handle-type-number">
+ <xsl:with-param name="t-part" select="substring-after($current-range, 'C')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="($part-type-r = 1) and ($part-type-c = 1)">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="4"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- It's type 2 specifying the cell position, or 4/unknown. -->
+ <xsl:variable name="part-type">
+ <xsl:call-template name="handle-type-number">
+ <xsl:with-param name="t-part" select="substring-after($current-range, 'R')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$part-type = 1">
+ <xsl:value-of select="2"/>
+ </xsl:when>
+ <xsl:when test="$part-type = 2">
+ <xsl:value-of select="4"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="4"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with($current-range, 'C')">
+ <!-- It's type 3 of cell position, or 4/unknown -->
+ <xsl:variable name="part-type">
+ <xsl:call-template name="handle-type-number">
+ <xsl:with-param name="t-part" select="substring-after($current-range, 'C')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$part-type = 1">
+ <xsl:value-of select="3"/>
+ </xsl:when>
+ <xsl:when test="$part-type = 2">
+ <xsl:value-of select="4"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="4"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- It's type 4, not cell position -->
+ <xsl:value-of select="4"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- Start to convert that cell position expression, that cell position unit -->
+ <xsl:choose>
+ <xsl:when test="$handle-type = 1">
+ <!-- It's type 1, e.g. R1C2 -->
+ <!-- process the row part -->
+ <xsl:variable name="after-R">
+ <xsl:value-of select="substring(substring-after($current-range,'R'),1,1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <!-- found one cell unit -->
+ <xsl:when test="$after-R='C' or $after-R='[' or $after-R='0' or $after-R='1' or $after-R='2' or $after-R='3' or $after-R='4' or $after-R='5' or $after-R='6' or $after-R='7' or $after-R='8' or $after-R='9'">
+ <xsl:variable name="row-pos">
+ <xsl:choose>
+ <xsl:when test="$after-R='['">
+ <xsl:value-of select="$cell-row-pos+substring-before( substring-after($current-range,'R['),']')"/>
+ </xsl:when>
+ <xsl:when test="$after-R='C'">
+ <xsl:value-of select="$cell-row-pos"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(substring-after($current-range,'R'),'C')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="row-pos-style">
+ <xsl:choose>
+ <xsl:when test="$after-R='[' or $after-R='C'">relative</xsl:when>
+ <xsl:otherwise>absolute</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- process the column part -->
+ <xsl:variable name="after-C">
+ <xsl:value-of select="substring(substring-after(substring-after($current-range,'R'),'C'),1,1)"/>
+ </xsl:variable>
+ <xsl:variable name="column-digit-length">
+ <xsl:choose>
+ <xsl:when test="$after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">
+ <xsl:call-template name="get-digit-length">
+ <xsl:with-param name="complexive-string" select="substring-after(substring-after($current-range,'R'),'C')"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="column-pos">
+ <xsl:choose>
+ <xsl:when test="$after-C='['">
+ <xsl:value-of select="$cell-column-pos + substring-before(substring-after(substring-after($current-range,'R'),'C['),']')"/>
+ </xsl:when>
+ <xsl:when test="$after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">
+ <xsl:value-of select="substring(substring-after(substring-after($current-range,'R'),'C'),1,$column-digit-length)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$cell-column-pos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="column-pos-style">
+ <xsl:choose>
+ <xsl:when test="$after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">absolute</xsl:when>
+ <xsl:otherwise>relative</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="trans-unit">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="$column-pos"/>
+ <xsl:with-param name="row-number" select="$row-pos"/>
+ <xsl:with-param name="column-pos-style" select="$column-pos-style"/>
+ <xsl:with-param name="row-pos-style" select="$row-pos-style"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), $trans-unit)"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($expression, $current-range)"/>
+ <xsl:with-param name="return-value">
+ <xsl:choose>
+ <xsl:when test="$is-range-mode = 'true'">
+ <xsl:value-of select="concat($return-value, $name-unit)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($return-value, '[.', $name-unit)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="is-range-mode" select="true()"/>
+ <xsl:with-param name="isRangeAddress" select="$isRangeAddress"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), translate( substring-before(substring-after($expression, '('),'R'),',!', ';.'))"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($current-range,'R')"/>
+ <xsl:with-param name="return-value">
+ <xsl:choose>
+ <xsl:when test="$is-range-mode = 'true'">
+ <xsl:value-of select="concat($return-value, $name-unit)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($return-value, '[.', $name-unit)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="is-range-mode" select="true()"/>
+ <xsl:with-param name="isRangeAddress" select="$isRangeAddress"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$handle-type = 2">
+ <!-- It's type 2, e.g. R3 -->
+ <!-- process the range only including a whole row -->
+ <xsl:variable name="after-R">
+ <xsl:value-of select="substring(substring-after($current-range,'R'),1,1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$after-R='[' or $after-R='0' or $after-R='1' or $after-R='2' or $after-R='3' or $after-R='4' or $after-R='5' or $after-R='6' or $after-R='7' or $after-R='8' or $after-R='9'">
+ <xsl:variable name="row-number">
+ <xsl:choose>
+ <xsl:when test="$after-R = '['">
+ <xsl:value-of select="substring-before(substring-after($current-range, 'R['), ']')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($current-range, 'R')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="row-pos">
+ <xsl:choose>
+ <xsl:when test="$after-R='['">
+ <xsl:value-of select="$cell-row-pos + $row-number"/>
+ </xsl:when>
+ <xsl:when test="$after-R='0' or $after-R='1' or $after-R='2' or $after-R='3' or $after-R='4' or $after-R='5' or $after-R='6' or $after-R='7' or $after-R='8' or $after-R='9'">
+ <xsl:value-of select="$row-number"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$cell-row-pos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="trans-unit1">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="1"/>
+ <xsl:with-param name="row-number" select="$row-pos"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="trans-unit2">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="256"/>
+ <xsl:with-param name="row-number" select="$row-pos"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), $trans-unit1, ':', $trans-unit2)"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($expression, $current-range)"/>
+ <xsl:with-param name="return-value">
+ <xsl:choose>
+ <xsl:when test="$is-range-mode = 'true'">
+ <xsl:value-of select="concat($return-value, $name-unit)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($return-value, '[.', $name-unit)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="is-range-mode" select="true()"/>
+ <xsl:with-param name="isRangeAddress" select="$isRangeAddress"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), translate( substring-before($current-range,'R'),',!', ';.'),'R')"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($current-range,'R')"/>
+ <xsl:with-param name="return-value">
+ <xsl:choose>
+ <xsl:when test="$is-range-mode = 'true'">
+ <xsl:value-of select="concat($return-value, $name-unit)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($return-value, '[.', $name-unit)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="is-range-mode" select="true()"/>
+ <xsl:with-param name="isRangeAddress" select="$isRangeAddress"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$handle-type = 3">
+ <!-- It's type 3, e.g. C4 -->
+ <!-- process the range only including a whole column -->
+ <xsl:variable name="after-C">
+ <xsl:value-of select="substring(substring-after($current-range,'C'),1,1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$after-C='[' or $after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">
+ <xsl:variable name="column-number">
+ <xsl:choose>
+ <xsl:when test="$after-C = '['">
+ <xsl:value-of select="substring-before(substring-after($current-range, 'C['), ']')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($current-range, 'C')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="column-pos">
+ <xsl:choose>
+ <xsl:when test="$after-C='['">
+ <xsl:value-of select="$cell-column-pos + $column-number"/>
+ </xsl:when>
+ <xsl:when test="$after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">
+ <xsl:value-of select="$column-number"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$cell-column-pos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="trans-unit1">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="$column-pos"/>
+ <xsl:with-param name="row-number" select="1"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="trans-unit2">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="$column-pos"/>
+ <xsl:with-param name="row-number" select="65565"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), $trans-unit1, ':', $trans-unit2)"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($expression, $current-range)"/>
+ <xsl:with-param name="return-value">
+ <xsl:choose>
+ <xsl:when test="$is-range-mode = 'true'">
+ <xsl:value-of select="concat($return-value, $name-unit)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($return-value, '[.', $name-unit)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="is-range-mode" select="true()"/>
+ <xsl:with-param name="isRangeAddress" select="$isRangeAddress"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), translate( substring-before($current-range,'C'),',!', ';.'),'C')"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($current-range,'C')"/>
+ <xsl:with-param name="return-value">
+ <xsl:choose>
+ <xsl:when test="$is-range-mode = 'true'">
+ <xsl:value-of select="concat($return-value, $name-unit)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($return-value, '[.', $name-unit)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="is-range-mode" select="true()"/>
+ <xsl:with-param name="isRangeAddress" select="$isRangeAddress"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- It's unknown, so just jump over it -->
+ <xsl:variable name="next-pit" select="substring-after($expression, $current-range)"/>
+ <xsl:choose>
+ <xsl:when test="contains($next-pit, '+') or contains($next-pit, '-') or contains($next-pit, '*') or contains($next-pit, '/') or contains($next-pit, ')') or contains($next-pit, '^') or contains($next-pit, ':') or contains($next-pit, '&quot;') or contains($next-pit, ';') or contains($next-pit, ',') or contains($next-pit, '[')">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($expression, $current-range)"/>
+ <xsl:with-param name="return-value" select="concat($return-value, substring-before($expression, $current-range), $current-range)"/>
+ <xsl:with-param name="is-range-mode" select="false()"/>
+ <xsl:with-param name="isRangeAddress" select="$isRangeAddress"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- return the final range or formula -->
+ <xsl:choose>
+ <!-- in case the closing bracket of the range wasn't set, do it now -->
+ <xsl:when test="$is-range-mode = 'true' and $current-range = ''">
+ <xsl:value-of select="translate( concat($return-value, ']'),',!', ';.')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate( concat($return-value, substring-before($expression, $current-range), $current-range),',!', ';.')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="parse-range-name">
+ <!-- return the string or name for next handle. the type 1 is names of function, sheet, special separated symbol, not to parse as range; type 2 is the range including R/C to be parsed -->
+ <xsl:param name="expression"/>
+ <xsl:param name="return-value"/>
+ <xsl:variable name="first-one" select="substring($expression,1,1)"/>
+ <xsl:choose>
+ <xsl:when test="$first-one = '='">
+ <xsl:choose>
+ <xsl:when test="string-length(normalize-space($return-value)) &gt; 0">
+ <xsl:value-of select="concat('2', $return-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>1=</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-one='(' or $first-one='!' or $first-one='&amp;'">
+ <xsl:value-of select="concat('1', $return-value, $first-one)"/>
+ </xsl:when>
+ <xsl:when test="$first-one='['">
+ <xsl:choose>
+ <xsl:when test="starts-with(substring-after($expression, ']'), 'C')">
+ <xsl:call-template name="parse-range-name">
+ <xsl:with-param name="expression" select="substring-after($expression, ']')"/>
+ <xsl:with-param name="return-value" select="concat($return-value, substring-before($expression, ']'), ']')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains(substring-before($expression, ']'), '.') and contains(substring-after($expression, ']'), '!')">
+ <xsl:value-of select="concat('1', &quot;&apos;&quot;, substring-before(substring-after($expression, '['), ']'), &quot;&apos;&quot;, '#$', substring-before(substring-after($expression, ']'), '!'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('2', $return-value, substring-before($expression, ']'), ']')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-one='&quot;'">
+ <xsl:value-of select="concat('1', $first-one, substring-before(substring-after($expression, '&quot;'), '&quot;'), '&quot;')"/>
+ </xsl:when>
+ <xsl:when test="$first-one=&quot;&apos;&quot;">
+ <!-- here the string &quot;&apos;&quot; represents a char &apos; -->
+ <xsl:variable name="str-in" select="substring-before(substring-after($expression, &quot;&apos;&quot;), &quot;&apos;&quot;)"/>
+ <xsl:choose>
+ <!-- for file path transformation -->
+ <xsl:when test="contains($str-in, '\') and contains($str-in, '[') and contains($str-in, ']')">
+ <xsl:variable name="first-pos" select="substring-before($str-in, '[')"/>
+ <xsl:variable name="second-pos" select="substring-before(substring-after($str-in, '['), ']')"/>
+ <xsl:variable name="third-pos" select="substring-after($str-in, ']')"/>
+ <xsl:value-of select="concat('1', &quot;&apos;&quot;, $first-pos, $second-pos, &quot;&apos;&quot;, '#$', $third-pos)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('1', &quot;&apos;&quot;, $str-in, &quot;&apos;&quot;)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-one='+' or $first-one='-' or $first-one='*' or $first-one='/' or $first-one=')' or $first-one='^' or $first-one=':' or $first-one='&quot;' or $first-one=';' or $first-one=',' or $first-one='&gt;' or $first-one='&lt;'">
+ <xsl:choose>
+ <xsl:when test="$return-value = ''">
+ <xsl:value-of select="concat('1', $first-one)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('2', $return-value)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$expression = ''">
+ <xsl:value-of select="concat('2', $return-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="parse-range-name">
+ <xsl:with-param name="expression" select="substring($expression, 2, string-length($expression)-1)"/>
+ <xsl:with-param name="return-value" select="concat($return-value, substring($expression, 1, 1))"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="handle-type-number">
+ <!-- to handle the part between R and C, or after C in range string in translate-expression. return type: 1: number or cell range; 2: other, not for next step -->
+ <xsl:param name="t-part"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($t-part, '[')">
+ <xsl:variable name="tt-str" select="substring-before( substring-after( $t-part, '['), ']')"/>
+ <xsl:choose>
+ <xsl:when test="($tt-str &lt; 0) or ($tt-str &gt; 0) or ($tt-str = 0)">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="($t-part &lt; 0) or ($t-part &gt; 0) or ($t-part = 0)">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:when test="$t-part = ''">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="translate-unit">
+ <!-- convert cell position expression unit, R1C1, R3, C4 -->
+ <xsl:param name="column-number"/>
+ <xsl:param name="row-number"/>
+ <xsl:param name="column-pos-style"/>
+ <xsl:param name="row-pos-style"/>
+ <xsl:variable name="column-number1">
+ <xsl:value-of select="floor( $column-number div 26 )"/>
+ </xsl:variable>
+ <xsl:variable name="column-number2">
+ <xsl:value-of select="$column-number mod 26"/>
+ </xsl:variable>
+ <xsl:variable name="column-character1">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="column-character2">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- position styles are 'absolute' or 'relative', -->
+ <xsl:choose>
+ <xsl:when test="$column-pos-style = 'absolute'">
+ <xsl:value-of select="concat( '$', $column-character1, $column-character2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat( $column-character1, $column-character2)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="$row-pos-style ='absolute'">
+ <xsl:value-of select="concat( '$', $row-number)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$row-number"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="number-to-character">
+ <xsl:param name="number"/>
+ <xsl:choose>
+ <xsl:when test="$number = 0"/>
+ <xsl:when test="$number = 1">A</xsl:when>
+ <xsl:when test="$number = 2">B</xsl:when>
+ <xsl:when test="$number = 3">C</xsl:when>
+ <xsl:when test="$number = 4">D</xsl:when>
+ <xsl:when test="$number = 5">E</xsl:when>
+ <xsl:when test="$number = 6">F</xsl:when>
+ <xsl:when test="$number = 7">G</xsl:when>
+ <xsl:when test="$number = 8">H</xsl:when>
+ <xsl:when test="$number = 9">I</xsl:when>
+ <xsl:when test="$number = 10">J</xsl:when>
+ <xsl:when test="$number = 11">K</xsl:when>
+ <xsl:when test="$number = 12">L</xsl:when>
+ <xsl:when test="$number = 13">M</xsl:when>
+ <xsl:when test="$number = 14">N</xsl:when>
+ <xsl:when test="$number = 15">O</xsl:when>
+ <xsl:when test="$number = 16">P</xsl:when>
+ <xsl:when test="$number = 17">Q</xsl:when>
+ <xsl:when test="$number = 18">R</xsl:when>
+ <xsl:when test="$number = 19">S</xsl:when>
+ <xsl:when test="$number = 20">T</xsl:when>
+ <xsl:when test="$number = 21">U</xsl:when>
+ <xsl:when test="$number = 22">V</xsl:when>
+ <xsl:when test="$number = 23">W</xsl:when>
+ <xsl:when test="$number = 24">X</xsl:when>
+ <xsl:when test="$number = 25">Y</xsl:when>
+ <xsl:when test="$number = 26">Z</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-digit-length">
+ <xsl:param name="complexive-string"/>
+ <xsl:variable name="first-char">
+ <xsl:value-of select="substring( $complexive-string, 1, 1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-char = '1' or $first-char = '2' or $first-char = '3' or $first-char = '4' or $first-char = '5' or $first-char = '6' or $first-char = '7' or $first-char = '8' or $first-char = '9' or $first-char = '0' ">
+ <xsl:variable name="temp">
+ <xsl:call-template name="get-digit-length">
+ <xsl:with-param name="complexive-string" select="substring( $complexive-string, 2)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$temp+1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="ss:Comment" mode="body">
+ <xsl:element name="office:annotation">
+ <xsl:if test="@ss:ShowAlways = '1'">
+ <xsl:attribute name="office:display">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@ss:Author">
+ <xsl:element name="dc:creator">
+ <xsl:value-of select="@ss:Author"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="ss:Data">
+ <text:p>
+ <xsl:call-template name="create-data-content">
+ <xsl:with-param name="style-id" select="@ss:StyleID"/>
+ </xsl:call-template>
+ </text:p>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Names">
+ <xsl:variable name="namedRanges" select="/ss:Workbook/ss:Worksheet/ss:Names/ss:NamedRange |
+ /ss:Workbook/ss:Names/ss:NamedRange" />
+ <xsl:if test="$namedRanges">
+ <table:named-expressions>
+ <xsl:for-each select="$namedRanges">
+ <xsl:choose>
+ <xsl:when test="contains( @ss:RefersTo, '!R')">
+ <xsl:variable name="referto">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="isRangeAddress" select="true()"/>
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="@ss:RefersTo"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="table:named-range">
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="@ss:Name"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:base-cell-address">
+ <xsl:variable name="worksheetName" select="translate(substring-before(@ss:RefersTo, '!'), '=', '$')" />
+ <xsl:call-template name="encode-as-cell-address">
+ <xsl:with-param name="string" select="concat($worksheetName,'.$A$1')"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="table:cell-range-address">
+ <xsl:call-template name="encode-as-cell-range-address">
+ <xsl:with-param name="string" select="translate( $referto, '=', '$')"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="@ss:Name = 'Print_Area'">
+ <xsl:attribute name="table:range-usable-as">print-range</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="expression-name">
+ <xsl:value-of select="@ss:Name"/>
+ </xsl:variable>
+ <xsl:element name="table:named-expression">
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="@ss:Name"/>
+ </xsl:attribute>
+ <!-- just set '$Sheet1.$A$1' as named-expressions virtual base-cell-address -->
+ <xsl:attribute name="table:base-cell-address">
+ <xsl:variable name="worksheetName" select="following-sibling::ss:Worksheet/@ss:Name" />
+ <xsl:call-template name="encode-as-cell-address">
+ <xsl:with-param name="string" select="concat('$', $worksheetName,'.$A$1')"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="table:expression">
+ <xsl:value-of select="substring( @ss:RefersTo, 2)"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </table:named-expressions>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="transform-advanced-filter">
+ <!-- transform the params of Advanced Filter.it's different from AutoFilter -->
+ <xsl:param name="target-value"/>
+ <xsl:param name="condition-pos"/>
+ <xsl:element name="table:database-range">
+ <xsl:variable name="target-range">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="$target-value"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="condition-range">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="$condition-pos"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="table:target-range-address">
+ <xsl:value-of select="$target-range"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="concat($target-range, '.filter')"/>
+ </xsl:attribute>
+ <xsl:element name="table:filter">
+ <xsl:attribute name="table:condition-source-range-address">
+ <xsl:value-of select="$condition-range"/>
+ </xsl:attribute>
+ <xsl:element name="table:filter-condition">
+ <xsl:attribute name="table:field-number">0</xsl:attribute>
+ <!-- The two attributes are recommended by OASIS -->
+ <xsl:attribute name="table:value"/>
+ <xsl:attribute name="table:operator"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="x:AutoFilter">
+ <!-- for AutoFilter -->
+ <xsl:element name="table:database-range">
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="concat(../@ss:Name,'_',@x:Range)"/>
+ </xsl:attribute>
+ <xsl:variable name="range">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="@x:Range"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="table:target-range-address">
+ <xsl:value-of select="concat('$',../@ss:Name,'.',$range)"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:display-filter-buttons">true</xsl:attribute>
+ <xsl:element name="table:filter">
+ <xsl:call-template name="auto-filter-condition">
+ <xsl:with-param name="item-pos" select="1"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="total" select="count(./x:AutoFilterColumn)"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="auto-filter-condition">
+ <!--?? generate element of filter-condition for AutoCondition to get position of index -->
+ <xsl:param name="item-pos"/>
+ <xsl:param name="index"/>
+ <xsl:param name="total"/>
+ <xsl:if test="($index - 1 &lt; $total) or ($index - 1 = $total)">
+ <xsl:element name="table:filter-condition">
+ <xsl:attribute name="table:data-type">number</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/@x:Type = 'TopPercent'">
+ <xsl:attribute name="table:operator">
+ <xsl:value-of select="'top value'"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:value">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]/@x:Value"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/@x:Type = 'Top'">
+ <xsl:attribute name="table:operator">
+ <xsl:value-of select="'top values'"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:value">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]/@x:Value"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/@x:Type = 'TopPercent'">
+ <xsl:attribute name="table:operator">
+ <xsl:value-of select="'top percent'"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:value">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]/@x:Value"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/@x:Type = 'Bottom'">
+ <xsl:attribute name="table:operator">
+ <xsl:value-of select="'bottom values'"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:value">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]/@x:Value"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/@x:Type = 'BottomPercent'">
+ <xsl:attribute name="table:operator">
+ <xsl:value-of select="'bottom percent'"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:value">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]/@x:Value"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/@x:Type = 'Custom'">
+ <xsl:choose>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/x:AutoFilterOr or ./x:AutoFilterColumn[position() = $item-pos]/x:AutoFilterAnd">
+ <xsl:attribute name="table:operator">
+ <xsl:choose>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]//@x:Operator = 'Equals'">
+ <xsl:value-of select="'='"/>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]//@x:Operator = 'DoesNotEquals'">
+ <xsl:value-of select="'!='"/>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]//@x:Operator = 'GreaterThan'">
+ <xsl:value-of select="'&gt;'"/>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]//@x:Operator = 'GreaterThanOrEqual'">
+ <xsl:value-of select="'&gt;='"/>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]//@x:Operator = 'LessThan'">
+ <xsl:value-of select="'&lt;'"/>
+ </xsl:when>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]//@x:Operator = 'LessThanOrEqual'">
+ <xsl:value-of select="'&lt;='"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'='"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="table:value">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]//@x:Value"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:operator">
+ <xsl:value-of select="'bottom percent'"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:value">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]//@x:Value"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:attribute name="table:field-number">
+ <xsl:choose>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/@x:Index">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]/@x:Index - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$index - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="auto-filter-condition">
+ <xsl:with-param name="item-pos" select="$item-pos + 1"/>
+ <xsl:with-param name="index">
+ <xsl:choose>
+ <xsl:when test="./x:AutoFilterColumn[position() = $item-pos]/@x:Index">
+ <xsl:value-of select="./x:AutoFilterColumn[position() = $item-pos]/@x:Index + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$index + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="total" select="count(./x:AutoFilterColumn)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="x:Sorting">
+ <!-- for Sorting don't contains header row -->
+ <xsl:if test="contains(./x:Sort, 'Column')">
+ <xsl:element name="table:database-range">
+ <xsl:variable name="first-sort-letter" select="normalize-space(substring-after(./x:Sort[position() = 1], 'Column'))"/>
+ <xsl:variable name="second-sort-letter" select="normalize-space(substring-after(./x:Sort[position() = 2], 'Column'))"/>
+ <xsl:variable name="third-sort-letter" select="normalize-space(substring-after(./x:Sort[position() = 3], 'Column'))"/>
+ <xsl:variable name="first-sort-num">
+ <xsl:call-template name="letter-to-number">
+ <xsl:with-param name="source-letter" select="$first-sort-letter"/>
+ <xsl:with-param name="return-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="second-sort-num">
+ <xsl:call-template name="letter-to-number">
+ <xsl:with-param name="source-letter" select="$second-sort-letter"/>
+ <xsl:with-param name="return-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="third-sort-num">
+ <xsl:call-template name="letter-to-number">
+ <xsl:with-param name="source-letter" select="$third-sort-letter"/>
+ <xsl:with-param name="return-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="min-left-num">
+ <xsl:call-template name="min-of-three">
+ <xsl:with-param name="first-num" select="$first-sort-num"/>
+ <xsl:with-param name="second-num" select="$second-sort-num"/>
+ <xsl:with-param name="third-num" select="$third-sort-num"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="max-right-num">
+ <xsl:call-template name="max-of-three">
+ <xsl:with-param name="first-num" select="$first-sort-num"/>
+ <xsl:with-param name="second-num" select="$second-sort-num"/>
+ <xsl:with-param name="third-num" select="$third-sort-num"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="left-column">
+ <xsl:call-template name="number-to-letter">
+ <xsl:with-param name="source-number" select="$min-left-num"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="right-column">
+ <xsl:call-template name="number-to-letter">
+ <xsl:with-param name="source-number" select="$max-right-num"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="table:target-range-address">
+ <xsl:value-of select="concat(../@ss:Name, '.', $left-column, '1:', ../@ss:Name, '.', $right-column, '32000')"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="concat(../@ss:Name, '.sort')"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:contains-header">
+ <xsl:value-of select="'false'"/>
+ </xsl:attribute>
+ <xsl:element name="table:sort">
+ <xsl:for-each select="./x:Sort">
+ <xsl:element name="table:sort-by">
+ <xsl:attribute name="table:field-number">
+ <xsl:value-of select="0"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:data-type">
+ <xsl:value-of select="'automatic'"/>
+ </xsl:attribute>
+ <xsl:variable name="after-sort" select="following-sibling::*"/>
+ <xsl:if test="name($after-sort[position() = 1]) = 'Descending'">
+ <xsl:attribute name="table:order">
+ <xsl:value-of select="'descending'"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="position() = 1">
+ <xsl:attribute name="table:field-number">
+ <xsl:value-of select="$first-sort-num - $min-left-num"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="position() = 2">
+ <xsl:attribute name="table:field-number">
+ <xsl:value-of select="$second-sort-num - $min-left-num"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="position() = 3">
+ <xsl:attribute name="table:field-number">
+ <xsl:value-of select="$third-sort-num - $min-left-num"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="letter-to-number">
+ <!-- convert letter to number for sorting. the string source-letter should be normalize-space and the first return-value should be zero -->
+ <xsl:param name="source-letter"/>
+ <xsl:param name="return-value"/>
+ <xsl:choose>
+ <xsl:when test="string-length($source-letter) &gt; 0">
+ <xsl:variable name="first-pit" select="substring($source-letter, 1, 1)"/>
+ <xsl:variable name="pit-number">
+ <xsl:choose>
+ <xsl:when test="($first-pit = 'A') or ($first-pit = 'a')">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'B') or ($first-pit = 'b')">
+ <xsl:value-of select="2"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'C') or ($first-pit = 'c')">
+ <xsl:value-of select="3"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'D') or ($first-pit = 'd')">
+ <xsl:value-of select="4"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'E') or ($first-pit = 'e')">
+ <xsl:value-of select="5"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'F') or ($first-pit = 'f')">
+ <xsl:value-of select="6"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'G') or ($first-pit = 'g')">
+ <xsl:value-of select="7"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'H') or ($first-pit = 'h')">
+ <xsl:value-of select="8"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'I') or ($first-pit = 'i')">
+ <xsl:value-of select="9"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'J') or ($first-pit = 'j')">
+ <xsl:value-of select="10"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'K') or ($first-pit = 'k')">
+ <xsl:value-of select="11"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'L') or ($first-pit = 'l')">
+ <xsl:value-of select="12"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'M') or ($first-pit = 'm')">
+ <xsl:value-of select="13"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'N') or ($first-pit = 'n')">
+ <xsl:value-of select="14"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'O') or ($first-pit = 'o')">
+ <xsl:value-of select="15"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'P') or ($first-pit = 'p')">
+ <xsl:value-of select="16"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'Q') or ($first-pit = 'q')">
+ <xsl:value-of select="17"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'R') or ($first-pit = 'r')">
+ <xsl:value-of select="18"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'S') or ($first-pit = 's')">
+ <xsl:value-of select="19"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'T') or ($first-pit = 't')">
+ <xsl:value-of select="20"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'U') or ($first-pit = 'u')">
+ <xsl:value-of select="21"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'V') or ($first-pit = 'v')">
+ <xsl:value-of select="22"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'W') or ($first-pit = 'w')">
+ <xsl:value-of select="23"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'X') or ($first-pit = 'x')">
+ <xsl:value-of select="24"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'Y') or ($first-pit = 'y')">
+ <xsl:value-of select="25"/>
+ </xsl:when>
+ <xsl:when test="($first-pit = 'Z') or ($first-pit = 'z')">
+ <xsl:value-of select="26"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="letter-to-number">
+ <xsl:with-param name="source-letter" select="substring($source-letter, 2)"/>
+ <xsl:with-param name="return-value">
+ <xsl:choose>
+ <xsl:when test="string-length($source-letter) &gt;= 2">
+ <xsl:value-of select="$pit-number * 26 + $return-value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$pit-number + $return-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="number-to-letter">
+ <!--?? convert number to letter for sorting -->
+ <xsl:param name="source-number"/>
+ <xsl:param name="return-value"/>
+ <xsl:variable name="current-value">
+ <xsl:call-template name="num-conv-letter">
+ <xsl:with-param name="first-pit">
+ <xsl:choose>
+ <xsl:when test="$source-number &gt; 26">
+ <xsl:value-of select="floor($source-number div 26)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$source-number"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$source-number &gt; 26">
+ <xsl:call-template name="number-to-letter">
+ <xsl:with-param name="source-number" select="$source-number mod 26"/>
+ <xsl:with-param name="return-value" select="concat($return-value,$current-value)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$source-number &lt; 27">
+ <xsl:value-of select="concat($return-value,$current-value)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="num-conv-letter">
+ <!-- convert number to number by pit of 26 -->
+ <xsl:param name="first-pit"/>
+ <xsl:choose>
+ <xsl:when test="$first-pit = 1">
+ <xsl:value-of select="'A'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 2">
+ <xsl:value-of select="'B'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 3">
+ <xsl:value-of select="'C'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 4">
+ <xsl:value-of select="'D'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 5">
+ <xsl:value-of select="'E'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 6">
+ <xsl:value-of select="'F'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 7">
+ <xsl:value-of select="'G'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 8">
+ <xsl:value-of select="'H'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 9">
+ <xsl:value-of select="'I'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 10">
+ <xsl:value-of select="'J'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 11">
+ <xsl:value-of select="'K'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 12">
+ <xsl:value-of select="'L'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 13">
+ <xsl:value-of select="'M'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 14">
+ <xsl:value-of select="'N'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 15">
+ <xsl:value-of select="'O'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 16">
+ <xsl:value-of select="'P'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 17">
+ <xsl:value-of select="'Q'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 18">
+ <xsl:value-of select="'R'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 19">
+ <xsl:value-of select="'S'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 20">
+ <xsl:value-of select="'T'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 21">
+ <xsl:value-of select="'U'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 22">
+ <xsl:value-of select="'V'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 23">
+ <xsl:value-of select="'W'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 24">
+ <xsl:value-of select="'X'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 25">
+ <xsl:value-of select="'Y'"/>
+ </xsl:when>
+ <xsl:when test="$first-pit = 26">
+ <xsl:value-of select="'Z'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'A'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="min-of-three">
+ <!-- return lowest of three for sorting -->
+ <xsl:param name="first-num"/>
+ <xsl:param name="second-num"/>
+ <xsl:param name="third-num"/>
+ <xsl:variable name="first-comp">
+ <xsl:choose>
+ <xsl:when test="$first-num = 0">
+ <xsl:value-of select="$second-num"/>
+ </xsl:when>
+ <xsl:when test="($first-num &lt; $second-num) or ($second-num = 0)">
+ <xsl:value-of select="$first-num"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$second-num"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="second-comp">
+ <xsl:choose>
+ <xsl:when test="($first-comp &lt; $third-num) or ($third-num = 0)">
+ <xsl:value-of select="$first-comp"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$third-num"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$second-comp"/>
+ </xsl:template>
+ <xsl:template name="max-of-three">
+ <!-- return greatest of three for sorting -->
+ <xsl:param name="first-num"/>
+ <xsl:param name="second-num"/>
+ <xsl:param name="third-num"/>
+ <xsl:variable name="first-comp">
+ <xsl:choose>
+ <xsl:when test="$first-num &gt; $second-num">
+ <xsl:value-of select="$first-num"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$second-num"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="second-comp">
+ <xsl:choose>
+ <xsl:when test="$first-comp &gt; $third-num">
+ <xsl:value-of select="$first-comp"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$third-num"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$second-comp"/>
+ </xsl:template>
+ <xsl:template name="set-calculation">
+ <xsl:element name="table:calculation-settings">
+ <xsl:if test="/ss:Workbook/x:ExcelWorkbook/x:PrecisionAsDisplayed">
+ <xsl:attribute name="table:precision-as-shown">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="/ss:Workbook/x:ExcelWorkbook/x:Date1904">
+ <table:null-date office:date-value="1904-01-01"/>
+ </xsl:if>
+ <xsl:element name="table:iteration">
+ <xsl:if test="/ss:Workbook/x:ExcelWorkbook/x:Iteration">
+ <xsl:attribute name="table:status">enable</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="/ss:Workbook/x:ExcelWorkbook/x:MaxIterations">
+ <xsl:attribute name="table:steps">
+ <xsl:value-of select="/ss:Workbook/x:ExcelWorkbook/x:MaxIterations"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="/ss:Workbook/x:ExcelWorkbook/x:MaxChange">
+ <xsl:attribute name="table:maximum-difference">
+ <xsl:value-of select="/ss:Workbook/x:ExcelWorkbook/x:MaxChange"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="x:DataValidation">
+ <!-- for DataValidation. don't support the attribute IMEMode currently. -->
+ <xsl:element name="table:content-validation">
+ <xsl:attribute name="table:name">
+ <xsl:value-of select="concat('val', position())"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:condition"><!-- don't support two type of qualifier: List, Custom -->
+ <xsl:variable name="qualifier-content">
+ <xsl:choose>
+ <xsl:when test="./x:Qualifier = 'NotBetween'">
+ <xsl:value-of select="concat('cell-content-is-not-between(', ./x:Min, ',', ./x:Max, ')')"/>
+ </xsl:when>
+ <xsl:when test="./x:Qualifier = 'NotEqual'">
+ <xsl:value-of select="concat('!=', ./x:Value)"/>
+ </xsl:when>
+ <xsl:when test="./x:Qualifier = 'Equal'">
+ <xsl:value-of select="concat('=', ./x:Value)"/>
+ </xsl:when>
+ <xsl:when test="./x:Qualifier = 'Less'">
+ <xsl:value-of select="concat('&lt;', ./x:Value)"/>
+ </xsl:when>
+ <xsl:when test="./x:Qualifier = 'Greater'">
+ <xsl:value-of select="concat('&gt;', ./x:Value)"/>
+ </xsl:when>
+ <xsl:when test="./x:Qualifier = 'GreaterOrEqual'">
+ <xsl:value-of select="concat('&gt;=', ./x:Value)"/>
+ </xsl:when>
+ <xsl:when test="./x:Qualifier = 'LessOrEqual'">
+ <xsl:value-of select="concat('&lt;=', ./x:Value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('cell-content-is-between(', ./x:Min, ',', ./x:Max)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="qualifier-value">
+ <xsl:choose>
+ <xsl:when test="./x:Type = 'Whole'">
+ <xsl:choose>
+ <xsl:when test="(./x:Qualifier = 'NotBetween') or ./x:Max">
+ <xsl:value-of select="concat('cell-content-is-whole-number() and ', $qualifier-content, ')')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('cell-content-is-whole-number() and ', 'cell-content()', $qualifier-content)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="./x:Type = 'Decimal'">
+ <xsl:choose>
+ <xsl:when test="(./x:Qualifier = 'NotBetween') or ./x:Max">
+ <xsl:value-of select="concat('cell-content-is-decimal-number() and ', $qualifier-content, ')')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('cell-content-is-decimal-number() and ', 'cell-content()', $qualifier-content)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="./x:Type = 'Date'">
+ <xsl:choose>
+ <xsl:when test="(./x:Qualifier = 'NotBetween') or ./x:Max">
+ <xsl:value-of select="concat('cell-content-is-date() and ', $qualifier-content, ')')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('cell-content-is-date() and ', 'cell-content()', $qualifier-content)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="./x:Type = 'Time'">
+ <xsl:choose>
+ <xsl:when test="(./x:Qualifier = 'NotBetween') or ./x:Max">
+ <xsl:value-of select="concat('cell-content-is-time() and ', $qualifier-content, ')')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('cell-content-is-time() and ', 'cell-content()', $qualifier-content)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="./x:Type = 'TextLength'">
+ <xsl:choose>
+ <xsl:when test="./x:Qualifier = 'NotBetween'">
+ <xsl:value-of select="concat('cell-content-text-length-is-not-between(', ./x:Min, ',', ./x:Max, ')')"/>
+ </xsl:when>
+ <xsl:when test="./x:Max and ./x:Min">
+ <xsl:value-of select="concat('cell-content-text-length-is-between(', ./x:Min, ',', ./x:Max, ')')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('cell-content-text-length()', $qualifier-content)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./x:Type"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$qualifier-value"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:base-cell-address">
+ <xsl:variable name="first-range">
+ <xsl:choose>
+ <xsl:when test="contains(./x:Range, ',')">
+ <xsl:value-of select="substring-before(./x:Range, ',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./x:Range"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="range">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="$first-range"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="encode-as-cell-address">
+ <xsl:with-param name="string" select="concat(../../ss:Worksheet/@ss:Name, '.', $range)"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:element name="table:help-message">
+ <xsl:attribute name="table:title">
+ <xsl:value-of select="./x:InputTitle"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:display">
+ <xsl:choose>
+ <xsl:when test="./x:InputHide">
+ <xsl:value-of select="'false'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'true'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:element name="text:p">
+ <xsl:value-of select="./x:InputMessage"/>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="table:error-message">
+ <xsl:attribute name="table:message-type">
+ <xsl:choose>
+ <xsl:when test="./x:ErrorStyle= 'Info'">
+ <xsl:value-of select="'information'"/>
+ </xsl:when>
+ <xsl:when test="./x:ErrorStyle= 'Warn'">
+ <xsl:value-of select="'warning'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'stop'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="table:title">
+ <xsl:value-of select="./x:ErrorTitle"/>
+ </xsl:attribute>
+ <xsl:attribute name="table:display">
+ <xsl:choose>
+ <xsl:when test="./x:ErrorHide">
+ <xsl:value-of select="'false'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'true'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:element name="text:p">
+ <xsl:value-of select="./x:ErrorMessage"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <!-- Note: Move template to common section -->
+ <xsl:template name="encode-as-cell-range-address">
+ <xsl:param name="string"/>
+ <xsl:value-of select="$string"/>
+ </xsl:template>
+ <xsl:template name="encode-as-cell-address">
+ <xsl:param name="string"/>
+ <xsl:value-of select="$string"/>
+ </xsl:template>
+ <xsl:template name="encode-as-nc-name">
+ <xsl:param name="string"/>
+ <xsl:value-of select="translate($string, '.%()/\+[]', '')"/>
+ </xsl:template>
+
+ <xsl:template name="set:distinct">
+ <xsl:param name="nodes" select="/.."/>
+ <xsl:param name="distinct" select="/.."/>
+ <xsl:choose>
+ <xsl:when test="$nodes">
+ <xsl:call-template name="set:distinct">
+ <xsl:with-param name="distinct" select="$distinct | $nodes[1][not(. = $distinct)]"/>
+ <xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$distinct" mode="set:distinct"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="node()|@*" mode="set:distinct">
+ <xsl:copy-of select="." />
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/uof/uof2odf_presentation.xsl b/filter/source/xslt/import/uof/uof2odf_presentation.xsl
new file mode 100644
index 000000000..1debe1dde
--- /dev/null
+++ b/filter/source/xslt/import/uof/uof2odf_presentation.xsl
@@ -0,0 +1,3494 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:图="http://schemas.uof.org/cn/2003/graph" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" office:version="1.0">
+ <xsl:output method="xml" indent="no" encoding="UTF-8" version="1.0"/>
+ <xsl:template match="uof:UOF">
+ <office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" office:version="1.0">
+ <xsl:apply-templates select="uof:元数据"/>
+ <office:settings>
+ <xsl:variable name="PageNumberFormat" select="/uof:UOF/uof:演示文稿/演:公用处理规则/演:页面设置集/演:页面设置/演:页码格式[1]"/>
+ <xsl:variable name="proportion">
+ <xsl:value-of select="substring-before(/uof:UOF/uof:演示文稿/演:公用处理规则/演:显示比例,'%')"/>
+ </xsl:variable>
+ <config:config-item-set config:name="ooo:view-settings">
+ <config:config-item config:name="VisibleAreaTop" config:type="int">0</config:config-item>
+ <config:config-item config:name="VisibleAreaLeft" config:type="int">0</config:config-item>
+ <config:config-item config:name="VisibleAreaWidth" config:type="int">14098</config:config-item>
+ <config:config-item config:name="VisibleAreaHeight" config:type="int">9998</config:config-item>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <config:config-item config:name="ViewId" config:type="string">view1</config:config-item>
+ <config:config-item config:name="GridIsVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="GridIsFront" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsSnapToGrid" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToPageMargins" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsSnapToSnapLines" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsSnapToObjectFrame" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsSnapToObjectPoints" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsPlusHandlesAlwaysVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsFrameDragSingles" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="EliminatePolyPointLimitAngle" config:type="int">1500</config:config-item>
+ <config:config-item config:name="IsEliminatePolyPoints" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="VisibleLayers" config:type="base64Binary">//////////////////////////////////////////8=</config:config-item>
+ <config:config-item config:name="PrintableLayers" config:type="base64Binary">//////////////////////////////////////////8=</config:config-item>
+ <config:config-item config:name="LockedLayers" config:type="base64Binary"/>
+ <config:config-item config:name="NoAttribs" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="NoColors" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="RulerIsVisible" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="PageKind" config:type="short">0</config:config-item>
+ <config:config-item config:name="SelectedPage" config:type="short">0</config:config-item>
+ <config:config-item config:name="IsLayerMode" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="IsDoubleClickTextEdit" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="IsClickChangeRotation" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SlidesPerRow" config:type="short">4</config:config-item>
+ <config:config-item config:name="EditModeStandard" config:type="int">0</config:config-item>
+ <config:config-item config:name="EditModeNotes" config:type="int">0</config:config-item>
+ <config:config-item config:name="EditModeHandout" config:type="int">1</config:config-item>
+ <config:config-item config:name="VisibleAreaTop" config:type="int">-5402</config:config-item>
+ <config:config-item config:name="VisibleAreaLeft" config:type="int">-441</config:config-item>
+ <config:config-item config:name="VisibleAreaWidth" config:type="int">
+ <xsl:value-of select="(100*13997) div $proportion"/>
+ </config:config-item>
+ <config:config-item config:name="VisibleAreaHeight" config:type="int">
+ <xsl:value-of select="(100*15426) div $proportion"/>
+ </config:config-item>
+ <config:config-item config:name="GridCoarseWidth" config:type="int">1000</config:config-item>
+ <config:config-item config:name="GridCoarseHeight" config:type="int">1000</config:config-item>
+ <config:config-item config:name="GridFineWidth" config:type="int">500</config:config-item>
+ <config:config-item config:name="GridFineHeight" config:type="int">500</config:config-item>
+ <config:config-item config:name="GridSnapWidth" config:type="int">1000</config:config-item>
+ <config:config-item config:name="GridSnapHeight" config:type="int">1000</config:config-item>
+ <config:config-item config:name="GridSnapWidthXNumerator" config:type="int">500</config:config-item>
+ <config:config-item config:name="GridSnapWidthXDenominator" config:type="int">1</config:config-item>
+ <config:config-item config:name="GridSnapWidthYNumerator" config:type="int">500</config:config-item>
+ <config:config-item config:name="GridSnapWidthYDenominator" config:type="int">1</config:config-item>
+ <config:config-item config:name="IsAngleSnapEnabled" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="SnapAngle" config:type="int">1500</config:config-item>
+ <config:config-item config:name="ZoomOnPage" config:type="boolean">true</config:config-item>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ <config:config-item-set config:name="ooo:configuration-settings">
+ <config:config-item config:name="PageNumberFormat" config:type="int">
+ <xsl:choose>
+ <xsl:when test="/uof:UOF/uof:演示文稿/演:公用处理规则/演:页面设置集/演:页面设置/演:页码格式">
+ <xsl:choose>
+ <xsl:when test="$PageNumberFormat='upper-letter'">0</xsl:when>
+ <xsl:when test="$PageNumberFormat='lower-letter'">1</xsl:when>
+ <xsl:when test="$PageNumberFormat='upper-roman'">2</xsl:when>
+ <xsl:when test="$PageNumberFormat='lower-letter'">3</xsl:when>
+ <xsl:when test="$PageNumberFormat='decimal'">4</xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>5</xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ </config:config-item-set>
+ </office:settings>
+ <office:scripts/>
+ <xsl:element name="office:font-face-decls">
+ <style:font-face style:name="宋体" svg:font-family="宋体" style:font-family-generic="swiss" style:font-pitch="variable"/>
+ <xsl:apply-templates select="uof:式样集/uof:字体集"/>
+ </xsl:element>
+ <office:styles>
+ <xsl:apply-templates select="uof:演示文稿/演:公用处理规则/演:页面版式集/演:页面版式"/>
+ <xsl:call-template name="编号字体"/>
+ <xsl:for-each select="uof:式样集/uof:段落式样">
+ <xsl:variable name="outline" select="@字:标识符"/>
+ <xsl:choose>
+ <xsl:when test="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号[@字:标识符=$outline]">
+ <xsl:call-template name="段落式样"/>
+ </xsl:when>
+ <xsl:when test="contains($outline,'outline')">
+ <xsl:call-template name="段落式样"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </office:styles>
+ <office:automatic-styles>
+ <xsl:apply-templates select="uof:演示文稿/演:公用处理规则/演:配色方案集/演:配色方案"/>
+ <xsl:apply-templates select="uof:式样集/uof:句式样"/>
+ <xsl:for-each select="uof:式样集/uof:段落式样">
+ <xsl:variable name="outline" select="@字:标识符"/>
+ <xsl:if test="not(/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号[@字:标识符=$outline]) and not(contains($outline,'outline'))">
+ <xsl:call-template name="段落式样"/>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:apply-templates select="uof:对象集"/>
+ <xsl:call-template name="create-page-master">
+ <xsl:with-param name="impressoptions" select="uof:演示文稿/演:公用处理规则/演:页面设置集/演:页面设置"/>
+ </xsl:call-template>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形/图:文本内容/字:段落/字:段落属性/字:自动编号信息">
+ <xsl:variable name="currlistid" select="@字:编号引用"/>
+ <xsl:variable name="currlist" select="."/>
+ <xsl:variable name="rootlist" select="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号[@字:标识符 =$currlistid]"/>
+ <xsl:if test="not(ancestor::字:段落/preceding-sibling::字:段落[1]/字:段落属性/字:自动编号信息/@字:编号引用= $currlistid)">
+ <xsl:element name="text:list-style">
+ <xsl:attribute name="style:name">List<xsl:value-of select="count(preceding::字:自动编号信息)"/></xsl:attribute>
+ <xsl:for-each select="$rootlist">
+ <xsl:call-template name="自动编号"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </office:automatic-styles>
+ <office:master-styles>
+ <xsl:apply-templates select="uof:演示文稿/演:主体/演:母版集"/>
+ </office:master-styles>
+ <office:body>
+ <office:presentation>
+ <xsl:apply-templates select="uof:演示文稿/演:主体/演:幻灯片集"/>
+ <xsl:apply-templates select="uof:演示文稿/演:公用处理规则/演:放映设置"/>
+ </office:presentation>
+ </office:body>
+ </office:document>
+ </xsl:template>
+ <xsl:template match="演:放映设置">
+ <presentation:settings>
+ <xsl:variable name="start-page">
+ <xsl:choose>
+ <xsl:when test="contains(演:幻灯片序列,' ')">
+ <xsl:value-of select="substring-before(演:幻灯片序列,' ')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="演:幻灯片序列"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="first-page">
+ <xsl:value-of select="/uof:UOF/uof:演示文稿/演:主体/演:幻灯片集/演:幻灯片[1]/@演:名称"/>
+ </xsl:variable>
+ <xsl:if test="not($start-page = $first-page)">
+ <xsl:attribute name="presentation:start-page"><xsl:value-of select="$start-page"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:全屏放映='false'">
+ <xsl:attribute name="presentation:full-screen">false</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:循环放映='true'">
+ <xsl:attribute name="presentation:endless">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:放映间隔">
+ <xsl:attribute name="presentation:pause"><xsl:variable name="OOtime"><xsl:value-of select="substring-after(演:放映间隔,'P0Y0M0DT')"/></xsl:variable><xsl:value-of select="concat('PT',$OOtime)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:手动方式='true'">
+ <xsl:attribute name="presentation:force-manual">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:导航帮助='true'">
+ <xsl:attribute name="presentation:start-with-navigator">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:放映动画='false'">
+ <xsl:attribute name="presentation:animations">disabled</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:前端显示='true'">
+ <xsl:attribute name="presentation:stay-on-top">true</xsl:attribute>
+ </xsl:if>
+ </presentation:settings>
+ </xsl:template>
+ <xsl:template name="自动编号">
+ <xsl:for-each select="字:级别">
+ <xsl:choose>
+ <xsl:when test="字:项目符号">
+ <xsl:call-template name="xiangmufuhao">
+ <xsl:with-param name="biaoshifu" select="../@字:标识符"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="字:图片符号引用">
+ <xsl:call-template name="imagefuhao">
+ <xsl:with-param name="biaoshifu" select="../@字:标识符"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="jibianhao">
+ <xsl:with-param name="biaoshifu" select="../@字:标识符"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="编号字体">
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号">
+ <xsl:if test="字:级别/字:符号字体">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="concat( @字:标识符,字:级别/@字:级别值)"/></xsl:attribute>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ <xsl:element name="style:text-properties">
+ <xsl:attribute name="fo:color"><xsl:value-of select="字:级别/字:符号字体/字:字体/@字:颜色"/></xsl:attribute>
+ <xsl:if test="字:级别/字:符号字体/字:粗体 and 字:级别/字:符号字体/字:粗体/@字:值='true'">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="style:font-style-asian">bold</xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="ziti">
+ <xsl:value-of select="字:级别/字:符号字体/字:字体/@字:中文字体引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:字体集/uof:字体声明">
+ <xsl:if test="@uof:标识符=$ziti">
+ <xsl:attribute name="style:font-name"><xsl:value-of select="@uof:名称"/></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:attribute name="fo:font-style">normal</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">normal</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="uof:对象集">
+ <xsl:apply-templates select="图:图形"/>
+ <xsl:apply-templates select="图:图形/图:文本内容/字:段落/字:句/字:句属性" mode="style"/>
+ </xsl:template>
+ <xsl:variable name="uofUnit">
+ <xsl:variable name="uu">
+ <xsl:value-of select="/uof:UOF/uof:演示文稿/演:公用处理规则/演:度量单位"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$uu='cm'">cm</xsl:when>
+ <xsl:when test="$uu='mm'">mm</xsl:when>
+ <xsl:when test="$uu='pt'">pt</xsl:when>
+ <xsl:when test="$uu='inch'">inch</xsl:when>
+ <xsl:otherwise>pt</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="other-to-cm-conversion-factor">
+ <xsl:choose>
+ <xsl:when test="$uofUnit='cm'">1</xsl:when>
+ <xsl:when test="$uofUnit='mm'">0.1</xsl:when>
+ <xsl:when test="$uofUnit='pt'">0.03527</xsl:when>
+ <xsl:when test="$uofUnit='inch'">2.54</xsl:when>
+ <xsl:when test="$uofUnit='pica'">0.4233</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:key match="/uof:UOF/uof:演示文稿/演:主体/演:母版集/演:母版/uof:锚点 | /uof:UOF/uof:演示文稿/演:主体/演:幻灯片集/演:幻灯片/uof:锚点 | /uof:UOF/uof:演示文稿/演:主体/演:幻灯片集/演:幻灯片/演:幻灯片备注/uof:锚点" name="rel_graphic_name" use="@uof:图形引用"/>
+ <xsl:template match="图:图形">
+ <xsl:variable name="random-name">
+ <xsl:value-of select="generate-id()"/>
+ </xsl:variable>
+ <xsl:variable name="draw-name">
+ <xsl:value-of select="substring($random-name,string-length($random-name)-1)"/>
+ </xsl:variable>
+ <xsl:call-template name="graphic-fill">
+ <xsl:with-param name="draw-name" select="$draw-name"/>
+ <xsl:with-param name="gradient-name" select="图:预定义图形/图:属性/图:填充/图:渐变"/>
+ </xsl:call-template>
+ <xsl:variable name="biaozhifu" select="@图:标识符"/>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:渐变">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family"><xsl:choose><xsl:when test="图:预定义图形/图:类别='3' or 图:预定义图形/图:类别='67'">presentation</xsl:when><xsl:otherwise>graphic</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="/uof:UOF/uof:演示文稿/演:主体/演:母版集/演:母版/uof:锚点[@uof:图形引用=$biaozhifu]">
+ <xsl:variable name="duan" select="图:文本内容/字:段落/字:段落属性/@字:式样引用"/>
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="/uof:UOF/uof:式样集/uof:段落式样[@字:标识符=$duan]/@字:基式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:graphic-properties">
+ <xsl:call-template name="process-graphics">
+ <xsl:with-param name="draw-name" select="$draw-name"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family"><xsl:choose><xsl:when test="图:预定义图形/图:类别='3' or 图:预定义图形/图:类别='67'">presentation</xsl:when><xsl:otherwise>graphic</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="/uof:UOF/uof:演示文稿/演:主体/演:母版集/演:母版/uof:锚点[@uof:图形引用=$biaozhifu]">
+ <xsl:variable name="duan" select="图:文本内容/字:段落/字:段落属性/@字:式样引用"/>
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="/uof:UOF/uof:式样集/uof:段落式样[@字:标识符=$duan]/@字:基式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:graphic-properties">
+ <xsl:if test="@图:其他对象">
+ <xsl:attribute name="fo:clip">rect(0cm 0cm 0cm 0cm)</xsl:attribute>
+ <xsl:attribute name="draw:color-mode">standard</xsl:attribute>
+ <xsl:attribute name="draw:luminance">0%</xsl:attribute>
+ <xsl:attribute name="draw:contrast">0%</xsl:attribute>
+ <xsl:attribute name="draw:gamma">100%</xsl:attribute>
+ <xsl:attribute name="draw:red">0%</xsl:attribute>
+ <xsl:attribute name="draw:green">0%</xsl:attribute>
+ <xsl:attribute name="draw:blue">0%</xsl:attribute>
+ <xsl:attribute name="draw:image-opacity">100%</xsl:attribute>
+ <xsl:attribute name="style:mirror">none</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-graphics"/>
+ </xsl:element>
+ <xsl:if test="图:文本内容/@图:文字排列方向='vert-r2l' or 图:文本内容/@图:文字排列方向='vert-l2r'">
+ <xsl:element name="style:paragraph-properties">
+ <xsl:attribute name="style:writing-mode">tb-rl</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="process-graphics">
+ <xsl:param name="draw-name"/>
+ <xsl:if test="not(key('rel_graphic_name',@图:标识符)/@uof:随动方式='movesize')">
+ <xsl:attribute name="style:protect"><xsl:choose><xsl:when test="key('rel_graphic_name',@图:标识符)/@uof:随动方式='move'">size</xsl:when><xsl:otherwise>position size</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="not(图:预定义图形/图:属性/图:填充)">
+ <xsl:attribute name="draw:fill">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图片">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-image-name"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"/></xsl:attribute>
+ <xsl:if test="not(图:预定义图形/图:属性/图:填充/图:图片/@图:位置='title')">
+ <xsl:attribute name="style:repeat"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:位置='center'">no-repeat</xsl:when><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:位置='stretch'">stretch</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图案">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:前景色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:颜色">
+ <xsl:attribute name="draw:fill">solid</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:颜色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:渐变">
+ <xsl:attribute name="draw:fill">gradient</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:渐变/@图:起始色"/></xsl:attribute>
+ <xsl:attribute name="draw:fill-gradient-name"><xsl:value-of select="concat('Gradient ',$draw-name)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="图:预定义图形/图:属性/图:线颜色">
+ <xsl:attribute name="svg:stroke-color"><xsl:value-of select="图:预定义图形/图:属性/图:线颜色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:线型 and not(图:预定义图形/图:属性/图:线型 = 'single') and not(图:预定义图形/图:属性/图:线型 = 'thick')">
+ <xsl:variable name="linetype" select="图:预定义图形/图:属性/图:线型"/>
+ <xsl:attribute name="draw:stroke"><xsl:choose><xsl:when test="$linetype='none'">none</xsl:when><xsl:otherwise>dash</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="draw:stroke-dash"><xsl:choose><xsl:when test="$linetype='dot-dot-dash' or $linetype='dash-dot-dot-heavy'">_32__20_Dots_20_1_20_Dash</xsl:when><xsl:when test="$linetype='dash' or $linetype='dashed-heavy'">Ultrafine_20_Dashed</xsl:when><xsl:when test="$linetype='dotted' or $linetype='dotted-heavy'">Ultrafine_20_Dotted_20__28_var_29_</xsl:when><xsl:when test="$linetype='double'">Line_20_with_20_Fine_20_Dots</xsl:when><xsl:when test="$linetype='dot-dash' or $linetype='dash-dot-heavy'">_33__20_Dashes_20_3_20_Dots_20__28_var_29_</xsl:when><xsl:when test="$linetype='wave' or $linetype='wavy-heavy'">Ultrafine_20_2_20_Dots_20_3_20_Dashes</xsl:when><xsl:when test="$linetype='wavy-double'">Fine_20_Dashed_20__28_var_29_</xsl:when><xsl:otherwise>Fine Dashed</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:线粗细">
+ <xsl:attribute name="svg:stroke-width"><xsl:value-of select="concat(图:预定义图形/图:属性/图:线粗细,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头">
+ <xsl:attribute name="draw:marker-start"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">Line_20_Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">Arrow_20_concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">Square_20_45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头/图:大小">
+ <xsl:attribute name="draw:marker-start-width"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '1'"><xsl:value-of select="concat('0.05',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '2'"><xsl:value-of select="concat('0.10',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '3'"><xsl:value-of select="concat('0.15',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '4'"><xsl:value-of select="concat('0.20',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '5'"><xsl:value-of select="concat('0.25',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '6'"><xsl:value-of select="concat('0.30',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '7'"><xsl:value-of select="concat('0.35',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '8'"><xsl:value-of select="concat('0.40',$uofUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('0.45',$uofUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头">
+ <xsl:attribute name="draw:marker-end"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">Line_20_Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">Arrow_20_concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">Square_20_45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头/图:大小">
+ <xsl:attribute name="draw:marker-end-width"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '1'"><xsl:value-of select="concat('0.05',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '2'"><xsl:value-of select="concat('0.10',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '3'"><xsl:value-of select="concat('0.15',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '4'"><xsl:value-of select="concat('0.20',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '5'"><xsl:value-of select="concat('0.25',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '6'"><xsl:value-of select="concat('0.30',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '7'"><xsl:value-of select="concat('0.35',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '8'"><xsl:value-of select="concat('0.40',$uofUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('0.45',$uofUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:透明度">
+ <xsl:attribute name="draw:opacity"><xsl:variable name="opacity"><xsl:value-of select="./图:预定义图形/图:属性/图:透明度"/></xsl:variable><xsl:value-of select="concat((1 - $opacity)*100,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:for-each select="图:文本内容">
+ <xsl:if test="@图:上边距">
+ <xsl:attribute name="fo:padding-top"><xsl:value-of select="concat(@图:上边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-bottom"><xsl:value-of select="concat(@图:下边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-left"><xsl:value-of select="concat(@图:左边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-right"><xsl:value-of select="concat(@图:右边距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(@图:文字排列方向='middle')">
+ <xsl:variable name="hori-or-vert" select="@图:文字排列方向"/>
+ <xsl:choose>
+ <xsl:when test="$hori-or-vert='vert-l2r'">
+ <xsl:attribute name="draw:textarea-vertical-align">bottom</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$hori-or-vert='hori-l2r'">
+ <xsl:attribute name="draw:textarea-horizontal-align">left</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$hori-or-vert='hori-r2l'">
+ <xsl:attribute name="draw:textarea-horizontal-align">right</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$hori-or-vert"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@图:自动换行">
+ <xsl:attribute name="fo:wrap-option">no-wrap</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:auto-grow-width"><xsl:choose><xsl:when test="@图:大小适应文字">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="bina_graphic">
+ <xsl:param name="refGraphic"/>
+ <xsl:element name="office:binary-data">
+ <xsl:for-each select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符 = $refGraphic]">
+ <xsl:value-of select="uof:数据"/>
+ </xsl:for-each>
+ </xsl:element>
+ <text:p/>
+ </xsl:template>
+ <xsl:template name="graphic-fill">
+ <xsl:param name="draw-name"/>
+ <xsl:param name="gradient-name"/>
+ <xsl:if test="图:预定义图形/图:属性/图:填充/图:渐变">
+ <xsl:element name="draw:gradient">
+ <xsl:attribute name="draw:name"><xsl:value-of select="concat('Gradient ',$draw-name)"/></xsl:attribute>
+ <xsl:attribute name="draw:style"><xsl:choose><xsl:when test="$gradient-name/@图:种子类型='linear'"><xsl:value-of select="'linear'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='radar'"><xsl:value-of select="'radial'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='oval'"><xsl:value-of select="'ellipsoid'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='square'"><xsl:value-of select="'square'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='rectangle'"><xsl:value-of select="'rectangular'"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="draw:start-color"><xsl:value-of select="$gradient-name/@图:起始色"/></xsl:attribute>
+ <xsl:attribute name="draw:end-color"><xsl:value-of select="$gradient-name/@图:终止色"/></xsl:attribute>
+ <xsl:attribute name="draw:start-intensity"><xsl:value-of select="concat($gradient-name/@图:起始浓度,'%')"/></xsl:attribute>
+ <xsl:attribute name="draw:end-intensity"><xsl:value-of select="concat($gradient-name/@图:终止浓度,'%')"/></xsl:attribute>
+ <xsl:attribute name="draw:angle"><xsl:value-of select="$gradient-name/@图:渐变方向 * 10"/></xsl:attribute>
+ <xsl:attribute name="draw:border"><xsl:value-of select="concat($gradient-name/@图:边界,'%')"/></xsl:attribute>
+ <xsl:if test="$gradient-name/@图:种子X位置">
+ <xsl:attribute name="draw:cx"><xsl:value-of select="concat($gradient-name/@图:种子X位置,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$gradient-name/@图:种子Y位置">
+ <xsl:attribute name="draw:cy"><xsl:value-of select="concat($gradient-name/@图:种子Y位置,'%')"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头">
+ <xsl:element name="draw:marker">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">Line_20_Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">Arrow_20_concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">Square_20_45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">
+ <xsl:attribute name="svg:viewBox">0 0 20 30</xsl:attribute>
+ <xsl:attribute name="svg:d">m10 0-10 30h20z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">
+ <xsl:attribute name="svg:viewBox">0 0 1122 2243</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1580</xsl:attribute>
+ <xsl:attribute name="svg:d">m1013 1491 118 89-567-1580-564 1580 114-85 136-68 148-46 161-17 161 13 153 46z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m462 1118-102-29-102-51-93-72-72-93-51-102-29-102-13-105 13-102 29-106 51-102 72-89 93-72 102-50 102-34 106-9 101 9 106 34 98 50 93 72 72 89 51 102 29 106 13 102-13 105-29 102-51 102-72 93-93 72-98 51-106 29-101 13z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 564 564 567 567-567-567-564z</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头">
+ <xsl:element name="draw:marker">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">Line_20_Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">Arrow_20_concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">Square_20_45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">
+ <xsl:attribute name="svg:viewBox">0 0 20 30</xsl:attribute>
+ <xsl:attribute name="svg:d">m10 0-10 30h20z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">
+ <xsl:attribute name="svg:viewBox">0 0 1122 2243</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1580</xsl:attribute>
+ <xsl:attribute name="svg:d">m1013 1491 118 89-567-1580-564 1580 114-85 136-68 148-46 161-17 161 13 153 46z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m462 1118-102-29-102-51-93-72-72-93-51-102-29-102-13-105 13-102 29-106 51-102 72-89 93-72 102-50 102-34 106-9 101 9 106 34 98 50 93 72 72 89 51 102 29 106 13 102-13 105-29 102-51 102-72 93-93 72-98 51-106 29-101 13z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 564 564 567 567-567-567-564z</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用 or 图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用">
+ <xsl:element name="draw:fill-image">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:类型"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:call-template name="bina_graphic">
+ <xsl:with-param name="refGraphic">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用">
+ <xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用"/>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用">
+ <xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="not(图:预定义图形/图:属性/图:线型='single') and not(图:预定义图形/图:属性/图:线型='thick') and 图:预定义图形/图:属性/图:线型">
+ <xsl:variable name="line" select="图:预定义图形/图:属性/图:线型"/>
+ <xsl:element name="draw:stroke-dash">
+ <xsl:choose>
+ <xsl:when test="$line='dash-long' or $line='dash-long-heavy'">
+ <xsl:attribute name="draw:name">Fine_20_Dashed</xsl:attribute>
+ <xsl:attribute name="draw:display-name">Fine dashed</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">0.508cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">1</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.508cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.508cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='dot-dot-dash' or $line='dash-dot-dot-heavy'">
+ <xsl:attribute name="draw:name">_32__20_Dots_20_1_20_Dash</xsl:attribute>
+ <xsl:attribute name="draw:display-name">2 Dots 1 Dash</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">2</xsl:attribute>
+ <xsl:attribute name="draw:dots2">1</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.203cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.203cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='dash' or $line='dashed-heavy'">
+ <xsl:attribute name="draw:name">Ultrafine_20_Dashed</xsl:attribute>
+ <xsl:attribute name="draw:display-name">Ultrafine Dashed</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">0.051cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">1</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.051cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.051cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='dotted' or $line='dotted-heavy'">
+ <xsl:attribute name="draw:name">Ultrafine_20_Dotted_20__28_var_29_</xsl:attribute>
+ <xsl:attribute name="draw:display-name">Ultrafine Dotted (var)</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:distance">50%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='wave' or $line='wavy-heavy'">
+ <xsl:attribute name="draw:name">Ultrafine_20_2_20_Dots_20_3_20_Dashes</xsl:attribute>
+ <xsl:attribute name="draw:display-name">Ultrafine 2 Dots 3 Dashes</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">2</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">0.051cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">3</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.254cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.127cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='dot-dash' or $line='dash-dot-heavy'">
+ <xsl:attribute name="draw:name">_33__20_Dashes_20_3_20_Dots_20__28_var_29_</xsl:attribute>
+ <xsl:attribute name="draw:display-name">3 Dashes 3 Dots (var)</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">3</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">197%</xsl:attribute>
+ <xsl:attribute name="draw:dots2">3</xsl:attribute>
+ <xsl:attribute name="draw:distance">100%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='double'">
+ <xsl:attribute name="draw:name">Line_20_with_20_Fine_20_Dots</xsl:attribute>
+ <xsl:attribute name="draw:display-name">Line with Fine Dots</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">2.007cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">10</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.152cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='wavy-double'">
+ <xsl:attribute name="draw:name">Fine_20_Dashed_20__28_var_29_</xsl:attribute>
+ <xsl:attribute name="draw:display-name">Fine Dashed (var)</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">197%</xsl:attribute>
+ <xsl:attribute name="draw:distance">197%</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="draw:name">Fine Dashed</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">0.508cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">1</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.508cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.508cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-page-master">
+ <xsl:param name="impressoptions"/>
+ <xsl:for-each select="$impressoptions">
+ <xsl:element name="style:page-layout">
+ <xsl:attribute name="style:name"><xsl:call-template name="encode-as-nc-name"><xsl:with-param name="string" select="@演:标识符"/></xsl:call-template></xsl:attribute>
+ <xsl:element name="style:page-layout-properties">
+ <xsl:if test="演:纸张/@uof:宽度">
+ <xsl:attribute name="fo:page-width"><xsl:value-of select="concat(演:纸张/@uof:宽度,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:纸张/@uof:高度">
+ <xsl:attribute name="fo:page-height"><xsl:value-of select="concat((演:纸张/@uof:高度),$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:页边距">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(演:页边距/@uof:上,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(演:页边距/@uof:下,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(演:页边距/@uof:左,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(演:页边距/@uof:右,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="演:纸张方向 = 'landscape'">
+ <xsl:attribute name="style:print-orientation">landscape</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:print-orientation">portrait</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="encode-as-nc-name">
+ <xsl:param name="string"/>
+ <xsl:value-of select="translate($string, '. %()/\+', '')"/>
+ </xsl:template>
+ <xsl:key name="tianchongmu" match="/uof:UOF/uof:演示文稿/演:主体/演:母版集/演:母版" use="@演:配色方案引用"/>
+ <xsl:key name="tianchonghuan" match="/uof:UOF/uof:演示文稿/演:主体/演:幻灯片集/演:幻灯片" use="@演:标识符"/>
+ <xsl:template match="演:配色方案">
+ <xsl:if test="key('tianchongmu',@演:标识符)/演:背景">
+ <xsl:for-each select="key('tianchongmu',@演:标识符)/演:背景">
+ <xsl:call-template name="officestyle"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="key('tianchonghuan',@演:标识符)/演:背景">
+ <xsl:for-each select="key('tianchonghuan',@演:标识符)/演:背景">
+ <xsl:call-template name="officestyle"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:family">drawing-page</xsl:attribute>
+ <xsl:attribute name="style:name"><xsl:value-of select="@演:标识符"/></xsl:attribute>
+ <xsl:element name="style:drawing-page-properties">
+ <xsl:if test="演:填充">
+ <xsl:attribute name="draw:fill">solid</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="演:背景色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:背景色">
+ <xsl:attribute name="draw:background-size">border</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:阴影">
+ <xsl:attribute name="draw:shadow">visible</xsl:attribute>
+ <xsl:attribute name="draw:shadow-color"><xsl:value-of select="演:阴影"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:文本和线条">
+ <xsl:attribute name="svg:stroke-color"><xsl:value-of select="演:文本和线条"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="key('tianchongmu',@演:标识符)/演:背景">
+ <xsl:for-each select="key('tianchongmu',@演:标识符)/演:背景">
+ <xsl:call-template name="background"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="key('tianchonghuan',@演:标识符)/演:背景">
+ <xsl:for-each select="key('tianchonghuan',@演:标识符)/演:背景">
+ <xsl:call-template name="background"/>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:element>
+ <xsl:variable name="style-name">
+ <xsl:value-of select="@演:标识符"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:演示文稿/演:主体/演:幻灯片集/演:幻灯片[@演:标识符=$style-name]/演:切换">
+ <style:drawing-page-properties>
+ <xsl:if test="@演:速度='slow'">
+ <xsl:attribute name="presentation:transition-speed">slow</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(@演:效果 = 'none')">
+ <xsl:variable name="effect">
+ <xsl:value-of select="@演:效果"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$effect='box in'">
+ <xsl:attribute name="smil:type">irisWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">rectangle</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='box out'">
+ <xsl:attribute name="smil:type">irisWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">rectangle</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='checkerboard across'">
+ <xsl:attribute name="smil:type">checkerBoardWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">across</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='checkerboard down'">
+ <xsl:attribute name="smil:type">checkerBoardWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">down</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='comb horizontal'">
+ <xsl:attribute name="smil:type">pushWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">combHorizontal</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='comb vertical'">
+ <xsl:attribute name="smil:type">pushWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">combVertical</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='uncover down'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromTop</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='uncover left'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromRight</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='uncover right'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromLeft</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='uncover up'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromBottom</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='uncover left-down'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromTopRight</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='uncover left-up'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromBottomRight</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='uncover right-down'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromTopLeft</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='uncover right-up'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromBottomLeft</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='cover down'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromTop</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='cover left'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromRight</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='cover right'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromLeft</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='cover up'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromBottom</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='cover left-down'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromTopRight</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='cover left-up'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromBottomRight</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='cover right-down'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromTopLeft</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='cover right-up'">
+ <xsl:attribute name="smil:type">slideWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromBottomLeft</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='fade through black'">
+ <xsl:attribute name="smil:type">fade</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fadeOverColor</xsl:attribute>
+ <xsl:attribute name="smil:fadeColor">#000000</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='push down'">
+ <xsl:attribute name="smil:type">pushWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromTop</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='push left'">
+ <xsl:attribute name="smil:type">pushWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromRight</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='push right'">
+ <xsl:attribute name="smil:type">pushWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromLeft</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='push up'">
+ <xsl:attribute name="smil:type">pushWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fromBottom</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='random bars horizontal'">
+ <xsl:attribute name="smil:type">randomBarWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">horizontal</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='random bars vertical'">
+ <xsl:attribute name="smil:type">randomBarWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">vertical</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='shape circle'">
+ <xsl:attribute name="smil:type">ellipseWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">circle</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='shape diamond'">
+ <xsl:attribute name="smil:type">irisWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">diamond</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='shape plus'">
+ <xsl:attribute name="smil:type">fourBoxWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">cornersOut</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='split horizontal in'">
+ <xsl:attribute name="smil:type">barnDoorWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">horizontal</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='split horizontal out'">
+ <xsl:attribute name="smil:type">barnDoorWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">horizontal</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='split vertical in'">
+ <xsl:attribute name="smil:type">barnDoorWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">vertical</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='split vertical out'">
+ <xsl:attribute name="smil:type">barnDoorWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">vertical</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wedge'">
+ <xsl:attribute name="smil:type">fanWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">centerTop</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wheel clockwise – 1 spoke'">
+ <xsl:attribute name="smil:type">pinWheelWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">oneBlade</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wheel clockwise – 2 spoke'">
+ <xsl:attribute name="smil:type">pinWheelWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">twoBladeVertical</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wheel clockwise – 3 spoke'">
+ <xsl:attribute name="smil:type">pinWheelWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">threeBlade</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wheel clockwise – 4 spoke'">
+ <xsl:attribute name="smil:type">pinWheelWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">fourBlade</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wheel clockwise – 8 spoke'">
+ <xsl:attribute name="smil:type">pinWheelWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">eightBlade</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wipe left'">
+ <xsl:attribute name="smil:type">barWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">leftToRight</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wipe right'">
+ <xsl:attribute name="smil:type">barWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">leftToRight</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wipe up'">
+ <xsl:attribute name="smil:type">barWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">topToBottom</xsl:attribute>
+ <xsl:attribute name="smil:direction">reverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='wipe down'">
+ <xsl:attribute name="smil:type">barWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">topToBottom</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='blinds vertical'">
+ <xsl:attribute name="smil:type">blindsWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">vertical</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='blinds horizontal'">
+ <xsl:attribute name="smil:type">blindsWipe</xsl:attribute>
+ <xsl:attribute name="smil:subtype">horizontal</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='dissolve'">
+ <xsl:attribute name="smil:type">dissolve</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$effect='random transition'">
+ <xsl:attribute name="smil:type">random</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="演:方式/演:单击鼠标='false'">
+ <xsl:attribute name="presentation:transition-type">automatic</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:方式/演:时间间隔">
+ <xsl:attribute name="presentation:duration"><xsl:value-of select="concat('PT00H00M',演:方式/演:时间间隔,'S')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="(演:声音/@演:预定义声音 and not(演:声音/@演:预定义声音='none')) or 演:声音/@演:自定义声音">
+ <xsl:choose>
+ <xsl:when test="演:声音/@演:预定义声音">
+ <xsl:variable name="voice">
+ <xsl:value-of select="演:声音/@演:预定义声音"/>
+ </xsl:variable>
+ <presentation:sound xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">
+ <xsl:attribute name="xlink:href"><xsl:choose><xsl:when test="$voice='applause'">../../../../../../../softwware/Redoffcie%203.0/share/gallery/sounds/applause.wav</xsl:when><xsl:when test="$voice='explosion'">../../../../../../../softwware/Redoffcie%203.0/share/gallery/sounds/explos.wav</xsl:when><xsl:when test="$voice='laser'">../../../../../../../softwware/Redoffcie%203.0/share/gallery/sounds/laser.wav</xsl:when><xsl:otherwise><xsl:value-of select="演:声音/@演:预定义声音"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </presentation:sound>
+ </xsl:when>
+ <xsl:otherwise>
+ <presentation:sound xlink:type="simple" xlink:show="new" xlink:actuate="onRequest">
+ <xsl:attribute name="xlink:href"><xsl:value-of select="演:声音/@演:自定义声音"/></xsl:attribute>
+ </presentation:sound>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </style:drawing-page-properties>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="officestyle">
+ <xsl:variable name="random-name">
+ <xsl:value-of select="generate-id()"/>
+ </xsl:variable>
+ <xsl:variable name="draw-name">
+ <xsl:value-of select="substring($random-name,string-length($random-name)-1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="图:渐变">
+ <xsl:element name="draw:gradient">
+ <xsl:attribute name="draw:name"><xsl:value-of select="concat('Gradient ',$draw-name)"/></xsl:attribute>
+ <xsl:attribute name="draw:style"><xsl:choose><xsl:when test="图:渐变/@图:种子类型='linear'"><xsl:value-of select="'linear'"/></xsl:when><xsl:when test="图:渐变/@图:种子类型='radar'"><xsl:value-of select="'radial'"/></xsl:when><xsl:when test="图:渐变/@图:种子类型='oval'"><xsl:value-of select="'ellipsoid'"/></xsl:when><xsl:when test="图:渐变/@图:种子类型='square'"><xsl:value-of select="'square'"/></xsl:when><xsl:when test="图:渐变/@图:种子类型='rectangle'"><xsl:value-of select="'rectangular'"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="draw:start-color"><xsl:value-of select="图:渐变/@图:起始色"/></xsl:attribute>
+ <xsl:attribute name="draw:end-color"><xsl:value-of select="图:渐变/@图:终止色"/></xsl:attribute>
+ <xsl:attribute name="draw:start-intensity"><xsl:value-of select="concat(图:渐变/@图:起始浓度,'%')"/></xsl:attribute>
+ <xsl:attribute name="draw:end-intensity"><xsl:value-of select="concat(图:渐变/@图:终止浓度,'%')"/></xsl:attribute>
+ <xsl:attribute name="draw:angle"><xsl:value-of select="图:渐变/@图:渐变方向 * 10"/></xsl:attribute>
+ <xsl:attribute name="draw:border"><xsl:value-of select="concat(图:渐变/@图:边界,'%')"/></xsl:attribute>
+ <xsl:if test="图:渐变/@图:种子X位置">
+ <xsl:attribute name="draw:cx"><xsl:value-of select="concat(图:渐变/@图:种子X位置,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:渐变/@图:种子Y位置">
+ <xsl:attribute name="draw:cy"><xsl:value-of select="concat(图:渐变/@图:种子Y位置,'%')"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="图:图片/@图:图形引用 or 图:图案/@图:图形引用">
+ <xsl:element name="draw:fill-image">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:图案/@图:图形引用"><xsl:value-of select="图:图案/@图:类型"/></xsl:when><xsl:when test="图:图片/@图:图形引用"><xsl:value-of select="图:图片/@图:名称"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:call-template name="bina_graphic">
+ <xsl:with-param name="refGraphic">
+ <xsl:choose>
+ <xsl:when test="图:图案/@图:图形引用">
+ <xsl:value-of select="图:图案/@图:图形引用"/>
+ </xsl:when>
+ <xsl:when test="图:图片/@图:图形引用">
+ <xsl:value-of select="图:图片/@图:图形引用"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="background">
+ <xsl:variable name="random-name">
+ <xsl:value-of select="generate-id()"/>
+ </xsl:variable>
+ <xsl:variable name="draw-name">
+ <xsl:value-of select="substring($random-name,string-length($random-name)-1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="图:图片">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-image-name"><xsl:value-of select="图:图片/@图:名称"/></xsl:attribute>
+ <xsl:if test="not(图:图片/@图:位置='title')">
+ <xsl:attribute name="style:repeat"><xsl:choose><xsl:when test="图:图片/@图:位置='center'">no-repeat</xsl:when><xsl:when test="图:图片/@图:位置='stretch'">stretch</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="图:图案">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:图案/@图:前景色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:颜色">
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:颜色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:渐变">
+ <xsl:attribute name="draw:fill">gradient</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:渐变/@图:起始色"/></xsl:attribute>
+ <xsl:attribute name="draw:fill-gradient-name"><xsl:value-of select="concat('Gradient ',$draw-name)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="演:母版集">
+ <draw:layer-set>
+ <draw:layer draw:name="layout"/>
+ <draw:layer draw:name="background"/>
+ <draw:layer draw:name="backgroundobjects"/>
+ <draw:layer draw:name="controls"/>
+ <draw:layer draw:name="measurelines"/>
+ </draw:layer-set>
+ <xsl:apply-templates select="演:母版"/>
+ </xsl:template>
+ <xsl:template match="演:母版">
+ <xsl:choose>
+ <xsl:when test="@演:类型 = 'handout' ">
+ <xsl:element name="style:handout-master">
+ <xsl:attribute name="style:name"><xsl:value-of select="@演:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:page-layout-name"><xsl:value-of select="@演:页面设置引用"/></xsl:attribute>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@演:配色方案引用"/></xsl:attribute>
+ <xsl:for-each select="uof:锚点[@uof:缩略图='true']">
+ <draw:page-thumbnail draw:layer="backgroundobjects">
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@uof:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ </draw:page-thumbnail>
+ </xsl:for-each>
+ <xsl:apply-templates select="uof:锚点[not(@uof:缩略图='true')]"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@演:类型 = 'slide'">
+ <xsl:element name="style:master-page">
+ <xsl:attribute name="style:name"><xsl:value-of select="@演:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:page-layout-name"><xsl:value-of select="@演:页面设置引用"/></xsl:attribute>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@演:配色方案引用"/></xsl:attribute>
+ <xsl:apply-templates select="uof:锚点 "/>
+ <xsl:for-each select="/uof:UOF/uof:演示文稿/演:主体/演:母版集/演:母版">
+ <xsl:if test="@演:类型 = 'notes'">
+ <xsl:element name="presentation:notes">
+ <xsl:attribute name="style:page-layout-name"><xsl:value-of select="@演:页面设置引用"/></xsl:attribute>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@演:配色方案引用"/></xsl:attribute>
+ <xsl:apply-templates select="uof:锚点 "/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="uof:句式样">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ <xsl:if test="@字:基式样引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:基式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="ancestor::字:段落式样">
+ <xsl:attribute name="style:family">paragraph</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="*"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="段落式样">
+ <xsl:element name="style:style">
+ <xsl:variable name="outline" select="@字:标识符"/>
+ <xsl:attribute name="style:family"><xsl:choose><xsl:when test="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号[@字:标识符=$outline]">presentation</xsl:when><xsl:otherwise>paragraph</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ <xsl:if test="@字:基式样引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:基式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号[@字:标识符=$outline]">
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号[@字:标识符=$outline]">
+ <style:graphic-properties draw:stroke="none" draw:fill="none">
+ <xsl:element name="text:list-style">
+ <xsl:call-template name="自动编号"/>
+ </xsl:element>
+ </style:graphic-properties>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:element name="style:paragraph-properties">
+ <xsl:if test="字:自动编号信息">
+ <xsl:attribute name="text:enable-numbering">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains($outline,'title')">
+ <xsl:attribute name="fo:text-align">center</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="paragraph-properties"/>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="*"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="paragraph-properties">
+ <xsl:choose>
+ <xsl:when test="descendant::字:页边距[@uof:左]">
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="number(((descendant::字:页边距/@uof:左)div 10) *1)"/>cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-left">0cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="descendant::字:页边距[@uof:右]">
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="number(((descendant::字:页边距/@uof:右)div 10) *1)"/>cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-right">0cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:text-indent">0cm</xsl:attribute>
+ <xsl:call-template name="bidi"/>
+ </xsl:template>
+ <xsl:template name="bidi">
+ </xsl:template>
+ <xsl:template name="jibianhao">
+ <xsl:param name="biaoshifu"/>
+ <xsl:element name="text:list-level-style-number">
+ <xsl:variable name="currlevel" select="number(@字:级别值)"/>
+ <xsl:attribute name="text:level"><xsl:value-of select="$currlevel"/></xsl:attribute>
+ <xsl:attribute name="text:style-name">Numbering Symbols</xsl:attribute>
+ <xsl:if test="字:起始编号">
+ <xsl:attribute name="text:start-value"><xsl:value-of select="字:起始编号"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:正规格式">
+ <xsl:attribute name="text:num-regular-exp"><xsl:value-of select="字:正规格式/@值"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="text:display-levels"><xsl:value-of select="string-length(字:编号格式表示) - string-length(translate(字:编号格式表示,'%','') )"/></xsl:attribute>
+ <xsl:if test="字:编号格式">
+ <xsl:call-template name="编号格式"/>
+ </xsl:if>
+ <xsl:if test="字:编号格式表示">
+ <xsl:attribute name="style:num-prefix"><xsl:choose><xsl:when test="number($currlevel) =1"><xsl:value-of select="substring-before(字:编号格式表示,concat('%',$currlevel))"/></xsl:when><xsl:otherwise><xsl:value-of select="substring-after(substring-after( substring-before(字:编号格式表示,concat('%',$currlevel)),concat('%',string(number($currlevel) -1))),'.')"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="substring-after(字:编号格式表示,concat('%',$currlevel))"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:list-level-properties">
+ <xsl:if test="@字:编号对齐方式">
+ <xsl:attribute name="fo:text-align"><xsl:value-of select="@字:编号对齐方式"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="suojinleixing"/>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:if test="字:符号字体">
+ <xsl:variable name="Font-ID">
+ <xsl:value-of select="字:符号字体/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样">
+ <xsl:if test="@字:标识符=$Font-ID">
+ <xsl:if test="字:字体/@字:中文字体引用">
+ <xsl:attribute name="fo:font-family"><xsl:value-of select="字:字体/@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="字:符号字体">
+ <xsl:apply-templates select="*"/>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="xiangmufuhao">
+ <xsl:param name="biaoshifu"/>
+ <xsl:variable name="currlevel" select="number(@字:级别值)"/>
+ <xsl:element name="text:list-level-style-bullet">
+ <xsl:attribute name="text:level"><xsl:value-of select="$currlevel"/></xsl:attribute>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat( $biaoshifu,$currlevel)"/></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="substring-after(字:编号格式表示,'%1')"/></xsl:attribute>
+ <xsl:attribute name="text:bullet-char"><xsl:value-of select="字:项目符号"/></xsl:attribute>
+ <xsl:element name="style:list-level-properties">
+ <xsl:if test="@字:编号对齐方式">
+ <xsl:attribute name="fo:text-align"><xsl:value-of select="@字:编号对齐方式"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="suojinleixing"/>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:if test="字:符号字体">
+ <xsl:variable name="Font-ID">
+ <xsl:value-of select="字:符号字体/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样[@字:标识符=$Font-ID]">
+ <xsl:if test="字:字体/@字:中文字体引用">
+ <xsl:attribute name="fo:font-family"><xsl:value-of select="字:字体/@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="字:符号字体">
+ <xsl:apply-templates select="*"/>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="suojinleixing">
+ <xsl:if test="字:缩进/字:左/字:绝对/@字:值">
+ <xsl:attribute name="text:space-before"><xsl:value-of select="concat(number(字:缩进/字:左/字:绝对/@字:值),$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:缩进/字:右/字:绝对/@字:值">
+ <xsl:attribute name="text:min-label-width"><xsl:value-of select="concat(number(字:缩进/字:右/字:绝对/@字:值),$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:缩进/字:首行/字:绝对/@字:值">
+ <xsl:attribute name="text:min-label-distance"><xsl:value-of select="concat(number(字:缩进/字:首行/字:绝对/@字:值),$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="imagefuhao">
+ <xsl:param name="biaoshifu"/>
+ <xsl:variable name="currlevel" select="number(@字:级别值)"/>
+ <xsl:element name="text:list-level-style-image" style:vertical-pos="middle" style:vertical-rel="line" fo:width="0.265cm" fo:height="0.265cm">
+ <xsl:attribute name="text:level"><xsl:value-of select="$currlevel"/></xsl:attribute>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat( $biaoshifu,$currlevel)"/></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="substring-after(字:编号格式表示,'%1')"/></xsl:attribute>
+ <xsl:if test="字:图片符号引用">
+ <xsl:variable name="gid">
+ <xsl:value-of select="字:图片符号引用"/>
+ </xsl:variable>
+ <xsl:element name="office:binary-data">
+ <xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$gid]/uof:数据"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="style:list-level-properties">
+ <xsl:attribute name="style:vertical-pos">middle</xsl:attribute>
+ <xsl:attribute name="style:vertical-rel">line</xsl:attribute>
+ <xsl:attribute name="fo:width"><xsl:value-of select="concat(字:图片符号引用/@字:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:height"><xsl:value-of select="concat(字:图片符号引用/@字:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="字:符号字体">
+ <xsl:variable name="Font-ID">
+ <xsl:value-of select="字:符号字体/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样">
+ <xsl:if test="@字:标识符=$Font-ID">
+ <xsl:if test="字:字体/@字:中文字体引用">
+ <xsl:attribute name="fo:font-family"><xsl:value-of select="字:字体/@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:call-template name="suojinleixing"/>
+ <xsl:if test="@字:编号对齐方式">
+ <xsl:attribute name="fo:text-align"><xsl:value-of select="@字:编号对齐方式"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:for-each select="字:符号字体">
+ <xsl:apply-templates select="*"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="编号格式">
+ <xsl:attribute name="style:num-format"><xsl:choose><xsl:when test="string(字:编号格式)='lower-letter'">a</xsl:when><xsl:when test="string(字:编号格式)='upper-letter'">A</xsl:when><xsl:when test="string(字:编号格式)='lower-roman'">i</xsl:when><xsl:when test="string(字:编号格式)='upper-roman'">I</xsl:when><xsl:when test="string(字:编号格式)='decimal-enclosed-circle'">①, ②, ③, ...</xsl:when><xsl:when test="string(字:编号格式)='ideograph-traditional'">甲, 乙, 丙, ...</xsl:when><xsl:when test="string(字:编号格式)='ideograph-zodiac'">子, 丑, 寅, ...</xsl:when><xsl:when test="string(字:编号格式)='chinese-counting'">一, 二, 三, ...</xsl:when><xsl:when test="string(字:编号格式)='chinese-legal-simplified'">壹, 贰, 叁, ...</xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="演:幻灯片集">
+ <xsl:for-each select="演:幻灯片">
+ <xsl:element name="draw:page">
+ <xsl:attribute name="draw:name"><xsl:value-of select="@演:名称"/></xsl:attribute>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@演:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:master-page-name"><xsl:value-of select="@演:母版引用"/></xsl:attribute>
+ <xsl:if test="@演:页面版式引用">
+ <xsl:attribute name="presentation:presentation-page-layout-name"><xsl:value-of select="@演:页面版式引用"/></xsl:attribute>
+ </xsl:if>
+ <office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
+ <xsl:apply-templates select="uof:锚点"/>
+ <xsl:apply-templates select="演:动画"/>
+ <xsl:element name="presentation:notes">
+ <xsl:attribute name="draw:style-name">dp2</xsl:attribute>
+ <xsl:apply-templates select="./演:幻灯片备注/uof:锚点"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="演:动画">
+ <xsl:element name="anim:par">
+ <xsl:attribute name="presentation:node-type">timing-root</xsl:attribute>
+ <anim:seq presentation:node-type="main-sequence">
+ <xsl:for-each select="演:序列">
+ <anim:par begin="next">
+ <anim:par smil:begin="0s">
+ <xsl:variable name="animnodename">anim:par</xsl:variable>
+ <xsl:choose>
+ <xsl:when test="演:效果//演:其他">
+ <xsl:copy-of select="演:效果//演:其他/*"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="{$animnodename}">
+ <xsl:attribute name="smil:fill"><xsl:choose><xsl:when test="演:定时/@演:回卷='true'">remove</xsl:when><xsl:otherwise>hold</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="演:增强/演:动画播放后/@演:播放后隐藏='true'">
+ <xsl:attribute name="presentation:preset-property">Direction;Accelerate;Decelerate</xsl:attribute>
+ </xsl:when>
+ <xsl:when test=".//演:轮子">
+ <xsl:attribute name="presentation:preset-property">Spokes</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:效果/演:强调/演:更改填充颜色">
+ <xsl:attribute name="presentation:preset-property">FillColor;ColorStyle;Accelerate;Decelerate;AutoReverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:效果/演:强调/演:更改字体颜色">
+ <xsl:attribute name="presentation:preset-property">CharColor;ColorStyle;Accelerate;Decelerate;AutoReverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:效果/演:强调/演:更改字号">
+ <xsl:attribute name="presentation:preset-property">CharHeight</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:效果/演:强调/演:更改字形">
+ <xsl:attribute name="presentation:preset-property">CharDecoration</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:效果/演:强调/演:陀螺旋">
+ <xsl:attribute name="presentation:preset-property">Rotate;Accelerate;Decelerate;AutoReverse</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:效果/演:强调/演:透明">
+ <xsl:attribute name="presentation:preset-property">Transparency</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:效果/演:强调/演:更改线条颜色">
+ <xsl:attribute name="presentation:preset-property">LineColor;ColorStyle;Accelerate;Decelerate;AutoReverse</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:attribute name="presentation:node-type"><xsl:choose><xsl:when test="演:定时/@演:事件='on click'">on-click</xsl:when><xsl:otherwise><xsl:value-of select="演:定时/@演:事件"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="smil:begin"><xsl:value-of select="演:定时/@演:延时"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="演:定时/@演:重复='until next click' ">
+ <xsl:attribute name="smil:repeatCount">indefinite</xsl:attribute>
+ <xsl:attribute name="smil:end">next</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:定时/@演:重复='until next slide' ">
+ <xsl:attribute name="smil:repeatCount">indefinite</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="演:定时/@演:重复 !='none'">
+ <xsl:attribute name="smil:repeatCount"><xsl:value-of select="演:定时/@演:重复"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="演:增强/演:动画文本/@演:发送">
+ <xsl:attribute name="anim:iterate-type"><xsl:choose><xsl:when test="演:增强/演:动画文本/@演:发送='by word'">by-word</xsl:when><xsl:when test="演:增强/演:动画文本/@演:发送='by letter'">by-letter</xsl:when><xsl:otherwise>all at once</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="演:增强/演:动画文本/@演:间隔">
+ <xsl:attribute name="anim:iterate-interval"><xsl:value-of select="演:增强/演:动画文本/@演:间隔"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$animnodename='anim:iterate' ">
+ <xsl:attribute name="anim:id"><xsl:value-of select="@演:动画对象"/></xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="演:效果"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </anim:par>
+ </anim:par>
+ </xsl:for-each>
+ </anim:seq>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="演:效果">
+ <xsl:apply-templates select="演:进入 "/>
+ <xsl:apply-templates select="演:强调"/>
+ <xsl:apply-templates select="演:退出"/>
+ </xsl:template>
+ <xsl:template match="演:进入">
+ <xsl:attribute name="presentation:preset-class">entrance</xsl:attribute>
+ <xsl:apply-templates select="." mode="entrance"/>
+ </xsl:template>
+ <xsl:template match="演:强调">
+ <xsl:attribute name="presentation:preset-class">emphasis</xsl:attribute>
+ <xsl:apply-templates select="." mode="emphasis"/>
+ </xsl:template>
+ <xsl:template match="演:退出">
+ <xsl:attribute name="presentation:preset-class">exit</xsl:attribute>
+ <xsl:apply-templates select="." mode="exit"/>
+ </xsl:template>
+ <xsl:template name="演速度">
+ <xsl:choose>
+ <xsl:when test="./@演:速度='very fast' ">0.5s</xsl:when>
+ <xsl:when test="./@演:速度='fast'">1s</xsl:when>
+ <xsl:when test="./@演:速度='medium'">2s</xsl:when>
+ <xsl:when test="./@演:速度='slow'">3s</xsl:when>
+ <xsl:when test="./@演:速度='very slow'">5s</xsl:when>
+ <xsl:otherwise>1s</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="演:出现" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-appear</xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.001s" smil:fill="hold" anim:sub-item="text" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:盒状" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-box</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.004s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="irisWipe" smil:subtype="rectangle" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:棋盘" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-checkerboard</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向='down'">downward</xsl:when><xsl:when test="@演:方向='across'">across</xsl:when></xsl:choose></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.004s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:dur="2s" anim:sub-item="text" smil:type="checkerBoardWipe" smil:subtype="down">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:圆形扩展" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-circle</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="ellipseWipe" smil:subtype="horizontal" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:阶梯状" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-diagonal-squares</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向='left down'">left-to-bottom</xsl:when><xsl:when test="@演:方向='left up'">left-to-top</xsl:when><xsl:when test="@演:方向='right down'">right-to-bottom</xsl:when><xsl:when test="@演:方向='right up'">right-to-top</xsl:when></xsl:choose></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="waterfallWipe" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向='left down'">horizontalLeft</xsl:when><xsl:when test="@演:方向='left up'">horizontalLeft</xsl:when><xsl:when test="@演:方向='right down'">horizontalRight</xsl:when><xsl:when test="@演:方向='right up'">horizontalRight</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:菱形" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-diamond</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="irisWipe" smil:subtype="diamond" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:内向溶解" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-dissolve-in</xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="dissolve" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:闪烁一次" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-flash-once</xsl:attribute>
+ <anim:set smil:begin="0s" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:飞入" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-fly-in</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向= 'from bottom'">from-bottom</xsl:when><xsl:when test="@演:方向 = 'from top-right'">from-top-right</xsl:when><xsl:when test="@演:方向 = 'from top-left'">from-top-left</xsl:when><xsl:when test="@演:方向 = 'from bottom-left'">from-bottom-left</xsl:when><xsl:when test="@演:方向 = 'from bottom-right'">from-bottom-right</xsl:when><xsl:when test="@演:方向 = 'from right'">from-right</xsl:when><xsl:when test="@演:方向 = 'from left'">from-left</xsl:when><xsl:when test="@演:方向 = 'from top'">from-top</xsl:when></xsl:choose></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <xsl:variable name="smilvalueX">
+ <xsl:choose>
+ <xsl:when test="contains(@演:方向,'right')">1+width/2;x</xsl:when>
+ <xsl:when test="contains(@演:方向,'left')">0-width/2;x</xsl:when>
+ <xsl:otherwise>x;x</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="smilvalueY">
+ <xsl:choose>
+ <xsl:when test="contains(@演:方向,'bottom')">1+height/2;y</xsl:when>
+ <xsl:when test="contains(@演:方向,'top')">0-height/2;y</xsl:when>
+ <xsl:otherwise>y;y</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <anim:animate smil:fill="hold" smil:attributeName="x" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:values"><xsl:value-of select="$smilvalueX"/></xsl:attribute>
+ </anim:animate>
+ <anim:animate smil:fill="hold" smil:attributeName="y" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:values"><xsl:value-of select="$smilvalueY"/></xsl:attribute>
+ </anim:animate>
+ </xsl:template>
+ <xsl:template match="演:缓慢飞入" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-fly-in-slow</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向= 'from bottom'">from-bottom</xsl:when><xsl:when test="@演:方向 = 'from right'">from-right</xsl:when><xsl:when test="@演:方向 = 'from left'">from-left</xsl:when><xsl:when test="@演:方向 = 'from top'">from-top</xsl:when></xsl:choose></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <xsl:variable name="smilvalueX">
+ <xsl:choose>
+ <xsl:when test="contains(@演:方向,'right')">1+width/2;x</xsl:when>
+ <xsl:when test="contains(@演:方向,'left')">0-width/2;x</xsl:when>
+ <xsl:otherwise>x;x</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="smilvalueY">
+ <xsl:choose>
+ <xsl:when test="contains(@演:方向,'bottom')">1+height/2;y</xsl:when>
+ <xsl:when test="contains(@演:方向,'top')">0-height/2;y</xsl:when>
+ <xsl:otherwise>y;y</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <anim:animate smil:fill="hold" smil:attributeName="x" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:values"><xsl:value-of select="$smilvalueX"/></xsl:attribute>
+ </anim:animate>
+ <anim:animate smil:fill="hold" smil:attributeName="y" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:values"><xsl:value-of select="$smilvalueY"/></xsl:attribute>
+ </anim:animate>
+ </xsl:template>
+ <xsl:template match="演:切入" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-peek-in</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向= 'from bottom'">from-bottom</xsl:when><xsl:when test="@演:方向 = 'from right'">from-right</xsl:when><xsl:when test="@演:方向 = 'from left'">from-left</xsl:when><xsl:when test="@演:方向 = 'from top'">from-top</xsl:when></xsl:choose></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="slideWipe" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向= 'from bottom'">fromBottom</xsl:when><xsl:when test="@演:方向 = 'from right'">fromRight</xsl:when><xsl:when test="@演:方向 = 'from left'">fromLeft</xsl:when><xsl:when test="@演:方向 = 'from top'">fromTop</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:十字形扩展" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-plus</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.00025s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="fourBoxWipe" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向= 'in'">cornersIn</xsl:when><xsl:when test="@演:方向 = 'out'">cornersOut</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:随机线条" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-bars</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.001s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="randomBarWipe" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向= 'horizontal'">vertical</xsl:when><xsl:when test="@演:方向 = 'vertical'">horizontal</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:劈裂" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-split</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向 = 'horizontal out'">horizontal-out</xsl:when><xsl:when test="@演:方向= 'horizontal in'">horizontal-in</xsl:when><xsl:when test="@演:方向= 'vertical in'">vertical-in</xsl:when><xsl:when test="@演:方向= 'vertical out'">vertical-out</xsl:when></xsl:choose></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.001s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:dur="0.5s" smil:type="barnDoorWipe">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向 = 'horizontal out'">horizontal</xsl:when><xsl:when test="@演:方向= 'horizontal in'">horizontal</xsl:when><xsl:when test="@演:方向= 'vertical in'">vertical</xsl:when><xsl:when test="@演:方向= 'vertical out'">vertical</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:百叶窗" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-venetian-blinds</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.001s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="blindsWipe" smil:direction="reverse">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向= 'horizontal'">vertical</xsl:when><xsl:when test="@演:方向 = 'vertical'">horizontal</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:扇形展开" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-wedge</xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.0015s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="fanWipe" smil:subtype="centerTop">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:轮子" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-wheel</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:辐射状"/></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.00025s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:dur="0.5s" smil:type="pinWheelWipe">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:辐射状='1'">oneBlade</xsl:when><xsl:when test="@演:辐射状='2'">twoBlade</xsl:when><xsl:when test="@演:辐射状='3'">threeBlade</xsl:when><xsl:when test="@演:辐射状='4'">fourBlade</xsl:when><xsl:when test="@演:辐射状='8'">eightBlade</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:擦除" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-wipe</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:速度 = 'from right'">from-right</xsl:when><xsl:when test="@演:速度 = 'from left'">from-left</xsl:when><xsl:when test="@演:速度 = 'from top'">from-top</xsl:when><xsl:when test="@演:速度 = 'from bottom'">from-bottom</xsl:when><xsl:otherwise>from-left</xsl:otherwise></xsl:choose></xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.006s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:transitionFilter smil:type="barWipe" smil:subtype="leftToRight" smil:direction="reverse">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="(@演:速度 = 'from right') or (@演:速度 = 'from left')">leftToRight</xsl:when><xsl:when test="(@演:速度 = 'from top') or (@演:速度 = 'from bottom')">topToBottom</xsl:when><xsl:otherwise>leftToRight</xsl:otherwise></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="演:随机效果" mode="entrance">
+ <xsl:attribute name="presentation:preset-id">ooo-entrance-random</xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.001s" smil:fill="hold" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ <anim:animate smil:dur="1s" smil:fill="hold" smil:attributeName="width" smil:values="0;width" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ </anim:animate>
+ <anim:animate smil:fill="hold" smil:attributeName="height" smil:values="0;height" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ </anim:animate>
+ <anim:animate smil:fill="hold" smil:attributeName="rotate" smil:values="90;0" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ </anim:animate>
+ <anim:transitionFilter smil:type="fade" smil:subtype="crossfade">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ </anim:transitionFilter>
+ </xsl:template>
+ <xsl:template match="更改填充颜色" mode="emphasis">
+ <xsl:attribute name="presentation:preset-id">ooo-emphasis-fill-color</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type">2</xsl:attribute>
+ <anim:animateColor smil:fill="hold" smil:attributeName="fill-color" presentation:additive="base" anim:color-interpolation="rgb" anim:color-interpolation-direction="clockwise">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:to"><xsl:value-of select="@演:颜色"/></xsl:attribute>
+ </anim:animateColor>
+ <anim:set smil:dur="0.5s" smil:fill="hold" smil:attributeName="fill" smil:to="solid">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="更改字体颜色" mode="emphasis">
+ <xsl:attribute name="presentation:preset-id">ooo-emphasis-font-color</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type">2</xsl:attribute>
+ <anim:animateColor smil:fill="hold" smil:attributeName="fill-color" presentation:additive="base" anim:color-interpolation="rgb" anim:color-interpolation-direction="clockwise">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:to"><xsl:value-of select="@演:颜色"/></xsl:attribute>
+ </anim:animateColor>
+ </xsl:template>
+ <xsl:template match="演:更改字号" mode="emphasis">
+ <xsl:attribute name="presentation:preset-id">ooo-emphasis-font-size</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type">2</xsl:attribute>
+ <anim:animate smil:fill="hold" smil:attributeName="font-size" presentation:additive="base">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:to"><xsl:choose><xsl:when test="@演:预定义尺寸='tiny' ">0.25,1</xsl:when><xsl:when test="@演:预定义尺寸='smaller' ">0.5,1</xsl:when><xsl:when test="@演:预定义尺寸='larger' ">1.5,1</xsl:when><xsl:when test="@演:预定义尺寸='huge' ">4,1</xsl:when><xsl:when test="@演:自定义尺寸"><xsl:value-of select="@演:自定义尺寸"/></xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:attribute>
+ </anim:animate>
+ </xsl:template>
+ <xsl:template name="emp_font_style">
+ <xsl:param name="fontstyle"/>
+ <xsl:choose>
+ <xsl:when test="contains($fontstyle,' ')">
+ <anim:set smil:dur="indefinite" smil:attributeName="font-style">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:to"><xsl:value-of select="substring-before($fontstyle,' ')"/></xsl:attribute>
+ </anim:set>
+ <xsl:variable name="fontstyle1">
+ <xsl:choose>
+ <xsl:when test="contains($fontstyle,' ')">
+ <xsl:value-of select="substring-after($fontstyle,' ')"/>
+ </xsl:when>
+ <xsl:when test="not($fontstyle=' ')">
+ <xsl:value-of select="$fontstyle"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="emp_font_style">
+ <xsl:with-param name="fontstyle">
+ <xsl:value-of select="$fontstyle1"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="演:更改字形" mode="emphasis">
+ <xsl:attribute name="presentation:preset-id">ooo-emphasis-font-style</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type">1</xsl:attribute>
+ <xsl:call-template name="emp_font_style">
+ <xsl:with-param name="fontstyle">
+ <xsl:value-of select="@演:字形"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template match="演:更改线条颜色" mode="emphasis">
+ <xsl:attribute name="presentation:preset-id">ooo-emphasis-line-color</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type">2</xsl:attribute>
+ <anim:animateColor smil:dur="0s" smil:fill="hold" smil:attributeName="stroke-color" presentation:additive="base" anim:color-interpolation="rgb" anim:color-interpolation-direction="clockwise">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:to"><xsl:value-of select="@演:颜色"/></xsl:attribute>
+ </anim:animateColor>
+ <anim:set smil:dur="0s" smil:fill="hold" anim:sub-item="text" smil:attributeName="stroke" smil:to="solid">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:陀螺旋" mode="emphasis">
+ <xsl:attribute name="presentation:preset-id">ooo-emphasis-spin</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type">2</xsl:attribute>
+ <anim:animateTransform smil:fill="hold" smil:by="180" presentation:additive="base" svg:type="rotate">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:by"><xsl:choose><xsl:when test="@演:预定义角度='quarter spin'">90</xsl:when><xsl:when test="@演:预定义角度='half spin'">180</xsl:when><xsl:when test="@演:预定义角度='full spin'">360</xsl:when><xsl:when test="@演:预定义角度='two spins'">720 </xsl:when><xsl:when test="@演:自定义角度"><xsl:value-of select="@演:自定义角度"/></xsl:when></xsl:choose></xsl:attribute>
+ </anim:animateTransform>
+ </xsl:template>
+ <xsl:template match="演:透明" mode="emphasis">
+ <xsl:attribute name="presentation:preset-id">ooo-emphasis-transparency</xsl:attribute>
+ <xsl:attribute name="smil:repeatCount"><xsl:choose><xsl:when test="(@演:期间 = 'until next click') or (@演:期间 ='until next slide') ">indefinite</xsl:when><xsl:when test="@演:期间='2' or @演:期间 ='3' or @演:期间 ='4' or @演:期间 ='5' or @演:期间 ='10'"><xsl:value-of select="@演:期间"/></xsl:when><xsl:otherwise>2</xsl:otherwise></xsl:choose></xsl:attribute>
+ <anim:set smil:dur="indefinite" anim:sub-item="text" smil:attributeName="opacity">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:to"><xsl:choose><xsl:when test="@演:预定义透明度='25' ">0.25</xsl:when><xsl:when test="@演:预定义透明度='50' ">0.5</xsl:when><xsl:when test="@演:预定义透明度='75' ">0.75</xsl:when><xsl:when test="@演:预定义透明度='100' ">1</xsl:when><xsl:when test="@演:自定义透明度"><xsl:value-of select="@演:自定义透明度"/></xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:缩放" mode="emphasis">
+ <xsl:attribute name="presentation:preset-id">ooo-emphasis-grow-and-shrink</xsl:attribute>
+ <anim:animateTransform smil:fill="hold" anim:sub-item="text" presentation:additive="base" svg:type="scale">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:to"><xsl:choose><xsl:when test="@演:预定义尺寸='tiny' ">0.25,1</xsl:when><xsl:when test="@演:预定义尺寸='smaller' ">0.5,1</xsl:when><xsl:when test="@演:预定义尺寸='larger' ">1.5,1</xsl:when><xsl:when test="@演:预定义尺寸='huge' ">4,1</xsl:when><xsl:when test="@演:自定义尺寸"><xsl:value-of select="@演:自定义尺寸"/></xsl:when><xsl:otherwise>0.5,1</xsl:otherwise></xsl:choose></xsl:attribute>
+ </anim:animateTransform>
+ </xsl:template>
+ <xsl:template match="演:盒状" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-box</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:transitionFilter smil:type="irisWipe" smil:subtype="rectangle" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.004s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:棋盘" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-checkerboard</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向='down'">downward</xsl:when><xsl:when test="@演:方向='across'">across</xsl:when></xsl:choose></xsl:attribute>
+ <anim:transitionFilter smil:dur="2s" anim:sub-item="text" smil:type="checkerBoardWipe" smil:subtype="down" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.004s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:圆形扩展" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-circle</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:transitionFilter smil:type="ellipseWipe" smil:subtype="horizontal" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:阶梯状" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-diagonal-squares</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向='left down'">left-to-bottom</xsl:when><xsl:when test="@演:方向='left up'">left-to-top</xsl:when><xsl:when test="@演:方向='right down'">right-to-bottom</xsl:when><xsl:when test="@演:方向='right up'">right-to-top</xsl:when></xsl:choose></xsl:attribute>
+ <anim:transitionFilter smil:type="waterfallWipe" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向='left down'">horizontalLeft</xsl:when><xsl:when test="@演:方向='left up'">horizontalLeft</xsl:when><xsl:when test="@演:方向='right down'">horizontalRight</xsl:when><xsl:when test="@演:方向='right up'">horizontalRight</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:菱形" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-diamond</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:transitionFilter smil:type="irisWipe" smil:subtype="diamond" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:消失" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-disappear</xsl:attribute>
+ <anim:set smil:begin="0s" smil:dur="0.001s" smil:fill="hold" anim:sub-item="text" smil:attributeName="visibility" smil:to="visible">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:向外溶解" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-dissolve</xsl:attribute>
+ <anim:transitionFilter smil:type="dissolve" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:闪烁一次" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-flash-once</xsl:attribute>
+ <anim:animate smil:attributeName="visibility" smil:values="hidden;visible" smil:keyTimes="0;0.5" smil:calcMode="discrete" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:animate>
+ <anim:set smil:dur="0s" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:飞出" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-fly-out</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向= 'to bottom'">from-bottom</xsl:when><xsl:when test="@演:方向 = 'to top-right'">from-top-right</xsl:when><xsl:when test="@演:方向 = 'to top-left'">from-top-left</xsl:when><xsl:when test="@演:方向 = 'to bottom-left'">from-bottom-left</xsl:when><xsl:when test="@演:方向 = 'to bottom-right'">from-bottom-right</xsl:when><xsl:when test="@演:方向 = 'to right'">from-right</xsl:when><xsl:when test="@演:方向 = 'to left'">from-left</xsl:when><xsl:when test="@演:方向 = 'to top'">from-top</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:variable name="smilvalueX">
+ <xsl:choose>
+ <xsl:when test="contains(@演:方向,'right')">x;1+width/2</xsl:when>
+ <xsl:when test="contains(@演:方向,'left')">x;0-width/2</xsl:when>
+ <xsl:otherwise>x;x</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="smilvalueY">
+ <xsl:choose>
+ <xsl:when test="contains(@演:方向,'bottom')">y;1+height/2</xsl:when>
+ <xsl:when test="contains(@演:方向,'top')">y;0-height/2</xsl:when>
+ <xsl:otherwise>y;y</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <anim:animate smil:fill="hold" smil:attributeName="x" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:values"><xsl:value-of select="$smilvalueX"/></xsl:attribute>
+ </anim:animate>
+ <anim:animate smil:fill="hold" smil:attributeName="y" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:values"><xsl:value-of select="$smilvalueY"/></xsl:attribute>
+ </anim:animate>
+ <anim:set smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:缓慢移出" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-crawl-out</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向= 'to bottom'">from-bottom</xsl:when><xsl:when test="@演:方向 = 'to right'">from-right</xsl:when><xsl:when test="@演:方向 = 'to left'">from-left</xsl:when><xsl:when test="@演:方向 = 'to top'">from-top</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:variable name="smilvalueX">
+ <xsl:choose>
+ <xsl:when test="contains(@演:方向,'right')">x;1+width/2</xsl:when>
+ <xsl:when test="contains(@演:方向,'left')">x;0-width/2</xsl:when>
+ <xsl:otherwise>x;x</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="smilvalueY">
+ <xsl:choose>
+ <xsl:when test="contains(@演:方向,'bottom')">y;1+height/2</xsl:when>
+ <xsl:when test="contains(@演:方向,'top')">y;0-height/2</xsl:when>
+ <xsl:otherwise>y;y</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <anim:animate smil:fill="hold" smil:attributeName="x" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:values"><xsl:value-of select="$smilvalueX"/></xsl:attribute>
+ </anim:animate>
+ <anim:animate smil:fill="hold" smil:attributeName="y" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:values"><xsl:value-of select="$smilvalueY"/></xsl:attribute>
+ </anim:animate>
+ <anim:set smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:切出" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-peek-out</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向= 'from bottom'">from-bottom</xsl:when><xsl:when test="@演:方向 = 'from right'">from-right</xsl:when><xsl:when test="@演:方向 = 'from left'">from-left</xsl:when><xsl:when test="@演:方向 = 'from top'">from-top</xsl:when></xsl:choose></xsl:attribute>
+ <anim:transitionFilter smil:type="slideWipe" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向= 'from bottom'">fromBottom</xsl:when><xsl:when test="@演:方向 = 'from right'">fromRight</xsl:when><xsl:when test="@演:方向 = 'from left'">fromLeft</xsl:when><xsl:when test="@演:方向 = 'from top'">fromTop</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.0005s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:十字形扩展" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-plus</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:transitionFilter smil:type="fourBoxWipe" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向= 'in'">cornersIn</xsl:when><xsl:when test="@演:方向 = 'out'">cornersOut</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.00025s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:随机线条" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-random-bars</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:transitionFilter smil:type="randomBarWipe" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向= 'horizontal'">vertical</xsl:when><xsl:when test="@演:方向 = 'vertical'">horizontal</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.001s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:劈裂" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-split</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:方向 = 'horizontal out'">horizontal-out</xsl:when><xsl:when test="@演:方向= 'horizontal in'">horizontal-in</xsl:when><xsl:when test="@演:方向= 'vertical in'">vertical-in</xsl:when><xsl:when test="@演:方向= 'vertical out'">vertical-out</xsl:when></xsl:choose></xsl:attribute>
+ <anim:transitionFilter smil:dur="0.5s" smil:type="barnDoorWipe" smil:mode="out">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向 = 'horizontal out'">horizontal</xsl:when><xsl:when test="@演:方向= 'horizontal in'">horizontal</xsl:when><xsl:when test="@演:方向= 'vertical in'">vertical</xsl:when><xsl:when test="@演:方向= 'vertical out'">vertical</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.001s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:百叶窗" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-venetian-blinds</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:方向"/></xsl:attribute>
+ <anim:transitionFilter smil:type="blindsWipe" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:方向= 'horizontal'">vertical</xsl:when><xsl:when test="@演:方向 = 'vertical'">horizontal</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.001s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:扇形展开" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-wedge</xsl:attribute>
+ <anim:transitionFilter smil:type="fanWipe" smil:subtype="centerTop" smil:mode="out">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.0015s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:轮子" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-wheel</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:value-of select="@演:辐射状"/></xsl:attribute>
+ <anim:transitionFilter smil:dur="0.5s" smil:type="pinWheelWipe" smil:mode="out">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="@演:辐射状='1'">oneBlade</xsl:when><xsl:when test="@演:辐射状='2'">twoBlade</xsl:when><xsl:when test="@演:辐射状='3'">threeBlade</xsl:when><xsl:when test="@演:辐射状='4'">fourBlade</xsl:when><xsl:when test="@演:辐射状='8'">eightBlade</xsl:when></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.00025s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:擦除" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-wipe</xsl:attribute>
+ <xsl:attribute name="presentation:preset-sub-type"><xsl:choose><xsl:when test="@演:速度 = 'from right'">from-right</xsl:when><xsl:when test="@演:速度 = 'from left'">from-left</xsl:when><xsl:when test="@演:速度 = 'from top'">from-top</xsl:when><xsl:when test="@演:速度 = 'from bottom'">from-bottom</xsl:when><xsl:otherwise>from-left</xsl:otherwise></xsl:choose></xsl:attribute>
+ <anim:transitionFilter smil:type="barWipe" smil:subtype="leftToRight" smil:direction="reverse" smil:mode="out">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:subtype"><xsl:choose><xsl:when test="(@演:速度 = 'from right') or (@演:速度 = 'from left')">leftToRight</xsl:when><xsl:when test="(@演:速度 = 'from top') or (@演:速度 = 'from bottom')">topToBottom</xsl:when><xsl:otherwise>leftToRight</xsl:otherwise></xsl:choose></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:set smil:dur="0.006s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="演:随机效果" mode="exit">
+ <xsl:attribute name="presentation:preset-id">ooo-exit-random</xsl:attribute>
+ <anim:transitionFilter smil:type="fade" smil:subtype="crossfade" smil:mode="out">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:transitionFilter>
+ <anim:animate smil:attributeName="x" smil:values="x;x" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:dur"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:animate>
+ <anim:animate smil:dur="0.1s" smil:decelerate="1" smil:attributeName="y" smil:values="y;y-.03" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:animate>
+ <anim:animate smil:begin="0.1s" smil:dur="0.9s" smil:accelerate="1" smil:attributeName="y" smil:values="y;y+1" smil:keyTimes="0;1" presentation:additive="base">
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:animate>
+ <anim:set smil:dur="0.001s" smil:fill="hold" smil:attributeName="visibility" smil:to="hidden">
+ <xsl:attribute name="smil:begin"><xsl:call-template name="演速度"/></xsl:attribute>
+ <xsl:attribute name="smil:targetElement"><xsl:value-of select="ancestor::演:序列/@演:动画对象"/></xsl:attribute>
+ </anim:set>
+ </xsl:template>
+ <xsl:template match="uof:锚点" name="图形解析">
+ <xsl:variable name="tuxing1" select="@uof:图形引用"/>
+ <xsl:choose>
+ <xsl:when test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]">
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='png' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='jpg' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='bmp' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='gif'">
+ <xsl:element name="draw:frame">
+ <xsl:attribute name="draw:name"><xsl:variable name="pos"><xsl:value-of select="count(preceding::uof:锚点)"/></xsl:variable><xsl:value-of select="concat('图形',$pos)"/></xsl:attribute>
+ <xsl:attribute name="presentation:class">graphic</xsl:attribute>
+ <xsl:attribute name="presentation:user-transformed">true</xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@uof:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="draw:layer">layout</xsl:attribute>
+ <xsl:if test="../演:动画/演:序列/@演:动画对象=$tuxing1">
+ <xsl:attribute name="draw:id"><xsl:value-of select="$tuxing1"/></xsl:attribute>
+ </xsl:if>
+ <draw:image>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径">
+ <xsl:attribute name="xlink:href"><xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径">
+ <xsl:attribute name="xlink:href"><xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:数据">
+ <office:binary-data>
+ <xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:数据"/>
+ </office:binary-data>
+ </xsl:if>
+ </draw:image>
+ </xsl:element>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="graph">
+ <xsl:with-param name="id" select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]"/>
+ <xsl:with-param name="groupx" select="0"/>
+ <xsl:with-param name="groupy" select="0"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="graph">
+ <xsl:param name="id"/>
+ <xsl:param name="groupx"/>
+ <xsl:param name="groupy"/>
+ <xsl:for-each select="$id">
+ <xsl:variable name="tuxing1">
+ <xsl:value-of select="图:预定义图形/图:类别"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$tuxing1='11'">
+ <xsl:call-template name="Rectangle">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='19'">
+ <xsl:call-template name="Oval">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='61'">
+ <xsl:call-template name="Line">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='64'">
+ <xsl:call-template name="Curve">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='65'">
+ <xsl:call-template name="Freeform">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='66'">
+ <xsl:call-template name="Scribble">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='3'">
+ <xsl:call-template name="演文本框"/>
+ </xsl:when>
+ <xsl:when test="$tuxing1='67'">
+ <xsl:call-template name="演缩略图"/>
+ </xsl:when>
+ <xsl:when test="$tuxing1='4'">
+ <xsl:element name="draw:g">
+ <xsl:variable name="tu">
+ <xsl:value-of select="@图:标识符"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="$tu"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:variable name="this-group-x">
+ <xsl:value-of select="key('rel_graphic_name',@图:标识符)/@uof:x坐标"/>
+ </xsl:variable>
+ <xsl:variable name="this-group-y">
+ <xsl:value-of select="key('rel_graphic_name',@图:标识符)/uof:y坐标"/>
+ </xsl:variable>
+ <xsl:variable name="group-x">
+ <xsl:value-of select="number($groupx + $this-group-x)"/>
+ </xsl:variable>
+ <xsl:variable name="group-y">
+ <xsl:value-of select="number($groupy + $this-group-y)"/>
+ </xsl:variable>
+ <xsl:call-template name="组合图形">
+ <xsl:with-param name="zuheliebiao" select="@图:组合列表"/>
+ <xsl:with-param name="groupx1" select="$group-x"/>
+ <xsl:with-param name="groupy1" select="$group-y"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="common">
+ <xsl:param name="groupx"/>
+ <xsl:param name="groupy"/>
+ <xsl:variable name="tuxing">
+ <xsl:value-of select="@图:标识符"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="key('rel_graphic_name',@图:标识符)">
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@uof:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="draw:layer"><xsl:choose><xsl:when test="parent::演:母版">backgroundobjects</xsl:when><xsl:otherwise>layout</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="../演:动画/演:序列/@演:动画对象=$tuxing">
+ <xsl:attribute name="draw:id"><xsl:value-of select="$tuxing"/></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="zuheweizhi-x">
+ <xsl:value-of select="图:组合位置/@图:x坐标"/>
+ </xsl:variable>
+ <xsl:variable name="zuheweizhi-y">
+ <xsl:value-of select="图:组合位置/@图:y坐标"/>
+ </xsl:variable>
+ <xsl:attribute name="text:anchor-type">paragraph</xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(($groupx + $zuheweizhi-x),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(($groupy + $zuheweizhi-y),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(图:预定义图形 /图:属性/图:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(图:预定义图形/图:属性 /图:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="draw:layer">layout</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="组合图形">
+ <xsl:param name="zuheliebiao"/>
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:variable name="x">
+ <xsl:value-of select="$groupx1"/>
+ </xsl:variable>
+ <xsl:variable name="y">
+ <xsl:value-of select="$groupy1"/>
+ </xsl:variable>
+ <xsl:variable name="first-pictures">
+ <xsl:value-of select="substring-before($zuheliebiao,',')"/>
+ </xsl:variable>
+ <xsl:variable name="other-pictures">
+ <xsl:value-of select="substring-after($zuheliebiao,',')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($other-pictures,',')">
+ <xsl:call-template name="graph">
+ <xsl:with-param name="id" select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $first-pictures]"/>
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ <xsl:call-template name="组合图形">
+ <xsl:with-param name="zuheliebiao" select="$other-pictures"/>
+ <xsl:with-param name="groupx1" select="$x"/>
+ <xsl:with-param name="groupy1" select="$y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="graph">
+ <xsl:with-param name="id" select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $first-pictures]"/>
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ <xsl:call-template name="graph">
+ <xsl:with-param name="id" select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $other-pictures]"/>
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="Curve">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:path">
+ <xsl:variable name="width" select="number(图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="svg:d"><xsl:value-of select="图:预定义图形/图:关键点坐标/@图:路径"/></xsl:attribute>
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Freeform">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:polygon">
+ <xsl:variable name="width" select="number(图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="draw:points"><xsl:call-template name="drawpoints"><xsl:with-param name="points" select="图:预定义图形/图:关键点坐标/@图:路径"/><xsl:with-param name="value"/></xsl:call-template></xsl:attribute>
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Scribble">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:polyline">
+ <xsl:variable name="width" select="number(图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="draw:points"><xsl:call-template name="drawpoints"><xsl:with-param name="points" select="图:预定义图形/图:关键点坐标/@图:路径"/><xsl:with-param name="value"/></xsl:call-template></xsl:attribute>
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="drawpoints">
+ <xsl:param name="points"/>
+ <xsl:param name="value"/>
+ <xsl:variable name="frist-piont">
+ <xsl:value-of select="substring-before($points,'lineto')"/>
+ </xsl:variable>
+ <xsl:variable name="other-points">
+ <xsl:value-of select="substring-after($points,'lineto')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($other-points,'lineto')">
+ <xsl:variable name="x-coor">
+ <xsl:value-of select="substring-before($frist-piont,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="y-coor">
+ <xsl:value-of select="substring-after($frist-piont,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="all-points">
+ <xsl:value-of select="concat($value,$x-coor,',',$y-coor,' ')"/>
+ </xsl:variable>
+ <xsl:call-template name="drawpoints">
+ <xsl:with-param name="points" select="$other-points"/>
+ <xsl:with-param name="value" select="$all-points"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="q-x-coor">
+ <xsl:value-of select="substring-before($frist-piont,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="q-y-coor">
+ <xsl:value-of select="substring-after($frist-piont,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="e-x-coor">
+ <xsl:value-of select="substring-before($other-points,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="e-y-coor">
+ <xsl:value-of select="substring-after($other-points,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:value-of select="concat($value,$q-x-coor,',',$q-y-coor,' ',$e-x-coor,',',$e-y-coor)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="Oval">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:ellipse">
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Rectangle">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:rect">
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Line">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:line">
+ <xsl:variable name="tuxing1" select="@图:标识符"/>
+ <xsl:choose>
+ <xsl:when test="key('rel_graphic_name',@图:标识符)">
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)">
+ <xsl:attribute name="svg:x1"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y1"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:x2"><xsl:value-of select="concat((@uof:x坐标 + @uof:宽度),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y2"><xsl:value-of select="concat((@uof:y坐标 + @uof:高度),$uofUnit)"/></xsl:attribute>
+ <xsl:if test="../演:动画/演:序列/@演:动画对象=$tuxing1">
+ <xsl:attribute name="draw:id"><xsl:value-of select="$tuxing1"/></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="zuheweizhi-x">
+ <xsl:value-of select="图:组合位置/@图:x坐标"/>
+ </xsl:variable>
+ <xsl:variable name="zuheweizhi-y">
+ <xsl:value-of select="图:组合位置/@图:y坐标"/>
+ </xsl:variable>
+ <xsl:variable name="hex">
+ <xsl:value-of select="concat(number($groupx1 + $zuheweizhi-x),$uofUnit)"/>
+ </xsl:variable>
+ <xsl:variable name="hey">
+ <xsl:value-of select="concat(number($groupy1 + $zuheweizhi-y),$uofUnit)"/>
+ </xsl:variable>
+ <xsl:attribute name="svg:x1"><xsl:value-of select="$hex"/></xsl:attribute>
+ <xsl:attribute name="svg:y1"><xsl:value-of select="$hey"/></xsl:attribute>
+ <xsl:attribute name="svg:x2"><xsl:value-of select="concat(($hex + 图:预定义图形/图:属性/图:宽度),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y2"><xsl:value-of select="concat(($hey + 图:预定义图形/图:属性/图:高度),$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="text:anchor-type">paragraph</xsl:attribute>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="$tuxing1"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="演文本框">
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)">
+ <xsl:variable name="tuxing1" select="@uof:图形引用"/>
+ <xsl:element name="draw:frame">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@uof:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="draw:layer"><xsl:choose><xsl:when test="parent::演:母版">backgroundobjects</xsl:when><xsl:otherwise>layout</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:预定义图形/图:类别 = '3' and (parent::演:幻灯片/@演:配色方案引用) and not(@uof:占位符 = 'graphic')">
+ <xsl:attribute name="presentation:style-name"><xsl:value-of select="parent::演:幻灯片/@演:配色方案引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="../演:动画/演:序列/@演:动画对象=$tuxing1">
+ <xsl:attribute name="draw:id"><xsl:value-of select="$tuxing1"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(@uof:占位符 = 'graphic')">
+ <xsl:attribute name="presentation:style-name"><xsl:value-of select="@uof:图形引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="placeholdType">
+ <xsl:value-of select="@uof:占位符"/>
+ </xsl:variable>
+ <xsl:if test="@uof:占位符">
+ <xsl:attribute name="presentation:class"><xsl:choose><xsl:when test="@uof:占位符 = 'clipart'">graphic</xsl:when><xsl:when test="@uof:占位符 = 'media_clip'">graphic</xsl:when><xsl:when test="@uof:占位符 = 'graphics'">graphic</xsl:when><xsl:when test="@uof:占位符 = 'number'">page_number</xsl:when><xsl:when test="@uof:占位符 = 'centertitle'">title</xsl:when><xsl:when test="@uof:占位符 = 'date'">date-time</xsl:when><xsl:when test="@uof:占位符 = 'vertical_text'">vertical_outline</xsl:when><xsl:when test="@uof:占位符 = 'vertical_subtitle'">vertical_outline</xsl:when><xsl:otherwise><xsl:value-of select="@uof:占位符"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]">
+ <xsl:variable name="leibie">
+ <xsl:value-of select="图:预定义图形/图:类别"/>
+ </xsl:variable>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="图:文本内容 or @图:其他对象">
+ <xsl:attribute name="presentation:user-transformed">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="presentation:placeholder">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="$placeholdType = 'graphic' or $placeholdType = 'clipart' or $placeholdType ='media_clip'">
+ <draw:image/>
+ </xsl:when>
+ <xsl:when test="$placeholdType = 'table' or $placeholdType = 'chart' or $placeholdType ='object'">
+ <draw:object/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="draw:text-box">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="演缩略图">
+ <draw:page-thumbnail>
+ <xsl:call-template name="common"/>
+ <xsl:attribute name="draw:layer">layout</xsl:attribute>
+ <xsl:attribute name="draw:page-number"><xsl:for-each select="../.."><xsl:value-of select="count(preceding-sibling::演:幻灯片) + 1"/></xsl:for-each></xsl:attribute>
+ <xsl:attribute name="presentation:class">page</xsl:attribute>
+ </draw:page-thumbnail>
+ </xsl:template>
+ <xsl:template match="演:页面版式">
+ <xsl:element name="style:presentation-page-layout">
+ <xsl:attribute name="style:name"><xsl:value-of select="@演:标识符"/></xsl:attribute>
+ <xsl:apply-templates select="演:占位符" mode="layout"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="演:占位符" mode="layout">
+ <presentation:placeholder>
+ <xsl:attribute name="presentation:object"><xsl:choose><xsl:when test="@演:类型='vertical_text'">vertical_outline</xsl:when><xsl:when test="@演:类型='date'">date-time</xsl:when><xsl:when test="@演:类型='number'">page_number</xsl:when><xsl:otherwise><xsl:value-of select="@演:类型"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(uof:锚点/@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(uof:锚点/@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(uof:锚点/@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(uof:锚点/@uof:高度,$uofUnit)"/></xsl:attribute>
+ </presentation:placeholder>
+ </xsl:template>
+ <xsl:template match="字:段落">
+ <xsl:choose>
+ <xsl:when test="字:段落属性/字:自动编号信息">
+ <xsl:call-template name="编号解析"/>
+ </xsl:when>
+ <xsl:when test="字:句/字:分页符">
+ <xsl:call-template name="processPageBreaks"/>
+ </xsl:when>
+ <xsl:when test="string(parent::node()/@uof:locID)='t0107'">
+ <xsl:call-template name="jiaozhu"/>
+ </xsl:when>
+ <xsl:when test="string(parent::node()/@uof:locID)='t0108'">
+ <xsl:call-template name="weizhu"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="jiaozhu">
+ <xsl:element name="text:footnote">
+ <xsl:element name="text:footnote-body">
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="weizhu">
+ <xsl:element name="text:endnote">
+ <xsl:element name="text:endnote-body">
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="processPageBreaks">
+ <xsl:variable name="pageBreak" select="字:句/字:分页符"/>
+ <xsl:call-template name="createSubParagraph">
+ <xsl:with-param name="list" select="$pageBreak[1]/preceding-sibling::字:句"/>
+ <xsl:with-param name="pageBreak"/>
+ <xsl:with-param name="needsPageBreak">false</xsl:with-param>
+ </xsl:call-template>
+ <xsl:for-each select="$pageBreak">
+ <xsl:call-template name="createSubParagraph">
+ <xsl:with-param name="list" select="./following-sibling::字:句[preceding::字:句/字:分页符 = '.']"/>
+ <xsl:with-param name="pageBreak" select="."/>
+ <xsl:with-param name="needsPageBreak">true</xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="createSubParagraph">
+ <xsl:param name="list"/>
+ <xsl:param name="pageBreak"/>
+ <xsl:param name="needsPageBreak"/>
+ <xsl:if test="(count($list) &gt; 0) or ($needsPageBreak ='true') ">
+ <xsl:element name="text:p">
+ <xsl:choose>
+ <xsl:when test="$needsPageBreak = 'true'">
+ <xsl:choose>
+ <xsl:when test="ancestor::字:段落/字:段落属性">
+ <xsl:attribute name="text:style-name">P<xsl:number from="/uof:UOF/uof:演示文稿/演:主体" level="any" count="字:段落属性"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:style-name">PageBreak</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="$pageBreak">
+ <xsl:apply-templates select="$pageBreak"/>
+ </xsl:if>
+ <xsl:apply-templates select="$list"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:区域开始[@字:类型='bookmark']">
+ <text:bookmark-start text:name="{@字:标识符}"/>
+ </xsl:template>
+ <xsl:template match="字:区域结束[preceding::字:区域开始[1]/@字:类型='bookmark']">
+ <text:bookmark-end text:name="{@字:标识符引用}"/>
+ </xsl:template>
+ <xsl:template match="字:段落/字:域开始">
+ <xsl:choose>
+ <xsl:when test="@字:类型='CREATEDATE'">
+ <xsl:variable name="datestr" select="../字:句/字:文本串"/>
+ <xsl:element name="text:date">
+ <xsl:attribute name="style:data-style-name">Time<xsl:number from="/uof:UOF/uof:演示文稿/演:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'CREATEDATE']"/></xsl:attribute>
+ <xsl:attribute name="text:date-value"><xsl:value-of select="concat(substring-before($datestr,' '),'T',substring-after($datestr,' '))"/></xsl:attribute>
+ <xsl:value-of select="$datestr"/>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="commonParagraph">
+ <xsl:element name="text:p">
+ <xsl:if test="@字:动画标识">
+ <xsl:attribute name="text:id"><xsl:value-of select="@字:动画标识"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="commonParagraphAttributes"/>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="commonParagraphAttributes">
+ <xsl:choose>
+ <xsl:when test="字:段落属性">
+ <xsl:attribute name="text:style-name"><xsl:value-of select="字:段落属性/@字:式样引用"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="generate-id(ancestor::字:主体/descendant::字:段落[1]) = generate-id(.)">
+ <xsl:variable name="paragraph-number">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落[字:段落属性]"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name">P<xsl:value-of select="number($paragraph-number)"/>_1</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="not(字:段落属性) and (descendant::字:分栏符 or ancestor::字:分节/descendant::字:节属性[字:分栏/@字:栏数 &gt; 1])">
+ <xsl:attribute name="text:style-name">ColumnBreakPara</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:句">
+ <xsl:apply-templates select="字:文本串"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:段落属性"/>
+ <xsl:template match="字:句/字:句属性"/>
+ <xsl:template match="字:句属性" mode="style">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">T<xsl:number from="/uof:UOF/uof:对象集" level="any" count="字:句属性" format="1"/></xsl:attribute>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ <xsl:if test="@字:式样引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="./*"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:句/字:文本串">
+ <xsl:choose>
+ <xsl:when test="string(.) = ' ' ">
+ <xsl:element name="text:s"/>
+ </xsl:when>
+ <xsl:when test="contains(.,' ')">
+ <xsl:call-template name="replace-spaces">
+ <xsl:with-param name="curr-string" select="."/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="replace-spaces">
+ <xsl:param name="curr-string"/>
+ <xsl:if test="contains($curr-string,' ')">
+ <xsl:value-of select="substring-before($curr-string,' ')"/>
+ <text:s text:c="2"/>
+ <xsl:variable name="next-string" select="substring-after($curr-string,' ')"/>
+ <xsl:choose>
+ <xsl:when test="contains($next-string, ' ')">
+ <xsl:call-template name="replace-spaces">
+ <xsl:with-param name="curr-string" select="$next-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$next-string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:句">
+ <xsl:if test="name(following-sibling::*[1])!='字:域结束'">
+ <xsl:if test="字:换行符">
+ <xsl:element name="text:line-break"/>
+ </xsl:if>
+ <xsl:variable name="currently-node" select="./字:锚点"/>
+ <xsl:choose>
+ <xsl:when test="字:句属性//字:隐藏文字/@字:值='true'">
+ <text:hidden-text text:is-hidden="true" text:string-value="{.}"/>
+ </xsl:when>
+ <xsl:when test="字:区域开始[@字:类型='hyperlink']">
+ <xsl:element name="text:a">
+ <xsl:attribute name="xlink:type">simple</xsl:attribute>
+ <xsl:variable name="hyperDest" select="字:区域开始/@字:标识符"/>
+ <xsl:attribute name="xlink:href"><xsl:for-each select="/uof:UOF/uof:链接集/uof:超级链接"><xsl:if test="@uof:链源=$hyperDest"><xsl:if test="@uof:目标"><xsl:value-of select="@uof:目标"/></xsl:if><xsl:if test="@uof:书签"><xsl:variable name="bookmarkDest" select="@uof:书签"/><xsl:for-each select="/uof:UOF/uof:书签集/uof:书签"><xsl:if test="@uof:名称=$bookmarkDest"><xsl:value-of select="concat('#',uof:文本位置/@字:区域引用)"/></xsl:if></xsl:for-each></xsl:if></xsl:if></xsl:for-each></xsl:attribute>
+ <xsl:apply-templates select="字:文本串"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="(preceding-sibling::字:句) or (字:句属性)or(字:区域开始)">
+ <xsl:element name="text:span">
+ <xsl:choose>
+ <xsl:when test="字:区域开始[@字:类型='annotation']">
+ <xsl:variable name="ref_comment">
+ <xsl:value-of select="字:区域开始/@字:标识符"/>
+ </xsl:variable>
+ <xsl:apply-templates/>
+ <xsl:apply-templates select="/uof:UOF/uof:文字处理/字:公用处理规则/字:批注集/字:批注[@字:区域引用 = $ref_comment]"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="stylenum">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:句" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="字:句属性/@字:式样引用"/></xsl:attribute>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="node()[name() = '字:位置']">
+ <xsl:variable name="height">100% </xsl:variable>
+ <xsl:variable name="position">
+ <xsl:choose>
+ <xsl:when test="parent::字:句属性//字:位置">
+ <xsl:value-of select="concat( parent::字:句属性//字:位置, '%')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:text-position"><xsl:value-of select="concat(concat( $position, ' '), $height)"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:字体">
+ <xsl:if test="@字:字号">
+ <xsl:attribute name="fo:font-size"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:相对字号 and self::node( )[not(parent::字:句属性)]">
+ <xsl:variable name="stylename" select="parent::node()/@字:基式样引用"/>
+ <xsl:variable name="zihao">
+ <xsl:for-each select="/uof:UOF/uof:式样集//uof:段落式样[@字:标识符=$stylename]">
+ <xsl:value-of select="字:字体/@字:字号"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="font-size" select="@字:相对字号"/>
+ <xsl:attribute name="fo:font-size"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:颜色">
+ <xsl:attribute name="fo:color"><xsl:value-of select="string(@字:颜色)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:中文字体引用">
+ <xsl:attribute name="style:font-name-asian"><xsl:value-of select="@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:西文字体引用">
+ <xsl:attribute name="style:font-name"><xsl:value-of select="@字:西文字体引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:斜体">
+ <xsl:if test="@字:值='true'">
+ <xsl:attribute name="fo:font-style">italic</xsl:attribute>
+ <xsl:attribute name="fo:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-complex">italic</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:粗体">
+ <xsl:if test="@字:值='true'">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="fo:font-weight-asian">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-complex">bold</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:下划线">
+ <xsl:choose>
+ <xsl:when test="@字:字下划线 = 'true'">
+ <xsl:attribute name="style:text-underline">single</xsl:attribute>
+ <xsl:attribute name="style:text-underline-color">font-color</xsl:attribute>
+ <xsl:attribute name="fo:score-spaces">false</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'thick'">
+ <xsl:attribute name="style:text-underline">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dotted-heavy'">
+ <xsl:attribute name="style:text-underline">bold-dotted</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dashed-heavy'">
+ <xsl:attribute name="style:text-underline">bold-dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-long'">
+ <xsl:attribute name="style:text-underline">long-dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-long-heavy'">
+ <xsl:attribute name="style:text-underline">bold-long-dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-dot-heavy'">
+ <xsl:attribute name="style:text-underline">bold-dot-dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-dot-dot-heavy'">
+ <xsl:attribute name="style:text-underline">bold-dot-dot-dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'wavy-heavy'">
+ <xsl:attribute name="style:text-underline">bold-wave</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'wavy-double'">
+ <xsl:attribute name="style:text-underline">double-wave</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:text-underline"><xsl:value-of select="@字:类型"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@字:颜色 and not(@字:颜色 = 'auto')">
+ <xsl:attribute name="style:text-underline-color"><xsl:value-of select="concat( '#', @字:颜色)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:阴影">
+ <xsl:attribute name="style:text-shadow">1pt 1pt</xsl:attribute>
+ <xsl:attribute name="fo:text-shadow">1pt 1pt</xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:删除线">
+ <xsl:choose>
+ <xsl:when test="@字:类型 = 'single' ">
+ <xsl:attribute name="style:text-crossing-out">single-line</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字类型 = 'double'">
+ <xsl:attribute name="style:text-crossing-out">double-line</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:突出显示">
+ <xsl:attribute name="fo:text-transform">uppercase</xsl:attribute>
+ <xsl:attribute name="fo:text-background-color"><xsl:value-of select="string(@字:颜色)"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="@字:颜色[not(.='auto')]">
+ <xsl:attribute name="fo:color">#<xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:浮雕">
+ <xsl:attribute name="style:font-relief">embossed</xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:外框">
+ <xsl:attribute name="style:text-outline">true</xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:缩放">
+ <xsl:attribute name="style:text-scale"><xsl:value-of select="@字:字号"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:字符间距[parent::字:句属性]">
+ <xsl:attribute name="fo:letter-spacing"><xsl:value-of select="concat( floor(number(字:字符间距 div 1440) * 2540) div 1000, 'cm')"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="uof:字体集">
+ <xsl:if test="not(uof:字体声明[@uof:名称='StarSymbol'])">
+ <style:font-face style:name="StarSymbol" svg:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </xsl:if>
+ <xsl:for-each select="uof:字体声明">
+ <xsl:element name="style:font-face">
+ <xsl:attribute name="style:name"><xsl:value-of select="@uof:名称"/></xsl:attribute>
+ <xsl:attribute name="svg:font-family"><xsl:value-of select="@uof:字体族"/></xsl:attribute>
+ <xsl:if test="@uof:字符集 = '02'">
+ <xsl:attribute name="style:font-charset">x-symbol</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@uof:字体族">
+ <xsl:choose>
+ <xsl:when test="@uof:字体族 = 'Swiss'">
+ <xsl:attribute name="style:font-family-generic">swiss</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Modern'">
+ <xsl:attribute name="style:font-family-generic">modern</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族='Roman'">
+ <xsl:attribute name="style:font-family-generic">roman</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Script'">
+ <xsl:attribute name="style:font-family-generic">script</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Decorative'">
+ <xsl:attribute name="style:font-family-generic">decorative</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='System'">
+ <xsl:attribute name="style:font-family-generic">system</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:font-family-generic">system</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:attribute name="style:font-pitch">12</xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:apply-templates select="uof:字体声明"/>
+ </xsl:template>
+ <xsl:template match="uof:元数据">
+ <office:meta>
+ <meta:generator>UOFText 2004</meta:generator>
+ <dc:title>
+ <xsl:value-of select="uof:标题"/>
+ </dc:title>
+ <dc:description>
+ <xsl:value-of select="uof:摘要"/>
+ </dc:description>
+ <dc:subject>
+ <xsl:value-of select="uof:主题"/>
+ </dc:subject>
+ <meta:initial-creator>
+ <xsl:value-of select="uof:作者"/>
+ </meta:initial-creator>
+ <meta:creation-date>
+ <xsl:value-of select="substring-before( uof:创建日期, 'Z')"/>
+ </meta:creation-date>
+ <dc:creator>
+ <xsl:value-of select="uof:最后作者"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="substring-before( uof:编辑时间, 'Z')"/>
+ </dc:date>
+ <meta:printed-by/>
+ <meta:print-date/>
+ <meta:keywords>
+ <meta:keyword>
+ <xsl:value-of select="uof:关键字集/uof:关键字"/>
+ </meta:keyword>
+ </meta:keywords>
+ <dc:language/>
+ <meta:editing-cycles>
+ <xsl:value-of select="uof:编辑次数"/>
+ </meta:editing-cycles>
+ <meta:editing-duration>
+ <xsl:if test="uof:编辑时间">
+ <xsl:value-of select="concat('PT', floor(uof:编辑时间 div 60), 'H', uof:编辑时间 mod 60, 'M0S')"/>
+ </xsl:if>
+ </meta:editing-duration>
+ <meta:user-defined meta:name="Category">
+ <xsl:value-of select="uof:分类"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Manager">
+ <xsl:value-of select="uof:经理名称"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Company">
+ <xsl:value-of select="uof:公司名称"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Version">
+ <xsl:value-of select="uof:创建应用程序"/>
+ </meta:user-defined>
+ <xsl:if test="uof:文档模板|child::*[@uof:locID='u0013']">
+ <meta:template xlink:type="simple" xlink:actuate="onRequest" xlink:href="{child::*[@uof:locID='u0013']}"/>
+ </xsl:if>
+ <xsl:if test="uof:用户自定义元数据集/uof:用户自定义元数据|child::*[@uof:locID='u0016']/*[@uof:locID='u0017']">
+ <xsl:for-each select="uof:用户自定义元数据集/uof:用户自定义元数据|child::*[@uof:locID='u0016']/*[@uof:locID='u0017']">
+ <xsl:element name="meta:user-defined">
+ <xsl:attribute name="meta:name"><xsl:value-of select="@uof:名称"/></xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:if>
+ <meta:document-statistic meta:page-count="{child::*[@uof:locID='u0020']}" meta:paragraph-count="{child::*[@uof:locID='u0025']}" meta:word-count="{child::*[@uof:locID='u0023']}" meta:object-count="{child::*[@uof:locID='u0026']}" meta:character-count="{child::*[@uof:locID='u0021']}"/>
+ <meta:document-statistic/>
+ </office:meta>
+ </xsl:template>
+ <xsl:template match="uof:用户自定义元数据集">
+ <xsl:for-each select="node()[@名称]">
+ <meta:user-defined meta:name="{name()}">
+ <xsl:value-of select="."/>
+ </meta:user-defined>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="parse-range">
+ <xsl:param name="range-value"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="first-pit">
+ <xsl:choose>
+ <xsl:when test="contains($range-value,',')">
+ <xsl:value-of select="substring-before($range-value,',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$range-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="current">
+ <xsl:choose>
+ <xsl:when test="contains($first-pit,':')">
+ <xsl:variable name="R-start" select="substring-before(substring-after($first-pit,'R'),'C')"/>
+ <xsl:variable name="C-start" select="substring-before(substring-after($first-pit,'C'),':')"/>
+ <xsl:variable name="second-pit" select="substring-after($first-pit,':')"/>
+ <xsl:variable name="R-end" select="substring-before(substring-after($second-pit,'R'),'C')"/>
+ <xsl:variable name="C-end" select="substring-after($second-pit,'C')"/>
+ <xsl:variable name="the-str">
+ <xsl:call-template name="condition-rc-str">
+ <xsl:with-param name="r-start" select="$R-start"/>
+ <xsl:with-param name="r-end" select="$R-end"/>
+ <xsl:with-param name="c-start" select="$C-start"/>
+ <xsl:with-param name="c-end" select="$C-end"/>
+ <xsl:with-param name="last" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$the-str"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($first-pit,',')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($range-value,',')">
+ <xsl:call-template name="parse-range">
+ <xsl:with-param name="range-value" select="substring-after($range-value,',')"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="condition-rc-str">
+ <xsl:param name="r-start"/>
+ <xsl:param name="r-end"/>
+ <xsl:param name="c-start"/>
+ <xsl:param name="c-end"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="current">
+ <xsl:call-template name="condition-c-str">
+ <xsl:with-param name="rc-str" select="concat('R',$r-start)"/>
+ <xsl:with-param name="start" select="$c-start"/>
+ <xsl:with-param name="end" select="$c-end"/>
+ <xsl:with-param name="last" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$r-start &lt; $r-end">
+ <xsl:call-template name="condition-rc-str">
+ <xsl:with-param name="r-start" select="$r-start + 1"/>
+ <xsl:with-param name="r-end" select="$r-end"/>
+ <xsl:with-param name="c-start" select="$c-start"/>
+ <xsl:with-param name="c-end" select="$c-end"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$r-start = $r-end">
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="condition-c-str">
+ <xsl:param name="rc-str"/>
+ <xsl:param name="start"/>
+ <xsl:param name="end"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="current" select="concat($rc-str,'C',$start,',')"/>
+ <xsl:if test="$start &lt; $end">
+ <xsl:call-template name="condition-c-str">
+ <xsl:with-param name="rc-str" select="$rc-str"/>
+ <xsl:with-param name="start" select="$start + 1"/>
+ <xsl:with-param name="end" select="$end"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$start = $end">
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="condition-str">
+ <xsl:param name="param-str"/>
+ <xsl:choose>
+ <xsl:when test="contains($param-str,'(')">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-after($param-str,'(')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($param-str,':')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="encode-as-cell-range-address">
+ <xsl:param name="string"/>
+ <xsl:value-of select="$string"/>
+ </xsl:template>
+ <xsl:template name="encode-as-cell-address">
+ <xsl:param name="string"/>
+ <xsl:value-of select="$string"/>
+ </xsl:template>
+ <xsl:param name="dpi" select="111"/>
+ <xsl:param name="centimeter-in-mm" select="10"/>
+ <xsl:param name="inch-in-mm" select="25.4"/>
+ <xsl:param name="didot-point-in-mm" select="0.376065"/>
+ <xsl:param name="pica-in-mm" select="4.2333333"/>
+ <xsl:param name="point-in-mm" select="0.3527778"/>
+ <xsl:param name="twip-in-mm" select="0.017636684"/>
+ <xsl:param name="pixel-in-mm" select="$inch-in-mm div $dpi"/>
+ <!-- ***** MEASUREMENT CONVERSIONS *****
+ PARAM 'value'
+ The measure to be converted.
+ The current measure is judged by a substring (e.g. 'mm', 'cm', 'in', 'pica'...)
+ directly added to the number.
+
+ PARAM 'rounding-factor'
+ Is used for the rounding of decimal places.
+ The parameter number is the product of 1 and some '10', where
+ every zero represents a decimal place.
+
+ For example, providing as parameter:
+ <xsl:param name="rounding-factor" select="10000" />
+ Gives by default four decimal places.
+
+ To round two decimal places, basically the following is done:
+ <xsl:value-of select="round(100 * value) div 100"/>
+
+ RETURN The converted number, by default rounded to four decimal places.
+ In case the input measure could not be matched the same value is
+ returned and a warning message is written out.
+
+
+
+ MEASURE LIST:
+ * 1 millimeter (mm), the basic measure
+
+ * 1 centimeter (cm) = 10 mm
+
+ * 1 inch (in) = 25.4 mm
+ While the English have already seen the light (read: the metric system), the US
+ remains loyal to this medieval system.
+
+ * 1 point (pt) = 0.35277777.. mm
+ Sometimes called PostScript point (ppt), as when Adobe created PostScript, they added their own system of points.
+ There are exactly 72 PostScript points in 1 inch.
+
+ * 1 twip = twentieth of a (PostScript) point
+ A twip (twentieth of a point) is a 1/20th of a PostScript point, a traditional measure in printing.
+
+ * 1 didot point (dpt) = 0.376065 mm
+ Didot point after the French typographer Firmin Didot (1764-1836).
+
+ More details under
+ http://www.unc.edu/~rowlett/units/dictP.html:
+ "A unit of length used by typographers and printers. When printing was done
+ from hand-set metal type, one point represented the smallest element of type
+ that could be handled, roughly 1/64 inch. Eventually, the point was standardized
+ in Britain and America as exactly 1/72.27 = 0.013 837 inch, which is
+ about 0.35 mm (351.46 micrometers). In continental Europe, typographers
+ traditionally used a slightly larger point of 0.014 83 inch (about
+ 1/72 pouce, 0.377 mm, or roughly 1/67 English inch), called a Didot point
+ after the French typographer Firmin Didot (1764-1836). In the U.S.,
+ Adobe software defines the point to be exactly 1/72 inch (0.013 888 9 inch
+ or 0.352 777 8 millimeters) and TeX software uses a slightly smaller point
+ of 0.351 459 8035 mm. The German standards agency DIN has proposed that
+ all these units be replaced by multiples of 0.25 millimeters (1/101.6 inch).
+
+ * 1 pica = 4.233333 mm
+ 1/6 inch or 12 points
+
+ * 1 pixel (px) = 0.26458333.. mm (relative to 'DPI', here: 96 dpi)
+ Most pictures have the 96 dpi resolution, but the dpi variable may vary by stylesheet parameter
+
+
+ -->
+ <!-- changing measure to mm -->
+ <xsl:template name="convert2mm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="substring-before($value, 'mm')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm' ) * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in' ) * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'mm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to cm -->
+ <xsl:template name="convert2cm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="substring-before($value, 'cm')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $centimeter-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $centimeter-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $centimeter-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $centimeter-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $centimeter-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $centimeter-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'cm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to inch (cp. section comment) -->
+ <xsl:template name="convert2in">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $inch-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="substring-before($value, 'in')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $inch-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $inch-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $inch-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $inch-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $inch-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'in'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to dpt (cp. section comment) -->
+ <xsl:template name="convert2dpt">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $didot-point-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $didot-point-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $didot-point-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="substring-before($value, 'dpt')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $didot-point-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $didot-point-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $didot-point-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'dpt'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pica (cp. section comment) -->
+ <xsl:template name="convert2pica">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $pica-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $pica-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $pica-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $pica-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="substring-before($value, 'pica')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $pica-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $pica-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'pica'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pt (cp. section comment) -->
+ <xsl:template name="convert2pt">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $point-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $point-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="substring-before($value, 'pt')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $point-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $point-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $point-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $point-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'pt'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="编号解析">
+ <xsl:variable name="bianhao">
+ <xsl:value-of select="字:段落属性/字:自动编号信息/@字:编号引用"/>
+ </xsl:variable>
+ <xsl:variable name="bianhaojibie">
+ <xsl:value-of select="字:段落属性/字:自动编号信息/@字:编号级别"/>
+ </xsl:variable>
+ <xsl:variable name="isxiangmuorisimage">
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号">
+ <xsl:choose>
+ <xsl:when test="$bianhao=@字:标识符">
+ <xsl:choose>
+ <xsl:when test="字:级别[@字:级别值= (number($bianhaojibie))]/字:项目符号">true</xsl:when>
+ <xsl:when test="字:级别[@字:级别值= (number($bianhaojibie))]/字:图片符号引用">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$isxiangmuorisimage='true'">
+ <xsl:call-template name="无序"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="有序"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="有序">
+ <xsl:variable name="currlistid" select="字:段落属性/字:自动编号信息/@字:编号引用"/>
+ <xsl:variable name="currlistlvl" select="字:段落属性/字:自动编号信息/@字:编号级别"/>
+ <xsl:variable name="firstoccur" select="/descendant::字:段落属性[字:自动编号信息/@字:编号引用 = $currlistid][1]"/>
+ <xsl:element name="text:list">
+ <xsl:attribute name="text:style-name">List<xsl:value-of select="count($firstoccur/preceding::字:自动编号信息)"/></xsl:attribute>
+ <xsl:if test="字:段落属性/字:自动编号信息/@字:重新编号">
+ <xsl:attribute name="text:continue-numbering"><xsl:choose><xsl:when test="字:段落属性/字:自动编号信息/@字:重新编号='true'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="ordered-levels">
+ <xsl:with-param name="level" select="$currlistlvl -1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="ordered-levels">
+ <xsl:param name="level"/>
+ <xsl:choose>
+ <xsl:when test="$level = '0'">
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="text:list">
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="ordered-levels">
+ <xsl:with-param name="level" select="$level -1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="无序">
+ <xsl:variable name="currlistid" select="字:段落属性/字:自动编号信息/@字:编号引用"/>
+ <xsl:variable name="currlistlvl" select="字:段落属性/字:自动编号信息/@字:编号级别"/>
+ <xsl:variable name="firstoccur" select="/descendant::字:段落属性[字:自动编号信息/@字:编号引用 = $currlistid][1]"/>
+ <xsl:element name="text:list">
+ <xsl:attribute name="text:style-name">List<xsl:value-of select="count($firstoccur/preceding::字:自动编号信息)"/></xsl:attribute>
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="unordered-levels">
+ <xsl:with-param name="level" select="$currlistlvl -1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="unordered-levels">
+ <xsl:param name="level"/>
+ <xsl:choose>
+ <xsl:when test="$level = '0'">
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="text:list">
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="unordered-levels">
+ <xsl:with-param name="level" select="$level -1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pt (cp. section comment) -->
+ <xsl:template name="convert2twip">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $twip-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $twip-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $twip-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $twip-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $twip-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="substring-before($value, 'twip')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $twip-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'twip'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pixel by via parameter provided dpi (dots per inch) standard factor (cp. section comment) -->
+ <xsl:template name="convert2px">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round(number(substring-before($value, 'mm')) div $pixel-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round(number(substring-before($value, 'cm')) div $pixel-in-mm * $centimeter-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round(number(substring-before($value, 'in')) div $pixel-in-mm * $inch-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round(number(substring-before($value, 'pt')) div $pixel-in-mm * $point-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round(number(substring-before($value, 'dpt')) div $pixel-in-mm * $didot-point-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round(number(substring-before($value, 'pica')) div $pixel-in-mm * $pica-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round(number(substring-before($value, 'twip')) div $pixel-in-mm * $twip-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'px'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/uof/uof2odf_spreadsheet.xsl b/filter/source/xslt/import/uof/uof2odf_spreadsheet.xsl
new file mode 100644
index 000000000..95d0d6b9d
--- /dev/null
+++ b/filter/source/xslt/import/uof/uof2odf_spreadsheet.xsl
@@ -0,0 +1,9071 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:图="http://schemas.uof.org/cn/2003/graph" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" office:version="1.0">
+ <xsl:output method="xml" indent="no" encoding="UTF-8" version="1.0"/>
+ <xsl:template match="uof:UOF">
+ <!--chengxz0804 OK-->
+ <!--office:document xmlns:office="http://openoffice.org/2000/office" xmlns:style="http://openoffice.org/2000/style" xmlns:text="http://openoffice.org/2000/text" xmlns:table="http://openoffice.org/2000/table" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="http://openoffice.org/2000/meta" xmlns:number="http://openoffice.org/2000/datastyle" xmlns:svg="http://www.w3.org/2000/svg" xmlns:chart="http://openoffice.org/2000/chart" xmlns:dr3d="http://openoffice.org/2000/dr3d" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="http://openoffice.org/2000/form" xmlns:script="http://openoffice.org/2000/script" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.0" office:class="spreadsheet"-->
+ <office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" office:version="1.0">
+ <xsl:apply-templates select="uof:元数据"/>
+ <office:settings>
+ <xsl:call-template name="工作表属性"/>
+ </office:settings>
+ <xsl:apply-templates select="uof:式样集"/>
+ <!--xsl:apply-templates select="表:公用处理规则"/-->
+ <xsl:apply-templates select="uof:电子表格"/>
+ </office:document>
+ </xsl:template>
+ <!--Redoffice comment lil from chenjh SC0013 06.02.15-->
+ <!--增加内容-->
+ <xsl:variable name="uofUnit">
+ <xsl:variable name="uu">
+ <xsl:value-of select="/uof:UOF/uof:电子表格/表:公用处理规则/表:度量单位"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$uu='cm'">cm</xsl:when>
+ <xsl:when test="$uu='mm'">mm</xsl:when>
+ <xsl:when test="$uu='pt'">pt</xsl:when>
+ <xsl:when test="$uu='inch'">inch</xsl:when>
+ <xsl:otherwise>cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="other-to-cm-conversion-factor">
+ <xsl:choose>
+ <xsl:when test="$uofUnit='cm'">1</xsl:when>
+ <xsl:when test="$uofUnit='mm'">0.1</xsl:when>
+ <xsl:when test="$uofUnit='pt'">0.03527</xsl:when>
+ <xsl:when test="$uofUnit='inch'">2.54</xsl:when>
+ <xsl:when test="$uofUnit='pica'">0.4233</xsl:when>
+ <xsl:otherwise>0.03527</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!--Redoffice comment liliang end 06.02.15-->
+ <xsl:template name="set-calculation">
+ <xsl:element name="table:calculation-settings">
+ <xsl:if test="表:公用处理规则/表:度量单位">
+ <xsl:variable name="uofUnit">
+ <xsl:variable name="uu">
+ <xsl:value-of select="表:公用处理规则/表:度量单位"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$uu='cm'">cm</xsl:when>
+ <xsl:when test="$uu='mm'">mm</xsl:when>
+ <xsl:when test="$uu='pt'">pt</xsl:when>
+ <xsl:when test="$uu='inch'">inch</xsl:when>
+ <xsl:otherwise>cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="other-to-cm-conversion-factor">
+ <xsl:choose>
+ <xsl:when test="$uofUnit='cm'">1</xsl:when>
+ <xsl:when test="$uofUnit='mm'">0.1</xsl:when>
+ <xsl:when test="$uofUnit='pt'">0.03527</xsl:when>
+ <xsl:when test="$uofUnit='inch'">2.54</xsl:when>
+ <xsl:when test="$uofUnit='pica'">0.4233</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ </xsl:if>
+ <xsl:if test="表:公用处理规则/表:精确度以显示值为准">
+ <xsl:attribute name="table:precision-as-shown">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:公用处理规则/表:日期系统-1904/@表:值='true'">
+ <table:null-date table:date-value="1904-01-01"/>
+ </xsl:if>
+ <xsl:if test="表:公用处理规则/表:计算设置">
+ <xsl:element name="table:iteration">
+ <xsl:attribute name="table:status">enable</xsl:attribute>
+ <xsl:attribute name="table:steps"><xsl:value-of select="表:公用处理规则/表:计算设置/@表:迭代次数"/></xsl:attribute>
+ <xsl:attribute name="table:maximum-difference"><xsl:value-of select="表:公用处理规则/表:计算设置/@表:偏差值"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="uof:字体集">
+ <xsl:if test="not(uof:字体声明[@uof:名称='StarSymbol'])">
+ <style:font-face style:name="StarSymbol" fo:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </xsl:if>
+ <xsl:for-each select="uof:字体声明">
+ <xsl:element name="style:font-face">
+ <xsl:attribute name="style:name"><xsl:value-of select="@uof:名称"/></xsl:attribute>
+ <xsl:attribute name="svg:font-family"><xsl:value-of select="@uof:字体族"/></xsl:attribute>
+ <xsl:if test="@uof:字符集 = '02'">
+ <xsl:attribute name="style:font-charset">x-symbol</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@uof:字体族">
+ <xsl:choose>
+ <xsl:when test="@uof:字体族 = 'Swiss'">
+ <xsl:attribute name="style:font-family-generic">swiss</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Modern'">
+ <xsl:attribute name="style:font-family-generic">modern</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族='Roman'">
+ <xsl:attribute name="style:font-family-generic">roman</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Script'">
+ <xsl:attribute name="style:font-family-generic">script</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Decorative'">
+ <xsl:attribute name="style:font-family-generic">decorative</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='System'">
+ <xsl:attribute name="style:font-family-generic">system</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:font-family-generic">system</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:attribute name="style:font-pitch">12</xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:apply-templates select="uof:字体声明"/>
+ </xsl:template>
+ <xsl:template match="uof:电子表格">
+ <office:body>
+ <office:spreadsheet>
+ <xsl:call-template name="trackchange"/>
+ <xsl:call-template name="set-calculation"/>
+ <xsl:if test="表:公用处理规则/表:数据有效性集">
+ <xsl:element name="table:content-validations">
+ <xsl:call-template name="create-content-validations">
+ <xsl:with-param name="validation-set" select="表:公用处理规则/表:数据有效性集/表:数据有效性"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:apply-templates select="表:主体/表:工作表"/>
+ <!--MSexcel 中的names暂时没有对应的-->
+ <xsl:element name="table:database-ranges">
+ <xsl:for-each select="表:主体/表:工作表">
+ <xsl:if test="./表:筛选">
+ <xsl:variable name="filter" select="./表:筛选"/>
+ <xsl:variable name="column-and-row" select="substring-before(substring-after($filter/表:范围/text(),'.'),':')"/>
+ <xsl:variable name="dd" select="number(substring($column-and-row,2,1))"/>
+ <xsl:variable name="zone-left-column-string">
+ <xsl:choose>
+ <xsl:when test="contains($dd,'NaN') ">
+ <xsl:value-of select="substring($column-and-row,1,2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring($column-and-row,1,1)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="zone-left-column-num">
+ <xsl:call-template name="translate-column-char-to-number">
+ <xsl:with-param name="string" select="$zone-left-column-string"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="table:database-range">
+ <xsl:attribute name="table:name"><xsl:value-of select="uof:电子表格/表:主体/表:工作表/@表:名称"/></xsl:attribute>
+ <xsl:attribute name="table:target-range-address"><xsl:call-template name="translate-expression2"><xsl:with-param name="expression2" select="translate($filter/表:范围/text(),'$','')"/></xsl:call-template></xsl:attribute>
+ <xsl:if test="$filter/@表:类型='auto'">
+ <xsl:attribute name="table:display-filter-buttons">true</xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="$filter/表:条件区域">
+ <xsl:element name="table:filter">
+ <xsl:attribute name="table:condition-source-range-address"><xsl:call-template name="translate-expression2"><xsl:with-param name="expression2" select="translate($filter/表:条件区域/text(),'$','')"/></xsl:call-template></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="table:filter">
+ <xsl:element name="table:filter-and">
+ <xsl:call-template name="auto-filter-condition">
+ <xsl:with-param name="condition-set" select="$filter/表:条件"/>
+ <xsl:with-param name="zone-left-column-num" select="$zone-left-column-num"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </office:spreadsheet>
+ </office:body>
+ </xsl:template>
+ <xsl:template name="trackchange">
+ <xsl:for-each select="表:主体/表:工作表/表:工作表内容//字:修订开始">
+ <xsl:variable name="num">
+ <xsl:number level="any" from="表:主体/表:工作表/表:工作表内容//*" count="字:修订开始"/>
+ </xsl:variable>
+ <table:tracked-changes>
+ <table:cell-content-change>
+ <xsl:attribute name="table:id"><xsl:value-of select="concat('ct',$num)"/></xsl:attribute>
+ <table:cell-address>
+ <xsl:attribute name="table:column"><xsl:value-of select="substring-after(@字:标识符,'-')"/></xsl:attribute>
+ <xsl:attribute name="table:row"><xsl:value-of select="substring-before(@字:标识符,'-')"/></xsl:attribute>
+ <xsl:attribute name="table:table">0</xsl:attribute>
+ </table:cell-address>
+ <office:change-info>
+ <dc:creator>
+ <xsl:choose>
+ <xsl:when test="starts-with(@字:修订信息引用,'+')"/>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(@字:修订信息引用,'+')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </dc:creator>
+ <!--xsl:value-of select="/uof:UOF/uof:元数据/uof:作者"/-->
+ <!--xsl:value-of select="/uof:UOF/uof:元数据/uof:创建日期"/-->
+ <dc:date>
+ <xsl:value-of select="substring-before(substring-after(@字:修订信息引用,'+'),'%')"/>
+ </dc:date>
+ </office:change-info>
+ <table:previous>
+ <table:change-track-table-cell>
+ <text:p>
+ <xsl:value-of select="substring-after(@字:修订信息引用,'%')"/>
+ </text:p>
+ </table:change-track-table-cell>
+ </table:previous>
+ </table:cell-content-change>
+ </table:tracked-changes>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="uof:式样集">
+ <xsl:element name="office:font-face-decls">
+ <style:font-face style:name="宋体" svg:font-family="宋体" style:font-family-generic="swiss"/>
+ <xsl:apply-templates select="uof:字体集"/>
+ </xsl:element>
+ <xsl:call-template name="单元格式样"/>
+ </xsl:template>
+ <xsl:key match="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/uof:锚点 | /uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:行/表:单元格/uof:锚点" name="rel_graphic_name" use="@uof:图形引用"/>
+ <xsl:template match="图:图形">
+ <xsl:variable name="random-name">
+ <xsl:value-of select="generate-id()"/>
+ </xsl:variable>
+ <xsl:variable name="draw-name">
+ <xsl:value-of select="substring($random-name,string-length($random-name)-1)"/>
+ </xsl:variable>
+ <xsl:call-template name="graphic-fill">
+ <xsl:with-param name="draw-name" select="$draw-name"/>
+ <xsl:with-param name="gradient-name" select="图:预定义图形/图:属性/图:填充/图:渐变"/>
+ </xsl:call-template>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:渐变">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family">graphic</xsl:attribute>
+ <xsl:element name="style:graphic-properties">
+ <xsl:call-template name="process-graphics">
+ <xsl:with-param name="draw-name" select="$draw-name"/>
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:element name="style:paragraph-properties">
+ <xsl:if test="图:文本内容/@图:文字排列方向">
+ <xsl:choose>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-l2r'">
+ <xsl:attribute name="style:writing-mode">tb-lr</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-r2l'">
+ <xsl:attribute name="style:writing-mode">tb-rl</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family">graphic</xsl:attribute>
+ <xsl:element name="style:graphic-properties">
+ <xsl:if test="@图:其他对象">
+ <xsl:attribute name="fo:clip">rect(0cm 0cm 0cm 0cm)</xsl:attribute>
+ <xsl:attribute name="draw:color-mode">standard</xsl:attribute>
+ <xsl:attribute name="draw:luminance">0%</xsl:attribute>
+ <xsl:attribute name="draw:contrast">0%</xsl:attribute>
+ <xsl:attribute name="draw:gamma">100%</xsl:attribute>
+ <xsl:attribute name="draw:red">0%</xsl:attribute>
+ <xsl:attribute name="draw:green">0%</xsl:attribute>
+ <xsl:attribute name="draw:blue">0%</xsl:attribute>
+ <xsl:attribute name="draw:image-opacity">100%</xsl:attribute>
+ <xsl:attribute name="style:mirror">none</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-graphics"/>
+ </xsl:element>
+ <xsl:element name="style:paragraph-properties">
+ <xsl:if test="图:文本内容/@图:文字排列方向">
+ <xsl:choose>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-l2r'">
+ <xsl:attribute name="style:writing-mode">tb-lr</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-r2l'">
+ <xsl:attribute name="style:writing-mode">tb-rl</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="process-graphics">
+ <xsl:param name="draw-name"/>
+ <xsl:if test="not(key('rel_graphic_name',@图:标识符)/@uof:随动方式='movesize')">
+ <xsl:attribute name="style:protect"><xsl:choose><xsl:when test="key('rel_graphic_name',@图:标识符)/@uof:随动方式='move'">size</xsl:when><xsl:otherwise>position size</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="not(图:预定义图形/图:属性/图:填充)">
+ <xsl:attribute name="draw:fill">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图片">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-image-name"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"/></xsl:attribute>
+ <xsl:if test="not(图:预定义图形/图:属性/图:填充/图:图片/@图:位置='tile')">
+ <xsl:attribute name="style:repeat"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:位置='center'">no-repeat</xsl:when><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:位置='stretch'">stretch</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图案">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:前景色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:颜色">
+ <xsl:attribute name="draw:fill">solid</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:颜色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:渐变">
+ <xsl:attribute name="draw:fill">gradient</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:渐变/@图:起始色"/></xsl:attribute>
+ <xsl:attribute name="draw:fill-gradient-name"><xsl:value-of select="concat('Gradient ',$draw-name)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="图:预定义图形/图:属性/图:线颜色">
+ <xsl:attribute name="svg:stroke-color"><xsl:value-of select="图:预定义图形/图:属性/图:线颜色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:线型 and not(图:预定义图形/图:属性/图:线型 = 'single') and not(图:预定义图形/图:属性/图:线型 = 'thick')">
+ <xsl:variable name="type" select="图:预定义图形/图:属性/图:线型"/>
+ <xsl:attribute name="draw:stroke"><xsl:choose><xsl:when test="$type='none'">none</xsl:when><xsl:when test="$type='single'">solid</xsl:when><xsl:otherwise>dash</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="draw:stroke-dash"><xsl:choose><xsl:when test="$type='dash'">Ultrafine_20_Dashed</xsl:when><xsl:when test="$type='dot-dash'">Ultrafine_20_2_20_Dots_20_3_20_Dashes</xsl:when><xsl:when test="$type='dashed-heavy'">Fine_20_Dashed</xsl:when><xsl:when test="$type='dotted' ">Fine_20_Dotted</xsl:when><xsl:when test="$type='dash-long-heavy'">Line_20_with_20_Fine_20_Dots</xsl:when><xsl:when test="$type='dash-long'">Fine_20_Dashed_20__28_var_29_</xsl:when><xsl:when test="$type='dash-dot-dot'">_33__20_Dashes_20_3_20_Dots_20__28_var_29_</xsl:when><xsl:when test="$type='dotted-heavy'">Ultrafine_20_Dotted_20__28_var_29_</xsl:when><xsl:when test="$type='thick'">Line_20_Style_20_9</xsl:when><xsl:when test="$type='dot-dot-dash'">_32__20_Dots_20_1_20_Dash</xsl:when><xsl:when test="$type='dash-dot-dot-heavy'">Dashed_20__28_var_29_</xsl:when><xsl:when test="$type='dash-dot-heavy'">Dash_20_10</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:线粗细">
+ <xsl:attribute name="svg:stroke-width"><xsl:value-of select="concat(图:预定义图形/图:属性/图:线粗细,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头">
+ <xsl:attribute name="draw:marker-start"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">Line Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">Arrow concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">Square 45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头/图:大小">
+ <xsl:attribute name="draw:marker-start-width"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '1'"><xsl:value-of select="concat('0.05',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '2'"><xsl:value-of select="concat('0.10',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '3'"><xsl:value-of select="concat('0.15',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '4'"><xsl:value-of select="concat('0.20',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '5'"><xsl:value-of select="concat('0.25',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '6'"><xsl:value-of select="concat('0.30',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '7'"><xsl:value-of select="concat('0.35',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '8'"><xsl:value-of select="concat('0.40',$uofUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('0.45',$uofUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头">
+ <xsl:attribute name="draw:marker-end"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">Line Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">Arrow concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">Square 45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头/图:大小">
+ <xsl:attribute name="draw:marker-end-width"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '1'"><xsl:value-of select="concat('0.05',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '2'"><xsl:value-of select="concat('0.10',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '3'"><xsl:value-of select="concat('0.15',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '4'"><xsl:value-of select="concat('0.20',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '5'"><xsl:value-of select="concat('0.25',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '6'"><xsl:value-of select="concat('0.30',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '7'"><xsl:value-of select="concat('0.35',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '8'"><xsl:value-of select="concat('0.40',$uofUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('0.45',$uofUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:透明度">
+ <xsl:attribute name="draw:opacity"><xsl:value-of select="concat(图:预定义图形/图:属性/图:透明度,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:if test="图:文本内容/@图:上边距">
+ <xsl:attribute name="fo:padding-top"><xsl:value-of select="concat(图:文本内容/@图:上边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-bottom"><xsl:value-of select="concat(图:文本内容/@图:下边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-left"><xsl:value-of select="concat(图:文本内容/@图:左边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-right"><xsl:value-of select="concat(图:文本内容/@图:右边距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容/@图:文字排列方向">
+ <xsl:choose>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-l2r'">
+ <xsl:attribute name="style:writing-mode">tb-lr</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-r2l'">
+ <xsl:attribute name="style:writing-mode">tb-rl</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:文本内容/@图:文字排列方向='hori-r2l'">
+ <xsl:attribute name="draw:textarea-horizontal-align">right</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:文本内容/@图:文字排列方向='hori-12r'">
+ <xsl:attribute name="draw:textarea-horizontal-align">left</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="图:文本内容/@图:水平对齐">
+ <xsl:attribute name="draw:textarea-horizontal-align"><xsl:value-of select="图:文本内容/@图:水平对齐"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容/@图:垂直对齐">
+ <xsl:attribute name="draw:textarea-vertical-align"><xsl:value-of select="图:文本内容/@图:垂直对齐"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容/@图:自动换行">
+ <xsl:attribute name="fo:wrap-option">no-wrap</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:auto-grow-width"><xsl:choose><xsl:when test="图:文本内容/@图:大小适应文字">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="draw:auto-grow-height"><xsl:choose><xsl:when test="图:文本内容/@图:大小适应文字">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="bina_graphic">
+ <xsl:param name="refGraphic"/>
+ <xsl:element name="office:binary-data">
+ <xsl:for-each select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符 = $refGraphic]">
+ <xsl:value-of select="uof:数据"/>
+ </xsl:for-each>
+ </xsl:element>
+ <text:p/>
+ </xsl:template>
+ <xsl:template name="graphic-fill">
+ <xsl:param name="draw-name"/>
+ <xsl:param name="gradient-name"/>
+ <xsl:if test="图:预定义图形/图:属性/图:填充/图:渐变">
+ <xsl:element name="draw:gradient">
+ <xsl:attribute name="draw:name"><xsl:value-of select="concat('Gradient ',$draw-name)"/></xsl:attribute>
+ <xsl:attribute name="draw:style"><xsl:choose><xsl:when test="$gradient-name/@图:种子类型='linear'"><xsl:value-of select="'linear'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='radar'"><xsl:value-of select="'radial'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='oval'"><xsl:value-of select="'ellipsoid'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='square'"><xsl:value-of select="'square'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='rectangle'"><xsl:value-of select="'rectangular'"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="draw:start-color"><xsl:value-of select="$gradient-name/@图:起始色"/></xsl:attribute>
+ <xsl:attribute name="draw:end-color"><xsl:value-of select="$gradient-name/@图:终止色"/></xsl:attribute>
+ <xsl:attribute name="draw:start-intensity"><xsl:value-of select="concat($gradient-name/@图:起始浓度,'%')"/></xsl:attribute>
+ <xsl:attribute name="draw:end-intensity"><xsl:value-of select="concat($gradient-name/@图:终止浓度,'%')"/></xsl:attribute>
+ <xsl:attribute name="draw:angle"><xsl:value-of select="$gradient-name/@图:渐变方向 * 10"/></xsl:attribute>
+ <xsl:attribute name="draw:border"><xsl:value-of select="concat($gradient-name/@图:边界,'%')"/></xsl:attribute>
+ <xsl:if test="$gradient-name/@图:种子X位置">
+ <xsl:attribute name="draw:cx"><xsl:value-of select="concat($gradient-name/@图:种子X位置,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$gradient-name/@图:种子Y位置">
+ <xsl:attribute name="draw:cy"><xsl:value-of select="concat($gradient-name/@图:种子Y位置,'%')"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头">
+ <xsl:element name="draw:marker">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">Line Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">Arrow concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">Square 45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">
+ <xsl:attribute name="svg:viewBox">0 0 20 30</xsl:attribute>
+ <xsl:attribute name="svg:d">m10 0-10 30h20z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">
+ <xsl:attribute name="svg:viewBox">0 0 1122 2243</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1580</xsl:attribute>
+ <xsl:attribute name="svg:d">m1013 1491 118 89-567-1580-564 1580 114-85 136-68 148-46 161-17 161 13 153 46z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m462 1118-102-29-102-51-93-72-72-93-51-102-29-102-13-105 13-102 29-106 51-102 72-89 93-72 102-50 102-34 106-9 101 9 106 34 98 50 93 72 72 89 51 102 29 106 13 102-13 105-29 102-51 102-72 93-93 72-98 51-106 29-101 13z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 564 564 567 567-567-567-564z</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头">
+ <xsl:element name="draw:marker">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">Line Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">Arrow concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">Square 45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">
+ <xsl:attribute name="svg:viewBox">0 0 20 30</xsl:attribute>
+ <xsl:attribute name="svg:d">m10 0-10 30h20z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">
+ <xsl:attribute name="svg:viewBox">0 0 1122 2243</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1580</xsl:attribute>
+ <xsl:attribute name="svg:d">m1013 1491 118 89-567-1580-564 1580 114-85 136-68 148-46 161-17 161 13 153 46z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m462 1118-102-29-102-51-93-72-72-93-51-102-29-102-13-105 13-102 29-106 51-102 72-89 93-72 102-50 102-34 106-9 101 9 106 34 98 50 93 72 72 89 51 102 29 106 13 102-13 105-29 102-51 102-72 93-93 72-98 51-106 29-101 13z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 564 564 567 567-567-567-564z</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用 or 图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用">
+ <xsl:element name="draw:fill-image">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:类型"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:call-template name="bina_graphic">
+ <xsl:with-param name="refGraphic">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用">
+ <xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用"/>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用">
+ <xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="not(图:预定义图形/图:属性/图:线型='single') and not(图:预定义图形/图:属性/图:线型='thick') and 图:预定义图形/图:属性/图:线型">
+ <draw:stroke-dash draw:name="Ultrafine_20_Dashed" draw:display-name="Ultrafine Dashed" draw:style="rect" draw:dots1="1" draw:dots1-length="0.051cm" draw:dots2="1" draw:dots2-length="0.051cm" draw:distance="0.051cm"/>
+ <draw:stroke-dash draw:name="Fine_20_Dashed" draw:display-name="Fine Dashed" draw:style="rect" draw:dots1="1" draw:dots1-length="0.508cm" draw:dots2="1" draw:dots2-length="0.508cm" draw:distance="0.508cm"/>
+ <draw:stroke-dash draw:name="Ultrafine_20_2_20_Dots_20_3_20_Dashes" draw:display-name="Ultrafine 2 Dots 3 Dashes" draw:style="rect" draw:dots1="2" draw:dots1-length="0.051cm" draw:dots2="3" draw:dots2-length="0.254cm" draw:distance="0.127cm"/>
+ <draw:stroke-dash draw:name="Fine_20_Dashed_20__28_var_29_" draw:display-name="Fine Dashed (var)" draw:style="rect" draw:dots1="1" draw:dots1-length="197%" draw:distance="197%"/>
+ <draw:stroke-dash draw:name="Fine_20_Dotted" draw:display-name="Fine Dotted" draw:style="rect" draw:dots1="1" draw:distance="0.457cm"/>
+ <draw:stroke-dash draw:name="Fine_20_Dashed_20__28_var_29_" draw:display-name="Fine Dashed (var)" draw:style="rect" draw:dots1="1" draw:dots1-length="197%" draw:distance="197%"/>
+ <draw:stroke-dash draw:name="Fine_20_Dotted" draw:display-name="Fine Dotted" draw:style="rect" draw:dots1="1" draw:distance="0.457cm"/>
+ <draw:stroke-dash draw:name="Line_20_with_20_Fine_20_Dots" draw:display-name="Line with Fine Dots" draw:style="rect" draw:dots1="1" draw:dots1-length="2.007cm" draw:dots2="10" draw:distance="0.152cm"/>
+ <draw:stroke-dash draw:name="Line_20_Style_20_9" draw:display-name="Line Style 9" draw:style="rect" draw:dots1="1" draw:dots1-length="197%" draw:distance="120%"/>
+ <draw:stroke-dash draw:name="_33__20_Dashes_20_3_20_Dots_20__28_var_29_" draw:display-name="3 Dashes 3 Dots (var)" draw:style="rect" draw:dots1="3" draw:dots1-length="197%" draw:dots2="3" draw:distance="100%"/>
+ <draw:stroke-dash draw:name="_32__20_Dots_20_1_20_Dash" draw:display-name="2 Dots 1 Dash" draw:style="rect" draw:dots1="2" draw:dots2="1" draw:dots2-length="0.203cm" draw:distance="0.203cm"/>
+ <draw:stroke-dash draw:name="Ultrafine_20_Dotted_20__28_var_29_" draw:display-name="Ultrafine Dotted (var)" draw:style="rect" draw:dots1="1" draw:distance="50%"/>
+ <draw:stroke-dash draw:name="Dash_20_10" draw:display-name="Dash 10" draw:style="rect" draw:dots1="1" draw:dots1-length="0.02cm" draw:dots2="1" draw:dots2-length="0.02cm" draw:distance="0.02cm"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="单元格式样">
+ <xsl:variable name="uofSheet" select="/uof:UOF/uof:电子表格"/>
+ <xsl:variable name="uofSheet1" select="/uof:UOF/uof:电子表格/表:主体/表:工作表"/>
+ <xsl:variable name="uofSheetCom" select="$uofSheet/表:公用处理规则"/>
+ <xsl:variable name="first-style" select="/uof:UOF/uof:式样集/uof:单元格式样"/>
+ <xsl:variable name="quyu" select="/uof:UOF/uof:电子表格/表:公用处理规则/表:条件格式化集/表:条件格式化/表:区域"/>
+ <xsl:variable name="condition-format-set" select="/uof:UOF/uof:电子表格/表:公用处理规则/表:条件格式化集/表:条件格式化"/>
+ <xsl:variable name="aa">
+ <xsl:for-each select="$first-style">
+ <xsl:if test="@表:标识符!=@表:名称 and @表:名称!='Normal'">
+ <xsl:value-of select="@表:名称"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="bb">
+ <xsl:for-each select="$first-style">
+ <xsl:if test="@表:标识符!=@表:名称 and @表:名称!='Normal'">
+ <xsl:value-of select="@表:标识符"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <office:styles>
+ <!-- if ConditionalFormatting exists,it should generate some styles for style:style -->
+ <!--xsl:if test="$uofSheetCom/表:条件格式化集">
+ <xsl:call-template name="CondFormat_office_style"/>
+ </xsl:if-->
+ <!--ro000179 chenjh-->
+ <xsl:for-each select="$first-style[@表:类型='custom' or @表:类型='default']">
+ <xsl:call-template name="单元格具体式样"/>
+ <xsl:apply-templates select="表:数字格式[@表:格式码]"/>
+ <xsl:apply-templates select="表:字体格式[字:上下标]"/>
+ </xsl:for-each>
+ </office:styles>
+ <office:automatic-styles>
+ <xsl:for-each select="$first-style[@表:类型='auto']">
+ <xsl:variable name="apply-style-name" select="@表:名称"/>
+ <xsl:variable name="style-name" select="@表:标识符"/>
+ <xsl:choose>
+ <xsl:when test="$style-name!=$apply-style-name and $apply-style-name!='Normal'">
+ <xsl:for-each select="$condition-format-set/表:条件">
+ <style:style>
+ <xsl:attribute name="style:name"><xsl:value-of select="//uof:单元格式样[@表:名称=current()/表:格式/@表:式样引用 and @表:类型='auto']/@表:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family">table-cell</xsl:attribute>
+ <xsl:attribute name="style:parent-style-name">Default</xsl:attribute>
+ <xsl:for-each select="parent::表:条件格式化/表:条件">
+ <xsl:variable name="condition-text">
+ <xsl:choose>
+ <xsl:when test="@表:类型='cell value'">
+ <xsl:choose>
+ <xsl:when test="表:操作码/text()='between' ">
+ <xsl:value-of select="concat('cell-content-is-between','(',表:第一操作数/text(),',',表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test=" 表:操作码/text()='not between'">
+ <xsl:value-of select="concat('cell-content-is-not-between','(',表:第一操作数/text(),',',表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='equal to'">
+ <xsl:value-of select="concat('cell-content()=',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='not equal to'">
+ <xsl:value-of select="concat('cell-content()!=',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='greater than'">
+ <xsl:value-of select="concat('cell-content()&gt;',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='less than'">
+ <xsl:value-of select="concat('cell-content()&lt;',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='greater than or equal to'">
+ <xsl:value-of select="concat('cell-content()&gt;=',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='less than or equal to'">
+ <xsl:value-of select="concat('cell-content()&lt;=',表:第一操作数/text())"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@表:类型='formula'">
+ <xsl:value-of select="concat('is-true-formula','(',表:第一操作数/text(),')')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="style:map">
+ <xsl:variable name="address">
+ <xsl:value-of select="preceding-sibling::表:区域"/>
+ </xsl:variable>
+ <xsl:attribute name="style:condition"><xsl:value-of select="$condition-text"/></xsl:attribute>
+ <xsl:attribute name="style:apply-style-name"><xsl:value-of select="表:格式/@表:式样引用"/></xsl:attribute>
+ <xsl:attribute name="style:base-cell-address"><xsl:value-of select="substring-after($address,':')"/></xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </style:style>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="uof:单元格式样 ">
+ <xsl:if test="@表:类型='auto' and (@表:标识符=@表:名称 or @表:名称='Normal')">
+ <xsl:call-template name="单元格具体式样"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ <!--Redoffie comment liliang SC0008 06.02.14-->
+ <!--1新增内容-->
+ <xsl:if test="uof:单元格式样">
+ <xsl:for-each select="uof:单元格式样">
+ <xsl:if test="@表:类型='auto' and (@表:标识符=@表:名称 or @表:名称='Normal')">
+ <xsl:call-template name="单元格具体式样"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象/@uof:公有类型='png' or /uof:UOF/uof:对象集/uof:其他对象/@uof:公有类型='ipg' or /uof:UOF/uof:对象集/uof:其他对象/@uof:公有类型='bmp' or /uof:UOF/uof:对象集/uof:其他对象/@uof:公有类型='gif'">
+ <style:style style:name="Graphics" style:family="graphics">
+ <style:properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="none" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/>
+ </style:style>
+ </xsl:if>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形"/>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形/图:文本内容/字:段落/字:句/字:句属性" mode="style"/>
+ <!--Redoffice comment end 06.02.14-->
+ <xsl:apply-templates select="$uofSheet1/表:工作表内容"/>
+ <xsl:if test="uof:单元格式样">
+ <xsl:for-each select="uof:单元格式样[@表:类型='auto' and (@表:标识符=@表:名称 or @表:名称='Normal')]">
+ <xsl:call-template name="单元格具体式样"/>
+ <xsl:apply-templates select="表:数字格式[@表:格式码]"/>
+ <xsl:apply-templates select="表:字体格式[字:上下标]"/>
+ </xsl:for-each>
+ </xsl:if>
+ <!-- if ConditionalFormatting exists,transforing the styles -->
+ <!--xsl:if test="$uofSheetCom/表:条件格式化集">
+ <xsl:call-template name="CondFormat_automatic_style"/>
+ </xsl:if-->
+ <xsl:if test="$uofSheetCom/表:条件格式化集/表:条件格式化">
+ <xsl:variable name="style-name" select="$first-style/@表:标识符"/>
+ <xsl:variable name="left-top">
+ <xsl:call-template name="search-left-top-in-tables">
+ <xsl:with-param name="cellstylename" select="$style-name"/>
+ <xsl:with-param name="tableslist" select="$uofSheet1/表:工作表内容"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="after-translated-left-top">
+ <xsl:call-template name="translate-left-top">
+ <xsl:with-param name="left-top" select="$left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$after-translated-left-top!=''">
+ <xsl:call-template name="create-the-condition-format-map">
+ <xsl:with-param name="condition-format-set" select="$uofSheetCom/表:条件格式化集//表:条件格式化"/>
+ <xsl:with-param name="current-left-top" select="$after-translated-left-top"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ <xsl:apply-templates select="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:列/表:单元格/*[descendant-or-self::*[namespace-uri()='http://www.w3.org/TR/REC-html40']]"/>
+ <!--xsl:apply-templates select="$uofSheet1/表:工作表属性/表:页面设置/表:页眉页脚/字:段落" /-->
+ <xsl:call-template name="create-page-master">
+ <xsl:with-param name="worksheetoptions" select="$uofSheet1/表:工作表属性"/>
+ </xsl:call-template>
+ <xsl:for-each select="uof:句式样">
+ <style:style>
+ <xsl:attribute name="style:name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ <style:text-properties>
+ <xsl:apply-templates select="./*"/>
+ </style:text-properties>
+ </style:style>
+ </xsl:for-each>
+ </office:automatic-styles>
+ <office:master-styles>
+ <xsl:call-template name="create-master-styles">
+ <xsl:with-param name="worksheetoptions" select="$uofSheet1/表:工作表属性"/>
+ </xsl:call-template>
+ </office:master-styles>
+ </xsl:template>
+ <xsl:template match="表:数据有效性">
+ <xsl:variable name="range-name-temp">
+ <xsl:value-of select="substring-before(表:区域,'!')"/>
+ </xsl:variable>
+ <xsl:variable name="range-name">
+ <xsl:value-of select="substring($range-name-temp,2,string-length($range-name-temp)-2)"/>
+ </xsl:variable>
+ <xsl:variable name="first-range">
+ <xsl:choose>
+ <xsl:when test="contains(表:区域, ',')">
+ <xsl:value-of select="translate(substring-after(substring-before(表:区域, ','),'!'),'$','')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(substring-after(表:区域,'!'),'$','')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="value-first">
+ <xsl:value-of select="translate(表:第一操作数,'=','')"/>
+ </xsl:variable>
+ <xsl:variable name="value-second">
+ <xsl:value-of select="translate(表:第二操作数,'=','')"/>
+ </xsl:variable>
+ <xsl:element name="table:content-validation">
+ <xsl:attribute name="table:name"><xsl:value-of select="concat('val', position())"/></xsl:attribute>
+ <!--数据有效性:第一操作数、第二操作数-->
+ <!-- don't support two type of qualifier: List, Custom -->
+ <xsl:attribute name="table:condition"><xsl:variable name="qualifier-content"><xsl:choose><xsl:when test="表:操作码 = 'between'"><xsl:choose><xsl:when test="(number($value-second))"><xsl:value-of select="concat('cell-content-is-between([',$range-name,'.',$value-first,'],',$value-second)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('cell-content-is-between([',$range-name,'.',$value-first,'],[',$range-name,'.',$value-second,']')"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="表:操作码 = 'not between'"><xsl:choose><xsl:when test="number($value-second)"><xsl:value-of select="concat('cell-content-is-not-between([',$range-name,'.',$value-first,'],',$value-second)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('cell-content-is-not-between([',$range-name,'.',$value-first,'],[',$range-name,'.',$value-second,']')"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="表:操作码 = 'not equal to'"><xsl:value-of select="concat('!=', $value-first)"/></xsl:when><xsl:when test="表:操作码 = 'equal to'"><xsl:variable name="range1"><xsl:value-of select="substring-after(substring-before($value-first,':'),'(')"/></xsl:variable><xsl:variable name="range2"><xsl:value-of select="substring-before(substring-after($value-first,':'),')')"/></xsl:variable><xsl:value-of select="concat('=SUM([',$range-name,'.',$range1,':',$range-name,'.',$range2,']')"/></xsl:when><xsl:when test="表:操作码 = 'less than'"><xsl:value-of select="concat('&lt;', $value-first)"/></xsl:when><xsl:when test="表:操作码 = 'greater than'"><xsl:value-of select="concat('&gt;', $value-first)"/></xsl:when><xsl:when test="表:操作码 = 'greater than or equal to'"><xsl:value-of select="concat('&gt;=[',$range-name, '.',$value-first,']')"/></xsl:when><xsl:when test="表:操作码 = 'less than or equal to'"><xsl:value-of select="concat('&lt;=[',$range-name,'.', $value-first,']')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('([',$range-name,'.',substring-before($value-first,':'),':',$range-name,'.',substring-after($value-first,':'),'])')"/></xsl:otherwise></xsl:choose></xsl:variable><!--操作码、校验类型--><xsl:variable name="qualifier-value"><xsl:choose><xsl:when test="表:校验类型 = 'whole number'"><xsl:choose><xsl:when test="(表:操作码 = 'not between') or (表:操作码 = 'between')"><xsl:value-of select="concat('oooc:cell-content-is-whole-number() and ', $qualifier-content, ')')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-is-whole-number() and ', 'cell-content()', $qualifier-content)"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="表:校验类型 = 'decimal'"><xsl:choose><xsl:when test="(表:操作码 = 'not between') or (表:操作码 = 'between')"><xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and ', $qualifier-content, ')')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and ', 'cell-content()', $qualifier-content)"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="表:校验类型 = 'list'"><xsl:choose><xsl:when test="(表:操作码 = 'not between') or (表:操作码 = 'between')"><xsl:value-of select="concat('oooc:cell-content-is-in-list() and ', $qualifier-content, ')')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-is-in-list',$qualifier-content)"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="表:校验类型 = 'date'"><xsl:choose><xsl:when test="(表:操作码 = 'not between') or (表:操作码 = 'between')"><xsl:value-of select="concat('oooc:cell-content-is-date() and ', $qualifier-content, ')')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-is-date() and ', 'cell-content()', $qualifier-content)"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="表:校验类型 = 'time'"><xsl:choose><xsl:when test="(表:操作码 = 'not between') or (表:操作码 = 'between')"><xsl:value-of select="concat('oooc:cell-content-is-time() and ', $qualifier-content, ')')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-is-time() and ', 'cell-content()', $qualifier-content)"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="表:校验类型 = 'text length'"><xsl:choose><xsl:when test="表:操作码 = 'not between'"><xsl:choose><xsl:when test="number($value-second)"><xsl:value-of select="concat('oooc:cell-content-text-length-is-not-between([', $range-name,'.',$value-first, '],', $value-second, ')')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-text-length-is-not-between([',$range-name,'.', $value-first, '],[',$range-name,'.', $value-second, '])')"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="$value-second and $value-first"><xsl:choose><xsl:when test="number($value-second)"><xsl:value-of select="concat('oooc:cell-content-text-length-is-between([',$range-name,'.',$value-first,'],',$value-second,')')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-text-length-is-between([',$range-name,'.',$value-first,'],[',$range-name,'.',$value-second,'])')"/></xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-text-length()', $qualifier-content)"/></xsl:otherwise></xsl:choose></xsl:when><xsl:when test="表:校验类型 = 'custom'"><xsl:choose><xsl:when test="表:操作码 = 'between'"><xsl:value-of select="concat('and cell-content-is-between(',substring-before($value-first,'('),'([',$range-name,'.',substring-after(substring-before($value-first,':'),'('),':',$range-name,'.',substring-before(substring-after($value-first,':'),')'),']),0')"/></xsl:when><xsl:when test="表:操作码 = 'not between'"><xsl:value-of select="concat('oooc:and cell-content-is-not-between(',substring-before($value-first,'('),'([',$range-name,'.',substring-after(substring-before($value-first,':'),'('),':',$range-name,'.',substring-before(substring-after($value-first,':'),')'),']),0')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('oooc:cell-content-is-custom() and ', 'cell-content()', $qualifier-content)"/></xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise><xsl:value-of select="表:校验类型"/></xsl:otherwise></xsl:choose></xsl:variable><xsl:value-of select="$qualifier-value"/></xsl:attribute>
+ <!--忽略空格-->
+ <xsl:attribute name="table:allow-empty-cell"><xsl:choose><xsl:when test="表:忽略空格"><xsl:value-of select="'false'"/></xsl:when><xsl:otherwise><xsl:value-of select="'true'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="table:base-cell-address"><xsl:variable name="range"><xsl:value-of select="$first-range"/><!--xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0" />
+ <xsl:with-param name="cell-column-pos" select="0" />
+ <xsl:with-param name="expression" select="$first-range" />
+ <xsl:with-param name="return-value" select="''" />
+ </xsl:call-template--></xsl:variable><xsl:call-template name="encode-as-cell-address"><xsl:with-param name="string" select="concat($range-name, '.', $range)"/></xsl:call-template></xsl:attribute>
+ <!--输入提示-->
+ <xsl:element name="table:help-message">
+ <xsl:attribute name="table:title"><xsl:value-of select="表:输入提示/@表:标题"/></xsl:attribute>
+ <xsl:attribute name="table:display"><xsl:choose><xsl:when test="表:输入提示/@表:显示"><xsl:value-of select="表:输入提示/@表:显示"/></xsl:when><xsl:otherwise><xsl:value-of select="'false'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:element name="text:p">
+ <xsl:value-of select="表:输入提示/@表:内容"/>
+ </xsl:element>
+ </xsl:element>
+ <!--错误提示-->
+ <xsl:element name="table:error-message">
+ <xsl:attribute name="table:message-type"><xsl:choose><xsl:when test="表:错误提示/@表:类型= 'information'"><xsl:value-of select="'information'"/></xsl:when><xsl:when test="表:错误提示/@表:类型= 'warning'"><xsl:value-of select="'warning'"/></xsl:when><xsl:otherwise><xsl:value-of select="'stop'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="table:title"><xsl:value-of select="表:错误提示/@表:标题"/></xsl:attribute>
+ <xsl:attribute name="table:display"><xsl:choose><xsl:when test="表:错误提示/@表:显示"><xsl:value-of select="表:错误提示/@表:显示"/></xsl:when><xsl:otherwise><xsl:value-of select="'false'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:element name="text:p">
+ <xsl:value-of select="表:错误提示/@表:内容"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="CondFormat_office_style">
+ <xsl:for-each select="../../uof:电子表格/表:公用处理规则/表:条件格式化集/表:条件格式化">
+ <xsl:variable name="table-pos" select="count(../../../preceding-sibling::表:公用处理规则)+1"/>
+ <xsl:variable name="conditions" select="count(../preceding-sibling::表:条件格式化集)+1"/>
+ <xsl:for-each select="表:条件">
+ <xsl:variable name="condition-number" select="count(preceding-sibling::表:条件)+1"/>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:call-template name="encode-as-nc-name"><xsl:with-param name="string" select="concat('Excel_CondFormat_',$table-pos,'_',$conditions,'_',$condition-number)"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="style:family">table-cell</xsl:attribute>
+ <xsl:element name="style:properties">
+ <xsl:choose>
+ <xsl:when test="表:格式/@表:式样引用">
+ <xsl:variable name="stylevalue" select="表:格式/@表:式样引用"/>
+ <xsl:call-template name="recursion-condformat-style-table-cell">
+ <xsl:with-param name="style-value-t">
+ <xsl:choose>
+ <xsl:when test="substring($stylevalue,string-length($stylevalue),1) != ';'">
+ <xsl:value-of select="concat($stylevalue,';')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$stylevalue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <!--xsl:element name="style:text-properties"-->
+ <!--chengxz0618-->
+ <xsl:element name="style:properties">
+ <xsl:choose>
+ <xsl:when test="表:格式/@表:式样引用">
+ <xsl:variable name="stylevalue" select="表:格式/@表:式样引用"/>
+ <xsl:call-template name="recursion-condformat-style-text">
+ <xsl:with-param name="style-value-t">
+ <xsl:choose>
+ <xsl:when test="substring($stylevalue,string-length($stylevalue),1) != ';'">
+ <xsl:value-of select="concat($stylevalue,';')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$stylevalue"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:font-style"><xsl:value-of select="'italic'"/></xsl:attribute>
+ <xsl:attribute name="style:text-underline-type"><xsl:value-of select="'single'"/></xsl:attribute>
+ <xsl:attribute name="style:text-underline-color"><xsl:value-of select="'font-color'"/></xsl:attribute>
+ <xsl:attribute name="fo:font-weight"><xsl:value-of select="'bold'"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="cell-pattern-color">
+ <xsl:param name="pattern"/>
+ <xsl:param name="color-value"/>
+ <xsl:param name="pattern-color-value"/>
+ <xsl:variable name="rev-pattern" select="1 - $pattern"/>
+ <xsl:variable name="color-R-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($color-value,2,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="color-G-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($color-value,4,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="color-B-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($color-value,6,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="pattern-R-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($pattern-color-value,2,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="pattern-G-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($pattern-color-value,4,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="pattern-B-value">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="substring($pattern-color-value,6,2)"/>
+ <xsl:with-param name="index" select="1"/>
+ <xsl:with-param name="str-length" select="2"/>
+ <xsl:with-param name="last-value" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="R-value">
+ <xsl:variable name="combined-R-value">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="floor($color-R-value * $rev-pattern + $pattern-R-value * $pattern)"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($combined-R-value) = 1">
+ <xsl:value-of select="concat('0',$combined-R-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$combined-R-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="G-value">
+ <xsl:variable name="combined-G-value">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="floor($color-G-value * $rev-pattern + $pattern-G-value * $pattern)"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($combined-G-value) = 1">
+ <xsl:value-of select="concat('0',$combined-G-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$combined-G-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="B-value">
+ <xsl:variable name="combined-B-value">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="floor($color-B-value * $rev-pattern + $pattern-B-value * $pattern)"/>
+ <xsl:with-param name="last-value" select="'H'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length($combined-B-value) = 1">
+ <xsl:value-of select="concat('0',$combined-B-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$combined-B-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat('#',$R-value,$G-value,$B-value)"/>
+ </xsl:template>
+ <xsl:template name="hex2decimal">
+ <xsl:param name="hex-number"/>
+ <xsl:param name="index"/>
+ <xsl:param name="str-length"/>
+ <xsl:param name="last-value"/>
+ <xsl:variable name="dec-char">
+ <xsl:call-template name="hexNumber2dec">
+ <xsl:with-param name="hex-value" select="substring($hex-number, $index ,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="current-value" select="$last-value * 16 + $dec-char"/>
+ <xsl:if test="$index &lt; $str-length">
+ <xsl:call-template name="hex2decimal">
+ <xsl:with-param name="hex-number" select="$hex-number"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ <xsl:with-param name="str-length" select="$str-length"/>
+ <xsl:with-param name="last-value" select="$current-value"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$index = $str-length">
+ <xsl:value-of select="$current-value"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="hexNumber2dec">
+ <xsl:param name="hex-value"/>
+ <xsl:choose>
+ <xsl:when test="$hex-value = 'A' or ($hex-value = 'a')">
+ <xsl:value-of select="10"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'B' or ($hex-value = 'b')">
+ <xsl:value-of select="11"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'C' or ($hex-value = 'c')">
+ <xsl:value-of select="12"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'D' or ($hex-value = 'd')">
+ <xsl:value-of select="13"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'E' or ($hex-value = 'e')">
+ <xsl:value-of select="14"/>
+ </xsl:when>
+ <xsl:when test="$hex-value = 'F' or ($hex-value = 'f')">
+ <xsl:value-of select="15"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$hex-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="decimal2hex">
+ <xsl:param name="dec-number"/>
+ <xsl:param name="last-value"/>
+ <xsl:variable name="current-value">
+ <xsl:call-template name="decNumber2hex">
+ <xsl:with-param name="dec-value">
+ <xsl:if test="$dec-number &gt; 15">
+ <xsl:value-of select="floor($dec-number div 16)"/>
+ </xsl:if>
+ <xsl:if test="$dec-number &lt; 16">
+ <xsl:value-of select="$dec-number"/>
+ </xsl:if>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$dec-number &gt; 15">
+ <xsl:call-template name="decimal2hex">
+ <xsl:with-param name="dec-number" select="$dec-number mod 16"/>
+ <xsl:with-param name="last-value" select="concat($last-value,$current-value)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$dec-number &lt; 16">
+ <xsl:value-of select="substring-after(concat($last-value,$current-value),'H')"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="decNumber2hex">
+ <xsl:param name="dec-value"/>
+ <xsl:choose>
+ <xsl:when test="$dec-value = 10">
+ <xsl:value-of select="'A'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 11">
+ <xsl:value-of select="'B'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 12">
+ <xsl:value-of select="'C'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 13">
+ <xsl:value-of select="'D'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 14">
+ <xsl:value-of select="'E'"/>
+ </xsl:when>
+ <xsl:when test="$dec-value = 15">
+ <xsl:value-of select="'F'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$dec-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="recursion-condformat-style-table-cell">
+ <xsl:param name="style-value-t"/>
+ <xsl:variable name="style-value" select="$style-value-t"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($style-value,'background')">
+ <xsl:choose>
+ <xsl:when test="contains($style-value,'mso-pattern')">
+ <xsl:variable name="color-value">
+ <xsl:call-template name="translate-color-style">
+ <xsl:with-param name="source-str" select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="mso-value">
+ <xsl:call-template name="translate-color-style">
+ <xsl:with-param name="source-str" select="normalize-space(substring-after($style-value,'mso-pattern'))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="mso-color" select="substring-after($mso-value,'#')"/>
+ <xsl:variable name="pattern-color-value" select="substring($mso-color,1,6)"/>
+ <xsl:variable name="pattern" select="concat('0.',normalize-space(substring-before(substring-after($mso-color,'gray-'),';')))"/>
+ <xsl:variable name="pattern-color">
+ <xsl:call-template name="cell-pattern-color">
+ <xsl:with-param name="pattern" select="$pattern"/>
+ <xsl:with-param name="color-value" select="$color-value"/>
+ <xsl:with-param name="pattern-color-value" select="concat('#',$pattern-color-value)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:background-color"><xsl:value-of select="normalize-space($pattern-color)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:background-color"><xsl:call-template name="translate-color-style"><xsl:with-param name="source-str" select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/></xsl:call-template></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with($style-value,'border')">
+ <xsl:attribute name="fo:border"><xsl:value-of select="'0.002cm solid #000000'"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="contains($style-value,':')">
+ <xsl:call-template name="recursion-condformat-style-table-cell">
+ <xsl:with-param name="style-value-t" select="substring-after($style-value,';')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="recursion-condformat-style-text">
+ <xsl:param name="style-value-t"/>
+ <xsl:variable name="style-value" select="normalize-space($style-value-t)"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($style-value,'color')">
+ <xsl:attribute name="fo:color"><xsl:call-template name="translate-color-style"><xsl:with-param name="source-str" select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/></xsl:call-template></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="starts-with($style-value,'font-style')">
+ <xsl:attribute name="fo:font-style"><xsl:value-of select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="starts-with($style-value,'font-weight')">
+ <xsl:variable name="font-weight" select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/>
+ <xsl:attribute name="fo:font-weight"><xsl:choose><xsl:when test="($font-weight &gt; 300) and ($font-weight &lt; 500)"><xsl:value-of select="'normal'"/></xsl:when><xsl:when test="($font-weight &gt; 500) or ($font-weight = 500)"><xsl:value-of select="'bold'"/></xsl:when><xsl:otherwise><xsl:value-of select="'0'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="starts-with($style-value,'text-underline-style')">
+ <xsl:attribute name="style:text-underline-type"><xsl:value-of select="normalize-space(substring-before(substring-after($style-value,':'),';'))"/></xsl:attribute>
+ <xsl:attribute name="style:text-underline-color"><xsl:value-of select="'#000000'"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="contains($style-value,':')">
+ <xsl:call-template name="recursion-condformat-style-text">
+ <xsl:with-param name="style-value-t" select="substring-after($style-value,';')"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="translate-color-style">
+ <xsl:param name="source-str"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($source-str,'#')">
+ <xsl:value-of select="$source-str"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="starts-with($source-str,'black')">
+ <xsl:value-of select="'#000000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'maroon')">
+ <xsl:value-of select="'#800000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'red')">
+ <xsl:value-of select="'#FF0000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'fuchsia')">
+ <xsl:value-of select="'#FF00FF'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'olive')">
+ <xsl:value-of select="'#808000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'yellow')">
+ <xsl:value-of select="'#FFFF00'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'green')">
+ <xsl:value-of select="'#008000'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'lime')">
+ <xsl:value-of select="'#00FF00'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'teal')">
+ <xsl:value-of select="'#008080'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'aqua')">
+ <xsl:value-of select="'#00FFFF'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'navy')">
+ <xsl:value-of select="'#000080'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'blue')">
+ <xsl:value-of select="'#0000FF'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'purple')">
+ <xsl:value-of select="'#800080'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'gray')">
+ <xsl:value-of select="'#808080'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'silver')">
+ <xsl:value-of select="'#C0C0C0'"/>
+ </xsl:when>
+ <xsl:when test="starts-with($source-str,'white')">
+ <xsl:value-of select="'#FFFFFF'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'#FFFFFF'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="CondFormat_automatic_style">
+ <xsl:for-each select="../uof:电子表格/表:公用处理规则/表:条件格式化集/表:条件格式化">
+ <xsl:variable name="table-pos" select="count(../../../preceding-sibling::表:公用处理规则)+1"/>
+ <xsl:variable name="conditions" select="count(../preceding-sibling::表:条件格式化集)+1"/>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:call-template name="encode-as-nc-name"><xsl:with-param name="string" select="concat('ce',$table-pos,'-',$conditions)"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="style:family">table-cell</xsl:attribute>
+ <xsl:for-each select="uof:单元格式样/表:条件">
+ <xsl:variable name="condition-number" select="count(preceding-sibling::表:条件)+1"/>
+ <xsl:variable name="base-address">
+ <xsl:choose>
+ <xsl:when test="contains(../表:区域,',')">
+ <xsl:choose>
+ <xsl:when test="contains(substring-before(../表:区域,','),':')">
+ <xsl:value-of select="substring-before(substring-after(../表:区域,':'),',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(../表:区域,',')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="../表:区域"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="base-cell-address">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="substring-before(substring-after($base-address,'R'),'C')"/>
+ <xsl:with-param name="row-number" select="substring-after($base-address,'C')"/>
+ <xsl:with-param name="column-pos-style" select="absolute"/>
+ <xsl:with-param name="row-pos-style" select="absolute"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="condition-value">
+ <xsl:call-template name="translate-condition">
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="style:map">
+ <xsl:attribute name="style:condition"><xsl:value-of select="$condition-value"/></xsl:attribute>
+ <xsl:attribute name="style:apply-style-name"><xsl:value-of select="concat('Excel_CondFormat_',$table-pos,'_',$conditions,'_',$condition-number)"/></xsl:attribute>
+ <xsl:attribute name="style:base-cell-address"><xsl:value-of select="concat(../../@Name,'.',$base-cell-address)"/></xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="translate-condition">
+ <xsl:variable name="address-value">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="表:第一操作数"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="表:操作码">
+ <xsl:variable name="qualifier" select="表:操作码"/>
+ <xsl:variable name="first-value" select="表:第一操作数"/>
+ <xsl:choose>
+ <xsl:when test="$qualifier = 'Equal'">
+ <xsl:choose>
+ <xsl:when test="starts-with($first-value,'&quot;')">
+ <xsl:value-of select="concat('cell-content()=',$address-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('cell-content()=[',$address-value,']')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$qualifier = 'Less'">
+ <xsl:value-of select="concat('cell-content()&lt;[',$address-value,']')"/>
+ </xsl:when>
+ <xsl:when test="$qualifier = 'Greater'">
+ <xsl:value-of select="concat('cell-content()&gt;[',$address-value,']')"/>
+ </xsl:when>
+ <xsl:when test="$qualifier = 'LessOrEqual'">
+ <xsl:value-of select="concat('cell-content()&lt;=[',$address-value,']')"/>
+ </xsl:when>
+ <xsl:when test="$qualifier = 'GreaterOrEqual'">
+ <xsl:value-of select="concat('cell-content()&gt;=[',$address-value,']')"/>
+ </xsl:when>
+ <xsl:when test="$qualifier = 'NotEqual'">
+ <xsl:value-of select="concat('cell-content()!=[',$address-value,']')"/>
+ </xsl:when>
+ <xsl:when test="$qualifier = 'Between'">
+ <xsl:variable name="second-value">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="表:第二操作数"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('cell-content-is-between([',$address-value,'],[',$second-value,'])')"/>
+ </xsl:when>
+ <xsl:when test="$qualifier = 'NotBetween'">
+ <xsl:variable name="second-value">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="0"/>
+ <xsl:with-param name="cell-column-pos" select="0"/>
+ <xsl:with-param name="expression" select="表:第二操作数"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('cell-content-is-not-between([',$address-value,'],[',$second-value,'])')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('is-true-formula(',$address-value,')')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="translate-expression">
+ <xsl:param name="cell-row-pos"/>
+ <xsl:param name="cell-column-pos"/>
+ <xsl:param name="expression"/>
+ <xsl:param name="return-value"/>
+ <xsl:variable name="temp-range">
+ <xsl:choose>
+ <xsl:when test="$expression != ''">
+ <xsl:call-template name="parse-range-name">
+ <xsl:with-param name="expression" select="$expression"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="range-type">
+ <xsl:choose>
+ <xsl:when test="substring($temp-range, 1, 1) = '1'">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:when test="substring($temp-range, 1, 1) = '2'">
+ <xsl:value-of select="2"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="current-range">
+ <xsl:value-of select="substring($temp-range, 2)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$range-type = 1">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression">
+ <xsl:choose>
+ <xsl:when test="contains($current-range, '#$')">
+ <xsl:variable name="temp-token">
+ <xsl:choose>
+ <xsl:when test="contains($current-range, '\')">
+ <xsl:value-of select="concat(']', substring-after($current-range, '#$'), &quot;&apos;&quot;)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($current-range, '#$')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="substring-after($expression, $temp-token)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($expression, $current-range)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="return-value">
+ <xsl:choose>
+ <xsl:when test="$current-range = '='">
+ <xsl:text>oooc:=</xsl:text>
+ </xsl:when>
+ <xsl:when test="substring($current-range, string-length($current-range)) = '('">
+ <xsl:value-of select="concat($return-value, substring-before($expression, $current-range), $current-range, '[.')"/>
+ </xsl:when>
+ <xsl:when test="$current-range = ','">
+ <xsl:value-of select="concat($return-value, substring-before($expression, $current-range), '];[.')"/>
+ </xsl:when>
+ <xsl:when test="$current-range = ')'">
+ <xsl:value-of select="concat($return-value, substring-before($expression, $current-range), '])')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($return-value, substring-before($expression, $current-range), $current-range)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="handle-type">
+ <xsl:choose>
+ <xsl:when test="starts-with($current-range, 'R')">
+ <xsl:choose>
+ <xsl:when test="contains($current-range, 'C')">
+ <xsl:variable name="part-type-r">
+ <xsl:call-template name="handle-type-number">
+ <xsl:with-param name="t-part" select="substring-before( substring-after($current-range, 'R'), 'C')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="part-type-c">
+ <xsl:call-template name="handle-type-number">
+ <xsl:with-param name="t-part" select="substring-after($current-range, 'C')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="($part-type-r = 1) and ($part-type-c = 1)">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="4"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="part-type">
+ <xsl:call-template name="handle-type-number">
+ <xsl:with-param name="t-part" select="substring-after($current-range, 'R')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$part-type = 1">
+ <xsl:value-of select="2"/>
+ </xsl:when>
+ <xsl:when test="$part-type = 2">
+ <xsl:value-of select="4"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="4"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with($current-range, 'C')">
+ <xsl:variable name="part-type">
+ <xsl:call-template name="handle-type-number">
+ <xsl:with-param name="t-part" select="substring-after($current-range, 'C')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$part-type = 1">
+ <xsl:value-of select="3"/>
+ </xsl:when>
+ <xsl:when test="$part-type = 2">
+ <xsl:value-of select="4"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="4"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="4"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$handle-type = 1">
+ <xsl:variable name="after-R">
+ <xsl:value-of select="substring(substring-after($current-range,'R'),1,1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$after-R='C' or $after-R='[' or $after-R='0' or $after-R='1' or $after-R='2' or $after-R='3' or $after-R='4' or $after-R='5' or $after-R='6' or $after-R='7' or $after-R='8' or $after-R='9'">
+ <xsl:variable name="row-pos">
+ <xsl:choose>
+ <xsl:when test="$after-R='['">
+ <xsl:value-of select="$cell-row-pos+substring-before( substring-after($current-range,'R['),']')"/>
+ </xsl:when>
+ <xsl:when test="$after-R='C'">
+ <xsl:value-of select="$cell-row-pos"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(substring-after($current-range,'R'),'C')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="row-pos-style">
+ <xsl:choose>
+ <xsl:when test="$after-R='[' or $after-R='C'">relative</xsl:when>
+ <xsl:otherwise>absolute</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="after-C">
+ <xsl:value-of select="substring(substring-after(substring-after($current-range,'R'),'C'),1,1)"/>
+ </xsl:variable>
+ <xsl:variable name="column-digit-length">
+ <xsl:choose>
+ <xsl:when test="$after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">
+ <xsl:call-template name="get-digit-length">
+ <xsl:with-param name="complexive-string" select="substring-after(substring-after($current-range,'R'),'C')"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="column-pos">
+ <xsl:choose>
+ <xsl:when test="$after-C='['">
+ <xsl:value-of select="$cell-column-pos + substring-before(substring-after(substring-after($current-range,'R'),'C['),']')"/>
+ </xsl:when>
+ <xsl:when test="$after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">
+ <xsl:value-of select="substring(substring-after(substring-after($current-range,'R'),'C'),1,$column-digit-length)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$cell-column-pos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="column-pos-style">
+ <xsl:choose>
+ <xsl:when test="$after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">absolute</xsl:when>
+ <xsl:otherwise>relative</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="trans-unit">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="$column-pos"/>
+ <xsl:with-param name="row-number" select="$row-pos"/>
+ <xsl:with-param name="column-pos-style" select="$column-pos-style"/>
+ <xsl:with-param name="row-pos-style" select="$row-pos-style"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), $trans-unit)"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($expression, $current-range)"/>
+ <xsl:with-param name="return-value" select="concat($return-value, $name-unit)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), translate( substring-before(substring-after($expression, '('),'R'),',!', ';.'))"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($current-range,'R')"/>
+ <xsl:with-param name="return-value" select="concat($return-value, $name-unit)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$handle-type = 2">
+ <xsl:variable name="after-R">
+ <xsl:value-of select="substring(substring-after($current-range,'R'),1,1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$after-R='[' or $after-R='0' or $after-R='1' or $after-R='2' or $after-R='3' or $after-R='4' or $after-R='5' or $after-R='6' or $after-R='7' or $after-R='8' or $after-R='9'">
+ <xsl:variable name="row-number">
+ <xsl:choose>
+ <xsl:when test="$after-R = '['">
+ <xsl:value-of select="substring-before(substring-after($current-range, 'R['), ']')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($current-range, 'R')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="row-pos">
+ <xsl:choose>
+ <xsl:when test="$after-R='['">
+ <xsl:value-of select="$cell-row-pos + $row-number"/>
+ </xsl:when>
+ <xsl:when test="$after-R='0' or $after-R='1' or $after-R='2' or $after-R='3' or $after-R='4' or $after-R='5' or $after-R='6' or $after-R='7' or $after-R='8' or $after-R='9'">
+ <xsl:value-of select="$row-number"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$cell-row-pos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="trans-unit1">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="1"/>
+ <xsl:with-param name="row-number" select="$row-pos"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="trans-unit2">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="256"/>
+ <xsl:with-param name="row-number" select="$row-pos"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), $trans-unit1, ':', $trans-unit2)"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($expression, $current-range)"/>
+ <xsl:with-param name="return-value" select="concat($return-value, $name-unit)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), translate( substring-before($current-range,'R'),',!', ';.'),'R')"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($current-range,'R')"/>
+ <xsl:with-param name="return-value" select="concat($return-value, $name-unit)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$handle-type = 3">
+ <xsl:variable name="after-C">
+ <xsl:value-of select="substring(substring-after($current-range,'C'),1,1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$after-C='[' or $after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">
+ <xsl:variable name="column-number">
+ <xsl:choose>
+ <xsl:when test="$after-C = '['">
+ <xsl:value-of select="substring-before(substring-after($current-range, 'C['), ']')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after($current-range, 'C')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="column-pos">
+ <xsl:choose>
+ <xsl:when test="$after-C='['">
+ <xsl:value-of select="$cell-column-pos + $column-number"/>
+ </xsl:when>
+ <xsl:when test="$after-C='0' or $after-C='1' or $after-C='2' or $after-C='3' or $after-C='4' or $after-C='5' or $after-C='6' or $after-C='7' or $after-C='8' or $after-C='9'">
+ <xsl:value-of select="$column-number"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$cell-column-pos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="trans-unit1">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="$column-pos"/>
+ <xsl:with-param name="row-number" select="1"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="trans-unit2">
+ <xsl:call-template name="translate-unit">
+ <xsl:with-param name="column-number" select="$column-pos"/>
+ <xsl:with-param name="row-number" select="32000"/>
+ <xsl:with-param name="column-pos-style" select="'relative'"/>
+ <xsl:with-param name="row-pos-style" select="'relative'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), $trans-unit1, ':', $trans-unit2)"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($expression, $current-range)"/>
+ <xsl:with-param name="return-value" select="concat($return-value, $name-unit)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="name-unit" select="concat(substring-before($expression, $current-range), translate( substring-before($current-range,'C'),',!', ';.'),'C')"/>
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($current-range,'C')"/>
+ <xsl:with-param name="return-value" select="concat($return-value, $name-unit)"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="next-pit" select="substring-after($expression, $current-range)"/>
+ <xsl:choose>
+ <xsl:when test="contains($next-pit, '+') or contains($next-pit, '-') or contains($next-pit, '*') or contains($next-pit, '/') or contains($next-pit, ')') or contains($next-pit, '^') or contains($next-pit, ':') or contains($next-pit, '&quot;') or contains($next-pit, ';') or contains($next-pit, ',') or contains($next-pit, '[')">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$cell-row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$cell-column-pos"/>
+ <xsl:with-param name="expression" select="substring-after($expression, $current-range)"/>
+ <xsl:with-param name="return-value" select="concat($return-value, substring-before($expression, $current-range), $current-range)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate( concat($return-value, substring-before($expression, $current-range), $current-range),',!', ';.')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="parse-range-name">
+ <xsl:param name="expression"/>
+ <xsl:param name="return-value"/>
+ <xsl:variable name="first-one" select="substring($expression,1,1)"/>
+ <xsl:choose>
+ <xsl:when test="$first-one = '='">
+ <xsl:choose>
+ <xsl:when test="string-length(normalize-space($return-value)) &gt; 0">
+ <xsl:value-of select="concat('2', $return-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>1=</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-one='(' or $first-one='!' or $first-one='&amp;'">
+ <xsl:value-of select="concat('1', $return-value, $first-one)"/>
+ </xsl:when>
+ <xsl:when test="$first-one='['">
+ <xsl:choose>
+ <xsl:when test="starts-with(substring-after($expression, ']'), 'C')">
+ <xsl:call-template name="parse-range-name">
+ <xsl:with-param name="expression" select="substring-after($expression, ']')"/>
+ <xsl:with-param name="return-value" select="concat($return-value, substring-before($expression, ']'), ']')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains(substring-before($expression, ']'), '.') and contains(substring-after($expression, ']'), '!')">
+ <xsl:value-of select="concat('1', &quot;&apos;&quot;, substring-before(substring-after($expression, '['), ']'), &quot;&apos;&quot;, '#$', substring-before(substring-after($expression, ']'), '!'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('2', $return-value, substring-before($expression, ']'), ']')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-one='&quot;'">
+ <xsl:value-of select="concat('1', $first-one, substring-before(substring-after($expression, '&quot;'), '&quot;'), '&quot;')"/>
+ </xsl:when>
+ <xsl:when test="$first-one=&quot;&apos;&quot;">
+ <xsl:variable name="str-in" select="substring-before(substring-after($expression, &quot;&apos;&quot;), &quot;&apos;&quot;)"/>
+ <xsl:choose>
+ <xsl:when test="contains($str-in, '\') and contains($str-in, '[') and contains($str-in, ']')">
+ <xsl:variable name="first-pos" select="substring-before($str-in, '[')"/>
+ <xsl:variable name="second-pos" select="substring-before(substring-after($str-in, '['), ']')"/>
+ <xsl:variable name="third-pos" select="substring-after($str-in, ']')"/>
+ <xsl:value-of select="concat('1', &quot;&apos;&quot;, $first-pos, $second-pos, &quot;&apos;&quot;, '#$', $third-pos)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('1', &quot;&apos;&quot;, $str-in, &quot;&apos;&quot;)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-one='+' or $first-one='-' or $first-one='*' or $first-one='/' or $first-one=')' or $first-one='^' or $first-one=':' or $first-one='&quot;' or $first-one=';' or $first-one=',' or $first-one='&gt;' or $first-one='&lt;'">
+ <xsl:choose>
+ <xsl:when test="$return-value = ''">
+ <xsl:value-of select="concat('1', $first-one)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat('2', $return-value)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$expression = ''">
+ <xsl:value-of select="concat('2', $return-value)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="parse-range-name">
+ <xsl:with-param name="expression" select="substring($expression, 2, string-length($expression)-1)"/>
+ <xsl:with-param name="return-value" select="concat($return-value, substring($expression, 1, 1))"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="handle-type-number">
+ <xsl:param name="t-part"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($t-part, '[')">
+ <xsl:variable name="tt-str" select="substring-before( substring-after( $t-part, '['), ']')"/>
+ <xsl:choose>
+ <xsl:when test="($tt-str &lt; 0) or ($tt-str &gt; 0) or ($tt-str = 0)">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="($t-part &lt; 0) or ($t-part &gt; 0) or ($t-part = 0)">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:when test="$t-part = ''">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="2"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="translate-unit">
+ <xsl:param name="column-number"/>
+ <xsl:param name="row-number"/>
+ <xsl:param name="column-pos-style"/>
+ <xsl:param name="row-pos-style"/>
+ <xsl:variable name="column-number1">
+ <xsl:value-of select="floor( $column-number div 26 )"/>
+ </xsl:variable>
+ <xsl:variable name="column-number2">
+ <xsl:value-of select="$column-number mod 26"/>
+ </xsl:variable>
+ <xsl:variable name="column-character1">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="column-character2">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$column-pos-style = 'absolute'">
+ <xsl:value-of select="concat( '$', $column-character1, $column-character2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat( $column-character1, $column-character2)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="$row-pos-style ='absolute'">
+ <xsl:value-of select="concat( '$', $row-number)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$row-number"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="number-to-character">
+ <xsl:param name="number"/>
+ <xsl:choose>
+ <xsl:when test="$number = 0"/>
+ <xsl:when test="$number = 1">A</xsl:when>
+ <xsl:when test="$number = 2">B</xsl:when>
+ <xsl:when test="$number = 3">C</xsl:when>
+ <xsl:when test="$number = 4">D</xsl:when>
+ <xsl:when test="$number = 5">E</xsl:when>
+ <xsl:when test="$number = 6">F</xsl:when>
+ <xsl:when test="$number = 7">G</xsl:when>
+ <xsl:when test="$number = 8">H</xsl:when>
+ <xsl:when test="$number = 9">I</xsl:when>
+ <xsl:when test="$number = 10">J</xsl:when>
+ <xsl:when test="$number = 11">K</xsl:when>
+ <xsl:when test="$number = 12">L</xsl:when>
+ <xsl:when test="$number = 13">M</xsl:when>
+ <xsl:when test="$number = 14">N</xsl:when>
+ <xsl:when test="$number = 15">O</xsl:when>
+ <xsl:when test="$number = 16">P</xsl:when>
+ <xsl:when test="$number = 17">Q</xsl:when>
+ <xsl:when test="$number = 18">R</xsl:when>
+ <xsl:when test="$number = 19">S</xsl:when>
+ <xsl:when test="$number = 20">T</xsl:when>
+ <xsl:when test="$number = 21">U</xsl:when>
+ <xsl:when test="$number = 22">V</xsl:when>
+ <xsl:when test="$number = 23">W</xsl:when>
+ <xsl:when test="$number = 24">X</xsl:when>
+ <xsl:when test="$number = 25">Y</xsl:when>
+ <xsl:when test="$number = 26">Z</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-digit-length">
+ <xsl:param name="complexive-string"/>
+ <xsl:variable name="first-char">
+ <xsl:value-of select="substring( $complexive-string, 1, 1)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-char = '1' or $first-char = '2' or $first-char = '3' or $first-char = '4' or $first-char = '5' or $first-char = '6' or $first-char = '7' or $first-char = '8' or $first-char = '9' or $first-char = '0' ">
+ <xsl:variable name="temp">
+ <xsl:call-template name="get-digit-length">
+ <xsl:with-param name="complexive-string" select="substring( $complexive-string, 2)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$temp+1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:句属性" mode="style">
+ <!--chengxz 0725-->
+ <xsl:if test="not(@字:式样引用)">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">T<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:句属性" format="1"/></xsl:attribute>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ <xsl:if test="@字:式样引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="./*"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="style-style-content">
+ <xsl:variable name="style-name" select="@表:标识符"/>
+ <xsl:variable name="apply-style-name" select="@表:名称"/>
+ <xsl:attribute name="style:family"><xsl:choose><xsl:when test="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:列[@表:式样引用=$style-name]">table-column</xsl:when><xsl:otherwise>table-cell</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:列[@表:式样引用=$style-name]/@表:列宽">
+ <xsl:element name="style:table-column-properties">
+ <xsl:attribute name="style:column-width"><xsl:value-of select="concat(/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:列[@表:式样引用=$style-name]/@表:列宽,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:列[@表:式样引用=$style-name]/@表:跨度">
+ <xsl:attribute name="fo:break-before">auto</xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:列[@表:式样引用=$style-name]">
+ <xsl:if test="preceding-sibling::表:列[1]/@表:跨度 and ancestor::表:工作表/表:分页符集/表:分页符/@表:列号">
+ <xsl:variable name="kuadu">
+ <xsl:value-of select="preceding-sibling::表:列[1]/@表:跨度"/>
+ </xsl:variable>
+ <xsl:if test="not($kuadu='1')">
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$kuadu='1' and not(preceding::表:列[2])">
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="style:table-cell-properties">
+ <xsl:if test="表:对齐格式">
+ <xsl:if test="表:对齐格式/表:垂直对齐方式">
+ <xsl:variable name="vertical-align">
+ <xsl:choose>
+ <xsl:when test="表:对齐格式/表:垂直对齐方式 = 'top'">top</xsl:when>
+ <xsl:when test="表:对齐格式/表:垂直对齐方式 = 'center'">center</xsl:when>
+ <xsl:when test="表:对齐格式/表:垂直对齐方式 = 'bottom'">bottom</xsl:when>
+ <xsl:otherwise>middle</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:vertical-align"><xsl:value-of select="$vertical-align"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:对齐格式/表:自动换行/@表:值 = 'true'">
+ <xsl:attribute name="fo:wrap-option">wrap</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:对齐格式/表:缩进">
+ <xsl:attribute name="fo:padding-left"><xsl:variable name="indent" select="表:对齐格式/表:缩进 * 10"/><xsl:call-template name="convert2cm"><xsl:with-param name="value" select="concat($indent,'pt')"/></xsl:call-template><xsl:text>cm</xsl:text></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:对齐格式/表:文字旋转角度">
+ <xsl:attribute name="style:rotation-angle"><xsl:choose><xsl:when test="表:对齐格式/表:文字旋转角度 &lt; 0"><xsl:value-of select="360 - 表:对齐格式/表:文字旋转角度"/></xsl:when><xsl:otherwise><xsl:value-of select="表:对齐格式/表:文字旋转角度"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:rotation-align">none</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:对齐格式/表:文字方向 = 'vertical'">
+ <xsl:attribute name="style:direction">ttb</xsl:attribute>
+ <xsl:if test="not(表:对齐格式/字:水平对齐方式)">
+ <xsl:attribute name="style:text-align-source">fix</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:if>
+ <!--xsl:if test="表:边框">
+ <xsl:apply-templates select="表:边框" />
+ </xsl:if-->
+ <!--chenjh add 边框 again-->
+ <xsl:if test="表:边框/uof:上/@uof:宽度 !=''">
+ <xsl:variable name="top-line-width" select="concat(表:边框/uof:上/@uof:宽度,$uofUnit)"/>
+ <xsl:variable name="top-line-tyle">
+ <xsl:choose>
+ <xsl:when test="表:边框/uof:上/@uof:类型='single'">solid</xsl:when>
+ <xsl:when test="表:边框/uof:上/@uof:类型='double'">double</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="top-line-color" select="表:边框/uof:上/@uof:颜色"/>
+ <xsl:variable name="border-top" select="concat($top-line-width,' ',$top-line-tyle,' ',$top-line-color)"/>
+ <xsl:attribute name="fo:border-top"><xsl:value-of select="$border-top"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:边框/uof:下/@uof:宽度 !=''">
+ <xsl:variable name="bottom-line-width" select="concat(表:边框/uof:下/@uof:宽度,$uofUnit)"/>
+ <xsl:variable name="bottom-line-tyle">
+ <xsl:choose>
+ <xsl:when test="表:边框/uof:下/@uof:类型='single'">solid</xsl:when>
+ <xsl:when test="表:边框/uof:下/@uof:类型='double'">double</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="bottom-line-color" select="表:边框/uof:下/@uof:颜色"/>
+ <xsl:variable name="border-bottom" select="concat($bottom-line-width,' ',$bottom-line-tyle,' ',$bottom-line-color)"/>
+ <xsl:attribute name="fo:border-bottom"><xsl:value-of select="$border-bottom"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:边框/uof:左/@uof:宽度 !=''">
+ <xsl:variable name="left-line-width" select="concat(表:边框/uof:左/@uof:宽度,$uofUnit)"/>
+ <xsl:variable name="left-line-tyle">
+ <xsl:choose>
+ <xsl:when test="表:边框/uof:左/@uof:类型='single'">solid</xsl:when>
+ <xsl:when test="表:边框/uof:左/@uof:类型='double'">double</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="left-line-color" select="表:边框/uof:左/@uof:颜色"/>
+ <xsl:variable name="border-left" select="concat($left-line-width,' ',$left-line-tyle,' ',$left-line-color)"/>
+ <xsl:attribute name="fo:border-left"><xsl:value-of select="$border-left"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:边框/uof:右/@uof:宽度 !=''">
+ <xsl:variable name="right-line-width" select="concat(表:边框/uof:右/@uof:宽度,$uofUnit)"/>
+ <xsl:variable name="right-line-tyle">
+ <xsl:choose>
+ <xsl:when test="@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="@uof:类型 = 'double'">double</xsl:when>
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="right-line-color" select="表:边框/uof:右/@uof:颜色"/>
+ <xsl:variable name="border-right" select="concat($right-line-width,' ',$right-line-tyle,' ',$right-line-color)"/>
+ <xsl:attribute name="fo:border-right"><xsl:value-of select="$border-right"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:边框/uof:对角线1/@uof:宽度 !=''">
+ <xsl:variable name="diagonal-lr-width" select="concat(表:边框/uof:对角线1/@uof:宽度,$uofUnit)"/>
+ <xsl:variable name="diagonal-lr-tyle">
+ <xsl:choose>
+ <xsl:when test="表:边框/uof:对角线1/@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="表:边框/uof:对角线1/@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="表:边框/uof:对角线1/@uof:类型 = 'double'">double</xsl:when>
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="diagonal-lr-color" select="表:边框/uof:对角线1/@uof:颜色"/>
+ <xsl:variable name="border-diagonal" select="concat($diagonal-lr-width,' ',$diagonal-lr-tyle,' ',$diagonal-lr-color)"/>
+ <xsl:attribute name="style:diagonal-bl-tr"><xsl:value-of select="$border-diagonal"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:边框/uof:对角线2/@uof:宽度 !=''">
+ <xsl:variable name="diagonal-rl-width" select="concat(表:边框/uof:对角线2/@uof:宽度,$uofUnit)"/>
+ <xsl:variable name="diagonal-rl-tyle">
+ <xsl:choose>
+ <xsl:when test="表:边框/uof:对角线1/@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="表:边框/uof:对角线1/@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="表:边框/uof:对角线1/@uof:类型 = 'double'">double</xsl:when>
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="diagonal-rl-color" select="表:边框/uof:对角线2/@uof:颜色"/>
+ <xsl:variable name="border-diagonal" select="concat($diagonal-rl-width,' ',$diagonal-rl-tyle,' ',$diagonal-rl-color)"/>
+ <xsl:attribute name="style:diagonal-tl-br"><xsl:value-of select="$border-diagonal"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:边框/*/@uof:阴影">
+ <xsl:choose>
+ <xsl:when test="表:边框/uof:下/@uof:阴影 and 表:边框/uof:右/@uof:阴影">
+ <xsl:attribute name="style:shadow">#808080 0.18cm 0.18cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:边框/uof:下/@uof:阴影 and 表:边框/uof:左/@uof:阴影">
+ <xsl:attribute name="style:shadow">#808080 -0.18cm 0.18cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:边框/uof:上/@uof:阴影 and 表:边框/uof:右/@uof:阴影">
+ <xsl:attribute name="style:shadow">#808080 0.18cm -0.18cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:边框/uof:上/@uof:阴影 and 表:边框/uof:左/@uof:阴影">
+ <xsl:attribute name="style:shadow">#808080 -0.18cm -0.18cm</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <!--边框 end -->
+ <xsl:if test="表:填充">
+ <xsl:choose>
+ <xsl:when test="表:填充/图:颜色">
+ <xsl:attribute name="fo:background-color"><xsl:value-of select="表:填充/图:颜色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="表:填充/图:图案/@图:前景色">
+ <xsl:variable name="pattern-value">
+ <xsl:call-template name="cell-pattern-color">
+ <xsl:with-param name="pattern" select="concat('0.',substring-after(表:填充/图:图案/图:背景色,'y'))"/>
+ <xsl:with-param name="color-value" select="表:填充/图:颜色"/>
+ <xsl:with-param name="pattern-color-value" select="表:填充/图:图案/图:背景色"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:background-color"><xsl:value-of select="$pattern-value"/></xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="表:字体格式/字:隐藏文字">
+ <xsl:choose>
+ <xsl:when test="表:字体格式/字:隐藏文字 = 'true'">
+ <xsl:attribute name="style:cell-protect">protected formula-hidden</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:cell-protect">none</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:attribute name="style:cell-protect">none</xsl:attribute>
+ <xsl:attribute name="style:text-align-source">fix</xsl:attribute>
+ </xsl:element>
+ <xsl:element name="style:paragraph-properties">
+ <xsl:if test="表:对齐格式/表:水平对齐方式">
+ <xsl:variable name="text-align">
+ <xsl:choose>
+ <xsl:when test="表:对齐格式/表:水平对齐方式 = 'left'">start</xsl:when>
+ <xsl:when test="表:对齐格式/表:水平对齐方式 = 'center'">center</xsl:when>
+ <xsl:when test="表:对齐格式/表:水平对齐方式 = 'right'">end</xsl:when>
+ <xsl:when test="表:对齐格式/表:水平对齐方式 = 'justify'">justify</xsl:when>
+ <xsl:otherwise>start</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="fo:text-align"><xsl:value-of select="$text-align"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:if test="表:字体格式/字:字体">
+ <xsl:choose>
+ <xsl:when test="(表:字体格式/字:字体/@字:中文字体引用)or (表:字体格式/字:字体/@字:西文字体引用)">
+ <xsl:variable name="fontnameZ" select="表:字体格式/字:字体/@字:中文字体引用"/>
+ <xsl:variable name="fontnameX" select="表:字体格式/字:字体/@字:西文字体引用"/>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:字体集/uof:字体声明">
+ <xsl:if test="(./@uof:标识符 = $fontnameZ)or(./@uof:标识符 = $fontnameX)">
+ <xsl:attribute name="style:font-name"><xsl:value-of select="./@uof:名称"/></xsl:attribute>
+ <xsl:attribute name="style:font-name-asian"><xsl:value-of select="./@uof:名称"/></xsl:attribute>
+ <xsl:attribute name="style:font-name-complex"><xsl:value-of select="./@uof:名称"/></xsl:attribute>
+ <xsl:attribute name="style:font-charset"><xsl:value-of select="./@uof:字体族"/></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:font-name">Arial</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="表:字体格式/字:粗体/@字:值">
+ <xsl:attribute name="fo:font-weight"><xsl:choose><xsl:when test="表:字体格式/字:粗体/@字:值=1 or 表:字体格式/字:粗体/@字:值='true'">bold</xsl:when><xsl:when test="表:字体格式/字:粗体/@字:值=0 or 表:字体格式/字:粗体/@字:值='false'">normal</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian"><xsl:choose><xsl:when test="表:字体格式/字:粗体/@字:值=1 or 表:字体格式/字:粗体/@字:值='true'">bold</xsl:when><xsl:when test="表:字体格式/字:粗体/@字:值=0 or 表:字体格式/字:粗体/@字:值='false'">normal</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:font-weight-complex"><xsl:choose><xsl:when test="表:字体格式/字:粗体/@字:值=1 or 表:字体格式/字:粗体/@字:值='true'">bold</xsl:when><xsl:when test="表:字体格式/字:粗体/@字:值=0 or 表:字体格式/字:粗体/@字:值='false'">normal</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:字体格式/字:斜体/@字:值">
+ <xsl:attribute name="fo:font-style"><xsl:choose><xsl:when test="表:字体格式/字:斜体/@字:值=1 or 表:字体格式/字:斜体/@字:值='true'">italic</xsl:when><xsl:when test="表:字体格式/字:斜体/@字:值=0 or 表:字体格式/字:斜体/@字:值='false'">normal</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:font-style-asian"><xsl:choose><xsl:when test="表:字体格式/字:斜体/@字:值=1 or 表:字体格式/字:斜体/@字:值='true'">italic</xsl:when><xsl:when test="表:字体格式/字:斜体/@字:值=0 or 表:字体格式/字:斜体/@字:值='false'">normal</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:font-style-complex"><xsl:choose><xsl:when test="表:字体格式/字:斜体/@字:值=1 or 表:字体格式/字:斜体/@字:值='true'">italic</xsl:when><xsl:when test="表:字体格式/字:斜体/@字:值=0 or 表:字体格式/字:斜体/@字:值='false'">normal</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="表:字体格式/字:字体/@字:颜色">
+ <xsl:attribute name="fo:color"><xsl:value-of select="表:字体格式/字:字体/@字:颜色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-window-font-color">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="表:字体格式/字:字体/@字:字号">
+ <xsl:attribute name="fo:font-size"><xsl:value-of select="concat( 表:字体格式/字:字体/@字:字号, 'pt')"/></xsl:attribute>
+ <xsl:attribute name="style:font-size-asian"><xsl:value-of select="concat( 表:字体格式/字:字体/@字:字号, 'pt')"/></xsl:attribute>
+ <xsl:attribute name="style:font-size-complex"><xsl:value-of select="concat( 表:字体格式/字:字体/@字:字号, 'pt')"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:font-size">12pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian">12pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex">12pt</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="表:字体格式/字:浮雕">
+ <xsl:variable name="aa">
+ <xsl:value-of select="表:字体格式/字:浮雕/@字:类型"/>
+ </xsl:variable>
+ <xsl:attribute name="style:font-relief"><xsl:choose><xsl:when test="$aa='emboss'">embossed</xsl:when><xsl:when test="$aa='engrave'">engraved</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:字体格式/字:阴影/@字:值 = '1' or 表:字体格式/字:阴影/@字:值 = 'true'">
+ <xsl:attribute name="fo:text-shadow">1pt 1pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:字体格式/字:删除线">
+ <xsl:attribute name="style:text-line-through-style">solid</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="表:字体格式/字:删除线/@字:类型='double'">
+ <xsl:attribute name="style:text-line-through-type">double</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:字体格式/字:删除线/@字:类型='single'">
+ <xsl:attribute name="style:text-underline-mode">continuous</xsl:attribute>
+ <xsl:attribute name="style:text-line-through-mode">continuous</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:字体格式/字:删除线/@字:类型='bold'">
+ <xsl:attribute name="style:text-line-through-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:字体格式/字:删除线/@字:类型='带/'">
+ <xsl:attribute name="style:text-line-through-text">/</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:字体格式/字:删除线/@字:类型='带X'">
+ <xsl:attribute name="style:text-line-through-text">X</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="表:字体格式/字:下划线">
+ <xsl:apply-templates select="表:字体格式/字:下划线"/>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="表:字体格式/字:着重号">
+ <xsl:apply-templates select="表:字体格式/字:着重号"/>
+ </xsl:if>
+ <xsl:if test="表:字体格式/字:空心/@字:值='true'">
+ <xsl:attribute name="style:text-outline">true</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="单元格具体式样">
+ <xsl:choose>
+ <xsl:when test="@表:类型 = 'Default'">
+ <xsl:element name="style:default-style">
+ <xsl:call-template name="style-style-content"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@表:标识符"/></xsl:attribute>
+ <xsl:if test="表:数字格式/@表:格式码 = 'general'">
+ <xsl:attribute name="style:parent-style-name">Default</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style:parent-style-name">Default</xsl:attribute>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select="concat( @表:标识符, 'F')"/></xsl:attribute>
+ <!--chengxz这里要改 -->
+ <!--xsl:attribute name="style:data-style-name"><xsl:value-of select="'N2'"/></xsl:attribute-->
+ <xsl:call-template name="style-style-content"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="表:边框">
+ <!--chengxz 0622-->
+ <xsl:if test="not(uof:下)">
+ <xsl:attribute name="fo:border-bottom">none</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(uof:上)">
+ <xsl:attribute name="fo:border-top">none</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(uof:左)">
+ <xsl:attribute name="fo:border-left">none</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(uof:右)">
+ <xsl:attribute name="fo:border-right">none</xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="uof:对角线1"/>
+ <xsl:apply-templates select="uof:对角线2"/>
+ <xsl:apply-templates select="uof:上"/>
+ <xsl:apply-templates select="uof:下"/>
+ <xsl:apply-templates select="uof:左"/>
+ <xsl:apply-templates select="uof:右"/>
+ </xsl:template>
+ <xsl:template match="uof:上">
+ <xsl:variable name="bordtype">
+ <xsl:choose>
+ <xsl:when test="@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="@uof:类型 = 'double'">double</xsl:when>
+ <!-- Dash, Dot, DashDot, DashDotDot, SlantDashDot are not supported yet -->
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="fo:border-top"><xsl:value-of select="concat(@uof:宽度 div 30,$uofUnit, ' ',$bordtype, ' ', @uof:颜色)"/></xsl:attribute>
+ <xsl:if test="@uof:类型 = 'double'">
+ <xsl:attribute name="style:border-line-width-top">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="uof:下">
+ <xsl:variable name="bordtype">
+ <xsl:choose>
+ <xsl:when test="@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="@uof:类型 = 'double'">double</xsl:when>
+ <!-- Dash, Dot, DashDot, DashDotDot, SlantDashDot are not supported yet -->
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="fo:border-bottom"><xsl:value-of select="concat(@uof:宽度 div 30, $uofUnit,' ',$bordtype, ' ',@uof:颜色)"/></xsl:attribute>
+ <xsl:if test="@uof:类型 = 'double'">
+ <xsl:attribute name="style:border-line-width-bottom">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="uof:左">
+ <xsl:variable name="bordtype">
+ <xsl:choose>
+ <xsl:when test="@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="@uof:类型 = 'double'">double</xsl:when>
+ <!-- Dash, Dot, DashDot, DashDotDot, SlantDashDot are not supported yet -->
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="fo:border-left"><xsl:value-of select="concat(@uof:宽度 div 30,$uofUnit, ' ',$bordtype, ' ', @uof:颜色)"/></xsl:attribute>
+ <xsl:if test="@uof:类型 = 'double'">
+ <xsl:attribute name="style:border-line-width-left">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="uof:右">
+ <xsl:variable name="bordtype">
+ <xsl:choose>
+ <xsl:when test="@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="@uof:类型 = 'double'">double</xsl:when>
+ <!-- Dash, Dot, DashDot, DashDotDot, SlantDashDot are not supported yet -->
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="fo:border-right"><xsl:value-of select="concat( @uof:宽度 div 30, $uofUnit,' ',$bordtype, ' ', @uof:颜色)"/></xsl:attribute>
+ <xsl:if test="@uof:类型 = 'double'">
+ <xsl:attribute name="style:border-line-width-right">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="uof:对角线1">
+ <xsl:variable name="bordtype">
+ <xsl:choose>
+ <xsl:when test="@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="@uof:类型 = 'double'">double</xsl:when>
+ <!-- Dash, Dot, DashDot, DashDotDot, SlantDashDot are not supported yet -->
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:diagonal-bl-tr"><xsl:value-of select="concat( @uof:宽度 div 30, $uofUnit,' ',$bordtype, ' ', @uof:颜色)"/></xsl:attribute>
+ <xsl:if test="@uof:类型 = 'double'">
+ <xsl:attribute name="style:diagonal-bl-tr-width">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="uof:对角线2">
+ <xsl:variable name="bordtype">
+ <xsl:choose>
+ <xsl:when test="@uof:类型 = 'none'">none</xsl:when>
+ <xsl:when test="@uof:类型 = 'continuous'">solid</xsl:when>
+ <xsl:when test="@uof:类型 = 'double'">double</xsl:when>
+ <!-- Dash, Dot, DashDot, DashDotDot, SlantDashDot are not supported yet -->
+ <xsl:otherwise>solid</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:diagonal-tl-br"><xsl:value-of select="concat( @uof:宽度 div 30, $uofUnit,' ',$bordtype, ' ', @uof:颜色)"/></xsl:attribute>
+ <xsl:if test="@uof:类型 = 'double'">
+ <xsl:attribute name="style:diagonal-tl-br-width">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="表:字体格式">
+ <xsl:choose>
+ <xsl:when test="字:上下标/@字:上下标 = 'sup'">
+ <style:style style:name="{concat(../@表:标识符,'T0')}" style:family="text">
+ <style:text-properties style:text-position="33% 58%"/>
+ </style:style>
+ </xsl:when>
+ <xsl:when test="字:上下标/@字:上下标 = 'sub'">
+ <style:style style:name="{concat(../@表:标识符,'T0')}" style:family="text">
+ <style:text-properties style:text-position="-33% 58%"/>
+ </style:style>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="tablecolumngroup">
+ <xsl:param name="start"/>
+ <xsl:param name="end"/>
+ <xsl:param name="prestart"/>
+ <xsl:param name="preend"/>
+ <xsl:param name="nextstart"/>
+ <xsl:param name="nextend"/>
+ <table:table-column-group>
+ <table:table-column>
+ <xsl:attribute name="table:style-name">co1</xsl:attribute>
+ <xsl:attribute name="table:table-column-repeated"><xsl:value-of select="@表:终止 - @表:起始 + 1"/></xsl:attribute>
+ </table:table-column>
+ <xsl:if test="$nextstart &gt;= $start and $nextend &lt;= $end">
+ <xsl:for-each select="following-sibling::表:列[1]">
+ <xsl:call-template name="tablecolumngroup"/>
+ </xsl:for-each>
+ </xsl:if>
+ </table:table-column-group>
+ </xsl:template>
+ <xsl:template match="表:工作表">
+ <xsl:variable name="rowpath" select="表:工作表内容/表:行"/>
+ <xsl:variable name="colpath" select="表:工作表内容/表:列"/>
+ <xsl:element name="table:table">
+ <xsl:attribute name="table:name"><xsl:value-of select="@表:名称"/></xsl:attribute>
+ <xsl:if test="表:工作表内容">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat( 'ta', count(preceding-sibling::表:工作表)+1)"/></xsl:attribute>
+ <xsl:if test="(@表:隐藏 = '1')or(@表:隐藏 = 'true')">
+ <xsl:attribute name="table:protected">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:工作表内容/uof:锚点 or 表:工作表内容/表:图表">
+ <table:shapes>
+ <xsl:apply-templates select="表:工作表内容/uof:锚点"/>
+ <xsl:apply-templates select="表:工作表内容/表:图表">
+ <xsl:with-param name="table-name" select="@表:名称"/>
+ </xsl:apply-templates>
+ </table:shapes>
+ </xsl:if>
+ <xsl:variable name="table-pos">
+ <xsl:value-of select="count(../preceding-sibling::表:工作表)+1"/>
+ </xsl:variable>
+ <xsl:if test="表:工作表内容/表:分组集/表:列">
+ <xsl:for-each select="表:工作表内容/表:分组集/表:列">
+ <xsl:variable name="start" select="@表:起始"/>
+ <xsl:variable name="end" select="@表:终止"/>
+ <xsl:variable name="prestart" select="preceding-sibling::表:列/@表:起始"/>
+ <xsl:variable name="preend" select="preceding-sibling::表:列/@表:终止"/>
+ <xsl:variable name="nextstart" select="following-sibling::表:列/@表:起始"/>
+ <xsl:variable name="nextend" select="following-sibling::表:列/@表:终止"/>
+ <xsl:call-template name="tablecolumngroup">
+ <xsl:with-param name="start" select="$start"/>
+ <xsl:with-param name="end" select="$end"/>
+ <xsl:with-param name="prestart" select="$prestart"/>
+ <xsl:with-param name="preend" select="$preend"/>
+ <xsl:with-param name="nextstart" select="$nextstart"/>
+ <xsl:with-param name="nextend" select="$nextend"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:for-each select="表:工作表内容/表:列">
+ <table:table-column>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="@表:式样引用"/></xsl:attribute>
+ <xsl:if test="@表:跨度 and not(@表:跨度='1')">
+ <xsl:attribute name="table:number-columns-repeated"><xsl:value-of select="@表:跨度"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@表:隐藏">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ </table:table-column>
+ </xsl:for-each>
+ <xsl:variable name="condition-pos-str1">
+ <xsl:if test="../../表:公用处理规则/表:条件格式化集/表:条件格式化">
+ <xsl:call-template name="condition-row-column-string">
+ <xsl:with-param name="last" select="''"/>
+ <xsl:with-param name="total" select="count(../../表:公用处理规则/表:条件格式化集/表:条件格式化)"/>
+ <xsl:with-param name="index" select="1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="condition-pos-str2">
+ <xsl:if test="../../表:公用处理规则/表:数据有效性集/表:数据有效性">
+ <xsl:call-template name="validation-row-column-string">
+ <xsl:with-param name="last" select="''"/>
+ <xsl:with-param name="total" select="count(../../表:公用处理规则/表:数据有效性集/表:数据有效性)"/>
+ <xsl:with-param name="index" select="1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="condition-pos-str" select="concat($condition-pos-str1, $condition-pos-str2)"/>
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行">
+ <xsl:call-template name="create-rows">
+ <xsl:with-param name="lastrowpos" select="0"/>
+ <xsl:with-param name="row-count" select="count(表:工作表内容/表:行)"/>
+ <xsl:with-param name="currentRow" select="1"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="tableHasStyle">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容[@表:式样引用]">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="./表:分页符集/表:分页符[@表:行号]">
+ <xsl:for-each select="./表:分页符集/表:分页符[@表:行号]">
+ <xsl:variable name="number-repeated">
+ <xsl:choose>
+ <xsl:when test="position() = 1">
+ <xsl:value-of select="./@表:行号"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./@表:行号 - preceding::表:分页符[@表:行号 and (position()=count(.))]/@表:行号 - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$number-repeated &gt; 0">
+ <xsl:element name="table:table-row">
+ <xsl:if test="($rowpath/@表:隐藏 = '1') or ($rowpath/@表:隐藏 = 'true')">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('ro',$table-pos)"/></xsl:attribute>
+ <xsl:attribute name="table:number-rows-repeated"><xsl:value-of select="$number-repeated"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$tableHasStyle = 1">
+ <table:table-cell table:number-columns-repeated="256"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="table:table-row">
+ <xsl:if test="($colpath/@表:隐藏 = '1') or ($colpath/@表:隐藏 = 'true')">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('rob',$table-pos)"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$tableHasStyle = 1">
+ <table:table-cell table:number-columns-repeated="256"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="table:table-row">
+ <xsl:choose>
+ <xsl:when test="表:工作表内容/@表:式样引用">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="表:工作表内容/@表:式样引用"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:text>ro1</xsl:text></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:element name="table:table-cell"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="../../表:公用处理规则/表:条件格式化集/表:条件格式化">
+ <xsl:variable name="condition-row-max">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'R'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="condition-col-max">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'C'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="break-row-max">
+ <xsl:call-template name="break-row-beyond-max">
+ <xsl:with-param name="pos" select="1"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="count-value" select="count(./表:分页符集/表:分页符[@表:行号])"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="end-value">
+ <xsl:choose>
+ <xsl:when test="$condition-row-max &lt; $break-row-max">
+ <xsl:value-of select="$break-row-max"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$condition-row-max"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="get-row-beyond-last">
+ <xsl:with-param name="index-value" select="1"/>
+ <xsl:with-param name="worksheetNo" select="count(preceding-sibling::表:工作表)+1"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="end-pos" select="$end-value"/>
+ <xsl:with-param name="total-col" select="$condition-col-max"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="./表:工作表内容/@表:式样引用">
+ <table:table-row table:style-name="ro1" table:number-rows-repeated="32000">
+ <table:table-cell table:number-columns-repeated="256"/>
+ </table:table-row>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="表:图表">
+ <table:shapes>
+ <xsl:apply-templates select="表:图表">
+ <xsl:with-param name="table-name" select="@表:名称"/>
+ </xsl:apply-templates>
+ </table:shapes>
+ </xsl:if>
+ </xsl:template>
+ <!--xsl:template name="create-columns-without-input"></xsl:template>
+ <xsl:template name="create-columns"></xsl:template>
+ <xsl:template name="condition-row-column-string"></xsl:template>
+<xsl:template name="validation-row-column-string"></xsl:template>
+<xsl:template name="create-rows"></xsl:template>
+<xsl:template name="condition-row-col-pos-max"></xsl:template>
+<xsl:template name="get-row-beyond-last"></xsl:template-->
+ <!--xsl:template name="break-row-beyond-max"></xsl:template-->
+ <!-- chengxz有问题-->
+ <xsl:template name="create-columns-without-input">
+ <xsl:param name="table-pos"/>
+ <xsl:variable name="rowpath" select="表:工作表内容/表:行"/>
+ <xsl:variable name="colpath" select="表:工作表内容/表:列"/>
+ <xsl:choose>
+ <xsl:when test="./表:分页符集/表:分页符[@表:列号]">
+ <xsl:for-each select="./表:分页符集/表:分页符[@表:列号]">
+ <xsl:variable name="number-repeated">
+ <xsl:choose>
+ <xsl:when test="position() = 1">
+ <xsl:value-of select="./@表:列号"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./@表:列号 - preceding::表:分页符[@表:列号 and (position()=count(.))]/@表:列号 - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$number-repeated &gt; 0">
+ <xsl:element name="table:table-column">
+ <xsl:if test="ancestor::表:工作表/表:工作表内容/@表:式样引用">
+ <xsl:attribute name="table:default-cell-style-name"><xsl:value-of select="ancestor::表:工作表/表:工作表内容/@表:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="($colpath/@表:隐藏 = '1') or ($colpath/@表:隐藏 = 'true')">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('co',$table-pos)"/></xsl:attribute>
+ <xsl:attribute name="table:number-columns-repeated"><xsl:value-of select="$number-repeated"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="table:table-column">
+ <xsl:if test="ancestor::表:工作表/表:工作表内容/@表:式样引用">
+ <xsl:attribute name="table:default-cell-style-name"><xsl:value-of select="ancestor::表:工作表/表:工作表内容/@表:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="($colpath/@表:隐藏 = '1') or ($colpath/@表:隐藏 = 'true')">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('cob',$table-pos)"/></xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="table:table-column">
+ <xsl:choose>
+ <xsl:when test="表:工作表内容/@表:式样引用">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="表:工作表内容/@表:式样引用"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:text>co1</xsl:text></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="表:工作表内容/@表:最大列 and 表:工作表内容/@表:最大列 > 0">
+ <xsl:attribute name="table:number-columns-repeated"><xsl:value-of select="表:工作表内容/@表:最大列"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:default-cell-style-name"><xsl:text>Default</xsl:text></xsl:attribute>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-columns">
+ <xsl:param name="columnCount"/>
+ <xsl:param name="currentColumn" select="1"/>
+ <xsl:param name="finishedColumns" select="0"/>
+ <xsl:param name="worksheetNo" select="count(preceding-sibling::表:工作表)+1"/>
+ <xsl:param name="currentColumnNode"/>
+ <xsl:choose>
+ <xsl:when test="$finishedColumns &lt; $columnCount">
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode">
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode/@表:列号 - $finishedColumns &gt; 1">
+ <xsl:call-template name="create-default-column">
+ <xsl:with-param name="currentColumn" select="$currentColumn"/>
+ <xsl:with-param name="currentColumnNode" select="$currentColumnNode"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="currentColumn" select="$currentColumn"/>
+ <xsl:with-param name="currentColumnNode" select="$currentColumnNode"/>
+ <xsl:with-param name="finishedColumns" select="$finishedColumns + 1"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="table:table-column">
+ <xsl:if test="($currentColumnNode/@表:隐藏 = '1') or ($currentColumnNode/@表:隐藏 = 'true')">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$currentColumnNode/@表:跨度">
+ <xsl:attribute name="table:number-columns-repeated"><xsl:value-of select="$currentColumnNode/@表:跨度 + 1"/></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="key('ColBreak', $currentColumn)">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('cob', $worksheetNo, '-', $currentColumn)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('co', $worksheetNo, '-', $currentColumn)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="currentColumn" select="$currentColumn + 1"/>
+ <xsl:with-param name="finishedColumns" select="$finishedColumns + 1"/>
+ <xsl:with-param name="currentColumnNode" select="表:工作表属性/表:列[$currentColumn + 1]"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-default-column">
+ <xsl:with-param name="currentColumn" select="$currentColumn"/>
+ <xsl:with-param name="currentColumnNode" select="$currentColumnNode"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ <xsl:call-template name="create-columns">
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="currentColumn" select="$currentColumn"/>
+ <xsl:with-param name="finishedColumns" select="$finishedColumns + 1"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$currentColumn = $columnCount">
+ <xsl:if test="表:分页符集/表:分页符/@表:列号 &gt; $finishedColumns">
+ <xsl:call-template name="get-column-beyond-last">
+ <xsl:with-param name="index-value" select="$finishedColumns"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-column-beyond-last">
+ <xsl:param name="index-value"/>
+ <xsl:param name="worksheetNo"/>
+ <xsl:for-each select="表:分页符集/表:分页符[@表:列号]">
+ <xsl:variable name="each-column-value" select="@表:列号"/>
+ <xsl:choose>
+ <xsl:when test="$each-column-value + 1 &gt; $index-value">
+ <xsl:variable name="number-repeated">
+ <xsl:choose>
+ <xsl:when test="preceding-sibling::表:分页符[@表:列号][position()=count(.)]/@表:列号 + 1 = $index-value">
+ <xsl:value-of select="$each-column-value - preceding-sibling::表:分页符[@表:列号 and (position()=count(.))]/@表:列号 - 1"/>
+ </xsl:when>
+ <xsl:when test="preceding-sibling::表:分页符[@表:列号 and (position()=count(.))]/@表:列号 + 1 &gt; $index-value">
+ <xsl:value-of select="$each-column-value - preceding-sibling::表:分页符[@表:列号][position()=count(.)]/@表:列号 - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$each-column-value - $index-value + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$number-repeated &gt; 0">
+ <xsl:element name="table:table-column">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="'co1'"/></xsl:attribute>
+ <xsl:attribute name="table:number-columns-repeated"><xsl:value-of select="$number-repeated"/></xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="table:table-column">
+ <xsl:if test="../../表:工作表内容[@表:式样引用]">
+ <xsl:attribute name="table:default-cell-style-name"><xsl:value-of select="./表:工作表内容/@表:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('cob',$worksheetNo)"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="$each-column-value + 1 = $index-value">
+ <xsl:element name="table:table-column">
+ <xsl:if test="/../../表:工作表内容[@表:式样引用]">
+ <xsl:attribute name="table:default-cell-style-name"><xsl:value-of select="./../../表:工作表内容/@表:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('cob',$worksheetNo)"/></xsl:attribute>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="condition-row-column-string">
+ <xsl:param name="last"/>
+ <xsl:param name="total"/>
+ <xsl:param name="index"/>
+ <xsl:variable name="table-pos" select="count(preceding-sibling::表:工作表)+1"/>
+ <xsl:variable name="current">
+ <xsl:call-template name="parse-range">
+ <xsl:with-param name="range-value" select="../../表:公用处理规则/表:条件格式化集/表:条件格式化[position() = $index]/表:范围"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="current-value" select="concat('(c',$table-pos,'-',$index,':', $current,');')"/>
+ <xsl:if test="$index &lt; $total">
+ <xsl:call-template name="condition-row-column-string">
+ <xsl:with-param name="last" select="concat($last, $current-value)"/>
+ <xsl:with-param name="total" select="$total"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$index = $total">
+ <xsl:value-of select="concat($last, $current-value)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="validation-row-column-string">
+ <xsl:param name="last"/>
+ <xsl:param name="total"/>
+ <xsl:param name="index"/>
+ <xsl:variable name="table-pos" select="count(preceding-sibling::表:工作表)+1"/>
+ <xsl:variable name="current">
+ <xsl:call-template name="parse-range">
+ <xsl:with-param name="range-value" select="../../表:公用处理规则/表:数据有效性集/表:数据有效性[position() = $index]/表:范围"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="current-value" select="concat('(v',$index,':', $current,');')"/>
+ <xsl:if test="$index &lt; $total">
+ <xsl:call-template name="validation-row-column-string">
+ <xsl:with-param name="last" select="concat($last, $current-value)"/>
+ <xsl:with-param name="total" select="$total"/>
+ <xsl:with-param name="index" select="$index + 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$index = $total">
+ <xsl:value-of select="concat($last, $current-value)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-rows">
+ <xsl:param name="lastrowpos"/>
+ <xsl:param name="row-count"/>
+ <xsl:param name="currentRow"/>
+ <xsl:param name="condition-pos-str"/>
+ <xsl:choose>
+ <xsl:when test="$currentRow &lt; ($row-count + 1)">
+ <xsl:variable name="span-value">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:行号">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="./表:工作表内容/表:行[position() = $currentRow]/@表:行号 - $lastrowpos + ./表:工作表内容/表:行[position() = $currentRow]/@表:跨度"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./表:工作表内容/表:行[position() = $currentRow]/@表:行号 - $lastrowpos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="./表:工作表内容/表:行[position() = $currentRow]/@表:跨度 + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="current-index">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:行号">
+ <xsl:value-of select="./表:工作表内容/表:行[position() = $currentRow]/@表:行号"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$lastrowpos + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:分组集/表:行">
+ <xsl:for-each select="./表:工作表内容/表:分组集/表:行[1]">
+ <xsl:call-template name="table:table-row-group"/>
+ </xsl:for-each>
+ <xsl:for-each select="./表:工作表内容/表:行[not(@表:行号)]">
+ <xsl:call-template name="create-row">
+ <xsl:with-param name="index-value" select="$lastrowpos"/>
+ <xsl:with-param name="span-value" select="$span-value"/>
+ <xsl:with-param name="worksheetNo" select="count(preceding-sibling::表:工作表)+1"/>
+ <xsl:with-param name="row-value" select="$currentRow"/>
+ <xsl:with-param name="times" select="1"/>
+ <xsl:with-param name="current-index" select="$current-index"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="./表:工作表内容/表:分组集 and ( ./表:工作表内容/表:分组集/表:行/@表:起始 &gt;= ($currentRow - 1) and ($currentRow - 1) &lt;= ./表:工作表内容/表:分组集/表:行/@表:终止 )">
+ <xsl:element name="table:table-row-group">
+ <xsl:variable name="TempStart">
+ <xsl:value-of select="./表:工作表内容/表:分组集/表:行/@表:起始"/>
+ </xsl:variable>
+ <xsl:variable name="TempEnd">
+ <xsl:value-of select="./表:工作表内容/表:分组集/表:行/@表:终止"/>
+ </xsl:variable>
+ <xsl:for-each select="./表:工作表内容/表:行">
+ <xsl:if test="$TempStart &gt;= ($currentRow - 1) and ($currentRow - 1) &lt;= $TempEnd">
+ <xsl:call-template name="create-row">
+ <xsl:with-param name="index-value" select="$lastrowpos"/>
+ <xsl:with-param name="span-value" select="$span-value"/>
+ <xsl:with-param name="worksheetNo" select="count(preceding-sibling::表:工作表)+1"/>
+ <xsl:with-param name="row-value" select="$currentRow"/>
+ <xsl:with-param name="times" select="1"/>
+ <xsl:with-param name="current-index" select="$current-index"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-row">
+ <xsl:with-param name="index-value" select="$lastrowpos"/>
+ <xsl:with-param name="span-value" select="$span-value"/>
+ <xsl:with-param name="worksheetNo" select="count(preceding-sibling::表:工作表)+1"/>
+ <xsl:with-param name="row-value" select="$currentRow"/>
+ <xsl:with-param name="times" select="1"/>
+ <xsl:with-param name="current-index" select="$current-index"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ <xsl:if test="$currentRow &lt; $row-count">
+ <xsl:call-template name="create-rows">
+ <xsl:with-param name="lastrowpos">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:行号">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="./表:工作表内容/表:行[position() = $currentRow]/@表:行号 + ./表:工作表内容/表:行[position() = $currentRow]/@表:跨度"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./表:工作表内容/表:行[position() = $currentRow]/@表:行号"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="$lastrowpos + ./表:工作表内容/表:行[position() = $currentRow]/@表:跨度 + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$lastrowpos + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="row-count" select="$row-count"/>
+ <xsl:with-param name="currentRow" select="$currentRow + 1"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$currentRow = $row-count">
+ <xsl:variable name="last-pos">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:行号">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="./表:工作表内容/表:行[position() = $currentRow]/@表:行号 + ./表:工作表内容/表:行[position() = $currentRow]/@表:跨度"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./表:工作表内容/表:行[position() = $currentRow]/@表:行号"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="$lastrowpos + ./表:工作表内容/表:行[position() = $currentRow]/@表:跨度 + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$lastrowpos + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="./表:分页符集/表:分页符/@表:行号 &gt; ($last-pos - 1) or ../../表:公用处理规则/表:条件格式化集/表:条件格式化">
+ <xsl:variable name="condition-row-max">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'R'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="condition-col-max">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'C'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="break-row-max">
+ <xsl:call-template name="break-row-beyond-max">
+ <xsl:with-param name="pos" select="1"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="count-value" select="count(./表:分页符集/表:分页符[@表:行号])"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="end-value">
+ <xsl:choose>
+ <xsl:when test="$condition-row-max &lt; $break-row-max">
+ <xsl:value-of select="$break-row-max"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$condition-row-max"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="get-row-beyond-last">
+ <xsl:with-param name="index-value" select="$last-pos + 1"/>
+ <xsl:with-param name="worksheetNo" select="count(preceding-sibling::表:工作表)+1"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="end-pos" select="$end-value"/>
+ <xsl:with-param name="total-col" select="$condition-col-max"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="./表:工作表内容/表:列[@表:式样引用] or ./表:工作表内容[@表:式样引用]">
+ <table:table-row table:style-name="ro1" table:number-rows-repeated="31990">
+ <table:table-cell table:number-columns-repeated="256"/>
+ </table:table-row>
+ <table:table-row table:style-name="ro1">
+ <table:table-cell table:number-columns-repeated="256"/>
+ </table:table-row>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <!-- add row-group 2.6-->
+ <xsl:template name="table:table-row-group">
+ <xsl:param name="start"/>
+ <xsl:param name="end"/>
+ <xsl:variable name="start1" select="@表:起始"/>
+ <xsl:variable name="end1" select="@表:终止"/>
+ <xsl:variable name="nextstart" select="following-sibling::表:行/@表:起始"/>
+ <xsl:variable name="nextend" select="following-sibling::表:行/@表:终止"/>
+ <xsl:variable name="prestart" select="preceding-sibling::表:行/@表:起始"/>
+ <xsl:variable name="preend" select="preceding-sibling::表:行/@表:终止"/>
+ <xsl:variable name="numrow" select="$end1 - $start1"/>
+ <xsl:variable name="position" select="position()"/>
+ <xsl:choose>
+ <xsl:when test="$nextstart &gt;= $start1 and $nextend &lt;= $end1">
+ <table:table-row-group>
+ <xsl:call-template name="creategroup"/>
+ </table:table-row-group>
+ </xsl:when>
+ <xsl:when test="$nextstart &gt;= $end1">
+ <xsl:choose>
+ <xsl:when test="$nextend &lt;=$preend">
+ <xsl:call-template name="row">
+ <xsl:with-param name="start1" select="$start1"/>
+ <xsl:with-param name="end1" select="$end1"/>
+ <xsl:with-param name="nextstart" select="$nextstart"/>
+ <xsl:with-param name="nextend" select="$nextend"/>
+ <xsl:with-param name="prestart" select="$prestart"/>
+ <xsl:with-param name="preend" select="$preend"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="levelgroup"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="row">
+ <xsl:with-param name="start1" select="$start1"/>
+ <xsl:with-param name="end1" select="$end1"/>
+ <xsl:with-param name="nextstart" select="$nextstart"/>
+ <xsl:with-param name="nextend" select="$nextend"/>
+ <xsl:with-param name="prestart" select="$prestart"/>
+ <xsl:with-param name="preend" select="$preend"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="levelrowgroup">
+ <xsl:param name="start"/>
+ <xsl:param name="end"/>
+ <xsl:variable name="start1" select="@表:起始"/>
+ <xsl:variable name="end1" select="@表:终止"/>
+ <xsl:variable name="nextstart" select="following-sibling::表:行/@表:起始"/>
+ <xsl:variable name="nextend" select="following-sibling::表:行/@表:终止"/>
+ <xsl:variable name="prestart" select="preceding-sibling::表:行/@表:起始"/>
+ <xsl:variable name="preend" select="preceding-sibling::表:行/@表:终止"/>
+ <xsl:variable name="numrow" select="$end1 - $start1"/>
+ <xsl:variable name="position" select="position()"/>
+ <xsl:call-template name="row">
+ <xsl:with-param name="start1" select="$start1"/>
+ <xsl:with-param name="end1" select="$end1"/>
+ <xsl:with-param name="nextstart" select="$nextstart"/>
+ <xsl:with-param name="nextend" select="$nextend"/>
+ <xsl:with-param name="prestart" select="$prestart"/>
+ <xsl:with-param name="preend" select="$preend"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="creategroup">
+ <xsl:for-each select="following-sibling::表:行">
+ <xsl:variable name="start1" select="@表:起始"/>
+ <xsl:variable name="end1" select="@表:终止"/>
+ <xsl:variable name="nextstart" select="following-sibling::表:行/@表:起始"/>
+ <xsl:variable name="nextend" select="following-sibling::表:行/@表:终止"/>
+ <xsl:variable name="prestart" select="preceding-sibling::表:行/@表:起始"/>
+ <xsl:variable name="preend" select="preceding-sibling::表:行/@表:终止"/>
+ <xsl:if test="$start1 &gt;= $prestart and $end1 &lt;= $preend">
+ <xsl:call-template name="table:table-row-group"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="levelgroup">
+ <xsl:for-each select="parent::表:分组集/表:行">
+ <xsl:call-template name="levelrowgroup"/>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="row">
+ <xsl:param name="start1"/>
+ <xsl:param name="end1"/>
+ <xsl:param name="nextstart"/>
+ <xsl:param name="nextend"/>
+ <xsl:param name="prestart"/>
+ <xsl:param name="preend"/>
+ <xsl:for-each select="ancestor::表:工作表内容/表:行[@表:行号]">
+ <xsl:variable name="rownum" select="@表:行号"/>
+ <xsl:variable name="aa" select="$start1 - $prestart"/>
+ <xsl:if test="$rownum &gt;= $prestart and $rownum &lt;= ($prestart + $aa - 1) and $start1 &lt;= $preend">
+ <table:table-row>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="@表:式样引用"/></xsl:attribute>
+ <xsl:call-template name="celldata"/>
+ </table:table-row>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="ancestor::表:工作表内容/表:行[@表:行号]">
+ <xsl:variable name="rownum" select="@表:行号"/>
+ <xsl:variable name="ss" select="$start1 - $preend"/>
+ <xsl:if test="$rownum &gt;= ($preend +1) and $rownum &lt;= ($preend + $ss - 1) and $start1 &gt;= $preend">
+ <table:table-row>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="@表:式样引用"/></xsl:attribute>
+ <xsl:call-template name="celldata"/>
+ </table:table-row>
+ </xsl:if>
+ </xsl:for-each>
+ <table:table-row-group>
+ <xsl:for-each select="ancestor::表:工作表内容/表:行[@表:行号]">
+ <xsl:variable name="rownum" select="@表:行号"/>
+ <xsl:if test="$rownum &lt;= $end1">
+ <xsl:if test="$rownum &gt;= $start1">
+ <table:table-row>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="@表:式样引用"/></xsl:attribute>
+ <xsl:call-template name="celldata"/>
+ </table:table-row>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </table:table-row-group>
+ <xsl:for-each select="ancestor::表:工作表内容/表:行[@表:行号]">
+ <xsl:variable name="rownum" select="@表:行号"/>
+ <xsl:variable name="bb" select="$preend - $end1"/>
+ <xsl:if test="$rownum &gt;= ($end1 + 1) and $rownum &lt;= ($end1 + $bb) and $start1 &lt; $preend">
+ <table:table-row>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="@表:式样引用"/></xsl:attribute>
+ <xsl:call-template name="celldata"/>
+ </table:table-row>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="celldata">
+ <xsl:for-each select="./表:单元格">
+ <table:table-cell>
+ <xsl:choose>
+ <xsl:when test="表:数据/@表:数据类型 = 'number'">
+ <xsl:attribute name="office:value-type">float</xsl:attribute>
+ <xsl:attribute name="office:value"><xsl:choose><xsl:when test="表:数据/@表:数据数值"><xsl:value-of select="表:数据/@表:数据数值"/></xsl:when><xsl:otherwise><xsl:value-of select="表:数据/字:句/字:文本串"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:数据/@表:数据类型 = 'date'">
+ <xsl:attribute name="office:value-type">date</xsl:attribute>
+ <xsl:attribute name="table:date-value"><xsl:value-of select="表:数据/@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:数据/@表:数据类型 = 'time'">
+ <xsl:attribute name="office:value-type">time</xsl:attribute>
+ <xsl:attribute name="table:time-value"><xsl:value-of select="表:数据/@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:数据/@表:数据类型 = 'boolean'">
+ <xsl:attribute name="office:value-type">boolean</xsl:attribute>
+ <xsl:attribute name="table:boolean-value"><xsl:choose><xsl:when test="表:数据/字:句/字:文本串 = '1'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:数据/@表:数据类型 = 'text'">
+ <xsl:attribute name="office:value-type">string</xsl:attribute>
+ <xsl:attribute name="table:string-value"><xsl:value-of select="表:数据/@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="表:数据/字:句/字:文本串">
+ <text:p>
+ <xsl:value-of select="表:数据/字:句/字:文本串"/>
+ </text:p>
+ </xsl:if>
+ </table:table-cell>
+ </xsl:for-each>
+ </xsl:template>
+ <!-- add row-group 2.8 -->
+ <xsl:template name="create-row">
+ <xsl:param name="index-value"/>
+ <xsl:param name="span-value"/>
+ <xsl:param name="worksheetNo"/>
+ <xsl:param name="row-value"/>
+ <xsl:param name="times"/>
+ <xsl:param name="current-index"/>
+ <xsl:param name="condition-pos-str"/>
+ <xsl:element name="table:table-row">
+ <xsl:choose>
+ <xsl:when test="./表:分页符集/表:分页符/@表:行号 = ($index-value + $times - 1)">
+ <xsl:choose>
+ <xsl:when test="($index-value + $times &lt; $current-index) and ($current-index != 0)">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('rob',$worksheetNo)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('rob', $worksheetNo, '-', $row-value)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="($index-value + $times &lt; $current-index) and ($current-index != 0)">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('ro',$worksheetNo)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('ro', $worksheetNo, '-', $row-value)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--chengxiuzhi0617-->
+ <xsl:if test="./表:工作表内容/表:行[position() = $row-value]/@表:隐藏 = 'true'">
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容/表:行[position() = $row-value]/@表:跨度">
+ <xsl:if test="$index-value + $times &gt; ($current-index - 1)">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$index-value + $times = $current-index">
+ <xsl:attribute name="table:visibility">collapse</xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="not(./表:工作表内容/表:行[position() = $row-value]/*)">
+ <table:table-cell>
+ <xsl:for-each select="./表:单元格/表:数据">
+ <xsl:choose>
+ <xsl:when test="@表:数据类型 = 'number'">
+ <xsl:attribute name="office:value-type">float</xsl:attribute>
+ <xsl:attribute name="office:value"><xsl:choose><xsl:when test="@表:数据数值"><xsl:value-of select="@表:数据数值"/></xsl:when><xsl:otherwise><xsl:value-of select="字:句/字:文本串"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:数据类型 = 'date'">
+ <xsl:attribute name="office:value-type">date</xsl:attribute>
+ <xsl:attribute name="table:date-value"><xsl:value-of select="@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:数据类型 = 'time'">
+ <xsl:attribute name="office:value-type">time</xsl:attribute>
+ <xsl:attribute name="table:time-value"><xsl:value-of select="@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:数据类型 = 'boolean'">
+ <xsl:attribute name="office:value-type">boolean</xsl:attribute>
+ <xsl:attribute name="table:boolean-value"><xsl:choose><xsl:when test="字:句/字:文本串 = '1'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:数据类型 = 'text'">
+ <xsl:attribute name="office:value-type">string</xsl:attribute>
+ <xsl:attribute name="table:string-value"><xsl:value-of select="@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="字:句/字:文本串">
+ <text:p>
+ <xsl:value-of select="字:句/字:文本串"/>
+ </text:p>
+ </xsl:if>
+ </xsl:for-each>
+ </table:table-cell>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$index-value + $times &lt; $current-index">
+ <xsl:variable name="current" select="concat('R',($index-value + $times),'C')"/>
+ <xsl:variable name="col-pos-max">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'C'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str,$current)">
+ <xsl:call-template name="get-cell-span-in">
+ <xsl:with-param name="row-pos" select="$index-value + $times"/>
+ <xsl:with-param name="c-start" select="1"/>
+ <xsl:with-param name="c-end" select="$col-pos-max"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$index-value + $times = $current-index">
+ <xsl:apply-templates select="表:工作表内容/表:行[position() = $row-value]" mode="selected">
+ <xsl:with-param name="row-pos" select="$index-value + $times"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="$times &lt; $span-value">
+ <xsl:call-template name="create-row">
+ <xsl:with-param name="index-value" select="$index-value"/>
+ <xsl:with-param name="span-value" select="$span-value"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ <xsl:with-param name="row-value" select="$row-value"/>
+ <xsl:with-param name="times" select="$times + 1"/>
+ <xsl:with-param name="current-index" select="$current-index"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="condition-row-col-pos-max">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="last-value"/>
+ <xsl:param name="div-value"/>
+ <xsl:variable name="pre-value">
+ <xsl:choose>
+ <xsl:when test="$div-value = 'R'">
+ <xsl:value-of select="substring-before(substring-after($condition-pos-str,$div-value),'C')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(substring-after($condition-pos-str,$div-value),',')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="end-value">
+ <xsl:choose>
+ <xsl:when test="$last-value &lt; $pre-value">
+ <xsl:value-of select="$pre-value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$last-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str,$div-value)">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="substring-after($condition-pos-str,$div-value)"/>
+ <xsl:with-param name="last-value" select="$end-value"/>
+ <xsl:with-param name="div-value" select="$div-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$end-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="break-row-beyond-max">
+ <xsl:param name="pos"/>
+ <xsl:param name="last-value"/>
+ <xsl:param name="count-value"/>
+ <xsl:variable name="pre-value" select="./表:分页符集/表:分页符[@表:列号 and (position() = $pos)]/@表:列号"/>
+ <xsl:variable name="end-value">
+ <xsl:choose>
+ <xsl:when test="$last-value &lt; $pre-value">
+ <xsl:value-of select="$pre-value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$last-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$pos &lt; $count-value">
+ <xsl:call-template name="break-row-beyond-max">
+ <xsl:with-param name="pos" select="$pos + 1"/>
+ <xsl:with-param name="last-value" select="$end-value"/>
+ <xsl:with-param name="count-value" select="$count-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$end-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-row-beyond-last">
+ <xsl:param name="index-value"/>
+ <xsl:param name="worksheetNo"/>
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="end-pos"/>
+ <xsl:param name="total-col"/>
+ <xsl:variable name="current" select="concat('R',$index-value)"/>
+ <xsl:element name="table:table-row">
+ <xsl:choose>
+ <xsl:when test="./表:分页符集/表:分页符/@行号 = ($index-value - 1)">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('rob',$worksheetNo)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('ro',$worksheetNo)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str,$current)">
+ <xsl:call-template name="get-cell-span-in">
+ <xsl:with-param name="row-pos" select="$index-value"/>
+ <xsl:with-param name="c-start" select="1"/>
+ <xsl:with-param name="c-end" select="$total-col"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:if test="$index-value &lt; ($end-pos + 1)">
+ <xsl:call-template name="get-row-beyond-last">
+ <xsl:with-param name="index-value" select="$index-value + 1"/>
+ <xsl:with-param name="worksheetNo" select="$worksheetNo"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="end-pos" select="$end-pos"/>
+ <xsl:with-param name="total-col" select="$total-col"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="get-cell-span-in">
+ <xsl:param name="row-pos"/>
+ <xsl:param name="c-start"/>
+ <xsl:param name="c-end"/>
+ <xsl:param name="condition-pos-str"/>
+ <xsl:variable name="current" select="concat('R',$row-pos,'C',$c-start,',')"/>
+ <xsl:variable name="style-name">
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str,$current)">
+ <xsl:variable name="temp-str">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-before($condition-pos-str,$current)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="starts-with($temp-str, 'c')">
+ <xsl:value-of select="concat('ce', substring-after($temp-str, 'c'))"/>
+ </xsl:when>
+ <xsl:when test="starts-with($temp-str, 'v')">
+ <xsl:value-of select="concat('val', substring-after($temp-str, 'v'))"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="../表:单元格[position() = position() - 1]/@表:式样引用">
+ <xsl:value-of select="../表:单元格[position() = position() - 1]/@表:式样引用 "/>
+ </xsl:when>
+ <xsl:when test="../@表:式样引用">
+ <xsl:value-of select="../@表:式样引用"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'Default'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$c-start &lt; $c-end">
+ <xsl:call-template name="get-cell-condition-in">
+ <xsl:with-param name="style-name" select="$style-name"/>
+ </xsl:call-template>
+ <xsl:call-template name="get-cell-span-in">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="c-start" select="$c-start + 1"/>
+ <xsl:with-param name="c-end" select="$c-end"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$c-start = $c-end">
+ <xsl:call-template name="get-cell-condition-in">
+ <xsl:with-param name="style-name" select="$style-name"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-cell-condition-in">
+ <xsl:param name="style-name"/>
+ <xsl:element name="table:table-cell">
+ <xsl:if test="not( contains($style-name, 'Default'))">
+ <xsl:choose>
+ <xsl:when test="starts-with($style-name, 'val')">
+ <xsl:attribute name="table:content-validation-name"><xsl:value-of select="$style-name"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="starts-with($style-name, 'ce')">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="$style-name"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="$style-name"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <!--chengxiuzhi0617 单元格-->
+ </xsl:element>
+ </xsl:template>
+ <xsl:key match="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:分页符集/表:分页符[@表:列号]" name="ColBreak" use="Column"/>
+ <xsl:template name="create-default-column">
+ <xsl:param name="currentColumn"/>
+ <xsl:param name="currentColumnNode"/>
+ <xsl:param name="worksheetNo"/>
+ <xsl:element name="table:table-column">
+ <xsl:attribute name="table:default-cell-style-name"><xsl:call-template name="get-default-cell-style"><xsl:with-param name="currentColumnNode" select="$currentColumnNode"/></xsl:call-template></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="key('ColBreak', $currentColumn)">
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('cob',$worksheetNo)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('co',$worksheetNo)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--chengxiuzhi0617用key就错-->
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="get-default-cell-style">
+ <xsl:param name="currentColumnNode"/>
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode">
+ <xsl:choose>
+ <xsl:when test="$currentColumnNode/@表:式样引用">
+ <xsl:value-of select="$currentColumnNode/@表:式样引用"/>
+ </xsl:when>
+ <xsl:otherwise>Default</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./表:工作表内容[@表:式样引用]">
+ <xsl:value-of select="./表:工作表内容/@表:式样引用"/>
+ </xsl:when>
+ <xsl:otherwise>Default</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="表:行" mode="selected">
+ <xsl:param name="row-pos"/>
+ <xsl:param name="condition-pos-str"/>
+ <xsl:choose>
+ <xsl:when test="表:单元格">
+ <xsl:apply-templates select="表:单元格[1]" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'C'"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="col-pos-before" select="0"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="current" select="concat('R',$row-pos,'C')"/>
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str,$current)">
+ <xsl:call-template name="get-cell-span-in">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="c-start" select="1"/>
+ <xsl:with-param name="c-end">
+ <xsl:call-template name="condition-row-col-pos-max">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="last-value" select="0"/>
+ <xsl:with-param name="div-value" select="'C'"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos" select="1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="表:单元格" mode="selected">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="col-pos-max"/>
+ <xsl:param name="col-pos-before"/>
+ <xsl:param name="row-pos"/>
+ <xsl:param name="col-repeated" select="1"/>
+ <xsl:variable name="col-pos">
+ <xsl:choose>
+ <xsl:when test="@表:列号">
+ <xsl:choose>
+ <xsl:when test="@表:合并列数">
+ <xsl:value-of select="@表:合并列数 + @表:列号"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@表:列号"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@表:合并列数">
+ <xsl:value-of select="1 + @表:合并列数 + $col-pos-before"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="1 + $col-pos-before"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="next-cell" select="following-sibling::表:单元格[1]"/>
+ <xsl:variable name="maodian" select="boolean($next-cell/uof:锚点)"/>
+ <xsl:variable name="cell-is-repeatable" select="not(current()/*) and not($next-cell/*) and not($next-cell/text()) and (@表:式样引用 = $next-cell/@表:式样引用) and not($next-cell/@表:列号)"/>
+ <xsl:if test="$col-repeated = 1">
+ <xsl:if test="@表:列号 != ($col-pos-before + 1)">
+ <xsl:call-template name="get-cell-span-in">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="c-start" select="$col-pos-before + 1"/>
+ <xsl:with-param name="c-end" select="@表:列号 - 1"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:element name="table:table-cell">
+ <xsl:call-template name="create-table-cell-attributes">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos" select="$col-pos"/>
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ </xsl:call-template>
+ <xsl:if test="$cell-is-repeatable">
+ <xsl:apply-templates select="$next-cell" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-before" select="$col-pos + 1"/>
+ <xsl:with-param name="col-repeated" select="$col-repeated + 1"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ <xsl:call-template name="create-table-cell-content">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos" select="$col-pos"/>
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:if test="@表:合并列数">
+ <xsl:element name="table:covered-table-cell">
+ <xsl:if test="@表:合并列数 &gt; 1">
+ <xsl:attribute name="table:number-columns-repeated"><xsl:value-of select="@表:合并列数"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="not($cell-is-repeatable and $col-repeated = 1)">
+ <xsl:choose>
+ <xsl:when test="not($cell-is-repeatable) and $col-repeated &gt; 1">
+ <xsl:attribute name="table:number-columns-repeated"><xsl:value-of select="$col-repeated"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="not($next-cell)">
+ <xsl:if test="../../../../../表:公用处理规则/表:条件格式化集/表:条件格式化">
+ <xsl:call-template name="get-cell-span-in">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="c-start" select="$col-pos"/>
+ <xsl:with-param name="c-end" select="$col-pos-max"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="not($cell-is-repeatable)">
+ <xsl:apply-templates select="$next-cell" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-before" select="$col-pos"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="$next-cell" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-before" select="$col-pos"/>
+ <xsl:with-param name="col-repeated" select="$col-repeated + 1"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$next-cell">
+ <xsl:apply-templates select="$next-cell" mode="skip">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-before" select="$col-pos"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--Redoffice comment liliang sc0012 06.02.15-->
+ <!--新增内容-->
+ <xsl:template match="uof:锚点">
+ <xsl:variable name="tuxing1" select="@uof:图形引用"/>
+ <xsl:choose>
+ <xsl:when test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]">
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='png' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='ipg' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='bmp' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='gif'">
+ <xsl:element name="draw:frame">
+ <xsl:attribute name="draw:name"><xsl:variable name="pos"><xsl:value-of select="count(preceding::uof:锚点)"/></xsl:variable><xsl:value-of select="concat('图形',$pos)"/></xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@uof:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:element name="draw:image">
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径">
+ <xsl:attribute name="xlink:href"><xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符= $tuxing1]/uof:路径"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:数据">
+ <office:binary-data>
+ <xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:数据"/>
+ </office:binary-data>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:文本内容[@图:文本框='true']">
+ <draw:text-box text:anchor-type="paragraph">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="$tuxing1"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@uof:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="@uof:x坐标">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@uof:y坐标">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="/uof:UOF/uof:对象集/图:图形/@图:层次"/></xsl:attribute>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]/图:文本内容/字:段落"/>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]/图:文本内容/字:文字表"/>
+ </draw:text-box>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="graph">
+ <xsl:with-param name="id" select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]"/>
+ <xsl:with-param name="groupx" select="0"/>
+ <xsl:with-param name="groupy" select="0"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="graph">
+ <xsl:param name="id"/>
+ <xsl:param name="groupx"/>
+ <xsl:param name="groupy"/>
+ <xsl:for-each select="$id">
+ <xsl:variable name="tuxing1">
+ <xsl:value-of select="图:预定义图形/图:类别"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$tuxing1='11'">
+ <xsl:call-template name="Rectangle">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='19'">
+ <xsl:call-template name="Oval">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='61'">
+ <xsl:call-template name="Line">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='64'">
+ <xsl:call-template name="Curve">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='65'">
+ <xsl:call-template name="Freeform">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='66'">
+ <xsl:call-template name="Scribble">
+ <xsl:with-param name="groupx1" select="$groupx"/>
+ <xsl:with-param name="groupy1" select="$groupy"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$tuxing1='4'">
+ <xsl:element name="draw:g">
+ <xsl:variable name="tu">
+ <xsl:value-of select="@图:标识符"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="$tu"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:variable name="this-group-x">
+ <xsl:choose>
+ <xsl:when test="key('rel_graphic_name',@图:标识符)/@uof:x坐标">
+ <xsl:value-of select="key('rel_graphic_name',@图:标识符)/@uof:x坐标"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="number(0)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="this-group-y">
+ <xsl:choose>
+ <xsl:when test="key('rel_graphic_name',@图:标识符)/@uof:y坐标">
+ <xsl:value-of select="key('rel_graphic_name',@图:标识符)/@uof:y坐标"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="number(0)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="group-x">
+ <xsl:value-of select="number($groupx + $this-group-x)"/>
+ </xsl:variable>
+ <xsl:variable name="group-y">
+ <xsl:value-of select="number($groupy + $this-group-y)"/>
+ </xsl:variable>
+ <xsl:call-template name="组合图形">
+ <xsl:with-param name="zuheliebiao" select="@图:组合列表"/>
+ <xsl:with-param name="groupx1" select="$group-x"/>
+ <xsl:with-param name="groupy1" select="$group-y"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="common">
+ <xsl:param name="groupx"/>
+ <xsl:param name="groupy"/>
+ <xsl:variable name="tuxing">
+ <xsl:value-of select="@图:标识符"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="key('rel_graphic_name',@图:标识符)/@uof:x坐标">
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)">
+ <xsl:if test="@uof:x坐标">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@uof:y坐标">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="tuxing1" select="@uof:图形引用"/>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@uof:高度,$uofUnit)"/></xsl:attribute>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="zuheweizhi-x">
+ <xsl:value-of select="图:组合位置/@图:x坐标"/>
+ </xsl:variable>
+ <xsl:variable name="zuheweizhi-y">
+ <xsl:value-of select="图:组合位置/@图:y坐标"/>
+ </xsl:variable>
+ <xsl:attribute name="text:anchor-type">paragraph</xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(($groupx + $zuheweizhi-x),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(($groupy + $zuheweizhi-y),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(图:预定义图形/图:属性/图:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(图:预定义图形/图:属性 /图:高度,$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="组合图形">
+ <xsl:param name="zuheliebiao"/>
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:variable name="x">
+ <xsl:value-of select="$groupx1"/>
+ </xsl:variable>
+ <xsl:variable name="y">
+ <xsl:value-of select="$groupy1"/>
+ </xsl:variable>
+ <xsl:variable name="first-pictures">
+ <xsl:value-of select="substring-before($zuheliebiao,',')"/>
+ </xsl:variable>
+ <xsl:variable name="other-pictures">
+ <xsl:value-of select="substring-after($zuheliebiao,',')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($other-pictures,',')">
+ <xsl:call-template name="graph">
+ <xsl:with-param name="id" select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $first-pictures]"/>
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ <xsl:call-template name="组合图形">
+ <xsl:with-param name="zuheliebiao" select="$other-pictures"/>
+ <xsl:with-param name="groupx1" select="$x"/>
+ <xsl:with-param name="groupy1" select="$y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="graph">
+ <xsl:with-param name="id" select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $first-pictures]"/>
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ <xsl:call-template name="graph">
+ <xsl:with-param name="id" select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $other-pictures]"/>
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="Curve">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:path">
+ <xsl:variable name="width" select="number(图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="svg:d"><xsl:value-of select="图:预定义图形/图:关键点坐标/@图:路径"/></xsl:attribute>
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Freeform">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:polygon">
+ <xsl:variable name="width" select="number(图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="draw:points"><xsl:call-template name="drawpoints"><xsl:with-param name="points" select="图:预定义图形/图:关键点坐标/@图:路径"/><xsl:with-param name="value"/></xsl:call-template></xsl:attribute>
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Scribble">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:polyline">
+ <xsl:variable name="width" select="number(图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="draw:points"><xsl:call-template name="drawpoints"><xsl:with-param name="points" select="图:预定义图形/图:关键点坐标/@图:路径"/><xsl:with-param name="value"/></xsl:call-template></xsl:attribute>
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="drawpoints">
+ <xsl:param name="points"/>
+ <xsl:param name="value"/>
+ <xsl:variable name="frist-piont">
+ <xsl:value-of select="substring-before($points,'lineto')"/>
+ </xsl:variable>
+ <xsl:variable name="other-points">
+ <xsl:value-of select="substring-after($points,'lineto')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($other-points,'lineto')">
+ <xsl:variable name="x-coor">
+ <xsl:value-of select="substring-before($frist-piont,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="y-coor">
+ <xsl:value-of select="substring-after($frist-piont,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="all-points">
+ <xsl:value-of select="concat($value,$x-coor,',',$y-coor,' ')"/>
+ </xsl:variable>
+ <xsl:call-template name="drawpoints">
+ <xsl:with-param name="points" select="$other-points"/>
+ <xsl:with-param name="value" select="$all-points"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="q-x-coor">
+ <xsl:value-of select="substring-before($frist-piont,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="q-y-coor">
+ <xsl:value-of select="substring-after($frist-piont,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="e-x-coor">
+ <xsl:value-of select="substring-before($other-points,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:variable name="e-y-coor">
+ <xsl:value-of select="substring-after($other-points,' ') * 1000"/>
+ </xsl:variable>
+ <xsl:value-of select="concat($value,$q-x-coor,',',$q-y-coor,' ',$e-x-coor,',',$e-y-coor)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="Oval">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:ellipse">
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Rectangle">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:rect">
+ <xsl:call-template name="common">
+ <xsl:with-param name="groupx" select="$groupx1"/>
+ <xsl:with-param name="groupy" select="$groupy1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Line">
+ <xsl:param name="groupx1"/>
+ <xsl:param name="groupy1"/>
+ <xsl:element name="draw:line">
+ <xsl:variable name="tuxing1" select="@图:标识符"/>
+ <xsl:choose>
+ <xsl:when test="key('rel_graphic_name',@图:标识符)">
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)">
+ <xsl:attribute name="svg:x1"><xsl:value-of select="concat(@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y1"><xsl:value-of select="concat(@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:x2"><xsl:value-of select="concat((number(@uof:x坐标) + number(@uof:宽度)),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y2"><xsl:value-of select="concat((number(@uof:y坐标) + number(@uof:高度)),$uofUnit)"/></xsl:attribute>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="zuheweizhi-x">
+ <xsl:value-of select="图:组合位置/@图:x坐标"/>
+ </xsl:variable>
+ <xsl:variable name="zuheweizhi-y">
+ <xsl:value-of select="图:组合位置/@图:y坐标"/>
+ </xsl:variable>
+ <xsl:variable name="hex">
+ <xsl:value-of select="concat(number($groupx1 + $zuheweizhi-x),$uofUnit)"/>
+ </xsl:variable>
+ <xsl:variable name="hey">
+ <xsl:value-of select="concat(number($groupy1 + $zuheweizhi-y),$uofUnit)"/>
+ </xsl:variable>
+ <xsl:attribute name="svg:x1"><xsl:value-of select="$hex"/></xsl:attribute>
+ <xsl:attribute name="svg:y1"><xsl:value-of select="$hey"/></xsl:attribute>
+ <xsl:attribute name="svg:x2"><xsl:value-of select="concat(($hex + 图:预定义图形/图:属性/图:宽度),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y2"><xsl:value-of select="concat(($hey + 图:预定义图形/图:属性/图:高度),$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="text:anchor-type">paragraph</xsl:attribute>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="$tuxing1"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="rotate-angle">
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <!--Redoffice comment liliang end 06.02.15-->
+ <xsl:template match="表:单元格" mode="skip">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="col-pos-max"/>
+ <xsl:param name="col-pos-before"/>
+ <xsl:param name="row-pos"/>
+ <xsl:variable name="next-cell" select="following-sibling::表:单元格[1]"/>
+ <xsl:variable name="cell-is-repeatable" select="not($next-cell/*) and not($next-cell/text()) and (@表:式样引用 = $next-cell/@表:式样引用) and not($next-cell/@表:列号)"/>
+ <xsl:choose>
+ <xsl:when test="$cell-is-repeatable">
+ <xsl:apply-templates select="$next-cell" mode="skip">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-before" select="$col-pos-before + 1"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="$next-cell">
+ <xsl:apply-templates select="$next-cell" mode="selected">
+ <xsl:with-param name="row-pos" select="$row-pos"/>
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="col-pos-max" select="$col-pos-max"/>
+ <xsl:with-param name="col-pos-before" select="$col-pos-before +1"/>
+ </xsl:apply-templates>
+ <!--chengxz0925 no otherwise ,some content cells missed -->
+ </xsl:if>
+ <!--chengxz 060418 add if sentence-->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--xsl:template name="create-table-cell-attributes"></xsl:template>
+<xsl:template name="create-table-cell-content"></xsl:template>
+<xsl:template name="create-data-content"></xsl:template>
+<xsl:template name="get-condition-dependent-cell-attributes"></xsl:template-->
+ <xsl:template name="create-table-cell-attributes">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="col-pos-max"/>
+ <xsl:param name="col-pos"/>
+ <xsl:param name="row-pos"/>
+ <xsl:choose>
+ <xsl:when test="$condition-pos-str">
+ <xsl:call-template name="get-condition-dependent-cell-attributes">
+ <xsl:with-param name="condition-pos-str" select="$condition-pos-str"/>
+ <xsl:with-param name="current-pos-str" select="concat('R',$row-pos,'C',$col-pos,',')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:choose><xsl:when test="@表:式样引用"><xsl:value-of select="@表:式样引用"/></xsl:when><xsl:when test="../@表:式样引用 and ../@表:式样引用 != ''"><xsl:value-of select="../@表:式样引用"/></xsl:when><xsl:otherwise><xsl:value-of select="'Default'"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <!--chengxiuzhi-->
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@表:合并列数 or @表:合并行数">
+ <xsl:choose>
+ <xsl:when test="@表:合并列数">
+ <xsl:attribute name="table:number-columns-spanned"><xsl:value-of select="@表:合并列数 + 1"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:number-columns-spanned">1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@表:合并行数">
+ <xsl:attribute name="table:number-rows-spanned"><xsl:value-of select="@表:合并行数+1"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:number-rows-spanned">1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="表:数据">
+ <xsl:if test="表:数据/表:公式">
+ <xsl:variable name="calc-formula">
+ <xsl:call-template name="translate-expression">
+ <xsl:with-param name="cell-row-pos" select="$row-pos"/>
+ <xsl:with-param name="cell-column-pos" select="$col-pos"/>
+ <xsl:with-param name="expression" select="表:数据/表:公式"/>
+ <xsl:with-param name="return-value" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="table:formula"><xsl:value-of select="$calc-formula"/></xsl:attribute>
+ </xsl:if>
+ <!--RedOffice Comment from Zengjh:UOF0020 2006-04-17 Based on Original-->
+ <xsl:variable name="table-stylename" select="@表:式样引用"/>
+ <xsl:variable name="data-format">
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:单元格式样">
+ <xsl:if test="$table-stylename = ./@ 表:标识符">
+ <xsl:value-of select="表:数字格式/@表:分类名称"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="data-formatcode">
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:单元格式样">
+ <xsl:if test="$table-stylename= ./@表:标识符">
+ <xsl:value-of select="表:数字格式/@表:格式码"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="表:数据/@表:数据类型 = 'number'">
+ <xsl:choose>
+ <xsl:when test="$data-format = 'percentage' or contains( $data-formatcode, '%')">
+ <xsl:attribute name="office:value-type">percentage</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains($data-format, 'currency')">
+ <xsl:attribute name="office:value-type">currency</xsl:attribute>
+ <xsl:attribute name="office:currency">CNY</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="office:value-type">float</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="office:value"><xsl:choose><xsl:when test="表:数据/@表:数据数值"><xsl:value-of select="表:数据/@表:数据数值"/></xsl:when><xsl:otherwise><xsl:value-of select="表:数据/字:句/字:文本串"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:数据/@表:数据类型 = 'date'">
+ <xsl:attribute name="office:value-type">date</xsl:attribute>
+ <xsl:attribute name="office:date-value"><xsl:value-of select="表:数据/@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:数据/@表:数据类型 = 'time'">
+ <xsl:attribute name="office:value-type">time</xsl:attribute>
+ <xsl:attribute name="office:time-value"><xsl:value-of select="表:数据/@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:数据/@表:数据类型 = 'boolean'">
+ <xsl:attribute name="office:value-type">boolean</xsl:attribute>
+ <xsl:attribute name="office:boolean-value"><xsl:choose><xsl:when test="表:数据/字:句/字:文本串 = '1'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="表:数据/@表:数据类型 = 'text'">
+ <xsl:attribute name="office:value-type">string</xsl:attribute>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="表:数据/@表:数据数值"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <!-- zhangying ok and /uof:UOF/uof:电子表格/表:公共处理规则/表:数据有效性集-->
+ <xsl:if test="表:数据">
+ <xsl:variable name="validation-name">
+ <xsl:call-template name="zyvalidationtest">
+ <xsl:with-param name="column-num" select="$col-pos"/>
+ <xsl:with-param name="row-num" select="$row-pos"/>
+ <xsl:with-param name="table-name" select="ancestor::表:工作表/@表:名称"/>
+ <xsl:with-param name="validation-set" select="/uof:UOF/uof:电子表格/表:公用处理规则/表:数据有效性集/表:数据有效性"/>
+ <xsl:with-param name="validation-num" select="'1'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$validation-name!=''">
+ <xsl:attribute name="table:content-validation-name"><xsl:value-of select="$validation-name"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <!-- zhangying mod end -->
+ </xsl:template>
+ <!-- zhangying o -->
+ <xsl:template name="zyvalidationtest">
+ <xsl:param name="row-num"/>
+ <xsl:param name="column-num"/>
+ <xsl:param name="table-name"/>
+ <xsl:param name="validation-set"/>
+ <xsl:param name="validation-num"/>
+ <xsl:if test="$validation-set">
+ <xsl:variable name="zone" select="$validation-set/表:区域/text()"/>
+ <xsl:variable name="success">
+ <xsl:choose>
+ <xsl:when test="$table-name=substring-after(substring-before($zone,'.'),'$')">
+ <xsl:variable name="validation-row-left-top" select="substring-before(substring-after(substring-after(substring-after($zone,'$'),'$'),'$'),':')"/>
+ <xsl:variable name="validation-row-right-bottom" select="substring-after(substring-after(substring-after($zone,':$'),'$'),'$')"/>
+ <xsl:choose>
+ <xsl:when test="($row-num &gt;= $validation-row-left-top and $row-num &lt;= $validation-row-right-bottom) or $validation-row-left-top=$validation-row-right-bottom">
+ <xsl:variable name="validation-column-left-top">
+ <xsl:call-template name="translate-column-char-to-number">
+ <xsl:with-param name="string" select="substring-before(substring-after(substring-after($zone,'$'),'$'),'$')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="validation-column-right-bottom">
+ <xsl:call-template name="translate-column-char-to-number">
+ <xsl:with-param name="string" select="substring-before(substring-after(substring-after($zone,':$'),'$'),'$')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="($column-num &gt;= $validation-column-left-top) and ($column-num &lt;= $validation-column-right-bottom)">yes</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$success='yes'">
+ <xsl:value-of select="concat('val',$validation-num)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="zyvalidationtest">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="column-num" select="$column-num"/>
+ <xsl:with-param name="validation-set" select="$validation-set[position()!=1]"/>
+ <xsl:with-param name="validation-num" select="$validation-num + 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <!--zhangying mod end -->
+ <xsl:template name="create-table-cell-content">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="col-pos-max"/>
+ <xsl:param name="col-pos"/>
+ <xsl:param name="row-pos"/>
+ <!--Redoffice comment liliang SC0011 06.02.15 -->
+ <!--新增内容-->
+ <xsl:apply-templates select="uof:锚点"/>
+ <!--Redoffice comment liliang end 06.02.15 -->
+ <xsl:apply-templates select="表:批注" mode="body"/>
+ <!--RedOffice Comment from Zengjh:UOF0020 2006-04-26 charts-->
+ <xsl:apply-templates select="表:图表"/>
+ <xsl:if test="表:数据/字:句">
+ <text:p>
+ <xsl:call-template name="create-data-content">
+ <xsl:with-param name="style-id" select="../../@表:式样引用"/>
+ </xsl:call-template>
+ </text:p>
+ </xsl:if>
+ <!--chengxz0701多个句不能读入-->
+ </xsl:template>
+ <xsl:template name="create-data-content">
+ <xsl:param name="style-id" select="@表:式样引用"/>
+ <xsl:variable name="html-children" select="表:式样引用/descendant-or-self::*[namespace-uri()='http://www.w3.org/TR/REC-html40'][string-length(text()) != 0]"/>
+ <xsl:choose>
+ <xsl:when test="$html-children and $html-children != ''">
+ <xsl:for-each select="$html-children">
+ <text:span text:style-name="{concat($style-id, 'T', count(preceding::表:数据/字:句/字:文本串[child::html:*]), '_', position())}">
+ <xsl:copy-of select="text()"/>
+ </text:span>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="@表:超链接引用">
+ <text:a xlink:href="{@表:超链接引用}">
+ <xsl:value-of select="表:数据/字:句/字:文本串"/>
+ </text:a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="表:数据/字:句">
+ <xsl:choose>
+ <xsl:when test="name(descendant::*[1])='字:句属性'">
+ <text:span>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="descendant::*[1]/@字:式样引用"/></xsl:attribute>
+ <xsl:value-of select="./字:文本串"/>
+ </text:span>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./字:文本串"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="create-comment-data-content">
+ <xsl:param name="style-id" select="@表:式样引用"/>
+ <xsl:variable name="html-children" select="表:式样引用/descendant-or-self::*[namespace-uri()='http://www.w3.org/TR/REC-html40'][string-length(text()) != 0]"/>
+ <xsl:choose>
+ <xsl:when test="$html-children and $html-children != ''">
+ <xsl:for-each select="$html-children">
+ <text:span text:style-name="{concat($style-id, 'T', count(preceding::图:文本内容/字:段落/字:句/字:文本串[child::html:*]), '_', position())}">
+ <xsl:copy-of select="text()"/>
+ </text:span>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:when test="@表:超链接引用">
+ <text:a xlink:href="{@表:超链接引用}">
+ <xsl:value-of select="图:文本内容/字:段落/字:句/字:文本串"/>
+ </text:a>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="图:文本内容/字:段落/字:句/字:文本串"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-condition-dependent-cell-attributes">
+ <xsl:param name="condition-pos-str"/>
+ <xsl:param name="current-pos-str"/>
+ <xsl:variable name="temp-str">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-before($condition-pos-str,$current-pos-str)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="style-name">
+ <xsl:choose>
+ <xsl:when test="contains($condition-pos-str, $current-pos-str) and starts-with($temp-str, 'c')">
+ <xsl:value-of select="concat('ce', substring-after($temp-str, 'c'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@表:式样引用">
+ <xsl:value-of select="@表:式样引用"/>
+ </xsl:when>
+ <xsl:when test="../@表:式样引用">
+ <xsl:value-of select="../@表:式样引用"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'Default'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="not( contains($style-name, 'Default'))">
+ <xsl:choose>
+ <xsl:when test="starts-with($style-name, 'val')">
+ <xsl:attribute name="table:content-validation-name"><xsl:value-of select="$style-name"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="$style-name"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="contains($style-name, 'Default')">
+ <xsl:variable name="style-nametemp">
+ <xsl:choose>
+ <xsl:when test="@表:式样引用">
+ <xsl:value-of select="@表:式样引用"/>
+ </xsl:when>
+ <xsl:when test="../@表:式样引用">
+ <xsl:value-of select="../@表:式样引用"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'Default'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="$style-nametemp"/></xsl:attribute>
+ <!--xsl:attribute name="style:data-style-name"><xsl:value-of select="N104" /></xsl:attribute-->
+ </xsl:if>
+ <!--chengxz-->
+ <xsl:if test="contains($condition-pos-str, $current-pos-str)">
+ <xsl:choose>
+ <xsl:when test="starts-with($temp-str, 'v')">
+ <xsl:attribute name="table:content-validation-name"><xsl:value-of select="concat('val', substring-after($temp-str, 'v'))"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="after-str" select="substring-after($condition-pos-str, $current-pos-str)"/>
+ <xsl:if test="contains( $after-str, $current-pos-str)">
+ <xsl:variable name="temp-str-2">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-before( $after-str,$current-pos-str)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="starts-with( $temp-str-2, 'v')">
+ <xsl:attribute name="table:content-validation-name"><xsl:value-of select="concat('val', substring-after($temp-str-2, 'v'))"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="表:工作表内容">
+ <xsl:variable name="default-column-width">
+ <xsl:choose>
+ <xsl:when test="@表:缺省列宽">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(@表:缺省列宽,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>2.096cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="table-pos">
+ <xsl:value-of select="count(../preceding-sibling::表:工作表)+1"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="表:列">
+ <xsl:call-template name="get-column-style-name">
+ <xsl:with-param name="finishedColumns" select="0"/>
+ <xsl:with-param name="columnCount" select="count(./表:列)"/>
+ <xsl:with-param name="currentCount" select="1"/>
+ <xsl:with-param name="table-pos" select="$table-pos"/>
+ <xsl:with-param name="default-column-width" select="$default-column-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="../表:分页符集/表:分页符[@表:列号]">
+ <style:style style:name="{concat('cob',$table-pos)}" style:family="table-column">
+ <xsl:element name="style:table-column-properties">
+ <xsl:attribute name="style:column-width"><xsl:value-of select="$default-column-width"/></xsl:attribute>
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:element>
+ </style:style>
+ </xsl:if>
+ <xsl:variable name="default-row-height">
+ <xsl:choose>
+ <xsl:when test="@表:缺省行高">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="concat(@表:缺省行高,'pt')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>0.503cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <style:style style:family="table-row" style:name="{concat('ro', $table-pos)}">
+ <style:table-row-properties style:row-height="{$default-row-height}" style:use-optimal-row-height="false"/>
+ </style:style>
+ <xsl:if test="表:行">
+ <xsl:call-template name="get-row-style-name">
+ <xsl:with-param name="lastrowpos" select="0"/>
+ <xsl:with-param name="row-count" select="count(./表:行)"/>
+ <xsl:with-param name="currentRow" select="1"/>
+ <xsl:with-param name="table-pos" select="$table-pos"/>
+ <xsl:with-param name="default-row-height" select="$default-row-height"/>
+ </xsl:call-template>
+ </xsl:if>
+ <!--RedOffice Comment from Zengjh:UOF0020 2006-06-11 charts-->
+ <xsl:for-each select="//表:图表">
+ <xsl:variable name="chart-current">
+ <xsl:number level="any" count="表:图表" format="1"/>
+ </xsl:variable>
+ <style:style style:family="graphics" style:name="{concat('chart', $chart-current)}">
+ <style:graphic-properties>
+ <xsl:choose>
+ <xsl:when test="@表:随动方式='none'">
+ <xsl:attribute name="draw:move-protect">true</xsl:attribute>
+ <xsl:attribute name="draw:size-protect">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:随动方式='move'">
+ <xsl:attribute name="draw:size-protect">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </style:graphic-properties>
+ </style:style>
+ </xsl:for-each>
+ <!--RedOffice comment (Zengjh) end charts-->
+ <xsl:if test="../表:分页符集/表:分页符[@行号]">
+ <style:style style:name="{concat('rob',$table-pos)}" style:family="table-row">
+ <xsl:element name="style:table-row-properties">
+ <xsl:attribute name="style:row-height"><xsl:value-of select="$default-row-height"/></xsl:attribute>
+ <xsl:attribute name="style:use-optimal-row-height">false</xsl:attribute>
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:element>
+ </style:style>
+ </xsl:if>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="concat( 'ta', $table-pos)"/></xsl:attribute>
+ <xsl:attribute name="style:family">table</xsl:attribute>
+ <xsl:attribute name="style:master-page-name"><xsl:call-template name="encode-as-nc-name"><xsl:with-param name="string" select="concat( 'TAB_',../@表:名称)"/></xsl:call-template></xsl:attribute>
+ <xsl:element name="style:properties">
+ <xsl:choose>
+ <xsl:when test="../@表:隐藏 = 'true'">
+ <xsl:attribute name="table:display">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:display">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="get-column-style-name">
+ <xsl:param name="finishedColumns"/>
+ <xsl:param name="columnCount"/>
+ <xsl:param name="currentCount"/>
+ <xsl:param name="table-pos"/>
+ <xsl:param name="default-column-width"/>
+ <xsl:if test="$currentCount &lt; ($columnCount + 1)">
+ <xsl:variable name="span-value">
+ <xsl:choose>
+ <xsl:when test="./表:列[position() = $currentCount]/@表:跨度">
+ <xsl:value-of select="./表:跨度[position() = $currentCount]/@表:跨度 + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="current-index">
+ <xsl:choose>
+ <xsl:when test="./表:列[position() = $currentCount]/@表:列号">
+ <xsl:value-of select="./表:列[position() = $currentCount]/@表:列号 - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$finishedColumns"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="column-break">
+ <xsl:choose>
+ <xsl:when test="$span-value = 0">
+ <xsl:if test="../表:分页符集/表:分页符/表:列 = $current-index">
+ <xsl:value-of select="1"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="../表:分页符集/表:分页符[(@表:列号 &gt; $finishedColumns) and (@表:列号 &lt; ($finishedColumns + $span-value))]">
+ <xsl:value-of select="1"/>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$column-break = 1">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:call-template name="encode-as-nc-name"><xsl:with-param name="string" select="concat('cob', $table-pos, '-',$currentCount)"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="style:family">table-column</xsl:attribute>
+ <xsl:element name="style:table-column-properties">
+ <xsl:choose>
+ <xsl:when test="./表:列[position() = $currentCount]/@表:列宽">
+ <xsl:attribute name="style:column-width"><xsl:call-template name="convert2cm"><xsl:with-param name="value" select="concat(./表:列[position() = $currentCount]/@表:列宽,'pt')"/></xsl:call-template><xsl:text>cm</xsl:text></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:column-width"><xsl:value-of select="$default-column-width"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="./表:列[position() = $currentCount]/@表:列宽 &gt; 0">
+ <xsl:attribute name="style:use-optimal-column-width">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-optimal-column-width">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ <style:style style:name="{concat('co', $table-pos, '-',$currentCount)}" style:family="table-column">
+ <xsl:element name="style:table-column-properties">
+ <xsl:choose>
+ <xsl:when test="./表:列[position() = $currentCount]/@表:列宽">
+ <xsl:attribute name="style:column-width"><xsl:call-template name="convert2cm"><xsl:with-param name="value" select="concat(./表:列[position() = $currentCount]/@表:列宽,'pt')"/></xsl:call-template><xsl:text>cm</xsl:text></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:column-width"><xsl:value-of select="$default-column-width"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:break-before">auto</xsl:attribute>
+ </xsl:element>
+ </style:style>
+ <xsl:if test="$currentCount &lt; $columnCount">
+ <xsl:call-template name="get-column-style-name">
+ <xsl:with-param name="finishedColumns">
+ <xsl:choose>
+ <xsl:when test="./表:列[position() = $currentCount]/@表:列号">
+ <xsl:choose>
+ <xsl:when test="./表:列[position() = $currentCount]/@表:跨度">
+ <xsl:value-of select="./表:列[position() = $currentCount]/@表:列宽 + ./表:列[position() = $currentCount]/@表:跨度"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./表:列[position() = $currentCount]/@表:列号"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./表:列[position() = $currentCount]/@表:跨度">
+ <xsl:value-of select="$finishedColumns + ./表:列[position() = $currentCount]/@表:跨度 + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$finishedColumns + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="columnCount" select="$columnCount"/>
+ <xsl:with-param name="currentCount" select="$currentCount + 1"/>
+ <xsl:with-param name="table-pos" select="$table-pos"/>
+ <xsl:with-param name="default-column-width" select="$default-column-width"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="get-row-style-name">
+ <xsl:param name="lastrowpos"/>
+ <xsl:param name="row-count"/>
+ <xsl:param name="currentRow"/>
+ <xsl:param name="table-pos"/>
+ <xsl:param name="default-row-height"/>
+ <xsl:if test="$currentRow &lt; ($row-count + 1)">
+ <xsl:variable name="span-value">
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:行号">
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="./表:行[position() = $currentRow]/@表:行号 - $lastrowpos+ ./表:行[position() = $currentRow]/@表:跨度"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="./表:行[position() = $currentRow]/@表:跨度 + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="current-index">
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:行号">
+ <xsl:value-of select="./表:行[position() = $currentRow]/@表:行号 - 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$lastrowpos"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="row-break">
+ <xsl:choose>
+ <xsl:when test="$span-value = 0">
+ <xsl:if test="../表:分页符集/表:分页符/@表:行号 = $current-index">
+ <xsl:value-of select="1"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="../表:分页符集/表:分页符[(@表:行号 &gt; $lastrowpos) and (@表:行号 &lt; ($lastrowpos + $span-value))]">
+ <xsl:value-of select="1"/>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$row-break = 1">
+ <style:style style:name="{concat('rob', $table-pos, '-',$currentRow)}" style:family="table-row">
+ <xsl:element name="style:table-row-properties">
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:行高">
+ <xsl:attribute name="style:row-height"><xsl:call-template name="convert2cm"><xsl:with-param name="value" select="concat(./表:行[position() = $currentRow]/@表:行高,'pt')"/></xsl:call-template><xsl:text>cm</xsl:text></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:row-height"><xsl:value-of select="$default-row-height"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:行高 &gt; 0">
+ <xsl:attribute name="style:use-optimal-row-height">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-optimal-row-height">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:element>
+ </style:style>
+ </xsl:if>
+ <style:style style:name="{concat('ro', $table-pos, '-',$currentRow)}" style:family="table-row">
+ <xsl:element name="style:table-row-properties">
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:行高">
+ <xsl:attribute name="style:row-height"><xsl:call-template name="convert2cm"><xsl:with-param name="value" select="concat(./表:行[position() = $currentRow]/@表:行高,'pt')"/></xsl:call-template><xsl:text>cm</xsl:text></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:row-height"><xsl:value-of select="$default-row-height"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="style:use-optimal-row-height">true</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:行高 &gt; 0">
+ <xsl:attribute name="style:use-optimal-row-height">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:use-optimal-row-height">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:break-before">auto</xsl:attribute>
+ </xsl:element>
+ </style:style>
+ <xsl:if test="$currentRow &lt; $row-count">
+ <xsl:call-template name="get-row-style-name">
+ <xsl:with-param name="lastrowpos">
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:行号">
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="./表:行[position() = $currentRow]/@表:行号 + ./表:行[position() = $currentRow]/@表:跨度"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="./表:行[position() = $currentRow]/@表:行号"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="./表:行[position() = $currentRow]/@表:跨度">
+ <xsl:value-of select="$lastrowpos + ./表:行[position() = $currentRow]/@表:跨度 + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$lastrowpos + 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="row-count" select="$row-count"/>
+ <xsl:with-param name="currentRow" select="$currentRow + 1"/>
+ <xsl:with-param name="table-pos" select="$table-pos"/>
+ <xsl:with-param name="default-row-height" select="$default-row-height"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="encode-as-nc-name">
+ <xsl:param name="string"/>
+ <xsl:value-of select="translate($string, '. %()/\+', '')"/>
+ </xsl:template>
+ <xsl:key match="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:行/表:单元格" name="cells" use="@表:式样引用"/>
+ <xsl:template match="表:数字格式">
+ <xsl:variable name="unit-count" select="string-length(@表:格式码) - string-length(translate(@表:格式码,';','')) + 1"/>
+ <xsl:variable name="style-id" select="../@表:标识符"/>
+ <xsl:variable name="number-format-name">
+ <xsl:choose>
+ <xsl:when test="@表:分类名称='fraction' or @表:分类名称='scientific'">number</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@表:分类名称"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="process-number-format">
+ <xsl:with-param name="number-format-name" select="$number-format-name"/>
+ <xsl:with-param name="number-format-unit" select="@表:格式码"/>
+ <xsl:with-param name="style-id" select="concat($style-id,'F')"/>
+ <xsl:with-param name="format-type" select="key('cells', $style-id)/表:数据/@表:数据类型"/>
+ <xsl:with-param name="total-unit" select="$unit-count"/>
+ <xsl:with-param name="current-unit" select="0"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="process-number-format">
+ <xsl:param name="number-format-name"/>
+ <xsl:param name="number-format-unit"/>
+ <xsl:param name="style-id"/>
+ <xsl:param name="format-type"/>
+ <xsl:param name="total-unit"/>
+ <xsl:param name="current-unit"/>
+ <xsl:choose>
+ <xsl:when test="$current-unit &lt; ($total-unit -1)">
+ <xsl:variable name="style-name">
+ <xsl:choose>
+ <xsl:when test="contains(substring-before($number-format-unit,';'),'[$')">currency</xsl:when>
+ <xsl:when test="contains(substring-before($number-format-unit,';'),'%')">percentage</xsl:when>
+ <xsl:otherwise>number</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="{concat('number:',$style-name,'-style')}">
+ <xsl:attribute name="style:name"><xsl:value-of select="concat( $style-id, 'P',$current-unit)"/></xsl:attribute>
+ <xsl:attribute name="style:volatile">true</xsl:attribute>
+ <xsl:call-template name="general-number">
+ <xsl:with-param name="number-format-unit" select="substring-before($number-format-unit,';')"/>
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:call-template name="process-number-format">
+ <xsl:with-param name="number-format-name" select="$number-format-name"/>
+ <xsl:with-param name="number-format-unit" select="substring-after($number-format-unit,';')"/>
+ <xsl:with-param name="style-id" select="$style-id"/>
+ <xsl:with-param name="format-type" select="$format-type"/>
+ <xsl:with-param name="total-unit" select="$total-unit"/>
+ <xsl:with-param name="current-unit" select="$current-unit +1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="{concat('number:',$number-format-name,'-style')}">
+ <xsl:attribute name="style:name"><xsl:value-of select="$style-id"/></xsl:attribute>
+ <xsl:call-template name="element-attribute">
+ <xsl:with-param name="number-format-unit" select="string($number-format-unit)"/>
+ </xsl:call-template>
+ <xsl:call-template name="general-number">
+ <xsl:with-param name="number-format-unit" select="string($number-format-unit)"/>
+ </xsl:call-template>
+ <xsl:call-template name="style-map">
+ <xsl:with-param name="number-format-name" select="@表:分类名称"/>
+ <xsl:with-param name="number-format-unit" select="@表:格式码"/>
+ <xsl:with-param name="style-id" select="$style-id"/>
+ <xsl:with-param name="format-type" select="$format-type"/>
+ <xsl:with-param name="total-unit" select="$total-unit"/>
+ <xsl:with-param name="current-unit" select="0"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="style-map">
+ <xsl:param name="number-format-name"/>
+ <xsl:param name="number-format-unit"/>
+ <xsl:param name="style-id"/>
+ <xsl:param name="format-type"/>
+ <xsl:param name="total-unit"/>
+ <xsl:param name="current-unit"/>
+ <xsl:if test="$current-unit &lt; ($total-unit -1)">
+ <xsl:variable name="stylecondition" select="substring-after(substring-before($number-format-unit,']'),'[')"/>
+ <style:map style:condition="{$stylecondition}" style:apply-style-name="{concat( $style-id, 'P',$current-unit)}"/>
+ <xsl:call-template name="style-map">
+ <xsl:with-param name="number-format-name" select="$number-format-name"/>
+ <xsl:with-param name="number-format-unit" select="substring-after($number-format-unit,';')"/>
+ <xsl:with-param name="style-id" select="$style-id"/>
+ <xsl:with-param name="format-type" select="$format-type"/>
+ <xsl:with-param name="total-unit" select="$total-unit"/>
+ <xsl:with-param name="current-unit" select="$current-unit +1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="general-number">
+ <xsl:param name="number-format-unit"/>
+ <xsl:call-template name="number-format-color">
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ </xsl:call-template>
+ <xsl:call-template name="number-format-currency">
+ <xsl:with-param name="number-format-unit" select="$number-format-unit"/>
+ </xsl:call-template>
+ <xsl:choose>
+ <xsl:when test="starts-with($number-format-unit,'&quot;')">
+ <number:text>
+ <xsl:value-of select="substring-before(substring-after($number-format-unit,'&quot;'),'&quot;')"/>
+ </number:text>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'@')">
+ <number:text-content/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'-') or starts-with($number-format-unit,'$') or starts-with($number-format-unit,'¥')">
+ <number:text>
+ <xsl:value-of select="substring($number-format-unit,1,1)"/>
+ </number:text>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'YYYY')">
+ <number:year number:style="long"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'YY')">
+ <number:year number:style="rolong"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'MMMM')">
+ <number:month number:style="long" number:textual="true"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'MMM')">
+ <number:month number:style="rolong" number:textual="true"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'DD')">
+ <number:day number:style="long"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'D')">
+ <number:day number:style="rolong"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[HH]')">
+ <number:hours number:style="long"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'HH')">
+ <number:hours number:style="long"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'H')">
+ <number:hours/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'SS.00')">
+ <number:seconds number:style="long" number:decimal-places="2"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'SS')">
+ <number:seconds number:style="long"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'S')">
+ <number:seconds/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'AM/PM')">
+ <number:am-pm/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'NNNN')">
+ <number:day-of-week number:style="long"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'NNN')">
+ <number:day-of-week/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'QQ')">
+ <number:quarter number:style="long"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'Q')">
+ <number:quarter/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'WW')">
+ <number:week-of-year/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'MM')">
+ <xsl:choose>
+ <xsl:when test="starts-with(substring($number-format-unit,3),'S') or (starts-with(substring($number-format-unit,3),'&quot;') and starts-with(substring-after(substring-after($number-format-unit,'&quot;'),'&quot;'),'S'))">
+ <number:minutes number:style="long"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <number:month number:style="long"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'M')">
+ <xsl:choose>
+ <xsl:when test="starts-with(substring($number-format-unit,2),'S') or (starts-with(substring($number-format-unit,2),'&quot;') and starts-with(substring-after(substring-after($number-format-unit,'&quot;'),'&quot;'),'S'))">
+ <number:minutes/>
+ </xsl:when>
+ <xsl:otherwise>
+ <number:month/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'#') or starts-with($number-format-unit,'0')">
+ <xsl:variable name="digits-part">
+ <xsl:choose>
+ <xsl:when test="contains($number-format-unit,'&quot;')">
+ <xsl:value-of select="substring-before($number-format-unit,'&quot;')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$number-format-unit"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="decimal-integer-exponent-fraction">
+ <xsl:with-param name="digits-part" select="$digits-part"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:variable name="unit-length">
+ <xsl:choose>
+ <xsl:when test="starts-with($number-format-unit,'[value()')">
+ <xsl:value-of select="string-length(substring-before($number-format-unit,']')) +2"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[NatNum')">
+ <xsl:value-of select="string-length(substring-before($number-format-unit,']')) +2"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$-804]')">8</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'&quot;')">
+ <xsl:value-of select="string-length(substring-before(substring-after($number-format-unit,'&quot;'),'&quot;')) +3"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'@')">2</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'-') or starts-with($number-format-unit,'$') or starts-with($number-format-unit,'¥')">2</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'YYYY')">5</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'YY')">3</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'MMMM')">5</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'MMM')">4</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'MM')">3</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'M')">2</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'DD')">3</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'D')">2</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[HH]')">5</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'HH')">3</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'H')">2</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'SS.00')">6</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'SS')">3</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'S')">2</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'AM/PM')">6</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'NNNN')">5</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'NNN')">4</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'QQ')">3</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'Q')">2</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'WW')">3</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'#') or starts-with($number-format-unit,'0')">
+ <xsl:choose>
+ <xsl:when test="contains($number-format-unit,'&quot;')">
+ <xsl:value-of select="string-length(substring-before($number-format-unit,'&quot;')) +1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length($number-format-unit) +1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$unit-length &gt;1 and $unit-length &lt;=string-length($number-format-unit)">
+ <xsl:call-template name="general-number">
+ <xsl:with-param name="number-format-unit" select="substring($number-format-unit,$unit-length)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="decimal-integer-exponent-fraction">
+ <xsl:param name="digits-part"/>
+ <xsl:variable name="decimal-digits">
+ <xsl:choose>
+ <xsl:when test="contains($digits-part,'.')">
+ <xsl:choose>
+ <xsl:when test="contains($digits-part,' ')">
+ <xsl:value-of select="string-length(substring-before(substring-after($digits-part,'.'),' '))"/>
+ </xsl:when>
+ <xsl:when test="contains(substring-after($digits-part,'.'),',')">
+ <xsl:value-of select="string-length(substring-before(substring-after($digits-part,'.'),','))"/>
+ </xsl:when>
+ <xsl:when test="contains($digits-part,'E')">
+ <xsl:value-of select="string-length(substring-before(substring-after($digits-part,'.'),'E'))"/>
+ </xsl:when>
+ <xsl:when test="contains($digits-part,'e')">
+ <xsl:value-of select="string-length(substring-before(substring-after($digits-part,'.'),'e'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length(substring-after($digits-part,'.'))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="decimal-replacement">
+ <xsl:choose>
+ <xsl:when test="contains($digits-part,'.')">
+ <xsl:choose>
+ <xsl:when test="contains($digits-part,' ') and contains(substring-before(substring-after($digits-part,'.'),' '),'#')">true</xsl:when>
+ <xsl:when test="contains($digits-part,'E') and contains(substring-before(substring-after($digits-part,'.'),'E'),'#')">true</xsl:when>
+ <xsl:when test="contains($digits-part,'e') and contains(substring-before(substring-after($digits-part,'.'),'e'),'#')">true</xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="contains(substring-after($digits-part,'.'),'#')">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="integer-digits">
+ <xsl:choose>
+ <xsl:when test="contains($digits-part,'.')">
+ <xsl:value-of select="string-length(substring-before($digits-part,'.')) - string-length(translate(substring-before($digits-part,'.'),'0',''))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="string-length($digits-part) - string-length(translate($digits-part,'0',''))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="factor-digits">
+ <xsl:call-template name="display-factor-digits">
+ <xsl:with-param name="digits-part" select="$digits-part"/>
+ <xsl:with-param name="count" select="0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="grouping">
+ <xsl:choose>
+ <xsl:when test="(string-length($digits-part) - string-length(translate($digits-part,',',''))) &gt;$factor-digits">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="exponent-digits">
+ <xsl:choose>
+ <xsl:when test="contains($digits-part,'E')">
+ <xsl:value-of select="string-length(substring-after($digits-part,'E')) -1"/>
+ </xsl:when>
+ <xsl:when test="contains($digits-part,'e')">
+ <xsl:value-of select="string-length(substring-after($digits-part,'e')) -1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="numerator-digits">
+ <xsl:choose>
+ <xsl:when test="contains($digits-part,' ')">
+ <xsl:value-of select="string-length(substring-before(substring-after($digits-part,' '),'/'))"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="denominator-digits">
+ <xsl:choose>
+ <xsl:when test="contains($digits-part,' ')">
+ <xsl:value-of select="string-length(substring-after(substring-after($digits-part,' '),'/'))"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="number-type">
+ <xsl:choose>
+ <xsl:when test="$exponent-digits &gt;0">number:scientific-number</xsl:when>
+ <xsl:when test="($numerator-digits &gt;0) or ($denominator-digits &gt;0)">number:fraction</xsl:when>
+ <xsl:otherwise>number:number</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="{$number-type}">
+ <xsl:if test="$decimal-digits &gt;=0">
+ <xsl:attribute name="number:decimal-places"><xsl:value-of select="$decimal-digits"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$decimal-replacement='true'">
+ <xsl:attribute name="number:decimal-replacement"/>
+ </xsl:if>
+ <xsl:if test="$integer-digits &gt;=0">
+ <xsl:attribute name="number:min-integer-digits"><xsl:value-of select="$integer-digits"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$grouping='true'">
+ <xsl:attribute name="number:grouping"><xsl:value-of select="$grouping"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$factor-digits &gt;0">
+ <xsl:attribute name="number:display-factor"><xsl:choose><xsl:when test="$factor-digits=1">1000</xsl:when><xsl:when test="$factor-digits=2">1000000</xsl:when><xsl:when test="$factor-digits=3">1000000000</xsl:when><xsl:when test="$factor-digits=4">1000000000000</xsl:when><xsl:when test="$factor-digits=5">1000000000000000</xsl:when><xsl:when test="$factor-digits=6">1000000000000000000</xsl:when><xsl:otherwise>0</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$exponent-digits &gt;0">
+ <xsl:attribute name="number:min-exponent-digits"><xsl:value-of select="$exponent-digits"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$numerator-digits &gt;0">
+ <xsl:attribute name="number:min-numerator-digits"><xsl:value-of select="$numerator-digits"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$denominator-digits &gt;0">
+ <xsl:attribute name="number:min-denominator-digits"><xsl:value-of select="$denominator-digits"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="number-format-color">
+ <xsl:param name="number-format-unit"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($number-format-unit,'[Black]')">
+ <style:text-properties fo:color="#000000"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Blue]')">
+ <style:text-properties fo:color="#0000ff"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Cyan]')">
+ <style:text-properties fo:color="#00ffff"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Green]')">
+ <style:text-properties fo:color="#00ff00"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Magenta]')">
+ <style:text-properties fo:color="#ff00ff"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Red]')">
+ <style:text-properties fo:color="#ff0000"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[White]')">
+ <style:text-properties fo:color="#ffffff"/>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Yellow]')">
+ <style:text-properties fo:color="#ffff00"/>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:variable name="unit-length">
+ <xsl:choose>
+ <xsl:when test="starts-with($number-format-unit,'[Black]')">8</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Blue]')">7</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Cyan]')">7</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Green]')">8</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Magenta]')">10</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Red]')">6</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[White]')">8</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[Yellow]')">9</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$unit-length &gt;1 and $unit-length &lt;=string-length($number-format-unit)">
+ <xsl:call-template name="general-number">
+ <xsl:with-param name="number-format-unit" select="substring($number-format-unit,$unit-length)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="number-format-currency">
+ <xsl:param name="number-format-unit"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($number-format-unit,'[$¥-804]')">
+ <number:currency-symbol number:language="zh" number:country="CN">¥</number:currency-symbol>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$$-409]')">
+ <number:currency-symbol number:language="en" number:country="US">$</number:currency-symbol>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$$-2C0A]')">
+ <number:currency-symbol number:language="es" number:country="AR">$</number:currency-symbol>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$$-C0C]')">
+ <number:currency-symbol number:language="fr" number:country="CA">$</number:currency-symbol>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$CNY]')">
+ <number:currency-symbol>CNY</number:currency-symbol>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$AFA]')">
+ <number:currency-symbol>AFA</number:currency-symbol>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'CNY')">
+ <number:currency-symbol>CNY</number:currency-symbol>
+ </xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'CCC')">
+ <number:currency-symbol>CCC</number:currency-symbol>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:variable name="unit-length">
+ <xsl:choose>
+ <xsl:when test="starts-with($number-format-unit,'[$¥-804]')">9</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$$-409]')">9</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$$-2C0A]')">10</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$$-C0C]')">9</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$CNY]')">7</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'[$AFA]')">7</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'CNY')">4</xsl:when>
+ <xsl:when test="starts-with($number-format-unit,'CCC')">4</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$unit-length &gt;1 and $unit-length &lt;=string-length($number-format-unit)">
+ <xsl:call-template name="general-number">
+ <xsl:with-param name="number-format-unit" select="substring($number-format-unit,$unit-length)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="display-factor-digits">
+ <xsl:param name="digits-part"/>
+ <xsl:param name="count"/>
+ <xsl:choose>
+ <xsl:when test="not(substring($digits-part,string-length($digits-part),1) =',')">
+ <xsl:value-of select="$count"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="display-factor-digits">
+ <xsl:with-param name="digits-part" select="substring($digits-part,1,string-length($digits-part) -1)"/>
+ <xsl:with-param name="count" select="$count +1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="element-attribute">
+ <xsl:param name="number-format-unit"/>
+ <xsl:if test="contains($number-format-unit,'[HH]')">
+ <xsl:attribute name="number:truncate-on-overflow">false</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum1]')">
+ <xsl:attribute name="number:transliteration-format">一</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">short</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum2]')">
+ <xsl:attribute name="number:transliteration-format">壹</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">short</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum3]')">
+ <xsl:attribute name="number:transliteration-format">1</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">short</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum4]')">
+ <xsl:attribute name="number:transliteration-format">一</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">long</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum5]')">
+ <xsl:attribute name="number:transliteration-format">壹</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">long</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum6]')">
+ <xsl:attribute name="number:transliteration-format">1</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">long</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum7]')">
+ <xsl:attribute name="number:transliteration-format">一</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">medium</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum8]')">
+ <xsl:attribute name="number:transliteration-format">壹</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">medium</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="starts-with($number-format-unit,'[NatNum0]')">
+ <xsl:attribute name="number:transliteration-format">1</xsl:attribute>
+ <xsl:attribute name="number:transliteration-style">short</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains($number-format-unit,'[$-804]')">
+ <xsl:attribute name="number:transliteration-language">zh</xsl:attribute>
+ <xsl:attribute name="number:transliteration-country">CN</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:key name="pz" match="/uof:UOF/uof:对象集/图:图形" use="@图:标识符"/>
+ <xsl:template match="表:批注" mode="body">
+ <xsl:element name="office:annotation">
+ <xsl:if test="@表:是否显示 = 'true'">
+ <xsl:attribute name="office:display">true</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="uof:锚点/@uof:图形引用"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(uof:锚点/@uof:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(uof:锚点/@uof:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(uof:锚点/@uof:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(uof:锚点/@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:variable name="w">
+ <xsl:value-of select="./uof:锚点/@uof:图形引用"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="key('pz',$w)/图:文本内容/字:句/字:文本串">
+ <text:p>
+ <xsl:for-each select="key('pz',$w)/图:文本内容/字:句">
+ <text:span>
+ <xsl:if test="字:句属性/@字:式样引用">
+ <xsl:attribute name="text:style-name"><xsl:value-of select="字:句属性/@字:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:value-of select="字:文本串"/>
+ </text:span>
+ </xsl:for-each>
+ </text:p>
+ </xsl:when>
+ </xsl:choose>
+ <!--xsl:if test="图:文本内容/字:段落/字:句/字:文本串">
+ <text:p>
+ <xsl:call-template name="create-comment-data-content">
+ <xsl:with-param name="style-id" select="../@表:式样引用"/>
+ </xsl:call-template>
+ </text:p>
+ </xsl:if-->
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="auto-filter-condition">
+ <xsl:param name="condition-set"/>
+ <xsl:param name="zone-left-column-num"/>
+ <xsl:if test="$condition-set">
+ <xsl:variable name="first-condition" select="$condition-set[1]"/>
+ <xsl:element name="table:filter-condition">
+ <xsl:attribute name="table:field-number"><xsl:value-of select="$first-condition/@表:列号 - $zone-left-column-num"/></xsl:attribute>
+ <xsl:attribute name="office:value"><xsl:choose><xsl:when test="$first-condition/表:普通"><xsl:value-of select="$first-condition/表:普通/@表:值"/></xsl:when><xsl:when test="$first-condition/表:自定义"><xsl:value-of select="$first-condition/表:自定义/表:操作条件/表:值"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:variable name="operator">
+ <xsl:choose>
+ <xsl:when test="$first-condition/表:普通">
+ <xsl:variable name="general" select="$first-condition/表:普通/@表:类型"/>
+ <xsl:choose>
+ <xsl:when test="$general ='topitem'">top values</xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-condition/表:自定义">
+ <xsl:variable name="operator-text" select="$first-condition/表:自定义/表:操作条件/表:操作码/text()"/>
+ <xsl:choose>
+ <xsl:when test="$operator-text ='less than'">&lt;</xsl:when>
+ <xsl:when test="$operator-text ='greater than'">&gt;</xsl:when>
+ <xsl:when test="$operator-text ='equal to'">
+ <xsl:value-of select="'='"/>
+ </xsl:when>
+ <xsl:when test="$operator-text ='greater than or equal to'">
+ <xsl:value-of select="'&gt;='"/>
+ </xsl:when>
+ <xsl:when test="$operator-text ='less than or equal to'">
+ <xsl:value-of select="'&lt;='"/>
+ </xsl:when>
+ <xsl:when test="$operator-text ='not equal to'">
+ <xsl:value-of select="'!='"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="table:operator"><xsl:value-of select="$operator"/></xsl:attribute>
+ </xsl:element>
+ <xsl:call-template name="auto-filter-condition">
+ <xsl:with-param name="condition-set" select="$condition-set[position()!=1]"/>
+ <xsl:with-param name="zone-left-column-num" select="$zone-left-column-num"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="translate-column-char-to-number">
+ <xsl:param name="string"/>
+ <xsl:choose>
+ <xsl:when test="string-length($string)=1">
+ <xsl:call-template name="char-to-number">
+ <xsl:with-param name="char" select="$string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="tens-place">
+ <xsl:call-template name="char-to-number">
+ <xsl:with-param name="char" select="substring($string,1,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="units-place">
+ <xsl:call-template name="char-to-number">
+ <xsl:with-param name="char" select="substring($string,2,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$tens-place * 26 + $units-place"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="char-to-number">
+ <xsl:param name="char"/>
+ <xsl:choose>
+ <xsl:when test="$char='A'">1</xsl:when>
+ <xsl:when test="$char='B'">2</xsl:when>
+ <xsl:when test="$char='C'">3</xsl:when>
+ <xsl:when test="$char='D'">4</xsl:when>
+ <xsl:when test="$char='E'">5</xsl:when>
+ <xsl:when test="$char='F'">6</xsl:when>
+ <xsl:when test="$char='G'">7</xsl:when>
+ <xsl:when test="$char='H'">8</xsl:when>
+ <xsl:when test="$char='I'">9</xsl:when>
+ <xsl:when test="$char='J'">10</xsl:when>
+ <xsl:when test="$char='K'">11</xsl:when>
+ <xsl:when test="$char='L'">12</xsl:when>
+ <xsl:when test="$char='M'">13</xsl:when>
+ <xsl:when test="$char='N'">14</xsl:when>
+ <xsl:when test="$char='O'">15</xsl:when>
+ <xsl:when test="$char='P'">16</xsl:when>
+ <xsl:when test="$char='Q'">17</xsl:when>
+ <xsl:when test="$char='R'">18</xsl:when>
+ <xsl:when test="$char='S'">19</xsl:when>
+ <xsl:when test="$char='T'">20</xsl:when>
+ <xsl:when test="$char='U'">21</xsl:when>
+ <xsl:when test="$char='V'">22</xsl:when>
+ <xsl:when test="$char='W'">23</xsl:when>
+ <xsl:when test="$char='X'">24</xsl:when>
+ <xsl:when test="$char='Y'">25</xsl:when>
+ <xsl:when test="$char='Z'">26</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="translate-expression2">
+ <xsl:param name="expression2"/>
+ <xsl:choose>
+ <xsl:when test="contains($expression2,':')">
+ <xsl:variable name="column-one">
+ <xsl:value-of select="substring(substring-before($expression2,':'),1,1)"/>
+ </xsl:variable>
+ <xsl:variable name="row-one">
+ <xsl:value-of select="substring(substring-before($expression2,':'),2)"/>
+ </xsl:variable>
+ <xsl:variable name="column-two">
+ <xsl:value-of select="substring(substring-after($expression2,':'),1,1)"/>
+ </xsl:variable>
+ <xsl:variable name="row-two">
+ <xsl:value-of select="substring(substring-after($expression2,':'),2)"/>
+ </xsl:variable>
+ <xsl:variable name="column-value1">
+ <xsl:call-template name="character-to-column">
+ <xsl:with-param name="column-value" select="$column-one"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="column-value2">
+ <xsl:call-template name="character-to-column">
+ <xsl:with-param name="column-value" select="$column-two"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('R',$row-one,'C',$column-value1,':','R',$row-two,'C',$column-value2)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="column-one">
+ <xsl:value-of select="substring($expression2,1,1)"/>
+ </xsl:variable>
+ <xsl:variable name="row-one">
+ <xsl:value-of select="substring($expression2,2)"/>
+ </xsl:variable>
+ <xsl:variable name="column-value1">
+ <xsl:call-template name="character-to-column">
+ <xsl:with-param name="column-value" select="$column-one"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat('R',$row-one,'C',$column-value1)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="character-to-column">
+ <xsl:param name="column-value"/>
+ <xsl:choose>
+ <xsl:when test="$column-value= 'A'">1</xsl:when>
+ <xsl:when test="$column-value= 'B'">2</xsl:when>
+ <xsl:when test="$column-value= 'C'">3</xsl:when>
+ <xsl:when test="$column-value= 'D'">4</xsl:when>
+ <xsl:when test="$column-value= 'E'">5</xsl:when>
+ <xsl:when test="$column-value= 'F'">6</xsl:when>
+ <xsl:when test="$column-value= 'G'">7</xsl:when>
+ <xsl:when test="$column-value= 'H'">8</xsl:when>
+ <xsl:when test="$column-value= 'I'">9</xsl:when>
+ <xsl:when test="$column-value= 'J'">10</xsl:when>
+ <xsl:when test="$column-value= 'K'">11</xsl:when>
+ <xsl:when test="$column-value= 'L'">12</xsl:when>
+ <xsl:when test="$column-value= 'M'">13</xsl:when>
+ <xsl:when test="$column-value= 'N'">14</xsl:when>
+ <xsl:when test="$column-value= 'O'">15</xsl:when>
+ <xsl:when test="$column-value= 'P'">16</xsl:when>
+ <xsl:when test="$column-value= 'Q'">17</xsl:when>
+ <xsl:when test="$column-value= 'R'">18</xsl:when>
+ <xsl:when test="$column-value= 'S'">19</xsl:when>
+ <xsl:when test="$column-value= 'T'">20</xsl:when>
+ <xsl:when test="$column-value= 'U'">21</xsl:when>
+ <xsl:when test="$column-value= 'V'">22</xsl:when>
+ <xsl:when test="$column-value= 'W'">23</xsl:when>
+ <xsl:when test="$column-value= 'X'">24</xsl:when>
+ <xsl:when test="$column-value= 'Y'">25</xsl:when>
+ <xsl:when test="$column-value= 'Z'">26</xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <!--chenjh end 20050611-->
+ <xsl:template name="工作表属性">
+ <!--office:settings-->
+ <xsl:variable name="sheetprop" select="/uof:UOF/uof:电子表格/表:主体/表:工作表"/>
+ <config:config-item-set config:name="ooo:view-settings">
+ <xsl:variable name="ratio" select="15"/>
+ <xsl:if test="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:行/表:单元格/表:数据/字:句/字:修订开始">
+ <config:config-item-set config:name="TrackedChangesViewSettings">
+ <config:config-item config:name="ShowChanges" config:type="boolean">true</config:config-item>
+ <config:config-item config:name="ShowAcceptedChanges" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ShowRejectedChanges" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ShowChangesByDatetime" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ShowChangesByDatetimeMode" config:type="short">0</config:config-item>
+ <config:config-item config:name="ShowChangesByDatetimeFirstDatetime" config:type="datetime">2007-01-17T10:56:46.21</config:config-item>
+ <config:config-item config:name="ShowChangesByDatetimeSecondDatetime" config:type="datetime">2007-01-17T10:56:46.21</config:config-item>
+ <config:config-item config:name="ShowChangesByAuthor" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ShowChangesByAuthorName" config:type="string"/>
+ <config:config-item config:name="ShowChangesByComment" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ShowChangesByCommentText" config:type="string"/>
+ <config:config-item config:name="ShowChangesByRanges" config:type="boolean">false</config:config-item>
+ <config:config-item config:name="ShowChangesByRangesList" config:type="string"/>
+ </config:config-item-set>
+ </xsl:if>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <config:config-item config:name="ViewId" config:type="string">View1</config:config-item>
+ <config:config-item-map-named config:name="Tables">
+ <xsl:for-each select="$sheetprop/表:工作表属性/表:视图">
+ <xsl:element name="config:config-item-map-entry">
+ <xsl:attribute name="config:name"><xsl:value-of select="ancestor::表:工作表/@表:名称"/></xsl:attribute>
+ <xsl:element name="config:config-item">
+ <xsl:attribute name="config:name">HorizontalSplitMode</xsl:attribute>
+ <xsl:attribute name="config:type">short</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="表:冻结 and 表:冻结/@表:列号!=0">2</xsl:when>
+ <xsl:when test="表:冻结 and 表:冻结/@表:列号=0">0</xsl:when>
+ <xsl:when test="表:拆分 and 表:拆分/@表:宽度!=0">1</xsl:when>
+ <xsl:when test="表:拆分 and 表:拆分/@表:宽度=0">0</xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="config:config-item">
+ <xsl:attribute name="config:name">VerticalSplitMode</xsl:attribute>
+ <xsl:attribute name="config:type">short</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="表:冻结 and 表:冻结/@表:行号!=0">2</xsl:when>
+ <xsl:when test="表:冻结 and 表:冻结/@表:行号=0">0</xsl:when>
+ <xsl:when test="表:拆分 and 表:拆分/@表:高度!=0">1</xsl:when>
+ <xsl:when test="表:拆分 and 表:拆分/@表:高度=0">0</xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="config:config-item">
+ <xsl:attribute name="config:name">HorizontalSplitPosition</xsl:attribute>
+ <xsl:attribute name="config:type">int</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="表:冻结 and 表:冻结/@表:列号=0">0</xsl:when>
+ <xsl:when test="表:冻结 and 表:冻结/@表:列号!=0">
+ <xsl:value-of select="表:冻结/@表:列号"/>
+ </xsl:when>
+ <xsl:when test="表:拆分 and 表:拆分/@表:宽度=0">0</xsl:when>
+ <xsl:when test="表:拆分 and 表:拆分/@表:宽度!=0">
+ <xsl:value-of select="表:拆分/@表:宽度"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:element name="config:config-item">
+ <xsl:attribute name="config:name">VerticalSplitPosition</xsl:attribute>
+ <xsl:attribute name="config:type">int</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="表:冻结 and 表:冻结/@表:行号=0">0</xsl:when>
+ <xsl:when test="表:冻结 and 表:冻结/@表:行号!=0">
+ <xsl:value-of select="表:冻结/@表:行号"/>
+ </xsl:when>
+ <xsl:when test="表:拆分 and 表:拆分/@表:高度=0">0</xsl:when>
+ <xsl:when test="表:拆分 and 表:拆分/@表:高度!=0">
+ <xsl:value-of select="表:拆分/@表:高度"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:variable name="position-top">
+ <xsl:choose>
+ <xsl:when test="$sheetprop/表:工作表属性/表:视图/表:最上行">
+ <xsl:value-of select="//表:工作表属性/表:视图/表:最上行"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="position-left">
+ <xsl:choose>
+ <xsl:when test="$sheetprop/表:工作表属性/表:视图/表:最左列">
+ <xsl:value-of select="$sheetprop/表:工作表属性/表:视图/表:最左列"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <config:config-item config:name="PositionRight" config:type="int">
+ <xsl:value-of select="$position-left"/>
+ </config:config-item>
+ <config:config-item config:name="PositionBottom" config:type="int">
+ <xsl:value-of select="$position-top"/>
+ </config:config-item>
+ </xsl:element>
+ </xsl:for-each>
+ </config:config-item-map-named>
+ <xsl:if test="$sheetprop/表:工作表属性/表:视图/表:当前视图">
+ <xsl:element name="config:config-item">
+ <xsl:attribute name="config:name">ShowPageBreakPreview</xsl:attribute>
+ <xsl:attribute name="config:type">boolean</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$sheetprop/表:工作表属性/表:视图/表:当前视图/@表:类型='normal'">false</xsl:when>
+ <xsl:otherwise>true</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$sheetprop/表:工作表属性/表:视图/表:网格">
+ <xsl:element name="config:config-item">
+ <xsl:attribute name="config:name">ShowGrid</xsl:attribute>
+ <xsl:attribute name="config:type">boolean</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$sheetprop/表:工作表属性/表:视图/表:网格/@表:值=1 or $sheetprop/表:工作表属性/表:视图/表:网格/@表:值='true'">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$sheetprop/表:工作表属性/表:视图/表:网格颜色">
+ <xsl:element name="config:config-item">
+ <xsl:attribute name="config:name">GridColor</xsl:attribute>
+ <xsl:attribute name="config:type">long</xsl:attribute>
+ <xsl:call-template name="transform-hex-to-decimal">
+ <xsl:with-param name="number" select="//表:视图/表:网格颜色/text()"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$sheetprop/表:工作表属性/表:视图/表:选中">
+ <xsl:element name="config:config-item">
+ <xsl:attribute name="config:name">ActiveTable</xsl:attribute>
+ <xsl:attribute name="config:type">string</xsl:attribute>
+ <xsl:value-of select="$sheetprop/表:工作表属性/表:视图[表:选中]/ancestor::表:工作表/@表:名称"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$sheetprop/表:工作表属性/表:视图/表:缩放">
+ <config:config-item config:name="ZoomValue" config:type="int">
+ <xsl:value-of select="$sheetprop/表:工作表属性/表:视图/表:缩放/text()"/>
+ </config:config-item>
+ </xsl:if>
+ <xsl:if test="$sheetprop/表:工作表属性/表:视图/表:分页缩放">
+ <config:config-item config:name="PageViewZoomValue" config:type="int">
+ <xsl:value-of select="$sheetprop/表:工作表属性/表:视图/表:分页缩放/text()"/>
+ </config:config-item>
+ </xsl:if>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ </xsl:template>
+ <xsl:template name="create-page-master">
+ <xsl:param name="worksheetoptions"/>
+ <xsl:for-each select="$worksheetoptions">
+ <xsl:element name="style:page-layout">
+ <xsl:attribute name="style:name"><xsl:call-template name="encode-as-nc-name"><xsl:with-param name="string" select="concat( 'pm_', ../@表:名称)"/></xsl:call-template></xsl:attribute>
+ <xsl:element name="style:page-layout-properties">
+ <xsl:if test="表:页面设置/表:纸张/@uof:宽度">
+ <xsl:attribute name="fo:page-width"><xsl:value-of select="concat(表:页面设置/表:纸张/@uof:宽度,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:页面设置/表:纸张/@uof:高度">
+ <xsl:attribute name="fo:page-height"><xsl:value-of select="concat(表:页面设置/表:纸张/@uof:高度,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:页面设置/表:纸张方向">
+ <xsl:attribute name="style:print-orientation"><xsl:value-of select="表:页面设置/表:纸张方向"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:页面设置/表:缩放">
+ <xsl:attribute name="style:scale-to"><xsl:value-of select="concat(表:页面设置/表:缩放,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="/uof:UOF/uof:电子表格/表:主体/表:工作表/@表:背景">
+ <xsl:attribute name="fo:background-color"><xsl:value-of select="/uof:UOF/uof:电子表格/表:主体/表:工作表/@表:背景"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style:first-page-number">continue</xsl:attribute>
+ <xsl:if test="表:页面设置/表:页边距">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(表:页面设置/表:页边距/@uof:上,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(表:页面设置/表:页边距/@uof:下,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(表:页面设置/表:页边距/@uof:左,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(表:页面设置/表:页边距/@uof:右,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:页面设置/表:打印/@表:先列后行='true'">
+ <xsl:attribute name="style:print-page-order">ltr</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:页面设置/表:垂直对齐/@表:对齐方式">
+ <xsl:attribute name="style:table-centering">vertical</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:页面设置/表:水平对齐/@表:对齐方式">
+ <xsl:attribute name="style:table-centering">horizontal</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="style:header-style">
+ <xsl:element name="style:header-footer-properties">
+ <xsl:attribute name="fo:min-height">0.75cm</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="表:页面设置/表:页眉页脚/@uof:边距">
+ <xsl:attribute name="fo:margin-bottom"><xsl:call-template name="convert2cm"><xsl:with-param name="value" select="concat(表:页面设置/表:页眉页脚/@uof:边距,'pt')"/></xsl:call-template><xsl:text>cm</xsl:text></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-bottom">0.25cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="style:footer-style">
+ <xsl:element name="style:header-footer-properties">
+ <xsl:attribute name="fo:min-height">0.75cm</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="表:页面设置/表:页眉页脚/@uof:边距">
+ <xsl:attribute name="fo:margin-top"><xsl:call-template name="convert2cm"><xsl:with-param name="value" select="concat(表:页面设置/表:页眉页脚/@uof:边距,'pt')"/></xsl:call-template><xsl:text>cm</xsl:text></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-top">0.25cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template match="字:文本串">
+ <xsl:value-of select="text()"/>
+ </xsl:template>
+ <xsl:template match="字:换行符">
+ <xsl:element name="text:line-break"/>
+ </xsl:template>
+ <xsl:template match="字:制表符">
+ <xsl:element name="text:tab-stop"/>
+ </xsl:template>
+ <xsl:template match="字:区域开始">
+ <xsl:if test="@字:类型='hyperlink'">
+ <xsl:variable name="superlink" select="//uof:超级链接[@uof:标识符=current()/@字:标识符]"/>
+ <xsl:element name="text:a">
+ <xsl:attribute name="xlink:href"><xsl:value-of select="$superlink/@uof:目标"/></xsl:attribute>
+ <xsl:value-of select="$superlink/@uof:提示"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:空格符">
+ <xsl:element name="text:s">
+ <xsl:if test="@字:个数">
+ <xsl:attribute name="text:c"><xsl:value-of select="@字:个数"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="create-page-header-footer-text-p">
+ <xsl:param name="paragragh-set"/>
+ <xsl:choose>
+ <xsl:when test="$paragragh-set">
+ <xsl:element name="text:p">
+ <xsl:for-each select="$paragragh-set[1]/字:句">
+ <xsl:choose>
+ <xsl:when test="not(字:句属性)">
+ <xsl:apply-templates select="字:文本串 | 字:空格符 | 字:换行符"/>
+ </xsl:when>
+ <xsl:when test="字:句属性">
+ <xsl:element name="text:span">
+ <xsl:attribute name="text:style-name"><xsl:value-of select="//uof:句式样[@字:标识符=current()/字:句属性/@字:式样引用]/@字:名称"/></xsl:attribute>
+ <xsl:apply-templates select="字:空格符 | 字:文本串 | 字:换行符 | 字:制表符"/>
+ </xsl:element>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:element>
+ <xsl:call-template name="create-page-header-footer-text-p">
+ <xsl:with-param name="paragragh-set" select="$paragragh-set[position()!=1]"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <!--Redoffice comment lilliang SC0016 06.02.16 -->
+ <!--新增内容-->
+ <xsl:template match="字:段落">
+ <xsl:element name="text:p">
+ <xsl:choose>
+ <xsl:when test="字:段落属性">
+ <xsl:attribute name="text:style-name">P<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落[字:段落属性]"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="generate-id(ancestor::字:主体/descendant::字:段落[1]) = generate-id(.)">
+ <!-- create the leading paragraph style name in one section for master page style application, glu -->
+ <xsl:variable name="paragraph-number">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落[字:段落属性]"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name">P<xsl:value-of select="number($paragraph-number)"/>_1</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="not(字:段落属性) and (descendant::字:分栏符 or ancestor::字:分节/descendant::字:节属性[字:分栏/@字:栏数 &gt; 1])">
+ <xsl:attribute name="text:style-name">ColumnBreakPara</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:句">
+ <xsl:apply-templates select="字:句/字:文本串"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+ <!--Redoffice comment liliang end 06.02.16-->
+ <xsl:template name="create-master-styles">
+ <xsl:param name="worksheetoptions"/>
+ <xsl:for-each select="$worksheetoptions">
+ <xsl:element name="style:master-page">
+ <xsl:attribute name="style:name"><xsl:call-template name="encode-as-nc-name"><xsl:with-param name="string" select="concat( 'TAB_', ../@表:名称)"/></xsl:call-template></xsl:attribute>
+ <!--xsl:attribute name="style:page-layout-name"-->
+ <xsl:attribute name="style:page-layout-name"><xsl:call-template name="encode-as-nc-name"><xsl:with-param name="string" select="concat( 'pm_', ../@表:名称)"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="style:display-name"><xsl:value-of select="concat( 'PageStyle_', ../@表:名称)"/></xsl:attribute>
+ <style:header>
+ <xsl:for-each select="表:页面设置/表:页眉页脚">
+ <xsl:variable name="temp" select="@表:位置"/>
+ <xsl:choose>
+ <xsl:when test="contains($temp,'header')">
+ <xsl:if test="字:段落">
+ <xsl:choose>
+ <xsl:when test="@表:位置='headerleft'">
+ <xsl:element name="style:region-left">
+ <xsl:call-template name="create-page-header-footer-text-p">
+ <xsl:with-param name="paragragh-set" select="字:段落"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@表:位置='headercenter'">
+ <xsl:element name="style:region-center">
+ <xsl:call-template name="create-page-header-footer-text-p">
+ <xsl:with-param name="paragragh-set" select="字:段落"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@表:位置='headerright'">
+ <xsl:element name="style:region-right">
+ <xsl:call-template name="create-page-header-footer-text-p">
+ <xsl:with-param name="paragragh-set" select="字:段落"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </style:header>
+ <style:footer>
+ <xsl:for-each select="表:页面设置/表:页眉页脚">
+ <xsl:variable name="temp" select="@表:位置"/>
+ <xsl:choose>
+ <xsl:when test="contains($temp,'footer')">
+ <xsl:if test="字:段落">
+ <xsl:choose>
+ <xsl:when test="@表:位置='footerleft'">
+ <xsl:element name="style:region-left">
+ <xsl:call-template name="create-page-header-footer-text-p">
+ <xsl:with-param name="paragragh-set" select="字:段落"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@表:位置='footercenter'">
+ <xsl:element name="style:region-center">
+ <xsl:call-template name="create-page-header-footer-text-p">
+ <xsl:with-param name="paragragh-set" select="字:段落"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@表:位置='footerright'">
+ <xsl:element name="style:region-right">
+ <xsl:call-template name="create-page-header-footer-text-p">
+ <xsl:with-param name="paragragh-set" select="字:段落"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </style:footer>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <!--xsl:template name="create-page-master">
+ </xsl:template>
+ <xsl:template match="表:页面设置">
+ </xsl:template>
+
+ <xsl:template name="create-master-styles">
+ </xsl:template>
+ <xsl:template name="表:工作表属性">
+ </xsl:template-->
+ <!--00000000000-->
+ <xsl:template match="uof:元数据">
+ <office:meta>
+ <xsl:if test="uof:创建应用程序">
+ <meta:generator>
+ <xsl:value-of select="uof:创建应用程序"/>
+ </meta:generator>
+ </xsl:if>
+ <xsl:if test="uof:标题">
+ <dc:title>
+ <xsl:value-of select="uof:标题"/>
+ </dc:title>
+ </xsl:if>
+ <xsl:if test="uof:摘要">
+ <dc:description>
+ <xsl:value-of select="uof:摘要"/>
+ </dc:description>
+ </xsl:if>
+ <xsl:if test="uof:主题">
+ <dc:subject>
+ <xsl:value-of select="uof:主题"/>
+ </dc:subject>
+ </xsl:if>
+ <xsl:if test="uof:作者">
+ <meta:initial-creator>
+ <xsl:value-of select="uof:作者"/>
+ </meta:initial-creator>
+ </xsl:if>
+ <xsl:if test="uof:创建日期">
+ <meta:creation-date>
+ <xsl:value-of select="uof:创建日期"/>
+ </meta:creation-date>
+ </xsl:if>
+ <xsl:if test="uof:最后作者">
+ <dc:creator>
+ <xsl:value-of select="uof:最后作者"/>
+ </dc:creator>
+ </xsl:if>
+ <xsl:if test="uof:编辑时间">
+ <meta:editing-duration>
+ <xsl:value-of select="uof:编辑时间"/>
+ </meta:editing-duration>
+ </xsl:if>
+ <dc:language/>
+ <meta:keyword>
+ <xsl:value-of select="uof:关键字集/uof:关键字"/>
+ </meta:keyword>
+ <xsl:if test="uof:编辑次数">
+ <meta:editing-cycles>
+ <xsl:value-of select="uof:编辑次数"/>
+ </meta:editing-cycles>
+ </xsl:if>
+ <xsl:if test="uof:分类">
+ <meta:user-defined meta:name="Category">
+ <xsl:value-of select="uof:分类"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="uof:经理名称">
+ <meta:user-defined meta:name="Manager">
+ <xsl:value-of select="uof:经理名称"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="uof:公司名称">
+ <meta:user-defined meta:name="Company">
+ <xsl:value-of select="uof:公司名称"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:apply-templates select="uof:用户自定义元数据集"/>
+ </office:meta>
+ </xsl:template>
+ <xsl:template match="uof:用户自定义元数据集">
+ <xsl:for-each select="uof:用户自定义元数据">
+ <meta:user-defined meta:name="{@uof:名称}">
+ <xsl:value-of select="."/>
+ </meta:user-defined>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="parse-range">
+ <xsl:param name="range-value"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="first-pit">
+ <xsl:choose>
+ <xsl:when test="contains($range-value,',')">
+ <xsl:value-of select="substring-before($range-value,',')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$range-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="current">
+ <xsl:choose>
+ <xsl:when test="contains($first-pit,':')">
+ <xsl:variable name="R-start" select="substring-before(substring-after($first-pit,'R'),'C')"/>
+ <xsl:variable name="C-start" select="substring-before(substring-after($first-pit,'C'),':')"/>
+ <xsl:variable name="second-pit" select="substring-after($first-pit,':')"/>
+ <xsl:variable name="R-end" select="substring-before(substring-after($second-pit,'R'),'C')"/>
+ <xsl:variable name="C-end" select="substring-after($second-pit,'C')"/>
+ <xsl:variable name="the-str">
+ <xsl:call-template name="condition-rc-str">
+ <xsl:with-param name="r-start" select="$R-start"/>
+ <xsl:with-param name="r-end" select="$R-end"/>
+ <xsl:with-param name="c-start" select="$C-start"/>
+ <xsl:with-param name="c-end" select="$C-end"/>
+ <xsl:with-param name="last" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$the-str"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($first-pit,',')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($range-value,',')">
+ <xsl:call-template name="parse-range">
+ <xsl:with-param name="range-value" select="substring-after($range-value,',')"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="condition-rc-str">
+ <!-- dealing the range of row\column -->
+ <xsl:param name="r-start"/>
+ <xsl:param name="r-end"/>
+ <xsl:param name="c-start"/>
+ <xsl:param name="c-end"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="current">
+ <xsl:call-template name="condition-c-str">
+ <xsl:with-param name="rc-str" select="concat('R',$r-start)"/>
+ <xsl:with-param name="start" select="$c-start"/>
+ <xsl:with-param name="end" select="$c-end"/>
+ <xsl:with-param name="last" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$r-start &lt; $r-end">
+ <xsl:call-template name="condition-rc-str">
+ <xsl:with-param name="r-start" select="$r-start + 1"/>
+ <xsl:with-param name="r-end" select="$r-end"/>
+ <xsl:with-param name="c-start" select="$c-start"/>
+ <xsl:with-param name="c-end" select="$c-end"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$r-start = $r-end">
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="condition-c-str">
+ <!-- return value for the template condition-rc-str -->
+ <xsl:param name="rc-str"/>
+ <xsl:param name="start"/>
+ <xsl:param name="end"/>
+ <xsl:param name="last"/>
+ <xsl:variable name="current" select="concat($rc-str,'C',$start,',')"/>
+ <xsl:if test="$start &lt; $end">
+ <xsl:call-template name="condition-c-str">
+ <xsl:with-param name="rc-str" select="$rc-str"/>
+ <xsl:with-param name="start" select="$start + 1"/>
+ <xsl:with-param name="end" select="$end"/>
+ <xsl:with-param name="last" select="concat($last,$current)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$start = $end">
+ <xsl:value-of select="concat($last,$current)"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="condition-str">
+ <xsl:param name="param-str"/>
+ <xsl:choose>
+ <xsl:when test="contains($param-str,'(')">
+ <xsl:call-template name="condition-str">
+ <xsl:with-param name="param-str" select="substring-after($param-str,'(')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($param-str,':')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="encode-as-cell-range-address">
+ <xsl:param name="string"/>
+ <xsl:value-of select="$string"/>
+ </xsl:template>
+ <xsl:template name="encode-as-cell-address">
+ <xsl:param name="string"/>
+ <xsl:value-of select="$string"/>
+ </xsl:template>
+ <!--chengxiuzhi 111111111111111111111111111111111111111111111111111111111111111-->
+ <!-- measure_conversion.xsl Begin-->
+ <xsl:param name="dpi" select="111"/>
+ <xsl:param name="centimeter-in-mm" select="10"/>
+ <xsl:param name="inch-in-mm" select="25.4"/>
+ <xsl:param name="didot-point-in-mm" select="0.376065"/>
+ <xsl:param name="pica-in-mm" select="4.2333333"/>
+ <xsl:param name="point-in-mm" select="0.3527778"/>
+ <xsl:param name="twip-in-mm" select="0.017636684"/>
+ <xsl:param name="pixel-in-mm" select="$inch-in-mm div $dpi"/>
+ <!-- ***** MEASUREMENT CONVERSIONS *****
+ PARAM 'value'
+ The measure to be converted.
+ The current measure is judged by a substring (e.g. 'mm', 'cm', 'in', 'pica'...)
+ directly added to the number.
+
+ PARAM 'rounding-factor'
+ Is used for the rounding of decimal places.
+ The parameter number is the product of 1 and some '10', where
+ every zero represents a decimal place.
+
+ For example, providing as parameter:
+ <xsl:param name="rounding-factor" select="10000" />
+ Gives by default four decimal places.
+
+ To round two decimal places, basically the following is done:
+ <xsl:value-of select="round(100 * value) div 100"/>
+
+ RETURN The converted number, by default rounded to four decimal places.
+ In case the input measure could not be matched the same value is
+ returned and a warning message is written out.
+
+
+
+ MEASURE LIST:
+ * 1 millimeter (mm), the basic measure
+
+ * 1 centimeter (cm) = 10 mm
+
+ * 1 inch (in) = 25.4 mm
+ While the English have already seen the light (read: the metric system), the US
+ remains loyal to this medieval system.
+
+ * 1 point (pt) = 0.35277777.. mm
+ Sometimes called PostScript point (ppt), as when Adobe created PostScript, they added their own system of points.
+ There are exactly 72 PostScript points in 1 inch.
+
+ * 1 twip = twentieth of a (PostScript) point
+ A twip (twentieth of a point) is a 1/20th of a PostScript point, a traditional measure in printing.
+
+ * 1 didot point (dpt) = 0.376065 mm
+ Didot point after the French typographer Firmin Didot (1764-1836).
+
+ More details under
+ http://www.unc.edu/~rowlett/units/dictP.html:
+ "A unit of length used by typographers and printers. When printing was done
+ from hand-set metal type, one point represented the smallest element of type
+ that could be handled, roughly 1/64 inch. Eventually, the point was standardized
+ in Britain and America as exactly 1/72.27 = 0.013 837 inch, which is
+ about 0.35 mm (351.46 micrometers). In continental Europe, typographers
+ traditionally used a slightly larger point of 0.014 83 inch (about
+ 1/72 pouce, 0.377 mm, or roughly 1/67 English inch), called a Didot point
+ after the French typographer Firmin Didot (1764-1836). In the U.S.,
+ Adobe software defines the point to be exactly 1/72 inch (0.013 888 9 inch
+ or 0.352 777 8 millimeters) and TeX software uses a slightly smaller point
+ of 0.351 459 8035 mm. The German standards agency DIN has proposed that
+ all these units be replaced by multiples of 0.25 millimeters (1/101.6 inch).
+
+ * 1 pica = 4.233333 mm
+ 1/6 inch or 12 points
+
+ * 1 pixel (px) = 0.26458333.. mm (relative to 'DPI', here: 96 dpi)
+ Most pictures have the 96 dpi resolution, but the dpi variable may vary by stylesheet parameter
+
+
+ -->
+ <!-- changing measure to mm -->
+ <xsl:template name="convert2mm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="substring-before($value, 'mm')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm' ) * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in' ) * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'mm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to cm -->
+ <xsl:template name="convert2cm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="substring-before($value, 'cm')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $centimeter-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $centimeter-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $centimeter-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $centimeter-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $centimeter-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $centimeter-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'cm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to inch (cp. section comment) -->
+ <xsl:template name="convert2in">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $inch-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="substring-before($value, 'in')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $inch-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $inch-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $inch-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $inch-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $inch-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'in'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to dpt (cp. section comment) -->
+ <xsl:template name="convert2dpt">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $didot-point-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $didot-point-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $didot-point-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="substring-before($value, 'dpt')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $didot-point-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $didot-point-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $didot-point-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'dpt'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pica (cp. section comment) -->
+ <xsl:template name="convert2pica">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $pica-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $pica-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $pica-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $pica-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="substring-before($value, 'pica')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $pica-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $pica-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'pica'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pt (cp. section comment) -->
+ <xsl:template name="convert2pt">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $point-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $point-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="substring-before($value, 'pt')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $point-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $point-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $point-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $point-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'pt'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pt (cp. section comment) -->
+ <xsl:template name="convert2twip">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'cm') div $twip-in-mm * $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $twip-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $twip-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $twip-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $twip-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="substring-before($value, 'twip')"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $twip-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'twip'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- changing measure to pixel by via parameter provided dpi (dots per inch) standard factor (cp. section comment) -->
+ <xsl:template name="convert2px">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round(number(substring-before($value, 'mm')) div $pixel-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'cm')">
+ <xsl:value-of select="round(number(substring-before($value, 'cm')) div $pixel-in-mm * $centimeter-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round(number(substring-before($value, 'in')) div $pixel-in-mm * $inch-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round(number(substring-before($value, 'pt')) div $pixel-in-mm * $point-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round(number(substring-before($value, 'dpt')) div $pixel-in-mm * $didot-point-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round(number(substring-before($value, 'pica')) div $pixel-in-mm * $pica-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round(number(substring-before($value, 'twip')) div $pixel-in-mm * $twip-in-mm)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'px'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- chenjh zhangying-->
+ <xsl:template name="create-content-validations">
+ <xsl:param name="validation-set"/>
+ <xsl:if test="$validation-set">
+ <xsl:variable name="first-validation" select="$validation-set[1]"/>
+ <xsl:variable name="condition-text">
+ <xsl:choose>
+ <xsl:when test="$first-validation/表:校验类型/text()='whole number'">
+ <xsl:choose>
+ <xsl:when test="$first-validation/表:操作码/text()='between' ">
+ <xsl:value-of select="concat('oooc:cell-content-is-whole-number() and cell-content-is-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not between'">
+ <xsl:value-of select="concat('oooc:cell-content-is-whole-number() and cell-content-is-not-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-whole-number() and cell-content()=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-whole-number() and cell-content()!=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than'">
+ <xsl:value-of select="concat('oooc:cell-content-is-whole-number() and cell-content()&gt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than'">
+ <xsl:value-of select="concat('oooc:cell-content-is-whole-number() and cell-content()&lt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-whole-number() and cell-content()&gt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-whole-number() and cell-content()&lt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:校验类型/text()='decimal'">
+ <xsl:choose>
+ <xsl:when test="$first-validation/表:操作码/text()='between' ">
+ <xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and cell-content-is-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not between'">
+ <xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and cell-content-is-not-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and cell-content()=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and cell-content()!=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than'">
+ <xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and cell-content()&gt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than'">
+ <xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and cell-content()&lt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and cell-content()&gt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-decimal-number() and cell-content()&lt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:校验类型/text()='date'">
+ <xsl:choose>
+ <xsl:when test="$first-validation/表:操作码/text()='between' ">
+ <xsl:value-of select="concat('oooc:cell-content-is-date() and cell-content-is-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not between'">
+ <xsl:value-of select="concat('oooc:cell-content-is-date() and cell-content-is-not-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-date() and cell-content()=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-date() and cell-content()!=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than'">
+ <xsl:value-of select="concat('oooc:cell-content-is-date() and cell-content()&gt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than'">
+ <xsl:value-of select="concat('oooc:cell-content-is-date() and cell-content()&lt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-date() and cell-content()&gt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-date() and cell-content()&lt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:校验类型/text()='time'">
+ <xsl:choose>
+ <xsl:when test="$first-validation/表:操作码/text()='between' ">
+ <xsl:value-of select="concat('oooc:cell-content-is-time() and cell-content-is-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not between'">
+ <xsl:value-of select="concat('oooc:cell-content-is-time() and cell-content-is-not-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-time() and cell-content()=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-time() and cell-content()!=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than'">
+ <xsl:value-of select="concat('oooc:cell-content-is-time() and cell-content()&gt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than'">
+ <xsl:value-of select="concat('oooc:cell-content-is-time() and cell-content()&lt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-time() and cell-content()&gt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-is-time() and cell-content()&lt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <!-- add 20060317 -->
+ <xsl:when test="$first-validation/表:校验类型/text()='cell range'">
+ <xsl:value-of select="concat('oooc:cell-content-is-in-list',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:校验类型/text()='list'">
+ <xsl:value-of select="concat('oooc:cell-content-is-in-list',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <!-- add 20060317 end -->
+ <xsl:when test="$first-validation/表:校验类型/text()='text length'">
+ <xsl:choose>
+ <xsl:when test="$first-validation/表:操作码/text()='between' ">
+ <xsl:value-of select="concat('oooc:cell-content-text-length-is-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not between'">
+ <xsl:value-of select="concat('oooc:cell-content-text-length-is-not-between','(',$first-validation/表:第一操作数/text(),',',$first-validation/表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-text-length()=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='not equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-text-length()!=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than'">
+ <xsl:value-of select="concat('oooc:cell-content-text-length()&gt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than'">
+ <xsl:value-of select="concat('oooc:cell-content-text-length()&lt;',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='greater than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-text-length()&gt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="$first-validation/表:操作码/text()='less than or equal to'">
+ <xsl:value-of select="concat('oooc:cell-content-text-length()&lt;=',$first-validation/表:第一操作数/text())"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="table:content-validation">
+ <xsl:attribute name="table:name"><xsl:value-of select="concat('val',count($first-validation/preceding-sibling::表:数据有效性)+1)"/></xsl:attribute>
+ <xsl:attribute name="table:condition"><xsl:value-of select="$condition-text"/></xsl:attribute>
+ <xsl:attribute name="table:allow-empty-cell"><xsl:value-of select="$first-validation/表:忽略空格/@表:值"/></xsl:attribute>
+ <xsl:attribute name="table:base-cell-address"><xsl:value-of select="translate(substring-after($first-validation/表:区域/text(),':'),'$','')"/></xsl:attribute>
+ <xsl:if test="$first-validation/表:输入提示">
+ <xsl:element name="table:help-message">
+ <xsl:attribute name="table:title"><xsl:value-of select="$first-validation/表:输入提示/@表:标题"/></xsl:attribute>
+ <xsl:attribute name="table:display"><xsl:value-of select="$first-validation/表:输入提示/@表:显示"/></xsl:attribute>
+ <xsl:element name="text:p">
+ <xsl:value-of select="$first-validation/表:输入提示/@表:内容"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$first-validation/表:错误提示">
+ <xsl:element name="table:error-message">
+ <xsl:attribute name="table:title"><xsl:value-of select="$first-validation/表:错误提示/@表:标题"/></xsl:attribute>
+ <xsl:attribute name="table:display"><xsl:value-of select="$first-validation/表:错误提示/@表:显示"/></xsl:attribute>
+ <xsl:attribute name="table:message-type"><xsl:value-of select="$first-validation/表:错误提示/@表:类型"/></xsl:attribute>
+ <xsl:element name="text:p">
+ <xsl:value-of select="$first-validation/表:错误提示/@表:内容"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ <xsl:call-template name="create-content-validations">
+ <xsl:with-param name="validation-set" select="$validation-set[position()!=1]"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <!--RedOffice Comment from Zengjh:UOF0020 2006-04-26 charts-->
+ <xsl:template match="表:图表">
+ <xsl:param name="table-name"/>
+ <xsl:element name="draw:frame">
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="'0'"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@表:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@表:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(@表:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(@表:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:variable name="chart-current">
+ <xsl:number level="any" count="表:图表" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="concat('chart', $chart-current)"/></xsl:attribute>
+ <xsl:variable name="series-value-start">
+ <xsl:for-each select="表:数据源/表:系列[position()='1']">
+ <xsl:value-of select="@表:系列值"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="series-value-end">
+ <xsl:for-each select="表:数据源/表:系列[position()=last()]">
+ <xsl:value-of select="@表:系列值"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="series-generate-type">
+ <xsl:choose>
+ <xsl:when test="表:数据源/@表序号产生">
+ <xsl:value-of select="表:数据源/@表序号产生"/>
+ </xsl:when>
+ <xsl:when test="substring(substring-after($series-value-start,'!'),2,1)=substring(substring-after($series-value-start,':'),2,1)">row</xsl:when>
+ <xsl:otherwise>col</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="draw:object">
+ <xsl:attribute name="draw:notify-on-update-of-ranges"><xsl:value-of select="表:数据源/@表:数据区域"/></xsl:attribute>
+ <office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" office:version="1.0" office:mimetype="application/vnd.oasis.opendocument.chart">
+ <xsl:call-template name="表:元数据">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="@表:类型"/>
+ <xsl:with-param name="table-subtype" select="@表:子类型"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ <xsl:call-template name="表:式样集">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="@表:类型"/>
+ <xsl:with-param name="table-subtype" select="@表:子类型"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ <xsl:call-template name="表:主体">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="@表:类型"/>
+ <xsl:with-param name="table-subtype" select="@表:子类型"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </office:document>
+ </xsl:element>
+ <xsl:element name="draw:image">
+ <office:binary-data>
+ <xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象/uof:数据"/>
+ </office:binary-data>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="表:元数据">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:for-each select="/uof:UOF/uof:元数据">
+ <office:meta>
+ <meta:generator>OpenOffice.org 1.1.3 (Win32)</meta:generator>
+ <xsl:if test="uof:标题">
+ <dc:title>
+ <xsl:value-of select="uof:标题"/>
+ </dc:title>
+ </xsl:if>
+ <xsl:if test="uof:摘要">
+ <dc:description>
+ <xsl:value-of select="uof:摘要"/>
+ </dc:description>
+ </xsl:if>
+ <xsl:if test="uof:主题">
+ <dc:subject>
+ <xsl:value-of select="uof:主题"/>
+ </dc:subject>
+ </xsl:if>
+ <xsl:if test="uof:作者">
+ <meta:initial-creator>
+ <xsl:value-of select="uof:作者"/>
+ </meta:initial-creator>
+ </xsl:if>
+ <xsl:if test="uof:创建日期">
+ <meta:creation-date>
+ <xsl:value-of select="uof:创建日期"/>
+ </meta:creation-date>
+ </xsl:if>
+ <xsl:if test="uof:最后作者">
+ <dc:creator>
+ <xsl:value-of select="uof:最后作者"/>
+ </dc:creator>
+ </xsl:if>
+ <xsl:if test="uof:编辑时间">
+ <meta:editing-duration>
+ <xsl:value-of select="uof:编辑时间"/>
+ </meta:editing-duration>
+ </xsl:if>
+ <dc:language/>
+ <meta:keywords>
+ <meta:keyword>
+ <xsl:value-of select="uof:关键字集/uof:关键字"/>
+ </meta:keyword>
+ </meta:keywords>
+ <xsl:if test="uof:编辑次数">
+ <meta:editing-cycles>
+ <xsl:value-of select="uof:编辑次数"/>
+ </meta:editing-cycles>
+ </xsl:if>
+ <xsl:if test="uof:分类">
+ <meta:user-defined meta:name="Category">
+ <xsl:value-of select="uof:分类"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="uof:经理名称">
+ <meta:user-defined meta:name="Manager">
+ <xsl:value-of select="uof:经理名称"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="uof:公司名称">
+ <meta:user-defined meta:name="Company">
+ <xsl:value-of select="uof:公司名称"/>
+ </meta:user-defined>
+ </xsl:if>
+ <xsl:if test="uof:创建应用程序">
+ <meta:user-defined meta:name="Version">
+ <xsl:value-of select="uof:创建应用程序"/>
+ </meta:user-defined>
+ </xsl:if>
+ </office:meta>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:式样集">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <office:styles>
+ <draw:stroke-dash draw:name="Ultrafine_20_Dashed" draw:display-name="Ultrafine Dashed" draw:style="rect" draw:dots1="1" draw:dots1-length="0.051cm" draw:dots2="1" draw:dots2-length="0.051cm" draw:distance="0.051cm"/>
+ <draw:stroke-dash draw:name="Fine_20_Dashed" draw:display-name="Fine Dashed" draw:style="rect" draw:dots1="1" draw:dots1-length="0.508cm" draw:dots2="1" draw:dots2-length="0.508cm" draw:distance="0.508cm"/>
+ <draw:stroke-dash draw:name="Ultrafine_20_2_20_Dots_20_3_20_Dashes" draw:display-name="Ultrafine 2 Dots 3 Dashes" draw:style="rect" draw:dots1="2" draw:dots1-length="0.051cm" draw:dots2="3" draw:dots2-length="0.254cm" draw:distance="0.127cm"/>
+ <draw:stroke-dash draw:name="Fine_20_Dashed_20__28_var_29_" draw:display-name="Fine Dashed (var)" draw:style="rect" draw:dots1="1" draw:dots1-length="197%" draw:distance="197%"/>
+ <draw:stroke-dash draw:name="Fine_20_Dotted" draw:display-name="Fine Dotted" draw:style="rect" draw:dots1="1" draw:distance="0.457cm"/>
+ <draw:stroke-dash draw:name="Fine_20_Dashed_20__28_var_29_" draw:display-name="Fine Dashed (var)" draw:style="rect" draw:dots1="1" draw:dots1-length="197%" draw:distance="197%"/>
+ <draw:stroke-dash draw:name="Fine_20_Dotted" draw:display-name="Fine Dotted" draw:style="rect" draw:dots1="1" draw:distance="0.457cm"/>
+ <draw:stroke-dash draw:name="Line_20_with_20_Fine_20_Dots" draw:display-name="Line with Fine Dots" draw:style="rect" draw:dots1="1" draw:dots1-length="2.007cm" draw:dots2="10" draw:distance="0.152cm"/>
+ <draw:stroke-dash draw:name="Line_20_Style_20_9" draw:display-name="Line Style 9" draw:style="rect" draw:dots1="1" draw:dots1-length="197%" draw:distance="120%"/>
+ <draw:stroke-dash draw:name="_33__20_Dashes_20_3_20_Dots_20__28_var_29_" draw:display-name="3 Dashes 3 Dots (var)" draw:style="rect" draw:dots1="3" draw:dots1-length="197%" draw:dots2="3" draw:distance="100%"/>
+ <draw:stroke-dash draw:name="_32__20_Dots_20_1_20_Dash" draw:display-name="2 Dots 1 Dash" draw:style="rect" draw:dots1="2" draw:dots2="1" draw:dots2-length="0.203cm" draw:distance="0.203cm"/>
+ <draw:stroke-dash draw:name="Ultrafine_20_Dotted_20__28_var_29_" draw:display-name="Ultrafine Dotted (var)" draw:style="rect" draw:dots1="1" draw:distance="50%"/>
+ <draw:stroke-dash draw:name="Dash_20_10" draw:display-name="Dash 10" draw:style="rect" draw:dots1="1" draw:dots1-length="0.02cm" draw:dots2="1" draw:dots2-length="0.02cm" draw:distance="0.02cm"/>
+ <xsl:for-each select="//图:图片">
+ <xsl:variable name="chart-image-name" select="@图:名称"/>
+ <draw:fill-image>
+ <xsl:attribute name="draw:name"><xsl:value-of select="@图:名称"/></xsl:attribute>
+ <office:binary-data>
+ <xsl:for-each select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$chart-image-name]">
+ <xsl:value-of select="uof:数据"/>
+ </xsl:for-each>
+ </office:binary-data>
+ </draw:fill-image>
+ </xsl:for-each>
+ <xsl:for-each select="//图:图案">
+ <xsl:variable name="chart-hatch-name" select="@图:图形引用"/>
+ <draw:hatch>
+ <xsl:if test="@图:图形引用">
+ <xsl:attribute name="draw:name"><xsl:value-of select="$chart-hatch-name"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:类型">
+ <xsl:attribute name="draw:style"><xsl:value-of select="@图:类型"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:前景色">
+ <xsl:attribute name="draw:color"><xsl:value-of select="@图:前景色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:距离">
+ <xsl:attribute name="draw:distance"><xsl:value-of select="@图:距离"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:旋转度">
+ <xsl:attribute name="draw:rotation"><xsl:value-of select="@图:旋转度"/></xsl:attribute>
+ </xsl:if>
+ </draw:hatch>
+ </xsl:for-each>
+ <xsl:for-each select="//图:渐变">
+ <draw:gradient>
+ <xsl:if test="@图:图形引用">
+ <xsl:attribute name="draw:name"><xsl:value-of select="@图:图形引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:起始色">
+ <xsl:attribute name="draw:start-color"><xsl:value-of select="@图:起始色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:终止色">
+ <xsl:attribute name="draw:end-color"><xsl:value-of select="@图:终止色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:种子类型">
+ <xsl:attribute name="draw:style"><xsl:value-of select="@图:种子类型"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:起始浓度">
+ <xsl:attribute name="draw:start-intensity"><xsl:value-of select="@图:起始浓度"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:终止浓度">
+ <xsl:attribute name="draw:end-intensity"><xsl:value-of select="@图:终止浓度"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:渐变方向">
+ <xsl:attribute name="draw:angle"><xsl:value-of select="@图:渐变方向"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:边界">
+ <xsl:attribute name="draw:border"><xsl:value-of select="@图:边界"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:种子X位置">
+ <xsl:attribute name="draw:cx"><xsl:value-of select="@图:种子X位置"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@图:种子Y位置">
+ <xsl:attribute name="draw:cy"><xsl:value-of select="@图:种子Y位置"/></xsl:attribute>
+ </xsl:if>
+ </draw:gradient>
+ </xsl:for-each>
+ </office:styles>
+ <office:automatic-styles>
+ <xsl:for-each select="node( )">
+ <xsl:choose>
+ <xsl:when test="name(.)='表:图表区'">
+ <xsl:call-template name="表:图表区式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:绘图区'">
+ <xsl:call-template name="表:绘图区式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ <xsl:call-template name="表:图表背景墙式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:分类轴'">
+ <xsl:call-template name="表:分类轴式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:数值轴'">
+ <xsl:call-template name="表:数值轴式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:图例'">
+ <xsl:call-template name="表:图例式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:数据表'">
+ <xsl:call-template name="表:数据表式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:数据系列集'">
+ <xsl:call-template name="表:数据系列集式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:数据点集'">
+ <xsl:call-template name="表:数据点集式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:网格线集'">
+ <xsl:call-template name="表:网格线集式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:数据源'">
+ <xsl:call-template name="表:数据源式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name(.)='表:标题集'">
+ <xsl:call-template name="表:标题集式样">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </office:automatic-styles>
+ </xsl:template>
+ <xsl:template name="表:主体">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <office:body>
+ <office:chart>
+ <chart:chart>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(@表:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(@表:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="chart:class"><xsl:choose><xsl:when test="$table-type='column'">chart:bar</xsl:when><xsl:when test="$table-type='line'">chart:line</xsl:when><xsl:when test="$table-type='pie'"><xsl:choose><xsl:when test="$table-subtype='pie_ring'">chart:ring</xsl:when><xsl:otherwise>chart:circle</xsl:otherwise></xsl:choose></xsl:when><xsl:otherwise><xsl:value-of select="$table-type"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="chart:style-name">chart-area</xsl:attribute>
+ <xsl:for-each select="表:标题集/表:标题[@表:位置='chart']">
+ <chart:title chart:style-name="chart-title">
+ <text:p>
+ <xsl:value-of select="@表:名称"/>
+ </text:p>
+ </chart:title>
+ </xsl:for-each>
+ <xsl:call-template name="表:图例区域">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ <xsl:call-template name="表:绘图区域">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ <xsl:call-template name="表:本地表">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </chart:chart>
+ </office:chart>
+ </office:body>
+ </xsl:template>
+ <xsl:template name="表:图例区域">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <chart:legend>
+ <xsl:attribute name="chart:legend-position"><xsl:choose><xsl:when test="表:图例/@表:位置"><xsl:value-of select="表:图例/@表:位置"/></xsl:when><xsl:otherwise>right</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(表:图例/@表:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(表:图例/@表:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="chart:style-name">legend</xsl:attribute>
+ </chart:legend>
+ </xsl:template>
+ <xsl:template name="表:绘图区域">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <chart:plot-area>
+ <xsl:variable name="start-range">
+ <xsl:value-of select="concat('.$',substring(substring-after($series-value-start,'!'),1,1),'$',substring-before(substring(substring-after($series-value-start,'!'),2),':'))"/>
+ </xsl:variable>
+ <xsl:variable name="end-range">
+ <xsl:value-of select="concat(':.$',substring(substring-after($series-value-end,':'),1,1),'$',substring(substring-after($series-value-end,':'),2))"/>
+ </xsl:variable>
+ <xsl:attribute name="chart:style-name">plot-area</xsl:attribute>
+ <xsl:attribute name="table:cell-range-address"><xsl:value-of select="concat($table-name,$start-range,$end-range)"/></xsl:attribute>
+ <!--xsl:value-of select="表:数据源/@表:数据区域"/-->
+ <xsl:attribute name="chart:table-number-list">0</xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(表:绘图区/@表:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(表:绘图区/@表:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(表:绘图区/@表:x坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(表:绘图区/@表:y坐标,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="表:分类轴">
+ <chart:axis chart:dimension="x" chart:name="primary-x" chart:style-name="category-axis">
+ <xsl:for-each select="表:标题集/表:标题[@表:位置='category axis']">
+ <chart:title chart:style-name="category-axis-title">
+ <text:p>
+ <xsl:value-of select="@表:名称"/>
+ </text:p>
+ </chart:title>
+ </xsl:for-each>
+ <chart:categories/>
+ <xsl:if test="表:网格线集/表:网格线[@表:位置='category axis']">
+ <chart:grid chart:style-name="category-axis-grid" chart:class="major"/>
+ </xsl:if>
+ </chart:axis>
+ </xsl:if>
+ <xsl:if test="表:数值轴">
+ <chart:axis chart:dimension="y" chart:name="primary-y" chart:style-name="value-axis">
+ <xsl:for-each select="表:标题集/表:标题[@表:位置='value axis']">
+ <chart:title chart:style-name="value-axis-title">
+ <text:p>
+ <xsl:value-of select="@表:名称"/>
+ </text:p>
+ </chart:title>
+ </xsl:for-each>
+ <chart:grid chart:style-name="value-axis-grid" chart:class="major"/>
+ </chart:axis>
+ </xsl:if>
+ <xsl:call-template name="表:数据组">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ <chart:wall>
+ <xsl:attribute name="chart:style-name">chart-wall</xsl:attribute>
+ </chart:wall>
+ <chart:floor>
+ <xsl:attribute name="chart:style-name">chart-floor</xsl:attribute>
+ </chart:floor>
+ </chart:plot-area>
+ </xsl:template>
+ <xsl:template name="表:本地表">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <table:table table:name="local-table">
+ <table:table-header-columns>
+ <xsl:call-template name="表:本地表_表头列">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="sum" select="1"/>
+ </xsl:call-template>
+ </table:table-header-columns>
+ <table:table-columns>
+ <xsl:variable name="column-sum">
+ <xsl:value-of select="count(表:数据源/表:系列)"/>
+ </xsl:variable>
+ <xsl:call-template name="表:本地表_列">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="column-sum" select="$column-sum"/>
+ </xsl:call-template>
+ </table:table-columns>
+ <table:table-header-rows>
+ <xsl:call-template name="表:本地表_表头行">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="row-current" select="1"/>
+ <xsl:with-param name="fixed-row-sum" select="'1'"/>
+ </xsl:call-template>
+ </table:table-header-rows>
+ <table:table-rows>
+ <xsl:variable name="row-start">
+ <xsl:value-of select="substring-before(substring(substring-after($series-value-start,'!'),2),':')"/>
+ </xsl:variable>
+ <xsl:variable name="row-end">
+ <xsl:value-of select="substring(substring-after($series-value-end,':'),2)"/>
+ </xsl:variable>
+ <xsl:variable name="fixed-row-sum">
+ <xsl:value-of select="$row-end -$row-start +1"/>
+ </xsl:variable>
+ <xsl:call-template name="表:本地表_行">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="row-current" select="'1'"/>
+ <xsl:with-param name="fixed-row-sum" select="$fixed-row-sum"/>
+ </xsl:call-template>
+ </table:table-rows>
+ </table:table>
+ </xsl:template>
+ <xsl:template name="表:本地表_表头列">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="sum"/>
+ <xsl:choose>
+ <xsl:when test="$sum=0"/>
+ <xsl:otherwise>
+ <table:table-column/>
+ <xsl:call-template name="表:本地表_表头列">
+ <xsl:with-param name="sum" select="$sum -1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:本地表_列">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="column-sum"/>
+ <xsl:choose>
+ <xsl:when test="$column-sum=0"/>
+ <xsl:otherwise>
+ <table:table-column/>
+ <xsl:call-template name="表:本地表_列">
+ <xsl:with-param name="column-sum" select="$column-sum -1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:本地表_表头行">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="row-current"/>
+ <xsl:param name="fixed-row-sum"/>
+ <xsl:choose>
+ <xsl:when test="$row-current >$fixed-row-sum"/>
+ <xsl:otherwise>
+ <table:table-row>
+ <xsl:variable name="series-value-current">
+ <xsl:for-each select="表:数据源/表:系列[position()=$row-current]">
+ <xsl:value-of select="@表:系列值"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="cell-start">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($series-value-start,'!'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cell-end">
+ <xsl:choose>
+ <xsl:when test="$series-generate-type='row'">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($series-value-start,':'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($series-value-end,'!'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="cell-sum">
+ <xsl:value-of select="$cell-end -$cell-start +2"/>
+ </xsl:variable>
+ <xsl:variable name="fixed-cell-sum" select="$cell-sum"/>
+ <xsl:call-template name="表:本地表_表头行_单元格">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="series-value-current" select="$series-value-current"/>
+ <xsl:with-param name="row-current" select="$row-current"/>
+ <xsl:with-param name="cell-sum" select="$cell-sum"/>
+ <xsl:with-param name="fixed-cell-sum" select="$fixed-cell-sum"/>
+ </xsl:call-template>
+ </table:table-row>
+ <xsl:call-template name="表:本地表_表头行">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="row-current" select="$row-current +1"/>
+ <xsl:with-param name="fixed-row-sum" select="$fixed-row-sum"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:本地表_表头行_单元格">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="series-value-current"/>
+ <xsl:param name="row-current"/>
+ <xsl:param name="cell-sum"/>
+ <xsl:param name="fixed-cell-sum"/>
+ <xsl:choose>
+ <xsl:when test="$cell-sum=0"/>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$fixed-cell-sum=$cell-sum">
+ <table:table-cell>
+ <text:p/>
+ </table:table-cell>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell office:value-type="string">
+ <xsl:variable name="cell-no">
+ <xsl:value-of select="$fixed-cell-sum -$cell-sum +1"/>
+ </xsl:variable>
+ <xsl:variable name="cell-start">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($series-value-start,'!'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="char">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="$cell-start +$cell-no -2"/>
+ <xsl:with-param name="output-type" select="'CHARS_UPPER_LETTER'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <text:p>
+ <xsl:value-of select="concat('列 ',$char)"/>
+ </text:p>
+ </table:table-cell>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="表:本地表_表头行_单元格">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="series-value-current" select="$series-value-current"/>
+ <xsl:with-param name="row-current" select="$row-current"/>
+ <xsl:with-param name="cell-sum" select="$cell-sum -1"/>
+ <xsl:with-param name="fixed-cell-sum" select="$fixed-cell-sum"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:本地表_行">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="row-current"/>
+ <xsl:param name="fixed-row-sum"/>
+ <xsl:choose>
+ <xsl:when test="$row-current >$fixed-row-sum"/>
+ <xsl:otherwise>
+ <xsl:variable name="series-value-current">
+ <xsl:for-each select="表:数据源/表:系列[position()=$row-current]">
+ <xsl:value-of select="@表:系列值"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <table:table-row>
+ <xsl:variable name="cell-start">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($series-value-start,'!'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cell-end">
+ <xsl:choose>
+ <xsl:when test="$series-generate-type='row'">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($series-value-start,':'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($series-value-end,'!'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="cell-sum">
+ <xsl:value-of select="$cell-end -$cell-start +2"/>
+ </xsl:variable>
+ <xsl:variable name="fixed-cell-sum" select="$cell-sum"/>
+ <xsl:call-template name="表:本地表_行_单元格">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="series-value-current" select="$series-value-current"/>
+ <xsl:with-param name="row-current" select="$row-current"/>
+ <xsl:with-param name="cell-sum" select="$cell-sum"/>
+ <xsl:with-param name="fixed-cell-sum" select="$fixed-cell-sum"/>
+ </xsl:call-template>
+ </table:table-row>
+ <xsl:call-template name="表:本地表_行">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="row-current" select="$row-current +1"/>
+ <xsl:with-param name="fixed-row-sum" select="$fixed-row-sum"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:本地表_行_单元格">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="series-value-current"/>
+ <xsl:param name="row-current"/>
+ <xsl:param name="cell-sum"/>
+ <xsl:param name="fixed-cell-sum"/>
+ <xsl:choose>
+ <xsl:when test="$cell-sum=0"/>
+ <xsl:otherwise>
+ <xsl:variable name="cell-start">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="substring(substring-after($series-value-start,'!'),1,1)"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cell-no">
+ <xsl:value-of select="$cell-start +$fixed-cell-sum -$cell-sum -1"/>
+ </xsl:variable>
+ <xsl:variable name="row-start">
+ <xsl:value-of select="substring(substring-after($series-value-start,'!'),2,1)"/>
+ </xsl:variable>
+ <xsl:variable name="row-no">
+ <xsl:value-of select="$row-start +$row-current -1"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$fixed-cell-sum=$cell-sum">
+ <table:table-cell office:value-type="string">
+ <text:p>
+ <xsl:value-of select="concat('行 ',$row-no)"/>
+ </text:p>
+ </table:table-cell>
+ </xsl:when>
+ <xsl:otherwise>
+ <table:table-cell office:value-type="float">
+ <xsl:variable name="cell-content">
+ <xsl:choose>
+ <xsl:when test="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:行/@表:行号">
+ <xsl:for-each select="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:行[@表:行号=$row-no]">
+ <xsl:for-each select="表:单元格[@表:列号=$cell-no]">
+ <xsl:value-of select="表:数据/字:句/字:文本串"/>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="/uof:UOF/uof:电子表格/表:主体/表:工作表/表:工作表内容/表:行[position()=$row-no]">
+ <xsl:for-each select="表:单元格[position()=$cell-no]">
+ <xsl:value-of select="表:数据/字:句/字:文本串"/>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:value"><xsl:value-of select="$cell-content"/></xsl:attribute>
+ <text:p>
+ <xsl:value-of select="$cell-content"/>
+ </text:p>
+ </table:table-cell>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:call-template name="表:本地表_行_单元格">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="series-value-current" select="$series-value-current"/>
+ <xsl:with-param name="row-current" select="$row-current"/>
+ <xsl:with-param name="cell-sum" select="$cell-sum -1"/>
+ <xsl:with-param name="fixed-cell-sum" select="$fixed-cell-sum"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:数据组">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:variable name="input-char-start">
+ <xsl:choose>
+ <xsl:when test="$series-generate-type='row'">
+ <xsl:value-of select="substring(substring-after($series-value-start,'!'),1,1)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before(substring(substring-after($series-value-start,'!'),2),':')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="input-char-end">
+ <xsl:choose>
+ <xsl:when test="$series-generate-type='row'">
+ <xsl:value-of select="substring(substring-after($series-value-start,':'),1,1)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring(substring-after($series-value-start,':'),2)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="cell-start">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="$input-char-start"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="cell-end">
+ <xsl:call-template name="General-Char-Transition">
+ <xsl:with-param name="input-char" select="$input-char-end"/>
+ <xsl:with-param name="output-type" select="'ARABIC'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="fixed-cell-sum">
+ <xsl:value-of select="$cell-end -$cell-start +1"/>
+ </xsl:variable>
+ <xsl:for-each select="表:数据系列集/表:数据系列">
+ <chart:series>
+ <xsl:attribute name="chart:style-name"><xsl:value-of select="concat('data-series',position())"/></xsl:attribute>
+ <xsl:call-template name="表:数据点">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="data-series-current" select="position()"/>
+ <xsl:with-param name="cell-current" select="'1'"/>
+ <xsl:with-param name="fixed-cell-sum" select="$fixed-cell-sum"/>
+ </xsl:call-template>
+ </chart:series>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:数据点">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="data-series-current"/>
+ <xsl:param name="cell-current"/>
+ <xsl:param name="fixed-cell-sum"/>
+ <xsl:choose>
+ <xsl:when test="$cell-current>$fixed-cell-sum"/>
+ <xsl:otherwise>
+ <chart:data-point>
+ <xsl:attribute name="chart:style-name"><xsl:value-of select="concat('data-point',$data-series-current,$cell-current)"/></xsl:attribute>
+ </chart:data-point>
+ <xsl:call-template name="表:数据点">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="data-series-current" select="$data-series-current"/>
+ <xsl:with-param name="cell-current" select="$cell-current +1"/>
+ <xsl:with-param name="fixed-cell-sum" select="$fixed-cell-sum"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="表:图表区式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <style:style style:name="chart-area" style:family="chart">
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name(.)='表:边框'">
+ <style:graphic-properties>
+ <xsl:call-template name="uof:边框"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:填充'">
+ <style:graphic-properties>
+ <xsl:call-template name="图:填充类型"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:字体'">
+ <style:text-properties>
+ <xsl:call-template name="字:句属性类型"/>
+ </style:text-properties>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </style:style>
+ </xsl:template>
+ <xsl:template name="表:绘图区式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <style:style style:name="plot-area" style:family="chart">
+ <style:chart-properties>
+ <xsl:choose>
+ <xsl:when test="$table-subtype='bar_stacked' or $table-subtype='column_stacked' or $table-subtype='line_stacked'">
+ <xsl:attribute name="chart:stacked">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$table-subtype='bar_percent' or $table-subtype='column_percent' or $table-subtype='line_percent'">
+ <xsl:attribute name="chart:percentage">true</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:attribute name="chart:vertical"><xsl:choose><xsl:when test="$table-type='bar'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="chart:series-source"><xsl:choose><xsl:when test="$series-generate-type='row'">rows</xsl:when><xsl:otherwise>columns</xsl:otherwise></xsl:choose></xsl:attribute>
+ </style:chart-properties>
+ </style:style>
+ </xsl:template>
+ <xsl:template name="表:图表背景墙式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <style:style style:name="chart-wall" style:family="chart">
+ <style:graphic-properties>
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name(.)='表:边框'">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:when>
+ <xsl:when test="name(.)='表:填充'">
+ <xsl:call-template name="图:填充类型"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </style:graphic-properties>
+ </style:style>
+ </xsl:template>
+ <xsl:template name="表:分类轴式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <style:style style:name="category-axis" style:family="chart">
+ <xsl:call-template name="表:坐标轴类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="axis-type" select="'category axis'"/>
+ </xsl:call-template>
+ </style:style>
+ </xsl:template>
+ <xsl:template name="表:数值轴式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <style:style style:name="value-axis" style:family="chart">
+ <xsl:call-template name="表:坐标轴类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="axis-type" select="'value axis'"/>
+ </xsl:call-template>
+ </style:style>
+ </xsl:template>
+ <xsl:template name="表:图例式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <style:style style:name="legend" style:family="chart">
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name(.)='表:边框'">
+ <style:graphic-properties>
+ <xsl:call-template name="uof:边框"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:填充'">
+ <style:graphic-properties>
+ <xsl:call-template name="图:填充类型"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:字体'">
+ <style:text-properties>
+ <xsl:call-template name="字:句属性类型"/>
+ </style:text-properties>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </style:style>
+ </xsl:template>
+ <xsl:template name="表:数据表式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <style:style style:name="data-table" style:family="chart">
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name(.)='表:边框'">
+ <style:graphic-properties>
+ <xsl:call-template name="uof:边框"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:填充'">
+ <style:graphic-properties>
+ <xsl:call-template name="图:填充类型"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:字体'">
+ <style:text-properties>
+ <xsl:call-template name="字:句属性类型"/>
+ </style:text-properties>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </style:style>
+ </xsl:template>
+ <xsl:template name="表:数据系列集式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:for-each select="表:数据系列">
+ <style:style style:family="chart">
+ <xsl:variable name="current-position" select="position()"/>
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('data-series',$current-position)"/></xsl:attribute>
+ <xsl:call-template name="表:数据点类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="recall-type" select="'data-series'"/>
+ </xsl:call-template>
+ </style:style>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:数据点集式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:for-each select="表:数据点">
+ <style:style style:family="chart">
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('data-point',@表:系列,@表:点)"/></xsl:attribute>
+ <xsl:call-template name="表:数据点类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ <xsl:with-param name="recall-type" select="'data-point'"/>
+ </xsl:call-template>
+ </style:style>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:网格线集式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:for-each select="表:网格线">
+ <xsl:choose>
+ <xsl:when test="@表:位置='category axis'">
+ <style:style style:name="category-axis-grid" style:family="chart">
+ <style:graphic-properties>
+ <xsl:call-template name="uof:边框"/>
+ </style:graphic-properties>
+ </style:style>
+ </xsl:when>
+ <xsl:when test="@表:位置='value axis'">
+ <style:style style:name="value-axis-grid" style:family="chart">
+ <style:graphic-properties>
+ <xsl:call-template name="uof:边框"/>
+ </style:graphic-properties>
+ </style:style>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:数据源式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:for-each select="表:系列">
+ <style:style style:family="chart">
+ <xsl:variable name="current-position" select="position()"/>
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('data-source',$current-position)"/></xsl:attribute>
+ </style:style>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:标题集式样">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:for-each select="表:标题">
+ <xsl:choose>
+ <xsl:when test="@表:位置='chart'">
+ <style:style style:name="chart-title" style:family="chart">
+ <xsl:call-template name="表:标题类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </style:style>
+ </xsl:when>
+ <xsl:when test="@表:位置='category axis'">
+ <style:style style:name="category-axis-title" style:family="chart">
+ <xsl:call-template name="表:标题类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </style:style>
+ </xsl:when>
+ <xsl:when test="@表:位置='value axis'">
+ <style:style style:name="value-axis-title" style:family="chart">
+ <xsl:call-template name="表:标题类型">
+ <xsl:with-param name="table-name" select="$table-name"/>
+ <xsl:with-param name="table-type" select="$table-type"/>
+ <xsl:with-param name="table-subtype" select="$table-subtype"/>
+ <xsl:with-param name="series-value-start" select="$series-value-start"/>
+ <xsl:with-param name="series-value-end" select="$series-value-end"/>
+ <xsl:with-param name="series-generate-type" select="$series-generate-type"/>
+ </xsl:call-template>
+ </style:style>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:坐标轴类型">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="axis-type"/>
+ <style:chart-properties>
+ <xsl:choose>
+ <xsl:when test="@表:主刻度类型='cross'">
+ <xsl:attribute name="chart:tick-marks-major-inner">true</xsl:attribute>
+ <xsl:attribute name="chart:tick-marks-major-outer">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:主刻度类型='inside'">
+ <xsl:attribute name="chart:tick-marks-major-inner">true</xsl:attribute>
+ <xsl:attribute name="chart:tick-marks-major-outer">false</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:主刻度类型='outside'">
+ <xsl:attribute name="chart:tick-marks-major-inner">false</xsl:attribute>
+ <xsl:attribute name="chart:tick-marks-major-outer">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@表:次刻度类型='cross'">
+ <xsl:attribute name="chart:tick-marks-minor-inner">true</xsl:attribute>
+ <xsl:attribute name="chart:tick-marks-minor-outer">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:次刻度类型='inside'">
+ <xsl:attribute name="chart:tick-marks-minor-inner">true</xsl:attribute>
+ <xsl:attribute name="chart:tick-marks-minor-outer">false</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@表:次刻度类型='outside'">
+ <xsl:attribute name="chart:tick-marks-minor-inner">false</xsl:attribute>
+ <xsl:attribute name="chart:tick-marks-minor-outer">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:if test="@表:刻度线标志='next to axis'">
+ <xsl:attribute name="chart:display-label">true</xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name(.)='表:线型'">
+ <xsl:call-template name="uof:线型"/>
+ </xsl:when>
+ <xsl:when test="name(.)='表:数值'">
+ <xsl:attribute name="chart:link-data-style-to-source"><xsl:value-of select="@表:链接到源"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="name(.)='表:刻度'">
+ <xsl:call-template name="表:刻度类型"/>
+ </xsl:when>
+ <xsl:when test="name(.)='表:对齐'">
+ <xsl:if test="表:文字方向">
+ <xsl:attribute name="fo:direction"><xsl:value-of select="表:文字方向"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:旋转角度">
+ <xsl:attribute name="text:rotation-angle"><xsl:value-of select="表:旋转角度"/></xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </style:chart-properties>
+ <xsl:if test="表:字体">
+ <xsl:for-each select="表:字体">
+ <xsl:element name="style:text-properties">
+ <xsl:call-template name="字:句属性类型"/>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="表:数据点类型">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:param name="recall-type"/>
+ <xsl:if test="name(.)='表:数据点'">
+ <style:chart-properties>
+ <xsl:if test="$table-type='pie' and $table-subtype='pie_offset1' and @表:点='1'">
+ <xsl:attribute name="chart:pie-offset">10</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$table-type='pie' and $table-subtype='pie_offset2'">
+ <xsl:attribute name="chart:pie-offset">10</xsl:attribute>
+ </xsl:if>
+ </style:chart-properties>
+ </xsl:if>
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name(.)='表:边框'">
+ <style:graphic-properties>
+ <xsl:call-template name="uof:边框"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:填充'">
+ <style:graphic-properties>
+ <xsl:call-template name="图:填充类型"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:字体'">
+ <style:text-properties>
+ <xsl:call-template name="字:句属性类型"/>
+ </style:text-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:显示标志'">
+ <style:chart-properties>
+ <xsl:if test="@表:类别名">
+ <xsl:attribute name="chart:data-label-text"><xsl:value-of select="@表:类别名"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@表:数值">
+ <xsl:attribute name="chart:data-label-number">value</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@表:百分数">
+ <xsl:attribute name="chart:data-label-number">percentage</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@表:图例标志">
+ <xsl:attribute name="chart:data-label-symbol"><xsl:value-of select="@表:图例标志"/></xsl:attribute>
+ </xsl:if>
+ </style:chart-properties>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="表:标题类型">
+ <xsl:param name="table-name"/>
+ <xsl:param name="table-type"/>
+ <xsl:param name="table-subtype"/>
+ <xsl:param name="series-value-start"/>
+ <xsl:param name="series-value-end"/>
+ <xsl:param name="series-generate-type"/>
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name(.)='表:边框'">
+ <style:graphic-properties>
+ <xsl:call-template name="uof:边框"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:填充'">
+ <style:graphic-properties>
+ <xsl:call-template name="图:填充类型"/>
+ </style:graphic-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:对齐'">
+ <style:chart-properties>
+ <xsl:call-template name="表:对齐格式类型"/>
+ </style:chart-properties>
+ </xsl:when>
+ <xsl:when test="name(.)='表:字体'">
+ <style:text-properties>
+ <xsl:call-template name="字:句属性类型"/>
+ </style:text-properties>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="uof:边框">
+ <xsl:if test="@uof:类型">
+ <xsl:variable name="type" select="@uof:类型"/>
+ <xsl:attribute name="draw:stroke"><xsl:choose><xsl:when test="@uof:类型='single'">solid</xsl:when><xsl:when test="@uof:类型='none'">none</xsl:when><xsl:otherwise>dash</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="draw:stroke-dash"><xsl:choose><xsl:when test="$type='dash'">Ultrafine_20_Dashed</xsl:when><xsl:when test="$type='dot-dash'">Ultrafine_20_2_20_Dots_20_3_20_Dashes</xsl:when><xsl:when test="$type='dashed-heavy'">Fine_20_Dashed</xsl:when><xsl:when test="$type='dotted' ">Fine_20_Dotted</xsl:when><xsl:when test="$type='dash-long-heavy'">Line_20_with_20_Fine_20_Dots</xsl:when><xsl:when test="$type='dash-long'">Fine_20_Dashed_20__28_var_29_</xsl:when><xsl:when test="$type='dash-dot-dot'">_33__20_Dashes_20_3_20_Dots_20__28_var_29_</xsl:when><xsl:when test="$type='dotted-heavy'">Ultrafine_20_Dotted_20__28_var_29_</xsl:when><xsl:when test="$type='thick'">Line_20_Style_20_9</xsl:when><xsl:when test="$type='dot-dot-dash'">_32__20_Dots_20_1_20_Dash</xsl:when><xsl:when test="$type='dash-dot-dot-heavy'">Dashed_20__28_var_29_</xsl:when><xsl:when test="$type='dash-dot-heavy'">Dash_20_10</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@uof:宽度">
+ <xsl:attribute name="svg:stroke-width"><xsl:value-of select="concat(@uof:宽度,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@uof:颜色">
+ <xsl:attribute name="svg:stroke-color"><xsl:value-of select="@uof:颜色"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="图:填充类型">
+ <xsl:if test="图:颜色">
+ <xsl:attribute name="draw:fill">solid</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:颜色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:图片">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-image-name"><xsl:value-of select="图:图片/@图:名称"/></xsl:attribute>
+ <xsl:if test="not(图:图片/@图:位置='tile')">
+ <xsl:attribute name="style:repeat"><xsl:choose><xsl:when test="图:图片/@图:位置='center'">no-repeat</xsl:when><xsl:when test="图:图片/@图:位置='stretch'">stretch</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="图:图案">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-hatch-name"><xsl:value-of select="图:图案/@图:图形引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:渐变">
+ <xsl:attribute name="draw:fill">gradient</xsl:attribute>
+ <xsl:attribute name="draw:fill-gradient-name"><xsl:value-of select="图:渐变/@图:图形引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="uof:线型">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:template>
+ <xsl:template name="字:句属性类型">
+ <xsl:apply-templates select="./*"/>
+ </xsl:template>
+ <xsl:template name="表:刻度类型">
+ <xsl:if test="表:最小值">
+ <xsl:attribute name="chart:minimum"><xsl:value-of select="表:最小值"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:最大值">
+ <xsl:attribute name="chart:maximum"><xsl:value-of select="表:最大值"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:主单位">
+ <xsl:attribute name="chart:interval-major"><xsl:value-of select="表:主单位"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:次单位">
+ <xsl:attribute name="chart:interval-minor"><xsl:value-of select="表:次单位"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:分类交叉点">
+ <xsl:attribute name="chart:origin"><xsl:value-of select="表:分类交叉点"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="表:对齐格式类型">
+ <xsl:if test="表:文字方向">
+ <xsl:attribute name="style:direction"><xsl:value-of select="表:文字方向"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="表:文字旋转角度">
+ <xsl:attribute name="style:rotation-angle"><xsl:value-of select="表:文字旋转角度"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:字体">
+ <xsl:if test="@字:字号">
+ <xsl:attribute name="fo:font-size"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:相对字号 and self::node( )[not(parent::字:句属性)]">
+ <xsl:variable name="stylename" select="parent::node()/@字:基式样引用"/>
+ <xsl:variable name="zihao">
+ <xsl:for-each select="/uof:UOF/uof:式样集//uof:段落式样[@字:标识符=$stylename]">
+ <xsl:value-of select="字:字体/@字:字号"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="font-size" select="@字:相对字号"/>
+ <xsl:attribute name="fo:font-size"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:颜色">
+ <xsl:attribute name="fo:color"><xsl:value-of select="string(@字:颜色)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:中文字体引用">
+ <xsl:attribute name="style:font-family-asian"><xsl:value-of select="@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:西文字体引用">
+ <xsl:attribute name="fo:font-family"><xsl:value-of select="@字:西文字体引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:斜体">
+ <xsl:if test="@字:值='true'">
+ <xsl:attribute name="fo:font-style">italic</xsl:attribute>
+ <xsl:attribute name="fo:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-complex">italic</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:粗体">
+ <xsl:if test="@字:值='true'">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-complex">bold</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:下划线">
+ <xsl:choose>
+ <xsl:when test="@字:类型 = 'single'">
+ <xsl:attribute name="style:text-underline-style">solid</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'double'">
+ <xsl:attribute name="style:text-underline-style">solid</xsl:attribute>
+ <xsl:attribute name="style:text-underline-type">double</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'thick'">
+ <xsl:attribute name="style:text-underline-style">solid</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dotted'">
+ <xsl:attribute name="style:text-underline-style">dotted</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dotted-heavy'">
+ <xsl:attribute name="style:text-underline-style">dotted</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash'">
+ <xsl:attribute name="style:text-underline-style">dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dashed-heavy'">
+ <xsl:attribute name="style:text-underline-style">dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-long'">
+ <xsl:attribute name="style:text-underline-style">long-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-long-heavy'">
+ <xsl:attribute name="style:text-underline-style">long-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dot-dash'">
+ <xsl:attribute name="style:text-underline-style">dot-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-dot-heavy'">
+ <xsl:attribute name="style:text-underline-style">dot-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dot-dot-dash'">
+ <xsl:attribute name="style:text-underline-style">dot-dot-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-dot-dot-heavy'">
+ <xsl:attribute name="style:text-underline-style">dot-dot-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'wave'">
+ <xsl:attribute name="style:text-underline-style">wave</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'wavy-heavy'">
+ <xsl:attribute name="style:text-underline-style">wave</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'wavy-double'">
+ <xsl:attribute name="style:text-underline-style">wave</xsl:attribute>
+ <xsl:attribute name="style:text-underline-type">double</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@字:颜色">
+ <xsl:attribute name="style:text-underline-color"><xsl:choose><xsl:when test="@字:颜色='auto'">font-color</xsl:when><xsl:otherwise><xsl:value-of select="@字:颜色"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:text-underline-color">font-color</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:着重号">
+ <xsl:if test="not(@字:类型='none')">
+ <xsl:choose>
+ <xsl:when test="@字:类型='accent above' ">
+ <xsl:attribute name="style:text-emphasize">accent above</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='dot above' ">
+ <xsl:attribute name="style:text-emphasize">dot above</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='disc above' ">
+ <xsl:attribute name="style:text-emphasize">disc above</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='circle above' ">
+ <xsl:attribute name="style:text-emphasize">circle above</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='accent below' ">
+ <xsl:attribute name="style:text-emphasize">accent below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='dot below' ">
+ <xsl:attribute name="style:text-emphasize">dot below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='disc below' ">
+ <xsl:attribute name="style:text-emphasize">disc below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='circle below' ">
+ <xsl:attribute name="style:text-emphasize">circle below</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="字:颜色">
+ <xsl:attribute name="fo:color"><xsl:value-of select="@字:颜色"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:隐藏文字">
+ <xsl:attribute name="text:display"><xsl:value-of select="@字:值"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:空心">
+ <xsl:attribute name="style:text-outline"><xsl:value-of select="@字:值"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:阴影">
+ <xsl:if test="not(@字:值='false')">
+ <xsl:attribute name="fo:text-shadow">1pt 1pt</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:删除线">
+ <xsl:attribute name="style:text-line-through-style">solid</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@字:类型='double'">
+ <xsl:attribute name="style:text-line-through-type">double</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='single'">
+ <xsl:attribute name="style:text-underline-mode">continuous</xsl:attribute>
+ <xsl:attribute name="style:text-line-through-mode">continuous</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='bold'">
+ <xsl:attribute name="style:text-line-through-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='带/'">
+ <xsl:attribute name="style:text-line-through-text">/</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='带X'">
+ <xsl:attribute name="style:text-line-through-text">X</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="@字:颜色[not(.='auto')]">
+ <xsl:attribute name="fo:color">#<xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:浮雕">
+ <xsl:attribute name="style:font-relief"><xsl:choose><xsl:when test="@字:类型='engrave'">engraved</xsl:when><xsl:when test="@字:类型='emboss'">embossed</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:醒目字体">
+ <xsl:choose>
+ <xsl:when test="@字:类型='small-caps'">
+ <xsl:attribute name="fo:font-variant">small-caps</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='none'">
+ <xsl:attribute name="fo:font-variant">normal</xsl:attribute>
+ <xsl:attribute name="fo:text-transform">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:text-transform"><xsl:choose><xsl:when test="@字:类型='uppercase'">uppercase</xsl:when><xsl:when test="@字:类型='lowercase'">lowercase</xsl:when><xsl:when test="@字:类型='capital'">capitalize</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:位置">
+ <xsl:attribute name="style:text-position"><xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:缩放">
+ <xsl:attribute name="style:text-scale"><xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:字符间距">
+ <xsl:attribute name="fo:letter-spacing"><xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:调整字间距">
+ <xsl:attribute name="style:letter-kerning"><xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:外框">
+ <xsl:attribute name="style:text-outline">true</xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:缩放">
+ <xsl:attribute name="style:text-scale"><xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:字符间距[parent::字:句属性]">
+ <xsl:attribute name="fo:letter-spacing"><xsl:value-of select="concat( number(.)* $other-to-cm-conversion-factor, $uofUnit)"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template name="General-Char-Transition">
+ <xsl:param name="input-char"/>
+ <xsl:param name="output-type"/>
+ <xsl:choose>
+ <xsl:when test="$input-char='A' or $input-char='a' or $input-char='1' or $input-char='Roman_I' or $input-char='Roman_i' or $input-char='一' or $input-char='壹' or $input-char='甲' or $input-char='子'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">1</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">a</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">A</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">I</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">i</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">1</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">一</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">1</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">壹</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">1</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">甲</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">子</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='B' or $input-char='b' or $input-char='2' or $input-char='Roman_II' or $input-char='Roman_ii' or $input-char='二' or $input-char='贰' or $input-char='乙' or $input-char='丑'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">2</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">b</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">B</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">II</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">ii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">2</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">2</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">2</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">乙</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">丑</xsl:when>
+ <xsl:otherwise>2</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='C' or $input-char='c' or $input-char='3' or $input-char='Roman_III' or $input-char='Roman_iii' or $input-char='三' or $input-char='叁' or $input-char='丙' or $input-char='寅'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">3</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">c</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">C</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">III</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">iii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">3</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">三</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">3</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">叁</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">3</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">丙</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">寅</xsl:when>
+ <xsl:otherwise>3</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='D' or $input-char='d' or $input-char='4' or $input-char='Roman_IV' or $input-char='Roman_iv' or $input-char='四' or $input-char='肆' or $input-char='丁' or $input-char='卯'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">4</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">d</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">D</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">IV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">iv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">4</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">四</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">4</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">肆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">4</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">丁</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">卯</xsl:when>
+ <xsl:otherwise>4</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='E' or $input-char='e' or $input-char='5' or $input-char='Roman_V' or $input-char='Roman_v' or $input-char='五' or $input-char='伍' or $input-char='戊' or $input-char='辰'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">5</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">e</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">E</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">V</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">v</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">5</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">五</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">5</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">伍</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">5</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">戊</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">辰</xsl:when>
+ <xsl:otherwise>5</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='F' or $input-char='f' or $input-char='6' or $input-char='Roman_VI' or $input-char='Roman_vi' or $input-char='六' or $input-char='陆' or $input-char='己' or $input-char='巳'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">6</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">f</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">F</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">VI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">vi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">6</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">六</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">6</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">陆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">6</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">己</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">巳</xsl:when>
+ <xsl:otherwise>6</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='G' or $input-char='g' or $input-char='7' or $input-char='7' or $input-char='Roman_VII' or $input-char='Roman_vii' or $input-char='七' or $input-char='柒' or $input-char='庚' or $input-char='午'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">7</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">g</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">G</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">VII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">vii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">7</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">七</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">7</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">柒</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">7</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">庚</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">午</xsl:when>
+ <xsl:otherwise>7</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='H' or $input-char='h' or $input-char='8' or $input-char='Roman_VIII' or $input-char='Roman_viii' or $input-char='八' or $input-char='捌' or $input-char='辛' or $input-char='未'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">8</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">h</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">H</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">VIII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">viii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">8</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">八</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">8</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">捌</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">8</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">辛</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">未</xsl:when>
+ <xsl:otherwise>8</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='I' or $input-char='i' or $input-char='9' or $input-char='Roman_IX' or $input-char='Roman_ix' or $input-char='九' or $input-char='玖' or $input-char='壬' or $input-char='申'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">9</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">i</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">I</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">IX</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">ix</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">9</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">九</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">9</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">玖</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">9</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">壬</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">申</xsl:when>
+ <xsl:otherwise>9</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='J' or $input-char='j' or $input-char='10' or $input-char='Roman_X' or $input-char='Roman_x' or $input-char='十' or $input-char='拾' or $input-char='癸' or $input-char='酉'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">10</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">j</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">J</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">X</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">x</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">10</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">10</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">10</xsl:when>
+ <xsl:when test="$output-type='TIAN_GAN_ZH'">癸</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">酉</xsl:when>
+ <xsl:otherwise>10</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='K' or $input-char='k' or $input-char='11' or $input-char='Roman_XI' or $input-char='Roman_xi' or $input-char='十一' or $input-char='拾壹' or $input-char='戌'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">11</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">k</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">K</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">11</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十一</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">11</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾壹</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">11</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">戌</xsl:when>
+ <xsl:otherwise>11</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='L' or $input-char='l' or $input-char='12' or $input-char='Roman_XII' or $input-char='Roman_xii' or $input-char='十二' or $input-char='拾贰' or $input-char='亥'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">12</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">l</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">L</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">12</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十二</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">12</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾贰</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">12</xsl:when>
+ <xsl:when test="$output-type='DI_ZI_ZH'">亥</xsl:when>
+ <xsl:otherwise>12</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='M' or $input-char='m' or $input-char='13' or $input-char='Roman_XIII' or $input-char='Roman_xiii' or $input-char='十三' or $input-char='拾叁'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">13</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">m</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">M</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XIII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xiii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">13</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十三</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">13</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾叁</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">13</xsl:when>
+ <xsl:otherwise>13</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='N' or $input-char='n' or $input-char='14' or $input-char='Roman_XIV' or $input-char='Roman_xiv' or $input-char='十四' or $input-char='拾肆'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">14</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">n</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">N</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XIV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xiv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">14</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十四</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">14</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾肆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">14</xsl:when>
+ <xsl:otherwise>14</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='O' or $input-char='o' or $input-char='15' or $input-char='Roman_XV' or $input-char='Roman_xv' or $input-char='十五' or $input-char='拾伍'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">15</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">o</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">O</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">15</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十五</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">15</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾伍</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">15</xsl:when>
+ <xsl:otherwise>15</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='P' or $input-char='p' or $input-char='16' or $input-char='Roman_XVI' or $input-char='Roman_xvi' or $input-char='十六' or $input-char='拾陆'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">16</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">p</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">P</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XVI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xvi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">16</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十六</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">16</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾陆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">16</xsl:when>
+ <xsl:otherwise>16</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='Q' or $input-char='q' or $input-char='17' or $input-char='Roman_XVII' or $input-char='Roman_xvii' or $input-char='十七' or $input-char='拾柒'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">17</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">q</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">Q</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XVII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xvii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">17</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十七</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">17</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾柒</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">17</xsl:when>
+ <xsl:otherwise>17</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='R' or $input-char='r' or $input-char='18' or $input-char='Roman_XVIII' or $input-char='Roman_xviii' or $input-char='十八' or $input-char='拾捌'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">18</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">r</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">R</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XVIII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xviii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">18</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十八</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">18</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾捌</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">18</xsl:when>
+ <xsl:otherwise>18</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='S' or $input-char='s' or $input-char='19' or $input-char='Roman_XIX' or $input-char='Roman_xix' or $input-char='十九' or $input-char='拾玖'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">19</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">s</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">S</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XIX</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xix</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">19</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">十九</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">19</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">拾玖</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">19</xsl:when>
+ <xsl:otherwise>19</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='T' or $input-char='t' or $input-char='20' or $input-char='Roman_XX' or $input-char='Roman_xx' or $input-char='二十' or $input-char='贰拾'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">20</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">t</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">T</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XX</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xx</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">20</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">20</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">20</xsl:when>
+ <xsl:otherwise>20</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='U' or $input-char='u' or $input-char='21' or $input-char='Roman_XXI' or $input-char='Roman_xxi' or $input-char='二十一' or $input-char='贰拾壹'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">21</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">u</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">U</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">21</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十一</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">21</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾壹</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">21</xsl:when>
+ <xsl:otherwise>21</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='V' or $input-char='v' or $input-char='22' or $input-char='Roman_XXII' or $input-char='Roman_xxii' or $input-char='二十二' or $input-char='贰拾贰'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">22</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">v</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">V</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">22</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十二</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">22</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾贰</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">22</xsl:when>
+ <xsl:otherwise>22</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='W' or $input-char='w' or $input-char='23' or $input-char='Roman_XXIII' or $input-char='Roman_xxiii' or $input-char='二十三' or $input-char='贰拾叁'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">23</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">w</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">W</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXIII</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxiii</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">23</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十三</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">23</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾叁</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">23</xsl:when>
+ <xsl:otherwise>23</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='X' or $input-char='x' or $input-char='24' or $input-char='Roman_XXIV' or $input-char='Roman_xxiv' or $input-char='二十四' or $input-char='贰拾肆'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">24</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">x</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">X</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXIV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxiv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">24</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十四</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">24</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾肆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">24</xsl:when>
+ <xsl:otherwise>24</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='Y' or $input-char='y' or $input-char='25' or $input-char='Roman_XXV' or $input-char='Roman_xxv' or $input-char='二十五' or $input-char='贰拾伍'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">25</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">y</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">Y</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXV</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxv</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">25</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十五</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">25</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾伍</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">25</xsl:when>
+ <xsl:otherwise>25</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$input-char='Z' or $input-char='z' or $input-char='26' or $input-char='Roman_XXVI' or $input-char='Roman_xxvi' or $input-char='二十六' or $input-char='贰拾陆'">
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">26</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">z</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">Z</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">XXVI</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">xxvi</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">26</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">二十六</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">26</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">贰拾陆</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">26</xsl:when>
+ <xsl:otherwise>26</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$output-type='ARABIC'">1</xsl:when>
+ <xsl:when test="$output-type='CHARS_LOWER_LETTER'">a</xsl:when>
+ <xsl:when test="$output-type='CHARS_UPPER_LETTER'">A</xsl:when>
+ <xsl:when test="$output-type='ROMAN_UPPER'">I</xsl:when>
+ <xsl:when test="$output-type='ROMAN_LOWER'">i</xsl:when>
+ <xsl:when test="$output-type='FULLWIDTH_ARABIC'">1</xsl:when>
+ <xsl:when test="$output-type='NUMBER_LOWER_ZH'">一</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH_TW'">1</xsl:when>
+ <xsl:when test="$output-type='NUMBER_UPPER_ZH'">壹</xsl:when>
+ <xsl:when test="$output-type='CIRCLE_NUMBER'">1</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--RedOffice comment (Zengjh) end charts-->
+ <!-- 以下模板的作用是将网格线颜色由16进制转换为十进制 -->
+ <xsl:template name="transform-hex-to-decimal">
+ <xsl:param name="number"/>
+ <xsl:variable name="R-color-number">
+ <xsl:call-template name="color-hex-to-decimal">
+ <xsl:with-param name="chars" select="substring($number,2,2)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="G-color-number">
+ <xsl:call-template name="color-hex-to-decimal">
+ <xsl:with-param name="chars" select="substring($number,4,2)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="B-color-number">
+ <xsl:call-template name="color-hex-to-decimal">
+ <xsl:with-param name="chars" select="substring($number,6,2)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$R-color-number * 65536 + $G-color-number * 256 + $B-color-number"/>
+ </xsl:template>
+ <!-- 以下模板的作用是为R或G或B颜色转换为十进制形式-->
+ <xsl:template name="color-hex-to-decimal">
+ <xsl:param name="chars"/>
+ <xsl:variable name="first-num">
+ <xsl:call-template name="hex-to-decimal">
+ <xsl:with-param name="char" select="substring($chars,1,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="second-num">
+ <xsl:call-template name="hex-to-decimal">
+ <xsl:with-param name="char" select="substring($chars,2,1)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$first-num *16 + $second-num"/>
+ </xsl:template>
+ <xsl:template name="hex-to-decimal">
+ <xsl:param name="char"/>
+ <xsl:choose>
+ <xsl:when test="$char='0'">0</xsl:when>
+ <xsl:when test="$char='1'">1</xsl:when>
+ <xsl:when test="$char='2'">2</xsl:when>
+ <xsl:when test="$char='3'">3</xsl:when>
+ <xsl:when test="$char='4'">4</xsl:when>
+ <xsl:when test="$char='5'">5</xsl:when>
+ <xsl:when test="$char='6'">6</xsl:when>
+ <xsl:when test="$char='7'">7</xsl:when>
+ <xsl:when test="$char='8'">8</xsl:when>
+ <xsl:when test="$char='9'">9</xsl:when>
+ <xsl:when test="$char='a'">10</xsl:when>
+ <xsl:when test="$char='b'">11</xsl:when>
+ <xsl:when test="$char='c'">12</xsl:when>
+ <xsl:when test="$char='d'">13</xsl:when>
+ <xsl:when test="$char='e'">14</xsl:when>
+ <xsl:when test="$char='f'">15</xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <!-- end -->
+ <!--ro000179 chenjh-->
+ <xsl:template name="search-left-top-in-tables">
+ <xsl:param name="cellstylename"/>
+ <xsl:param name="tableslist"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$tableslist and $return=''">
+ <xsl:variable name="firsttablerows" select="$tableslist[1]//表:行"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-inatable">
+ <xsl:with-param name="row-num" select="'1'"/>
+ <xsl:with-param name="firsttablerows" select="$firsttablerows"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-in-tables">
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="tableslist" select="$tableslist[position()!=1]"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top!=''">
+ <xsl:value-of select="$rest-left-top"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- 以下模板的作用为在一个table中寻找左上角-->
+ <xsl:template name="search-left-top-inatable">
+ <xsl:param name="row-num"/>
+ <xsl:param name="firsttablerows"/>
+ <xsl:param name="cellstylename"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$firsttablerows and $return=''">
+ <xsl:variable name="firstcells" select="$firsttablerows[1]/表:单元格"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-inarow">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="firstcells" select="$firstcells"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="return" select="''"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="row-num-p">
+ <xsl:choose>
+ <xsl:when test="$firsttablerows[1]/@表:跨度">
+ <xsl:value-of select="$row-num+ $firsttablerows[1]/@表:跨度"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$row-num+1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-inatable">
+ <xsl:with-param name="row-num" select="$row-num-p"/>
+ <xsl:with-param name="firsttablerows" select="$firsttablerows[position()!=1]"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top !=''">
+ <xsl:value-of select="$rest-left-top "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- 以下模板的作用为在某一行中寻找左上角-->
+ <xsl:template name="search-left-top-inarow">
+ <xsl:param name="row-num"/>
+ <xsl:param name="firstcells"/>
+ <xsl:param name="cellstylename"/>
+ <xsl:param name="return"/>
+ <xsl:choose>
+ <xsl:when test="$firstcells and $return=''">
+ <xsl:variable name="firstcell" select="$firstcells[1]"/>
+ <xsl:variable name="first-left-top">
+ <xsl:call-template name="search-left-top-inacell">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="cell" select="$firstcell"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="rest-left-top">
+ <xsl:call-template name="search-left-top-inarow">
+ <xsl:with-param name="row-num" select="$row-num"/>
+ <xsl:with-param name="firstcells" select="$firstcells[position()!=1]"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="return" select="$first-left-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$first-left-top!=''">
+ <xsl:value-of select="$first-left-top"/>
+ </xsl:when>
+ <xsl:when test="$rest-left-top !=''">
+ <xsl:value-of select="$rest-left-top "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$return"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- 以下的模板的作用为判断某个cell是否为左上角 -->
+ <xsl:template name="search-left-top-inacell">
+ <xsl:param name="row-num"/>
+ <xsl:param name="cell"/>
+ <xsl:param name="cellstylename"/>
+ <xsl:choose>
+ <xsl:when test="$cell/@表:式样引用=$cellstylename">
+ <xsl:value-of select="concat($cell/ancestor::表:工作表/@表:名称,'.',$cell/@表:列号,' ',$row-num)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ <!-- <xsl:variable name="style-is-default">
+ <xsl:call-template name="is-default-or-not-condition-format">
+ <xsl:with-param name="column-num" select="$cell/@表:列号"/>
+ <xsl:with-param name="cell" select="$cell"/>
+ <xsl:with-param name="preceding-cellstylename" select="''"/>
+ <xsl:with-param name="temp-num" select="'0'"/>
+ <xsl:with-param name="cellstylename" select="$cellstylename"/>
+ <xsl:with-param name="table-columns" select="$cell/ancestor::表:工作表内容//表:列"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$style-is-default='yes' ">
+ <xsl:value-of select="concat($cell/ancestor::表:工作表/@表:名称,'.',$cell/@表:列号,' ',$row-num)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="''"/>
+ </xsl:otherwise>
+ </xsl:choose> -->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="translate-left-top">
+ <xsl:param name="left-top"/>
+ <xsl:if test="$left-top!=''">
+ <xsl:variable name="column-number" select="substring-before(substring-after($left-top,'.'),' ')"/>
+ <xsl:variable name="column-number1">
+ <xsl:value-of select="floor( $column-number div 26 )"/>
+ </xsl:variable>
+ <xsl:variable name="column-number2">
+ <xsl:value-of select="$column-number mod 26"/>
+ </xsl:variable>
+ <xsl:variable name="column-character1">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="column-character2">
+ <xsl:call-template name="number-to-character">
+ <xsl:with-param name="number" select="$column-number2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat(substring-before($left-top,'.'),'.',$column-character1,$column-character2,substring-after($left-top,' '))"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-the-condition-format-map">
+ <xsl:param name="condition-format-set"/>
+ <xsl:param name="current-left-top"/>
+ <xsl:if test="$condition-format-set">
+ <xsl:choose>
+ <xsl:when test="contains($condition-format-set[1]/表:区域/text(),$current-left-top)">
+ <xsl:for-each select="$condition-format-set[1]/表:条件">
+ <xsl:variable name="condition-text">
+ <xsl:choose>
+ <xsl:when test="@表:类型='cell value'">
+ <xsl:choose>
+ <xsl:when test="表:操作码/text()='between' ">
+ <xsl:value-of select="concat('cell-content-is-between','(',表:第一操作数/text(),',',表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test=" 表:操作码/text()='not between'">
+ <xsl:value-of select="concat('cell-content-is-not-between','(',表:第一操作数/text(),',',表:第二操作数/text(),')')"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='equal to'">
+ <xsl:value-of select="concat('cell-content()=',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='not equal to'">
+ <xsl:value-of select="concat('cell-content()!=',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='greater than'">
+ <xsl:value-of select="concat('cell-content()&gt;',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='less than'">
+ <xsl:value-of select="concat('cell-content()&lt;',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='greater than or equal to'">
+ <xsl:value-of select="concat('cell-content()&gt;=',表:第一操作数/text())"/>
+ </xsl:when>
+ <xsl:when test="表:操作码/text()='less than or equal to'">
+ <xsl:value-of select="concat('cell-content()&lt;=',表:第一操作数/text())"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="@表:类型='formula'">
+ <xsl:value-of select="concat('is-true-formula','(',表:第一操作数/text(),')')"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="style:map">
+ <xsl:attribute name="style:condition"><xsl:value-of select="$condition-text"/></xsl:attribute>
+ <xsl:attribute name="style:apply-style-name"><xsl:value-of select="//uof:单元格式样[@表:标识符=current()/表:格式/@表:式样引用]/@表:名称"/></xsl:attribute>
+ <xsl:attribute name="style:base-cell-address"><xsl:value-of select="substring-after($condition-format-set[1]/表:区域/text(),':')"/></xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-the-condition-format-map">
+ <xsl:with-param name="condition-format-set" select="$condition-format-set[position()!=1]"/>
+ <xsl:with-param name="current-left-top" select="$current-left-top"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <!--ro000179 end-->
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/uof/uof2odf_text.xsl b/filter/source/xslt/import/uof/uof2odf_text.xsl
new file mode 100644
index 000000000..162fa4c7f
--- /dev/null
+++ b/filter/source/xslt/import/uof/uof2odf_text.xsl
@@ -0,0 +1,4667 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:uof="http://schemas.uof.org/cn/2003/uof" xmlns:表="http://schemas.uof.org/cn/2003/uof-spreadsheet" xmlns:演="http://schemas.uof.org/cn/2003/uof-slideshow" xmlns:字="http://schemas.uof.org/cn/2003/uof-wordproc" xmlns:图="http://schemas.uof.org/cn/2003/graph" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" office:version="1.0">
+ <xsl:template match="uof:UOF">
+ <office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:smil="urn:oasis:names:tc:opendocument:xmlns:smil-compatible:1.0" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" office:version="1.0">
+ <xsl:apply-templates select="uof:元数据"/>
+ <xsl:apply-templates select="uof:文字处理/字:公用处理规则/字:文档设置"/>
+ <xsl:apply-templates select="uof:字体集"/>
+ <xsl:apply-templates select="uof:式样集"/>
+ <xsl:apply-templates select="uof:文字处理"/>
+ </office:document>
+ </xsl:template>
+ <xsl:template match="uof:元数据">
+ <xsl:element name="office:meta">
+ <meta:generator>UOFText 2004</meta:generator>
+ <dc:title>
+ <xsl:value-of select="uof:标题"/>
+ </dc:title>
+ <dc:description>
+ <xsl:value-of select="uof:摘要"/>
+ </dc:description>
+ <dc:subject>
+ <xsl:value-of select="uof:主题"/>
+ </dc:subject>
+ <meta:initial-creator>
+ <xsl:value-of select="uof:创建者"/>
+ </meta:initial-creator>
+ <meta:creation-date>
+ <xsl:value-of select="substring-before( uof:创建日期, 'Z')"/>
+ </meta:creation-date>
+ <dc:creator>
+ <xsl:value-of select="uof:最后作者"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="substring-before( uof:编辑时间, 'Z')"/>
+ </dc:date>
+ <meta:printed-by/>
+ <meta:print-date/>
+ <meta:keywords>
+ <meta:keyword>
+ <xsl:value-of select="uof:关键字集/uof:关键字"/>
+ </meta:keyword>
+ </meta:keywords>
+ <dc:language/>
+ <meta:editing-cycles>
+ <xsl:value-of select="uof:编辑次数"/>
+ </meta:editing-cycles>
+ <meta:editing-duration>
+ <xsl:if test="uof:编辑时间">
+ <xsl:value-of select="concat('PT', floor(uof:编辑时间 div 60), 'H', uof:编辑时间 mod 60, 'M0S')"/>
+ </xsl:if>
+ </meta:editing-duration>
+ <meta:user-defined meta:name="Category">
+ <xsl:value-of select="uof:分类"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Manager">
+ <xsl:value-of select="uof:经理名称"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Company">
+ <xsl:value-of select="uof:公司名称"/>
+ </meta:user-defined>
+ <meta:user-defined meta:name="Version">
+ <xsl:value-of select="uof:创建应用程序"/>
+ </meta:user-defined>
+ <xsl:if test="uof:文档模板|child::*[@uof:locID='u0013']">
+ <meta:template xlink:type="simple" xlink:actuate="onRequest" xlink:href="{child::*[@uof:locID='u0013']}"/>
+ </xsl:if>
+ <xsl:if test="uof:用户自定义元数据集/uof:用户自定义元数据|child::*[@uof:locID='u0016']/*[@uof:locID='u0017']">
+ <xsl:for-each select="uof:用户自定义元数据集/uof:用户自定义元数据|child::*[@uof:locID='u0016']/*[@uof:locID='u0017']">
+ <xsl:element name="meta:user-defined">
+ <xsl:attribute name="meta:name"><xsl:value-of select="@uof:名称"/></xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:if>
+ <meta:document-statistic>
+ <xsl:attribute name="meta:page-count">
+ <xsl:choose>
+ <xsl:when test="child::*[@uof:locID='u0020']"><xsl:value-of select="uof:页数"/></xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体/字:段落/字:域开始[@字:类型='numpages']">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="fmt">
+ <xsl:value-of select="substring-before($date0,' \*')"/>
+ </xsl:variable>
+ <xsl:if test="$fmt='Arabic'"><xsl:value-of select="following-sibling::字:句/字:文本串"/></xsl:if>
+ <xsl:if test="not($fmt='Arabic')">
+ <xsl:variable name="content">
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$content='I' or $content='i' or $content='A' or $content='a'">1</xsl:when>
+ <xsl:when test="$content='II' or $content='ii' or $content='B' or $content='b'">2</xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="meta:paragraph-count"><xsl:if test="child::*[@uof:locID='u0025']"><xsl:value-of select="uof:段落数"/></xsl:if></xsl:attribute>
+ <xsl:attribute name="meta:word-count"><xsl:if test="child::*[@uof:locID='u0023']"><xsl:value-of select="uof:中文字符数"/></xsl:if></xsl:attribute>
+ <xsl:attribute name="meta:object-count"><xsl:if test="child::*[@uof:locID='u0026']"><xsl:value-of select="uof:对象数"/></xsl:if></xsl:attribute>
+ <xsl:attribute name="meta:character-count">
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体/字:段落/字:域开始[@字:类型='numchars']">
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:for-each>
+ <xsl:if test="child::*[@uof:locID='u0021']"><xsl:value-of select="uof:字数"/></xsl:if>
+ </xsl:attribute>
+ </meta:document-statistic>
+ <meta:document-statistic/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:variable name="uofUnit">
+ <xsl:variable name="uu">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:公用处理规则/字:文档设置/字:度量单位"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$uu='cm'">cm</xsl:when>
+ <xsl:when test="$uu='mm'">mm</xsl:when>
+ <xsl:when test="$uu='pt'">pt</xsl:when>
+ <xsl:when test="$uu='inch'">in</xsl:when>
+ <xsl:otherwise>cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="other-to-cm-conversion-factor">
+ <xsl:choose>
+ <xsl:when test="$uofUnit='cm'">1</xsl:when>
+ <xsl:when test="$uofUnit='mm'">0.1</xsl:when>
+ <xsl:when test="$uofUnit='pt'">0.03527</xsl:when>
+ <xsl:when test="$uofUnit='inch'">2.54</xsl:when>
+ <xsl:when test="$uofUnit='pica'">0.4233</xsl:when>
+ <xsl:otherwise>0.03527</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:template match="uof:式样集">
+ <xsl:apply-templates select="uof:字体集"/>
+ <xsl:variable name="default_paragraph_style" select="uof:段落式样"/>
+ <xsl:variable name="default_character_style" select="uof:句式样"/>
+ <xsl:variable name="default_table_style" select="uof:文字表式样"/>
+ <office:styles>
+ <xsl:if test="uof:段落式样[@字:类型 = 'default']">
+ <style:default-style style:family="paragraph">
+ <xsl:element name="style:paragraph-properties">
+ <xsl:attribute name="style:tab-stop-distance"><xsl:value-of select="concat( number(/uof:UOF/uof:文字处理/字:公用处理规则/字:文档设置/字:默认制表位位置),$uofUnit)"/></xsl:attribute>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:choose>
+ <xsl:when test="/uof:UOF/uof:式样集/uof:字体集/uof:默认字体">
+ <xsl:attribute name="style:font-name"><xsl:value-of select="/uof:UOF//uof:字体集/uof:默认字体/@uof:ascii"/></xsl:attribute>
+ <xsl:attribute name="style:font-name-asian"><xsl:value-of select="/uof:UOF//uof:字体集/uof:默认字体/@uof:fareast"/></xsl:attribute>
+ <xsl:attribute name="style:font-name-complex"><xsl:value-of select="/uof:UOF//uof:字体集/uof:默认字体/@uof:cs"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:font-name">Times New Roman</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates select="uof:UOF/uof:式样集/uof:句式样/字:字体"/>
+ <xsl:if test="not(uof:UOF/uof:式样集/uof:句式样/字:字体/@字:字号 or uof:UOF/uof:式样集/uof:句属性/字:字体/@字:字号)">
+ <xsl:attribute name="fo:font-size">10pt</xsl:attribute>
+ <xsl:attribute name="fo:font-size-asian">10pt</xsl:attribute>
+ <xsl:attribute name="fo:font-size-complex">10pt</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </style:default-style>
+ </xsl:if>
+ <xsl:for-each select="uof:段落式样[@字:类型='auto']">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:family">paragraph</xsl:attribute>
+ <xsl:attribute name="style:name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ <xsl:if test="@字:基式样引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:基式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:别名">
+ <xsl:attribute name="style:display-name"><xsl:value-of select="@字:别名"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:paragraph-properties">
+ <xsl:call-template name="XDParagraphAttr"/>
+ <xsl:apply-templates select="*[not(name()='字:大纲级别')]"/>
+ <xsl:if test="字:制表位设置">
+ <xsl:call-template name="ootab"/>
+ </xsl:if>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="字:句属性/*"/>
+ </xsl:element>
+ <xsl:variable name="biaoshi" select="@字:标识符"/>
+ <xsl:for-each select="../uof:句式样">
+ <xsl:if test="@字:标识符=$biaoshi">
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="*"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="uof:句式样[@字:类型='auto']">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="ancestor::字:段落式样">
+ <xsl:attribute name="style:family">paragraph</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="*"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ <style:style style:name="ColumnBreakPara" style:family="paragraph">
+ <style:text-properties fo:break-after="column"/>
+ </style:style>
+ <xsl:if test="uof:句式样">
+ <style:default-style style:family="text"/>
+ </xsl:if>
+ <style:style style:name="Numbering Symbols" style:family="text"/>
+ <style:style style:name="Bullet Symbols" style:family="text">
+ <style:text-properties style:font-name="StarSymbol" fo:font-size="9pt" style:font-name-asian="StarSymbol" style:font-size-asian="9pt" style:font-name-complex="StarSymbol" style:font-size-complex="9pt"/>
+ </style:style>
+ <xsl:apply-templates select="uof:文字表式样" mode="table"/>
+ <xsl:apply-templates select="uof:式样"/>
+ <xsl:call-template name="脚注设置"/>
+ <xsl:call-template name="尾注设置"/>
+ <xsl:call-template name="行编号"/>
+ </office:styles>
+ <xsl:element name="office:automatic-styles">
+ <style:style style:name="PageBreak" style:family="paragraph">
+ <style:text-properties fo:break-before="page"/>
+ </style:style>
+ <xsl:apply-templates select="/uof:UOF/uof:文字处理/字:主体/字:段落/字:句/字:句属性" mode="style"/>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:句">
+ <xsl:variable name="stylename1" select="字:句属性/@字:式样引用"/>
+ <xsl:element name="style:style">
+ <xsl:variable name="stylenum">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:句" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('T',$stylenum)"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="ancestor::字:段落式样">
+ <xsl:attribute name="style:family">paragraph</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样">
+ <xsl:if test="$stylename1=@字:标识符">
+ <xsl:choose>
+ <xsl:when test="@字:标识符=/uof:UOF/uof:文字处理/字:主体/字:段落/字:句/字:句属性/字:格式修订/@字:修订信息引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:基式样引用"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:element name="style:text-properties">
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样">
+ <xsl:if test="$stylename1=@字:标识符">
+ <xsl:apply-templates select="./字:位置" mode="oo"/>
+ <xsl:apply-templates select="*[not(name()='字:位置')]"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:域开始[@字:类型 = 'date']">
+ <xsl:element name="number:date-style">
+ <xsl:attribute name="style:name">Date<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'date']"/></xsl:attribute>
+ <xsl:call-template name="日期域"/>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:域开始[@字:类型 = 'createdate']">
+ <xsl:element name="number:date-style">
+ <xsl:attribute name="style:name">CreateDate<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'createdate']"/></xsl:attribute>
+ <xsl:call-template name="日期域"/>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:域开始[@字:类型 = 'savedate']">
+ <xsl:element name="number:date-style">
+ <xsl:attribute name="style:name">SaveDate<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'savedate']"/></xsl:attribute>
+ <xsl:call-template name="日期域"/>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:域开始[@字:类型 = 'time']">
+ <xsl:element name="number:date-style">
+ <xsl:attribute name="style:name">Time<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'time']"/></xsl:attribute>
+ <xsl:call-template name="时间域"/>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:域开始[@字:类型 = 'edittime']">
+ <xsl:element name="number:time-style">
+ <xsl:attribute name="style:name">EditTime<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'edittime']"/></xsl:attribute>
+ <xsl:call-template name="编辑时间"/>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:域开始[@字:类型 = 'createtime']">
+ <xsl:element name="number:time-style">
+ <xsl:attribute name="style:name">CREATETIME<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'createtime']"/></xsl:attribute>
+ <xsl:call-template name="创建时间"/>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:apply-templates select="/uof:UOF/uof:文字处理/字:主体//字:文字表[not(@字:类型='sub-table')]" mode="style"/>
+ <xsl:apply-templates select="/uof:UOF/uof:文字处理/字:主体//字:单元格" mode="style"/>
+ <xsl:apply-templates select="/uof:UOF/uof:文字处理/字:主体//字:行[not(../../@字:类型='sub-table')]" mode="style"/>
+ <xsl:apply-templates select="/uof:UOF/uof:文字处理/字:主体//字:列宽集[not(../../@字:类型='sub-table')]" mode="style"/>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:自动编号信息">
+ <xsl:variable name="currlistid" select="@字:编号引用"/>
+ <xsl:variable name="currlist" select="."/>
+ <xsl:variable name="rootlist" select="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号[@字:标识符 =$currlistid]"/>
+ <xsl:if test="not(ancestor::字:段落/preceding-sibling::字:段落[1]/字:段落属性/字:自动编号信息/@字:编号引用= $currlistid)">
+ <xsl:element name="text:list-style">
+ <xsl:attribute name="style:name">List<xsl:value-of select="count(preceding::字:自动编号信息)"/></xsl:attribute>
+ <xsl:for-each select="$rootlist">
+ <xsl:for-each select="字:级别">
+ <xsl:choose>
+ <xsl:when test="字:项目符号">
+ <xsl:call-template name="xiangmufuhao">
+ <xsl:with-param name="biaoshifu" select="../@字:标识符"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="字:图片符号引用">
+ <xsl:call-template name="imagefuhao">
+ <xsl:with-param name="biaoshifu" select="../@字:标识符"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="jibianhao">
+ <xsl:with-param name="biaoshifu" select="../@字:标识符"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:节属性">
+ <xsl:element name="style:page-layout">
+ <xsl:attribute name="style:name">pm<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any"/></xsl:attribute>
+ <xsl:if test="字:对称页边距/@字:值='true'">
+ <xsl:attribute name="style:page-usage">mirrored</xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:page-layout-properties">
+ <xsl:if test="字:纸张方向">
+ <xsl:attribute name="style:print-orientation"><xsl:choose><xsl:when test="字:纸张方向='portrait'">portrait</xsl:when><xsl:when test="字:纸张方向='landscape'">landscape</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="fo:page-width"><xsl:value-of select="concat(字:纸张/@uof:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:page-height"><xsl:value-of select="concat(字:纸张/@uof:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="字:页边距">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(字:页边距/@uof:上 ,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(字:页边距/@uof:左,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(字:页边距/@uof:右,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(字:页边距/@uof:下,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:装订线/@字:位置='top'">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(字:页边距/@uof:上 ,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(字:页边距/@uof:左,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(字:页边距/@uof:右,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:装订线/@字:位置='left' ">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(字:页边距/@uof:上,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat((字:页边距/@uof:左+ 字:装订线/@字:距边界),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(字:页边距/@uof:右,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(字:页边距/@uof:上,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(字:页边距/@uof:左,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(字:页边距/@uof:右,$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(字:页边距/@uof:下,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="字:拼页/@字:值='1' or 字:拼页/@字:值='true'">
+ <xsl:attribute name="style:page-usage">mirrored</xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="string(字:文字排列方向)='vert-r2l'">
+ <xsl:attribute name="style:writing-mode">tb-rl</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="string(字:文字排列方向)='vert-l2r'">
+ <xsl:attribute name="style:writing-mode">tb-rl</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="string(字:文字排列方向)='hori-l2r'">
+ <xsl:attribute name="style:writing-mode">lr-tb</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="string(字:文字排列方向)='hori-r2l'">
+ <xsl:attribute name="style:writing-mode">lr-tb</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:writing-mode">page</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="字:网格设置/@字:网格类型">
+ <xsl:attribute name="style:layout-grid-mode"><xsl:choose><xsl:when test="字:网格设置/@字:网格类型='line-char'">both-nosnap</xsl:when><xsl:when test="字:网格设置/@字:网格类型='char'">both</xsl:when><xsl:when test="字:网格设置/@字:网格类型='line'">line</xsl:when><xsl:when test="字:网格设置/@字:网格类型='none'">none</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:网格设置/@字:宽度">
+ <xsl:attribute name="style:layout-grid-base-width"><xsl:value-of select="concat(字:网格设置/@字:宽度,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:网格设置/@字:高度">
+ <xsl:attribute name="style:layout-grid-base-height"><xsl:value-of select="concat(字:网格设置/@字:高度,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:网格设置/@字:显示网格">
+ <xsl:attribute name="style:layout-grid-display"><xsl:value-of select="字:网格设置/@字:显示网格"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:网格设置/@字:打印网格">
+ <xsl:attribute name="style:layout-grid-print"><xsl:value-of select="字:网格设置/@字:打印网格"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:稿纸设置/@字:类型">
+ <xsl:attribute name="style:layout-grid-mode"><xsl:choose><xsl:when test="字:稿纸设置/@字:类型='draft-paper' ">both</xsl:when><xsl:when test="字:稿纸设置/@字:类型='letter-paper' ">line</xsl:when><xsl:otherwise>both</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:稿纸设置/@字:格式">
+ <xsl:choose>
+ <xsl:when test="字:稿纸设置/@字:格式='fourth-gear'">
+ <xsl:attribute name="style:layout-grid-base-width">0.728cm</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-base-height">0.728cm</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-ruby-height">0.496cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:稿纸设置/@字:格式='third-gear'">
+ <xsl:attribute name="style:layout-grid-base-width">0.584cm</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-base-height">0.584cm</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-ruby-height">0.64cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:稿纸设置/@字:格式='second-gear'">
+ <xsl:attribute name="style:layout-grid-base-width">0.728cm</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-base-height">0.728cm</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-ruby-height">0.905cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:稿纸设置/@字:格式='first-gear'">
+ <xsl:attribute name="style:layout-grid-base-width">0.728cm</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-base-height">0.728cm</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-ruby-height">1.633cm</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:attribute name="style:layout-grid-display">true</xsl:attribute>
+ <xsl:attribute name="style:layout-grid-print">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:稿纸设置/@字:颜色">
+ <xsl:attribute name="style:layout-grid-color"><xsl:value-of select="字:稿纸设置/@字:颜色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:边框">
+ <xsl:for-each select="字:边框">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="字:填充">
+ <xsl:for-each select="字:填充">
+ <xsl:call-template name="uof:填充"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:apply-templates select="字:填充"/>
+ <xsl:attribute name="style:num-format"><xsl:variable name="format"><xsl:value-of select="字:页码设置/@字:格式"/></xsl:variable><xsl:call-template name="oo数字格式"><xsl:with-param name="oo_format" select="$format"/></xsl:call-template></xsl:attribute>
+ <xsl:if test="字:纸张来源/@字:其他页">
+ <xsl:attribute name="style:paper-tray-name"><xsl:value-of select="字:纸张来源/@字:其他页"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:分栏/@字:栏数">
+ <xsl:apply-templates select="字:分栏"/>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="字:页眉位置">
+ <style:header-style>
+ <xsl:element name="style:header-footer-properties">
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(字:页眉位置/@字:距边界,$uofUnit)"/></xsl:attribute>
+ <xsl:variable name="long1" select="字:页眉位置/@字:距边界"/>
+ <xsl:variable name="long2" select="字:页眉位置/@字:距版芯"/>
+ <xsl:variable name="long" select="$long1 + $long2"/>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat($long,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="style:dynamic-spacing">false</xsl:attribute>
+ </xsl:element>
+ </style:header-style>
+ </xsl:if>
+ <xsl:if test="字:页脚位置">
+ <style:footer-style>
+ <xsl:element name="style:header-footer-properties">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(字:页脚位置/@字:距边界,$uofUnit)"/></xsl:attribute>
+ <xsl:variable name="long1" select="字:页脚位置/@字:距边界"/>
+ <xsl:variable name="long2" select="字:页脚位置/@字:距版芯"/>
+ <xsl:variable name="long" select="$long1 + $long2"/>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat($long,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="style:dynamic-spacing">false</xsl:attribute>
+ </xsl:element>
+ </style:footer-style>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="字:分栏/@字:栏数">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">sect<xsl:value-of select="count(preceding::字:节属性[字:分栏/@字:栏数])"/></xsl:attribute>
+ <xsl:attribute name="style:family">section</xsl:attribute>
+ <xsl:element name="style:page-layout-properties">
+ <xsl:element name="style:columns">
+ <xsl:attribute name="fo:column-count"><xsl:value-of select="number(字:分栏/@字:栏数)"/></xsl:attribute>
+ <xsl:attribute name="fo:column-gap"><xsl:value-of select="concat(number(字:分栏/@字:分割线宽度),$uofUnit)"/></xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象/@uof:公有类型='png' or /uof:UOF/uof:对象集/uof:其他对象/@uof:公有类型='jpg' or /uof:UOF/uof:对象集/uof:其他对象/@uof:公有类型='bmp' or /uof:UOF/uof:对象集/uof:其他对象/@uof:公有类型='gif' or /uof:UOF/uof:对象集/uof:其他对象/@uof:私有类型='图片'">
+ <style:style style:name="Graphics" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="none" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/>
+ </style:style>
+ </xsl:if>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形"/>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形/图:文本内容/字:段落/字:句/字:句属性" mode="style"/>
+ <xsl:call-template name="duanluoshuxing"/>
+ </xsl:element>
+ <office:master-styles>
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体//字:节属性">
+ <xsl:element name="style:master-page">
+ <xsl:variable name="master-page-name">
+ <xsl:number count="字:节属性" from="/uof:UOF/uof:文字处理/字:主体" level="any"/>
+ </xsl:variable>
+ <xsl:attribute name="style:name"><xsl:choose>
+ <xsl:when test="../@字:名称"><xsl:value-of select="../@字:名称"/></xsl:when>
+ <xsl:otherwise>Standard</xsl:otherwise>
+ </xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:page-layout-name"><xsl:value-of select="concat('pm', $master-page-name)"/></xsl:attribute>
+ <xsl:if test="following::字:节属性">
+ <xsl:attribute name="style:next-style-name">Standard<xsl:value-of select="$master-page-name +1"/></xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="字:页眉">
+ <xsl:if test="字:首页页眉 or 字:奇数页页眉">
+ <xsl:element name="style:header">
+ <xsl:apply-templates select="字:奇数页页眉/字:段落 | 字:首页页眉/字:段落 | 字:奇数页页眉/字:文字表 | 字:首页页眉/字:文字表"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="字:偶数页页眉">
+ <xsl:element name="style:header-left">
+ <xsl:apply-templates select="字:偶数页页眉/字:段落 | 字:偶数页页眉/字:文字表"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="字:页脚">
+ <xsl:if test="字:奇数页页脚 or 字:首页页脚">
+ <xsl:element name="style:footer">
+ <xsl:apply-templates select="字:奇数页页脚/字:段落 | 字:首页页脚/字:段落 | 字:奇数页页脚/字:文字表 | 字:首页页脚/字:文字表"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="字:偶数页页脚">
+ <xsl:element name="style:footer-left">
+ <xsl:apply-templates select="字:偶数页页脚/字:段落 | 字:偶数页页脚/字:文字表"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="字:奇偶页页眉页脚不同">
+ <xsl:element name="style:header-left">
+ </xsl:element>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </office:master-styles>
+ </xsl:template>
+ <xsl:template match="字:填充">
+ <xsl:choose>
+ <xsl:when test="图:颜色">
+ <xsl:attribute name="fo:background-color"><xsl:value-of select="图:颜色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:图案/@图:背景色">
+ <xsl:attribute name="style:text-background-color"><xsl:choose><xsl:when test="contains(图:图案/@图:背景色,'#')"><xsl:value-of select="图:图案/@图:背景色"/></xsl:when><xsl:otherwise>auto</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:图案/@图:前景色">
+ <xsl:attribute name="fo:text-background-color"><xsl:choose><xsl:when test="contains(图:图案/@图:前景色,'#')"><xsl:value-of select="图:图案/@图:前景色"/></xsl:when><xsl:otherwise>auto</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:分栏">
+ <xsl:element name="style:columns">
+ <xsl:attribute name="fo:column-count"><xsl:value-of select="//字:分栏/@字:栏数"/></xsl:attribute>
+ <xsl:variable name="aa">
+ <xsl:value-of select="//字:分栏/字:栏[position()=1]/@字:间距"/>
+ </xsl:variable>
+ <xsl:if test="//字:分栏/@字:等宽='true' ">
+ <xsl:attribute name="fo:column-gap"><xsl:value-of select="concat($aa * 2,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="//字:分栏/@字:分隔线宽度">
+ <xsl:element name="style:column-sep">
+ <xsl:attribute name="style:width"><xsl:value-of select="concat(@字:分隔线宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="style:color"><xsl:value-of select="@字:分隔线颜色"/></xsl:attribute>
+ <xsl:attribute name="style:height">100%</xsl:attribute>
+ <xsl:attribute name="style:vertical-align">top</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ <xsl:for-each select="//字:分栏/字:栏">
+ <xsl:element name="style:column">
+ <xsl:attribute name="style:rel-width"><xsl:value-of select="@字:宽度"/>*</xsl:attribute>
+ <xsl:if test="parent::字:分栏/@字:宽度='true'">
+ <xsl:choose>
+ <xsl:when test="self::node()[not(preceding-sibling::字:栏)]">
+ <xsl:attribute name="fo:start-indent">0cm</xsl:attribute>
+ <xsl:attribute name="fo:end-indent"><xsl:value-of select="concat(@字:间距,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="self::node()[not(following-sibling::字:栏)]">
+ <xsl:attribute name="fo:start-indent"><xsl:value-of select="concat(@字:间距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:end-indent">0cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:start-indent"><xsl:value-of select="concat(@字:间距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:end-indent"><xsl:value-of select="concat(@字:间距,$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="parent::字:分栏/@字:等宽='false'">
+ <xsl:variable name="last" select="preceding-sibling::字:栏[1]/@字:间距"/>
+ <xsl:choose>
+ <xsl:when test="self::node()[not(preceding-sibling::字:栏)]">
+ <xsl:attribute name="fo:start-indent">0cm</xsl:attribute>
+ <xsl:attribute name="fo:end-indent"><xsl:value-of select="concat(@字:间距,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="self::node()[not(following-sibling::字:栏)]">
+ <xsl:attribute name="fo:start-indent"><xsl:value-of select="concat($last,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:end-indent">0cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:start-indent"><xsl:value-of select="concat($last,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:end-indent"><xsl:value-of select="concat(@字:间距,$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="uof:文字表式样" mode="table">
+ <style:style style:family="table">
+ <xsl:attribute name="style:name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ <xsl:if test="@字:基式样引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:基式样引用"/></xsl:attribute>
+ </xsl:if>
+ <style:table-properties>
+ <xsl:choose>
+ <xsl:when test="字:对齐">
+ <xsl:attribute name="table:align"><xsl:value-of select="字:对齐"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:align">margins</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="字:宽度/@字:相对宽度">
+ <xsl:variable name="reltblw">
+ <xsl:value-of select="concat(number(字:宽度/@字:相对宽度),'%')"/>
+ </xsl:variable>
+ <xsl:variable name="pagew">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:纸张/@uof:宽度"/>
+ </xsl:variable>
+ <xsl:variable name="leftm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:左"/>
+ </xsl:variable>
+ <xsl:variable name="rightm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:右"/>
+ </xsl:variable>
+ <xsl:attribute name="style:rel-width"><xsl:value-of select="concat(number(字:宽度/@字:相对宽度) * 100,'%')"/></xsl:attribute>
+ <xsl:attribute name="style:width"><xsl:value-of select="concat((number($pagew)-number($leftm)-number($rightm)) * number($reltblw),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:宽度/@字:绝对宽度">
+ <xsl:attribute name="style:width"><xsl:value-of select="concat(number(字:宽度/@字:绝对宽度),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </style:table-properties>
+ </style:style>
+ </xsl:template>
+ <xsl:template match="字:文字表" mode="style">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">Table<xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/></xsl:attribute>
+ <xsl:attribute name="style:family">table</xsl:attribute>
+ <xsl:if test="@字:式样引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="name(preceding-sibling::*[1])='字:分节'">
+ <xsl:attribute name="style:master-page-name"><xsl:value-of select="preceding-sibling::*[1]/@字:名称"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:table-properties">
+ <xsl:for-each select="字:文字表属性">
+ <xsl:variable name="biaoshi" select="@字:式样引用"/>
+ <xsl:choose>
+ <xsl:when test="字:对齐 = 'left' or 字:对齐 = 'center' or 字:对齐 = 'right'">
+ <xsl:attribute name="table:align"><xsl:value-of select="字:对齐"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="/uof:UOF/uof:式样集/uof:文字表式样[@字:标识符=$biaoshi]/字:对齐">
+ <xsl:attribute name="table:align"><xsl:value-of select="/uof:UOF/uof:式样集/uof:文字表式样[@字:标识符=$biaoshi]/字:对齐"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:align">margins</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="字:左缩进">
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(number(字:左缩进),$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:绕排/@字:值='around'">
+ <xsl:if test="字:绕排边距/@字:上">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(字:绕排边距/@字:上,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:绕排边距/@字:左">
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(字:绕排边距/@字:左,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:绕排边距/@字:右">
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(字:绕排边距/@字:右,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:绕排边距/@字:下">
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(字:绕排边距/@字:下,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="@字:式样引用">
+ <xsl:variable name="rootStyle" select="@字:式样引用"/>
+ <xsl:variable name="rootStyleNode" select="/uof:UOF/uof:式样集/字:文字表式样[@字:基式样引用 = $rootStyle]"/>
+ <xsl:variable name="paddingleft">
+ <xsl:value-of select="$rootStyleNode/字:文字表属性/字:边距/@uof:左"/>
+ </xsl:variable>
+ <xsl:variable name="paddingright">
+ <xsl:value-of select="$rootStyleNode/字:文字表属性/字:边距/@uof:右"/>
+ </xsl:variable>
+ <xsl:variable name="paddingtop">
+ <xsl:value-of select="$rootStyleNode/字:文字表属性/字:边距/@uof:上"/>
+ </xsl:variable>
+ <xsl:variable name="paddingbottom">
+ <xsl:value-of select="$rootStyleNode/字:文字表属性/字:边距/@uof:下"/>
+ </xsl:variable>
+ <xsl:if test="$rootStyleNode/字:文字表属性/字:边距/@uof:左">
+ <xsl:attribute name="fo:margin-left">-<xsl:value-of select="(number($paddingleft))* $other-to-cm-conversion-factor"/>cm</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="字:宽度/@字:相对宽度">
+ <xsl:variable name="reltblw">
+ <xsl:value-of select="字:宽度/@字:相对宽度"/>
+ </xsl:variable>
+ <xsl:variable name="pagew">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:纸张/@uof:宽度"/>
+ </xsl:variable>
+ <xsl:variable name="leftm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:左"/>
+ </xsl:variable>
+ <xsl:variable name="rightm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:右"/>
+ </xsl:variable>
+ <xsl:attribute name="style:rel-width"><xsl:value-of select="concat(number(字:宽度/@字:相对宽度) * 100,'%')"/></xsl:attribute>
+ <xsl:attribute name="style:width"><xsl:value-of select="concat((number($pagew)-number($leftm)-number($rightm)) * number($reltblw),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:宽度/@字:绝对宽度">
+ <xsl:attribute name="style:width"><xsl:value-of select="concat(number(字:宽度/@字:绝对宽度),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="/uof:UOF/uof:式样集/uof:文字表式样[@字:标识符=$biaoshi]/字:宽度/@字:相对宽度 or /uof:UOF/uof:式样集/uof:文字表式样[@字:标识符=$biaoshi]/字:宽度/@字:绝对宽度">
+ <xsl:attribute name="style:rel-width"><xsl:value-of select="concat(/uof:UOF/uof:式样集/uof:文字表式样[@字:标识符=$biaoshi]/字:宽度/@字:相对宽度 * 100,'%')"/></xsl:attribute>
+ <xsl:attribute name="style:width"><xsl:value-of select="/uof:UOF/uof:式样集/uof:文字表式样[@字:标识符=$biaoshi]/字:宽度/@字:绝对宽度"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="pagew">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:纸张/@uof:宽度"/>
+ </xsl:variable>
+ <xsl:variable name="leftm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:左"/>
+ </xsl:variable>
+ <xsl:variable name="rightm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:右"/>
+ </xsl:variable>
+ <xsl:attribute name="style:width"><xsl:value-of select="concat((number($pagew)-number($leftm)-number($rightm)),$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:variable name="tblsize" select="sum(字:列宽集/字:列宽)"/>
+ <xsl:if test="(not($tblsize='0')) and not(字:宽度) ">
+ <xsl:choose>
+ <xsl:when test="字:左缩进">
+ <xsl:attribute name="style:width"><xsl:value-of select="concat( number($tblsize - 字:左缩进), $uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:width"><xsl:value-of select="concat( number(sum(字:列宽集/字:列宽) ), $uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="字:边框">
+ <xsl:for-each select="字:边框">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:for-each select="字:填充">
+ <xsl:call-template name="uof:填充"/>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:列宽集" mode="style">
+ <xsl:choose>
+ <xsl:when test="not(./字:列宽)">
+ <xsl:for-each select="../..">
+ <xsl:for-each select="字:行[1]/字:单元格">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:family">table-column</xsl:attribute>
+ <xsl:attribute name="style:name">Table<xsl:number count="字:文字表" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>.C<xsl:number value="count(preceding::字:单元格)+1"/></xsl:attribute>
+ <xsl:element name="style:table-column-properties">
+ <xsl:choose>
+ <xsl:when test="字:单元格属性/字:宽度/@字:相对值">
+ <xsl:variable name="tblw1">
+ <xsl:choose>
+ <xsl:when test="../../字:文字表属性/字:宽度/@字:绝对宽度">
+ <xsl:value-of select="../../字:文字表属性/字:宽度/@字:绝对宽度"/>
+ </xsl:when>
+ <xsl:when test="../../字:文字表属性/字:宽度/@字:相对宽度">
+ <xsl:variable name="pagew">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:纸张/@uof:宽度"/>
+ </xsl:variable>
+ <xsl:variable name="leftm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:左"/>
+ </xsl:variable>
+ <xsl:variable name="rightm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:右"/>
+ </xsl:variable>
+ <xsl:variable name="relw">
+ <xsl:value-of select="../../字:文字表属性/字:宽度/@字:相对宽度"/>
+ </xsl:variable>
+ <xsl:value-of select=" ( number($pagew)-number($leftm)-number($rightm))* number($relw) div 100"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="pagew">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:纸张/@uof:宽度"/>
+ </xsl:variable>
+ <xsl:variable name="leftm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:左"/>
+ </xsl:variable>
+ <xsl:variable name="rightm">
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页边距/@uof:右"/>
+ </xsl:variable>
+ <xsl:value-of select="(number($pagew)-number($leftm)-number($rightm))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:column-width"><xsl:value-of select="concat(number(number($tblw1)*number(字:单元格属性/字:宽度/@字:相对值) div 100),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:单元格属性/字:宽度/@字:绝对值">
+ <xsl:attribute name="style:column-width"><xsl:value-of select="concat(number(字:单元格属性/字:宽度/@字:绝对值),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:column-width"><xsl:value-of select="'1cm'"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="字:列宽">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:family">table-column</xsl:attribute>
+ <xsl:attribute name="style:name">Table<xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>.C<xsl:number count="字:列宽" from="/uof:UOF/uof:文字处理/字:主体" level="single" format="1"/></xsl:attribute>
+ <xsl:variable name="tableRoot" select="ancestor::字:文字表"/>
+ <xsl:element name="style:table-column-properties">
+ <xsl:choose>
+ <xsl:when test="string(.)">
+ <xsl:attribute name="style:column-width"><xsl:value-of select="concat(.,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:column-width"><xsl:value-of select="'1cm'"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:行" mode="style">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:family">table-row</xsl:attribute>
+ <xsl:attribute name="style:name">Table<xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>.R<xsl:number count="字:行" from="/uof:UOF/uof:文字处理/字:主体/字:文字表[not (@字:类型='sub-table')]" level="any" format="1"/></xsl:attribute>
+ <xsl:element name="style:table-row-properties">
+ <xsl:for-each select="字:表行属性">
+ <xsl:choose>
+ <xsl:when test="字:高度/@字:固定值">
+ <xsl:attribute name="style:row-height"><xsl:value-of select="concat(number(字:高度/@字:固定值),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:高度/@字:最小值">
+ <xsl:attribute name="style:min-row-height"><xsl:value-of select="concat(number(字:高度/@字:最小值), $uofUnit )"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:attribute name="fo:keep-together"><xsl:value-of select="字:跨页/@字:值"/></xsl:attribute>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:单元格" mode="style">
+ <style:style>
+ <xsl:attribute name="style:name">Table<xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>.R<xsl:number count="字:行" from="/uof:UOF/uof:文字处理/字:主体/字:文字表[not (@字:类型='sub-table')]" level="any" format="1"/>C<xsl:number count="字:单元格" from="/uof:UOF/uof:文字处理/字:主体/字:文字表[not (@字:类型='sub-table')]/字:行" level="any" format="1"/></xsl:attribute>
+ <xsl:attribute name="style:family">table-cell</xsl:attribute>
+ <xsl:element name="style:table-cell-properties">
+ <xsl:for-each select="字:单元格属性">
+ <xsl:choose>
+ <xsl:when test="字:单元格边距/@字:左">
+ <xsl:attribute name="fo:padding-left"><xsl:value-of select="concat(number(字:单元格边距/@字:左),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:padding-left"><xsl:value-of select="../../../../字:文字表属性/字:默认单元格边距/@字:左"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="字:单元格边距/@字:右">
+ <xsl:attribute name="fo:padding-right"><xsl:value-of select="concat(number(字:单元格边距/@字:右),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:padding-right"><xsl:value-of select="../../../../字:文字表属性/字:默认单元格边距/@字:右"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="字:单元格边距/@字:上">
+ <xsl:attribute name="fo:padding-top"><xsl:value-of select="concat(number(字:单元格边距/@字:上),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:padding-top"><xsl:value-of select="../../../../字:文字表属性/字:默认单元格边距/@字:上"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="字:单元格边距/@字:下">
+ <xsl:attribute name="fo:padding-bottom"><xsl:value-of select="concat(number(字:单元格边距/@字:下),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:padding-bottom"><xsl:value-of select="../../../../字:文字表属性/字:默认单元格边距/@字:下"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:variable name="cellbefore">
+ <xsl:value-of select="count(ancestor::字:单元格/preceding-sibling::字:单元格)"/>
+ </xsl:variable>
+ <xsl:variable name="cellafter">
+ <xsl:value-of select="count(ancestor::字:单元格/following-sibling::字:单元格)"/>
+ </xsl:variable>
+ <xsl:variable name="rowbefore">
+ <xsl:value-of select="count(ancestor::字:行/preceding-sibling::字:行)"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="字:边框">
+ <xsl:for-each select="字:边框">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="number($cellafter) &gt; 0">
+ <xsl:attribute name="fo:border-right">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:border-right">0.002cm solid #000000</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:border-left">0.002cm solid #000000</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="number($rowbefore) &gt; 0">
+ <xsl:attribute name="fo:border-top">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:border-top">0.002cm solid #000000</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:border-bottom">0.002cm solid #000000</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="style:vertical-align"><xsl:choose><xsl:when test="字:垂直对齐方式='center' ">middle</xsl:when><xsl:when test="字:垂直对齐方式='bottom' ">bottom</xsl:when><xsl:otherwise>top</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:for-each select="字:填充">
+ <xsl:call-template name="uof:填充"/>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:element>
+ </style:style>
+ </xsl:template>
+ <xsl:template match="uof:字体集">
+ <xsl:element name="office:font-face-decls">
+ <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Symbol" svg:font-family="Symbol" style:font-family-generic="roman" style:font-pitch="variable" style:font-charset="x-symbol"/>
+ <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/>
+ <xsl:if test="not(uof:字体声明[@uof:名称='StarSymbol'])">
+ <style:font-face style:name="StarSymbol" svg:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </xsl:if>
+ <xsl:for-each select="uof:字体声明">
+ <xsl:element name="style:font-face">
+ <xsl:attribute name="style:name"><xsl:value-of select="@uof:标识符"/></xsl:attribute>
+ <xsl:attribute name="svg:font-family"><xsl:value-of select="@uof:名称"/></xsl:attribute>
+ <xsl:if test="@uof:字符集 = '02'">
+ <xsl:attribute name="style:font-charset">x-symbol</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@uof:字体族">
+ <xsl:choose>
+ <xsl:when test="@uof:字体族 = 'Swiss'">
+ <xsl:attribute name="style:font-family-generic">swiss</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Modern'">
+ <xsl:attribute name="style:font-family-generic">modern</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族='Roman'">
+ <xsl:attribute name="style:font-family-generic">roman</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Script'">
+ <xsl:attribute name="style:font-family-generic">script</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='Decorative'">
+ <xsl:attribute name="style:font-family-generic">decorative</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:字体族 ='System'">
+ <xsl:attribute name="style:font-family-generic">system</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:font-family-generic">system</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:attribute name="style:font-pitch">12</xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ <xsl:apply-templates select="uof:字体声明"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="uof:式样">
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="uof:句式样/*"/>
+ <xsl:apply-templates select="uof:段落式样/*"/>
+ <xsl:call-template name="paragraph-properties"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="uof:段落式样"/>
+ <xsl:template match="uof:句式样"/>
+ <xsl:template match="字:公用处理规则">
+ <xsl:apply-templates select="uof:文字处理/字:公用处理规则/字:文档设置"/>
+ </xsl:template>
+ <xsl:template match="uof:文字处理/字:公用处理规则/字:文档设置">
+ <office:settings>
+ <config:config-item-set config:name="ooo:view-settings">
+ <config:config-item config:name="InBrowseMode" config:type="boolean">
+ <xsl:choose>
+ <xsl:when test="字:当前视图='web'">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <xsl:if test="字:缩放">
+ <config:config-item config:name="VisibleRight" config:type="int">1</config:config-item>
+ <config:config-item config:name="VisibleBottom" config:type="int">1</config:config-item>
+ <xsl:choose>
+ <xsl:when test="字:缩放 = 'best-fit'">
+ <config:config-item config:name="ZoomType" config:type="short">3</config:config-item>
+ </xsl:when>
+ <xsl:when test="字:缩放 = 'full-page'">
+ <config:config-item config:name="ZoomType" config:type="short">2</config:config-item>
+ </xsl:when>
+ <xsl:when test="字:缩放 = 'text-fit'">
+ <config:config-item config:name="ZoomType" config:type="short">1</config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <config:config-item config:name="ZoomFactor" config:type="short">
+ <xsl:value-of select="字:缩放"/>
+ </config:config-item>
+ </xsl:if>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ <config:config-item-set config:name="configuration-settings">
+ <config:config-item-map-indexed config:name="ForbiddenCharacters">
+ <config:config-item-map-entry>
+ <config:config-item config:name="Language" config:type="string">zh</config:config-item>
+ <config:config-item config:name="Country" config:type="string">CN</config:config-item>
+ <config:config-item config:name="Variant" config:type="string"/>
+ <config:config-item config:name="BeginLine" config:type="string">
+ <xsl:choose>
+ <xsl:when test="字:标点禁则/字:行首字符 or *[@uof:locID='t0007']/*[@uof:locID='t0008']">
+ <xsl:value-of select="*[@uof:locID='t0007']/*[@uof:locID='t0008']"/>
+ </xsl:when>
+ <xsl:otherwise>:!),.:;?]}_'"、。〉》」』】〕〗〞︰︱︳﹐_﹒﹔﹕﹖﹗﹚﹜﹞!),.:;?|}︴︶︸︺︼︾﹀﹂﹄﹏_~¢々‖_·ˇˉ―--′</xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ <config:config-item config:name="EndLine" config:type="string">
+ <xsl:choose>
+ <xsl:when test="字:标点禁则/字:行尾字符 or *[@uof:locID='t0007']/*[@uof:locID='t0009']">
+ <xsl:value-of select="*[@uof:locID='t0007']/*[@uof:locID='t0009']"/>
+ </xsl:when>
+ <xsl:otherwise>([{__'"‵〈《「『【〔〖([{£¥〝︵︷︹︻︽︿﹁﹃﹙﹛﹝({</xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ </office:settings>
+ </xsl:template>
+ <xsl:template match="uof:文字处理">
+ <xsl:element name="office:body">
+ <xsl:element name="office:text">
+ <xsl:call-template name="GenerateTrackChanges"/>
+ <text:sequence-decls>
+ <xsl:call-template name="default_sequence_declaration"/>
+ </text:sequence-decls>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="default_sequence_declaration">
+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration">
+ </text:sequence-decl>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table">
+ </text:sequence-decl>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text">
+ </text:sequence-decl>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing">
+ </text:sequence-decl>
+ <text:sequence-decl text:display-outline-level="0" text:name="AutoNr">
+ </text:sequence-decl>
+ </xsl:template>
+ <xsl:template name="段落" match="字:段落[not((preceding-sibling::字:段落/字:域开始) and (not(preceding-sibling::字:段落/字:域结束)))][not(字:段落属性[字:自动编号信息])]">
+ <xsl:if test="字:域开始/@字:类型='caption'">
+ <xsl:apply-templates select="字:域代码"/>
+ </xsl:if>
+ <xsl:if test="字:域开始/@字:类型='REF'">
+ <xsl:call-template name="目录域"/>
+ </xsl:if>
+ <xsl:if test="字:域开始/@字:类型='INDEX'">
+ <xsl:call-template name="索引域"/>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="string(parent::node()/@uof:locID)='t0107'">
+ <xsl:apply-templates select="字:脚注"/>
+ </xsl:when>
+ <xsl:when test="string(parent::node()/@uof:locID)='t0108'">
+ <xsl:apply-templates select="字:尾注"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:脚注">
+ <xsl:element name="text:note">
+ <xsl:attribute name="text:note-class">footnote</xsl:attribute>
+ <xsl:element name="text:note-citation">
+ <xsl:attribute name="text:label"><xsl:value-of select="@字:引文体"/></xsl:attribute>
+ <xsl:value-of select="@字:引文体"/>
+ </xsl:element>
+ <xsl:element name="text:note-body">
+ <xsl:for-each select="字:段落">
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:尾注">
+ <xsl:element name="text:note">
+ <xsl:attribute name="text:note-class">endnote</xsl:attribute>
+ <xsl:element name="text:note-citation">
+ <xsl:attribute name="text:label"><xsl:value-of select="@字:引文体"/></xsl:attribute>
+ <xsl:value-of select="@字:引文体"/>
+ </xsl:element>
+ <xsl:element name="text:note-body">
+ <xsl:for-each select="字:段落">
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:锚点">
+ <xsl:call-template name="图形解析"/>
+ </xsl:template>
+ <xsl:key match="/uof:UOF/uof:文字处理/字:主体/字:段落/字:句/字:锚点 | /uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页眉//字:锚点 | /uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:页脚//字:锚点" name="rel_graphic_name" use="字:图形/@字:图形引用"/>
+ <xsl:template match="图:图形">
+ <xsl:variable name="random-name">
+ <xsl:value-of select="generate-id()"/>
+ </xsl:variable>
+ <xsl:variable name="draw-name">
+ <xsl:value-of select="substring($random-name,string-length($random-name)-1)"/>
+ </xsl:variable>
+ <xsl:call-template name="graphic-fill">
+ <xsl:with-param name="draw-name" select="$draw-name"/>
+ <xsl:with-param name="gradient-name" select="图:预定义图形/图:属性/图:填充/图:渐变"/>
+ </xsl:call-template>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:渐变 | 图:预定义图形/图:属性/图:填充/图:颜色 | 图:预定义图形/图:属性/图:填充/图:图片 | 图:预定义图形/图:属性/图:填充/图:位图">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family">graphic</xsl:attribute>
+ <xsl:if test="图:文本内容/@图:自动换行='true' or 图:文本内容/@图:自动换行='1'">
+ <xsl:attribute name="draw:fit-to-contour">true</xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:graphic-properties">
+ <xsl:call-template name="process-graphics">
+ <xsl:with-param name="draw-name" select="$draw-name"/>
+ </xsl:call-template>
+ </xsl:element>
+ <xsl:if test="图:文本内容/@图:文字排列方向">
+ <xsl:choose>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-l2r'">
+ <style:paragraph-properties style:writing-mode="tb-rl"/>
+ </xsl:when>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-r2l'">
+ <style:paragraph-properties style:writing-mode="tb-rl"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family">graphic</xsl:attribute>
+ <xsl:element name="style:graphic-properties">
+ <xsl:if test="@图:其他对象 or key('rel_graphic_name',@图:标识符)/字:锚点属性/字:锚点属性/字:位置/字:垂直/字:相对/@字:相对于">
+ <xsl:attribute name="fo:clip">rect(0cm 0cm 0cm 0cm)</xsl:attribute>
+ <xsl:attribute name="draw:color-mode">standard</xsl:attribute>
+ <xsl:attribute name="draw:luminance">0%</xsl:attribute>
+ <xsl:attribute name="draw:contrast">0%</xsl:attribute>
+ <xsl:attribute name="draw:gamma">100%</xsl:attribute>
+ <xsl:attribute name="draw:red">0%</xsl:attribute>
+ <xsl:attribute name="draw:green">0%</xsl:attribute>
+ <xsl:attribute name="draw:blue">0%</xsl:attribute>
+ <xsl:attribute name="draw:image-opacity">100%</xsl:attribute>
+ <xsl:attribute name="style:mirror">none</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="process-graphics"/>
+ </xsl:element>
+ <xsl:if test="图:文本内容/@图:文字排列方向">
+ <xsl:choose>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-l2r'">
+ <style:paragraph-properties style:writing-mode="tb-rl"/>
+ </xsl:when>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-r2l'">
+ <style:paragraph-properties style:writing-mode="tb-rl"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="bina_graphic">
+ <xsl:param name="refGraphic"/>
+ <xsl:element name="office:binary-data">
+ <xsl:for-each select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符 = $refGraphic]">
+ <xsl:value-of select="uof:数据"/>
+ </xsl:for-each>
+ </xsl:element>
+ <text:p/>
+ </xsl:template>
+ <xsl:template name="graphic-fill">
+ <xsl:param name="draw-name"/>
+ <xsl:param name="gradient-name"/>
+ <xsl:if test="图:预定义图形/图:属性/图:填充/图:渐变">
+ <xsl:element name="draw:gradient">
+ <xsl:attribute name="draw:name"><xsl:value-of select="concat('Gradient ',$draw-name)"/></xsl:attribute>
+ <xsl:attribute name="draw:style"><xsl:choose><xsl:when test="$gradient-name/@图:种子类型='linear'"><xsl:value-of select="'linear'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='radar'"><xsl:value-of select="'radial'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='oval'"><xsl:value-of select="'ellipsoid'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='square'"><xsl:value-of select="'square'"/></xsl:when><xsl:when test="$gradient-name/@图:种子类型='rectangle'"><xsl:value-of select="'rectangular'"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="draw:start-color"><xsl:value-of select="$gradient-name/@图:起始色"/></xsl:attribute>
+ <xsl:attribute name="draw:end-color"><xsl:value-of select="$gradient-name/@图:终止色"/></xsl:attribute>
+ <xsl:attribute name="draw:start-intensity"><xsl:value-of select="concat($gradient-name/@图:起始浓度,'%')"/></xsl:attribute>
+ <xsl:attribute name="draw:end-intensity"><xsl:value-of select="concat($gradient-name/@图:终止浓度,'%')"/></xsl:attribute>
+ <xsl:attribute name="draw:angle"><xsl:value-of select="$gradient-name/@图:渐变方向 * 10"/></xsl:attribute>
+ <xsl:attribute name="draw:border"><xsl:value-of select="concat($gradient-name/@图:边界,'%')"/></xsl:attribute>
+ <xsl:if test="$gradient-name/@图:种子X位置">
+ <xsl:attribute name="draw:cx"><xsl:value-of select="concat($gradient-name/@图:种子X位置,'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$gradient-name/@图:种子Y位置">
+ <xsl:attribute name="draw:cy"><xsl:value-of select="concat($gradient-name/@图:种子Y位置,'%')"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头">
+ <xsl:element name="draw:marker">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">Line Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">Arrow concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">Square 45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">
+ <xsl:attribute name="svg:viewBox">0 0 20 30</xsl:attribute>
+ <xsl:attribute name="svg:d">m10 0-10 30h20z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">
+ <xsl:attribute name="svg:viewBox">0 0 1122 2243</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1580</xsl:attribute>
+ <xsl:attribute name="svg:d">m1013 1491 118 89-567-1580-564 1580 114-85 136-68 148-46 161-17 161 13 153 46z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m462 1118-102-29-102-51-93-72-72-93-51-102-29-102-13-105 13-102 29-106 51-102 72-89 93-72 102-50 102-34 106-9 101 9 106 34 98 50 93 72 72 89 51 102 29 106 13 102-13 105-29 102-51 102-72 93-93 72-98 51-106 29-101 13z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 564 564 567 567-567-567-564z</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头">
+ <xsl:element name="draw:marker">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">Line Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">Arrow concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">Square 45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">
+ <xsl:attribute name="svg:viewBox">0 0 20 30</xsl:attribute>
+ <xsl:attribute name="svg:d">m10 0-10 30h20z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">
+ <xsl:attribute name="svg:viewBox">0 0 1122 2243</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1580</xsl:attribute>
+ <xsl:attribute name="svg:d">m1013 1491 118 89-567-1580-564 1580 114-85 136-68 148-46 161-17 161 13 153 46z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m462 1118-102-29-102-51-93-72-72-93-51-102-29-102-13-105 13-102 29-106 51-102 72-89 93-72 102-50 102-34 106-9 101 9 106 34 98 50 93 72 72 89 51 102 29 106 13 102-13 105-29 102-51 102-72 93-93 72-98 51-106 29-101 13z</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">
+ <xsl:attribute name="svg:viewBox">0 0 1131 1131</xsl:attribute>
+ <xsl:attribute name="svg:d">m0 564 564 567 567-567-567-564z</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用 or 图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用">
+ <xsl:element name="draw:fill-image">
+ <xsl:attribute name="draw:name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:类型"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"/></xsl:when></xsl:choose></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:call-template name="bina_graphic">
+ <xsl:with-param name="refGraphic">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用">
+ <xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:图形引用"/>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:名称">
+ <xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"/>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用">
+ <xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="not(图:预定义图形/图:属性/图:线型='single') and not(图:预定义图形/图:属性/图:线型='thick') and 图:预定义图形/图:属性/图:线型">
+ <xsl:variable name="line" select="图:预定义图形/图:属性/图:线型"/>
+ <xsl:element name="draw:stroke-dash">
+ <xsl:choose>
+ <xsl:when test="$line='dash-long' or $line='dash-long-heavy'">
+ <xsl:attribute name="draw:name">Fine_20_Dashed</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">0.508cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">1</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.508cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.508cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='dot-dot-dash' or $line='dash-dot-dot-heavy'">
+ <xsl:attribute name="draw:name">2 Dots 1 Dash</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">2</xsl:attribute>
+ <xsl:attribute name="draw:dots2">1</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.203cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.203cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='dash' or $line='dashed-heavy'">
+ <xsl:attribute name="draw:name">Ultrafine Dashed</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">0.051cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">1</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.051cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.051cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='dotted' or $line='dotted-heavy'">
+ <xsl:attribute name="draw:name">Ultrafine Dotted (var)</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:distance">50%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='wave' or $line='wavy-heavy'">
+ <xsl:attribute name="draw:name">Ultrafine 2 Dots 3 Dashes</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">2</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">0.051cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">3</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.254cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.127cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='dot-dash' or $line='dash-dot-heavy'">
+ <xsl:attribute name="draw:name">3 Dashes 3 Dots (var)</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">3</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">197%</xsl:attribute>
+ <xsl:attribute name="draw:dots2">3</xsl:attribute>
+ <xsl:attribute name="draw:distance">100%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='double'">
+ <xsl:attribute name="draw:name">Line with Fine Dots</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">2.007cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">10</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.152cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$line='wavy-double'">
+ <xsl:attribute name="draw:name">Fine Dashed (var)</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">197%</xsl:attribute>
+ <xsl:attribute name="draw:distance">197%</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="draw:name">Fine Dashed</xsl:attribute>
+ <xsl:attribute name="draw:style">rect</xsl:attribute>
+ <xsl:attribute name="draw:dots1">1</xsl:attribute>
+ <xsl:attribute name="draw:dots1-length">0.508cm</xsl:attribute>
+ <xsl:attribute name="draw:dots2">1</xsl:attribute>
+ <xsl:attribute name="draw:dots2-length">0.508cm</xsl:attribute>
+ <xsl:attribute name="draw:distance">0.508cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="process-graphics">
+ <xsl:param name="draw-name"/>
+ <xsl:if test="图:预定义图形/图:类别">
+ </xsl:if>
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)/字:锚点属性/字:位置/字:垂直">
+ <xsl:attribute name="style:vertical-pos"><xsl:choose><xsl:when test="字:绝对">from-top</xsl:when><xsl:when test="字:相对/@字:值='bottom'">bottom</xsl:when><xsl:when test="字:相对/@字:值='center'">middle</xsl:when><xsl:when test="字:相对/@字:值='inside'">below</xsl:when><xsl:otherwise>top</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:vertical-rel"><xsl:choose><xsl:when test="@字:相对于='margin'">paragraph-content</xsl:when><xsl:otherwise><xsl:value-of select="@字:相对于"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)/字:锚点属性/字:位置/字:水平">
+ <xsl:attribute name="style:horizontal-pos"><xsl:choose><xsl:when test="字:绝对">from-left</xsl:when><xsl:otherwise><xsl:value-of select="字:相对/@字:值"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:horizontal-rel"><xsl:choose><xsl:when test="@字:相对于='margin'">paragraph</xsl:when><xsl:when test="@字:相对于='page'">page</xsl:when><xsl:when test="@字:相对于='column'">paragraph</xsl:when><xsl:when test="@字:相对于='char'">char</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ <xsl:variable name="wrap_type">
+ <xsl:value-of select="key('rel_graphic_name',@图:标识符)/字:锚点属性/字:绕排/@字:绕排方式"/>
+ </xsl:variable>
+ <xsl:variable name="aa">
+ <xsl:value-of select="key('rel_graphic_name',@图:标识符)/字:锚点属性/字:绕排/@字:绕排顶点"/>
+ </xsl:variable>
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)/字:锚点属性/字:绕排/@字:绕排方式">
+ <xsl:attribute name="style:wrap"><xsl:choose><xsl:when test="$wrap_type = 'through'">run-through</xsl:when><xsl:when test="$wrap_type = 'tight'">right</xsl:when><xsl:when test="$wrap_type = 'square'">parallel</xsl:when><xsl:when test="$wrap_type = 'top-bottom'">dynamic</xsl:when><xsl:when test="$wrap_type = 'infrontoftext'">run-through</xsl:when><xsl:when test="$wrap_type = 'behindtext'">run-through</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:run-through"><xsl:choose><xsl:when test="$wrap_type = 'behindtext'">background</xsl:when><xsl:otherwise>foreground</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:for-each>
+ <xsl:if test="key('rel_graphic_name',@图:标识符)/字:锚点属性/字:边距">
+ <xsl:for-each select="key('rel_graphic_name',@图:标识符)/字:锚点属性/字:边距">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(@字:上,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(@字:下,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(@字:右,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(@字:左,$uofUnit)"/></xsl:attribute>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="key('rel_graphic_name',@图:标识符)/字:锚点属性/字:保护/@字:值='true'">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:名称">
+ <xsl:attribute name="style:protect">position size</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:protect">content size position</xsl:attribute>
+ <xsl:attribute name="draw:size-protect">true</xsl:attribute>
+ <xsl:attribute name="draw:move-protect">true</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:名称">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:名称='椭圆'">
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="not(图:预定义图形/图:属性/图:填充)">
+ <xsl:attribute name="draw:fill">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图片">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:名称='background-image'">
+ <xsl:element name="style:background-image">
+ <xsl:element name="office:binary-data">
+ <xsl:variable name="biaoshi">
+ <xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"/>
+ </xsl:variable>
+ <xsl:value-of select="ancestor::uof:对象集/uof:其他对象[@uof:标识符=$biaoshi]/uof:数据"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-image-name"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:名称"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图片/@图:图形引用"/></xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="not(图:预定义图形/图:属性/图:填充/图:图片/@图:位置='tile')">
+ <xsl:attribute name="style:repeat"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:位置='center'">no-repeat</xsl:when><xsl:when test="图:预定义图形/图:属性/图:填充/图:图片/@图:位置='stretch'">stretch</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:图案">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:图案/@图:前景色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:颜色">
+ <xsl:attribute name="draw:fill">solid</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:颜色"/></xsl:attribute>
+ <xsl:attribute name="fo:background-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:颜色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:预定义图形/图:属性/图:填充/图:渐变">
+ <xsl:attribute name="draw:fill">gradient</xsl:attribute>
+ <xsl:attribute name="draw:fill-color"><xsl:value-of select="图:预定义图形/图:属性/图:填充/图:渐变/@图:起始色"/></xsl:attribute>
+ <xsl:attribute name="draw:fill-gradient-name"><xsl:value-of select="concat('Gradient ',$draw-name)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="图:预定义图形/图:属性/图:线颜色">
+ <xsl:attribute name="svg:stroke-color"><xsl:value-of select="图:预定义图形/图:属性/图:线颜色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:线型 and not(图:预定义图形/图:属性/图:线型 = 'single') and not(图:预定义图形/图:属性/图:线型 = 'thick')">
+ <xsl:variable name="linetype" select="图:预定义图形/图:属性/图:线型"/>
+ <xsl:attribute name="draw:stroke"><xsl:choose><xsl:when test="$linetype='none'">none</xsl:when><xsl:otherwise>dash</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="$linetype='none'">
+ <xsl:attribute name="fo:border">none</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:stroke-dash"><xsl:choose><xsl:when test="$linetype='dot-dot-dash' or $linetype='dash-dot-dot-heavy'">2 Dots 1 Dash</xsl:when><xsl:when test="$linetype='dash' or $linetype='dashed-heavy'">Ultrafine_20_Dashed</xsl:when><xsl:when test="$linetype='dotted' or $linetype='dotted-heavy'">Ultrafine Dotted (var)</xsl:when><xsl:when test="$linetype='double'">Line with Fine Dots</xsl:when><xsl:when test="$linetype='dot-dash' or $linetype='dash-dot-heavy'">3 Dashes 3 Dots (var)</xsl:when><xsl:when test="$linetype='wave' or $linetype='wavy-heavy'">Ultrafine 2 Dots 3 Dashes</xsl:when><xsl:when test="$linetype='wavy-double'">Fine Dashed (var)</xsl:when><xsl:otherwise>Fine Dashed</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:线粗细">
+ <xsl:attribute name="svg:stroke-width"><xsl:value-of select="concat(图:预定义图形/图:属性/图:线粗细,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头">
+ <xsl:attribute name="draw:marker-start"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='open'">Line Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='stealth'">Arrow concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:式样='diamond'">Square 45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:前端箭头/图:大小">
+ <xsl:attribute name="draw:marker-start-width"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '1'"><xsl:value-of select="concat('0.05',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '2'"><xsl:value-of select="concat('0.10',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '3'"><xsl:value-of select="concat('0.15',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '4'"><xsl:value-of select="concat('0.20',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '5'"><xsl:value-of select="concat('0.25',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '6'"><xsl:value-of select="concat('0.30',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '7'"><xsl:value-of select="concat('0.35',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:前端箭头/图:大小 = '8'"><xsl:value-of select="concat('0.40',$uofUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('0.45',$uofUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头">
+ <xsl:attribute name="draw:marker-end"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='normal'">Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='open'">Line Arrow</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='stealth'">Arrow concave</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='oval'">Circle</xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:式样='diamond'">Square 45</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:后端箭头/图:大小">
+ <xsl:attribute name="draw:marker-end-width"><xsl:choose><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '1'"><xsl:value-of select="concat('0.05',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '2'"><xsl:value-of select="concat('0.10',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '3'"><xsl:value-of select="concat('0.15',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '4'"><xsl:value-of select="concat('0.20',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '5'"><xsl:value-of select="concat('0.25',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '6'"><xsl:value-of select="concat('0.30',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '7'"><xsl:value-of select="concat('0.35',$uofUnit)"/></xsl:when><xsl:when test="图:预定义图形/图:属性/图:后端箭头/图:大小 = '8'"><xsl:value-of select="concat('0.40',$uofUnit)"/></xsl:when><xsl:otherwise><xsl:value-of select="concat('0.45',$uofUnit)"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:宽度">
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:高度">
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度">
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:锁定纵横比">
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:打印对象">
+ </xsl:if>
+ <xsl:if test="图:预定义图形/图:属性/图:透明度">
+ <xsl:attribute name="draw:opacity"><xsl:value-of select="concat((100 - 图:预定义图形/图:属性/图:透明度),'%')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:if test="图:文本内容/@图:上边距">
+ <xsl:attribute name="fo:padding-top"><xsl:value-of select="concat(图:文本内容/@图:上边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-bottom"><xsl:value-of select="concat(图:文本内容/@图:下边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-left"><xsl:value-of select="concat(图:文本内容/@图:左边距,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:padding-right"><xsl:value-of select="concat(图:文本内容/@图:右边距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容/@图:文字排列方向">
+ <xsl:choose>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-l2r'">
+ <xsl:attribute name="style:writing-mode">tb-rl</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:文本内容/@图:文字排列方向='vert-r2l'">
+ <xsl:attribute name="style:writing-mode">tb-rl</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="图:文本内容/@图:水平对齐">
+ <xsl:attribute name="draw:textarea-horizontal-align"><xsl:value-of select="图:文本内容/@图:水平对齐"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容/@图:垂直对齐">
+ <xsl:attribute name="draw:textarea-vertical-align"><xsl:value-of select="图:文本内容/@图:垂直对齐"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容/@图:自动换行">
+ <xsl:attribute name="fo:wrap-option"><xsl:choose><xsl:when test="图:文本内容/@图:自动换行='1' or 图:文本内容/@图:自动换行='true'">wrap</xsl:when><xsl:otherwise>no-wrap</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="图:文本内容/@图:大小适应文字='true'">
+ <xsl:attribute name="draw:auto-grow-width">true</xsl:attribute>
+ <xsl:attribute name="draw:auto-grow-height">true</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="draw:auto-grow-width">false</xsl:attribute>
+ <xsl:attribute name="draw:auto-grow-height">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="图:控制点">
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="图形解析">
+ <xsl:variable name="tuxing1" select="字:图形/@字:图形引用"/>
+ <xsl:variable name="paiban">
+ <xsl:value-of select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:预定义图形/图:名称"/>
+ </xsl:variable>
+ <xsl:variable name="otherobject">
+ <xsl:value-of select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/@图:其他对象"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]">
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='png' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='jpg' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='bmp' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:公共类型='gif' or /uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/@uof:私有类型='图片'">
+ <xsl:element name="draw:frame">
+ <xsl:attribute name="draw:name"><xsl:variable name="pos"><xsl:value-of select="count(preceding::字:锚点)"/></xsl:variable><xsl:value-of select="concat('图形',$pos)"/></xsl:attribute>
+ <xsl:if test="字:锚点属性/字:位置/字:水平/字:绝对">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(字:锚点属性/字:位置/字:水平/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:锚点属性/字:位置/字:垂直/字:绝对">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(字:锚点属性/字:位置/字:垂直/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(字:锚点属性/字:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(字:锚点属性/字:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="text:anchor-type"><xsl:choose><xsl:when test="@字:类型='inline'">as-char</xsl:when><xsl:otherwise>paragraph</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="jiaodu">
+ <xsl:value-of select="图:预定义图形/图:属性/图:旋转角度"/>
+ </xsl:variable>
+ <xsl:variable name="shibie">
+ <xsl:value-of select="图:预定义图形/图:生成软件"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-angle">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:生成软件 and not($shibie='PNG')">
+ <xsl:value-of select="((360 - $jiaodu) * 2 * 3.14159265 ) div 360"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:数据">
+ <draw:image>
+ <office:binary-data>
+ <xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:数据"/>
+ </office:binary-data>
+ </draw:image>
+ </xsl:if>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径">
+ <xsl:attribute name="xlink:href"><xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]/@图:其他对象 and /uof:UOF/uof:对象集/uof:其他对象/@uof:公共类型='jpg'">
+ <xsl:variable name="bshi">
+ <xsl:value-of select="/uof:UOF/uof:对象集/图:图形/@图:其他对象"/>
+ </xsl:variable>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$bshi]/@uof:公共类型='jpg'">
+ <xsl:element name="draw:frame">
+ <xsl:attribute name="draw:name"><xsl:variable name="pos"><xsl:value-of select="count(preceding::字:锚点)"/></xsl:variable><xsl:value-of select="concat('图形',$pos)"/></xsl:attribute>
+ <xsl:if test="字:锚点属性/字:位置/字:水平/字:绝对">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(字:锚点属性/字:位置/字:水平/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:锚点属性/字:位置/字:垂直/字:绝对">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(字:锚点属性/字:位置/字:垂直/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(字:锚点属性/字:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(字:锚点属性/字:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="text:anchor-type"><xsl:choose><xsl:when test="@字:类型='inline'">as-char</xsl:when><xsl:otherwise>paragraph</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="jiaodu">
+ <xsl:value-of select="图:预定义图形/图:属性/图:旋转角度"/>
+ </xsl:variable>
+ <xsl:variable name="shibie">
+ <xsl:value-of select="图:预定义图形/图:生成软件"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-angle">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:生成软件 and not($shibie='PNG')">
+ <xsl:value-of select="((360 - $jiaodu) * 2 * 3.14159265 ) div 360"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ <xsl:variable name="qita">
+ <xsl:value-of select="self::node()/@图:其他对象"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$qita]/uof:数据">
+ <draw:image>
+ <office:binary-data>
+ <xsl:value-of select="."/>
+ </office:binary-data>
+ </draw:image>
+ </xsl:for-each>
+ </xsl:for-each>
+ <xsl:if test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径">
+ <xsl:attribute name="xlink:href"><xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$tuxing1]/uof:路径"/></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:文本内容[@图:文本框='true'] and not($paiban='排版框')">
+ <draw:frame text:anchor-type="paragraph">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="$tuxing1"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(字:锚点属性/字:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(字:锚点属性/字:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="字:锚点属性/字:位置/字:水平/字:绝对">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(字:锚点属性/字:位置/字:水平/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:锚点属性/字:位置/字:垂直/字:绝对">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(字:锚点属性/字:位置/字:垂直/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:z-index">
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]"><xsl:value-of select="@图:层次"/></xsl:for-each>
+ </xsl:attribute>
+ <draw:text-box>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]/图:文本内容/字:段落"/>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]/图:文本内容/字:文字表"/>
+ </draw:text-box>
+ </draw:frame>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="leibie">
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]">
+ <xsl:value-of select="图:预定义图形/图:类别"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="leibie2">
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]">
+ <xsl:value-of select="图:预定义图形/图:名称"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$leibie='22'">
+ <xsl:call-template name="排版框">
+ <xsl:with-param name="biaoshi" select="$tuxing1"/>
+ <xsl:with-param name="name" select="$leibie2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$leibie='23'">
+ <xsl:call-template name="文本框">
+ <xsl:with-param name="biaoshi" select="$tuxing1"/>
+ <xsl:with-param name="name" select="$leibie2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$leibie='11'">
+ <xsl:call-template name="Rectangle"/>
+ </xsl:when>
+ <xsl:when test="$leibie='19'">
+ <xsl:call-template name="Oval"/>
+ </xsl:when>
+ <xsl:when test="$leibie='61'">
+ <xsl:call-template name="Line"/>
+ </xsl:when>
+ <xsl:when test="$leibie='62'">
+ <xsl:call-template name="Line"/>
+ </xsl:when>
+ <xsl:when test="$leibie='63'">
+ <xsl:call-template name="Line"/>
+ </xsl:when>
+ <xsl:when test="$leibie='64'">
+ <xsl:call-template name="Curve"/>
+ </xsl:when>
+ <xsl:when test="$leibie='65'">
+ <xsl:call-template name="Freeform"/>
+ </xsl:when>
+ <xsl:when test="$leibie='66'">
+ <xsl:call-template name="Scribble"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="文本框">
+ <xsl:param name="biaoshi"/>
+ <xsl:param name="name"/>
+ <draw:frame text:anchor-type="paragraph">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="$biaoshi"/></xsl:attribute>
+ <xsl:attribute name="draw:name"><xsl:value-of select="$name"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(字:锚点属性/字:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="字:锚点属性/字:位置/字:水平/字:绝对">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(字:锚点属性/字:位置/字:水平/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:锚点属性/字:位置/字:垂直/字:绝对">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(字:锚点属性/字:位置/字:垂直/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:z-index">
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $biaoshi]">
+ <xsl:value-of select="@图:层次"/>
+ </xsl:for-each>
+ </xsl:attribute>
+ <draw:text-box>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$biaoshi]/图:文本内容/字:段落"/>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$biaoshi]/图:文本内容/字:文字表"/>
+ </draw:text-box>
+ </draw:frame>
+ </xsl:template>
+ <xsl:template name="Curve">
+ <xsl:element name="draw:path">
+ <xsl:variable name="tuxing1" select="字:图形/@字:图形引用"/>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]">
+ <xsl:variable name="width" select="number(图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="svg:d"><xsl:value-of select="图:预定义图形/图:关键点坐标/@图:路径"/></xsl:attribute>
+ </xsl:for-each>
+ <xsl:call-template name="common"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="common">
+ <xsl:if test="字:锚点属性/字:位置/字:水平/字:绝对">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(字:锚点属性/字:位置/字:水平/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:锚点属性/字:位置/字:垂直/字:绝对">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(字:锚点属性/字:位置/字:垂直/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="tuxing1" select="字:图形/@字:图形引用"/>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(字:锚点属性/字:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(字:锚点属性/字:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="text:anchor-type"><xsl:choose><xsl:when test="@字:类型='inline'">as-char</xsl:when><xsl:otherwise>paragraph</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="jiaodu">
+ <xsl:value-of select="图:预定义图形/图:属性/图:旋转角度"/>
+ </xsl:variable>
+ <xsl:variable name="shibie">
+ <xsl:value-of select="图:预定义图形/图:生成软件"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-angle">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:生成软件 and not($shibie='PNG')">
+ <xsl:value-of select="((360 - $jiaodu) * 2 * 3.14159265 ) div 360"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="common1">
+ <xsl:if test="字:锚点属性/字:位置/字:水平/字:绝对">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(字:锚点属性/字:位置/字:水平/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:锚点属性/字:位置/字:垂直/字:绝对">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(字:锚点属性/字:位置/字:垂直/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="tuxing1" select="字:图形/@字:图形引用"/>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]/图:预定义图形/图:属性/图:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:height"><xsl:value-of select="concat(/uof:UOF/uof:对象集/图:图形[@图:标识符=$tuxing1]/图:预定义图形/图:属性/图:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="text:anchor-type"><xsl:choose><xsl:when test="@字:类型='inline'">as-char</xsl:when><xsl:otherwise>paragraph</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="jiaodu">
+ <xsl:value-of select="图:预定义图形/图:属性/图:旋转角度"/>
+ </xsl:variable>
+ <xsl:variable name="shibie">
+ <xsl:value-of select="图:预定义图形/图:生成软件"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-angle">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:生成软件 and not($shibie='PNG')">
+ <xsl:value-of select="((360 - $jiaodu) * 2 * 3.14159265 ) div 360"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="Freeform">
+ <xsl:element name="draw:polygon">
+ <xsl:variable name="tuxing1" select="字:图形/@字:图形引用"/>
+ <xsl:variable name="width" select="number(/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="draw:points"><xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:预定义图形/图:关键点坐标"><xsl:call-template name="drawpoints"><xsl:with-param name="points" select="concat(number(图:坐标[1]/@x坐标)*1000,',',number(图:坐标[1]/@y坐标)*1000)"/><xsl:with-param name="point-pos" select="2"/></xsl:call-template></xsl:for-each></xsl:attribute>
+ <xsl:call-template name="common"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="drawpoints">
+ <xsl:param name="points"/>
+ <xsl:param name="point-pos"/>
+ <xsl:choose>
+ <xsl:when test="图:坐标[$point-pos]">
+ <xsl:variable name="points1" select="concat($points,' ',number(图:坐标[$point-pos]/@x坐标)*1000,',',number(图:坐标[$point-pos]/@y坐标)*1000)"/>
+ <xsl:call-template name="drawpoints">
+ <xsl:with-param name="points" select="$points1"/>
+ <xsl:with-param name="point-pos" select="$point-pos+1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$points"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="Scribble">
+ <xsl:element name="draw:polyline">
+ <xsl:variable name="tuxing1" select="字:图形/@字:图形引用"/>
+ <xsl:variable name="width" select="number(/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:预定义图形/图:属性/图:宽度)*1000"/>
+ <xsl:variable name="height" select="number(/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:预定义图形/图:属性/图:高度)*1000"/>
+ <xsl:attribute name="svg:viewBox"><xsl:value-of select="concat('0 0 ',$width, ' ',$height)"/></xsl:attribute>
+ <xsl:attribute name="draw:points"><xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]/图:预定义图形/图:关键点坐标"><xsl:call-template name="drawpoints"><xsl:with-param name="points" select="concat(number(图:坐标[1]/@x坐标)*1000,',',number(图:坐标[1]/@y坐标)*1000)"/><xsl:with-param name="point-pos" select="2"/></xsl:call-template></xsl:for-each></xsl:attribute>
+ <xsl:call-template name="common"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Oval">
+ <xsl:element name="draw:ellipse">
+ <xsl:call-template name="common1"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="排版框">
+ <xsl:param name="biaoshi"/>
+ <xsl:param name="name"/>
+ <draw:frame text:anchor-type="paragraph">
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="$biaoshi"/></xsl:attribute>
+ <xsl:attribute name="draw:name"><xsl:value-of select="$name"/></xsl:attribute>
+ <xsl:attribute name="svg:width"><xsl:value-of select="concat(字:锚点属性/字:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="字:锚点属性/字:位置/字:水平/字:绝对">
+ <xsl:attribute name="svg:x"><xsl:value-of select="concat(字:锚点属性/字:位置/字:水平/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:锚点属性/字:位置/字:垂直/字:绝对">
+ <xsl:attribute name="svg:y"><xsl:value-of select="concat(字:锚点属性/字:位置/字:垂直/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:z-index">
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $biaoshi]">
+ <xsl:value-of select="@图:层次"/>
+ </xsl:for-each>
+ </xsl:attribute>
+ <draw:text-box>
+ <xsl:attribute name="fo:min-height"><xsl:value-of select="concat(字:锚点属性/字:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$biaoshi]/图:文本内容/字:段落"/>
+ <xsl:apply-templates select="/uof:UOF/uof:对象集/图:图形[@图:标识符=$biaoshi]/图:文本内容/字:文字表"/>
+ </draw:text-box>
+ </draw:frame>
+ </xsl:template>
+ <xsl:template name="Rectangle">
+ <xsl:element name="draw:rect">
+ <xsl:call-template name="common1"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="Line">
+ <xsl:element name="draw:line">
+ <xsl:variable name="tuxing1" select="字:图形/@字:图形引用"/>
+ <xsl:attribute name="svg:x1"><xsl:value-of select="concat(字:锚点属性/字:位置/字:水平/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y1"><xsl:value-of select="concat(字:锚点属性/字:位置/字:垂直/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:x2"><xsl:value-of select="concat((字:锚点属性/字:位置/字:水平/字:绝对/@字:值 + 字:锚点属性/字:宽度),$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="svg:y2"><xsl:value-of select="concat((字:锚点属性/字:位置/字:垂直/字:绝对/@字:值 + 字:锚点属性/字:高度),$uofUnit)"/></xsl:attribute>
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形[@图:标识符 = $tuxing1]">
+ <xsl:attribute name="text:anchor-type">paragraph</xsl:attribute>
+ <xsl:attribute name="draw:style-name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="draw:z-index"><xsl:value-of select="@图:层次"/></xsl:attribute>
+ <xsl:if test="图:预定义图形/图:属性/图:旋转角度 and not(图:预定义图形/图:属性/图:旋转角度='0.0')">
+ <xsl:variable name="jiaodu">
+ <xsl:value-of select="图:预定义图形/图:属性/图:旋转角度"/>
+ </xsl:variable>
+ <xsl:variable name="shibie">
+ <xsl:value-of select="图:预定义图形/图:生成软件"/>
+ </xsl:variable>
+ <xsl:variable name="rotate-angle">
+ <xsl:choose>
+ <xsl:when test="图:预定义图形/图:生成软件 and not($shibie='PNG')">
+ <xsl:value-of select="((360 - $jiaodu) * 2 * 3.14159265 ) div 360"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="(图:预定义图形/图:属性/图:旋转角度 * 2 * 3.14159265 ) div 360"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="draw:transform"><xsl:value-of select="concat('rotate (',$rotate-angle,') translate (-0.0194027777777778cm 3.317875cm)')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="图:文本内容">
+ <xsl:apply-templates select="图:文本内容/字:段落"/>
+ <xsl:apply-templates select="图:文本内容/字:文字表"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="processPageBreaks">
+ <xsl:variable name="pageBreak" select="字:句/字:分页符"/>
+ <xsl:call-template name="createSubParagraph">
+ <xsl:with-param name="list" select="$pageBreak[1]/preceding-sibling::字:句"/>
+ <xsl:with-param name="pageBreak"/>
+ <xsl:with-param name="needsPageBreak">false</xsl:with-param>
+ </xsl:call-template>
+ <xsl:for-each select="$pageBreak">
+ <xsl:call-template name="createSubParagraph">
+ <xsl:with-param name="list" select="./following-sibling::字:句[preceding::字:句/字:分页符 = '.']"/>
+ <xsl:with-param name="pageBreak" select="."/>
+ <xsl:with-param name="needsPageBreak">true</xsl:with-param>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="createSubParagraph">
+ <xsl:param name="list"/>
+ <xsl:param name="pageBreak"/>
+ <xsl:param name="needsPageBreak"/>
+ <xsl:if test="(count($list) &gt; 0) or ($needsPageBreak ='true') ">
+ <xsl:element name="text:p">
+ <xsl:choose>
+ <xsl:when test="$needsPageBreak = 'true'">
+ <xsl:choose>
+ <xsl:when test="ancestor::字:段落/字:段落属性">
+ <xsl:attribute name="text:style-name">P<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落属性"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:style-name">PageBreak</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="$pageBreak">
+ <xsl:apply-templates select="$pageBreak"/>
+ </xsl:if>
+ <xsl:apply-templates select="$list"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:句/字:区域开始[@字:类型='bookmark']">
+ <xsl:variable name="biaoshi">
+ <xsl:value-of select="@字:标识符"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="not(@字:名称)">
+ <text:bookmark-start text:name="{/uof:UOF/uof:书签集/uof:书签[uof:文本位置/@字:区域引用=$biaoshi]/@uof:名称}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <text:bookmark-start text:name="{@字:名称}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:句/字:区域结束[preceding::字:区域开始[1]/@字:类型='bookmark']">
+ <xsl:variable name="biaoshi">
+ <xsl:value-of select="@字:标识符引用"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="not(@字:名称)">
+ <text:bookmark-end text:name="{/uof:UOF/uof:书签集/uof:书签[uof:文本位置/@字:区域引用=$biaoshi]/@uof:名称}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <text:bookmark-end text:name="{@字:名称}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:区域开始[@字:类型='annotation']">
+ <text:bookmark-start text:name="{@字:标识符}"/>
+ </xsl:template>
+ <xsl:template match="字:区域结束[preceding::字:区域开始[1]/@字:类型='annotation']">
+ <text:bookmark-end text:name="{@字:标识符引用}"/>
+ </xsl:template>
+ <xsl:template match="字:区域开始[@字:类型='user-data']">
+ <text:alphabetical-index-mark-start text:id="{@字:标识符}" text:string-value-phonetic="{@字:名称}"/>
+ </xsl:template>
+ <xsl:template match="字:区域结束[preceding::字:区域开始[1]/@字:类型='user-data']">
+ <text:alphabetical-index-mark-end text:id="{@字:标识符引用}"/>
+ </xsl:template>
+ <xsl:template match="字:段落/字:域开始">
+ <xsl:choose>
+ <xsl:when test="@字:类型='createdate'">
+ <xsl:variable name="datestr" select="../字:句[preceding-sibling::字:域代码]/字:文本串"/>
+ <xsl:element name="text:creation-date">
+ <xsl:attribute name="style:data-style-name">CreateDate<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'createdate']"/></xsl:attribute>
+ <xsl:attribute name="text:date-value"><xsl:value-of select="$datestr"/></xsl:attribute>
+ <xsl:value-of select="$datestr"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@字:类型='savedate'">
+ <xsl:variable name="datestr" select="../字:句[preceding-sibling::字:域代码]/字:文本串"/>
+ <xsl:element name="text:date">
+ <xsl:attribute name="style:data-style-name">SaveDate<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'savedate']"/></xsl:attribute>
+ <xsl:attribute name="text:date-value"><xsl:value-of select="$datestr"/></xsl:attribute>
+ <xsl:attribute name="text:fixed">true</xsl:attribute>
+ <xsl:value-of select="$datestr"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@字:类型='date'">
+ <xsl:variable name="datestr" select="../字:句[preceding-sibling::字:域代码]/字:文本串"/>
+ <xsl:element name="text:date">
+ <xsl:attribute name="style:data-style-name">Date<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'date']"/></xsl:attribute>
+ <xsl:attribute name="text:date-value"><xsl:value-of select="$datestr"/></xsl:attribute>
+ <xsl:value-of select="$datestr"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@字:类型='time'">
+ <xsl:variable name="datestr" select="../字:句[preceding-sibling::字:域代码]/字:文本串"/>
+ <xsl:element name="text:time">
+ <xsl:attribute name="style:data-style-name">Time<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'time']"/></xsl:attribute>
+ <xsl:attribute name="text:time-value"><xsl:value-of select="$datestr"/></xsl:attribute>
+ <xsl:value-of select="$datestr"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@字:类型='edittime'">
+ <xsl:variable name="datestr" select="../字:句[preceding-sibling::字:域代码]/字:文本串"/>
+ <xsl:element name="text:editing-duration">
+ <xsl:attribute name="style:data-style-name">EditTime<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'edittime']"/></xsl:attribute>
+ <xsl:value-of select="$datestr"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@字:类型='createtime'">
+ <xsl:variable name="datestr" select="../字:句[preceding-sibling::字:域代码]/字:文本串"/>
+ <xsl:element name="text:creation-time">
+ <xsl:attribute name="style:data-style-name">CREATETIME<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落/字:域开始[@字:类型 = 'createtime']"/></xsl:attribute>
+ <xsl:value-of select="$datestr"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@字:类型='page'">
+ <xsl:call-template name="页码域"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='numpages'">
+ <xsl:call-template name="页数域"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='author'">
+ <xsl:call-template name="作者域"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='username'">
+ <xsl:call-template name="用户域"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='userinitials'">
+ <xsl:call-template name="缩写域"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='title'">
+ <xsl:call-template name="标题域"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='subject'">
+ <xsl:call-template name="主题域"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='numchars'">
+ <xsl:call-template name="字符数"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='filename'">
+ <xsl:call-template name="文件名"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='edittime'">
+ <xsl:call-template name="编辑时间"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='creation-time'">
+ <xsl:call-template name="创建时间"/>
+ </xsl:when>
+ <xsl:when test="@字:类型='seq'">
+ <xsl:call-template name="题注"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="commonParagraph">
+ <xsl:choose>
+ <xsl:when test="字:段落属性/字:大纲级别">
+ <xsl:element name="text:h">
+ <xsl:call-template name="commonParagraphAttributes"/>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="not (字:域开始/@字:类型='ref') and not(字:域开始/@字:类型='index')">
+ <xsl:element name="text:p">
+ <xsl:call-template name="commonParagraphAttributes"/>
+ <xsl:apply-templates/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="commonParagraphAttributes">
+ <xsl:choose>
+ <xsl:when test="字:段落属性">
+ <xsl:variable name="pp">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落[字:段落属性]"/>
+ </xsl:variable>
+ <xsl:variable name="aa">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落[字:域结束]"/>
+ </xsl:variable>
+ <xsl:variable name="stylename" select="字:段落属性/@字:式样引用"/>
+ <xsl:choose>
+ <xsl:when test="preceding-sibling::字:段落/字:域结束">
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('P',$pp+$aa)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains($stylename,'Heading')">
+ <xsl:attribute name="text:style-name"><xsl:value-of select="$stylename"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('P',$pp)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="字:段落属性/字:大纲级别">
+ <xsl:attribute name="text:outline-level"><xsl:value-of select="字:段落属性/字:大纲级别"/></xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="generate-id(ancestor::字:主体/descendant::字:段落[1]) = generate-id(.)">
+ <xsl:variable name="paragraph-number">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落[字:段落属性]"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name">P<xsl:value-of select="number($paragraph-number)"/>_1</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="not(字:段落属性) and (descendant::字:分栏符 or ancestor::字:分节/descendant::字:节属性[字:分栏/@字:栏数 &gt; 1])">
+ <xsl:attribute name="text:style-name">ColumnBreakPara</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:句">
+ <xsl:apply-templates select="字:文本串"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:段落属性"/>
+ <xsl:template match="字:句/字:句属性"/>
+ <xsl:template match="字:句属性" mode="style">
+ <xsl:if test="not(@字:式样引用)">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">T<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:句属性" format="1"/></xsl:attribute>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ <xsl:if test="@字:式样引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:式样引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="./*"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:句/字:文本串">
+ <xsl:choose>
+ <xsl:when test="string(.) = ' ' ">
+ <xsl:element name="text:s"/>
+ </xsl:when>
+ <xsl:when test="contains(.,' ')">
+ <xsl:call-template name="replace-spaces">
+ <xsl:with-param name="curr-string" select="."/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="replace-spaces">
+ <xsl:param name="curr-string"/>
+ <xsl:if test="contains($curr-string,' ')">
+ <xsl:value-of select="substring-before($curr-string,' ')"/>
+ <text:s text:c="2"/>
+ <xsl:variable name="next-string" select="substring-after($curr-string,' ')"/>
+ <xsl:choose>
+ <xsl:when test="contains($next-string, ' ')">
+ <xsl:call-template name="replace-spaces">
+ <xsl:with-param name="curr-string" select="$next-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$next-string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:空格符[parent::字:句]">
+ <xsl:element name="text:s">
+ <xsl:attribute name="text:c"><xsl:value-of select="@字:个数"/></xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:制表符[parent::字:句]">
+ <xsl:element name="text:tab"/>
+ </xsl:template>
+ <xsl:template match="字:句">
+ <xsl:if test="name(following-sibling::*[1])!='字:域结束'">
+ <xsl:if test="字:换行符">
+ <xsl:element name="text:line-break"/>
+ </xsl:if>
+ <xsl:variable name="currently-node" select="./字:锚点"/>
+ <xsl:choose>
+ <xsl:when test="字:句属性//字:隐藏文字/@字:值='true'">
+ <text:hidden-text text:is-hidden="true" text:string-value="{.}"/>
+ </xsl:when>
+ <xsl:when test="字:区域开始[@字:类型='hyperlink']">
+ <xsl:element name="text:a">
+ <xsl:attribute name="xlink:type">simple</xsl:attribute>
+ <xsl:variable name="hyperDest" select="字:区域开始/@字:标识符"/>
+ <xsl:attribute name="xlink:href"><xsl:for-each select="/uof:UOF/uof:链接集/uof:超级链接"><xsl:if test="@uof:链源=$hyperDest"><xsl:if test="@uof:提示"><xsl:attribute name="office:name"><xsl:value-of select="@uof:提示"/></xsl:attribute></xsl:if><xsl:if test="@uof:目标"><xsl:variable name="bsh" select="@uof:目标"/><xsl:choose><xsl:when test="contains($bsh,'\')"><xsl:value-of select="concat('/',translate($bsh,'\','/'))"/></xsl:when><xsl:otherwise><xsl:value-of select="$bsh"/></xsl:otherwise></xsl:choose></xsl:if><xsl:if test="@uof:书签"><xsl:variable name="bookmarkDest" select="@uof:书签"/><xsl:choose><xsl:when test="/uof:UOF/uof:书签集/uof:书签"><xsl:for-each select="/uof:UOF/uof:书签集/uof:书签"><xsl:if test="@uof:名称=$bookmarkDest"><xsl:value-of select="concat('#',@uof:名称)"/></xsl:if></xsl:for-each></xsl:when><xsl:otherwise><xsl:value-of select="concat('#',$bookmarkDest)"/></xsl:otherwise></xsl:choose></xsl:if></xsl:if></xsl:for-each></xsl:attribute>
+ <xsl:for-each select="/uof:UOF/uof:链接集/uof:超级链接">
+ <xsl:if test="@uof:链源=$hyperDest">
+ <xsl:if test="@uof:提示">
+ <xsl:attribute name="office:name"><xsl:value-of select="@uof:提示"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:choose>
+ <xsl:when test="./字:文本串">
+ <xsl:apply-templates select="字:文本串"/>
+ </xsl:when>
+ <xsl:when test="following-sibling::字:句/字:文本串">
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="字:区域结束 and preceding::字:区域开始[1]/@字:类型='bookmark' and not(self::node()/字:区域开始)">
+ <xsl:variable name="aa">
+ <xsl:value-of select="字:区域结束/@字:标识符引用"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="preceding::字:区域开始[1]/@字:类型='bookmark' and not(preceding::字:区域开始[1]/@字:名称)">
+ <text:bookmark-end text:name="{/uof:UOF/uof:书签集/uof:书签[uof:文本位置/@字:区域引用=$aa]/@uof:名称}"/>
+ </xsl:when>
+ <xsl:when test="preceding::字:区域开始[1]/@字:类型='bookmark'">
+ <text:bookmark-end text:name="{preceding::字:区域开始[1]/@字:名称}"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="preceding-sibling::字:句[position()=1]/字:区域开始[@字:类型='hyperlink'] and not(preceding-sibling::字:句[position()=1]/字:区域结束)"/>
+ <xsl:when test="(preceding-sibling::字:句) or (字:句属性)or(字:区域开始)">
+ <xsl:element name="text:span">
+ <xsl:choose>
+ <xsl:when test="字:区域开始[@字:类型='annotation']">
+ <xsl:variable name="ref_comment">
+ <xsl:value-of select="字:区域开始/@字:标识符"/>
+ </xsl:variable>
+ <xsl:apply-templates/>
+ <xsl:apply-templates select="/uof:UOF/uof:文字处理/字:公用处理规则/字:批注集/字:批注[@字:区域引用 = $ref_comment]"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="stylenum">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:句" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('T',$stylenum)"/></xsl:attribute>
+ <xsl:apply-templates select="*[not(name()='字:引文符号')]"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select="字:文本串|字:锚点|字:空格符|字:换行符|字:制表符|字:区域开始|字:区域结束|字:脚注|字:尾注"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="node()[name() = '字:位置']">
+ <xsl:attribute name="style:text-position"><xsl:variable name="val"><xsl:value-of select="."/></xsl:variable><xsl:choose><xsl:when test="$val='sub' or $val='super'"><xsl:value-of select="concat($val,' 58%')"/></xsl:when><xsl:when test="contains($val,'sub ') or contains($val,'super ')"><xsl:value-of select="concat($val,'%')"/></xsl:when><xsl:when test="not(contains($val,' '))"><xsl:value-of select="concat($val,'% 100%')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat(substring-before($val,' '),'% ',substring-after($val,' '),'%' )"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:批注">
+ <office:annotation office:display="true">
+ <xsl:variable name="name" select="@字:作者"/>
+ <dc:creator>
+ <xsl:value-of select="/uof:UOF/uof:文字处理/字:公用处理规则/字:用户集/字:用户[@字:标识符=$name]/@字:姓名"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="@字:日期"/>
+ </dc:date>
+ <xsl:apply-templates select="字:段落"/>
+ </office:annotation>
+ </xsl:template>
+ <xsl:template match="字:字体">
+ <xsl:if test="@字:字号">
+ <xsl:attribute name="fo:font-size"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex"><xsl:value-of select="@字:字号"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:相对字号 and self::node( )[not(parent::字:句属性)]">
+ <xsl:variable name="stylename" select="parent::node()/@字:基式样引用"/>
+ <xsl:variable name="zihao">
+ <xsl:for-each select="/uof:UOF/uof:式样集//uof:段落式样[@字:标识符=$stylename]">
+ <xsl:value-of select="字:字体/@字:字号"/>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="font-size" select="@字:相对字号"/>
+ <xsl:attribute name="fo:font-size"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex"><xsl:value-of select="($zihao * $font-size div 100)"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:颜色">
+ <xsl:attribute name="fo:color"><xsl:value-of select="@字:颜色"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:中文字体引用">
+ <xsl:attribute name="style:font-name-asian"><xsl:value-of select="@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:西文字体引用">
+ <xsl:variable name="xiwen" select="@字:西文字体引用"/>
+ <xsl:attribute name="style:font-name"><xsl:value-of select="translate($xiwen,'_',' ')"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:斜体">
+ <xsl:if test="@字:值='true'">
+ <xsl:attribute name="fo:font-style">italic</xsl:attribute>
+ <xsl:attribute name="fo:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-asian">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-complex">italic</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:粗体">
+ <xsl:if test="@字:值='true'or @字:值='1'">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-complex">bold</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:下划线">
+ <xsl:choose>
+ <xsl:when test="@字:类型 = 'single'">
+ <xsl:attribute name="style:text-underline-style">solid</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'double'">
+ <xsl:attribute name="style:text-underline-style">solid</xsl:attribute>
+ <xsl:attribute name="style:text-underline-type">double</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'thick'">
+ <xsl:attribute name="style:text-underline-style">solid</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dotted'">
+ <xsl:attribute name="style:text-underline-style">dotted</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dotted-heavy'">
+ <xsl:attribute name="style:text-underline-style">dotted</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash'">
+ <xsl:attribute name="style:text-underline-style">dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dashed-heavy'">
+ <xsl:attribute name="style:text-underline-style">dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-long'">
+ <xsl:attribute name="style:text-underline-style">long-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-long-heavy'">
+ <xsl:attribute name="style:text-underline-style">long-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dot-dash'">
+ <xsl:attribute name="style:text-underline-style">dot-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-dot-heavy'">
+ <xsl:attribute name="style:text-underline-style">dot-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dot-dot-dash'">
+ <xsl:attribute name="style:text-underline-style">dot-dot-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'dash-dot-dot-heavy'">
+ <xsl:attribute name="style:text-underline-style">dot-dot-dash</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'wave'">
+ <xsl:attribute name="style:text-underline-style">wave</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'wavy-heavy'">
+ <xsl:attribute name="style:text-underline-style">wave</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'wavy-double'">
+ <xsl:attribute name="style:text-underline-style">wave</xsl:attribute>
+ <xsl:attribute name="style:text-underline-type">double</xsl:attribute>
+ <xsl:attribute name="style:text-underline-width">auto</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@字:颜色">
+ <xsl:attribute name="style:text-underline-color"><xsl:choose><xsl:when test="@字:颜色='auto'">font-color</xsl:when><xsl:otherwise><xsl:value-of select="@字:颜色"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:text-underline-color">font-color</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:着重号">
+ <xsl:if test="not(@字:类型='none')">
+ <xsl:choose>
+ <xsl:when test="@字:类型='dot'">
+ <xsl:attribute name="style:text-emphasize">dot below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='accent above' ">
+ <xsl:attribute name="style:text-emphasize">accent above</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='dot above' ">
+ <xsl:attribute name="style:text-emphasize">dot above</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='disc above' ">
+ <xsl:attribute name="style:text-emphasize">disc above</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='circle above' ">
+ <xsl:attribute name="style:text-emphasize">circle above</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='accent below' ">
+ <xsl:attribute name="style:text-emphasize">accent below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='dot below' ">
+ <xsl:attribute name="style:text-emphasize">dot below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='disc below' ">
+ <xsl:attribute name="style:text-emphasize">disc below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='circle below' ">
+ <xsl:attribute name="style:text-emphasize">circle below</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>none</xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="字:颜色">
+ <xsl:attribute name="fo:color"><xsl:value-of select="@字:颜色"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:隐藏文字">
+ <xsl:attribute name="text:display"><xsl:value-of select="@字:值"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:空心">
+ <xsl:attribute name="style:text-outline"><xsl:value-of select="@字:值"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:阴影">
+ <xsl:if test="not(@字:值='false')">
+ <xsl:attribute name="fo:text-shadow">1pt 1pt</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:闪动的">
+ <xsl:attribute name="style:text-blinking"><xsl:value-of select="@字:闪动的"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:删除线">
+ <xsl:choose>
+ <xsl:when test="@字:类型 = 'single' ">
+ <xsl:attribute name="style:text-line-through-style">solid</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'double' ">
+ <xsl:attribute name="style:text-line-through-type">double</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'bold' ">
+ <xsl:attribute name="style:text-line-through-width">bold</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = 'xl' ">
+ <xsl:attribute name="style:text-line-through-text">X</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型 = '/l' ">
+ <xsl:attribute name="style:text-line-through-text">/</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:text-crossing-out">none</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:突出显示">
+ <xsl:attribute name="fo:background-color">
+ <xsl:choose>
+ <xsl:when test="@字:颜色='auto'">transparent</xsl:when>
+ <xsl:otherwise><xsl:value-of select="@字:颜色"/></xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:template>
+ <xsl:template match="@字:颜色[not(.='auto')]">
+ <xsl:attribute name="fo:color">#<xsl:value-of select="."/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:浮雕">
+ <xsl:attribute name="style:font-relief"><xsl:choose><xsl:when test="@字:类型='engrave'">engraved</xsl:when><xsl:when test="@字:类型='emboss'">embossed</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:醒目字体">
+ <xsl:choose>
+ <xsl:when test="@字:类型='small-caps'">
+ <xsl:attribute name="fo:font-variant">small-caps</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:类型='none'">
+ <xsl:attribute name="fo:font-variant">normal</xsl:attribute>
+ <xsl:attribute name="fo:text-transform">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:text-transform"><xsl:choose><xsl:when test="@字:类型='uppercase'">uppercase</xsl:when><xsl:when test="@字:类型='lowercase'">lowercase</xsl:when><xsl:when test="@字:类型='capital'">capitalize</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:位置" mode="oo">
+ <xsl:attribute name="style:text-position"><xsl:variable name="val"><xsl:value-of select="."/></xsl:variable><xsl:choose><xsl:when test="$val='sub' or $val='super'"><xsl:value-of select="concat($val,' 58%')"/></xsl:when><xsl:when test="contains($val,'sub ') or contains($val,'super ')"><xsl:value-of select="concat($val,'%')"/></xsl:when><xsl:when test="not(contains($val,' '))"><xsl:value-of select="concat($val,'% 100%')"/></xsl:when><xsl:otherwise><xsl:value-of select="concat(substring-before($val,' '),'% ',substring-after($val,' '),'%' )"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:缩放">
+ <xsl:attribute name="style:text-scale"><xsl:value-of select="."/>%</xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:字符间距">
+ <xsl:attribute name="fo:letter-spacing"><xsl:value-of select="."/>cm</xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:调整字间距">
+ <xsl:variable name="tt" select="字:调整字间距"/>
+ <xsl:attribute name="style:letter-kerning"><xsl:choose><xsl:when test="$tt='1'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:外框">
+ <xsl:attribute name="style:text-outline">true</xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:字符间距[parent::字:句属性]">
+ <xsl:variable name="aa">
+ <xsl:value-of select="."/>
+ </xsl:variable>
+ <xsl:attribute name="fo:letter-spacing"><xsl:value-of select="concat( $aa, $uofUnit)"/></xsl:attribute>
+ </xsl:template>
+ <xsl:template match="字:分节">
+ <xsl:if test="字:节属性/字:脚注设置">
+ <xsl:call-template name="脚注设置"/>
+ </xsl:if>
+ <xsl:if test="字:节属性/字:尾注设置">
+ <xsl:call-template name="尾注设置"/>
+ </xsl:if>
+ <xsl:if test="字:节属性/字:行号设置">
+ <xsl:call-template name="行编号"/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="行编号">
+ <xsl:element name="text:linenumbering-configuration">
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:行号设置">
+ <xsl:choose>
+ <xsl:when test="@字:使用行号='false'">
+ <xsl:attribute name="text:number-lines">false</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:style-name">Line numbering</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@字:编号方式">
+ <xsl:choose>
+ <xsl:when test="@字:编号方式='section'">
+ <xsl:attribute name="text:count-in-floating-frames">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@字:编号方式='page'">
+ <xsl:attribute name="text:restart-on-page">true</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="字:编号方式='continuous'">
+ <xsl:attribute name="text:count-empty-lines">true</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="@字:起始编号">
+ <xsl:attribute name="style:num-format"><xsl:value-of select="@字:起始编号"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:距边界">
+ <xsl:attribute name="text:offset"><xsl:value-of select="concat(@字:距边界,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@字:行号间隔">
+ <xsl:attribute name="text:increment"><xsl:value-of select="@字:行号间隔"/></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="脚注设置">
+ <xsl:element name="text:notes-configuration">
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:脚注设置">
+ <xsl:attribute name="text:note-class">footnote</xsl:attribute>
+ <xsl:attribute name="text:master-page-name">Footnote</xsl:attribute>
+ <xsl:attribute name="text:footnotes-position"><xsl:choose><xsl:when test="@字:位置='page-bottom'">page</xsl:when><xsl:when test="@字:位置='below-text'">document</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="text:start-numbering-at"><xsl:choose><xsl:when test="@字:编号方式='continuous'">document</xsl:when><xsl:when test="@字:编号方式='section'">chapter</xsl:when><xsl:when test="@字:编号方式='page'">page</xsl:when></xsl:choose></xsl:attribute>
+ <xsl:attribute name="text:start-value"><xsl:value-of select="@字:起始编号 - 1"/></xsl:attribute>
+ <xsl:attribute name="style:num-format"><xsl:call-template name="oo数字格式"><xsl:with-param name="oo_format" select="@字:格式"/></xsl:call-template></xsl:attribute>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="尾注设置">
+ <xsl:element name="text:notes-configuration">
+ <xsl:for-each select="/uof:UOF/uof:文字处理/字:主体/字:分节/字:节属性/字:尾注设置">
+ <xsl:attribute name="text:note-class">endnote</xsl:attribute>
+ <xsl:attribute name="text:master-page-name">Endnote</xsl:attribute>
+ <xsl:attribute name="style:num-format"><xsl:call-template name="oo数字格式"><xsl:with-param name="oo_format" select="@字:格式"/></xsl:call-template></xsl:attribute>
+ <xsl:attribute name="text:start-value"><xsl:value-of select="@字:起始编号 - 1"/></xsl:attribute>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="paragraph-properties">
+ <xsl:choose>
+ <xsl:when test="descendant::字:页边距[@uof:左]">
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="number((descendant::字:页边距/@uof:左)) * $other-to-cm-conversion-factor"/>cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-left">0cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="descendant::字:页边距[@uof:右]">
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="number((descendant::字:页边距/@uof:右)) * $other-to-cm-conversion-factor"/>cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-right">0cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:text-indent">0cm</xsl:attribute>
+ <xsl:call-template name="bidi"/>
+ </xsl:template>
+ <xsl:template name="bidi">
+ </xsl:template>
+ <xsl:template match="字:文字表">
+ <xsl:choose>
+ <xsl:when test="@字:类型 = 'sub-table'">
+ <xsl:element name="table:table">
+ <xsl:attribute name="table:is-sub-table">true</xsl:attribute>
+ <xsl:apply-templates select="字:文字表属性">
+ <xsl:with-param name="sub-table" select="@字:类型"/>
+ </xsl:apply-templates>
+ <xsl:if test="字:行[position()=1]/字:表行属性/字:表头行/@字:值='true'">
+ <xsl:element name="table:table-header-rows">
+ <xsl:for-each select="字:行">
+ <xsl:if test="字:表行属性/字:表头行/@字:值='true'">
+ <xsl:apply-templates select="."/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:for-each select="字:行[not(字:表行属性/字:表头行) or (字:表行属性/字:表头行/@字:值='false')]">
+ <xsl:apply-templates select="."/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="table:table">
+ <xsl:if test="字:文字表属性">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(字:文字表属性/字:列宽集/字:列宽)">
+ <xsl:for-each select="字:行[1]/字:单元格">
+ <xsl:element name="table:table-column">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="字:文字表" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>.C<xsl:number value="count(preceding::字:单元格)+1"/></xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:apply-templates select="字:文字表属性"/>
+ <xsl:if test="字:行[position()=1]/字:表行属性/字:表头行/@字:值='true'">
+ <xsl:element name="table:table-header-rows">
+ <xsl:for-each select="字:行">
+ <xsl:if test="字:表行属性/字:表头行/@字:值='true'">
+ <xsl:apply-templates select="."/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:for-each select="字:行[not(字:表行属性/字:表头行) or (字:表行属性/字:表头行/@字:值='false')]">
+ <xsl:apply-templates select="."/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:文字表属性">
+ <xsl:param name="sub-table"/>
+ <xsl:apply-templates select="字:列宽集">
+ <xsl:with-param name="sub-table" select="$sub-table"/>
+ </xsl:apply-templates>
+ </xsl:template>
+ <xsl:template match="字:列宽集">
+ <xsl:param name="sub-table"/>
+ <xsl:apply-templates select="字:列宽">
+ <xsl:with-param name="sub-table" select="$sub-table"/>
+ </xsl:apply-templates>
+ </xsl:template>
+ <xsl:template match="字:列宽">
+ <xsl:param name="sub-table"/>
+ <xsl:element name="table:table-column">
+ <xsl:choose>
+ <xsl:when test="$sub-table='sub-table'">
+ <xsl:variable name="subtable-leikuan" select="."/>
+ <xsl:variable name="weizi">
+ <xsl:for-each select="ancestor::*[name()='字:文字表' and not(@字:类型='sub-table')]/字:文字表属性/字:列宽集/字:列宽">
+ <xsl:variable name="yyyyy" select="."/>
+ <xsl:if test="substring(string($yyyyy),1,string-length(string($yyyyy))-1)=substring(string($subtable-leikuan),1,string-length(string($subtable-leikuan))-1)">
+ <xsl:value-of select="concat(position(),';')"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:variable name="xxxxx">
+ <xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="table:style-name"><xsl:value-of select="concat('Table',$xxxxx,'.C',substring-before($weizi,';'))"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:style-name">Table<xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>.C<xsl:number count="字:列宽" from="/uof:UOF/uof:文字处理/字:主体" level="single" format="1"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:行">
+ <xsl:element name="table:table-row">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>.R<xsl:number count="字:行" from="/uof:UOF/uof:文字处理/字:主体/字:文字表[not (@字:类型='sub-table')]" level="any" format="1"/></xsl:attribute>
+ <xsl:for-each select="node()">
+ <xsl:choose>
+ <xsl:when test="name()='字:单元格'">
+ <xsl:call-template name="字:单元格"/>
+ </xsl:when>
+ <xsl:when test="name()='字:单元格覆盖'">
+
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="字:单元格">
+ <xsl:element name="table:table-cell">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="字:文字表[not (@字:类型='sub-table')]" from="/uof:UOF/uof:文字处理/字:主体" level="any" format="1"/>.R<xsl:number count="字:行" from="/uof:UOF/uof:文字处理/字:主体/字:文字表[not (@字:类型='sub-table')]" level="any" format="1"/>C<xsl:number count="字:单元格" from="/uof:UOF/uof:文字处理/字:主体/字:文字表[not (@字:类型='sub-table')]/字:行" level="any" format="1"/></xsl:attribute>
+ <xsl:if test="字:单元格属性">
+ <xsl:apply-templates select="字:单元格属性"/>
+ </xsl:if>
+ <xsl:for-each select="node( )">
+ <xsl:choose>
+ <xsl:when test="name( )='字:段落'">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:when test="name( )='字:文字表'">
+ <xsl:apply-templates select="."/>
+ </xsl:when>
+ <xsl:otherwise>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:单元格属性/字:边框">
+ <xsl:apply-templates/>
+ </xsl:template>
+ <xsl:template match="字:对齐[parent::字:文字表属性]">
+
+ </xsl:template>
+ <xsl:template match="uof:上">
+ <xsl:choose>
+ <xsl:when test="@uof:宽度='nil' ">
+ <xsl:attribute name="fo:border-top">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:宽度 and @uof:颜色">
+ <xsl:attribute name="fo:border-top"><xsl:value-of select="concat(number(@uof:宽度),$uofUnit)"/><xsl:text> </xsl:text><xsl:choose><xsl:when test="@uof:颜色 ='auto'"><xsl:text>solid #000000</xsl:text></xsl:when><xsl:otherwise><xsl:text>solid </xsl:text><xsl:value-of select="@uof:颜色"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:宽度">
+ <xsl:attribute name="fo:border-top"><xsl:value-of select="concat(number(@uof:宽度),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="uof:下">
+ <xsl:choose>
+ <xsl:when test="@uof:宽度='nil' ">
+ <xsl:attribute name="fo:border-bottom">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:宽度 and @uof:颜色">
+ <xsl:attribute name="fo:border-bottom"><xsl:value-of select="concat(number(@uof:宽度),$uofUnit)"/><xsl:text> </xsl:text><xsl:choose><xsl:when test="@uof:颜色 ='auto'"><xsl:text>solid #000000</xsl:text></xsl:when><xsl:otherwise><xsl:text>solid </xsl:text><xsl:value-of select="@uof:颜色"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:宽度">
+ <xsl:attribute name="fo:border-bottom"><xsl:value-of select="concat(number(@uof:宽度),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="uof:左">
+ <xsl:choose>
+ <xsl:when test="@uof:宽度='nil'">
+ <xsl:attribute name="fo:border-left">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:宽度 and @uof:颜色">
+ <xsl:attribute name="fo:border-left"><xsl:value-of select="concat(number(@uof:宽度),$uofUnit)"/><xsl:text> </xsl:text><xsl:choose><xsl:when test="@uof:颜色 ='auto'"><xsl:text>solid #000000</xsl:text></xsl:when><xsl:otherwise><xsl:text>solid </xsl:text><xsl:value-of select="@uof:颜色"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:宽度">
+ <xsl:attribute name="fo:border-left"><xsl:value-of select="concat(number(@uof:宽度),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="uof:右">
+ <xsl:choose>
+ <xsl:when test="@uof:宽度='nil' ">
+ <xsl:attribute name="fo:border-right">none</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:宽度 and @uof:颜色">
+ <xsl:attribute name="fo:border-right"><xsl:value-of select="concat(number(@uof:宽度),$uofUnit)"/><xsl:text> </xsl:text><xsl:choose><xsl:when test="@uof:颜色 ='auto'"><xsl:text>solid #000000</xsl:text></xsl:when><xsl:otherwise><xsl:text>solid </xsl:text><xsl:value-of select="@uof:颜色"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@uof:宽度">
+ <xsl:attribute name="fo:border-right"><xsl:value-of select="concat(number(@uof:宽度),$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:文字表属性/字:边框">
+ <xsl:apply-templates/>
+ </xsl:template>
+ <xsl:template match="字:单元格属性/字:边框">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:template>
+ <xsl:template match="字:左缩进">
+ </xsl:template>
+ <xsl:template match="字:单元格属性">
+ <xsl:if test="字:跨列/@字:值">
+ <xsl:attribute name="table:number-columns-spanned"><xsl:value-of select="字:跨列/@字:值"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="编号风格">
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="concat('P',@字:标识符)"/></xsl:attribute>
+ <xsl:attribute name="style:family">paragraph</xsl:attribute>
+ <xsl:attribute name="style:parent-style-name">Standard</xsl:attribute>
+ <xsl:attribute name="style:list-style-name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ <xsl:element name="style:text-properties">
+ <xsl:attribute name="fo:margin-left">0cm</xsl:attribute>
+ <xsl:attribute name="fo:margin-right">0cm</xsl:attribute>
+ <xsl:attribute name="fo:color"><xsl:value-of select="字:级别/字:符号字体/字:字体/字:颜色"/></xsl:attribute>
+ <xsl:attribute name="fo:text-indent"/>
+ <xsl:attribute name="style:auto-text-indent">false</xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="编号格式">
+ <xsl:attribute name="style:num-format"><xsl:choose><xsl:when test="string(字:编号格式)='lower-letter'">a</xsl:when><xsl:when test="string(字:编号格式)='upper-letter'">A</xsl:when><xsl:when test="string(字:编号格式)='lower-roman'">i</xsl:when><xsl:when test="string(字:编号格式)='upper-roman'">I</xsl:when><xsl:when test="string(字:编号格式)='decimal-enclosed-circle'">①, ②, ③, ...</xsl:when><xsl:when test="string(字:编号格式)='ideograph-traditional'">甲, 乙, 丙, ...</xsl:when><xsl:when test="string(字:编号格式)='ideograph-zodiac'">子, 丑, 寅, ...</xsl:when><xsl:when test="string(字:编号格式)='chinese-counting'">一, 二, 三, ...</xsl:when><xsl:when test="string(字:编号格式)='chinese-legal-simplified'">壹, 贰, 叁, ...</xsl:when><xsl:otherwise>1</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:template>
+ <xsl:template name="图形style">
+ <xsl:for-each select="/uof:UOF/uof:对象集/图:图形">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name"><xsl:value-of select="@图:标识符"/></xsl:attribute>
+ <xsl:attribute name="style:family">graphic</xsl:attribute>
+ <xsl:attribute name="style:parent-style-name">Graphics</xsl:attribute>
+ <xsl:element name="style:text-properties">
+ <xsl:attribute name="svg:stroke-width"><xsl:value-of select="图:预定义图形/图:属性/图:线粗细"/></xsl:attribute>
+ <xsl:attribute name="svg:stroke-color"><xsl:value-of select="图:预定义图形/图:属性/图:线颜色"/></xsl:attribute>
+ <xsl:attribute name="draw:stroke-dash"><xsl:value-of select="图:预定义图形/图:属性/图:线型"/></xsl:attribute>
+ <xsl:attribute name="draw:marker-start"><xsl:value-of select="图:预定义图形/图:属性/图:前端箭头/图:式样"/></xsl:attribute>
+ <xsl:attribute name="draw:marker-end"><xsl:value-of select="图:预定义图形/图:属性/图:后端箭头/图:式样"/></xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="duanluoshuxing">
+ <xsl:for-each select="/uof:UOF/uof:文字处理//字:段落">
+ <xsl:choose>
+ <xsl:when test="count(字:句)&lt;=1">
+ <xsl:call-template name="单个或者没有句"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="多个句"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="单个或者没有句">
+ <xsl:variable name="stylename" select="字:段落属性/@字:式样引用"/>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">P<xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落"/></xsl:attribute>
+ <xsl:attribute name="style:family">paragraph</xsl:attribute>
+ <xsl:if test="name(preceding-sibling::*[1])='字:分节'">
+ <xsl:attribute name="style:master-page-name"><xsl:value-of select="preceding-sibling::字:分节[1]/@字:名称"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/@字:式样引用">
+ <xsl:variable name="duanluoyinyong">
+ <xsl:value-of select="字:段落属性/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF//uof:段落式样">
+ <xsl:if test="$duanluoyinyong=@字:标识符">
+ <xsl:if test="@字:基式样引用">
+ <xsl:choose>
+ <xsl:when test="@字:标识符=/uof:UOF/uof:文字处理/字:主体/字:段落/字:段落属性/字:格式修订/@字:修订信息引用">
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:标识符"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:parent-style-name"><xsl:value-of select="@字:基式样引用"/></xsl:attribute>
+ <xsl:variable name="aa">
+ <xsl:value-of select="@字:基式样引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF//uof:段落式样">
+ <xsl:if test="$aa=@字:标识符">
+ <xsl:attribute name="style:display-name"><xsl:choose><xsl:when test="@字:别名"><xsl:value-of select="@字:别名"/></xsl:when><xsl:otherwise><xsl:value-of select="@字:名称"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:element name="style:paragraph-properties">
+ <xsl:if test="字:对齐">
+ <xsl:if test="字:对齐/@字:文字对齐">
+ <xsl:attribute name="style:vertical-align"><xsl:choose><xsl:when test="字:对齐/@字:文字对齐='base'">baseline</xsl:when><xsl:when test="字:对齐/@字:文字对齐='center'">middle</xsl:when><xsl:otherwise><xsl:value-of select="字:对齐/@字:文字对齐"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:对齐/@字:水平对齐">
+ <xsl:attribute name="fo:text-align"><xsl:choose><xsl:when test="字:对齐/@字:水平对齐='left'">start</xsl:when><xsl:when test="字:对齐/@字:水平对齐='right'">end</xsl:when><xsl:when test="字:对齐/@字:水平对齐='center'">center</xsl:when><xsl:otherwise>justify</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="字:对齐/@字:水平对齐='distributed'">
+ <xsl:attribute name="fo:text-align-last">justify</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style:justify-single-word">false</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:call-template name="ParagraphAttr"/>
+ <xsl:if test="字:段落属性/字:制表位设置">
+ <xsl:call-template name="ootab"/>
+ </xsl:if>
+ </xsl:element>
+ <xsl:if test="字:句属性">
+ <xsl:variable name="bsh">
+ <xsl:value-of select="字:句属性/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:element name="style:text-properties">
+ <xsl:for-each select="/uof:UOF//uof:句式样">
+ <xsl:if test="$bsh=@字:标识符">
+ <xsl:apply-templates select="./*"/>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="字:边框">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:element name="style:text-properties">
+ <xsl:if test="字:句/字:句属性/字:字体">
+ <xsl:variable name="ziti">
+ <xsl:value-of select="字:句/字:句属性/字:字体/@字:中文字体引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:字体集/uof:字体声明">
+ <xsl:if test="@uof:标识符=$ziti">
+ <xsl:attribute name="style:font-name"><xsl:value-of select="@uof:名称"/></xsl:attribute>
+ <xsl:attribute name="style:font-name-asian"><xsl:value-of select="@uof:名称"/></xsl:attribute>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:if test="字:句/字:句属性/字:字体/@字:字号">
+ <xsl:attribute name="fo:font-size"><xsl:value-of select="字:句/字:句属性/字:字体/@字:字号"/></xsl:attribute>
+ <xsl:attribute name="style:font-size-asian"><xsl:value-of select="字:句/字:句属性/字:字体/@字:字号"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:句属性">
+ <xsl:for-each select="字:段落属性/字:句属性">
+ <xsl:apply-templates select="./*"/>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:apply-templates select="字:句/字:句属性/字:浮雕 | 字:句/字:句属性/字:边框 | 字:句/字:句属性/字:缩放 | 字:句/字:句属性/字:阴影 | 字:句/字:句属性/字:删除线 | 字:句/字:句属性/字:下划线 | 字:句/字:填充"/>
+ <xsl:call-template name="ParagraphAttr"/>
+ <xsl:if test="字:段落属性/字:制表位设置">
+ <xsl:call-template name="ootab"/>
+ </xsl:if>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样[@字:标识符=$stylename]">
+ <xsl:apply-templates select="./*"/>
+ </xsl:for-each>
+ </xsl:element>
+ <style:paragraph-properties>
+ <xsl:if test="字:句/字:分栏符">
+ <xsl:attribute name="fo:break-before">column</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:句/字:分页符">
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="ParagraphAttr"/>
+ <xsl:if test="字:段落属性/字:制表位设置">
+ <xsl:call-template name="ootab"/>
+ </xsl:if>
+ </style:paragraph-properties>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="ParagraphAttr">
+ <xsl:apply-templates select="字:段落属性/字:填充"/>
+ <xsl:if test="字:段落属性/字:对齐">
+ <xsl:if test="字:段落属性/字:对齐/@字:文字对齐">
+ <xsl:attribute name="style:vertical-align"><xsl:choose><xsl:when test="字:段落属性/字:对齐/@字:文字对齐='base'">baseline</xsl:when><xsl:when test="字:段落属性/字:对齐/@字:文字对齐='center'">middle</xsl:when><xsl:otherwise><xsl:value-of select="字:段落属性/字:对齐/@字:文字对齐"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:对齐/@字:水平对齐">
+ <xsl:attribute name="fo:text-align"><xsl:choose><xsl:when test="字:段落属性/字:对齐/@字:水平对齐='left'">start</xsl:when><xsl:when test="字:段落属性/字:对齐/@字:水平对齐='right'">end</xsl:when><xsl:when test="字:段落属性/字:对齐/@字:水平对齐='center'">center</xsl:when><xsl:otherwise>justify</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="字:段落属性/字:对齐/@字:水平对齐='distributed'">
+ <xsl:attribute name="fo:text-align-last">justify</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style:justify-single-word">false</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="字:段落属性/字:缩进">
+ <xsl:variable name="a1">
+ <xsl:value-of select="字:段落属性/字:缩进/字:左/字:相对/@字:值"/>
+ </xsl:variable>
+ <xsl:variable name="a2">
+ <xsl:value-of select="字:段落属性/字:缩进/字:右/字:相对/@字:值"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="字:段落属性/字:缩进/字:左/字:相对 or 字:段落属性/字:缩进/字:右/字:相对">
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat($a1 * 0.37,'cm')"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat($a2 * 0.37,'cm')"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(字:段落属性/字:缩进/字:左/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(字:段落属性/字:缩进/字:右/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:attribute name="fo:text-indent"><xsl:value-of select="concat(字:段落属性/字:缩进/字:首行/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="ancestor::uof:UOF/uof:式样集/uof:自动编号集/字:自动编号/字:级别[following-sibling::字:级别[position()=1]/@字:级别值='1']/字:缩进">
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(ancestor::uof:UOF/uof:式样集/uof:自动编号集/字:自动编号/字:级别[following-sibling::字:级别[position()=1]/@字:级别值='1']/字:缩进/字:左/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(ancestor::uof:UOF/uof:式样集/uof:自动编号集/字:自动编号/字:级别[following-sibling::字:级别[position()=1]/@字:级别值='1']/字:缩进/字:右/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:text-indent"><xsl:value-of select="concat(ancestor::uof:UOF/uof:式样集/uof:自动编号集/字:自动编号/字:级别[following-sibling::字:级别[position()=1]/@字:级别值='1']/字:缩进/字:首行/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="字:段落属性/字:行距">
+ <xsl:variable name="type">
+ <xsl:value-of select="字:段落属性/字:行距/@字:类型"/>
+ </xsl:variable>
+ <xsl:variable name="val">
+ <xsl:value-of select="字:段落属性/字:行距/@字:值"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$type='fixed'">
+ <xsl:attribute name="fo:line-height"><xsl:value-of select="concat($val,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$type='multi-lines'">
+ <xsl:attribute name="fo:line-height"><xsl:value-of select="concat($val * 100,'%')"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$type='at-least'">
+ <xsl:attribute name="style:line-height-at-least"><xsl:value-of select="concat($val,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$type='line-space'">
+ <xsl:attribute name="style:line-spacing"><xsl:value-of select="concat($val,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:段间距">
+ <xsl:if test="字:段落属性/字:段间距/字:段前距/字:绝对值/@字:值">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(字:段落属性/字:段间距/字:段前距/字:绝对值/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:段间距/字:段后距/字:绝对值/@字:值">
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(字:段落属性/字:段间距/字:段后距/字:绝对值/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="aa">
+ <xsl:value-of select="字:段落属性/字:段间距/字:段前距/字:相对值/@字:值"/>
+ </xsl:variable>
+ <xsl:variable name="bb">
+ <xsl:value-of select="字:段落属性/字:段间距/字:段后距/字:相对值/@字:值"/>
+ </xsl:variable>
+ <xsl:if test="字:段落属性/字:段间距/字:段前距/字:相对值/@字:值">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat($aa * 15.6,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:段间距/字:段后距/字:相对值/@字:值">
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat($bb * 15.6,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:孤行控制">
+ <xsl:attribute name="fo:widows"><xsl:value-of select="字:段落属性/字:孤行控制"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:寡行控制">
+ <xsl:attribute name="fo:orphans"><xsl:value-of select="字:段落属性/字:寡行控制"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:段中不分页">
+ <xsl:attribute name="fo:keep-together"><xsl:choose><xsl:when test="字:段落属性/字:段中不分页/@字:值='1' or 字:段落属性/字:段中不分页/@字:值='true'">always</xsl:when><xsl:otherwise>auto</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:与下段同页">
+ <xsl:attribute name="fo:keep-with-next"><xsl:choose><xsl:when test="字:段落属性/字:与下段同页/@字:值='1' or 字:段落属性/字:与下段同页/@字:值='true'">always</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="字:段落属性/字:边框">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ <xsl:for-each select="字:段落属性/字:填充">
+ <xsl:call-template name="uof:填充"/>
+ </xsl:for-each>
+ <xsl:if test="字:段落属性/字:对齐网格">
+ <xsl:attribute name="style:snap-to-layout-grid"><xsl:choose><xsl:when test="字:段落属性/字:对齐网格/@字:值='1' or 字:段落属性/字:对齐网格/@字:值='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:取消断字">
+ <xsl:attribute name="fo:hyphenation-ladder-count">no-limit</xsl:attribute>
+ <xsl:attribute name="fo:hyphenation-remain-char-count">2</xsl:attribute>
+ <xsl:attribute name="fo:hyphenation-push-char-count">2</xsl:attribute>
+ <xsl:attribute name="fo:hyphenate"><xsl:choose><xsl:when test="字:段落属性/字:取消断字/@字:值='1' or 字:段落属性/字:取消断字/@字:值='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:取消行号">
+ <xsl:attribute name="text:number-lines"><xsl:choose><xsl:when test="字:段落属性/字:取消行号/@字:值='1' or 字:段落属性/字:取消行号/@字:值='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:行首尾标点控制">
+ <xsl:attribute name="style:punctuation-wrap"><xsl:choose><xsl:when test="字:段落属性/字:行首尾标点控制/@字:值='1' or 字:段落属性/字:行首尾标点控制/@字:值='true'">hanging</xsl:when><xsl:otherwise>simple</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:是否行首标点压缩/@字:值='true'">
+ <xsl:attribute name="style:punctuation-compress">false</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:中文习惯首尾字符">
+ <xsl:attribute name="style:line-break"><xsl:choose><xsl:when test="字:段落属性/字:中文习惯首尾字符/@字:值='1' or 字:段落属性/字:中文习惯首尾字符/@字:值='true'">strict</xsl:when><xsl:otherwise>normal</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:自动调整中英文字符间距 or 字:段落属性/字:自动调整中文与数字间距">
+ <xsl:attribute name="style:text-autospace"><xsl:choose><xsl:when test="字:段落属性/字:自动调整中英文字符间距/@字:值='1' or 字:段落属性/字:自动调整中文与数字间距/@字:值='1'or 字:段落属性/字:自动调整中英文字符间距/@字:值='true' or 字:段落属性/字:自动调整中文与数字间距/@字:值='true'">ideograph-alpha</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:首字下沉">
+ <xsl:element name="style:drop-cap">
+ <xsl:if test="字:段落属性/字:首字下沉/@字:行数">
+ <xsl:attribute name="style:lines"><xsl:value-of select="字:段落属性/字:首字下沉/@字:行数"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:首字下沉/@字:间距">
+ <xsl:attribute name="style:distance"><xsl:value-of select="concat(字:段落属性/字:首字下沉/@字:间距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:首字下沉/@字:字体引用">
+ <xsl:attribute name="style:style-name"><xsl:value-of select="translate(字:段落属性/字:首字下沉/@字:字体引用,'_',' ')"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段落属性/字:首字下沉/@字:字符数">
+ <xsl:attribute name="style:length"><xsl:choose><xsl:when test="字:段落属性/字:首字下沉/@字:字符数='1'">word</xsl:when><xsl:otherwise><xsl:value-of select="字:段落属性/字:首字下沉/@字:字符数"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="XDParagraphAttr">
+ <xsl:apply-templates select="字:填充"/>
+ <xsl:if test="字:对齐">
+ <xsl:if test="字:对齐/@字:文字对齐">
+ <xsl:attribute name="style:vertical-align"><xsl:choose><xsl:when test="字:对齐/@字:文字对齐='base'">baseline</xsl:when><xsl:when test="字:对齐/@字:文字对齐='center'">middle</xsl:when><xsl:otherwise><xsl:value-of select="字:对齐/@字:文字对齐"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:对齐/@字:水平对齐">
+ <xsl:attribute name="fo:text-align"><xsl:choose><xsl:when test="字:对齐/@字:水平对齐='left'">start</xsl:when><xsl:when test="字:对齐/@字:水平对齐='right'">end</xsl:when><xsl:when test="字:对齐/@字:水平对齐='center'">center</xsl:when><xsl:otherwise>justify</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="字:对齐/@字:水平对齐='distributed'">
+ <xsl:attribute name="fo:text-align-last">justify</xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style:justify-single-word">false</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="字:缩进">
+ <xsl:if test="字:缩进/字:左/字:绝对/@字:值">
+ <xsl:attribute name="fo:margin-left"><xsl:value-of select="concat(字:缩进/字:左/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:缩进/字:右/字:绝对/@字:值">
+ <xsl:attribute name="fo:margin-right"><xsl:value-of select="concat(字:缩进/字:右/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:缩进/字:首行/字:绝对/@字:值">
+ <xsl:attribute name="fo:text-indent"><xsl:value-of select="concat(字:缩进/字:首行/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="字:行距">
+ <xsl:variable name="type">
+ <xsl:value-of select="字:行距/@字:类型"/>
+ </xsl:variable>
+ <xsl:variable name="val">
+ <xsl:value-of select="字:行距/@字:值"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$type='fixed'">
+ <xsl:attribute name="fo:line-height"><xsl:value-of select="concat($val,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$type='multi-lines'">
+ <xsl:attribute name="fo:line-height"><xsl:value-of select="concat($val * 100,'%')"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$type='at-least'">
+ <xsl:attribute name="style:line-height-at-least"><xsl:value-of select="concat($val,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$type='line-space'">
+ <xsl:attribute name="style:line-spacing"><xsl:value-of select="concat($val,$uofUnit)"/></xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="字:段间距">
+ <xsl:if test="字:段间距/字:段前距/字:绝对值/@字:值">
+ <xsl:attribute name="fo:margin-top"><xsl:value-of select="concat(字:段间距/字:段前距/字:绝对值/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段间距/字:段后距/字:绝对值/@字:值">
+ <xsl:attribute name="fo:margin-bottom"><xsl:value-of select="concat(字:段间距/字:段后距/字:绝对值/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="字:孤行控制">
+ <xsl:attribute name="fo:orphans"><xsl:value-of select="字:孤行控制"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:寡行控制">
+ <xsl:attribute name="fo:widows"><xsl:value-of select="字:寡行控制"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:段中不分页">
+ <xsl:attribute name="fo:keep-together"><xsl:choose><xsl:when test="字:段中不分页/@字:值='1' or 字:段中不分页/@字:值='true'">always</xsl:when><xsl:otherwise>auto</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:与下段同页">
+ <xsl:attribute name="fo:keep-with-next"><xsl:choose><xsl:when test="字:与下段同页/@字:值='1' or 字:与下段同页/@字:值='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:for-each select="字:边框">
+ <xsl:call-template name="uof:边框"/>
+ </xsl:for-each>
+ <xsl:for-each select="字:填充">
+ <xsl:call-template name="uof:填充"/>
+ </xsl:for-each>
+ <xsl:if test="字:对齐网格">
+ <xsl:attribute name="style:snap-to-layout-grid"><xsl:choose><xsl:when test="字:对齐网格/@字:值='1' or 字:对齐网格/@字:值='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:取消断字">
+ <xsl:attribute name="fo:hyphenation-ladder-count">no-limit</xsl:attribute>
+ <xsl:attribute name="fo:hyphenation-remain-char-count">2</xsl:attribute>
+ <xsl:attribute name="fo:hyphenation-push-char-count">2</xsl:attribute>
+ <xsl:attribute name="fo:hyphenate"><xsl:choose><xsl:when test="字:取消断字/@字:值='1' or 字:取消断字/@字:值='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:取消行号">
+ <xsl:attribute name="text:number-lines"><xsl:choose><xsl:when test="字:取消行号/@字:值='1' or 字:取消行号/@字:值='true'">true</xsl:when><xsl:otherwise>false</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:行首尾标点控制">
+ <xsl:attribute name="style:punctuation-wrap"><xsl:choose><xsl:when test="字:行首尾标点控制/@字:值='1' or 字:行首尾标点控制/@字:值='true'">hanging</xsl:when><xsl:otherwise>simple</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:是否行首标点压缩/@字:值='true'">
+ <xsl:attribute name="style:punctuation-compress">false</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:中文习惯首尾字符">
+ <xsl:attribute name="style:line-break"><xsl:choose><xsl:when test="字:中文习惯首尾字符/@字:值='1' or 字:中文习惯首尾字符/@字:值='true'">strict</xsl:when><xsl:otherwise>normal</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:自动调整中英文字符间距 or 字:自动调整中文与数字间距">
+ <xsl:attribute name="style:text-autospace"><xsl:choose><xsl:when test="字:自动调整中英文字符间距/@字:值='1' or 字:自动调整中文与数字间距/@字:值='1'or 字:自动调整中英文字符间距/@字:值='true' or 字:自动调整中文与数字间距/@字:值='true'">ideograph-alpha</xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:首字下沉">
+ <xsl:element name="style:drop-cap">
+ <xsl:if test="字:首字下沉/@字:行数">
+ <xsl:attribute name="style:lines"><xsl:value-of select="字:首字下沉/@字:行数"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:首字下沉/@字:间距">
+ <xsl:attribute name="style:distance"><xsl:value-of select="concat(字:首字下沉/@字:间距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:首字下沉/@字:字体引用">
+ <xsl:attribute name="style:style-name"><xsl:value-of select="字:首字下沉/@字:字体引用"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:首字下沉/@字:字符数">
+ <xsl:attribute name="style:length"><xsl:choose><xsl:when test="字:首字下沉/@字:字符数='1'">word</xsl:when><xsl:otherwise><xsl:value-of select="字:首字下沉/@字:字符数"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="多个句">
+ <xsl:call-template name="单个或者没有句"/>
+ </xsl:template>
+ <xsl:template name="jibianhao">
+ <xsl:param name="biaoshifu"/>
+ <xsl:element name="text:list-level-style-number">
+ <xsl:variable name="currlevel" select="number(@字:级别值) + 1"/>
+ <xsl:attribute name="text:level"><xsl:value-of select="$currlevel"/></xsl:attribute>
+ <xsl:attribute name="text:style-name">Numbering Symbols</xsl:attribute>
+ <xsl:if test="@字:尾随字符">
+ <xsl:attribute name="style:num-suffix"><xsl:choose><xsl:when test="@字:尾随字符='space'"><xsl:value-of select="' ' "/></xsl:when><xsl:when test="@字:尾随字符='tab'"><xsl:value-of select="' '"/></xsl:when><xsl:otherwise>none</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:符号字体">
+ <xsl:variable name="Font-ID">
+ <xsl:value-of select="字:符号字体/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="$Font-ID"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:起始编号">
+ <xsl:attribute name="text:start-value"><xsl:value-of select="字:起始编号"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:正规格式">
+ <xsl:attribute name="text:num-regular-exp"><xsl:value-of select="字:正规格式/@值"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="text:display-levels"><xsl:value-of select="string-length(字:编号格式表示) - string-length(translate(字:编号格式表示,'%','') )"/></xsl:attribute>
+ <xsl:if test="字:编号格式">
+ <xsl:call-template name="编号格式"/>
+ </xsl:if>
+ <xsl:if test="字:编号格式表示">
+ <xsl:variable name="last" select="substring-after(字:编号格式表示,concat('%',$currlevel))"/>
+ <xsl:variable name="first">
+ <xsl:variable name="aa" select="substring-before(字:编号格式表示,concat('%',$currlevel))"/>
+ <xsl:choose>
+ <xsl:when test="not(substring-after($aa,'%'))">
+ <xsl:value-of select="$aa"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$first!=''">
+ <xsl:attribute name="style:num-prefix"><xsl:value-of select="$first"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$last!=''">
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="$last"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="bianhaogeshi">
+ <xsl:with-param name="biaoshi">
+ <xsl:value-of select="字:编号格式表示"/>
+ </xsl:with-param>
+ <xsl:with-param name="jibie">
+ <xsl:value-of select="1"/>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:element name="style:text-properties">
+ <xsl:call-template name="suojinleixing"/>
+ <xsl:if test="@字:编号对齐方式">
+ <xsl:attribute name="fo:text-align"><xsl:variable name="aa"><xsl:value-of select="@字:编号对齐方式"/></xsl:variable><xsl:choose><xsl:when test="$aa='center' ">center</xsl:when><xsl:when test="$aa='right' ">end</xsl:when><xsl:otherwise>left</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="字:符号字体">
+ <xsl:if test="字:符号字体/@字:式样引用">
+ <xsl:variable name="Font-ID">
+ <xsl:value-of select="字:符号字体/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样">
+ <xsl:if test="@字:标识符=$Font-ID">
+ <xsl:if test="字:字体/@字:中文字体引用">
+ <xsl:attribute name="fo:font-family"><xsl:value-of select="字:字体/@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="bianhaogeshi">
+ <xsl:param name="biaoshi"/>
+ <xsl:param name="jibie"/>
+ <xsl:variable name="bb">
+ <xsl:value-of select="substring-after($biaoshi,'%')"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="substring-after($bb,'%')">
+ <xsl:call-template name="bianhaogeshi">
+ <xsl:with-param name="biaoshi" select="$bb"/>
+ <xsl:with-param name="jibie" select="$jibie +1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="not($jibie=1)">
+ <xsl:attribute name="text:display-levels"><xsl:value-of select="$jibie"/></xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="xiangmufuhao">
+ <xsl:param name="biaoshifu"/>
+ <xsl:variable name="currlevel" select="number(@字:级别值) + 1"/>
+ <xsl:element name="text:list-level-style-bullet">
+ <xsl:attribute name="text:level"><xsl:value-of select="$currlevel"/></xsl:attribute>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="../@字:名称"/></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="substring-after(字:编号格式表示,'%1')"/></xsl:attribute>
+ <xsl:attribute name="text:bullet-char"><xsl:value-of select="字:项目符号"/></xsl:attribute>
+ <xsl:element name="style:text-properties">
+ <xsl:if test="字:符号字体">
+ <xsl:variable name="Font-ID">
+ <xsl:value-of select="字:符号字体/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样">
+ <xsl:if test="@字:标识符=$Font-ID">
+ <xsl:if test="字:字体/@字:中文字体引用">
+ <xsl:attribute name="svg:font-family"><xsl:value-of select="字:字体/@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="字:项目符号">
+ <xsl:attribute name="fo:font-family"><xsl:value-of select="'WingDings'"/></xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="suojinleixing"/>
+ <xsl:if test="@字:编号对齐方式">
+ <xsl:attribute name="fo:text-align"><xsl:variable name="aa"><xsl:value-of select="@字:编号对齐方式"/></xsl:variable><xsl:choose><xsl:when test="$aa='center' ">center</xsl:when><xsl:when test="$aa='right' ">end</xsl:when><xsl:otherwise>left</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="imagefuhao">
+ <xsl:param name="biaoshifu"/>
+ <xsl:variable name="currlevel" select="number(@字:级别值) + 1"/>
+ <xsl:element name="text:list-level-style-image" style:vertical-pos="middle" style:vertical-rel="line" fo:width="0.265cm" fo:height="0.265cm">
+ <xsl:attribute name="text:level"><xsl:value-of select="$currlevel"/></xsl:attribute>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat( $biaoshifu,$currlevel)"/></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="substring-after(字:编号格式表示,'%1')"/></xsl:attribute>
+ <xsl:if test="字:图片符号引用">
+ <xsl:variable name="gid">
+ <xsl:value-of select="字:图片符号引用"/>
+ </xsl:variable>
+ <xsl:element name="office:binary-data">
+ <xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$gid]/uof:数据"/>
+ </xsl:element>
+ </xsl:if>
+ <xsl:element name="style:list-level-properties">
+ <xsl:attribute name="style:vertical-pos">middle</xsl:attribute>
+ <xsl:attribute name="style:vertical-rel">line</xsl:attribute>
+ <xsl:attribute name="fo:width"><xsl:value-of select="concat(字:图片符号引用/@字:宽度,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="fo:height"><xsl:value-of select="concat(字:图片符号引用/@字:高度,$uofUnit)"/></xsl:attribute>
+ <xsl:if test="字:符号字体">
+ <xsl:variable name="Font-ID">
+ <xsl:value-of select="字:符号字体/@字:式样引用"/>
+ </xsl:variable>
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:句式样">
+ <xsl:if test="@字:标识符=$Font-ID">
+ <xsl:if test="字:字体/@字:中文字体引用">
+ <xsl:attribute name="svg:font-family"><xsl:value-of select="字:字体/@字:中文字体引用"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:call-template name="suojinleixing"/>
+ <xsl:if test="@字:编号对齐方式">
+ <xsl:attribute name="fo:text-align"><xsl:variable name="aa"><xsl:value-of select="@字:编号对齐方式"/></xsl:variable><xsl:choose><xsl:when test="$aa='center' ">center</xsl:when><xsl:when test="$aa='right' ">end</xsl:when><xsl:otherwise>left</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="ootab">
+ <xsl:element name="style:tab-stops">
+ <xsl:for-each select="字:段落属性/字:制表位设置/字:制表位 | 字:制表位设置/字:制表位">
+ <xsl:element name="style:tab-stop">
+ <xsl:attribute name="style:position"><xsl:value-of select="concat(@字:位置,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="style:type"><xsl:choose><xsl:when test="@字:类型='decimal'">char</xsl:when><xsl:when test="@字:类型='left' or @字:类型='right' or @字:类型='center'"><xsl:value-of select="@字:类型"/></xsl:when><xsl:otherwise/></xsl:choose></xsl:attribute>
+ <xsl:if test="@字:制表位字符">
+ <xsl:attribute name="style:leader-text"><xsl:value-of select="@字:制表位字符"/></xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style:leader-style"><xsl:value-of select="@字:前导符"/></xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="字:段落[字:段落属性[字:自动编号信息]]">
+ <xsl:call-template name="编号解析">
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="编号解析">
+ <xsl:variable name="bianhao">
+ <xsl:value-of select="字:段落属性/字:自动编号信息/@字:编号引用"/>
+ </xsl:variable>
+ <xsl:variable name="bianhaojibie">
+ <xsl:value-of select="字:段落属性/字:自动编号信息/@字:编号级别"/>
+ </xsl:variable>
+ <xsl:variable name="isxiangmuorisimage">
+ <xsl:for-each select="/uof:UOF/uof:式样集/uof:自动编号集/字:自动编号">
+ <xsl:choose>
+ <xsl:when test="$bianhao=@字:标识符">
+ <xsl:choose>
+ <xsl:when test="字:级别[@字:级别值= (number($bianhaojibie))]/字:项目符号">true</xsl:when>
+ <xsl:when test="字:级别[@字:级别值= (number($bianhaojibie))]/字:图片符号引用">true</xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>false</xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$isxiangmuorisimage='true'">
+ <xsl:call-template name="无序"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="有序"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="有序">
+ <xsl:variable name="currlistid" select="字:段落属性/字:自动编号信息/@字:编号引用"/>
+ <xsl:variable name="currlistlvl" select="字:段落属性/字:自动编号信息/@字:编号级别 + 1"/>
+ <xsl:variable name="firstoccur" select="/descendant::字:段落属性[字:自动编号信息/@字:编号引用 = $currlistid][1]"/>
+ <xsl:element name="text:list">
+ <xsl:attribute name="text:style-name">List<xsl:value-of select="count($firstoccur/preceding::字:自动编号信息)"/></xsl:attribute>
+ <xsl:attribute name="text:continue-numbering"><xsl:choose><xsl:when test="字:段落属性/字:自动编号信息/@字:重新编号='false'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:if test="字:段落属性/字:自动编号信息/@字:重新编号">
+ <xsl:attribute name="text:continue-numbering"><xsl:choose><xsl:when test="字:段落属性/字:自动编号信息/@字:重新编号='1'">false</xsl:when><xsl:otherwise>true</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="ordered-levels">
+ <xsl:with-param name="level" select="$currlistlvl - 1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="ordered-levels">
+ <xsl:param name="level"/>
+ <xsl:choose>
+ <xsl:when test="$level = '0'">
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="text:list">
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="ordered-levels">
+ <xsl:with-param name="level" select="$level - 1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="无序">
+ <xsl:variable name="currlistid" select="字:段落属性/字:自动编号信息/@字:编号引用"/>
+ <xsl:variable name="currlistlvl" select="字:段落属性/字:自动编号信息/@字:编号级别 + 1"/>
+ <xsl:variable name="firstoccur" select="/descendant::字:段落属性[字:自动编号信息/@字:编号引用 = $currlistid][1]"/>
+ <xsl:element name="text:list">
+ <xsl:attribute name="text:style-name">List<xsl:value-of select="count($firstoccur/preceding::字:自动编号信息)"/></xsl:attribute>
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="unordered-levels">
+ <xsl:with-param name="level" select="$currlistlvl - 1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="unordered-levels">
+ <xsl:param name="level"/>
+ <xsl:choose>
+ <xsl:when test="$level = '0'">
+ <xsl:call-template name="commonParagraph"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="text:list">
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="unordered-levels">
+ <xsl:with-param name="level" select="$level - 1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- measure_conversion.xsl Begin-->
+ <xsl:param name="dpi" select="111"/>
+ <xsl:param name="centimeter-in-mm" select="10"/>
+ <xsl:param name="inch-in-mm" select="25.4"/>
+ <xsl:param name="didot-point-in-mm" select="0.376065"/>
+ <xsl:param name="pica-in-mm" select="4.2333333"/>
+ <xsl:param name="point-in-mm" select="0.3527778"/>
+ <xsl:param name="twip-in-mm" select="0.017636684"/>
+ <xsl:param name="pixel-in-mm" select="$inch-in-mm div $dpi"/>
+ <!-- ***** MEASUREMENT CONVERSIONS *****
+ PARAM 'value'
+ The measure to be converted.
+ The current measure is judged by a substring (e.g. 'mm', 'cm', 'in', 'pica'...)
+ directly added to the number.
+
+ PARAM 'rounding-factor'
+ Is used for the rounding of decimal places.
+ The parameter number is the product of 1 and some '10', where
+ every zero represents a decimal place.
+
+ For example, providing as parameter:
+ <xsl:param name="rounding-factor" select="10000" />
+ Gives by default four decimal places.
+
+ To round two decimal places, basically the following is done:
+ <xsl:value-of select="round(100 * value) div 100"/>
+
+ RETURN The converted number, by default rounded to four decimal places.
+ In case the input measure could not be matched the same value is
+ returned and a warning message is written out.
+
+
+
+ MEASURE LIST:
+ * 1 millimeter (mm), the basic measure
+
+ * 1 centimeter (cm) = 10 mm
+
+ * 1 inch (in) = 25.4 mm
+ While the English have already seen the light (read: the metric system), the US
+ remains loyal to this medieval system.
+
+ * 1 point (pt) = 0.35277777.. mm
+ Sometimes called PostScript point (ppt), as when Adobe created PostScript, they added their own system of points.
+ There are exactly 72 PostScript points in 1 inch.
+
+ * 1 twip = twentieth of a (PostScript) point
+ A twip (twentieth of a point) is a 1/20th of a PostScript point, a traditional measure in printing.
+
+ * 1 didot point (dpt) = 0.376065 mm
+ Didot point after the French typographer Firmin Didot (1764-1836).
+
+ More details under
+ http://www.unc.edu/~rowlett/units/dictP.html:
+ "A unit of length used by typographers and printers. When printing was done
+ from hand-set metal type, one point represented the smallest element of type
+ that could be handled, roughly 1/64 inch. Eventually, the point was standardized
+ in Britain and America as exactly 1/72.27 = 0.013 837 inch, which is
+ about 0.35 mm (351.46 micrometers). In continental Europe, typographers
+ traditionally used a slightly larger point of 0.014 83 inch (about
+ 1/72 pouce, 0.377 mm, or roughly 1/67 English inch), called a Didot point
+ after the French typographer Firmin Didot (1764-1836). In the U.S.,
+ Adobe software defines the point to be exactly 1/72 inch (0.013 888 9 inch
+ or 0.352 777 8 millimeters) and TeX software uses a slightly smaller point
+ of 0.351 459 8035 mm. The German standards agency DIN has proposed that
+ all these units be replaced by multiples of 0.25 millimeters (1/101.6 inch).
+
+ * 1 pica = 4.233333 mm
+ 1/6 inch or 12 points
+
+ * 1 pixel (px) = 0.26458333.. mm (relative to 'DPI', here: 96 dpi)
+ Most pictures have the 96 dpi resolution, but the dpi variable may vary by stylesheet parameter
+
+
+ -->
+ <!-- changing measure to mm -->
+ <xsl:template name="convert2cm">
+ <xsl:param name="value"/>
+ <xsl:param name="rounding-factor" select="10000"/>
+ <xsl:choose>
+ <xsl:when test="contains($value, 'mm')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'mm') div $centimeter-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, $uofUnit)">
+ <xsl:value-of select="substring-before($value, $uofUnit)"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'in')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'in') div $centimeter-in-mm * $inch-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pt') div $centimeter-in-mm * $point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'dpt')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'dpt') div $centimeter-in-mm * $didot-point-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'pica')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'pica') div $centimeter-in-mm * $pica-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'twip')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'twip') div $centimeter-in-mm * $twip-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:when test="contains($value, 'px')">
+ <xsl:value-of select="round($rounding-factor * number(substring-before($value, 'px') div $centimeter-in-mm * $pixel-in-mm)) div $rounding-factor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>measure_conversion.xsl: Find no conversion for <xsl:value-of select="$value"/> to 'cm'!</xsl:message>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="uof:通用边框">
+ <xsl:param name="lineType"/>
+ <xsl:param name="width"/>
+ <xsl:param name="color"/>
+ <xsl:choose>
+ <xsl:when test="$lineType='none'">none</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$width"/>
+ <xsl:choose>
+ <xsl:when test="$lineType='single'">solid </xsl:when>
+ <xsl:when test="$lineType='double'">double </xsl:when>
+ <xsl:otherwise>solid </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="$color='auto' or $color='none' or $color=''">#808080</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$color"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="uof:边框">
+ <xsl:if test="uof:上">
+ <xsl:variable name="type" select="uof:上/@uof:类型"/>
+ <xsl:variable name="size" select="concat(uof:上/@uof:宽度,$uofUnit,' ')"/>
+ <xsl:variable name="clr" select="uof:上/@uof:颜色"/>
+ <xsl:attribute name="fo:border-top"><xsl:call-template name="uof:通用边框"><xsl:with-param name="lineType" select="$type"/><xsl:with-param name="width" select="$size"/><xsl:with-param name="color" select="$clr"/></xsl:call-template></xsl:attribute>
+ <xsl:if test="uof:上/@uof:线宽度">
+ <xsl:attribute name="style:border-line-width-top"><xsl:value-of select="uof:上/@uof:线宽度"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="uof:下">
+ <xsl:variable name="type" select="uof:下/@uof:类型"/>
+ <xsl:variable name="size" select="concat(uof:下/@uof:宽度,$uofUnit,' ')"/>
+ <xsl:variable name="clr" select="uof:下/@uof:颜色"/>
+ <xsl:attribute name="fo:border-bottom"><xsl:call-template name="uof:通用边框"><xsl:with-param name="lineType" select="$type"/><xsl:with-param name="width" select="$size"/><xsl:with-param name="color" select="$clr"/></xsl:call-template></xsl:attribute>
+ <xsl:if test="uof:下/@uof:线宽度">
+ <xsl:attribute name="style:border-line-width-bottom"><xsl:value-of select="uof:下/@uof:线宽度"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="uof:左">
+ <xsl:variable name="type" select="uof:左/@uof:类型"/>
+ <xsl:variable name="size" select="concat(uof:左/@uof:宽度,$uofUnit,' ')"/>
+ <xsl:variable name="clr" select="uof:左/@uof:颜色"/>
+ <xsl:attribute name="fo:border-left"><xsl:call-template name="uof:通用边框"><xsl:with-param name="lineType" select="$type"/><xsl:with-param name="width" select="$size"/><xsl:with-param name="color" select="$clr"/></xsl:call-template></xsl:attribute>
+ <xsl:if test="uof:左/@uof:线宽度">
+ <xsl:attribute name="style:border-line-width-left"><xsl:value-of select="uof:左/@uof:线宽度"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="uof:右">
+ <xsl:variable name="type" select="uof:右/@uof:类型"/>
+ <xsl:variable name="size" select="concat(uof:右/@uof:宽度,$uofUnit,' ')"/>
+ <xsl:variable name="clr" select="uof:右/@uof:颜色"/>
+ <xsl:attribute name="fo:border-right"><xsl:call-template name="uof:通用边框"><xsl:with-param name="lineType" select="$type"/><xsl:with-param name="width" select="$size"/><xsl:with-param name="color" select="$clr"/></xsl:call-template></xsl:attribute>
+ <xsl:if test="uof:右/@uof:线宽度">
+ <xsl:attribute name="style:border-line-width-right"><xsl:value-of select="uof:右/@uof:线宽度"/></xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="uof:上/@uof:阴影='true'or uof:上/@uof:阴影='1'">
+ <xsl:if test="uof:左/@uof:阴影='true'or uof:左/@uof:阴影='1'">
+ <xsl:attribute name="style:shadow">#808080 -0.18cm -0.18cm</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="uof:上/@uof:阴影='true'or uof:上/@uof:阴影='1'">
+ <xsl:if test="uof:右/@uof:阴影='true'or uof:右/@uof:阴影='1'">
+ <xsl:attribute name="style:shadow">#808080 0.18cm -0.18cm</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="uof:下/@uof:阴影='true'or uof:下/@uof:阴影='1'">
+ <xsl:if test="uof:左/@uof:阴影='true'or uof:左/@uof:阴影='1'">
+ <xsl:attribute name="style:shadow">#808080 -0.18cm 0.18cm</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="uof:下/@uof:阴影='true'or uof:下/@uof:阴影='1'">
+ <xsl:if test="uof:右/@uof:阴影='true'or uof:右/@uof:阴影='1'">
+ <xsl:attribute name="style:shadow">#808080 0.18cm 0.18cm</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="uof:上/@uof:边距">
+ <xsl:attribute name="fo:padding-top"><xsl:value-of select="concat(uof:上/@uof:边距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="uof:下/@uof:边距">
+ <xsl:attribute name="fo:padding-bottom"><xsl:value-of select="concat(uof:下/@uof:边距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="uof:左/@uof:边距">
+ <xsl:attribute name="fo:padding-left"><xsl:value-of select="concat(uof:左/@uof:边距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="uof:右/@uof:边距">
+ <xsl:attribute name="fo:padding-right"><xsl:value-of select="concat(uof:右/@uof:边距,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="uof:填充">
+ <xsl:choose>
+ <xsl:when test="图:颜色">
+ <xsl:attribute name="fo:background-color"><xsl:choose><xsl:when test="图:颜色"><xsl:value-of select="图:颜色"/></xsl:when><xsl:otherwise>transparent</xsl:otherwise></xsl:choose></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(图:图案/@图:前景色,'#')">
+ <xsl:attribute name="fo:text-background-color"><xsl:value-of select="图:图案/@图:前景色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="图:图案/@图:背景色">
+ <xsl:attribute name="fo:background-color"><xsl:value-of select="图:图案/@图:背景色"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ <xsl:if test="图:图片">
+ <xsl:element name="style:background-image">
+ <xsl:variable name="gid">
+ <xsl:value-of select="图:图片/@图:图形引用"/>
+ </xsl:variable>
+ <xsl:if test="图:图片/@图:位置 and not(图:图片/@图:位置='tile')">
+ <xsl:attribute name="style:repeat"><xsl:choose><xsl:when test="图:图片/@图:位置='stretch'">stretch</xsl:when><xsl:when test="图:图片/@图:位置='center'">no-repeat</xsl:when></xsl:choose></xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$gid]/uof:数据">
+ <xsl:element name="office:binary-data">
+ <xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$gid]/uof:数据"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="xlink:href"><xsl:value-of select="/uof:UOF/uof:对象集/uof:其他对象[@uof:标识符=$gid]/uof:路径"/></xsl:attribute>
+ <xsl:attribute name="xlink:type">simple</xsl:attribute>
+ <xsl:attribute name="xlink:actuate">onLoad</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="日期域">
+ <xsl:if test="following-sibling::字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(following-sibling::字:域代码/字:段落/字:句/字:文本串,'\@ ')"/>
+ <xsl:variable name="datestr">
+ <xsl:choose>
+ <xsl:when test="contains($date0,'\*')">
+ <xsl:value-of select="string(substring-before($date0,'\*'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$date0"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="zydate">
+ <xsl:with-param name="str1" select="substring($datestr,2,string-length($datestr)-2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="zydate">
+ <xsl:param name="str1"/>
+ <xsl:choose>
+ <xsl:when test="substring($str1,1,5)='am/pm'">
+ <xsl:variable name="str1-before" select="substring($str1,1,5)"/>
+ <xsl:variable name="str1-after" select="substring($str1,6)"/>
+ <number:am-pm/>
+ <xsl:if test="not($str1-after)=''">
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zytime">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+
+ <xsl:choose>
+ <xsl:when test="substring($str1,1,4)='yyyy'">
+ <xsl:variable name="str1-before" select="substring($str1,1,4)"/>
+ <xsl:variable name="str1-after" select="substring($str1,5)"/>
+ <number:year number:style="long"/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zydate">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="substring($str1,1,1)=substring($str1,2,1) and substring($str1,2,1) !=substring($str1,3,1) ">
+ <xsl:variable name="str1-before" select="substring($str1,1,2)"/>
+ <xsl:variable name="str1-after" select="substring($str1,3)"/>
+ <xsl:if test="substring($str1,1,1)='y'">
+ <number:year/>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='M'">
+ <number:month number:style="long"/>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='d'">
+ <number:day number:style="long"/>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='h'">
+ <number:hours number:style="long"/>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='m'">
+ <number:minutes number:style="long"/>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='s'">
+ <number:seconds number:style="long"/>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='W'">
+ <number:week-of-year number:style="long"/>
+ </xsl:if>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zydate">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="substring($str1,1,1)='M'or substring($str1,1,1)='d'or substring($str1,1,1)='h'or substring($str1,1,1)='m'or substring($str1,1,1)='s'">
+ <xsl:variable name="str1-after" select="substring($str1,2)"/>
+ <xsl:variable name="str1-before" select="substring($str1,1,1)"/>
+ <xsl:if test="substring($str1,1,1)='M'">
+ <number:month/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='d'">
+ <number:day/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='h'">
+ <number:hours/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='m'">
+ <number:minutes/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='s'">
+ <number:seconds/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zydate">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="contains(substring($str1,1,3),'Q' )">
+ <xsl:choose>
+ <xsl:when test="substring($str1,1,1)='Q'">
+ <xsl:variable name="str1-before" select="substring($str1,1,2)"/>
+ <xsl:variable name="str1-after" select="substring($str1,3)"/>
+ <number:quarter/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zydate">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="str1-before" select="substring($str1,1,5)"/>
+ <xsl:variable name="str1-after" select="substring($str1,6)"/>
+ <number:quarter number:style="long"/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zydate">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="contains(substring(normalize-space($str1),1,3),'W' )">
+ <xsl:variable name="str1-before" select="substring(normalize-space($str1),1,3)"/>
+ <xsl:variable name="str1-after" select="substring(normalize-space($str1),4)"/>
+ <number:day-of-week number:style="long"/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zydate">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="contains(substring($str1,1,3),'NN' ) and substring($str1,1,1)!='NN' ">
+ <xsl:variable name="str1-before" select="substring($str1,1,3)"/>
+ <xsl:variable name="str1-after" select="substring($str1,4)"/>
+ <number:text>第</number:text>
+ <number:week-of-year/>
+ <number:text>周</number:text>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zydate">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="时间域">
+ <xsl:if test="following-sibling::字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(following-sibling::字:域代码/字:段落/字:句/字:文本串,'\@ ')"/>
+ <xsl:variable name="datestr" select="$date0"/>
+ <xsl:call-template name="zytime">
+ <xsl:with-param name="str1" select="substring($datestr,2,string-length($datestr)-2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="zytime">
+ <xsl:param name="str1"/>
+ <xsl:choose>
+ <xsl:when test="substring($str1,1,5)='am/pm'">
+ <xsl:variable name="str1-before" select="substring($str1,1,5)"/>
+ <xsl:variable name="str1-after" select="substring($str1,6)"/>
+ <number:am-pm/>
+ <xsl:if test="not($str1-after)=''">
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zytime">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="substring($str1,1,1)=substring($str1,2,1) and substring($str1,2,1) !=substring($str1,3,1) ">
+ <xsl:variable name="str1-before" select="substring($str1,1,2)"/>
+ <xsl:variable name="str1-after" select="substring($str1,3)"/>
+ <xsl:if test="substring($str1,1,1)='H' or substring($str1,1,1)='h'">
+ <number:hours number:style="long"/>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='M' or substring($str1,1,1)='m'">
+ <number:minutes number:style="long"/>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='S' or substring($str1,1,1)='s'">
+ <number:seconds number:style="long"/>
+ </xsl:if>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zytime">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="substring($str1,1,1)='H'or substring($str1,1,1)='M'or substring($str1,1,1)='S'or substring($str1,1,1)='h' or substring($str1,1,1)='m' or substring($str1,1,1)='s'">
+ <xsl:variable name="str1-after" select="substring($str1,2)"/>
+ <xsl:variable name="str1-before" select="substring($str1,1,1)"/>
+ <xsl:if test="substring($str1,1,1)='H' or substring($str1,1,1)='h'">
+ <number:hours/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='M' or substring($str1,1,1)='m'">
+ <number:minutes/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="substring($str1,1,1)='S' or substring($str1,1,1)='s'">
+ <number:seconds/>
+ <number:text>
+ <xsl:value-of select="substring($str1-after,1,1)"/>
+ </number:text>
+ </xsl:if>
+ <xsl:if test="string-length($str1-after)&gt;1">
+ <xsl:call-template name="zytime">
+ <xsl:with-param name="str1" select="substring($str1-after,2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="oo数字格式域开关">
+ <xsl:param name="oo_format"/>
+ <xsl:choose>
+ <xsl:when test="$oo_format='Arabic'">1</xsl:when>
+ <xsl:when test="$oo_format='ROMAN'">I</xsl:when>
+ <xsl:when test="$oo_format='roman'">i</xsl:when>
+ <xsl:when test="$oo_format='ALPHABETIC'">A</xsl:when>
+ <xsl:when test="$oo_format='alphabetic'">a</xsl:when>
+ <xsl:when test="$oo_format='GB1'">1, 2, 3, ...</xsl:when>
+ <xsl:when test="$oo_format='GB3'">①, ②, ③, ...</xsl:when>
+ <xsl:when test="$oo_format='CHINESENUM3'">一, 二, 三, ...</xsl:when>
+ <xsl:when test="$oo_format='CHINESENUM2'">壹, 贰, 叁, ...</xsl:when>
+ <xsl:when test="$oo_format='ZODIAC1'">甲, 乙, 丙, ...</xsl:when>
+ <xsl:when test="$oo_format='ZODIAC2'">子, 丑, 寅, ...</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="题注">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串 or 字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="aa" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,'\f ')"/>
+ <xsl:variable name="ooow" select="substring-after($aa,'ooow:') "/>
+ <xsl:variable name="as" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="ad">
+ <xsl:value-of select="substring-after($as,'SEQ ') "/>
+ </xsl:variable>
+ <xsl:variable name="num">
+ <xsl:value-of select="substring-after(substring-before(../字:域代码/字:段落/字:句/字:文本串,' \f'),'\* ')"/>
+ </xsl:variable>
+ <xsl:variable name="fmt">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="$num"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="text:sequence">
+ <xsl:attribute name="text:name"><xsl:choose><xsl:when test="$ad='表格'">Table</xsl:when><xsl:when test="$ad='图表'">Drawing</xsl:when><xsl:otherwise><xsl:value-of select="$ad"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="text:formula"><xsl:choose><xsl:when test="contains($aa,'ooow:')"><xsl:value-of select="$ooow"/></xsl:when><xsl:when test="contains($as,'表格')"><xsl:value-of select="concat('Table','+',$fmt)"/></xsl:when><xsl:when test="contains($as,'图表')"><xsl:value-of select="concat('Drawing','+',$fmt)"/></xsl:when><xsl:otherwise><xsl:value-of select="$aa"/></xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$fmt"/></xsl:attribute>
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="页码域">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串 or 字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:variable name="fmt">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="$date0"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="text:page-number">
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$fmt"/></xsl:attribute>
+ <xsl:attribute name="text:select-page">current</xsl:attribute>
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="页数域">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:variable name="fmt">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="substring-before($date0,' \*')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="text:page-count">
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$fmt"/></xsl:attribute>
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="作者域">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:element name="text:initial-creator">
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="用户域">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:element name="text:author-name">
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="缩写域">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:element name="text:author-initials">
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="标题域">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:element name="text:title">
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="主题域">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:element name="text:subject">
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="文件名">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:element name="text:file-name">
+ <xsl:variable name="string">
+ <xsl:value-of select="../字:域代码/字:段落/字:句/字:文本串"/>
+ </xsl:variable>
+ <xsl:attribute name="text:display"><xsl:choose><xsl:when test="contains($string,' \p')">full</xsl:when><xsl:otherwise>name-and-extension</xsl:otherwise></xsl:choose></xsl:attribute>
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="编辑时间">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(following-sibling::字:域代码/字:段落/字:句/字:文本串,'\@ ')"/>
+ <xsl:variable name="datestr" select="$date0"/>
+ <xsl:call-template name="zytime">
+ <xsl:with-param name="str1" select="substring($datestr,2,string-length($datestr)-2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="创建时间">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(following-sibling::字:域代码/字:段落/字:句/字:文本串,'\@ ')"/>
+ <xsl:variable name="datestr" select="$date0"/>
+ <xsl:call-template name="zytime">
+ <xsl:with-param name="str1" select="substring($datestr,2,string-length($datestr)-2)"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="字符数">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:variable name="fmt">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="substring-before($date0,' \#')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="text:character-count">
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$fmt"/></xsl:attribute>
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:key name="mulu" match="/uof:UOF/uof:式样集/uof:段落式样" use="@字:标识符"/>
+ <xsl:template name="索引域">
+ <xsl:element name="text:alphabetical-index">
+ <xsl:variable name="stylenum">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:句" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('Sect',$stylenum)"/></xsl:attribute>
+ <xsl:variable name="aanum">
+ <xsl:number value="0" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="text:name"><xsl:value-of select="concat('索引目录',$aanum + 1)"/></xsl:attribute>
+ <text:alphabetical-index-source text:main-entry-style-name="Main_index_entry" text:sort-algorithm="pinyin" fo:language="zh" fo:country="CN">
+ <text:index-title-template text:style-name="Index_20_Heading">索引目录</text:index-title-template>
+ <text:alphabetical-index-entry-template text:outline-level="separator" text:style-name="Index_Separator">
+ <text:index-entry-text/>
+ </text:alphabetical-index-entry-template>
+ <text:alphabetical-index-entry-template text:outline-level="1" text:style-name="Index_20_1">
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ </text:alphabetical-index-entry-template>
+ <text:alphabetical-index-entry-template text:outline-level="2" text:style-name="Index_20_2">
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ </text:alphabetical-index-entry-template>
+ <text:alphabetical-index-entry-template text:outline-level="3" text:style-name="Index_20_3">
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ </text:alphabetical-index-entry-template>
+ </text:alphabetical-index-source>
+ <text:index-body>
+ <text:index-title>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('Sect',$stylenum)"/></xsl:attribute>
+ <xsl:attribute name="text:name"><xsl:value-of select="concat('索引目录',$aanum + 1,'_Head')"/></xsl:attribute>
+ <xsl:for-each select="字:域代码/字:段落[position()=2]">
+ <text:p text:style-name="Index_20_Heading">
+ <xsl:apply-templates select=".//字:文本串"/>
+ </text:p>
+ </xsl:for-each>
+ </text:index-title>
+ <xsl:if test="字:域开始/@字:类型='INDEX'">
+ <xsl:for-each select="字:域代码/字:段落[position()>2]">
+ <xsl:element name="text:p">
+ <xsl:variable name="aa">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落[字:段落属性]"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('P',$aa + 1)"/></xsl:attribute>
+ <xsl:for-each select="字:句">
+ <xsl:apply-templates select="self::node()/*"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:if>
+ </text:index-body>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="目录域">
+ <xsl:element name="text:table-of-content">
+ <xsl:variable name="stylenum">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:句" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('Sect',$stylenum)"/></xsl:attribute>
+ <xsl:variable name="aanum">
+ <xsl:number value="0" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="text:name"><xsl:value-of select="concat('内容目录',$aanum + 1)"/></xsl:attribute>
+ <text:table-of-content-source text:outline-level="10">
+ <text:index-title-template text:style-name="Contents_20_Heading">内容目录</text:index-title-template>
+ <text:table-of-content-entry-template text:outline-level="1" text:style-name="Contents 1">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="2" text:style-name="Contents 2">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="3" text:style-name="Contents 3">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="4" text:style-name="Contents 4">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="5" text:style-name="Contents 5">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="6" text:style-name="Contents 6">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="7" text:style-name="Contents 7">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="8" text:style-name="Contents 8">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="9" text:style-name="Contents 9">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ <text:table-of-content-entry-template text:outline-level="10" text:style-name="Contents 10">
+ <text:index-entry-link-start text:style-name="Index_20_Link"/>
+ <text:index-entry-chapter/>
+ <text:index-entry-text/>
+ <text:index-entry-tab-stop style:type="right" style:leader-char="."/>
+ <text:index-entry-page-number/>
+ <text:index-entry-link-end/>
+ </text:table-of-content-entry-template>
+ </text:table-of-content-source>
+ <text:index-body>
+ <text:index-title>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('Sect',$stylenum)"/></xsl:attribute>
+ <xsl:attribute name="text:name"><xsl:value-of select="concat('内容目录',$aanum + 1,'_Head')"/></xsl:attribute>
+ <xsl:for-each select="字:域代码/字:段落[position()=2]">
+ <text:p text:style-name="Contents_20_Heading">
+ <xsl:apply-templates select=".//字:文本串"/>
+ </text:p>
+ </xsl:for-each>
+ </text:index-title>
+ <xsl:if test="字:域开始/@字:类型='REF'">
+ <xsl:for-each select="字:域代码/字:段落[position()>2]">
+ <xsl:element name="text:p">
+ <xsl:variable name="aa">
+ <xsl:number from="/uof:UOF/uof:文字处理/字:主体" level="any" count="字:段落[字:段落属性]"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name"><xsl:value-of select="concat('P',$aa + 1)"/></xsl:attribute>
+ <xsl:element name="text:a">
+ <xsl:attribute name="xlink:type">simple</xsl:attribute>
+ <xsl:attribute name="text:style-name">Index Link</xsl:attribute>
+ <xsl:attribute name="text:visited-style-name">Index Link</xsl:attribute>
+ <xsl:variable name="hyperDest" select="./字:句/字:区域开始/@字:标识符"/>
+ <xsl:attribute name="xlink:href"><xsl:for-each select="/uof:UOF/uof:链接集/uof:超级链接"><xsl:if test="@uof:链源=$hyperDest"><xsl:value-of select="concat('#',@uof:书签)"/></xsl:if></xsl:for-each></xsl:attribute>
+ <xsl:apply-templates select="字:句/*"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:if>
+ </text:index-body>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="suojinleixing">
+ <xsl:if test="字:缩进/字:首行/字:绝对/@字:值 and 字:缩进/字:左/字:绝对/@字:值">
+ <xsl:attribute name="text:min-label-width"><xsl:value-of select="concat(0 - 字:缩进/字:首行/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ <xsl:attribute name="text:space-before"><xsl:value-of select="concat(字:缩进/字:左/字:绝对/@字:值 + 字:缩进/字:首行/字:绝对/@字:值,$uofUnit)"/></xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="字:修订开始[@字:类型='insert']">
+ <xsl:choose>
+ <xsl:when test="./@字:标识符">
+ <text:change-start text:change-id="{@字:标识符}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <text:change-start text:change-id="{@字:修订信息引用}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:修订结束[preceding::字:修订开始[1]/@字:类型='insert']">
+ <text:change-end>
+ <xsl:attribute name="text:change-id"><xsl:value-of select="@字:开始标识引用"/></xsl:attribute>
+ </text:change-end>
+ </xsl:template>
+ <xsl:template match="字:修订开始[@字:类型='delete']">
+ <xsl:choose>
+ <xsl:when test="./@字:标识符">
+ <text:change-start text:change-id="{@字:标识符}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <text:change-start text:change-id="{@字:修订信息引用}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:修订结束[preceding::字:修订开始[1]/@字:类型='delete']">
+ <text:change-end>
+ <xsl:attribute name="text:change-id"><xsl:value-of select="@字:开始标识引用"/></xsl:attribute>
+ </text:change-end>
+ </xsl:template>
+ <xsl:template match="字:修订开始[@字:类型='format']">
+ <xsl:choose>
+ <xsl:when test="./@字:标识符">
+ <text:change-start text:change-id="{@字:标识符}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <text:change-start text:change-id="{@字:修订信息引用}"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="字:修订结束[preceding::字:修订开始[1]/@字:类型='format']">
+ <text:change-end>
+ <xsl:attribute name="text:change-id"><xsl:value-of select="@字:开始标识引用"/></xsl:attribute>
+ </text:change-end>
+ </xsl:template>
+ <xsl:template name="GenerateTrackChanges">
+ <text:tracked-changes>
+ <xsl:if test="/uof:UOF/uof:文字处理/字:公用处理规则/字:文档设置/字:修订">
+ <xsl:attribute name="text:track-changes"><xsl:value-of select="/uof:UOF/uof:文字处理/字:公用处理规则/字:文档设置/字:修订/@字:值"/></xsl:attribute>
+ </xsl:if>
+ <xsl:if test="//字:段落/字:修订开始[@字:类型='insert']">
+ <xsl:for-each select="//字:段落/字:修订开始[@字:类型='insert']">
+ <xsl:variable name="id" select="@字:标识符"/>
+ <xsl:variable name="aid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:修订信息集/字:修订信息[@字:标识符=$id]/@字:作者"/>
+ <xsl:variable name="sid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:用户集/字:用户[@字:标识符=$aid]/@字:姓名"/>
+ <xsl:variable name="bid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:修订信息集/字:修订信息[@字:标识符=$id]/@字:日期"/>
+ <text:changed-region text:id="{$id}">
+ <xsl:choose>
+ <xsl:when test="name()='字:修订开始'">
+ <xsl:choose>
+ <xsl:when test="not(name(following-sibling::node()[1])='字:修订结束')">
+ <text:insertion>
+ <office:change-info>
+ <dc:creator>
+ <xsl:value-of select="$sid"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="$bid"/>
+ </dc:date>
+ </office:change-info>
+ </text:insertion>
+ </xsl:when>
+ <xsl:otherwise>
+ <text:format-change>
+ <office:change-info>
+ <dc:creator>
+ <xsl:value-of select="$sid"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="$bid"/>
+ </dc:date>
+ </office:change-info>
+ </text:format-change>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </text:changed-region>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="//字:段落/字:修订开始[@字:类型='insert']">
+ <xsl:for-each select="//字:段落/字:修订开始[@字:类型='delete']">
+ <xsl:variable name="id" select="@字:标识符"/>
+ <xsl:variable name="aid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:修订信息集/字:修订信息[@字:标识符=$id]/@字:作者"/>
+ <xsl:variable name="sid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:用户集/字:用户[@字:标识符=$aid]/@字:姓名"/>
+ <xsl:variable name="bid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:修订信息集/字:修订信息[@字:标识符=$id]/@字:日期"/>
+ <text:changed-region text:id="{$id}">
+ <xsl:choose>
+ <xsl:when test="name()='字:修订开始'">
+ <xsl:choose>
+ <xsl:when test="not(name(following-sibling::node()[1])='字:修订结束')">
+ <text:deletion>
+ <office:change-info>
+ <dc:creator>
+ <xsl:value-of select="$sid"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="$bid"/>
+ </dc:date>
+ </office:change-info>
+ </text:deletion>
+ </xsl:when>
+ <xsl:otherwise>
+ <text:format-change>
+ <office:change-info>
+ <dc:creator>
+ <xsl:value-of select="$sid"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="$bid"/>
+ </dc:date>
+ </office:change-info>
+ </text:format-change>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </text:changed-region>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="//字:段落/字:修订开始[@字:类型='format']">
+ <xsl:for-each select="//字:段落/字:修订开始[@字:类型='format']">
+ <xsl:variable name="id" select="@字:标识符"/>
+ <xsl:variable name="aid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:修订信息集/字:修订信息[@字:标识符=$id]/@字:作者"/>
+ <xsl:variable name="sid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:用户集/字:用户[@字:标识符=$aid]/@字:姓名"/>
+ <xsl:variable name="bid" select="/uof:UOF/uof:文字处理/字:公用处理规则/字:修订信息集/字:修订信息[@字:标识符=$id]/@字:日期"/>
+ <text:changed-region text:id="{$id}">
+ <xsl:choose>
+ <xsl:when test="name()='字:修订开始'">
+ <xsl:choose>
+ <xsl:when test="not(name(following-sibling::node()[1])='字:修订结束')">
+ <text:format-change>
+ <office:change-info>
+ <dc:creator>
+ <xsl:value-of select="$sid"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="$bid"/>
+ </dc:date>
+ </office:change-info>
+ </text:format-change>
+ </xsl:when>
+ <xsl:otherwise>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ </xsl:choose>
+ </text:changed-region>
+ </xsl:for-each>
+ </xsl:if>
+
+ </text:tracked-changes>
+
+ </xsl:template>
+ <xsl:template name="oo数字格式">
+ <xsl:param name="oo_format"/>
+ <xsl:choose>
+ <xsl:when test="$oo_format='decimal'">1</xsl:when>
+ <xsl:when test="$oo_format='upper-roman'">I</xsl:when>
+ <xsl:when test="$oo_format='lower-roman'">i</xsl:when>
+ <xsl:when test="$oo_format='upper-letter'">A</xsl:when>
+ <xsl:when test="$oo_format='lower-letter'">a</xsl:when>
+ <xsl:when test="$oo_format='decimal-full-width'">1, 2, 3, ...</xsl:when>
+ <xsl:when test="$oo_format='decimal-enclosed-circle'">①, ②, ③, ...</xsl:when>
+ <xsl:when test="$oo_format='chinese-counting'">一, 二, 三, ...</xsl:when>
+ <xsl:when test="$oo_format='chinese-legal-simplified'">壹, 贰, 叁, ...</xsl:when>
+ <xsl:when test="$oo_format='ideograph-traditional'">甲, 乙, 丙, ...</xsl:when>
+ <xsl:when test="$oo_format='ideograph-zodiac'">子, 丑, 寅, ...</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="章节域">
+ <xsl:if test="../字:域代码/字:段落/字:句/字:文本串">
+ <xsl:variable name="date0" select="substring-after(../字:域代码/字:段落/字:句/字:文本串,' \* ')"/>
+ <xsl:variable name="datestr" select="substring-before(../字:域代码/字:段落/字:句/字:文本串,'\* ')"/>
+ <xsl:variable name="fmt">
+ <xsl:choose>
+ <xsl:when test="substring-before($date0,' \*')='Arabic'">
+ <xsl:call-template name="oo数字格式域开关">
+ <xsl:with-param name="oo_format" select="substring-before($date0,' \*')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:element name="text:chapter">
+ <xsl:attribute name="text:display">name</xsl:attribute>
+ <xsl:attribute name="text:outline-level"><xsl:value-of select="$fmt"/></xsl:attribute>
+ <xsl:value-of select="following-sibling::字:句/字:文本串"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo.xsl b/filter/source/xslt/import/wordml/wordml2ooo.xsl
new file mode 100644
index 000000000..972a54ecc
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo.xsl
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt v" xmlns:fla="urn:experimental:fla">
+ <xsl:output method="xml" indent="no" encoding="UTF-8" version="1.0"/>
+ <xsl:include href="../../common/measure_conversion.xsl"/>
+ <xsl:include href="../common/ms2ooo_docpr.xsl"/>
+ <xsl:include href="wordml2ooo_text.xsl"/>
+ <xsl:include href="wordml2ooo_settings.xsl"/>
+ <xsl:include href="wordml2ooo_table.xsl"/>
+ <xsl:include href="wordml2ooo_page.xsl"/>
+ <xsl:include href="wordml2ooo_list.xsl"/>
+ <xsl:include href="wordml2ooo_draw.xsl"/>
+ <xsl:include href="wordml2ooo_field.xsl"/>
+ <xsl:include href="wordml2ooo_props.xsl"/>
+ <xsl:key name="paragraph-style" match="w:style[@w:type = 'paragraph']" use="@w:styleId"/>
+ <xsl:key name="heading-style" match="w:style[@w:type = 'paragraph' and w:pPr/w:outlineLvl]" use="@w:styleId"/>
+ <xsl:variable name="preserve-alien-markup">no</xsl:variable>
+ <xsl:variable name="native-namespace-prefixes">,w,o,v,wx,aml,w10,dt,</xsl:variable>
+ <xsl:variable name="to-dispatch-elements">,wx:sect,wx:sub-section,w:p,w:tbl,w:sectPr,w:r,w:fldSimple,w:hlink,w:t,w:pict,w:br,w:instrText,w:fldChar,w:tab,w:footnote,w:endnote,aml:annotation,w:hlink,w:footnote,w:endnote,w:tblGrid,w:tr,w:tc,wx:pBdrGroup,</xsl:variable>
+ <xsl:template match="/">
+ <xsl:apply-templates select="w:wordDocument"/>
+ </xsl:template>
+ <xsl:template match="*" mode="dispatch">
+ <xsl:choose>
+ <xsl:when test="not(contains($native-namespace-prefixes, concat(',', substring-before(name(), ':'), ',')))">
+ <!-- if alien namespace dispatch -->
+ <xsl:choose>
+ <xsl:when test="$preserve-alien-markup = 'yes'">
+ <xsl:copy>
+ <xsl:copy-of select="@*"/>
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:copy>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="contains($to-dispatch-elements, concat(',',name(),','))">
+ <xsl:apply-templates select="current()"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:wordDocument">
+ <office:document office:mimetype="application/vnd.oasis.opendocument.text" office:version="1.0">
+ <fla:fla.activate/>
+ <xsl:apply-templates select="o:DocumentProperties"/>
+ <xsl:apply-templates select="w:docOleData" mode="init"/>
+ <xsl:apply-templates select="w:docPr"/>
+ <xsl:apply-templates select="w:fonts"/>
+ <xsl:apply-templates select="w:styles"/>
+ <xsl:apply-templates select="w:body"/>
+ <xsl:apply-templates select="w:docOleData" mode="exit"/>
+ </office:document>
+ </xsl:template>
+ <xsl:template match="w:fonts">
+ <xsl:element name="office:font-face-decls">
+ <!-- MS Word's default font declaration, added for Writer automatically. glu -->
+ <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Symbol" svg:font-family="Symbol" style:font-family-generic="roman" style:font-pitch="variable" style:font-charset="x-symbol"/>
+ <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/>
+ <xsl:if test="not(w:font[@w:name='StarSymbol'])">
+ <style:font-face style:name="StarSymbol" svg:font-family="StarSymbol" style:font-charset="x-symbol"/>
+ </xsl:if>
+ <xsl:for-each select="w:font">
+ <xsl:element name="style:font-face">
+ <xsl:attribute name="style:name">
+ <xsl:value-of select="@w:name"/>
+ </xsl:attribute>
+ <xsl:attribute name="svg:font-family">
+ <xsl:value-of select="@w:name"/>
+ </xsl:attribute>
+ <!-- added by glu, for process special fonts e.g. Marlett, -->
+ <xsl:if test="w:charset/@w:val = '02'">
+ <xsl:attribute name="style:font-charset">x-symbol</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:family">
+ <xsl:choose>
+ <xsl:when test="w:family/@w:val = 'Swiss'">
+ <xsl:attribute name="style:font-family-generic">swiss</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:family/@w:val='Modern'">
+ <xsl:attribute name="style:font-family-generic">modern</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:family/@w:val='Roman'">
+ <xsl:attribute name="style:font-family-generic">roman</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:family/@w:val='Script'">
+ <xsl:attribute name="style:font-family-generic">script</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:family/@w:val='Decorative'">
+ <xsl:attribute name="style:font-family-generic">decorative</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:family/@w:val='System'">
+ <xsl:attribute name="style:font-family-generic">system</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:font-family-generic">system</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="w:pitch and string-length(w:pitch/@w:val) &gt; 0">
+ <xsl:attribute name="style:font-pitch">
+ <xsl:choose>
+ <xsl:when test="w:pitch/@w:val = 'default'">variable</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="w:pitch/@w:val"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:styles">
+ <office:styles>
+ <!--The next statement Added by wguo,collect the pict's dash and mark-style.The template is implemented in file wordml2ooo_draw.xsl-->
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:pict" mode="style4dash_mark"/>
+ <xsl:apply-templates select="//v:fill" mode="office-style"/>
+ <xsl:call-template name="create-default-paragraph-styles"/>
+ <xsl:call-template name="create-default-text-styles"/>
+ <xsl:call-template name="create-default-frame-style"/>
+ <!-- StarWriter has no default style family 'list'. glu -->
+ <xsl:if test="w:style[@w:type = 'paragraph' and w:pPr/w:outlineLvl and w:pPr/w:listPr]">
+ <xsl:call-template name="create-outline-style"/>
+ </xsl:if>
+ <xsl:apply-templates select="w:style[@w:type='table']" mode="table"/>
+ <xsl:apply-templates select="w:style[@w:type='list']" mode="list"/>
+ <xsl:apply-templates select="w:style[@w:type!='list']"/>
+ <xsl:apply-templates select="/w:wordDocument/w:docPr/w:footnotePr" mode="config"/>
+ <xsl:apply-templates select="/w:wordDocument/w:docPr/w:endnotePr" mode="config"/>
+ </office:styles>
+ <office:automatic-styles>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:p" mode="style"/>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:rPr[not(parent::w:pPr)]" mode="style"/>
+ <!--The next statement Added by wguo for the pict's draw-style.The template is implemented in file wordml2ooo_draw.xsl-->
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:pict" mode="style"/>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:tblPr" mode="style"/>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:gridCol" mode="style"/>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:trPr" mode="style"/>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:tcPr" mode="style"/>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:listPr" mode="style"/>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:sectPr" mode="page-layout"/>
+ <xsl:call-template name="default_date_style"/>
+ <!--add for generate the date , time style for date , time field G.Y.-->
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:instrText | /w:wordDocument/w:body//w:fldSimple " mode="style"/>
+ </office:automatic-styles>
+ <office:master-styles>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:sectPr" mode="master-page"/>
+ </office:master-styles>
+ </xsl:template>
+ <xsl:template match="w:style">
+ <style:style>
+ <xsl:attribute name="style:name">
+ <xsl:value-of select="concat('w',translate(@w:styleId,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ <xsl:if test="w:basedOn">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select="concat('w',translate(w:basedOn/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:next">
+ <xsl:attribute name="style:next-style-name">
+ <xsl:value-of select="concat('w',translate(w:basedOn/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="@w:type = 'character'">
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ </xsl:when>
+ <!-- table, paragraph are the same as in Writer . glu -->
+ <xsl:when test="@w:type">
+ <xsl:attribute name="style:family">
+ <xsl:value-of select="@w:type"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="@w:type = 'table'">
+ <xsl:element name="style:table-properties">
+ <!-- xsl:apply-templates select="w:tblPr" mode="style"/ -->
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="@w:type = 'character' ">
+ <xsl:element name="style:text-properties">
+<!--
+ <xsl:apply-templates select="w:pPr/w:rPr"/>
+ <xsl:apply-templates select="w:rPr"/>
+-->
+ <xsl:for-each select="w:rPr">
+ <xsl:call-template name="text-properties"/>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="style:paragraph-properties">
+ <xsl:apply-templates select="w:pPr"/>
+ </xsl:element>
+ <xsl:element name="style:text-properties">
+ <xsl:apply-templates select="w:rPr"/>
+ <xsl:apply-templates select="w:pPr/w:rPr"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </style:style>
+ </xsl:template>
+ <xsl:template match="w:body">
+ <xsl:element name="office:body">
+ <xsl:element name="office:text">
+ <!-- to add the sequence variable declaration at the beginning of the office:body G.Y.-->
+ <text:sequence-decls>
+ <xsl:call-template name="default_sequence_declaration"/>
+ <xsl:apply-templates select="/w:wordDocument/w:body//w:instrText[substring(normalize-space(text()),1,3) = 'SEQ' ] | /w:wordDocument/w:body//w:fldSimple[substring(normalize-space(@w:instr),1,3) = 'SEQ' ] " mode="sequence_declare"/>
+ </text:sequence-decls>
+ <!-- add the user field variables declare for Docproperty fields importing G.Y.-->
+ <text:user-field-decls>
+ <xsl:call-template name="user_fields_declare_docproperty"/>
+ </text:user-field-decls>
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="wx:sect">
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:template>
+ <xsl:template match="wx:sub-section">
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:template>
+ <xsl:template name="create-default-frame-style">
+ <!--add for default frame style -->
+ <style:style style:name="Frame" style:family="graphic">
+ <style:graphic-properties text:anchor-type="paragraph" svg:x="0in" svg:y="0in" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/>
+ </style:style>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_custom_draw.xsl b/filter/source/xslt/import/wordml/wordml2ooo_custom_draw.xsl
new file mode 100644
index 000000000..c286f3a96
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_custom_draw.xsl
@@ -0,0 +1,275 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt fo v">
+ <xsl:template name="ms_word_draw_map2ooo_custom_draw">
+ <xsl:param name="ms_word_draw_type"/>
+ <!-- all ooo draw names are get from EnhancedCustomShapeGeometry.idl-->
+ <xsl:choose>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t5' ">
+ <xsl:value-of select=" 'isosceles-triangle'"/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type ='#_x0000_t6' ">
+ <xsl:value-of select=" 'right-triangle' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t8' ">
+ <xsl:value-of select=" 'trapezoid' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t4' ">
+ <xsl:value-of select=" 'diamond' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t9' ">
+ <xsl:value-of select=" 'hexagon' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t7' ">
+ <xsl:value-of select="'parallelogram' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t56' ">
+ <xsl:value-of select=" 'pentagon' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t10' ">
+ <xsl:value-of select=" 'octagon' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t11' ">
+ <xsl:value-of select=" 'cross' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t23' ">
+ <xsl:value-of select=" 'ring' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t95' ">
+ <xsl:value-of select=" 'block-arc' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t22' ">
+ <xsl:value-of select=" 'can' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t16' ">
+ <xsl:value-of select=" 'cube' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t65' ">
+ <xsl:value-of select=" 'paper' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t96' ">
+ <xsl:value-of select=" 'smiley' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t183' ">
+ <xsl:value-of select=" 'sun' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t184' ">
+ <xsl:value-of select=" 'moon' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t74' ">
+ <xsl:value-of select=" 'heart' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t57' ">
+ <xsl:value-of select=" 'forbidden' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type ='#_x0000_t85' ">
+ <xsl:value-of select=" 'left-bracket' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t86' ">
+ <xsl:value-of select=" 'right-bracket' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t87' ">
+ <xsl:value-of select=" 'left-brace' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t88' ">
+ <xsl:value-of select=" 'right-brace' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t185' ">
+ <xsl:value-of select=" 'bracket-pair' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t186' ">
+ <xsl:value-of select=" 'brace-pair' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t189' ">
+ <xsl:value-of select=" 'quad-bevel' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t66' ">
+ <xsl:value-of select=" 'left-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t67' ">
+ <xsl:value-of select=" 'down-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t68' ">
+ <xsl:value-of select=" 'up-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t13' ">
+ <xsl:value-of select=" 'right-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t69' ">
+ <xsl:value-of select=" 'left-right-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t70' ">
+ <xsl:value-of select=" 'up-down-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t89' ">
+ <xsl:value-of select=" 'mso-spt89' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t76' ">
+ <xsl:value-of select=" 'quad-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t94' ">
+ <xsl:value-of select=" 'notched-right-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t177' ">
+ <xsl:value-of select=" 'pentagon-right' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t55' ">
+ <xsl:value-of select=" 'chevron' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t79' ">
+ <xsl:value-of select=" 'up-arrow-callout' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t80' ">
+ <xsl:value-of select=" 'down-arrow-callout' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t82' ">
+ <xsl:value-of select=" 'up-down-arrow-callout' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t103' ">
+ <xsl:value-of select=" 'circular-arrow' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t109' ">
+ <xsl:value-of select=" 'flowchart-process' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t116' ">
+ <xsl:value-of select=" 'flowchart-alternate-process' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t110' ">
+ <xsl:value-of select=" 'flowchart-decision' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t111' ">
+ <xsl:value-of select=" 'flowchart-data' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t112' ">
+ <xsl:value-of select=" 'flowchart-predefined-process' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t113' ">
+ <xsl:value-of select=" 'flowchart-internal-storage' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t114' ">
+ <xsl:value-of select=" 'flowchart-document' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t115' ">
+ <xsl:value-of select=" 'flowchart-multidocument' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t116' ">
+ <xsl:value-of select=" 'flowchart-terminator' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t117' ">
+ <xsl:value-of select=" 'flowchart-preparation' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t118' ">
+ <xsl:value-of select=" 'flowchart-manual-input' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t119' ">
+ <xsl:value-of select=" 'flowchart-manual-operation' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t120' ">
+ <xsl:value-of select=" 'flowchart-connector' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t177' ">
+ <xsl:value-of select=" 'flowchart-off-page-connector' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t121' ">
+ <xsl:value-of select=" 'flowchart-card' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t122' ">
+ <xsl:value-of select=" 'flowchart-punched-tape' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t123' ">
+ <xsl:value-of select=" 'flowchart-summing-junction' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t124' ">
+ <xsl:value-of select=" 'flowchart-or' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t125' ">
+ <xsl:value-of select=" 'flowchart-collate' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t126' ">
+ <xsl:value-of select=" 'flowchart-sort' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t127' ">
+ <xsl:value-of select=" 'flowchart-extract' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t128' ">
+ <xsl:value-of select=" 'flowchart-merge' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t130' ">
+ <xsl:value-of select=" 'flowchart-stored-data' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t135' ">
+ <xsl:value-of select=" 'flowchart-delay' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t131' ">
+ <xsl:value-of select=" 'flowchart-sequential-access' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t132' ">
+ <xsl:value-of select=" 'flowchart-magnetic-disk' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t133' ">
+ <xsl:value-of select=" 'flowchart-direct-access-storage' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t134' ">
+ <xsl:value-of select=" 'flowchart-display' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t61' ">
+ <xsl:value-of select=" 'rectangular-callout' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t62' ">
+ <xsl:value-of select=" 'round-rectangular-callout' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t63' ">
+ <xsl:value-of select=" 'round-callout' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t106' ">
+ <xsl:value-of select=" 'cloud-callout' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t50' ">
+ <xsl:value-of select=" 'line-callout-1' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t51' ">
+ <xsl:value-of select=" 'line-callout-2' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t47' ">
+ <xsl:value-of select=" 'line-callout-3' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t72' ">
+ <xsl:value-of select=" 'bang' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t187' ">
+ <xsl:value-of select=" 'star4' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t12' ">
+ <xsl:value-of select=" 'star5' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t58' ">
+ <xsl:value-of select=" 'star8' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t92' ">
+ <xsl:value-of select=" 'star24' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t97' ">
+ <xsl:value-of select=" 'vertical-scroll' "/>
+ </xsl:when>
+ <xsl:when test="$ms_word_draw_type = '#_x0000_t98' ">
+ <xsl:value-of select=" 'horizontal-scroll' "/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_draw.xsl b/filter/source/xslt/import/wordml/wordml2ooo_draw.xsl
new file mode 100644
index 000000000..3226f0d1c
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_draw.xsl
@@ -0,0 +1,2170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:ole="http://libreoffice.org/2011/xslt/ole" exclude-result-prefixes="w wx aml o dt v">
+ <xsl:include href="wordml2ooo_custom_draw.xsl"/>
+ <xsl:include href="wordml2ooo_path.xsl"/>
+
+ <xsl:key name="imagedata" match="w:binData" use="@w:name"/>
+ <xsl:key name="shapetype" match="v:shapetype" use="concat('#', @id)"/>
+ <xsl:template match="v:fill" mode="get-xsl-number">
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="v:fill" format="1"/>
+ </xsl:template>
+ <xsl:template match="v:textpath" mode="get-xsl-number">
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="v:textpath" format="1"/>
+ </xsl:template>
+ <xsl:template match="v:fill" mode="office-style">
+ <xsl:choose>
+ <xsl:when test="@type='pattern' or @type='tile' or @type='frame'">
+ <xsl:variable name="fill-src" select="key('imagedata',@src)"/>
+ <xsl:if test="$fill-src">
+ <draw:fill-image>
+ <xsl:if test="string-length(@o:title) &gt; 0">
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select="@o:title"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select="translate(@src,'&#9;&#10;&#13;&#32;:/.','' ) "/>
+ </xsl:attribute>
+ <xsl:element name="office:binary-data">
+ <xsl:value-of select="translate($fill-src/text(),'&#9;&#10;&#13;&#32;','' ) "/>
+ </xsl:element>
+ </draw:fill-image>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="contains(@type,'gradient')">
+ <draw:gradient>
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select=" 'gradient' "/>
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="v:fill" format="1"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:style">linear</xsl:attribute>
+ <xsl:if test="string-length(parent::v:*/@fillcolor) &gt; 0">
+ <xsl:attribute name="draw:start-color">
+ <xsl:call-template name="MapConstColor">
+ <xsl:with-param name="color" select="parent::v:*/@fillcolor"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length(@color2) &gt; 0">
+ <xsl:attribute name="draw:end-color">
+ <xsl:call-template name="MapConstColor">
+ <xsl:with-param name="color" select="@color2"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ </draw:gradient>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:pict" mode="style4dash_mark">
+ <xsl:if test="descendant::v:line or descendant::v:rect or descendant::v:oval or descendant::v:arc or descendant::v:shape">
+ <!--Changed-->
+ <xsl:variable name="vchild" select="./v:*"/>
+ <xsl:variable name="def" select="$vchild/v:stroke"/>
+ <xsl:if test="$def">
+ <!--<draw:marker draw:name="Stupid33" svg:viewBox="0 0 20 30" svg:d="m10 0-10 30h20z"/> -->
+ <xsl:variable name="wdashstyle" select="$vchild/v:stroke/@dashstyle"/>
+ <xsl:variable name="stroke-num">
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="v:stroke" format="1"/>
+ </xsl:variable>
+ <xsl:variable name="ptweight">
+ <xsl:choose>
+ <xsl:when test="$vchild/@strokeweight">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'pt'"/>
+ <xsl:with-param name="value" select="$vchild/@strokeweight"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'pt'"/>
+ <xsl:with-param name="value" select="'1pt'"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$wdashstyle and not ($wdashstyle = 'solid')">
+ <xsl:variable name="strdashdot">
+ <xsl:call-template name="getstrdashdot">
+ <xsl:with-param name="dashstyle" select="$wdashstyle"/>
+ <!--<xsl:with-param name="weight" select="$vchild/@strokeweight"/>-->
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="draw-style">
+ <xsl:variable name="end-cap" select="$vchild/v:stroke/@endcap"/>
+ <xsl:choose>
+ <xsl:when test="$end-cap = 'round'">round</xsl:when>
+ <xsl:otherwise>rect</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="dot1-length">
+ <xsl:call-template name="get-middle-substring">
+ <xsl:with-param name="string" select="$strdashdot"/>
+ <xsl:with-param name="prefix" select="'dol:'"/>
+ <xsl:with-param name="suffix" select="';don'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="dot1n">
+ <xsl:call-template name="get-middle-substring">
+ <xsl:with-param name="string" select="$strdashdot"/>
+ <xsl:with-param name="prefix" select="'don:'"/>
+ <xsl:with-param name="suffix" select="';dist'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="dist-length">
+ <xsl:call-template name="get-middle-substring">
+ <xsl:with-param name="string" select="$strdashdot"/>
+ <xsl:with-param name="prefix" select="'dist:'"/>
+ <xsl:with-param name="suffix" select="';dtl'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="dot2-length">
+ <xsl:call-template name="get-middle-substring">
+ <xsl:with-param name="string" select="$strdashdot"/>
+ <xsl:with-param name="prefix" select="'dtl:'"/>
+ <xsl:with-param name="suffix" select="';dtn'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="dot2n">
+ <xsl:call-template name="get-middle-substring">
+ <xsl:with-param name="string" select="$strdashdot"/>
+ <xsl:with-param name="prefix" select="'dtn:'"/>
+ <xsl:with-param name="suffix" select="';eddtn'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:element name="draw:stroke-dash">
+ <!--dol:8;don:1;dist:2;dtl:1;dtn:2;eddtn" />-->
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select="concat('Tdash',$stroke-num)"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:style">
+ <xsl:value-of select="$draw-style"/>
+ </xsl:attribute>
+ <xsl:if test="(string-length($dot1n) &gt; 0 ) and not ($dot1n ='-1')">
+ <xsl:attribute name="draw:dots1">
+ <xsl:value-of select="$dot1n"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="(string-length($dot2n) &gt; 0 ) and not ($dot2n ='-1')">
+ <xsl:attribute name="draw:dots2">
+ <xsl:value-of select="$dot2n"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="(string-length($dot1-length) &gt; 0 ) and not ($dot1-length ='-1')">
+ <xsl:attribute name="draw:dots1-length">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat($dot1-length,'pt')"/>
+ </xsl:call-template>in</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="(string-length($dot2-length) &gt; 0 ) and not ($dot2-length ='-1')">
+ <xsl:attribute name="draw:dots2-length">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat($dot2-length,'pt')"/>
+ </xsl:call-template>in</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="(string-length($dist-length) &gt; 0 ) and not ($dist-length ='-1')">
+ <xsl:variable name="valdistance-length">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat($dist-length,'pt')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="draw:distance">
+ <xsl:value-of select="$valdistance-length*$ptweight"/>in</xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:if test="$vchild/v:stroke/@startarrow">
+ <xsl:call-template name="CreateArrowStyle">
+ <xsl:with-param name="arrow-name" select="$vchild/v:stroke/@startarrow"/>
+ <xsl:with-param name="namenumber" select="concat('markerstart',$stroke-num)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$vchild/v:stroke/@endarrow">
+ <xsl:call-template name="CreateArrowStyle">
+ <xsl:with-param name="arrow-name" select="$vchild/v:stroke/@endarrow"/>
+ <xsl:with-param name="namenumber" select="concat('markerend',$stroke-num)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <!--<v:stroke dashstyle="1 1" startarrow="diamond" startarrowwidth="wide" startarrowlength="long" endarrow="block"
+ endarrowwidth="wide" endarrowlength="long" endcap="round"/>
+ <draw:stroke-dash draw:name="2 2dots 1 dash" draw:style="rect" draw:dots1="2" draw:dots2="1" draw:dots2-length="0.0795in"
+ draw:distance="0.102in"/>
+ Hehe, it needs to be revised-->
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="CreateArrowStyle">
+ <!--<draw:marker draw:name="Stupid33" svg:viewBox="0 0 20 30" svg:d="m10 0-10 30h20z"/> -->
+ <xsl:param name="arrow-name"/>
+ <xsl:param name="namenumber"/>
+ <xsl:param name="arrow-weight"/>
+ <xsl:variable name="svg-box">
+ <xsl:choose>
+ <xsl:when test="$arrow-name = 'block' ">0 0 1131 902</xsl:when>
+ <xsl:when test="$arrow-name = 'diamond' ">0 0 10 10</xsl:when>
+ <xsl:when test="$arrow-name = 'open' ">0 0 1122 2243</xsl:when>
+ <xsl:when test="$arrow-name = 'oval' ">0 0 1131 1131</xsl:when>
+ <xsl:when test="$arrow-name = 'diamond' ">0 0 1131 1131</xsl:when>
+ <xsl:when test="$arrow-name = 'classic' ">0 0 1131 1580</xsl:when>
+ <xsl:otherwise>0 0 1122 2243</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="svg-d">
+ <xsl:choose>
+ <xsl:when test="$arrow-name = 'block' ">m564 0-564 902h1131z</xsl:when>
+ <!--Symmetric Arrow-->
+ <xsl:when test="$arrow-name = 'diamond' ">m0 0h10v10h-10z</xsl:when>
+ <xsl:when test="$arrow-name = 'open' ">m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z</xsl:when>
+ <xsl:when test="$arrow-name = 'oval' ">m462 1118-102-29-102-51-93-72-72-93-51-102-29-102-13-105 13-102 29-106 51-102 72-89 93-72 102-50 102-34 106-9 101 9 106 34 98 50 93 72 72 89 51 102 29 106 13 102-13 105-29 102-51 102-72 93-93 72-98 51-106 29-101 13z</xsl:when>
+ <xsl:when test="$arrow-name = 'diamond' ">m0 564 564 567 567-567-567-564z</xsl:when>
+ <xsl:when test="$arrow-name = 'classic' ">m1013 1491 118 89-567-1580-564 1580 114-85 136-68 148-46 161-17 161 13 153 46z</xsl:when>
+ <xsl:otherwise>m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="draw:marker">
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select="$namenumber"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:display-name">
+ <xsl:value-of select="$namenumber"/>
+ </xsl:attribute>
+ <xsl:attribute name="svg:viewBox">
+ <xsl:value-of select="$svg-box"/>
+ </xsl:attribute>
+ <xsl:attribute name="svg:d">
+ <xsl:value-of select="$svg-d"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <!-- The template MapDashConst Map the const dashstyle to a number manner
+ It calls the template kickblanks to delete the extra blanks in the dash style here is the map
+• Solid (default) • ShortDash "2 2"
+• ShortDot "0 2" • ShortDashDot "2 2 0 2"
+• ShortDashDotDot "2 2 0 2 0 2" • Dot "1 2"
+• Dash "4 2" • LongDash "8 2"
+• DashDot "4 2 1 2"• LongDashDot "8 2 1 2"
+• LongDashDotDot "8 2 1 2 1 2"
+-->
+ <xsl:template name="MapDashConst">
+ <xsl:param name="dashstyle"/>
+ <xsl:choose>
+ <xsl:when test="$dashstyle='shortDash'"> 2 2 </xsl:when>
+ <xsl:when test="$dashstyle='shortDot'"> 0 2 </xsl:when>
+ <xsl:when test="$dashstyle='shortDashDot'"> 2 2 0 2 </xsl:when>
+ <xsl:when test="$dashstyle='shortDashDotDot'"> 2 2 0 2 0 2 </xsl:when>
+ <xsl:when test="$dashstyle='dot'"> 1 2 </xsl:when>
+ <xsl:when test="$dashstyle='dash'"> 4 2 </xsl:when>
+ <xsl:when test="$dashstyle='longDash'"> 8 2 </xsl:when>
+ <xsl:when test="$dashstyle='dashDot'"> 4 2 1 2 </xsl:when>
+ <xsl:when test="$dashstyle='longDashDot'"> 8 2 1 2 </xsl:when>
+ <xsl:when test="$dashstyle='longDashDotDot'"> 8 2 1 2 1 2 </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="str-style" select="concat(' ',$dashstyle ,' ')"/>
+ <xsl:variable name="cleanstyle">
+ <xsl:call-template name="kickblanks">
+ <xsl:with-param name="str" select="translate($str-style,' ','-')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="translate($cleanstyle,'-',' ')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--The template is used to delete the extra blanks from a string.-->
+ <xsl:template name="kickblanks">
+ <xsl:param name="str"/>
+ <xsl:variable name="tmpstr">
+ <xsl:choose>
+ <xsl:when test="contains($str,'--')">
+ <xsl:variable name="str-before">
+ <xsl:value-of select="substring-before($str,'--')"/>
+ </xsl:variable>
+ <xsl:variable name="str-after">
+ <xsl:value-of select="substring-after($str,'--')"/>
+ </xsl:variable>
+ <xsl:value-of select="concat($str-before,'-',$str-after)"/>
+ </xsl:when>
+ <xsl:when test="contains($str,' ')">
+ <xsl:variable name="str-before">
+ <xsl:value-of select="substring-before($str,' ')"/>
+ </xsl:variable>
+ <xsl:variable name="str-after">
+ <xsl:value-of select="substring-after($str,' ')"/>
+ </xsl:variable>
+ <xsl:value-of select="concat($str-before,' ',$str-after)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$str"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="not ( string-length($str) = string-length($tmpstr) )">
+ <xsl:variable name="restr">
+ <xsl:call-template name="kickblanks">
+ <xsl:with-param name="str" select="$tmpstr"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$restr"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$str"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="substrcount">
+ <xsl:param name="str"/>
+ <xsl:param name="substr"/>
+ <xsl:choose>
+ <xsl:when test="$substr and string-length($str) and contains($str,$substr) and string-length(substring-before($str,$substr)) = 0">
+ <xsl:variable name="restr" select="substring-after($str,$substr)"/>
+ <xsl:variable name="num">
+ <xsl:call-template name="substrcount">
+ <xsl:with-param name="str" select="$restr"/>
+ <xsl:with-param name="substr" select="$substr"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="$num+1"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="latest-substr-after">
+ <xsl:param name="str"/>
+ <xsl:param name="substr"/>
+ <xsl:choose>
+ <xsl:when test="contains($str,$substr) and string-length(substring-before($str,$substr)) = 0">
+ <xsl:variable name="restr" select="substring-after($str,$substr)"/>
+ <xsl:call-template name="latest-substr-after">
+ <xsl:with-param name="str" select="$restr"/>
+ <xsl:with-param name="substr" select="$substr"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$str"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--Template get_revised_adj is used to get real adj when adj show two time in the file. -->
+ <xsl:template name="get_remained_adj">
+ <xsl:param name="adj_typeid"/>
+ <xsl:param name="num"/>
+ <xsl:param name="mark"/>
+ <xsl:choose>
+ <xsl:when test="$num &gt; 0 ">
+ <xsl:variable name="new_remained_adj">
+ <xsl:choose>
+ <xsl:when test="string-length($adj_typeid) &gt; 0">
+ <xsl:call-template name="get_remained_adj">
+ <xsl:with-param name="adj_typeid" select="substring-after($adj_typeid,$mark)"/>
+ <xsl:with-param name="num" select="$num -1"/>
+ <xsl:with-param name="mark" select="$mark"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$new_remained_adj"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$adj_typeid"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--Template get_non_omit_adj is used to get the non-omit adj.(e.g. Adj="10,,11" means modifiers="10 0 11").-->
+ <xsl:template name="get_non_omit_adj">
+ <xsl:param name="adj_typeid"/>
+ <xsl:param name="num"/>
+ <xsl:param name="mark"/>
+ <xsl:choose>
+ <xsl:when test="$num &gt; 0 ">
+ <xsl:variable name="before" select="substring-before($adj_typeid,',')"/>
+ <xsl:variable name="after" select="substring-after($adj_typeid,',')"/>
+ <xsl:variable name="zero_or_itself">
+ <xsl:choose>
+ <xsl:when test="string-length(translate($before, ' ','' ) ) &gt; 0">
+ <xsl:value-of select="$before"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'0'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="new_non_omit_adj">
+ <xsl:call-template name="get_non_omit_adj">
+ <xsl:with-param name="adj_typeid" select="$after"/>
+ <xsl:with-param name="num" select="$num -1"/>
+ <xsl:with-param name="mark" select="$mark"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat($zero_or_itself, ' ',$new_non_omit_adj)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="zero_or_itself">
+ <xsl:choose>
+ <xsl:when test="string-length(translate($adj_typeid, ' ','' ) ) &gt; 0">
+ <xsl:value-of select="$adj_typeid"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="'0'"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="$zero_or_itself"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="getstrdashdot">
+ <!--Remember the robust!if dashstyle is '2'?What to do!-->
+ <xsl:param name="dashstyle"/>
+ <xsl:variable name="dstyle">
+ <xsl:variable name="tmpstyle">
+ <xsl:call-template name="MapDashConst">
+ <xsl:with-param name="dashstyle" select="$dashstyle"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="substring-after($tmpstyle,' ')"/>
+ </xsl:variable>
+ <xsl:variable name="dot1" select="substring-before($dstyle,' ')"/>
+ <xsl:variable name="dot1after" select="substring-after($dstyle,' ')"/>
+ <xsl:variable name="dot1distance" select="substring-before($dot1after,' ')"/>
+ <xsl:variable name="modesubstr1" select="concat($dot1,' ',$dot1distance,' ')"/>
+ <xsl:variable name="dot1n">
+ <xsl:call-template name="substrcount">
+ <xsl:with-param name="str" select="$dstyle"/>
+ <xsl:with-param name="substr" select="$modesubstr1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="dot2substr">
+ <xsl:call-template name="latest-substr-after">
+ <xsl:with-param name="str" select="$dstyle"/>
+ <xsl:with-param name="substr" select="$modesubstr1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="dot2">
+ <xsl:choose>
+ <xsl:when test="string-length($dot2substr) &gt; 3">
+ <xsl:value-of select="substring-before($dot2substr,' ')"/>
+ </xsl:when>
+ <xsl:otherwise>-1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="dot2distance">
+ <xsl:choose>
+ <xsl:when test="string-length($dot2substr) &gt; 3">
+ <xsl:variable name="tmpstr" select="substring-after($dot2substr,' ')"/>
+ <xsl:value-of select="substring-before($tmpstr,' ')"/>
+ </xsl:when>
+ <xsl:otherwise>-1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="modesubstr2" select="concat($dot2,' ',$dot2distance,' ') "/>
+ <xsl:variable name="dot2n">
+ <xsl:choose>
+ <xsl:when test="string-length($dot2substr) &gt; 3">
+ <xsl:call-template name="substrcount">
+ <xsl:with-param name="str" select="$dot2substr"/>
+ <xsl:with-param name="substr" select="$modesubstr2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>-1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="valDistance">
+ <!--Over all distance is the larger one!-->
+ <xsl:choose>
+ <xsl:when test="$dot2distance &gt; $dot1distance">
+ <xsl:value-of select="$dot2distance"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$dot1distance"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat('dol:',$dot1,';don:',$dot1n,';dist:',$valDistance,';dtl:',$dot2,';dtn:',$dot2n,';eddtn')"/>
+ <!--<xsl:choose>
+ <xsl:when test="$dashstyle='1 1' or $dashstyle='Dots'">
+ <xsl:variable name="do"><xsl:value-of select="'1'"/></xsl:variable>
+ <xsl:variable name="dol"><xsl:value-of select="$do * $cmweight"/></xsl:variable>
+ <xsl:variable name="ds"><xsl:value-of select="'1'"/></xsl:variable>
+ <xsl:variable name="dsl"><xsl:value-of select="$ds * $cmweight"/></xsl:variable>
+ <xsl:variable name="dt"><xsl:value-of select="'-1'"/></xsl:variable>
+ <xsl:variable name="dtl"><xsl:value-of select="'-1'"/></xsl:variable>
+ <xsl:value-of select="concat('dsl:',$dsl,'edsl','do:',$do, 'edo;','do')"/>
+ </xsl:when>
+ </xsl:choose>-->
+ </xsl:template>
+ <xsl:template match="w:pict" mode="style">
+ <xsl:apply-templates mode="style" select="v:*"/>
+ </xsl:template>
+ <xsl:template match="v:*" mode="style">
+ <xsl:variable name="vchild" select="."/>
+ <xsl:variable name="style" select="concat($vchild/@style, ';')"/>
+ <xsl:variable name="z-index" select="substring-before(substring-after($style,'z-index:'),';')"/>
+ <xsl:variable name="right-name" select="not(name($vchild) = 'v:formulas') and not(name($vchild) = 'v:f') and not(name($vchild) = 'v:shapetype')"/>
+ <xsl:variable name="def" select="string-length($style) &gt; 0 or $vchild/@stroke or $vchild/@stroked or $vchild/@strokecolor or $vchild/v:stroke or $vchild/@strokeweight or $vchild/@wrapcoords or $vchild/@fillcolor"/>
+ <xsl:choose>
+ <xsl:when test="$right-name and ($def or (number($z-index) &lt; 0))">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">Tgr<xsl:number from="/w:wordDocument/w:body" level="any" count="v:*" format="1"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">graphic</xsl:attribute>
+ <xsl:variable name="stroke-num">
+ <xsl:if test="$vchild/v:stroke">
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="v:stroke" format="1"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="draw-stroke">
+ <xsl:variable name="dashstyle" select="$vchild/v:stroke/@dashstyle"/>
+ <xsl:choose>
+ <xsl:when test="$vchild/@stroked and $vchild/@stroked='f'">none</xsl:when>
+ <xsl:when test="$dashstyle and not ($dashstyle = 'solid')">
+ <xsl:value-of select="concat('Tdash',$stroke-num)"/>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="style:graphic-properties">
+ <xsl:variable name="style-str" select="concat(@style,';')"/>
+ <xsl:choose>
+ <xsl:when test="number($z-index) &lt; 0 or (name($vchild) = 'v:group' and $vchild/@editas ='canvas' )">
+ <xsl:attribute name="style:wrap">run-through</xsl:attribute>
+ <xsl:attribute name="style:run-through">background</xsl:attribute>
+ <xsl:attribute name="style:flow-with-text">false</xsl:attribute>
+ <xsl:attribute name="fo:border">none</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:wrap">run-through</xsl:attribute>
+ <xsl:attribute name="style:run-through">foreground</xsl:attribute>
+ <xsl:attribute name="style:flow-with-text">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="contains($style-str,'mso-position-horizontal:')">
+ <xsl:attribute name="style:horizontal-pos">
+ <xsl:value-of select="substring-before( substring-after( $style-str , 'mso-position-horizontal:') , ';')"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="v:imagedata or v:textbox">
+ <xsl:attribute name="style:horizontal-pos">from-left</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="parent::w:pict/o:OLEObject">
+ <xsl:variable name="width" select="substring-before( substring-after($style,'width:') ,';')"/>
+ <xsl:variable name="height" select="substring-before(substring-after($style,'height:'),';')"/>
+ <xsl:attribute name="draw:visible-area-left">0cm</xsl:attribute>
+ <xsl:attribute name="draw:visible-area-top">0cm</xsl:attribute>
+ <xsl:attribute name="draw:visible-area-width">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$width"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="draw:visible-area-height">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$height"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="draw:ole-draw-aspect">
+ <!-- DVASPECT_CONTENT = 1,
+ DVASPECT_THUMBNAIL = 2,
+ DVASPECT_ICON = 4,
+ DVASPECT_DOCPRINT = 8 -->
+ <xsl:variable name="ms-aspect" select="parent::w:pict/o:OLEObject/@DrawAspect"/>
+ <xsl:choose>
+ <xsl:when test="$ms-aspect = 'Content'">1</xsl:when>
+ <xsl:when test="$ms-aspect = 'Thumbnail'">2</xsl:when>
+ <xsl:when test="$ms-aspect = 'Icon'">4</xsl:when>
+ <xsl:when test="$ms-aspect = 'Docprint'">8</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="parent::w:pict/o:OLEObject">
+ <xsl:attribute name="style:vertical-pos">middle</xsl:attribute>
+ <xsl:attribute name="style:vertical-rel">baseline</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains($style-str,'mso-position-vertical:')">
+ <xsl:attribute name="style:vertical-pos">
+ <xsl:value-of select="substring-before( substring-after( $style-str , 'mso-position-vertical:') , ';')"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="v:imagedata or v:textbox">
+ <xsl:attribute name="style:vertical-pos">from-top</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="string-length($draw-stroke) &gt; 0">
+ <!--draw:stroke="dash" draw:stroke-dash="Ohon!Ultrafine dashed" -->
+ <xsl:choose>
+ <xsl:when test="not ($draw-stroke = 'none')">
+ <xsl:attribute name="draw:stroke">
+ <xsl:value-of select="'dash'"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:stroke-dash">
+ <xsl:value-of select="$draw-stroke"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="draw:stroke">
+ <xsl:value-of select="'none'"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$vchild/v:stroke/@startarrow">
+ <!--<v:stroke startarrow="block" startarrowwidth="wide" startarrowlength="long"/-->
+ <xsl:attribute name="draw:marker-start">
+ <xsl:value-of select="concat('markerstart',$stroke-num)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$vchild/v:stroke/@endarrow">
+ <!--<v:stroke startarrow="block" startarrowwidth="wide" startarrowlength="long"/-->
+ <xsl:attribute name="draw:marker-end">
+ <xsl:value-of select="concat('markerend',$stroke-num)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$vchild/@strokeweight">
+ <xsl:attribute name="svg:stroke-width">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$vchild/@strokeweight"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$vchild/@strokecolor">
+ <xsl:attribute name="svg:stroke-color">
+ <xsl:call-template name="MapConstColor">
+ <xsl:with-param name="color" select="$vchild/@strokecolor"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$vchild/@fillcolor">
+ <xsl:attribute name="draw:fill-color">
+ <xsl:call-template name="MapConstColor">
+ <xsl:with-param name="color" select="$vchild/@fillcolor"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not($vchild/@fillcolor)">
+ <xsl:choose>
+ <xsl:when test="ancestor::v:group | v:shadow">
+ <xsl:attribute name="draw:fill-color">#ffffff</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="not($vchild/v:fill) and not(v:shadow)">
+ <xsl:attribute name="draw:fill">none</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$vchild/v:fill/@opacity">
+ <xsl:attribute name="draw:opacity">
+ <xsl:call-template name="convert2percent">
+ <xsl:with-param name="value" select="$vchild/v:fill/@opacity"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$vchild/v:fill/@type = 'pattern' or $vchild/v:fill/@type = 'tile' or $vchild/v:fill/@type = 'frame'">
+ <xsl:attribute name="draw:fill">bitmap</xsl:attribute>
+ <xsl:attribute name="draw:fill-image-name">
+ <xsl:value-of select="translate($vchild/v:fill/@src,'&#9;&#10;&#13;&#32;:/.','' ) "/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$vchild/v:fill/@type = 'gradient'">
+ <xsl:attribute name="draw:fill">gradient</xsl:attribute>
+ <xsl:attribute name="draw:fill-gradient-name">
+ <xsl:value-of select=" 'gradient' "/>
+ <xsl:apply-templates mode="get-xsl-number" select="$vchild/v:fill"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates mode="style" select="v:shadow"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <!--Default style which will surely be removed during imported from a .flat file to SO-->
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">Tgr<xsl:number from="/w:wordDocument/w:body" level="any" count="v:*" format="1"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">graphic</xsl:attribute>
+ <style:graphic-properties draw:textarea-horizontal-align="center" draw:textarea-vertical-align="middle" style:wrap="none" draw:fill="none"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="name() = 'v:group'">
+ <xsl:apply-templates mode="style" select="v:*"/>
+ </xsl:if>
+ <xsl:apply-templates mode="style" select="v:textpath"/>
+ </xsl:template>
+ <xsl:template match="v:shadow" mode="style">
+ <!-- v:shadow on="t" color="aqua" opacity=".5" offset="13pt,11pt" offset2="14pt,10pt" -->
+ <xsl:attribute name="draw:shadow">
+ <xsl:choose>
+ <xsl:when test="contains(@on,'f')">hidden</xsl:when>
+ <xsl:otherwise>visible</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="draw:shadow-color">
+ <xsl:call-template name="MapConstColor">
+ <xsl:with-param name="color" select="@color"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:if test="string-length(@opacity) &gt;0">
+ <xsl:attribute name="draw:shadow-opacity">
+ <xsl:call-template name="convert2percent">
+ <xsl:with-param name="value" select="@opacity"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="contains(@offset,',')">
+ <xsl:attribute name="draw:shadow-offset-x">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="substring-before(@offset,',')"/>
+ <xsl:with-param name="TargetMeasure" select=" 'cm' "/>
+ </xsl:call-template>
+ <xsl:value-of select="'cm'"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:shadow-offset-y">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="substring-after(@offset,',')"/>
+ <xsl:with-param name="TargetMeasure" select=" 'cm' "/>
+ </xsl:call-template>
+ <xsl:value-of select="'cm'"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="draw:shadow-offset-x">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="@offset"/>
+ <xsl:with-param name="TargetMeasure" select=" 'cm' "/>
+ </xsl:call-template>
+ <xsl:value-of select="'cm'"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:shadow-offset-y">0.062cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@type='perspective' and @offset='0,0'">
+ <xsl:message>This kind of shadow does not support yet.</xsl:message>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="convert2percent">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="contains($value,'%')">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:when test="contains($value,'f')">
+ <xsl:variable name="num-value" select="round(substring-before($value,'f') div 6.5536) div 100"/>
+ <xsl:value-of select="concat(100 - $num-value ,'%')"/>
+ </xsl:when>
+ <xsl:when test="string-length($value) = 0">
+ <xsl:value-of select="'1%'"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($value * 100 ,'%')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:pict">
+ <xsl:param name="x-scale" select="1"/>
+ <xsl:param name="y-scale" select="1"/>
+ <xsl:param name="group-left" select="0"/>
+ <xsl:param name="group-top" select="0"/>
+ <xsl:param name="coord-left" select="0"/>
+ <xsl:param name="coord-top" select="0"/>
+ <xsl:param name="MeasureMark"/>
+ <xsl:apply-templates>
+ <xsl:with-param name="x-scale" select="$x-scale"/>
+ <xsl:with-param name="y-scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-left" select="$group-left"/>
+ <xsl:with-param name="group-top" select="$group-top"/>
+ <xsl:with-param name="coord-left" select="$coord-left"/>
+ <xsl:with-param name="coord-top" select="$coord-top"/>
+ </xsl:apply-templates>
+ </xsl:template>
+ <xsl:template name="get-middle-substring">
+ <xsl:param name="string"/>
+ <xsl:param name="prefix"/>
+ <xsl:param name="suffix"/>
+ <xsl:if test="contains($string, $prefix)">
+ <xsl:choose>
+ <xsl:when test="contains(substring-after( $string, $prefix), $suffix)">
+ <xsl:value-of select="substring-before(substring-after( $string, $prefix), $suffix)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-after( $string, $prefix)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:binData">
+ </xsl:template>
+ <xsl:template match="v:group">
+ <xsl:param name="x-scale" select="1"/>
+ <xsl:param name="y-scale" select="1"/>
+ <xsl:param name="MeasureMark"/>
+ <xsl:param name="group-left" select="0"/>
+ <xsl:param name="group-top" select="0"/>
+ <xsl:param name="coord-left" select="0"/>
+ <xsl:param name="coord-top" select="0"/>
+ <xsl:variable name="style" select="concat(@style, ';')"/>
+ <xsl:variable name="left">
+ <xsl:variable name="direct-left" select="substring-before(substring-after($style,';left:'),';')"/>
+ <xsl:variable name="margin-left" select="substring-before( substring-after($style,'margin-left:') ,';')"/>
+ <xsl:call-template name="Add-with-Measure">
+ <xsl:with-param name="value1" select="$margin-left"/>
+ <xsl:with-param name="value2" select="$direct-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="top">
+ <xsl:variable name="direct-top" select="substring-before(substring-after($style,';top:'),';')"/>
+ <xsl:variable name="margin-top" select="substring-before( substring-after($style,'margin-top:') ,';')"/>
+ <xsl:call-template name="Add-with-Measure">
+ <xsl:with-param name="value1" select="$margin-top"/>
+ <xsl:with-param name="value2" select="$direct-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="width" select="substring-before( substring-after($style,'width:') ,';')"/>
+ <xsl:variable name="height" select="substring-before(substring-after($style,'height:'),';')"/>
+ <xsl:variable name="Current-coord-left">
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="substring-before(@coordorigin, ',' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="Current-coord-top">
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="substring-after(@coordorigin, ',' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="Current-coord-width">
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="substring-before(@coordsize, ',' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="Current-coord-height">
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="substring-after(@coordsize, ',' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="Current-MeasureMark">
+ <xsl:choose>
+ <xsl:when test="string-length($MeasureMark) &gt; 0">
+ <xsl:value-of select="$MeasureMark"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" 'cm' "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="left-value">
+ <xsl:variable name="adjusted-left">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$left"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$Current-MeasureMark"/>
+ <xsl:with-param name="Target-Measure" select="$Current-MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="$adjusted-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="top-value">
+ <xsl:variable name="adjusted-top">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$top"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$Current-MeasureMark"/>
+ <xsl:with-param name="Target-Measure" select="$Current-MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="$adjusted-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="width-value">
+ <xsl:variable name="adjusted-width">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$width"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$Current-MeasureMark"/>
+ <xsl:with-param name="Target-Measure" select="$Current-MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="$adjusted-width"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="height-value">
+ <xsl:variable name="adjusted-height">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$height"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$Current-MeasureMark"/>
+ <xsl:with-param name="Target-Measure" select="$Current-MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="$adjusted-height"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="Current-x-scale" select="( $Current-coord-width div $width-value ) * $x-scale"/>
+ <xsl:variable name="Current-y-scale" select="( $Current-coord-height div $height-value ) * $y-scale"/>
+ <xsl:choose>
+ <xsl:when test="@editas='canvas' ">
+ <!-- frame -->
+ <xsl:variable name="style-name">Tgr<xsl:number from="/w:wordDocument/w:body" level="any" count="v:*" format="1"/>
+ </xsl:variable>
+ <xsl:variable name="frame-name">frame<xsl:number from="/w:wordDocument/w:body" level="any" count="v:group" format="1"/>
+ </xsl:variable>
+ <draw:frame draw:style-name="{$style-name}" draw:name="{$frame-name}" text:anchor-type="as-char" svg:x="{$left-value}{$Current-MeasureMark}" svg:y="{$top-value}{$Current-MeasureMark}" svg:width="{$width-value}{$Current-MeasureMark}" svg:height="{$height-value}{$Current-MeasureMark}" draw:z-index="0">
+ <draw:text-box>
+ <text:p text:style-name="Drawing">
+ <xsl:apply-templates select="w:r/w:pict | v:*">
+ <xsl:with-param name="x-scale" select="$Current-x-scale"/>
+ <xsl:with-param name="y-scale" select="$Current-y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$Current-MeasureMark"/>
+ <xsl:with-param name="group-left" select="$left-value"/>
+ <xsl:with-param name="group-top" select="$top-value"/>
+ <xsl:with-param name="coord-left" select="$Current-coord-left"/>
+ <xsl:with-param name="coord-top" select="$Current-coord-top"/>
+ </xsl:apply-templates>
+ </text:p>
+ </draw:text-box>
+ </draw:frame>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="draw:g">
+ <xsl:apply-templates select="w:r/w:pict | v:*">
+ <xsl:with-param name="x-scale" select="$Current-x-scale"/>
+ <xsl:with-param name="y-scale" select="$Current-y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$Current-MeasureMark"/>
+ <xsl:with-param name="group-left" select="$left-value"/>
+ <xsl:with-param name="group-top" select="$top-value"/>
+ <xsl:with-param name="coord-left" select="$Current-coord-left"/>
+ <xsl:with-param name="coord-top" select="$Current-coord-top"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="v:*">
+ <xsl:param name="x-scale" select="1"/>
+ <xsl:param name="y-scale" select="1"/>
+ <xsl:param name="MeasureMark"/>
+ <xsl:param name="group-left" select="0"/>
+ <xsl:param name="group-top" select="0"/>
+ <xsl:param name="coord-left" select="0"/>
+ <xsl:param name="coord-top" select="0"/>
+ <xsl:if test="not (name() = 'v:shapetype' )">
+ <xsl:call-template name="DrawElements">
+ <xsl:with-param name="x-scale" select="$x-scale"/>
+ <xsl:with-param name="y-scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-left" select="$group-left"/>
+ <xsl:with-param name="group-top" select="$group-top"/>
+ <xsl:with-param name="coord-left" select="$coord-left"/>
+ <xsl:with-param name="coord-top" select="$coord-top"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="DrawElements">
+ <xsl:param name="x-scale" select="1"/>
+ <xsl:param name="y-scale" select="1"/>
+ <xsl:param name="MeasureMark"/>
+ <xsl:param name="group-left" select="0"/>
+ <xsl:param name="group-top" select="0"/>
+ <xsl:param name="coord-left" select="0"/>
+ <xsl:param name="coord-top" select="0"/>
+ <xsl:param name="force-draw" select="'false'"/>
+ <xsl:param name="shape-type"/>
+ <xsl:variable name="wordshapename" select="substring-after(name(),':')"/>
+ <xsl:variable name="custom_shapename">
+ <xsl:if test="$wordshapename='roundrect' ">round-rectangle</xsl:if>
+ <xsl:if test="$wordshapename='shape' and not (v:imagedata) and not (v:textbox) and @type">
+ <xsl:call-template name="ms_word_draw_map2ooo_custom_draw">
+ <xsl:with-param name="ms_word_draw_type" select="@type"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="is-image" select="$wordshapename='shape' and v:imagedata"/>
+ <xsl:variable name="element-name">
+ <xsl:choose>
+ <xsl:when test="$wordshapename='line'">draw:line</xsl:when>
+ <xsl:when test="$wordshapename='rect'">draw:rect</xsl:when>
+ <xsl:when test="$wordshapename='oval'">draw:ellipse</xsl:when>
+ <xsl:when test="$wordshapename='arc'">draw:ellipse</xsl:when>
+ <xsl:when test="$wordshapename='polyline'">draw:polyline</xsl:when>
+ <xsl:when test="$wordshapename='roundrect' ">draw:custom-shape</xsl:when>
+ <xsl:when test="$wordshapename='shape' and v:imagedata">draw:frame</xsl:when>
+ <xsl:when test="$wordshapename='shape' and not (v:imagedata) and @type">
+ <xsl:choose>
+ <xsl:when test="string-length($custom_shapename) &gt; 0">draw:custom-shape</xsl:when>
+ <xsl:when test=" string-length(@type) &gt; 0 and key('shapetype',@type)">draw:custom-shape</xsl:when>
+ <xsl:otherwise>draw:rect</xsl:otherwise>
+ <!--if nothing match it, we prefer rect-->
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$wordshapename='shape' and v:textbox">draw:frame</xsl:when>
+ <!--changed here!-->
+ <xsl:otherwise>draw:path</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="wfill" select="@fill"/>
+ <xsl:variable name="draw-kind">
+ <xsl:if test="$wordshapename='arc' and string-length($wfill) &gt; 0">arc</xsl:if>
+ <!--Means this is a Segment of Circle-->
+ </xsl:variable>
+ <!--Get the position,left,top,width,height,z-index,flip from Style-->
+ <xsl:variable name="style" select="concat(@style, ';')"/>
+ <xsl:variable name="position" select="substring-before(substring-after($style,'position:'),';')"/>
+ <xsl:variable name="direct-left" select="substring-before(substring-after($style,';left:'),';')"/>
+ <xsl:variable name="left">
+ <xsl:variable name="margin-left" select="substring-before( substring-after($style,'margin-left:') ,';')"/>
+ <xsl:call-template name="Add-with-Measure">
+ <xsl:with-param name="value1" select="$margin-left"/>
+ <xsl:with-param name="value2" select="$direct-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="direct-top" select="substring-before(substring-after($style,';top:'),';')"/>
+ <xsl:variable name="top">
+ <xsl:variable name="margin-top" select="substring-before( substring-after($style,'margin-top:') ,';')"/>
+ <xsl:call-template name="Add-with-Measure">
+ <xsl:with-param name="value1" select="$margin-top"/>
+ <xsl:with-param name="value2" select="$direct-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="width" select="substring-before( substring-after($style,'width:') ,';')"/>
+ <xsl:variable name="height" select="substring-before(substring-after($style,'height:'),';')"/>
+ <xsl:variable name="flip" select="substring-before(substring-after($style,'flip:'),';')"/>
+ <xsl:variable name="z-index" select="substring-before(substring-after($style,'z-index:'),';')"/>
+ <!--these are used for wrap margins get from style-->
+ <xsl:variable name="mso-wrap-distance-lefttmp" select="substring-after($style,'mso-wrap-distance-left:')"/>
+ <xsl:variable name="mso-wrap-distance-left" select="substring-before($mso-wrap-distance-lefttmp,';')"/>
+ <xsl:variable name="mso-wrap-distance-toptmp" select="substring-after($style,'mso-wrap-distance-top:')"/>
+ <xsl:variable name="mso-wrap-distance-top" select="substring-before($mso-wrap-distance-toptmp,';')"/>
+ <xsl:variable name="mso-wrap-distance-righttmp" select="substring-after($style,'mso-wrap-distance-right:')"/>
+ <xsl:variable name="mso-wrap-distance-right" select="substring-before($mso-wrap-distance-righttmp,';')"/>
+ <xsl:variable name="mso-wrap-distance-bottomtmp" select="substring-after($style,'mso-wrap-distance-bottom:')"/>
+ <xsl:variable name="mso-wrap-distance-bottom" select="substring-before($mso-wrap-distance-bottomtmp,';')"/>
+ <xsl:variable name="mso-position-horizontal-relativetmp" select="substring-after($style,'mso-position-horizontal-relative:')"/>
+ <xsl:variable name="mso-position-horizontal-relative" select="substring-before($mso-position-horizontal-relativetmp,';')"/>
+ <xsl:variable name="mso-position-vertical-relativetmp" select="substring-after($style,'mso-position-vertical-relative:')"/>
+ <xsl:variable name="mso-position-vertical-relative" select="substring-before($mso-position-vertical-relativetmp,';')"/>
+ <xsl:variable name="anchor-type">
+ <xsl:choose>
+ <xsl:when test="$mso-position-vertical-relative='page' or $mso-position-horizontal-relative = 'page'">page</xsl:when>
+ <xsl:when test="$position='absolute'">paragraph</xsl:when>
+ <xsl:otherwise>as-char</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="text-style-name">
+ <xsl:choose>
+ <xsl:when test="descendant::v:textbox">P1</xsl:when>
+ <xsl:when test="v:textpath">textpath<xsl:apply-templates mode="get-xsl-number" select="v:textpath"/>
+ </xsl:when>
+ <!--Should get the real style late-->
+ <xsl:otherwise>P1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="{$element-name}">
+ <xsl:if test="$element-name = 'draw:frame'">
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select="'frame'"/>
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="v:*" format="1"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$element-name ='draw:path'">
+ <xsl:choose>
+ <xsl:when test="string-length(@path) = 0">
+ <xsl:attribute name="svg:d">M 0,0 L 0,0</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="svg:d">
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="@path"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$element-name ='draw:path' or $wordshapename='polyline'">
+ <xsl:attribute name="svg:viewBox">
+ <xsl:value-of select="'0 0'"/>
+ <xsl:value-of select="' '"/>
+ <xsl:if test="string-length(@coordsize) = 0">
+ <xsl:value-of select="'1000 1000'"/>
+ </xsl:if>
+ <xsl:if test="not(string-length(@coordsize) = 0)">
+ <xsl:value-of select="translate(@coordsize,',',' ')"/>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains($style,'rotation:')">
+ <xsl:attribute name="draw:transform">
+ <xsl:variable name="rotate">
+ <xsl:call-template name="convert2redian">
+ <xsl:with-param name="x" select="substring-before(substring-after($style,'rotation:') , ';')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat( 'rotate(' , $rotate * -1 , ')' )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="text:anchor-type">
+ <xsl:value-of select="$anchor-type"/>
+ <!--This need to be checkout and built!-->
+ </xsl:attribute>
+ <xsl:if test="string-length($z-index) &gt; 0">
+ <xsl:if test="number($z-index) &lt; 0">
+ <xsl:attribute name="draw:z-index">
+ <xsl:value-of select="'0'"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(number($z-index) &lt; 0)">
+ <xsl:attribute name="draw:z-index">
+ <xsl:value-of select="$z-index"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:attribute name="draw:style-name">Tgr<xsl:number from="/w:wordDocument/w:body" level="any" count="v:*" format="1"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:text-style-name">
+ <xsl:value-of select="$text-style-name"/>
+ <!--This is difficult!!-->
+ </xsl:attribute>
+ <xsl:if test="$wordshapename='line'">
+ <xsl:variable name="fromx" select="substring-before(@from,',')"/>
+ <xsl:variable name="fromy" select="substring-after(@from,',')"/>
+ <xsl:variable name="tox" select="substring-before(@to,',')"/>
+ <xsl:variable name="toy" select="substring-after(@to,',')"/>
+ <xsl:variable name="valfromx"> </xsl:variable>
+ <xsl:if test="$anchor-type='as-char'">
+ <xsl:attribute name="svg:x1">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$fromx"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:y1">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$fromy"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-top"/>
+ <xsl:with-param name="coord-value" select="$coord-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:x2">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$tox"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:y2">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$toy"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-top"/>
+ <xsl:with-param name="coord-value" select="$coord-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not ($anchor-type='as-char')">
+ <xsl:attribute name="svg:x1">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$fromx"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:y1">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$toy"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-top"/>
+ <xsl:with-param name="coord-value" select="$coord-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:x2">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$tox"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:y2">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$fromy"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-top"/>
+ <xsl:with-param name="coord-value" select="$coord-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="$wordshapename='rect' or $wordshapename='oval' or $wordshapename='arc' or $wordshapename='shape' or $wordshapename='polyline' or ($wordshapename='shape' and v:textbox) or ($wordshapename='roundrect' and v:textbox) ">
+ <xsl:if test="$anchor-type='as-char'">
+ <xsl:attribute name="svg:width">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$width"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:height">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$height"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:x">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$left"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:y">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$top"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-top"/>
+ <xsl:with-param name="coord-value" select="$coord-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not ($anchor-type='as-char')">
+ <!--Something has to be down because We have Margin-top options-->
+ <xsl:attribute name="svg:width">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$width"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:height">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$height"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:x">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$left"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="svg:y">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$top"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$MeasureMark"/>
+ <xsl:with-param name="group-value" select="$group-top"/>
+ <xsl:with-param name="coord-value" select="$coord-top"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="$element-name='draw:ellipse' and string-length($draw-kind) &gt; 0">
+ <xsl:attribute name="draw:kind">
+ <xsl:value-of select="$draw-kind"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!--<draw:area-polygon … svg:x="0" svg:y="0" svg:width="2.0cm" svg:height="2.0cm" svg:viewBox="0 0 2000 2000" svg:points="400,1500 1600,1500 1000,400"/>
+ The element shown in the following example defines a triangle that is located in the middle of a 2cm by 2cm image. The bounding box covers an area of 2cm by 1.5cm. One view box unit corresponds to 0.01mm.-->
+ <xsl:if test="$wordshapename='polyline'">
+ <xsl:variable name="MeasureMark_Here" select="'cm'"/>
+ <!--MeasureMarkHere is cm because One view box unit corresponds to 0.01mm-->
+ <xsl:variable name="width_cm">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$width"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="height_cm">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$height"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="widthval">
+ <xsl:if test="contains($width_cm,'cm')">
+ <xsl:value-of select="round(substring-before($width_cm,'cm')*1000)"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="heightval">
+ <xsl:if test="contains($height_cm,'cm')">
+ <xsl:value-of select="round(substring-before($height_cm,'cm')*1000)"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="viewBoxstr" select="concat('0 0 ',$widthval,' ',$heightval)"/>
+ <xsl:attribute name="svg:viewBox">
+ <xsl:value-of select="$viewBoxstr"/>
+ </xsl:attribute>
+ <xsl:variable name="inputx_cm">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$left"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="group-value" select="$group-left"/>
+ <xsl:with-param name="coord-value" select="$coord-left"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="inputy_cm">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$top"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="group-value" select="$group-top"/>
+ <xsl:with-param name="coord-value" select="$coord-top"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="inputx_val">
+ <xsl:choose>
+ <xsl:when test="contains($inputx_cm,'cm')">
+ <xsl:value-of select="substring-before($inputx_cm,'cm')"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="inputy_val">
+ <xsl:choose>
+ <xsl:when test="contains($inputy_cm,'cm')">
+ <xsl:value-of select="substring-before($inputy_cm,'cm')"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="inputboxwidth" select="$widthval"/>
+ <xsl:variable name="oopoints">
+ <xsl:call-template name="wordpoints2oopoints">
+ <xsl:with-param name="input_x" select="$inputx_val"/>
+ <xsl:with-param name="input_y" select="$inputy_val"/>
+ <xsl:with-param name="input_width" select="$width"/>
+ <xsl:with-param name="input_height" select="$height"/>
+ <xsl:with-param name="input_boxwidth" select="$widthval"/>
+ <xsl:with-param name="input_boxheight" select="$heightval"/>
+ <xsl:with-param name="input_points" select="concat(@points,',')"/>
+ <!-- add a space to the end of input_points -->
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="string-length($oopoints) &gt; 0">
+ <xsl:attribute name="draw:points">
+ <xsl:value-of select="$oopoints"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="$is-image">
+ <xsl:variable name="the-image" select="key('imagedata',v:imagedata/@src)"/>
+ <xsl:choose>
+ <xsl:when test="string-length(v:imagedata/@o:title) &gt; 0">
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select="v:imagedata/@o:title"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="string-length(parent::w:pict/o:OLEObject/@ObjectID) &gt; 0">
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select="parent::w:pict/o:OLEObject/@ObjectID"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:apply-templates select="parent::w:pict/o:OLEObject" mode="output"/>
+ <draw:image>
+ <xsl:element name="office:binary-data">
+ <xsl:value-of select="translate($the-image/text(),'&#9;&#10;&#13;&#32;','' ) "/>
+ </xsl:element>
+ </draw:image>
+ </xsl:if>
+ <xsl:if test="$element-name = 'draw:custom-shape'">
+ <xsl:apply-templates select="v:textpath" mode="text-p">
+ <xsl:with-param name="type-textpath" select="key('shapetype',@type)/v:textpath[1]"/>
+ </xsl:apply-templates>
+ <xsl:element name="draw:enhanced-geometry">
+ <xsl:variable name="enhanced_path">
+ <!--enhanced_path call a template to get the enhanced-path-->
+ <xsl:choose>
+ <xsl:when test="string-length($custom_shapename) = 0">
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="@path"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:variable>
+ <!--####notice that:there is some drawing elements that don't have the shapetype so that can not have a viewbox
+ It is a ****problem**** now-so be sure to check it out.-->
+ <xsl:if test="$wordshapename='roundrect' ">
+ <xsl:variable name="tmp_MeasueMark">
+ <xsl:value-of select="'cm'"/>
+ </xsl:variable>
+ <xsl:variable name="svg_viewwidth">
+ <xsl:if test="$anchor-type='as-char'">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$width"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$tmp_MeasueMark"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not ($anchor-type='as-char')">
+ <!--Something has to be down because We have Margin-top options-->
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$width"/>
+ <xsl:with-param name="scale" select="$x-scale"/>
+ <xsl:with-param name="MeasureMark" select="$tmp_MeasueMark"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="svg_viewheight">
+ <xsl:if test="$anchor-type='as-char'">
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$height"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$tmp_MeasueMark"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not ($anchor-type='as-char')">
+ <!--Something has to be down because We have Margin-top options-->
+ <xsl:call-template name="convert-with-scale-and-measure">
+ <xsl:with-param name="value" select="$height"/>
+ <xsl:with-param name="scale" select="$y-scale"/>
+ <xsl:with-param name="MeasureMark" select="$tmp_MeasueMark"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="svg_viewBox">
+ <xsl:value-of select="concat( '0 0 ',substring-before($svg_viewwidth,$tmp_MeasueMark)*10000,' ',substring-before($svg_viewheight,$tmp_MeasueMark)*10000)"/>
+ </xsl:variable>
+ <xsl:attribute name="svg:viewBox">
+ <xsl:value-of select="$svg_viewBox"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($custom_shapename) &gt; 0">
+ <xsl:attribute name="draw:type">
+ <xsl:value-of select="$custom_shapename"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($enhanced_path) &gt; 0">
+ <xsl:attribute name="draw:enhanced-path">
+ <xsl:value-of select="$enhanced_path"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="typeid_adj">
+ <!--for fix the bug of version 1.63: the following description: adj="-11796480,,5400" in OOo should be: modifier =" -11796480 0 5400"-->
+ <xsl:variable name="tmp_adj">
+ <xsl:value-of select="key('shapetype',@type)/@adj"/>
+ </xsl:variable>
+ <xsl:if test="contains($tmp_adj, ',') ">
+ <xsl:variable name="number">
+ <xsl:value-of select="string-length(translate($tmp_adj,'+-0123456789 ','' ) )"/>
+ </xsl:variable>
+ <xsl:call-template name="get_non_omit_adj">
+ <xsl:with-param name="adj_typeid" select="$tmp_adj"/>
+ <xsl:with-param name="num" select="$number"/>
+ <xsl:with-param name="mark" select="',' "/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not (contains($tmp_adj, ',') )">
+ <xsl:value-of select="$tmp_adj"/>
+ </xsl:if>
+ </xsl:variable>
+ <!--the following choose statement code will process the revised modifier
+ It happens that if a drawing elements has more than 2 modifier, the modifier (or say adj
+ in wordml) can be adjusted and only the modified adj is recorded.
+ what makes it more complicated is that adj support both comma and blanks.
+ so you have to use kickblanks template to kick the blanks and change it to comma version.
+ <key('shapetype',@type)/v:textpath[1]-->
+ <xsl:choose>
+ <xsl:when test="string-length($typeid_adj) = 0">
+ <xsl:if test="contains(@adj,',')">
+ <!--Please Note that the modifier can be more than 2 , so use a translate can be more efficient.
+ -####Note that comma can't be recognized by OOo's modifiers
+ <xsl:variable name="adjust-x" select="substring-before(@adj,',')"/>
+ <xsl:variable name="adjust-y" select="substring-after(@adj,',')"/>
+ <xsl:variable name="adjuststr">
+ <xsl:if test="$adjust-x and $adjust-y">
+ -####Note that comma can't be recognized by OOo's modifiers->
+ <xsl:value-of select="concat( $adjust-x , ' ' ,$adjust-y )"/>
+ </xsl:if>
+ </xsl:variable>-->
+ <xsl:attribute name="draw:modifiers">
+ <xsl:value-of select="translate(@adj ,',' ,' ')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@adj and not(contains(@adj,','))">
+ <!--####Note that comma can't be recognized by OOo's modifiers.-->
+ <xsl:attribute name="draw:modifiers">
+ <xsl:value-of select="@adj"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <!--Means that you have to care about 2 adj parameters which is different-->
+ <xsl:variable name="mark_used_by_typeid">
+ <xsl:if test="contains($typeid_adj, ',' )">
+ <xsl:value-of select="',' "/>
+ </xsl:if>
+ <xsl:if test="not (contains( $typeid_adj, ',' ) ) ">
+ <xsl:value-of select="' ' "/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="@adj">
+ <xsl:variable name="remained_adj">
+ <xsl:if test="contains(@adj,',' ) ">
+ <xsl:variable name="number">
+ <xsl:value-of select="string-length(translate(@adj,'+-0123456789 ','' ) )"/>
+ </xsl:variable>
+ <xsl:call-template name="get_remained_adj">
+ <xsl:with-param name="adj_typeid" select="$typeid_adj"/>
+ <xsl:with-param name="num" select="$number+1"/>
+ <xsl:with-param name="mark" select="$mark_used_by_typeid"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="not (contains(@adj,',' ) ) ">
+ <xsl:variable name="tmp_str_adj">
+ <xsl:call-template name="kickblanks">
+ <xsl:with-param name="str" select="concat(' ' ,@adj,' ')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="number">
+ <xsl:value-of select="string-length(translate($tmp_str_adj,'+-0123456789','' ) )"/>
+ </xsl:variable>
+ <xsl:call-template name="get_remained_adj">
+ <xsl:with-param name="adj_typeid" select="$typeid_adj"/>
+ <xsl:with-param name="num" select="$number - 1"/>
+ <xsl:with-param name="mark" select="$mark_used_by_typeid "/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:attribute name="draw:modifiers">
+ <xsl:value-of select="translate(concat(@adj ,',' ,$remained_adj), ',' ,' ' )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="contains($typeid_adj,',')">
+ <xsl:attribute name="draw:modifiers">
+ <xsl:value-of select="translate($typeid_adj ,',' ,' ')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="not(contains($typeid_adj,','))">
+ <xsl:attribute name="draw:modifiers">
+ <xsl:value-of select="$typeid_adj"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="@type">
+ <xsl:apply-templates select="v:textpath" mode="output">
+ <xsl:with-param name="type-textpath" select="key('shapetype',@type)/v:textpath[1]"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="key('shapetype',@type)" mode="output">
+ <xsl:with-param name="instance" select="."/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="$wordshapename='shape' and v:textbox and $element-name='draw:frame' ">
+ <xsl:element name="draw:text-box">
+ <xsl:apply-templates select="v:textbox/w:txbxContent/w:p"/>
+ </xsl:element>
+ </xsl:when>
+ <!--It is a case statement for all shapes,so we add v:roundrect here.-->
+ <xsl:when test="$wordshapename='roundrect' and v:textbox and $element-name='draw:frame' ">
+ <xsl:element name="draw:text-box">
+ <xsl:apply-templates select="v:textbox/w:txbxContent/w:p"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="v:textbox">
+ <xsl:apply-templates select="v:textbox/w:txbxContent/w:p"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:docOleData" mode="init">
+ <xsl:apply-templates select="w:binData[@w:name='oledata.mso']" mode="oledata.mso"/>
+ </xsl:template>
+ <xsl:template match="w:binData" mode="oledata.mso">
+ <xsl:variable name="tmp" select="ole:insertByName('oledata.mso', translate(text(),'&#10;&#13;&#32;','' ) )"/>
+ </xsl:template>
+ <xsl:template match="o:OLEObject " mode="output">
+ <!-- depends on i43230,we can uncomment this code or find another way after i43230 got fixed -->
+ <draw:object-ole>
+ <xsl:element name="office:binary-data">
+ <xsl:value-of select="translate(ole:getByName(@ObjectID),'&#13;','')"/>
+ </xsl:element>
+ </draw:object-ole>
+ </xsl:template>
+ <xsl:template name="get-vml-value">
+ <xsl:param name="node1" select="''"/>
+ <xsl:param name="property-name"/>
+ <xsl:variable name="pn" select="concat(';',$property-name, ':')"/>
+ <xsl:choose>
+ <xsl:when test="string-length(@*[name() = $property-name]) &gt; 0">
+ <xsl:value-of select="@*[name() = $property-name]"/>
+ </xsl:when>
+ <xsl:when test="string-length(@style) &gt; 0 and contains(concat(';',translate(@style,' ','')),$pn)">
+ <xsl:value-of select=" substring-before( concat(substring-after(concat(';',translate($node1/@style,' ','')) , $pn),';') , ';') "/>
+ </xsl:when>
+ <xsl:when test="$node1 and string-length($node1/@*[name() = $property-name]) &gt; 0">
+ <xsl:value-of select="$node1/@*[name() = $property-name]"/>
+ </xsl:when>
+ <xsl:when test="$node1 and string-length($node1/@style) &gt; 0 and contains(concat(';',translate($node1/@style,' ','')),$pn)">
+ <xsl:value-of select=" substring-before( concat(substring-after(concat(';',translate($node1/@style,' ','')) , $pn),';') , ';') "/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="v:textpath" mode="text-p">
+ <xsl:param name="type-textpath" select="''"/>
+ <xsl:variable name="the-string">
+ <xsl:call-template name="get-vml-value">
+ <xsl:with-param name="node1" select="$type-textpath"/>
+ <xsl:with-param name="property-name" select="'string'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="style-name">
+ <xsl:value-of select="'textpath'"/>
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="v:textpath" format="1"/>
+ </xsl:variable>
+ <text:p text:style-name="{$style-name}">
+ <xsl:value-of select="$the-string"/>
+ </text:p>
+ </xsl:template>
+ <xsl:template match="v:textpath" mode="style">
+ <xsl:if test="contains(@style,'font-family:')">
+ <xsl:variable name="style-name">
+ <xsl:value-of select="'textpath'"/>
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="v:textpath" format="1"/>
+ </xsl:variable>
+ <xsl:variable name="font-family">
+ <!-- we need remove the additional &quot; from font-family -->
+ <xsl:value-of select="translate(substring-before(substring-after(@style,'font-family:'),';'), '&quot;' ,'')"/>
+ </xsl:variable>
+ <xsl:variable name="font-size">
+ <xsl:choose>
+ <xsl:when test="contains(@style,'font-size:')">
+ <xsl:value-of select="substring-before(substring-after(@style,'font-size:'),';')"/>
+ </xsl:when>
+ <xsl:otherwise>36pt</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <style:style style:name="{$style-name}" style:family="paragraph">
+ <style:paragraph-properties text:enable-numbering="false" style:writing-mode="lr-tb"/>
+ <style:text-properties fo:font-family="{$font-family}" fo:font-size="{$font-size}" style:font-family-generic="roman" style:text-scale="80%"/>
+ </style:style>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="v:textpath" mode="output">
+ <xsl:param name="type-textpath" select="''"/>
+ <xsl:variable name="on">
+ <xsl:call-template name="get-vml-value">
+ <xsl:with-param name="node1" select="$type-textpath"/>
+ <xsl:with-param name="property-name" select="'on'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="starts-with($on,'t')">
+ <xsl:attribute name="draw:text-path">true</xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="fitshape">
+ <xsl:call-template name="get-vml-value">
+ <xsl:with-param name="node1" select="$type-textpath"/>
+ <xsl:with-param name="property-name" select="'fitshape'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="fitpath">
+ <xsl:call-template name="get-vml-value">
+ <xsl:with-param name="node1" select="$type-textpath"/>
+ <xsl:with-param name="property-name" select="'fitpath'"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="draw:type">fontwork-plain-text</xsl:attribute>
+ <xsl:attribute name="draw:text-path-mode">
+ <xsl:choose>
+ <xsl:when test="starts-with($fitpath,'t') ">path</xsl:when>
+ <xsl:when test="starts-with($fitshape,'t') ">shape</xsl:when>
+ <xsl:otherwise>normal</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="draw:text-path-scale">path</xsl:attribute>
+ <!-- xsl:attribute name="draw:text-path-same-letter-heights">false</xsl:attribute -->
+ <!-- xsl:attribute name="draw:text-path-scale-x">false</xsl:attribute -->
+ </xsl:template>
+ <xsl:template match="v:shapetype" mode="output">
+ <xsl:param name="instance" select="''"/>
+ <!--#Dummy after version 1.63 The following test is for the adj attribute of the file. It is Dummy now.
+ <xsl:if test="not($instance/@adj)">
+ <xsl:if test="contains(@adj,',')">-->
+ <!--Please Note that the modifier can be more than 2 , so use a translate can be more efficient.
+ -####Note that comma can't be recognized by OOo's modifiers
+ <xsl:variable name="adjust-x" select="substring-before(@adj,',')"/>
+ <xsl:variable name="adjust-y" select="substring-after(@adj,',')"/>
+ <xsl:variable name="adjuststr">
+ <xsl:if test="$adjust-x and $adjust-y">
+ < -####Note that comma can't be recognized by OOo's modifiers.->
+ <xsl:value-of select="concat( $adjust-x , ' ' ,$adjust-y )"/>
+ </xsl:if>
+ </xsl:variable>-->
+ <!--Dummy after version 1.63 <xsl:attribute name="draw:modifiers">
+ <xsl:value-of select="translate(@adj, ',' , ' ' )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@adj and not(contains(@adj,','))">-->
+ <!--####Note that comma can't be recognized by OOo's modifiers.-->
+ <!--Dummy after version 1.63 <xsl:attribute name="draw:modifiers">
+ <xsl:value-of select="@adj"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>-->
+ <xsl:variable name="viewbox">
+ <xsl:value-of select="'0 0'"/>
+ <xsl:value-of select="' '"/>
+ <xsl:if test="string-length(@coordsize) = 0">
+ <xsl:value-of select="'1000 1000'"/>
+ </xsl:if>
+ <xsl:if test="not(string-length(@coordsize) = 0)">
+ <xsl:value-of select="translate(@coordsize,',',' ')"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:attribute name="svg:viewBox">
+ <xsl:value-of select="$viewbox"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:text-areas">
+ <xsl:value-of select="$viewbox"/>
+ </xsl:attribute>
+ <!-- This path need be output is instance does not have a path-->
+ <xsl:if test="not($instance/@path) and string-length(@path) &gt;0">
+ <xsl:attribute name="draw:enhanced-path">
+ <!--<xsl:call-template name="vmlpath2svgpath">rrrrrrevised-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="@path"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="v:formulas | v:handles" mode="output"/>
+ </xsl:template>
+ <xsl:template match="v:formulas" mode="output">
+ <xsl:apply-templates select="v:f" mode="output"/>
+ </xsl:template>
+ <xsl:template match="v:f" mode="output">
+ <xsl:element name="draw:equation">
+ <xsl:attribute name="draw:formula">
+ <xsl:call-template name="v-formula2o-formula">
+ <xsl:with-param name="v-formula" select="@eqn"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:attribute name="draw:name">
+ <xsl:value-of select="'f'"/>
+ <xsl:variable name="the-number">
+ <xsl:number format="1" level="single"/>
+ </xsl:variable>
+ <xsl:value-of select="$the-number - 1"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="v-formula2o-formula">
+ <xsl:param name="v-formula"/>
+ <xsl:variable name="command" select="substring-before(normalize-space($v-formula), ' ')"/>
+ <xsl:variable name="tmp" select="normalize-space(substring-after($v-formula, $command ))"/>
+ <xsl:variable name="step1">
+ <xsl:choose>
+ <xsl:when test="$command ='val'">
+ <xsl:value-of select="$tmp"/>
+ </xsl:when>
+ <!-- (sum a b c) = (a + b - c)-->
+ <xsl:when test="$command = 'sum' ">
+ <xsl:call-template name="replace-space">
+ <xsl:with-param name="value" select="$tmp"/>
+ <xsl:with-param name="replace1" select="'+'"/>
+ <xsl:with-param name="replace2" select="'-'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- (prod a b c) = (a * b / c)-->
+ <xsl:when test="$command = 'prod'">
+ <xsl:call-template name="replace-space">
+ <xsl:with-param name="value" select="$tmp"/>
+ <xsl:with-param name="replace1" select="'*'"/>
+ <xsl:with-param name="replace2" select="'/'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- (mid a b) = ((a + b) / 2)-->
+ <xsl:when test="$command = 'mid'">
+ <xsl:value-of select="concat('(' , translate($tmp,' ', '+') , ') / 2' )"/>
+ </xsl:when>
+ <!-- (if a b c) = (a>0? b : c) Conditional testing. -->
+ <xsl:when test="$command = 'if' ">
+ <xsl:value-of select="concat('if(' , translate($tmp,' ', ',') , ')' )"/>
+ </xsl:when>
+ <!-- (min a b) = (min (a , b) )-->
+ <!-- (max a b) = (max (a , b) )-->
+ <xsl:when test="$command = 'min' or $command = 'max'">
+ <xsl:value-of select="concat($command, '(' , translate($tmp,' ', ',') , ')' )"/>
+ </xsl:when>
+ <xsl:when test="$command = 'abs' or $command = 'sqrt'">
+ <xsl:value-of select="concat($command, '(' , $tmp , ')' )"/>
+ </xsl:when>
+ <!-- sin(a,b) = a*sin(b) -->
+ <xsl:when test="$command = 'sin' or $command = 'cos' or $command = 'tan' ">
+ <!-- atan is not this kind 2 $command = 'atan2' "-->
+ <xsl:variable name="value1" select="substring-before($tmp,' ')"/>
+ <xsl:variable name="value2" select="substring-after($tmp,' ')"/>
+ <xsl:value-of select="concat( $value1 , ' * ' , $command, '(' , $value2 , ')' )"/>
+ </xsl:when>
+ <!-- -->
+ <xsl:when test="$command = 'atan2' ">
+ <xsl:variable name="value1" select="substring-before($tmp,' ')"/>
+ <xsl:variable name="value2" select="substring-after($tmp,' ')"/>
+ <xsl:value-of select="concat( $command , '( ' , $value2, ',' , $value1 , ')' )"/>
+ </xsl:when>
+ <!-- -->
+ <!--><xsl:when test="$command = 'atan2' ">
+ <xsl:variable name="value1" select="substring-before($tmp,' ')"/>
+ <xsl:variable name="value2" select="substring-after($tmp,' ')"/>
+ <xsl:value-of select="concat( 'atan' , '( ' , $value2, '/' , $value1 , ')' )"/>
+ </xsl:when><- -->
+ <!-- ellipse and sumangle are always used by arc command like this
+ eqn="ellipse @24 @4 height" ; and eqn="sumangle @2 360 0"
+ mod is always used too.-->
+ <!--mod =sqrt( v*v + P1×P1 + P2×P2). ( 3 parameters )-->
+ <xsl:when test="$command='mod' ">
+ <xsl:variable name="value1" select="substring-before($tmp,' ')"/>
+ <xsl:variable name="value2" select="substring-before(substring-after($tmp,' '), ' ')"/>
+ <xsl:variable name="value3" select="substring-after(substring-after($tmp,' '), ' ')"/>
+ <xsl:value-of select="concat( 'sqrt( ' , $value3, ' * ',$value3, ' + ' ,$value2, ' * ' ,$value2, ' + ' ,$value1, ' * ', $value1, ' )' )"/>
+ </xsl:when>
+ <!--ellipse= P2* sqrt(1 - v*v /P1*P1) ( 3 parameters )-->
+ <xsl:when test="$command='ellipse' ">
+ <xsl:variable name="value1" select="substring-before($tmp,' ')"/>
+ <xsl:variable name="value2" select="substring-before(substring-after($tmp,' '), ' ')"/>
+ <xsl:variable name="value3" select="substring-after(substring-after($tmp,' '), ' ')"/>
+ <xsl:value-of select="concat( $value3 , ' * sqrt( ' , $value2 , ' * ' , $value2, ' - ',$value1 , ' * ', $value1, ' )' ,'/',$value2 )"/>
+ </xsl:when>
+ <!--sumangle =v + P1×2^16 - P2×2^16. ( 3 parameters )-->
+ <!--<xsl:when test="$command='sumangle' ">
+ <xsl:variable name="value1" select="substring-before($tmp,' ')"/>
+ <xsl:variable name="value2" select="substring-before(substring-after($tmp,' '), ' ')"/>
+ <xsl:variable name="value3" select="substring-after(substring-after($tmp,' '), ' ')"/>
+ <xsl:value-of select="concat( $value1 , '+' , $value2 , ' * ' , '65535',' + ', $value2,' - ' ,$value3 , ' * ', '65535', ' - ', $value3)"/>
+ </xsl:when>-->
+ <!--sumangle =v + P1×2^16 - P2×2^16. ( 3 parameters )-->
+ <xsl:when test="$command='sumangle' ">
+ <xsl:variable name="value1" select="substring-before($tmp,' ')"/>
+ <xsl:variable name="value2" select="substring-before(substring-after($tmp,' '), ' ')"/>
+ <xsl:variable name="value3" select="substring-after(substring-after($tmp,' '), ' ')"/>
+ <xsl:value-of select="concat( $value1 , '+' , $value2 , '*pi/180',' - ' ,$value3 , '*pi/180' )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>Find an unsupported formula:<xsl:value-of select="$v-formula"/>
+ </xsl:message>
+ <!--<xsl:value-of select="'0'"/><-for release use-->
+ <xsl:value-of select="concat('not found this:', $v-formula)"/>
+ <!--for Debug use-->
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="step2">
+ <xsl:value-of select="translate($step1,'#','$')"/>
+ </xsl:variable>
+ <xsl:call-template name="replace-at">
+ <xsl:with-param name="value" select="$step2"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="replace-space">
+ <xsl:param name="value"/>
+ <xsl:param name="replace1"/>
+ <xsl:param name="replace2"/>
+ <xsl:value-of select=" concat( substring-before($value,' ') , $replace1, translate(substring-after($value,' '), ' ', $replace2 ) ) "/>
+ </xsl:template>
+ <xsl:template name="replace-at">
+ <xsl:param name="value"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:choose>
+ <xsl:when test="string-length($value) &lt; $position">
+ <xsl:value-of select="$value"/>
+ </xsl:when>
+ <xsl:when test="substring($value,$position,1) = '@'">
+ <xsl:call-template name="replace-at">
+ <xsl:with-param name="value" select="concat(substring($value,1,$position -1) , '?f' , substring($value,$position+1)) "/>
+ <xsl:with-param name="position" select="$position + 2"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="replace-at">
+ <xsl:with-param name="value" select="$value"/>
+ <xsl:with-param name="position" select="$position + 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test=" substring($value,$position,1) = '@'">
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="v:handles" mode="output">
+ <xsl:apply-templates select="v:h" mode="output"/>
+ </xsl:template>
+ <xsl:template match="v:h" mode="output">
+ <xsl:element name="draw:handle">
+ <xsl:if test="@position">
+ <xsl:attribute name="draw:handle-position">
+ <xsl:value-of select="translate(@position,'#,' , '$ ')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@switch">
+ <xsl:attribute name="draw:handle-switched">
+ <xsl:value-of select="@switch"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@xrange">
+ <xsl:attribute name="draw:handle-range-x-maximum">
+ <xsl:value-of select="substring-after(@xrange,',')"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:handle-range-x-minimum">
+ <xsl:value-of select="substring-before(@xrange,',')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="@yrange">
+ <xsl:attribute name="draw:handle-range-y-maximum">
+ <xsl:value-of select="substring-after(@yrange,',')"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:handle-range-y-minimum">
+ <xsl:value-of select="substring-before(@yrange,',')"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <!--this template map word's points to svg:viewbox's point they are quite different because word's use pt but svg's use 0.001cm as a unit-->
+ <xsl:template name="wordpoints2oopoints">
+ <xsl:param name="input_points"/>
+ <xsl:param name="input_x"/>
+ <xsl:param name="input_y"/>
+ <xsl:param name="input_width"/>
+ <xsl:param name="input_height"/>
+ <xsl:param name="input_boxwidth"/>
+ <xsl:param name="input_boxheight"/>
+ <xsl:variable name="ptx" select="substring-before($input_points,',')"/>
+ <xsl:variable name="tempstr" select="substring-after($input_points,',')"/>
+ <xsl:variable name="pty" select="substring-before($tempstr,',')"/>
+ <xsl:variable name="nextinput" select="substring-after ($tempstr,',')"/>
+ <xsl:if test="$ptx and $pty">
+ <xsl:variable name="val_ptx">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="$ptx"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="val_pty">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="$pty"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="round( $input_boxwidth - ( $val_ptx - $input_x ) * 1000 )"/>
+ <xsl:value-of select="','"/>
+ <xsl:value-of select="round( ( $val_pty - $input_y ) * 1000 )"/>
+ </xsl:if>
+ <xsl:if test="contains($nextinput,',')">
+ <xsl:value-of select="' '"/>
+ <!--Leave a blank first as mark of points group-->
+ <xsl:call-template name="wordpoints2oopoints">
+ <xsl:with-param name="input_points" select="$nextinput"/>
+ <xsl:with-param name="input_x" select="$input_x"/>
+ <xsl:with-param name="input_y" select="$input_y"/>
+ <xsl:with-param name="input_width" select="$input_width"/>
+ <xsl:with-param name="input_height" select="$input_height"/>
+ <xsl:with-param name="input_boxwidth" select="$input_boxwidth"/>
+ <xsl:with-param name="input_boxheight" select="$input_boxheight"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <!--template MapConstColor:input is a color in form of const e.g 'red' or number e.g '#ff0010' output is a number color-->
+ <xsl:template name="MapConstColor">
+ <xsl:param name="color"/>
+ <xsl:choose>
+ <xsl:when test="$color='black'">#000000</xsl:when>
+ <xsl:when test="$color='olive'">#808000</xsl:when>
+ <xsl:when test="$color='red'">#ff0000</xsl:when>
+ <xsl:when test="$color='teal'">#008080</xsl:when>
+ <xsl:when test="$color='green'">#00ff00</xsl:when>
+ <xsl:when test="$color='gray'">#808080</xsl:when>
+ <xsl:when test="$color='blue'">#0000ff</xsl:when>
+ <xsl:when test="$color='navy'">#000080</xsl:when>
+ <xsl:when test="$color='white'">#ffffff</xsl:when>
+ <xsl:when test="$color='lime'">#00ff00</xsl:when>
+ <xsl:when test="$color='yellow'">#ffff00</xsl:when>
+ <xsl:when test="$color='fuchsia'">#ff00ff</xsl:when>
+ <xsl:when test="$color='purple'">#800080</xsl:when>
+ <xsl:when test="$color='aqua'">#00ffff</xsl:when>
+ <xsl:when test="$color='maroon'">#800000</xsl:when>
+ <xsl:when test="$color='silver'">#c0c0c0</xsl:when>
+ <xsl:when test="$color='window'">#ffffff</xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="string-length($color) =7">
+ <xsl:value-of select="$color"/>
+ </xsl:when>
+ <xsl:when test="string-length($color) =4">
+ <!--short form representation of color-->
+ <xsl:variable name="valr">
+ <xsl:value-of select="concat(substring($color,2,1),substring($color,2,1))"/>
+ <!--<xsl:call-template name="shortcolorconv"><xsl:with-param name="value" select="substring($color,2,1)"/></xsl:call-template>-->
+ </xsl:variable>
+ <xsl:variable name="valg" select="concat(substring($color,3,1),substring($color,3,1))"/>
+ <xsl:variable name="valb" select="concat(substring($color,4,1),substring($color,4,1))"/>
+ <xsl:value-of select="concat('#',$valr,$valg,$valb)"/>
+ </xsl:when>
+ <xsl:otherwise>#000000</xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="shortcolorconv">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="$value='1'">11</xsl:when>
+ <xsl:when test="$value='2'">22</xsl:when>
+ <xsl:when test="$value='3'">33</xsl:when>
+ <xsl:when test="$value='4'">44</xsl:when>
+ <xsl:when test="$value='5'">55</xsl:when>
+ <xsl:when test="$value='6'">66</xsl:when>
+ <xsl:when test="$value='7'">77</xsl:when>
+ <xsl:when test="$value='8'">88</xsl:when>
+ <xsl:when test="$value='9'">99</xsl:when>
+ <xsl:when test="$value='a'">aa</xsl:when>
+ <xsl:when test="$value='b'">bb</xsl:when>
+ <xsl:when test="$value='c'">cc</xsl:when>
+ <xsl:when test="$value='d'">dd</xsl:when>
+ <xsl:when test="$value='e'">ee</xsl:when>
+ <xsl:when test="$value='f'">ff</xsl:when>
+ <!--I just guess it, maybe it is not right-->
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="MapArrowStyle">
+ <!--What is a block?normal arrow?-->
+ <xsl:param name="arrow-name"/>
+ <xsl:choose>
+ <xsl:when test="$arrow-name = 'Block' ">Arrow</xsl:when>
+ <xsl:when test="$arrow-name = 'Diamond' ">Square</xsl:when>
+ <xsl:when test="$arrow-name = 'Open' ">Line Arrow</xsl:when>
+ <xsl:when test="$arrow-name = 'Oval' ">Circle</xsl:when>
+ <xsl:when test="$arrow-name = 'Diamond' ">Square 45</xsl:when>
+ <xsl:when test="$arrow-name = 'Classic' ">Arrow concave</xsl:when>
+ <xsl:otherwise>Arrow</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="Add-with-Measure">
+ <xsl:param name="value1"/>
+ <xsl:param name="value2"/>
+ <xsl:variable name="Current-MeasureMark">
+ <xsl:choose>
+ <xsl:when test="string-length(translate($value1 ,'-.0123456789 ','' )) &gt; 0">
+ <xsl:value-of select="translate($value1 ,'-.0123456789 ','' )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate($value2 ,'-.0123456789 ','' )"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="number-value1">
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="$value1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="number-value2">
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="$value2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat( $number-value1 + $number-value2 , $Current-MeasureMark)"/>
+ </xsl:template>
+ <xsl:template name="convert-with-scale-and-measure">
+ <xsl:param name="value"/>
+ <xsl:param name="group-value" select="0"/>
+ <xsl:param name="coord-value" select="0"/>
+ <xsl:param name="scale" select="1"/>
+ <xsl:param name="MeasureMark" select="''"/>
+ <xsl:param name="Target-Measure" select="''"/>
+ <xsl:variable name="Current-MeasureMark">
+ <xsl:choose>
+ <xsl:when test="not (translate($value ,'-. 0123456789 ','' ) = '') ">
+ <xsl:value-of select="translate($value ,'-. 0123456789 ','' ) "/>
+ </xsl:when>
+ <xsl:when test="string-length($MeasureMark) &gt; 0">
+ <xsl:value-of select="$MeasureMark"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate($value ,'-. 0123456789 ','' ) "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="number-value">
+ <xsl:call-template name="get-number">
+ <xsl:with-param name="value" select="$value"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="value-string" select="( $number-value - $coord-value) div $scale + $group-value"/>
+ <xsl:choose>
+ <xsl:when test="$value-string = 0">0cm</xsl:when>
+ <xsl:when test="$Target-Measure = $Current-MeasureMark">
+ <xsl:value-of select="concat($value-string , $Current-MeasureMark)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat($value-string , $Current-MeasureMark)"/>
+ </xsl:call-template>
+ <xsl:value-of select=" 'cm' "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number">
+ <xsl:param name="value"/>
+ <xsl:choose>
+ <xsl:when test="translate($value,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ','') = '' ">0</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="number(translate($value,'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',''))"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_field.xsl b/filter/source/xslt/import/wordml/wordml2ooo_field.xsl
new file mode 100644
index 000000000..590a97283
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_field.xsl
@@ -0,0 +1,1581 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt fo v">
+ <!--Generally, The MS fields can be represented in two forms, simple field w:fldsimple or complicated field
+ w:fldChar, so when importing we have to take care of two possible forms of the same type field -->
+ <xsl:template match="w:instrText">
+ <!-- ===this template is to process the w:fldChar fields ====== -->
+ <xsl:choose>
+ <xsl:when test="substring(normalize-space(.),1,7) = 'PAGEREF' ">
+ <xsl:variable name="bookmarkname">
+ <xsl:value-of select="normalize-space(substring-before (substring-after( . , 'PAGEREF' ), '\*')) "/>
+ </xsl:variable>
+ <text:bookmark-ref text:reference-format="page" text:ref-name="{$bookmarkname}">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:bookmark-ref>
+ </xsl:when>
+ <xsl:when test="substring( normalize-space(.),1,9) = 'HYPERLINK' ">
+ <xsl:variable name="hyper-str" select="normalize-space(.)"/>
+ <xsl:variable name="hyper-dest" select="substring-before( substring($hyper-str, 12), '&quot;')"/>
+ <xsl:variable name="hyper-bookmark">
+ <xsl:if test="contains( $hyper-str, ' \l ')">
+ <xsl:value-of select="concat( '#', substring-before( substring-after( substring-after( $hyper-str, ' \l '), '&quot;'), '&quot;') )"/>
+ </xsl:if>
+ </xsl:variable>
+ <text:a xlink:type="simple" xlink:href="{concat( $hyper-dest, $hyper-bookmark)}">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:a>
+ </xsl:when>
+ <xsl:when test="substring( normalize-space(.),1,3) = 'REF' ">
+ <text:bookmark-ref text:reference-format="text" text:ref-name="{normalize-space( substring-before (substring-after(text(), 'REF') , '\') )}">
+
+ </text:bookmark-ref>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,4) = 'DATE' or substring(normalize-space(.),1,4) = 'TIME' ">
+ <text:date>
+ <xsl:choose>
+ <xsl:when test="contains(text(), '\@')">
+ <xsl:attribute name="style:data-style-name">ND<xsl:number count="w:instrText | w:fldSimple" from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select=" 'NDF1' "/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </text:date>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,9) = 'PRINTDATE' ">
+ <text:print-date>
+ <xsl:choose>
+ <xsl:when test="contains(text(), '\@')">
+ <xsl:attribute name="style:data-style-name">ND<xsl:number count="w:instrText | w:fldSimple" from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select=" 'NDF1' "/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </text:print-date>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,10) = 'CREATEDATE' ">
+ <text:creation-date>
+ <xsl:choose>
+ <xsl:when test="contains(text(), '\@')">
+ <xsl:attribute name="style:data-style-name">ND<xsl:number count="w:instrText | w:fldSimple" from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select=" 'NDF1' "/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </text:creation-date>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,8) = 'SAVEDATE' ">
+ <text:modification-date>
+ <xsl:choose>
+ <xsl:when test="contains(text(), '\@')">
+ <xsl:attribute name="style:data-style-name">ND<xsl:number count="w:instrText | w:fldSimple" from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select=" 'NDF1' "/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </text:modification-date>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,4) = 'PAGE' ">
+ <text:page-number text:select-page="current">
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(text(), '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:page-number>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,8) = 'NUMPAGES' ">
+ <text:page-count>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(text(), '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:page-count>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,8) = 'NUMWORDS' ">
+ <text:word-count>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(text(), '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:word-count>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,8) = 'NUMCHARS' ">
+ <text:character-count>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(text(), '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:character-count>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,6) = 'REVNUM' ">
+ <text:editing-cycles>
+ <xsl:value-of select="w:r"/>
+ </text:editing-cycles>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,7) = 'AUTONUM' or substring(normalize-space(.),1,10) = 'AUTONUMLGL' or substring(normalize-space(.),1,10) = 'AUTONUMOUT' ">
+ <text:sequence>
+ <xsl:attribute name="text:ref-name">RefAutoNum<xsl:number count="w:instrText[contains(text(), 'AUTONUM') or contains(text(), 'AUTONUMLGL') or contains( text(), 'AUTONUMOUT') ] | w:fldSimple[contains(@w:instr,'AUTONUM') or contains(@w:instr, 'AUTONUMLGL') or contains(@w:instr, 'AUTONUMOUT') ] " from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ <xsl:attribute name="text:name"><xsl:value-of select=" 'AutoNr' "/></xsl:attribute>
+ <xsl:attribute name="text:formula"><xsl:value-of select=" 'ooow:AutoNr + 1' "/></xsl:attribute>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(text(), '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:sequence>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,3) = 'SEQ' ">
+ <text:sequence>
+ <xsl:attribute name="text:ref-name">Ref<xsl:number count="w:instrText[contains(text(), 'SEQ') ] | w:fldSimple[contains(@w:instr,'SEQ') ] " from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ <xsl:variable name="seq_text_name">
+ <xsl:call-template name="get_seq_name">
+ <xsl:with-param name="input_seq_string" select="normalize-space(substring-after(text(), 'SEQ'))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="text:name"><xsl:value-of select="$seq_text_name"/></xsl:attribute>
+ <xsl:attribute name="text:formula"><xsl:value-of select="concat (concat('ooow:',$seq_text_name), ' + 1' )"/></xsl:attribute>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(text(), '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:sequence>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,6) = 'AUTHOR' ">
+ <text:initial-creator>
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:initial-creator>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,5) = 'TITLE' ">
+ <text:title>
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:title>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,7) = 'SUBJECT' ">
+ <text:subject>
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:subject>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,8) = 'KEYWORDS' ">
+ <text:keywords>
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:keywords>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,6) = 'FILLIN' ">
+ <text:text-input>
+ <xsl:attribute name="text:description"><xsl:value-of select="substring-before(substring-after(text(), 'FILLIN'), '\*')"/></xsl:attribute>
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:text-input>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,11) = 'DOCPROPERTY' ">
+ <xsl:variable name="instr_command">
+ <xsl:value-of select="normalize-space (substring-after(text(), 'DOCPROPERTY' ))"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($instr_command, 'Author' ) ">
+ <text:user-field-get text:name="Author">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Bytes' ) ">
+ <text:user-field-get text:name="Bytes">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'CharactersWithSpaces' ) ">
+ <text:user-field-get text:name="CharactersWithSpaces">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Category' ) ">
+ <text:user-field-get text:name="Category">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Characters' ) ">
+ <text:user-field-get text:name="Characters">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Comments' ) ">
+ <text:user-field-get text:name="Comments">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Company' ) ">
+ <text:user-field-get text:name="Company">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'CreateTime' ) ">
+ <text:user-field-get text:name="CreateTime">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'HyperlinkBase' ) ">
+ <text:user-field-get text:name="HyperlinkBase">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Keywords' ) ">
+ <text:user-field-get text:name="Keywords">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'LastPrinted' ) ">
+ <text:user-field-get text:name="LastPrinted">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'LastSavedBy' ) ">
+ <text:user-field-get text:name="LastSavedBy">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'LastSavedTime' ) ">
+ <text:user-field-get text:name="LastSavedTime">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Lines' ) ">
+ <text:user-field-get text:name="Lines">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Manager' ) ">
+ <text:user-field-get text:name="Manager">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'NameofApplication' ) ">
+ <text:user-field-get text:name="NameofApplication">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'ODMADocId' ) ">
+ <text:user-field-get text:name="ODMADocId">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Pages' ) ">
+ <text:user-field-get text:name="Pages">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Paragraphs' ) ">
+ <text:user-field-get text:name="Paragraphs">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'RevisionNumber' ) ">
+ <text:user-field-get text:name="RevisionNumber">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Security' ) ">
+ <text:user-field-get text:name="Security">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Subject' ) ">
+ <text:user-field-get text:name="Subject">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Template' ) ">
+ <text:user-field-get text:name="Template">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Title' ) ">
+ <text:user-field-get text:name="Title">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'TotalEditingTime' ) ">
+ <text:user-field-get text:name="TotalEditingTime">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Words' ) ">
+ <text:user-field-get text:name="Words">
+ </text:user-field-get>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,10) = 'MERGEFIELD' ">
+ <text:database-display text:database-name="" text:table-name="" text:table-type="table">
+ <xsl:attribute name="text:column-name"><xsl:value-of select="substring-before(substring-after(normalize-space(.), 'MERGEFIELD' ), ' ' ) "/></xsl:attribute>
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:database-display>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,8) = 'MERGEREC' ">
+ <text:database-row-number text:database-name="" text:table-name="" text:table-type="table" style:num-format="A" text:value="0">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </text:database-row-number>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(.),1,4) = 'NEXT' ">
+ <text:database-next text:database-name="" text:table-name="" text:table-type="table" text:condition="">
+ </text:database-next>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:fldChar">
+ <!-- for complicated field w:fldChar, we only process the w:instrText, please see the template processing w:instrText -->
+ </xsl:template>
+ <xsl:template name="get-fldchar-content">
+ <!-- this template is to get the content of fldchar in-between w:instrText and w:fldChar/@w:fldCharType ='end' -->
+ <xsl:param name="next_node"/>
+ <xsl:param name="sibling_number"/>
+ <xsl:if test="not ($next_node/w:fldChar/@w:fldCharType ='end' ) and $next_node ">
+ <xsl:if test="$next_node/w:br">
+ <xsl:text>&#x0A;</xsl:text>
+ </xsl:if>
+ <xsl:value-of select="$next_node//w:t"/>
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[$sibling_number + 1]"/>
+ <xsl:with-param name="sibling_number" select="$sibling_number + 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <!-- ====== this template is to process the w:fldsimple fields ======= -->
+ <xsl:template match="w:fldSimple">
+ <xsl:choose>
+ <xsl:when test="substring(normalize-space(@w:instr),1,7) = 'PAGEREF' ">
+ <xsl:variable name="bookmarkname">
+ <xsl:value-of select="normalize-space(substring-before (substring-after( @w:instr , 'PAGEREF' ), '\*')) "/>
+ </xsl:variable>
+ <text:bookmark-ref text:reference-format="page" text:ref-name="{$bookmarkname}">
+ <xsl:value-of select=" .//w:t"/>
+ </text:bookmark-ref>
+ </xsl:when>
+ <xsl:when test="substring( normalize-space(@w:instr),1,9) = 'HYPERLINK' ">
+ <xsl:variable name="hyper-str" select="normalize-space(@w:instr)"/>
+ <xsl:variable name="hyper-dest" select="substring-before( substring($hyper-str, 12), '&quot;')"/>
+ <xsl:variable name="hyper-bookmark">
+ <xsl:if test="contains( $hyper-str, ' \l ')">
+ <xsl:value-of select="concat( '#', substring-before( substring-after( substring-after( $hyper-str, ' \l '), '&quot;'), '&quot;') )"/>
+ </xsl:if>
+ </xsl:variable>
+ <text:a xlink:type="simple" xlink:href="{concat( $hyper-dest, $hyper-bookmark)}">
+ <xsl:value-of select=" .//w:t"/>
+ </text:a>
+ </xsl:when>
+ <xsl:when test="substring( normalize-space(@w:instr),1,3) = 'REF' ">
+ <text:bookmark-ref text:reference-format="text" text:ref-name="{normalize-space( substring-before (substring-after(@w:instr, 'REF') , '\') )}">
+
+ </text:bookmark-ref>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,4) = 'DATE' or substring(normalize-space(@w:instr),1,4) = 'TIME' ">
+ <text:date>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select=" 'NDF1' "/></xsl:attribute>
+ <xsl:value-of select=".//w:t"/>
+ </text:date>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,9) = 'PRINTDATE' ">
+ <text:print-date>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select=" 'NDF1' "/></xsl:attribute>
+ <xsl:value-of select=".//w:t"/>
+ </text:print-date>
+ </xsl:when>
+ <xsl:when test=" substring(normalize-space(@w:instr),1,10) = 'CREATEDATE' ">
+ <text:creation-date>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select=" 'NDF1' "/></xsl:attribute>
+ <xsl:value-of select=".//w:t"/>
+ </text:creation-date>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,8) = 'SAVEDATE' ">
+ <text:modification-date>
+ <xsl:attribute name="style:data-style-name"><xsl:value-of select=" 'NDF1' "/></xsl:attribute>
+ <xsl:value-of select=".//w:t"/>
+ </text:modification-date>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,4) = 'PAGE' ">
+ <text:page-number text:select-page="current">
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(@w:instr, '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:page-number>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,8) = 'NUMPAGES' ">
+ <text:page-count>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(@w:instr, '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:page-count>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,8) = 'NUMWORDS' ">
+ <text:word-count>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(@w:instr, '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:word-count>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,8) = 'NUMCHARS' ">
+ <text:character-count>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(@w:instr, '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:character-count>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,6) = 'REVNUM' ">
+ <text:editing-cycles>
+ <xsl:value-of select="w:r"/>
+ </text:editing-cycles>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,7) = 'AUTONUM' or substring(normalize-space(@w:instr),1,10) = 'AUTONUMLGL' or substring(normalize-space(@w:instr),1,10) = 'AUTONUMOUT' ">
+ <text:sequence>
+ <xsl:attribute name="text:ref-name">RefAutoNum<xsl:number count="w:instrText[contains(text(), 'AUTONUM') or contains(text(), 'AUTONUMLGL') or contains( text(), 'AUTONUMOUT') ] | w:fldSimple[contains(@w:instr,'AUTONUM') or contains(@w:instr, 'AUTONUMLGL') or contains(@w:instr, 'AUTONUMOUT') ] " from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ <xsl:attribute name="text:name"><xsl:value-of select=" 'AutoNr' "/></xsl:attribute>
+ <xsl:attribute name="text:formula"><xsl:value-of select=" 'ooow:AutoNr + 1' "/></xsl:attribute>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(@w:instr, '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:sequence>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,3) = 'SEQ' ">
+ <text:sequence>
+ <xsl:attribute name="text:ref-name">Ref<xsl:number count="w:instrText[contains(text(), 'SEQ') ] | w:fldSimple[contains(@w:instr,'SEQ') ] " from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ <xsl:variable name="seq_text_name">
+ <xsl:call-template name="get_seq_name">
+ <xsl:with-param name="input_seq_string" select="normalize-space(substring-after(@w:instr, 'SEQ'))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="text:name"><xsl:value-of select="$seq_text_name "/></xsl:attribute>
+ <xsl:attribute name="text:formula"><xsl:value-of select="concat (concat('ooow:',$seq_text_name), ' + 1' )"/></xsl:attribute>
+ <xsl:variable name="num-format">
+ <xsl:call-template name="get_field_num_format">
+ <xsl:with-param name="input_MS_num_format" select="normalize-space(substring-after(@w:instr, '\*' ))"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:num-format"><xsl:value-of select="$num-format"/></xsl:attribute>
+ </text:sequence>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,6) = 'AUTHOR' ">
+ <text:initial-creator>
+ <xsl:value-of select=" .//w:t"/>
+ </text:initial-creator>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,5) = 'TITLE' ">
+ <text:title>
+ <xsl:value-of select=" .//w:t"/>
+ </text:title>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,7) = 'SUBJECT' ">
+ <text:subject>
+ <xsl:value-of select=" .//w:t"/>
+ </text:subject>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,8) = 'KEYWORDS' ">
+ <text:keywords>
+ <xsl:value-of select=" .//w:t"/>
+ </text:keywords>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,6) = 'FILLIN' ">
+ <text:text-input>
+ <xsl:attribute name="text:description"><xsl:value-of select="substring-before(substring-after(@w:instr, '&quot;'), '&quot;')"/></xsl:attribute>
+ <xsl:value-of select=" .//w:t"/>
+ </text:text-input>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,11) = 'DOCPROPERTY' ">
+ <xsl:variable name="instr_command">
+ <xsl:value-of select="normalize-space (substring-after(@w:instr, 'DOCPROPERTY' ))"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="contains($instr_command, 'Author' ) ">
+ <text:user-field-get text:name="Author">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Bytes' ) ">
+ <text:user-field-get text:name="Bytes">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Category' ) ">
+ <text:user-field-get text:name="Category">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'CharactersWithSpaces' ) ">
+ <text:user-field-get text:name="CharactersWithSpaces">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Characters' ) ">
+ <text:user-field-get text:name="Characters">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Comments' ) ">
+ <text:user-field-get text:name="Comments">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Company' ) ">
+ <text:user-field-get text:name="Company">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'CreateTime' ) ">
+ <text:user-field-get text:name="CreateTime">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'HyperlinkBase' ) ">
+ <text:user-field-get text:name="HyperlinkBase">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Keywords' ) ">
+ <text:user-field-get text:name="Keywords">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'LastPrinted' ) ">
+ <text:user-field-get text:name="LastPrinted">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'LastSavedBy' ) ">
+ <text:user-field-get text:name="LastSavedBy">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'LastSavedTime' ) ">
+ <text:user-field-get text:name="LastSavedTime">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Lines' ) ">
+ <text:user-field-get text:name="Lines">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Manager' ) ">
+ <text:user-field-get text:name="Manager">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'NameofApplication' ) ">
+ <text:user-field-get text:name="NameofApplication">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'ODMADocId' ) ">
+ <text:user-field-get text:name="ODMADocId">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Pages' ) ">
+ <text:user-field-get text:name="Pages">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Paragraphs' ) ">
+ <text:user-field-get text:name="Paragraphs">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'RevisionNumber' ) ">
+ <text:user-field-get text:name="RevisionNumber">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Security' ) ">
+ <text:user-field-get text:name="Security">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Subject' ) ">
+ <text:user-field-get text:name="Subject">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Template' ) ">
+ <text:user-field-get text:name="Template">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Title' ) ">
+ <text:user-field-get text:name="Title">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'TotalEditingTime' ) ">
+ <text:user-field-get text:name="TotalEditingTime">
+ </text:user-field-get>
+ </xsl:when>
+ <xsl:when test="contains($instr_command, 'Words' ) ">
+ <text:user-field-get text:name="Words">
+ </text:user-field-get>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,10) = 'MERGEFIELD' ">
+ <text:database-display text:database-name="" text:table-name="" text:table-type="table">
+ <xsl:attribute name="text:column-name"><xsl:value-of select="substring-before(substring-after(normalize-space(.), 'MERGEFIELD' ), ' ' ) "/></xsl:attribute>
+ <xsl:value-of select=" .//w:t"/>
+ </text:database-display>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,8) = 'MERGEREC' ">
+ <text:database-row-number text:database-name="" text:table-name="" text:table-type="table" style:num-format="A" text:value="0">
+ <xsl:value-of select=" .//w:t"/>
+ </text:database-row-number>
+ </xsl:when>
+ <xsl:when test="substring(normalize-space(@w:instr),1,4) = 'NEXT' ">
+ <text:database-next text:database-name="" text:table-name="" text:table-type="table" text:condition="">
+ <xsl:value-of select=" .//w:t"/>
+ </text:database-next>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- for MS simple fields that can not map to OOo writer fields, we just import the content of these fields -->
+ <xsl:value-of select="w:r"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get_seq_name">
+ <!-- this template is to get the identifier from the input MS seq string -->
+ <xsl:param name="input_seq_string"/>
+ <xsl:choose>
+ <xsl:when test="contains( $input_seq_string, ' ' )">
+ <xsl:value-of select="substring-before($input_seq_string, ' ' )"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$input_seq_string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="default_sequence_declaration">
+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration">
+ </text:sequence-decl>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table">
+ </text:sequence-decl>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text">
+ </text:sequence-decl>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing">
+ </text:sequence-decl>
+ <text:sequence-decl text:display-outline-level="0" text:name="AutoNr">
+ </text:sequence-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="sequence_declare">
+ <text:sequence-decl text:display-outline-level="0">
+ <xsl:variable name="seq_variable_name">
+ <xsl:choose>
+ <xsl:when test=" name() = 'w:instrText' ">
+ <xsl:if test="substring(normalize-space(text()),1,3) = 'SEQ' ">
+ <xsl:call-template name="get_seq_name">
+ <xsl:with-param name="input_seq_string" select="normalize-space( substring-after(text(), 'SEQ' ))"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test=" name() = 'w:fldSimple' ">
+ <xsl:if test="substring(normalize-space(@w:instr),1,3) = 'SEQ' ">
+ <xsl:call-template name="get_seq_name">
+ <xsl:with-param name="input_seq_string" select="normalize-space( substring-after(@w:instr, 'SEQ' ))"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="text:name"><xsl:value-of select="$seq_variable_name"/></xsl:attribute>
+ </text:sequence-decl>
+ </xsl:template>
+ <!-- ===== the following templates are to generate the user fields declarations for MS word DocProperty field importing == -->
+ <xsl:template name="user_fields_declare_docproperty">
+ <xsl:variable name="document-field-root" select="/w:wordDocument/w:body//w:instrText[substring(normalize-space(text()),1,11) = 'DOCPROPERTY' ] | /w:wordDocument/w:body//w:fldSimple[substring(normalize-space(@w:instr),1,11) = 'DOCPROPERTY' ] "/>
+ <xsl:variable name="field_Author_nodeset" select="$document-field-root[contains(text(), 'Author')] | $document-field-root[contains(@w:instr, 'Author')]"/>
+ <xsl:variable name="field_Bytes_nodeset" select="$document-field-root[contains(text(), 'Bytes')] | $document-field-root[contains(@w:instr, 'Bytes')]"/>
+ <xsl:variable name="field_Category_nodeset" select="$document-field-root[contains(text(), 'Category')] | $document-field-root[contains(@w:instr, 'Category')]"/>
+ <xsl:variable name="field_Characters_nodeset" select="$document-field-root[contains(text(), 'Characters')] | $document-field-root[contains(@w:instr, 'Characters')]"/>
+ <xsl:variable name="field_CharactersWithSpaces_nodeset" select="$document-field-root[contains(text(), 'CharactersWithSpaces')] | $document-field-root[contains(@w:instr, 'CharactersWithSpaces')]"/>
+ <xsl:variable name="field_Comments_nodeset" select="$document-field-root[contains(text(), 'Comments')] | $document-field-root[contains(@w:instr, 'Comments')]"/>
+ <xsl:variable name="field_Company_nodeset" select="$document-field-root[contains(text(), 'Company')] | $document-field-root[contains(@w:instr, 'Company')]"/>
+ <xsl:variable name="field_CreateTime_nodeset" select="$document-field-root[contains(text(), 'CreateTime')] | $document-field-root[contains(@w:instr, 'CreateTime')]"/>
+ <xsl:variable name="field_HyperlinkBase_nodeset" select="$document-field-root[contains(text(), 'HyperlinkBase')] | $document-field-root[contains(@w:instr, 'HyperlinkBase')]"/>
+ <xsl:variable name="field_Keywords_nodeset" select="$document-field-root[contains(text(), 'Keywords')] | $document-field-root[contains(@w:instr, 'Keywords')]"/>
+ <xsl:variable name="field_LastPrinted_nodeset" select="$document-field-root[contains(text(), 'LastPrinted')] | $document-field-root[contains(@w:instr, 'LastPrinted')]"/>
+ <xsl:variable name="field_LastSavedBy_nodeset" select="$document-field-root[contains(text(), 'LastSavedBy')] | $document-field-root[contains(@w:instr, 'LastSavedBy')]"/>
+ <xsl:variable name="field_LastSavedTime_nodeset" select="$document-field-root[contains(text(), 'LastSavedTime')] | $document-field-root[contains(@w:instr, 'LastSavedTime')]"/>
+ <xsl:variable name="field_Lines_nodeset" select="$document-field-root[contains(text(), 'Lines')] | $document-field-root[contains(@w:instr, 'Lines')]"/>
+ <xsl:variable name="field_Manager_nodeset" select="$document-field-root[contains(text(), 'Manager')] | $document-field-root[contains(@w:instr, 'Manager')]"/>
+ <xsl:variable name="field_NameofApplication_nodeset" select="$document-field-root[contains(text(), 'NameofApplication')] | $document-field-root[contains(@w:instr, 'NameofApplication')]"/>
+ <xsl:variable name="field_ODMADocId_nodeset" select="$document-field-root[contains(text(), 'ODMADocId')] | $document-field-root[contains(@w:instr, 'ODMADocId')]"/>
+ <xsl:variable name="field_Pages_nodeset" select="$document-field-root[contains(text(), 'Pages')] | $document-field-root[contains(@w:instr, 'Pages')]"/>
+ <xsl:variable name="field_Paragraphs_nodeset" select="$document-field-root[contains(text(), 'Paragraphs')] | $document-field-root[contains(@w:instr, 'Paragraphs')]"/>
+ <xsl:variable name="field_RevisionNumber_nodeset" select="$document-field-root[contains(text(), 'RevisionNumber')] | $document-field-root[contains(@w:instr, 'RevisionNumber')]"/>
+ <xsl:variable name="field_Security_nodeset" select="$document-field-root[contains(text(), 'Security')] | $document-field-root[contains(@w:instr, 'Security')]"/>
+ <xsl:variable name="field_Subject_nodeset" select="$document-field-root[contains(text(), 'Subject')] | $document-field-root[contains(@w:instr, 'Subject')]"/>
+ <xsl:variable name="field_Template_nodeset" select="$document-field-root[contains(text(), 'Template')] | $document-field-root[contains(@w:instr, 'Template')]"/>
+ <xsl:variable name="field_Title_nodeset" select="$document-field-root[contains(text(), 'Title')] | $document-field-root[contains(@w:instr, 'Title')]"/>
+ <xsl:variable name="field_TotalEditingTime_nodeset" select="$document-field-root[contains(text(), 'TotalEditingTime')] | $document-field-root[contains(@w:instr, 'TotalEditingTime')]"/>
+ <xsl:variable name="field_Words_nodeset" select="$document-field-root[contains(text(), 'Words')] | $document-field-root[contains(@w:instr, 'Words')]"/>
+ <xsl:apply-templates select="$field_Author_nodeset[1]" mode="user_field_Author_declare"/>
+ <xsl:apply-templates select="$field_Bytes_nodeset[1]" mode="user_field_Bytes_declare"/>
+ <xsl:apply-templates select="$field_Category_nodeset[1]" mode="user_field_Category_declare"/>
+ <xsl:apply-templates select="$field_Characters_nodeset[1]" mode="user_field_Characters_declare"/>
+ <xsl:apply-templates select="$field_CharactersWithSpaces_nodeset[1]" mode="user_field_CharactersWithSpaces_declare"/>
+ <xsl:apply-templates select="$field_Comments_nodeset[1]" mode="user_field_Comments_declare"/>
+ <xsl:apply-templates select="$field_Company_nodeset[1]" mode="user_field_Company_declare"/>
+ <xsl:apply-templates select="$field_CreateTime_nodeset[1]" mode="user_field_CreateTime_declare"/>
+ <xsl:apply-templates select="$field_HyperlinkBase_nodeset[1]" mode="user_field_HyperlinkBase_declare"/>
+ <xsl:apply-templates select="$field_Keywords_nodeset[1]" mode="user_field_Keywords_declare"/>
+ <xsl:apply-templates select="$field_LastPrinted_nodeset[1]" mode="user_field_LastPrinted_declare"/>
+ <xsl:apply-templates select="$field_LastSavedBy_nodeset[1]" mode="user_field_LastSavedBy_declare"/>
+ <xsl:apply-templates select="$field_LastSavedTime_nodeset[1]" mode="user_field_LastSavedTime_declare"/>
+ <xsl:apply-templates select="$field_Lines_nodeset[1]" mode="user_field_Lines_declare"/>
+ <xsl:apply-templates select="$field_Manager_nodeset[1]" mode="user_field_Manager_declare"/>
+ <xsl:apply-templates select="$field_NameofApplication_nodeset[1]" mode="user_field_NameofApplication_declare"/>
+ <xsl:apply-templates select="$field_ODMADocId_nodeset[1]" mode="user_field_ODMADocId_declare"/>
+ <xsl:apply-templates select="$field_Pages_nodeset[1]" mode="user_field_Pages_declare"/>
+ <xsl:apply-templates select="$field_Paragraphs_nodeset[1]" mode="user_field_Paragraphs_declare"/>
+ <xsl:apply-templates select="$field_RevisionNumber_nodeset[1]" mode="user_field_RevisionNumber_declare"/>
+ <xsl:apply-templates select="$field_Security_nodeset[1]" mode="user_field_Security_declare"/>
+ <xsl:apply-templates select="$field_Subject_nodeset[1]" mode="user_field_Subject_declare"/>
+ <xsl:apply-templates select="$field_Template_nodeset[1]" mode="user_field_Template_declare"/>
+ <xsl:apply-templates select="$field_Title_nodeset[1]" mode="user_field_Title_declare"/>
+ <xsl:apply-templates select="$field_TotalEditingTime_nodeset[1]" mode="user_field_TotalEditingTime_declare"/>
+ <xsl:apply-templates select="$field_Words_nodeset[1]" mode="user_field_Words_declare"/>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Author_declare">
+ <text:user-field-decl office:value-type="string" text:name="Author">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Bytes_declare">
+ <text:user-field-decl office:value-type="string" text:name="Bytes">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Category_declare">
+ <text:user-field-decl office:value-type="string" text:name="Category">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Characters_declare">
+ <text:user-field-decl office:value-type="string" text:name="Characters">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_CharactersWithSpaces_declare">
+ <text:user-field-decl office:value-type="string" text:name="CharactersWithSpaces">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Comments_declare">
+ <text:user-field-decl office:value-type="string" text:name="Comments">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Company_declare">
+ <text:user-field-decl office:value-type="string" text:name="Company">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_CreateTime_declare">
+ <text:user-field-decl office:value-type="string" text:name="CreateTime">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_HyperlinkBase_declare">
+ <text:user-field-decl office:value-type="string" text:name="HyperlinkBase">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Keywords_declare">
+ <text:user-field-decl office:value-type="string" text:name="Keywords">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_LastPrinted_declare">
+ <text:user-field-decl office:value-type="string" text:name="LastPrinted">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_LastSavedBy_declare">
+ <text:user-field-decl office:value-type="string" text:name="LastSavedBy">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_LastSavedTime_declare">
+ <text:user-field-decl office:value-type="string" text:name="LastSavedTime">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Lines_declare">
+ <text:user-field-decl office:value-type="string" text:name="Lines">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Manager_declare">
+ <text:user-field-decl office:value-type="string" text:name="Manager">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_NameofApplication_declare">
+ <text:user-field-decl office:value-type="string" text:name="NameofApplication">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_ODMADocId_declare">
+ <text:user-field-decl office:value-type="string" text:name="ODMADocId">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Pages_declare">
+ <text:user-field-decl office:value-type="string" text:name="Pages">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Paragraphs_declare">
+ <text:user-field-decl office:value-type="string" text:name="Paragraphs">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_RevisionNumber_declare">
+ <text:user-field-decl office:value-type="string" text:name="RevisionNumber">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Security_declare">
+ <text:user-field-decl office:value-type="string" text:name="Security">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Subject_declare">
+ <text:user-field-decl office:value-type="string" text:name="Subject">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Template_declare">
+ <text:user-field-decl office:value-type="string" text:name="Template">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Title_declare">
+ <text:user-field-decl office:value-type="string" text:name="Title">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_TotalEditingTime_declare">
+ <text:user-field-decl office:value-type="string" text:name="TotalEditingTime">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="user_field_Words_declare">
+ <text:user-field-decl office:value-type="string" text:name="Words">
+ <xsl:variable name="field_content">
+ <xsl:choose>
+ <xsl:when test="name() = 'w:instrText' ">
+ <xsl:call-template name="get-fldchar-content">
+ <xsl:with-param name="next_node" select="../following-sibling::w:r[1]"/>
+ <xsl:with-param name="sibling_number" select=" 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:value-of select=".//w:t"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="office:string-value"><xsl:value-of select="$field_content"/></xsl:attribute>
+ </text:user-field-decl>
+ </xsl:template>
+ <!-- =========this following template to convert the ms number format to OOo writer format === -->
+ <xsl:template name="get_field_num_format">
+ <xsl:param name="input_MS_num_format"/>
+ <xsl:choose>
+ <xsl:when test="contains($input_MS_num_format, 'Arabic' ) ">
+ <xsl:text>1</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'roman' ) ">
+ <xsl:text>i</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'ROMAN' ) ">
+ <xsl:text>I</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'alphabetic' ) ">
+ <xsl:text>a</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'ALPHABETIC' ) ">
+ <xsl:text>A</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>1</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--xsl:template name="get_field_num_format">
+ <xsl:param name="input_MS_num_format"/>
+ <xsl:choose>
+ <xsl:when test="contains($input_MS_num_format, 'Arabic' ) ">
+ <xsl:text>1</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains ($input_MS_num_format, 'CircleNum' )">
+ <xsl:text>①, ②, ③, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'roman' ) ">
+ <xsl:text>i</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'ROMAN' ) ">
+ <xsl:text>I</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'CHINESENUM3' )">
+ <xsl:text>一, 二, 三, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'CHINESENUM2' )">
+ <xsl:text>壹, 貳, 參, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'DBNUM3' ) ">
+ <xsl:text>壱, 弐, 参, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'ZODIAC2' ) ">
+ <xsl:text>子, 丑, 寅, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'ZODIAC1' ) ">
+ <xsl:text>甲, 乙, 丙, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'Iroha' ) ">
+ <xsl:text>イ, ロ, ハ, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'Aiueo' ) ">
+ <xsl:text>ア, イ, ウ, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'alphabetic' ) ">
+ <xsl:text>a</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'ALPHABETIC' ) ">
+ <xsl:text>A</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'hebrew1' ) ">
+ <xsl:text>א, י, ק, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'hebrew2' ) ">
+ <xsl:text>א, ב, ג, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'ArabicAlpha' ) ">
+ <xsl:text>أ, ب, ت, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'ThaiLetter' ) ">
+ <xsl:text>ก, ข, ฃ, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'Chosung' ) ">
+ <xsl:text>ㄱ, ㄴ, ㄷ, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'Ganada' ) ">
+ <xsl:text>가, 나, 다, ...</xsl:text>
+ </xsl:when>
+ <xsl:when test="contains($input_MS_num_format, 'Aiueo' ) ">
+ <xsl:text>ア, イ, ウ, ...</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>1</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template -->
+ <!-- ========= the following code is to generate the date styles for date/time fields ============ -->
+ <!--the default date style content -->
+ <xsl:template name="default_date_style_content">
+ <number:year number:style="long">
+ </number:year>
+ <number:text>/</number:text>
+ <number:month>
+ </number:month>
+ <number:text>/</number:text>
+ <number:day>
+ </number:day>
+ <number:text> </number:text>
+ <number:hours>
+ </number:hours>
+ <number:text>:</number:text>
+ <number:minutes number:style="long">
+ </number:minutes>
+ <number:text>:</number:text>
+ <number:seconds number:style="long">
+ </number:seconds>
+ <number:am-pm>
+ </number:am-pm>
+ </xsl:template>
+ <!--the default date style -->
+ <xsl:template name="default_date_style">
+ <number:date-style style:name="NDF1">
+ <xsl:call-template name="default_date_style_content"/>
+ </number:date-style>
+ </xsl:template>
+ <xsl:template match="w:instrText | w:fldSimple" mode="style">
+ <!-- this template is to generate the date, time styles according to the content of DateFormatString ( the string after \@ ) in w:instrText | w:fldSimple/@w:instr -->
+ <xsl:choose>
+ <xsl:when test=" name() = 'w:instrText' ">
+ <xsl:if test="substring(normalize-space(.),1,4) = 'DATE' or substring(normalize-space(.),1,4) = 'TIME' or substring(normalize-space(.),1,9) = 'PRINTDATE' or substring(normalize-space(.),1,10) = 'CREATEDATE' or substring(normalize-space(.),1,8) = 'SAVEDATE' ">
+ <number:date-style>
+ <xsl:attribute name="style:name">ND<xsl:number count="w:instrText | w:fldSimple" from="/w:wordDocument/w:body" level="any" format="1"/></xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="contains(text(), '\@' )">
+ <!-- if has the date format string then call the template parse_field_date_format to produce the style-->
+ <xsl:variable name="MS_date_format">
+ <xsl:value-of select="normalize-space(substring-before(substring-after(normalize-space(substring-after(text(), '\@')), '&#x22;'), '&#x22;'))"/>
+ </xsl:variable>
+ <xsl:if test="string-length($MS_date_format) &gt;=1">
+ <xsl:call-template name="parse_field_date_format">
+ <xsl:with-param name="input_MS_date_format" select="$MS_date_format"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="string-length($MS_date_format) &lt;1">
+ <xsl:call-template name="default_date_style_content"/>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- if doesn't have date format string so we use the following default format -->
+ <xsl:call-template name="default_date_style_content"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </number:date-style>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="name() = 'w:fldSimple' ">
+ <xsl:if test="substring(normalize-space(@w:instr),1,4) = 'DATE' or substring(normalize-space(@w:instr),1,4) = 'TIME' or substring(normalize-space(@w:instr),1,9) = 'PRINTDATE' or substring(normalize-space(@w:instr),1,10) = 'CREATEDATE' or substring(normalize-space(@w:instr),1,8) = 'SAVEDATE' ">
+ <!-- we use the default date/time style for w:fldsimple -->
+ <number:date-style>
+ <xsl:attribute name="style:name">NDF1</xsl:attribute>
+ <xsl:call-template name="default_date_style_content"/>
+ </number:date-style>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="parse_field_date_format">
+ <!--this template is to parse and generate the content of the date-time style base on the content of input_MS_date_format -->
+ <xsl:param name="input_MS_date_format"/>
+ <xsl:if test="string-length($input_MS_date_format) &gt;= 1">
+ <xsl:variable name="date_token_start_position">
+ <!-- to find the start position of the token ' d, M, yy, YY,m etc. -->
+ <xsl:call-template name="find_token_startposition">
+ <xsl:with-param name="input_string" select="$input_MS_date_format"/>
+ <xsl:with-param name="token_start_position" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="date_token">
+ <!-- get the matched the token such as MM, YYYY, yy,MMMM etc. -->
+ <xsl:call-template name="get_date_token">
+ <xsl:with-param name="input_string2" select="substring($input_MS_date_format,$date_token_start_position)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="number($date_token_start_position) &gt; 1">
+ <!-- print the text between the tokens -->
+ <number:text>
+ <xsl:value-of select="substring($input_MS_date_format,1, number($date_token_start_position - 1) )"/>
+ </number:text>
+ </xsl:if>
+ <xsl:call-template name="map_date_format_pattern">
+ <xsl:with-param name="input_date_format_pattern" select="$date_token"/>
+ </xsl:call-template>
+ <xsl:variable name="unparsed_string">
+ <xsl:value-of select="substring($input_MS_date_format,$date_token_start_position + string-length($date_token))"/>
+ </xsl:variable>
+ <xsl:call-template name="parse_field_date_format">
+ <xsl:with-param name="input_MS_date_format" select="$unparsed_string"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="find_token_startposition">
+ <xsl:param name="input_string"/>
+ <xsl:param name="token_start_position"/>
+ <xsl:choose>
+ <xsl:when test="starts-with( $input_string,'yy') or starts-with($input_string,'YY') or starts-with($input_string,'HH') or starts-with($input_string,'hh') or starts-with($input_string,'ss') or starts-with($input_string,'SS')">
+ <xsl:value-of select="$token_start_position"/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string, 'M') or starts-with($input_string,'d') or starts-with($input_string, 'm') or starts-with($input_string,'D') or starts-with($input_string,'h') or starts-with($input_string,'H') or starts-with($input_string,'s') or starts-with($input_string,'S')">
+ <xsl:value-of select="$token_start_position"/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string, 'am/pm') or starts-with($input_string, 'AM/PM') ">
+ <xsl:value-of select="$token_start_position"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="new_string">
+ <xsl:value-of select="substring($input_string, 2)"/>
+ </xsl:variable>
+ <xsl:call-template name="find_token_startposition">
+ <xsl:with-param name="input_string" select="$new_string"/>
+ <xsl:with-param name="token_start_position" select="$token_start_position +1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get_date_token">
+ <xsl:param name="input_string2"/>
+ <xsl:choose>
+ <xsl:when test="starts-with($input_string2, 'am/pm') or starts-with($input_string2, 'AM/PM') ">
+ <xsl:value-of select=" 'am/pm' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'yyyy') or starts-with($input_string2, 'YYYY')">
+ <xsl:value-of select=" 'yyyy' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'yy') or starts-with($input_string2, 'YY')">
+ <xsl:value-of select=" 'yy' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'MMMM') ">
+ <xsl:value-of select=" 'MMMM' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'MMM')">
+ <xsl:value-of select=" 'MMM' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'MM')">
+ <xsl:value-of select=" 'MM' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'M') ">
+ <xsl:value-of select=" 'M' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'dddd') or starts-with($input_string2, 'DDDD')">
+ <xsl:value-of select=" 'dddd' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'ddd') or starts-with($input_string2, 'DDD')">
+ <xsl:value-of select=" 'ddd' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'dd') or starts-with($input_string2, 'dd')">
+ <xsl:value-of select=" 'dd' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'd') or starts-with($input_string2, 'D')">
+ <xsl:value-of select=" 'd' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'mm')">
+ <xsl:value-of select=" 'mm' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'm')">
+ <xsl:value-of select=" 'm' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'hh') or starts-with($input_string2, 'HH')">
+ <xsl:value-of select=" 'hh' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'h') or starts-with($input_string2, 'H')">
+ <xsl:value-of select=" 'h' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 'ss') or starts-with($input_string2, 'SS')">
+ <xsl:value-of select=" 'ss' "/>
+ </xsl:when>
+ <xsl:when test="starts-with($input_string2, 's') or starts-with($input_string2, 'S')">
+ <xsl:value-of select=" 's' "/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="map_date_format_pattern">
+ <!-- this template map the MS date time format to OOo date time format -->
+ <xsl:param name="input_date_format_pattern"/>
+ <xsl:choose>
+ <xsl:when test="$input_date_format_pattern = 'am/pm' ">
+ <number:am-pm>
+ </number:am-pm>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'yyyy' ">
+ <number:year number:style="long">
+ </number:year>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'yy' ">
+ <number:year>
+ </number:year>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'MMMM' ">
+ <number:month number:style="long" number:textual="true">
+ </number:month>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'MMM' ">
+ <number:month number:textual="true">
+ </number:month>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'MM' ">
+ <number:month number:style="long">
+ </number:month>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'M' ">
+ <number:month>
+ </number:month>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'dddd' ">
+ <number:day-of-week number:style="long">
+ </number:day-of-week>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'ddd' ">
+ <number:day-of-week>
+ </number:day-of-week>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'dd' ">
+ <number:day number:style="long">
+ </number:day>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'd' ">
+ <number:day>
+ </number:day>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'mm' ">
+ <number:minutes number:style="long">
+ </number:minutes>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'm' ">
+ <number:minutes>
+ </number:minutes>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'hh' ">
+ <number:hours number:style="long">
+ </number:hours>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'h' ">
+ <number:hours>
+ </number:hours>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 'ss' ">
+ <number:seconds number:style="long">
+ </number:seconds>
+ </xsl:when>
+ <xsl:when test="$input_date_format_pattern = 's' ">
+ <number:seconds>
+ </number:seconds>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_list.xsl b/filter/source/xslt/import/wordml/wordml2ooo_list.xsl
new file mode 100644
index 000000000..71f7039a5
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_list.xsl
@@ -0,0 +1,648 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt v">
+ <xsl:template match="w:listPr" mode="style">
+ <xsl:variable name="currlistid" select="w:ilfo/@w:val"/>
+ <xsl:variable name="currlist" select="."/>
+ <xsl:variable name="rootlistid" select="/w:wordDocument/w:lists/w:list[@w:ilfo=$currlistid]/w:ilst/@w:val"/>
+ <xsl:variable name="rootlist" select="/w:wordDocument/w:lists/w:listDef[@w:listDefId =$rootlistid ]"/>
+ <xsl:if test="not(ancestor::w:p/preceding-sibling::w:p/w:pPr/w:listPr[1]/w:ilfo/@w:val= $currlistid) and $rootlist/w:lvl ">
+ <xsl:element name="text:list-style">
+ <xsl:attribute name="style:name">List<xsl:value-of select="count(preceding::w:listPr)"/>
+ </xsl:attribute>
+ <xsl:apply-templates select="$rootlist/w:lvl"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:lvl">
+ <xsl:variable name="listtype">
+ <xsl:choose>
+ <xsl:when test="w:nfc/@w:val">
+ <xsl:value-of select="w:nfc/@w:val"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$listtype =23 and w:lvlPicBulletId">
+ <!-- image characters. wym -->
+ <xsl:element name="text:list-level-style-image">
+ <xsl:call-template name="list-styles-image"/>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="$listtype =23">
+ <!-- nfcBullet: Bullet character. glu -->
+ <xsl:element name="text:list-level-style-bullet">
+ <xsl:call-template name="list-styles-common">
+ <xsl:with-param name="listtype" select="$listtype"/>
+ <xsl:with-param name="currlevel" select="number(@w:ilvl)+1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- all kinds of numbering characters. glu :( -->
+ <xsl:element name="text:list-level-style-number">
+ <xsl:call-template name="list-styles-common">
+ <xsl:with-param name="listtype" select="$listtype"/>
+ <xsl:with-param name="currlevel" select="number(@w:ilvl)+1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="list-styles-common">
+ <xsl:param name="listtype"/>
+ <xsl:param name="currlevel"/>
+ <xsl:variable name="startval" select="w:start/@w:val"/>
+ <xsl:attribute name="text:level">
+ <xsl:value-of select="$currlevel"/>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$listtype = 23">
+ <!-- bullet character. glu -->
+ <xsl:attribute name="text:style-name">Bullet_20_Symbols</xsl:attribute>
+ <xsl:if test="not (contains(w:lvlText/@w:val,'%'))">
+ <xsl:attribute name="text:bullet-char">
+ <xsl:value-of select="w:lvlText/@w:val"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="contains(w:lvlText/@w:val,'%')">
+ <xsl:attribute name="text:bullet-char">
+ <xsl:value-of select=" '·' "/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="($listtype &gt;= 0) and ($listtype &lt; 60)">
+ <xsl:attribute name="text:style-name">Numbering_20_Symbols</xsl:attribute>
+ <xsl:if test="$startval">
+ <xsl:choose>
+ <xsl:when test="$startval &gt; 0">
+ <xsl:attribute name="text:start-value">
+ <xsl:value-of select="$startval"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:start-value">
+ <xsl:value-of select=" '1' "/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:attribute name="text:start-value"><xsl:value-of select="$startval"/></xsl:attribute -->
+ </xsl:if>
+ <xsl:attribute name="text:display-levels">
+ <xsl:value-of select="string-length(w:lvlText/@w:val) - string-length(translate(w:lvlText/@w:val,'%','') ) + 1"/>
+ </xsl:attribute>
+ <xsl:call-template name="nfc2numformat">
+ <xsl:with-param name="nfcvalue" select="$listtype"/>
+ <xsl:with-param name="prefix" select="substring-before(w:lvlText/@w:val, '%')"/>
+ <xsl:with-param name="suffix" select="substring-after(w:lvlText/@w:val, concat('%', $currlevel) )"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:style-name">Numbering_20_Symbols</xsl:attribute>
+ <xsl:if test="$startval">
+ <xsl:choose>
+ <xsl:when test="$startval &gt; 0">
+ <xsl:attribute name="text:start-value">
+ <xsl:value-of select="$startval"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:start-value">
+ <xsl:value-of select=" '1' "/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- xsl:attribute name="text:start-value"><xsl:value-of select="$startval"/></xsl:attribute -->
+ </xsl:if>
+ <xsl:attribute name="text:display-levels">
+ <xsl:value-of select="string-length(w:lvlText/@w:val) - string-length(translate(w:lvlText/@w:val,'%','') ) + 1"/>
+ </xsl:attribute>
+ <!-- 'none' in Word 2003. wym -->
+ <xsl:attribute name="style:num-format"/>
+ <xsl:attribute name="style:num-prefix">
+ <xsl:value-of select="substring-before(w:lvlText/@w:val, '%')"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:num-suffix">
+ <xsl:value-of select="substring-after(w:lvlText/@w:val, concat('%', $currlevel + 1) )"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:element name="style:list-level-properties">
+ <xsl:choose>
+ <xsl:when test="w:lvlJc/@w:val='right'">
+ <xsl:attribute name="fo:text-align">end</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:lvlJc/@w:val='center'">
+ <xsl:attribute name="fo:text-align">center</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:text-align">start</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:variable name="labelwidth">
+ <xsl:choose>
+ <xsl:when test="w:pPr/w:ind/@w:hanging">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pPr/w:ind/@w:hanging,'twip')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="w:pPr/w:ind/@w:first-line">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat('-',w:pPr/w:ind/@w:first-line,'twip')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="leftwidth">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pPr/w:ind/@w:left,'twip')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="w:pPr/w:ind/@w:left">
+ <xsl:attribute name="text:space-before">
+ <xsl:choose>
+ <xsl:when test=" ( number($leftwidth)-number($labelwidth) ) &gt; 0">
+ <xsl:value-of select="concat(number($leftwidth)-number($labelwidth),'cm')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" '0cm' "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="text:min-label-width">
+ <xsl:choose>
+ <xsl:when test="$labelwidth &gt; 0">
+ <xsl:value-of select="concat($labelwidth,'cm')"/>
+ </xsl:when>
+ <xsl:otherwise>0cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <!-- In binary word translation, text:min-label-distance do not generate. So, the width of number-symbol will not effect the start position of text. But first line always start same position of second line, no indent. If text:min-label-distance generate, the look of list will change because of uncountable number-symbol's width, now use 0.25cm as default width-->
+ <xsl:choose>
+ <xsl:when test="w:suff/@w:val='Space'">
+ <xsl:attribute name="text:min-label-distance">0.20cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:pPr/w:tabs/w:tab/@w:pos">
+ <xsl:variable name="tabpos">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pPr/w:tabs/w:tab/@w:pos,'twip')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="number($tabpos) &gt; (number($leftwidth)-number($labelwidth))">
+ <xsl:variable name="min-label-distance">
+ <xsl:choose>
+ <xsl:when test="number($tabpos)+number($labelwidth)-number($leftwidth)-0.25 &lt; 0">0</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="number($tabpos)+number($labelwidth)-number($leftwidth)-0.25"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="text:min-label-distance">
+ <xsl:value-of select="concat($min-label-distance,'cm')"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ <!-- Find the node that corresponds to the level being processed. We can use this to determine the indentation to be used
+ <xsl:variable name="currNode" select="/w:wordDocument/w:body//w:listPr[w:ilvl/@w:val = $currlevel][w:ilfo/@w:val = $currlist/w:ilfo/@w:val]"/>
+ <xsl:choose>
+ <xsl:when test="($currNode/wx:t/@wx:wTabBefore ) and ($currNode/wx:t/@wx:wTabAfter ) and (not($currNode/following-sibling::w:jc) or $currNode/following-sibling::w:jc/@w:val = 'left')">
+ <xsl:attribute name="text:space-before"><xsl:value-of select="(number($currNode/wx:t/@wx:wTabBefore)div 1440) * 2.54"/>cm</xsl:attribute>
+ <xsl:attribute name="text:min-label-distance"><xsl:value-of select="(number($currNode/wx:t/@wx:wTabAfter)div 1440) * 2.54"/>cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:space-before"><xsl:value-of select="((number(w:pPr/w:ind/@w:left) div 1440) * 2.54) "/>cm</xsl:attribute>
+ <xsl:attribute name="text:min-label-distance"><xsl:value-of select="(number($currlist/wx:t/@wx:wTabAfter) div 1440) * 2.54"/>cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>-->
+ <xsl:if test="w:rPr/w:rFonts">
+ <xsl:if test="w:rPr/w:rFonts/@w:ascii">
+ <xsl:attribute name="style:font-name">
+ <xsl:value-of select="w:rPr/w:rFonts/@w:ascii"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- in Oasis format the style:font-name-asian is not allowed to appear here -->
+ <!--xsl:if test="w:rPr/w:rFonts/@w:fareast">
+ <xsl:attribute name="style:font-name-asian"><xsl:value-of select="w:rPr/w:rFonts/@w:fareast"/></xsl:attribute>
+ </xsl:if -->
+ <!--
+ <xsl:if test="w:rPr/w:rFonts/@w:cs">
+ <xsl:attribute name="style:font-name-complex"><xsl:value-of select="w:rPr/w:rFonts/@w:cs"/></xsl:attribute>
+ </xsl:if>
+ -->
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="list-styles-image">
+ <xsl:variable name="currlevel" select="number(@w:ilvl)"/>
+ <xsl:attribute name="text:level">
+ <xsl:value-of select="$currlevel+1"/>
+ </xsl:attribute>
+ <xsl:variable name="picid" select="w:lvlPicBulletId/@w:val"/>
+ <office:binary-data>
+ <xsl:value-of select="/descendant::w:lists/w:listPicBullet[@w:listPicBulletId=$picid]/w:pict/w:binData"/>
+ </office:binary-data>
+ <xsl:element name="style:list-level-properties">
+ <xsl:attribute name="style:vertical-pos">middle</xsl:attribute>
+ <xsl:attribute name="style:vertical-rel">line</xsl:attribute>
+ <xsl:variable name="picsize" select="/descendant::w:lists/w:listPicBullet[@w:listPicBulletId=$picid]/w:pict/v:shape/@style"/>
+ <xsl:attribute name="fo:text-align">left</xsl:attribute>
+ <xsl:attribute name="fo:width">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="substring-before(substring-after($picsize,'width:'), ';')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ <xsl:attribute name="fo:height">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="substring-after($picsize,'height:')"/>
+ </xsl:call-template>
+ <xsl:text>cm</xsl:text>
+ </xsl:attribute>
+ <xsl:variable name="labelwidth">
+ <xsl:choose>
+ <xsl:when test="w:pPr/w:ind/@w:hanging">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pPr/w:ind/@w:hanging,'twip')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="w:pPr/w:ind/@w:first-line">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat('-',w:pPr/w:ind/@w:first-line,'twip')"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="leftwidth">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pPr/w:ind/@w:left,'twip')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="text:space-before">
+ <xsl:choose>
+ <xsl:when test="(number($leftwidth)-number($labelwidth)) &gt; 0 ">
+ <xsl:value-of select="concat(number($leftwidth)-number($labelwidth),'cm')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" '0cm' "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:attribute name="text:min-label-width">
+ <xsl:choose>
+ <xsl:when test="$labelwidth &gt; 0">
+ <xsl:value-of select="concat($labelwidth,'cm')"/>
+ </xsl:when>
+ <xsl:otherwise>0cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="w:suff/@w:val='Space'">
+ <xsl:attribute name="text:min-label-distance">0.20cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:pPr/w:tabs/w:tab/@w:pos">
+ <xsl:variable name="tabpos">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pPr/w:tabs/w:tab/@w:pos,'twip')"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="number($tabpos) &gt; (number($leftwidth)-number($labelwidth))">
+ <xsl:attribute name="text:min-label-distance">
+ <xsl:value-of select="concat(number($tabpos)+number($labelwidth)-number($leftwidth),'cm')"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+ <!-- avoid listPr in textbox. :( glu -->
+ <xsl:template match="w:p[w:pPr/w:listPr[w:ilvl and w:ilfo]]">
+ <xsl:call-template name="genlist"/>
+ </xsl:template>
+ <xsl:template name="genlist">
+ <xsl:variable name="currlistid" select="w:pPr/w:listPr/w:ilfo/@w:val"/>
+ <xsl:variable name="currlistlvl" select="w:pPr/w:listPr/w:ilvl/@w:val"/>
+ <xsl:variable name="firstoccur" select="/descendant::w:pPr[w:listPr/w:ilfo/@w:val = $currlistid][1]"/>
+ <xsl:variable name="rootlistid" select="/w:wordDocument/w:lists/w:list[@w:ilfo=$currlistid]/w:ilst/@w:val"/>
+ <xsl:variable name="rootlistname" select="/w:wordDocument/w:lists/w:listDef[@w:listDefId =$rootlistid ]/w:listStyleLink/@w:val"/>
+ <xsl:element name="text:list">
+ <xsl:attribute name="text:style-name">
+ <xsl:choose>
+ <xsl:when test="string-length($rootlistname) &gt; 0">
+ <xsl:value-of select="translate($rootlistname,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_')"/>
+ </xsl:when>
+ <xsl:otherwise>List<xsl:value-of select="count($firstoccur/preceding::w:listPr)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="preceding::w:pPr/w:listPr/w:ilfo/@w:val = w:pPr/w:listPr/w:ilfo/@w:val">
+ <xsl:attribute name="text:continue-numbering">true</xsl:attribute>
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="levels">
+ <xsl:with-param name="level" select="$currlistlvl"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="levels">
+ <xsl:with-param name="level" select="$currlistlvl"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="levels">
+ <xsl:param name="level"/>
+ <xsl:choose>
+ <xsl:when test="$level = '0'">
+ <xsl:call-template name="process-common-paragraph"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="text:list">
+ <xsl:element name="text:list-item">
+ <xsl:call-template name="levels">
+ <xsl:with-param name="level" select="$level -1"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:style" mode="list">
+ <xsl:variable name="listname" select="@w:styleId"/>
+ <xsl:if test="/w:wordDocument/w:lists/w:listDef[w:styleLink/@w:val=$listname]">
+ <text:list-style style:name="{$listname}">
+ <xsl:apply-templates select="/w:wordDocument/w:lists/w:listDef[w:styleLink/@w:val=$listname]/w:lvl"/>
+ </text:list-style>
+ </xsl:if>
+ </xsl:template>
+ <!-- for create outline style in office:styles -->
+ <xsl:template name="create-outline-style">
+ <xsl:element name="text:outline-style">
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="1"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="2"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="3"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="4"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="5"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="6"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="7"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="8"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="9"/>
+ </xsl:call-template>
+ <xsl:call-template name="outline-level-style">
+ <xsl:with-param name="level" select="10"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="outline-level-style">
+ <xsl:param name="level"/>
+ <xsl:element name="text:outline-level-style">
+ <xsl:choose>
+ <xsl:when test="(w:style[@w:type = 'paragraph' and w:pPr/w:outlineLvl/@w:val = $level -1 and w:pPr/w:listPr ]/w:pPr/w:listPr)[position()=1]">
+ <xsl:apply-templates select="(w:style[@w:type = 'paragraph' and w:pPr/w:outlineLvl/@w:val = $level -1 and w:pPr/w:listPr ]/w:pPr/w:listPr)[position()=1]" mode="outline">
+ <xsl:with-param name="outlinelevel" select="$level"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:level">
+ <xsl:value-of select="$level"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:num-format"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:listPr" mode="outline">
+ <xsl:param name="outlinelevel"/>
+ <xsl:variable name="currlistid" select="w:ilfo/@w:val"/>
+ <xsl:variable name="currlistlevel">
+ <xsl:choose>
+ <xsl:when test="w:ilvl">
+ <xsl:value-of select="w:ilvl/@w:val"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="rootlistid" select="/w:wordDocument/w:lists/w:list[@w:ilfo=$currlistid]/w:ilst/@w:val"/>
+ <xsl:variable name="rootlist" select="/w:wordDocument/w:lists/w:listDef[@w:listDefId =$rootlistid ]"/>
+ <xsl:if test="$rootlist/w:lvl[@w:ilvl=$currlistlevel]">
+ <xsl:for-each select="$rootlist/w:lvl[@w:ilvl=$currlistlevel]">
+ <xsl:call-template name="list-styles-common">
+ <xsl:with-param name="listtype">
+ <xsl:choose>
+ <xsl:when test="w:nfc/@w:val">
+ <xsl:value-of select="w:nfc/@w:val"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="currlevel" select="$outlinelevel"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:if test="not($rootlist/w:lvl[@w:ilvl=$currlistlevel])">
+ <xsl:attribute name="text:level">
+ <xsl:value-of select="'1'"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="nfc2numformat">
+ <xsl:param name="nfcvalue"/>
+ <xsl:param name="prefix"/>
+ <xsl:param name="suffix"/>
+ <xsl:choose>
+ <xsl:when test="$nfcvalue=0">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=1">
+ <xsl:attribute name="style:num-format">I</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=2">
+ <xsl:attribute name="style:num-format">i</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=3">
+ <xsl:attribute name="style:num-format">A</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=4">
+ <xsl:attribute name="style:num-format">a</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="$nfcvalue=26">
+ <xsl:attribute name="style:num-prefix">
+ <xsl:value-of select="$prefix"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:num-suffix">
+ <xsl:value-of select="concat( '.' , $suffix )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=27 or $nfcvalue=29">
+ <xsl:attribute name="style:num-prefix">
+ <xsl:value-of select="concat( $prefix, '(' )"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:num-suffix">
+ <xsl:value-of select="concat( ')' , $suffix )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=57">
+ <xsl:attribute name="style:num-prefix">
+ <xsl:value-of select="concat( $prefix, '- ' )"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:num-suffix">
+ <xsl:value-of select="concat( ' -' , $suffix )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:num-prefix">
+ <xsl:value-of select="$prefix"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:num-suffix">
+ <xsl:value-of select="$suffix"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- xsl:template name="nfc2numformat">
+ <xsl:param name="nfcvalue"/>
+ <xsl:param name="prefix"/>
+ <xsl:param name="suffix"/>
+ <xsl:choose>
+ <xsl:when test="$nfcvalue=0">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=1">
+ <xsl:attribute name="style:num-format">I</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=2">
+ <xsl:attribute name="style:num-format">i</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=3">
+ <xsl:attribute name="style:num-format">A</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=4">
+ <xsl:attribute name="style:num-format">a</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=10 or $nfcvalue=11 or $nfcvalue=17 or $nfcvalue=29 or $nfcvalue=33 or $nfcvalue=35 or $nfcvalue=36 or $nfcvalue=37 or $nfcvalue=39 or $nfcvalue=44">
+ <xsl:attribute name="style:num-format">一, 二, 三, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=12">
+ <xsl:attribute name="style:num-format">ア, イ, ウ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=13">
+ <xsl:attribute name="style:num-format">イ, ロ, ハ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=14 or $nfcvalue=19">
+ <xsl:attribute name="style:num-format">1, 2, 3, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=16">
+ <xsl:attribute name="style:num-format">壱, 弐, 参, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=18 or $nfcvalue=28">
+ <xsl:attribute name="style:num-format">①, ②, ③, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=20">
+ <xsl:attribute name="style:num-format">ア, イ, ウ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=21">
+ <xsl:attribute name="style:num-format">イ, ロ, ハ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=24">
+ <xsl:attribute name="style:num-format">가, 나, 다, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=25">
+ <xsl:attribute name="style:num-format">ㄱ, ㄴ, ㄷ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=30">
+ <xsl:attribute name="style:num-format">甲, 乙, 丙, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=31">
+ <xsl:attribute name="style:num-format">子, 丑, 寅, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=34">
+ <xsl:attribute name="style:num-format">壹, 貳, 參, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=38">
+ <xsl:attribute name="style:num-format">壹, 贰, 叁, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=41 or $nfcvalue=42 or $nfcvalue=43">
+ <xsl:attribute name="style:num-format">일, 이, 삼, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=45 or $nfcvalue=47">
+ <xsl:attribute name="style:num-format">א, ב, ג, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=46 or $nfcvalue=48">
+ <xsl:attribute name="style:num-format">أ, ب, ت, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=53">
+ <xsl:attribute name="style:num-format">ก, ข, ฃ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue!=57 and $nfcvalue &gt; 48 and $nfcvalue &lt; 60">
+ <xsl:attribute name="style:num-format">Native Numbering</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="$nfcvalue=26">
+ <xsl:attribute name="style:num-prefix"><xsl:value-of select="$prefix"/></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="concat( '.' , $suffix )"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=27 or $nfcvalue=29">
+ <xsl:attribute name="style:num-prefix"><xsl:value-of select="concat( $prefix, '(' )"/></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="concat( ')' , $suffix )"/></xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$nfcvalue=57">
+ <xsl:attribute name="style:num-prefix"><xsl:value-of select="concat( $prefix, '- ' )"/></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="concat( ' -' , $suffix )"/></xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:num-prefix"><xsl:value-of select="$prefix"/></xsl:attribute>
+ <xsl:attribute name="style:num-suffix"><xsl:value-of select="$suffix"/></xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template -->
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_page.xsl b/filter/source/xslt/import/wordml/wordml2ooo_page.xsl
new file mode 100644
index 000000000..c53940643
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_page.xsl
@@ -0,0 +1,402 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt v">
+ <xsl:template match="w:footnotePr" mode="config">
+ <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol">
+ <xsl:if test="w:pos">
+ <xsl:choose>
+ <xsl:when test="w:pos/@w:val = 'beneath-text'">
+ <xsl:attribute name="text:footnotes-position">document</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:footnotes-position">page</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="w:numStart">
+ <xsl:choose>
+ <xsl:when test="w:numStart/@w:val - 1 &gt; 0">
+ <xsl:attribute name="text:start-value">
+ <xsl:value-of select="w:numStart/@w:val - 1"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:start-value">
+ <xsl:value-of select=" '1' "/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:attribute name="text:start-value"><xsl:value-of select="w:numStart/@w:val - 1"/></xsl:attribute-->
+ </xsl:if>
+ <xsl:if test="w:numFmt">
+ <xsl:call-template name="convert-number-format">
+ <xsl:with-param name="number-format" select="w:numFmt/@w:val"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="w:numRestart">
+ <xsl:choose>
+ <xsl:when test="w:numRestart/@w:val = 'continuous'">
+ <xsl:attribute name="text:start-numbering-at">document</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:numRestart/@w:val = 'each-sect'">
+ <xsl:attribute name="text:start-numbering-at">chapter</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:start-numbering-at">page</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <!--
+ <xsl:if test="w:footnote[@w:type = 'continuation-separator']">
+ <text:footnote-continuation-notice-backward>
+ <xsl:value-of select="normalize-space(w:footnote[@w:type = 'continuation-separator'])"/>
+ </text:footnote-continuation-notice-backward>
+ </xsl:if>
+ <xsl:if test="w:footnote[@w:type = 'continuation-notice']">
+ <text:footnote-continuation-notice-forward>
+ <xsl:value-of select="normalize-space(w:footnote[@w:type = 'continuation-notice'])"/>
+ </text:footnote-continuation-notice-forward>
+ </xsl:if>
+ -->
+ </text:notes-configuration>
+ </xsl:template>
+ <xsl:template match="w:endnotePr" mode="config">
+ <text:notes-configuration text:note-class="endnote" text:citation-style-name="Endnote_20_Symbol">
+ <xsl:if test="w:numStart">
+ <xsl:choose>
+ <xsl:when test="(w:numStart/@w:val - 1) &gt; 0">
+ <xsl:attribute name="text:start-value">
+ <xsl:value-of select="w:numStart/@w:val - 1"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:start-value">
+ <xsl:value-of select=" '1' "/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:attribute name="text:start-value"><xsl:value-of select="w:numStart/@w:val - 1"/></xsl:attribute -->
+ </xsl:if>
+ <xsl:if test="w:numFmt">
+ <xsl:call-template name="convert-number-format">
+ <xsl:with-param name="number-format" select="w:numFmt/@w:val"/>
+ </xsl:call-template>
+ </xsl:if>
+ </text:notes-configuration>
+ </xsl:template>
+ <xsl:template name="convert-number-format">
+ <xsl:param name="number-format"/>
+ <xsl:choose>
+ <xsl:when test="$number-format = 'decimal' or $number-format = 'decimal-half-width'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'decimal-zero'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">0</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'decimal-enclosed-fullstop'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">.</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'decimal-enclosed-paren'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">(</xsl:attribute>
+ <xsl:attribute name="style:num-suffix">)</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'number-in-dash'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">-</xsl:attribute>
+ <xsl:attribute name="style:num-suffix">-</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'upper-letter'">
+ <xsl:attribute name="style:num-format">A</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'lower-letter'">
+ <xsl:attribute name="style:num-format">a</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'upper-roman'">
+ <xsl:attribute name="style:num-format">I</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'lower-roman'">
+ <xsl:attribute name="style:num-format">i</xsl:attribute>
+ </xsl:when>
+ <!-- ordinal, cardinal-text, ordinal-text, hex, chicago, bullet, ideograph-zodiac-traditional,
+ vietnamese-counting, russian-lower, russian-upper, hindi-vowels, hindi-consonants, hindi-numbers, hindi-counting -->
+ <xsl:otherwise>
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:bgPict">
+ <xsl:if test="w:background/@w:bgcolor">
+ <xsl:attribute name="fo:background-color">
+ <xsl:call-template name="MapConstColor">
+ <xsl:with-param name="color" select="w:background/@w:bgcolor"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:background/@w:background">
+ <style:background-image>
+ <office:binary-data>
+ <xsl:variable name="the-image" select="key('imagedata',w:background/@w:background)"/>
+ <xsl:value-of select="translate($the-image/text(),'&#9;&#10;&#13;&#32;','' ) "/>
+ </office:binary-data>
+ </style:background-image>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:sectPr" mode="page-layout">
+ <style:page-layout>
+ <xsl:attribute name="style:name">pm<xsl:number from="/w:wordDocument/w:body" level="any" count="w:sectPr" format="1"/>
+ </xsl:attribute>
+ <style:page-layout-properties>
+ <xsl:call-template name="page-layout-properties"/>
+ <xsl:apply-templates select="/w:wordDocument/w:bgPict"/>
+ </style:page-layout-properties>
+ <style:header-style>
+ <style:header-footer-properties style:dynamic-spacing="true" fo:margin-bottom="0">
+ <xsl:variable name="header-margin">
+ <xsl:choose>
+ <xsl:when test="w:pgMar/@w:header">
+ <xsl:value-of select="w:pgMar/@w:header"/>
+ </xsl:when>
+ <xsl:otherwise>720</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="header-margin-diff">
+ <xsl:value-of select="w:pgMar/@w:top - $header-margin"/>
+ </xsl:variable>
+ <xsl:variable name="min-height">
+ <xsl:choose>
+ <xsl:when test="$header-margin-diff &gt; 0">
+ <xsl:value-of select="$header-margin-diff div 567.0"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="fo:min-height">
+ <xsl:value-of select="concat($min-height, 'cm')"/>
+ </xsl:attribute>
+ </style:header-footer-properties>
+ </style:header-style>
+ </style:page-layout>
+ </xsl:template>
+ <xsl:template match="w:sectPr" mode="master-page">
+ <!-- style:page-layout style:style-->
+
+ <xsl:variable name="master-page-number">
+ <xsl:number count="w:sectPr" from="/w:wordDocument/w:body" level="any" format="1"/>
+ </xsl:variable>
+ <xsl:if test="$master-page-number = '1'">
+ <style:master-page style:next-style-name="Standard-1" style:page-layout-name="pm1" style:display-name="First Page" style:name="First_20_Page">
+ <style:header>
+ <xsl:apply-templates select="w:hdr[@w:type='first']/child::*" mode="dispatch"/>
+ </style:header>
+ <style:footer>
+ <xsl:apply-templates select="w:ftr[@w:type='first']/child::*" mode="dispatch"/>
+ </style:footer>
+ </style:master-page>
+ </xsl:if>
+ <xsl:element name="style:master-page">
+ <xsl:attribute name="style:name">Standard-<xsl:value-of select="$master-page-number"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:page-layout-name">
+ <xsl:value-of select="concat('pm', $master-page-number)"/>
+ </xsl:attribute>
+
+ <style:header>
+ <xsl:apply-templates select="w:hdr[@w:type='odd']/child::*" mode="dispatch"/>
+ </style:header>
+ <style:header-left>
+ <xsl:apply-templates select="w:hdr[@w:type='even']/child::*" mode="dispatch"/>
+ </style:header-left>
+ <style:footer>
+ <xsl:apply-templates select="w:ftr[@w:type='odd']/child::*" mode="dispatch"/>
+ </style:footer>
+ <style:footer-left>
+ <xsl:apply-templates select="w:ftr[@w:type='even']/child::*" mode="dispatch"/>
+ </style:footer-left>
+
+ <!-- Headers and footers-->
+ <!--
+ <style:header-style>
+ <style:header-footer-properties>
+ <xsl:attribute name="fo:min-height"><xsl:call-template name="ConvertMeasure"><xsl:with-param name="value" select="concat(w:pgMar/@w:header,'twip')"/></xsl:call-template>cm</xsl:attribute>
+ <xsl:attribute name="fo:margin-bottom">0.792cm</xsl:attribute>
+ <xsl:attribute name="style:dynamic-spacing">true</xsl:attribute>
+ </style:header-footer-properties>
+ </style:header-style>
+ <style:footer-style>
+ <style:header-footer-properties>
+ <xsl:attribute name="fo:min-height"><xsl:call-template name="ConvertMeasure"><xsl:with-param name="value" select="concat(w:pgMar/@w:footer,'twip')"/></xsl:call-template>cm</xsl:attribute>
+ <xsl:attribute name="fo:margin-top">0.792cm</xsl:attribute>
+ <xsl:attribute name="style:dynamic-spacing">true</xsl:attribute>
+ </style:header-footer-properties>
+ </style:footer-style>
+ -->
+
+ <!-- any examples for w:titlePg usage? -->
+ <xsl:if test="not(w:titlePg)">
+ <xsl:apply-templates select="w:hdr[@w:type='odd']"/>
+ <xsl:apply-templates select="w:hdr[@w:type='even']"/>
+ <xsl:apply-templates select="w:ftr[@w:type='odd']"/>
+ <xsl:apply-templates select="w:ftr[@w:type='even']"/>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:hdr">
+ <!--
+ <xsl:choose>
+ <xsl:when test="@w:type = 'odd'">
+ <style:header>
+ <xsl:apply-templates select="wx:pBdrGroup | w:p | w:tbl"/>
+ </style:header>
+ </xsl:when>
+ <xsl:when test="@w:type = 'even'">
+ <style:header>
+ <xsl:apply-templates select="wx:pBdrGroup | w:p | w:tbl"/>
+ </style:header>
+ </xsl:when>
+ </xsl:choose>
+ -->
+ </xsl:template>
+ <xsl:template match="w:ftr">
+ <!--
+ <xsl:choose>
+ <xsl:when test="@w:type = 'odd'">
+ <style:footer>
+ <xsl:apply-templates select="wx:pBdrGroup | w:p | w:tbl"/>
+ </style:footer>
+ </xsl:when>
+ <xsl:when test="@w:type = 'even'">
+ <style:footer-left>
+ <xsl:apply-templates select="wx:pBdrGroup | w:p | w:tbl"/>
+ </style:footer-left>
+ </xsl:when>
+ </xsl:choose>
+ -->
+ </xsl:template>
+ <xsl:template match="wx:pBdrGroup">
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:template>
+ <!-- xsl:template name="convert-number-format">
+ <xsl:param name="number-format"/>
+ <xsl:choose>
+ <xsl:when test="$number-format = 'decimal' or $number-format = 'decimal-half-width'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'decimal-zero'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">0</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'decimal-enclosed-fullstop'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">.</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'decimal-enclosed-paren'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">(</xsl:attribute>
+ <xsl:attribute name="style:num-suffix">)</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'number-in-dash'">
+ <xsl:attribute name="style:num-format">1</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">-</xsl:attribute>
+ <xsl:attribute name="style:num-suffix">-</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'upper-letter'">
+ <xsl:attribute name="style:num-format">A</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'lower-letter'">
+ <xsl:attribute name="style:num-format">a</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'upper-roman'">
+ <xsl:attribute name="style:num-format">I</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'lower-roman'">
+ <xsl:attribute name="style:num-format">i</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'decimal-full-width' or $number-format = 'decimal-full-width2'">
+ <xsl:attribute name="style:num-format">1, 2, 3, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'decimal-enclosed-circle-chinese' or $number-format = 'decimal-enclosed-circle'">
+ <xsl:attribute name="style:num-format">①, ②, ③, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ideograph-enclosed-circle'">
+ <xsl:attribute name="style:num-format">一, 二, 三, ...</xsl:attribute>
+ <xsl:attribute name="style:num-prefix">(</xsl:attribute>
+ <xsl:attribute name="style:num-suffix">)</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'chinese-counting-thousand' or $number-format = 'ideograph-digital' or $number-format = 'japanese-counting' or $number-format = 'japanese-digital-ten-thousand' or $number-format = 'taiwanese-counting-thousand' or $number-format = 'taiwanese-counting' or $number-format = 'taiwanese-digital' or $number-format = 'chinese-counting' or $number-format = 'korean-digital2' or $number-format = 'chinese-not-impl'">
+ <xsl:attribute name="style:num-format">一, 二, 三, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'chinese-legal-simplified'">
+ <xsl:attribute name="style:num-format">壹, 贰, 叁, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ideograph-legal-traditional'">
+ <xsl:attribute name="style:num-format">壹, 貳, 參, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ideograph-traditional'">
+ <xsl:attribute name="style:num-format">甲, 乙, 丙, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ideograph-zodiac'">
+ <xsl:attribute name="style:num-format">子, 丑, 寅, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'japanese-legal'">
+ <xsl:attribute name="style:num-format">壱, 弐, 参, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'aiueo-full-width'">
+ <xsl:attribute name="style:num-format">ア, イ, ウ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'aiueo'">
+ <xsl:attribute name="style:num-format">ア, イ, ウ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'iroha-full-width'">
+ <xsl:attribute name="style:num-format">イ, ロ, ハ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'iroha'">
+ <xsl:attribute name="style:num-format">イ, ロ, ハ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'korean-digital' or $number-format = 'korean-counting' or $number-format = 'korean-legal'">
+ <xsl:attribute name="style:num-format">일, 이, 삼, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'chosung'">
+ <xsl:attribute name="style:num-format">ㄱ, ㄴ, ㄷ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'ganada'">
+ <xsl:attribute name="style:num-format">가, 나, 다, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'arabic-alpha' or $number-format = 'arabic-abjad'">
+ <xsl:attribute name="style:num-format">أ, ب, ت, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'thai-letters' or $number-format = 'thai-numbers' or $number-format = 'thai-counting'">
+ <xsl:attribute name="style:num-format">ก, ข, ฃ, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'hebrew-1'">
+ <xsl:attribute name="style:num-format">א, י, ק, ...</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$number-format = 'hebrew-2'">
+ <xsl:attribute name="style:num-format">א, ב, ג, ...</xsl:attribute>
+ </xsl:when>
+ < ordinal, cardinal-text, ordinal-text, hex, chicago, bullet, ideograph-zodiac-traditional,
+ vietnamese-counting, russian-lower, russian-upper, hindi-vowels, hindi-consonants, hindi-numbers, hindi-counting >
+ <xsl:otherwise>
+ <xsl:attribute name="style:num-format">Native Numbering</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template -->
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_path.xsl b/filter/source/xslt/import/wordml/wordml2ooo_path.xsl
new file mode 100644
index 000000000..ed8dbac42
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_path.xsl
@@ -0,0 +1,1809 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt v">
+ <xsl:include href="../../common/math.xsl"/>
+ <xsl:template name="dummy">
+ <xsl:call-template name="test"/>
+ </xsl:template>
+ <xsl:template name="test-arc">
+ <xsl:call-template name="svg-arc2vml-arc">
+ <!-- M 125,75 a100,50 0 ?,? 100,50 -->
+ <xsl:with-param name="x0" select="125"/>
+ <xsl:with-param name="y0" select="75"/>
+ <xsl:with-param name="rx" select="100"/>
+ <xsl:with-param name="ry" select="50"/>
+ <xsl:with-param name="x-axis-rotation" select="0"/>
+ <xsl:with-param name="large-arc-flag" select="0"/>
+ <xsl:with-param name="sweep-flag" select="0"/>
+ <xsl:with-param name="x" select="225"/>
+ <xsl:with-param name="y" select="125"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="test">
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="'m,l,4500,3420,2520,6120,4500r2160,l6660,3240,8460,2520,8460,,3960,540r360,720l2700,1260,3240,540,,xe'"/>
+ </xsl:call-template>
+ </xsl:template>
+ <xsl:template name="vmlpath2svgpath">
+ <xsl:param name="vml-path"/>
+ <xsl:param name="svg-path" select="''"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="last-command" select="'m'"/>
+ <xsl:param name="current-x" select="'0'"/>
+ <xsl:param name="current-y" select="'0'"/>
+ <xsl:variable name="command-and-newpos">
+ <xsl:call-template name="get-path-command">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="last-command" select="$last-command"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="command" select="substring-before($command-and-newpos , ':')"/>
+ <xsl:variable name="newpos" select="substring-after($command-and-newpos , ':')"/>
+ <xsl:choose>
+ <xsl:when test="$command = 'm' ">
+ <!-- absolute moveto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' M ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 't' ">
+ <!-- relative moveto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' m ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x"/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'l' ">
+ <!-- absolute lineto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' L ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'r' ">
+ <!-- relative lineto -->
+ <!-- 'l' command is not supported currently, so we use 'L' -->
+ <xsl:message>'l' command is not supported currently, so we use 'L'. This may case problem.</xsl:message>
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' L ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="new-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:variable name="new-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <!-- 'l' command is not supported currently-->
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , $new-x ,' ' , $new-y , ' ') "/>
+ <!-- xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $num-and-pos , ':') , ' ') "/ -->
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'dummyH' ">
+ <!-- absolute horizontal lineto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $num-and-pos , ':') , ' ' , $current-y , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( $num-and-pos , ':') "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'dummyh' ">
+ <!-- relative horizontal lineto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $num-and-pos , ':') + $current-x , ' ' , $current-y , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( $num-and-pos , ':') + $current-x"/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'dummyV' ">
+ <!-- absolute vertical lineto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , $current-x , ' ' , substring-before( $num-and-pos , ':') , ' ' ) "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x"/>
+ <xsl:with-param name="current-y" select=" substring-before( $num-and-pos , ':') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'dummyv' ">
+ <!-- relative horizontal lineto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' l ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , $current-x , ' ' , substring-before( $num-and-pos , ':') + $current-y , ' ' ) "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x"/>
+ <xsl:with-param name="current-y" select=" substring-before( $num-and-pos , ':') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'c' ">
+ <!-- absolute curveto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' C ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="4"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'v' ">
+ <!-- relative curveto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' c ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="4"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'dummyS' ">
+ <!-- absolute shorthand/smooth curveto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' c ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="control-1">
+ <xsl:choose>
+ <xsl:when test="string-length(translate($last-command, 'CcSs','') )= 0 ">
+ <xsl:variable name="previous-control-2">
+ <xsl:call-template name="get-number-before">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="count" select="2"/>
+ <xsl:with-param name="skipcount" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="substring-before($previous-control-2 , ':') "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($control-and-pos, ':') "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , $control-1 , ' ' , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'dummys' ">
+ <!-- absolute shorthand/smooth curveto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' v ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="control-1">
+ <xsl:choose>
+ <xsl:when test="string-length(translate($last-command, 'CcSs' , '')) = 0 ">
+ <xsl:variable name="previous-control-2">
+ <xsl:call-template name="get-number-before">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="count" select="2"/>
+ <xsl:with-param name="skipcount" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="substring-before($previous-control-2 , ':') "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="substring-before($control-and-pos, ':') "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , $control-1 , ' ' , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'dummyQ' ">
+ <!-- absolute quadratic bézier curves -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' qb ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'dummyq' ">
+ <!-- relative quadratic bézier curves -->
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="control" select="substring-before( $control-and-pos , ':') "/>
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' qb ' , substring-before($control,' ') + $current-x , ' ' , substring-after($control , ' ') + $current-y ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="number" select="substring-before($num-and-pos, ':')"/>
+ <xsl:variable name="absolute-number" select="concat(substring-before($number, ' ') + $current-x , ' ' , substring-after($number, ' ') + $current-y)"/>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ' , $absolute-number , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( $absolute-number , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( $absolute-number , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'x' ">
+ <!--dummy or $command = 'z' "-->
+ <!-- closepath -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' Z ' ) "/>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'e' ">
+ <!-- end path -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' N ' )"/>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!--Code below is for the support of h-command like ha,hb...hi, maybe still need to revise-->
+ <xsl:when test="$command = 'ha' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hb' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hc' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hd' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'he' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hf' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hg' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hh' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hi' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'nf' or $command = 'ns' ">
+ <xsl:variable name="new-svg-path" select="$svg-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'al' ">
+ <!-- absolute moveto -->
+ <xsl:variable name="new-svg-path" select="concat($svg-path ,' W ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="6"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2svgpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="svg-path" select=" concat($new-svg-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$svg-path"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--
+ **Template vmlpath2enhancedpath**
+ The template is responsible for converting the vml-path to enhanced-path, because the svg:path
+ can't support command a now.(But heard that will be supported in OOo3.0)
+ And the 2nd reason of using an enhanced-path is that enhanced-path have a perfect mapping to
+ vmlpath.(You will find out that often, we even don't need to change the parameters).
+ -->
+ <xsl:template name="vmlpath2enhancedpath">
+ <xsl:param name="vml-path"/>
+ <xsl:param name="enhanced-path" select="''"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="last-command" select="'m'"/>
+ <xsl:param name="current-x" select="'0'"/>
+ <xsl:param name="current-y" select="'0'"/>
+ <xsl:variable name="command-and-newpos">
+ <xsl:call-template name="get-path-command">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="last-command" select="$last-command"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="command" select="substring-before($command-and-newpos , ':')"/>
+ <xsl:variable name="newpos" select="substring-after($command-and-newpos , ':')"/>
+ <xsl:choose>
+ <xsl:when test="$command = 'm' ">
+ <!--####Notice that the "m 0,0,1,1,1,1" means two lines-->
+ <!-- absolute moveto -->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' M ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'l' ">
+ <!-- absolute lineto -->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' L ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'x' ">
+ <!--dummy or $command = 'z' "-->
+ <!-- closepath -->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' Z ' ) "/>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'e' ">
+ <!-- end path -->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' N ' )"/>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'c' ">
+ <!-- absolute curveto -->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' C ' ) "/>
+ <xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="4"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 't' ">
+ <!-- relative moveto -->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' M ' ) "/>
+ <!--####maybe this is not created because t r and v haven't direct image in enhanced-path-->
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x"/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'r' ">
+ <!-- relative lineto -->
+ <!--####maybe this is not created because 't' 'r' and 'v' haven't direct image in enhanced-path-->
+ <!-- 'l' command is not supported currently, so we use 'L' -->
+ <xsl:message>'l' command is not supported currently, so we use 'L'. This may case problem.</xsl:message>
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' L ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="new-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:variable name="new-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <!-- 'l' command is not supported currently-->
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , $new-x ,' ' , $new-y , ' ') "/>
+ <!-- xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/ -->
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'v' ">
+ <!-- relative curveto -->
+ <!--####maybe this is not created because 't' 'r' and 'v' haven't direct image in enhanced-path-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' C ' ) "/>
+ <!--<xsl:variable name="control-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="4"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $control-and-pos , ':') "/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $control-and-pos , ':') , ' ' , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') + $current-x "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') + $current-y "/>
+ </xsl:call-template>-
+ -->
+ <xsl:variable name="x1">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="y1">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $x1 , ':')"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="x2">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $y1 , ':')"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="y2">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $x2 , ':')"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="x">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $y2 , ':')"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="y">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after( $x , ':')"/>
+ <xsl:with-param name="count" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="val_x1">
+ <xsl:value-of select="substring-before( $x1 , ':')+$current-x"/>
+ </xsl:variable>
+ <xsl:variable name="val_y1">
+ <xsl:value-of select="substring-before( $y1 , ':')+$current-y"/>
+ </xsl:variable>
+ <xsl:variable name="val_x2">
+ <xsl:value-of select="substring-before( $x2 , ':')+$current-x"/>
+ </xsl:variable>
+ <xsl:variable name="val_y2">
+ <xsl:value-of select="substring-before( $y2 , ':')+$current-y"/>
+ </xsl:variable>
+ <xsl:variable name="val_x">
+ <xsl:value-of select="substring-before( $x , ':')+$current-x"/>
+ </xsl:variable>
+ <xsl:variable name="val_y">
+ <xsl:value-of select="substring-before( $y , ':')+$current-y"/>
+ </xsl:variable>
+ <xsl:variable name="control-and-pos">
+ <xsl:value-of select="concat($val_x1, ' ',$val_y1, ' ',$val_x2, ' ',$val_y2, ' ' )"/>
+ </xsl:variable>
+ <xsl:variable name="num-and-pos">
+ <xsl:value-of select="concat($val_x, ' ',$val_y, ' ' )"/>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ',$control-and-pos , ' ' , $num-and-pos , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $y , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $val_x "/>
+ <xsl:with-param name="current-y" select=" $val_y "/>
+ </xsl:call-template>
+ </xsl:when>
+ <!--Code below is for the support of h-command like ha,hb...hi, maybe still need to revise-->
+ <xsl:when test="$command = 'ha' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hb' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hc' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hd' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'he' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hf' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hg' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hh' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'hi' ">
+ <xsl:variable name="new-enhanced-path" select="$enhanced-path"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'nf' ">
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' F ' )"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'ns' ">
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' S ' )"/>
+ <!--simply did nothing which might be wrong-->
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , ' ') "/>
+ <xsl:with-param name="position" select=" $newpos "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" $current-x "/>
+ <xsl:with-param name="current-y" select=" $current-y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!--The following is 6 command which deal with arcs:
+ ae -> T al -> U
+ at -> A ar -> B
+ wa -> W wr -> V
+ These pairs of commands have shown the perfect mapping from vml-path to enhanced-path-->
+ <xsl:when test="$command = 'ae' ">
+ <!-- arc on the screen with the start and end angles -->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' T ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="6"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'al' ">
+ <!-- ae command plus an implicitly moveto startpoint-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' U ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="6"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'at' ">
+ <!-- arc on the screen with the edge box ,start points and end points(Notice it's counter-clockwise)-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' A ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="8"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'ar' ">
+ <!-- at command plus an implicitly moveto startpoint-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' B ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="8"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'wa' ">
+ <!-- arc on the screen with the edge box ,start points and end points(Notice it's clockwise)-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' W ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="8"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'wr' ">
+ <!-- wa command plus an implicitly moveto startpoint-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' V ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="8"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'qx' ">
+ <!-- Draw a quarter ellipse retated to the x-axis-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' X ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'qy' ">
+ <!-- Draw a quarter ellipse retated to the y-axis-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' Y ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="2"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$command = 'qb' ">
+ <!-- quadratic Bezier-->
+ <xsl:variable name="new-enhanced-path" select="concat($enhanced-path ,' Q ' ) "/>
+ <xsl:variable name="num-and-pos">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$newpos"/>
+ <xsl:with-param name="count" select="4"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="vmlpath2enhancedpath">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="enhanced-path" select=" concat($new-enhanced-path , substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="position" select=" substring-after( $num-and-pos , ':') "/>
+ <xsl:with-param name="last-command" select="$command"/>
+ <xsl:with-param name="current-x" select=" substring-before( substring-before( $num-and-pos , ':') , ' ') "/>
+ <xsl:with-param name="current-y" select=" substring-after( substring-before( $num-and-pos , ':') , ' ') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$enhanced-path"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number-before">
+ <!-- get $count number of number before current position , output format:number1 number2 ... numberN:newposition
+ skip $skipcount of numbers
+ -->
+ <xsl:param name="vml-path"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="count" select="1"/>
+ <xsl:param name="skipcount" select="0"/>
+ <xsl:param name="number" select="''"/>
+ <xsl:choose>
+ <xsl:when test="$count = 0">
+ <xsl:value-of select=" concat($number , ':' , $position) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="num-pos">
+ <xsl:call-template name="get-number-position">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="direction" select="-1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="previous-num-and-pos">
+ <xsl:call-template name="get-previous-number">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$num-pos"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$skipcount &gt; 0">
+ <xsl:call-template name="get-number-before">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after($previous-num-and-pos , ':')"/>
+ <xsl:with-param name="count" select="$count"/>
+ <xsl:with-param name="skipcount" select="$skipcount - 1"/>
+ <xsl:with-param name="number" select="$number"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$skipcount = 0">
+ <xsl:variable name="new-number">
+ <xsl:if test="not($count = 1)">
+ <xsl:value-of select="' '"/>
+ </xsl:if>
+ <xsl:value-of select=" concat( substring-before($previous-num-and-pos , ':') , $number ) "/>
+ </xsl:variable>
+ <xsl:call-template name="get-number-before">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after($previous-num-and-pos , ':')"/>
+ <xsl:with-param name="count" select="$count - 1"/>
+ <xsl:with-param name="skipcount" select="0"/>
+ <xsl:with-param name="number" select="$new-number"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number-after">
+ <!-- get $count number of number after current position, output format:number1 number2 ... numberN:newposition
+ skip $skipcount of numbers
+ -->
+ <xsl:param name="vml-path"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="count" select="1"/>
+ <xsl:param name="skipcount" select="0"/>
+ <xsl:param name="number" select="''"/>
+ <xsl:choose>
+ <xsl:when test="$count = 0">
+ <xsl:value-of select=" concat($number , ':' , $position) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="num-pos">
+ <xsl:call-template name="get-number-position">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ <xsl:with-param name="direction" select="1"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="next-num-and-pos">
+ <xsl:call-template name="get-next-number">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$num-pos"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$skipcount &gt; 0">
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after($next-num-and-pos , ':')"/>
+ <xsl:with-param name="count" select="$count"/>
+ <xsl:with-param name="skipcount" select="$skipcount - 1"/>
+ <xsl:with-param name="number" select="$number"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:if test="$skipcount = 0">
+ <xsl:variable name="new-number">
+ <xsl:value-of select=" concat( $number , substring-before($next-num-and-pos , ':') ) "/>
+ <xsl:if test="not($count = 1)">
+ <xsl:value-of select="' '"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:call-template name="get-number-after">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="substring-after($next-num-and-pos , ':')"/>
+ <xsl:with-param name="count" select="$count - 1"/>
+ <xsl:with-param name="skipcount" select="0"/>
+ <xsl:with-param name="number" select="$new-number"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-number-position">
+ <!-- get the next number start position, direction should be 1 or -1-->
+ <xsl:param name="vml-path"/>
+ <xsl:param name="position"/>
+ <xsl:param name="direction" select="1"/>
+ <xsl:choose>
+ <xsl:when test="$direction = 1 and $position &gt; string-length($vml-path) ">0</xsl:when>
+ <xsl:when test="$direction = -1 and not($position &gt; 0)">0</xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char">
+ <xsl:if test="$direction = 1">
+ <xsl:value-of select="substring($vml-path, $position , 1)"/>
+ </xsl:if>
+ <xsl:if test="$direction = -1">
+ <xsl:value-of select="substring($vml-path, $position -1 , 1)"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="string-length(translate($curr-char , '+-.0123456789@' ,'')) = 0 ">
+ <!-- number start-->
+ <xsl:value-of select="$position"/>
+ </xsl:when>
+ <xsl:when test="not($curr-char = ' ')">
+ <xsl:value-of select="$position"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-number-position">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position + $direction"/>
+ <xsl:with-param name="direction" select="$direction"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="skip-space">
+ <xsl:param name="vml-path"/>
+ <xsl:param name="position"/>
+ <xsl:param name="skip-comma" select="'yes'"/>
+ <xsl:variable name="curr-char" select="substring($vml-path, $position , 1)"/>
+ <xsl:choose>
+ <xsl:when test="$curr-char = ',' and $skip-comma = 'yes'">
+ <xsl:call-template name="skip-space">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position+1"/>
+ <xsl:with-param name="skip-comma" select="'no'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$curr-char = ' '">
+ <xsl:call-template name="skip-space">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position+1"/>
+ <xsl:with-param name="skip-comma" select="$skip-comma"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$position"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="format-number-pos">
+ <xsl:param name="number"/>
+ <xsl:param name="position"/>
+ <xsl:choose>
+ <xsl:when test="contains($number,'@')">
+ <xsl:value-of select="concat('?f',translate($number,'@',''),':' , $position ) "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" concat(round($number) , ':' , $position) "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-next-number">
+ <!-- get the next number from current position-->
+ <xsl:param name="vml-path"/>
+ <xsl:param name="position"/>
+ <xsl:param name="number" select=" '' "/>
+ <xsl:choose>
+ <xsl:when test="$position &gt; string-length($vml-path) ">
+ <xsl:call-template name="format-number-pos">
+ <xsl:with-param name="number" select="$number"/>
+ <xsl:with-param name="position" select="$position"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char" select="substring($vml-path, $position , 1)"/>
+ <xsl:choose>
+ <xsl:when test="string-length(translate($curr-char , '.0123456789' ,'')) = 0 ">
+ <!-- is number -->
+ <xsl:call-template name="get-next-number">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position +1"/>
+ <xsl:with-param name="number" select="concat( $number, $curr-char) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '@+-' ,'') ) = 0 and string-length($number) = 0">
+ <!-- is number -->
+ <xsl:call-template name="get-next-number">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position +1"/>
+ <xsl:with-param name="number" select="concat( $number, $curr-char) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test=" $number = '' and $curr-char = ',' ">
+ <xsl:variable name="new-pos">
+ <xsl:call-template name="skip-space">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat( '0:' , $new-pos )"/>
+ </xsl:when>
+ <xsl:when test=" $number = '' and not($curr-char = ',') ">
+ <xsl:variable name="new-pos">
+ <xsl:call-template name="skip-space">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:value-of select="concat( '0:' , $new-pos)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="new-pos">
+ <xsl:call-template name="skip-space">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="format-number-pos">
+ <xsl:with-param name="number" select="$number"/>
+ <xsl:with-param name="position" select="$new-pos"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-previous-number">
+ <!-- get the previous number from current position-->
+ <xsl:param name="vml-path"/>
+ <xsl:param name="position"/>
+ <xsl:param name="number" select="''"/>
+ <xsl:choose>
+ <xsl:when test="not($position &gt; 0)">
+ <xsl:call-template name="format-number-pos">
+ <xsl:with-param name="number" select="$number"/>
+ <xsl:with-param name="position" select="'0'"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char" select="substring($vml-path, $position -1 , 1)"/>
+ <xsl:choose>
+ <xsl:when test="string-length(translate($curr-char , '.0123456789' ,'')) = 0 ">
+ <!-- is number -->
+ <xsl:call-template name="get-previous-number">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position -1"/>
+ <xsl:with-param name="number" select="concat($curr-char , $number) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '@+-' ,'') ) = 0 and string-length($number) = 0">
+ <!-- skip it -->
+ <xsl:call-template name="get-previous-number">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position -1"/>
+ <xsl:with-param name="number" select="$number "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '+-' ,'') ) = 0 and string-length($number) &gt; 0">
+ <!-- finish it with +/- -->
+ <xsl:call-template name="format-number-pos">
+ <xsl:with-param name="number" select="$number"/>
+ <xsl:with-param name="position" select="$position"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="format-number-pos">
+ <xsl:with-param name="number" select="$number"/>
+ <xsl:with-param name="position" select="$position"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="get-path-command_dummy">
+ <xsl:param name="vml-path"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="last-command"/>
+ <xsl:choose>
+ <xsl:when test="$position &gt; string-length($vml-path) "/>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char" select="substring($vml-path, $position , 1)"/>
+ <xsl:choose>
+ <xsl:when test="string-length(translate($curr-char , 'mlcxetrvnfsawqyb' ,'')) = 0 ">
+ <!-- "MmZzLlHhVvCcSsQqTtAa" are all possible command chars -->
+ <xsl:value-of select="concat( $curr-char , ':' , $position +1)"/>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '+-.0123456789@' ,'')) = 0 ">
+ <!-- number start, use last command -->
+ <xsl:if test="string-length($last-command) = 0">
+ <xsl:message>ooo2wordml_path.xsl: Find undefined command</xsl:message>
+ </xsl:if>
+ <xsl:value-of select="concat( $last-command , ':' , $position )"/>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , ',&#9;&#10;&#13;&#32;' ,'')) = 0 ">
+ <!-- space or ',' should be skip -->
+ <xsl:call-template name="get-path-command">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position +1"/>
+ <xsl:with-param name="last-command" select="$last-command"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>ooo2wordml_path.xsl: Find undefined command:<xsl:value-of select="$curr-char"/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!--
+ **get-path- command**
+ This function will collect the next command from a string. If the input string should has a start of number character,
+ we here implicitly think the command is the last-command
+ All of the command of vml is listed as following:
+ __Basic commands:__
+ m l c x e t r v nf ns ae al at ar wa wr qx qy qb
+ __Edit behavior extensions commands__
+ ha hb hc hd he hf hg hh hi
+
+ So we know the longest command should be four character.The function is implemented on this basis:
+ -->
+ <xsl:template name="get-path-command">
+ <xsl:param name="vml-path"/>
+ <xsl:param name="position" select="1"/>
+ <xsl:param name="last-command"/>
+ <xsl:choose>
+ <xsl:when test="$position &gt; string-length($vml-path) "/>
+ <xsl:otherwise>
+ <xsl:variable name="curr-char" select="substring($vml-path, $position , 1)"/>
+ <xsl:variable name="curr-2char" select="substring($vml-path, $position - 1 , 2)"/>
+ <xsl:choose>
+ <xsl:when test="$curr-char = 'a' ">
+ <!--process the commands ae al at ar-->
+ <xsl:variable name="second-char" select="substring($vml-path, $position+1 , 1)"/>
+ <xsl:variable name="isvalid">
+ <xsl:choose>
+ <xsl:when test="$second-char='e' ">1</xsl:when>
+ <xsl:when test="$second-char='l' ">1</xsl:when>
+ <xsl:when test="$second-char='t' ">1</xsl:when>
+ <xsl:when test="$second-char='r' ">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$isvalid = '1' ">
+ <xsl:value-of select="concat( $curr-char,$second-char , ':' , $position +2)"/>
+ </xsl:if>
+ <xsl:if test="$isvalid = '0' ">
+ <xsl:message>ooo2wordml_path.xsl: Error command occurred </xsl:message>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="$curr-char = 'n' ">
+ <!--process the commands nf ns -->
+ <xsl:variable name="second-char" select="substring($vml-path, $position+1 , 1)"/>
+ <xsl:variable name="isvalid">
+ <xsl:choose>
+ <xsl:when test="$second-char='f' ">1</xsl:when>
+ <xsl:when test="$second-char='s' ">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$isvalid = '1' ">
+ <xsl:value-of select="concat( $curr-char,$second-char , ':' , $position +2)"/>
+ </xsl:if>
+ <xsl:if test="$isvalid = '0' ">
+ <xsl:message>ooo2wordml_path.xsl: Error command occurred </xsl:message>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="$curr-char = 'w' ">
+ <!--process the commands wa wr-->
+ <xsl:variable name="second-char" select="substring($vml-path, $position+1 , 1)"/>
+ <xsl:variable name="isvalid">
+ <xsl:choose>
+ <xsl:when test="$second-char='a' ">1</xsl:when>
+ <xsl:when test="$second-char='r' ">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$isvalid = '1' ">
+ <xsl:value-of select="concat( $curr-char,$second-char , ':' , $position +2)"/>
+ </xsl:if>
+ <xsl:if test="$isvalid = '0' ">
+ <xsl:message>ooo2wordml_path.xsl: Error command occurred </xsl:message>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="$curr-char = 'q' ">
+ <!--process the commands qx qy qb-->
+ <xsl:variable name="second-char" select="substring($vml-path, $position+1 , 1)"/>
+ <xsl:variable name="isvalid">
+ <xsl:choose>
+ <xsl:when test="$second-char='x' ">1</xsl:when>
+ <xsl:when test="$second-char='y' ">1</xsl:when>
+ <xsl:when test="$second-char='b' ">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$isvalid = '1' ">
+ <xsl:value-of select="concat( $curr-char,$second-char , ':' , $position +2)"/>
+ </xsl:if>
+ <xsl:if test="$isvalid = '0' ">
+ <xsl:message>ooo2wordml_path.xsl: Error command occurred </xsl:message>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="$curr-char = 'h' ">
+ <!--process the edit behavior extensions commands-->
+ <xsl:variable name="second-char" select="substring($vml-path, $position+1 , 1)"/>
+ <xsl:variable name="isvalid">
+ <xsl:choose>
+ <xsl:when test="string-length(translate($second-char , 'abcdefghi' ,'')) = 0">1</xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="$isvalid = '1' ">
+ <xsl:value-of select="concat( $curr-char,$second-char , ':' , $position +2)"/>
+ </xsl:if>
+ <xsl:if test="$isvalid = '0' ">
+ <xsl:message>ooo2wordml_path.xsl: Error command occurred </xsl:message>
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , 'mlcxetrv' ,'')) = 0 ">
+ <!--process the single character commands m l c x e t r v -->
+ <xsl:value-of select="concat( $curr-char , ':' , $position +1)"/>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , '+-.0123456789@' ,'')) = 0 ">
+ <!-- number start, use last command -->
+ <xsl:if test="string-length($last-command) = 0">
+ <xsl:message>ooo2wordml_path.xsl: Find undefined command</xsl:message>
+ </xsl:if>
+ <xsl:value-of select="concat( $last-command , ':' , $position )"/>
+ </xsl:when>
+ <xsl:when test="$curr-2char=',,' ">
+ <!-- here are two ',' -->
+ <xsl:if test="string-length($last-command) = 0">
+ <xsl:message>ooo2wordml_path.xsl: Find undefined command</xsl:message>
+ </xsl:if>
+ <xsl:value-of select="concat( $last-command , ':' , $position )"/>
+ </xsl:when>
+ <xsl:when test="string-length(translate($curr-char , ',&#9;&#10;&#13;&#32;' ,'')) = 0 ">
+ <!-- space or ',' should be skip -->
+ <xsl:call-template name="get-path-command">
+ <xsl:with-param name="vml-path" select="$vml-path"/>
+ <xsl:with-param name="position" select="$position +1"/>
+ <xsl:with-param name="last-command" select="$last-command"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>ooo2wordml_path.xsl: Find undefined command:<xsl:value-of select="$curr-char"/>
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="svg-arc2vml-arc">
+ <xsl:param name="x0"/>
+ <xsl:param name="y0"/>
+ <xsl:param name="rx"/>
+ <xsl:param name="ry"/>
+ <xsl:param name="x-axis-rotation" select="0"/>
+ <xsl:param name="large-arc-flag" select="0"/>
+ <xsl:param name="sweep-flag" select="0"/>
+ <xsl:param name="x"/>
+ <xsl:param name="y"/>
+ <!-- Compute 1/2 distance between current and final point -->
+ <xsl:variable name="dx2" select="($x0 - $x) div 2"/>
+ <xsl:variable name="dy2" select="($y0 - $y) div 2"/>
+ <!-- Convert from degrees to radians -->
+ <xsl:variable name="rotation-radian" select="$x-axis-rotation * $pi div 180"/>
+ <!-- Compute (x1, y1). What are x1,y1?-->
+ <xsl:variable name="cos-rotation">
+ <xsl:call-template name="cos">
+ <xsl:with-param name="x" select="$rotation-radian"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="sin-rotation">
+ <xsl:call-template name="sin">
+ <xsl:with-param name="x" select="$rotation-radian"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="x1" select="$cos-rotation * $dx2 + $sin-rotation * $dy2"/>
+ <xsl:variable name="y1" select="-1 * $sin-rotation * $dx2 + $cos-rotation * $dy2"/>
+ <!-- Make sure radii are large enough -->
+ <xsl:variable name="rx-abs">
+ <xsl:call-template name="abs">
+ <xsl:with-param name="x" select="$rx"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="ry-abs">
+ <xsl:call-template name="abs">
+ <xsl:with-param name="x" select="$ry"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="rx-sq" select="$rx-abs * $rx-abs"/>
+ <xsl:variable name="ry-sq" select="$ry-abs * $ry-abs"/>
+ <xsl:variable name="x1-sq" select="$x1 * $x1"/>
+ <xsl:variable name="y1-sq" select="$y1 * $y1"/>
+ <xsl:variable name="radius-check" select=" $x1-sq div $rx-sq + $y1-sq div $ry-sq "/>
+ <xsl:variable name="radius-check-sqrt">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="$radius-check"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="new-rx">
+ <xsl:choose>
+ <xsl:when test="$radius-check &gt; 1">
+ <xsl:value-of select="$rx-abs * $radius-check-sqrt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$rx-abs"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="new-ry">
+ <xsl:choose>
+ <xsl:when test="$radius-check &gt; 1">
+ <xsl:value-of select="$ry-abs * $radius-check-sqrt"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$ry-abs"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="new-ry-sq">
+ <xsl:choose>
+ <xsl:when test="$radius-check &gt; 1">
+ <xsl:value-of select="$new-ry * $new-ry"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$ry-sq"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="new-rx-sq">
+ <xsl:choose>
+ <xsl:when test="$radius-check &gt; 1">
+ <xsl:value-of select="$new-rx * $new-rx"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$rx-sq"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- Step 2: Compute (cx1, cy1) -->
+ <xsl:variable name="sign">
+ <xsl:choose>
+ <xsl:when test="$large-arc-flag = $sweep-flag">-1</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="unchecked-sq" select=" (($new-rx-sq * $new-ry-sq) - ($new-rx-sq * $y1-sq) - ($new-ry-sq * $x1-sq)) div (($new-rx-sq * $y1-sq) + ($new-ry-sq * $x1-sq)) "/>
+ <xsl:variable name="sq">
+ <xsl:choose>
+ <xsl:when test=" $unchecked-sq &lt; 0">0</xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$unchecked-sq"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="sq-sqrt">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="$sq"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="coef" select="$sign * $sq-sqrt "/>
+ <xsl:variable name="cx1" select="$coef * $new-rx * $y1 div $new-ry"/>
+ <xsl:variable name="cy1" select=" -1 * $coef * $new-ry * $x1 div $new-rx"/>
+ <!-- Step 3: Compute (cx, cy) from (cx1, cy1) -->
+ <xsl:variable name="sx2" select="($x0 +$x) div 2 "/>
+ <xsl:variable name="sy2" select="($y0 +$y) div 2 "/>
+ <xsl:variable name="tmp1" select="$cos-rotation * $cx1 "/>
+ <xsl:variable name="tmp2" select="$cos-rotation * $cx1 "/>
+ <xsl:variable name="cx" select=" $sx2 + ( $cos-rotation * $cx1 - $sin-rotation * $cy1 ) "/>
+ <xsl:variable name="cy" select=" $sy2 + ( $sin-rotation * $cx1 + $cos-rotation * $cy1 ) "/>
+ <!-- Step 4: Compute angle start and angle extent -->
+ <xsl:variable name="ux" select="( $x1 - $cx1) div $new-rx"/>
+ <xsl:variable name="uy" select="( $y1 - $cy1) div $new-ry"/>
+ <xsl:variable name="vx" select="( - 1 * $x1 - $cx1) div $new-rx"/>
+ <xsl:variable name="vy" select="(- 1 * $y1 - $cy1) div $new-ry"/>
+ <xsl:variable name="n">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select=" ($ux * $ux) + ($uy * $uy) "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- 1 * ux + 0 * uy -->
+ <xsl:variable name="p" select="$ux"/>
+ <xsl:variable name="uy-sign">
+ <xsl:choose>
+ <xsl:when test=" $uy &lt; 0 ">-1</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="acos-pn">
+ <xsl:call-template name="acos">
+ <xsl:with-param name="x" select="$p div $n"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="theta" select="( $uy-sign * $acos-pn * 180 div $pi ) mod 360 "/>
+ <xsl:variable name="n-delta">
+ <xsl:call-template name="sqrt">
+ <xsl:with-param name="x" select="($ux * $ux + $uy * $uy) * ($vx * $vx + $vy * $vy)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="p-delta" select="$ux * $vx + $uy * $vy"/>
+ <xsl:variable name="vy-sign">
+ <xsl:choose>
+ <xsl:when test="($ux * $vy - $uy * $vx) &lt; 0 ">-1</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="acos-pn-delta">
+ <xsl:call-template name="acos">
+ <xsl:with-param name="x" select="$p-delta div $n-delta"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="unchecked-delta" select="$vy-sign * $acos-pn-delta * 180 div $pi "/>
+ <xsl:variable name="delta">
+ <xsl:choose>
+ <xsl:when test=" $sweep-flag = 0 and $unchecked-delta &gt; 0 ">
+ <xsl:value-of select=" ($unchecked-delta - 360) mod 360 "/>
+ </xsl:when>
+ <xsl:when test=" $sweep-flag = 1 and $unchecked-delta &lt; 0 ">
+ <xsl:value-of select=" ($unchecked-delta + 360) mod 360 "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" $unchecked-delta mod 360 "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat ($cx, ' ' , $cy, ' ' , $rx, ' ' , $ry, ' ' , $theta, ' ' , $delta, ' ' , $x-axis-rotation) "/>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_props.xsl b/filter/source/xslt/import/wordml/wordml2ooo_props.xsl
new file mode 100644
index 000000000..85a4555fe
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_props.xsl
@@ -0,0 +1,268 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt v" xmlns:an="urn:flr:annotate">
+
+<an:page-layout-properties
+ context-node-input="w:sectPr"
+ context-node-output="style:page-layout-properties">
+<an:so-supported select="w:pgMar/@w:gutter"/>
+<an:so-supported select="w:pgSz/@w:code"/>
+</an:page-layout-properties>
+
+<xsl:template name="page-layout-properties">
+
+<!-- NOTE: "div 567.0" converts from twips to cm -->
+<xsl:attribute name="fo:margin-top">
+ <xsl:variable name="header-margin">
+ <xsl:choose>
+ <xsl:when test="w:pgMar/@w:header">
+ <xsl:value-of select="w:pgMar/@w:header"/>
+ </xsl:when>
+ <xsl:otherwise>720</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="margin-top">
+ <xsl:choose>
+ <xsl:when test="w:hdr">
+ <xsl:choose>
+ <xsl:when test="w:pgMar/@w:top &gt;= $header-margin">
+ <xsl:value-of select="$header-margin"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="w:pgMar/@w:top"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="w:pgMar/@w:top"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat($margin-top div 567.0, 'cm')"/>
+</xsl:attribute>
+<xsl:attribute name="fo:margin-bottom">
+ <xsl:variable name="footer-margin">
+ <xsl:choose>
+ <xsl:when test="w:pgMar/@w:footer">
+ <xsl:value-of select="w:pgMar/@w:footer"/>
+ </xsl:when>
+ <xsl:otherwise>720</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="margin-bottom">
+ <xsl:choose>
+ <xsl:when test="w:ftr">
+ <xsl:value-of select="$footer-margin"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="w:pgMar/@w:bottom"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:value-of select="concat($margin-bottom div 567.0, 'cm')"/>
+</xsl:attribute>
+<xsl:attribute name="fo:margin-left">
+ <xsl:value-of select="concat(w:pgMar/@w:left div 567.0, 'cm')"/>
+</xsl:attribute>
+<xsl:attribute name="fo:margin-right">
+ <xsl:value-of select="concat(w:pgMar/@w:right div 567.0, 'cm')"/>
+</xsl:attribute>
+
+<xsl:attribute name="fo:page-width">
+ <xsl:value-of select="concat(w:pgSz/@w:w div 567.0, 'cm')"/>
+</xsl:attribute>
+<xsl:attribute name="fo:page-height">
+ <xsl:value-of select="concat(w:pgSz/@w:h div 567.0, 'cm')"/>
+</xsl:attribute>
+<xsl:attribute name="style:footnote-max-height">
+ <xsl:value-of select="'0cm'"/>
+</xsl:attribute>
+<xsl:attribute name="style:print-orientation">
+ <xsl:choose>
+ <xsl:when test="w:pgSz/@w:orient">
+ <xsl:value-of select="w:pgSz/@w:orient"/>
+ </xsl:when>
+ <xsl:otherwise>portrait</xsl:otherwise>
+ </xsl:choose>
+</xsl:attribute>
+<xsl:apply-templates select="//w:bgPict"/>
+<xsl:call-template name="column-properties"/>
+</xsl:template>
+
+
+<an:column-properties
+ context-node-input="w:sectPr"
+ context-node-output="style:page-layout-properties">
+<an:so-supported select="w:cols/@w:sep"/>
+</an:column-properties>
+<xsl:template name="column-properties">
+<style:columns>
+<xsl:attribute name="fo:column-count">
+ <xsl:choose>
+ <xsl:when test="w:cols/@w:num">
+ <xsl:value-of select="w:cols/@w:num"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+</xsl:attribute>
+
+<xsl:if test="not(w:cols/w:col)">
+<!-- bug in the OASIS spec resp. bug in xmloff -->
+<xsl:attribute name="fo:column-gap">
+ <xsl:value-of select="concat(w:cols/@w:space div 567.0, 'cm')"/>
+</xsl:attribute>
+</xsl:if>
+
+<xsl:for-each select="w:cols/w:col">
+ <style:column>
+ <xsl:attribute name="style:rel-width">
+ <xsl:value-of select="concat(@w:w, '*')"/>
+ </xsl:attribute>
+ <xsl:attribute name="fo:start-indent">
+ <xsl:value-of select="'0cm'"/>
+ </xsl:attribute>
+ <xsl:attribute name="fo:end-indent">
+ <xsl:choose>
+ <xsl:when test="@w:space">
+ <xsl:value-of select="concat(@w:space div 567.0, 'cm')"/>
+ </xsl:when>
+ <xsl:otherwise>0cm</xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </style:column>
+</xsl:for-each>
+</style:columns>
+</xsl:template>
+
+<an:text-properties
+ context-node-input="w:rPr"
+ context-node-output="style:text-properties">
+</an:text-properties >
+<xsl:template name="text-properties">
+<xsl:variable name="b-value">
+ <xsl:choose>
+ <xsl:when test="w:b/@val">
+ <xsl:value-of select="w:b/@val"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="local-name(w:b)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:variable>
+<!-- could be simplified: is "b" actually a valid value of w:b/@val ? -->
+<xsl:variable name="font-weight">
+ <xsl:choose>
+ <xsl:when test="$b-value = 'on'">bold</xsl:when>
+ <xsl:when test="$b-value = 'off'">normal</xsl:when>
+ <xsl:when test="$b-value = 'b'">bold</xsl:when>
+ <xsl:otherwise></xsl:otherwise>
+ </xsl:choose>
+</xsl:variable>
+<xsl:attribute name="fo:font-weight">
+ <xsl:value-of select="$font-weight"/>
+</xsl:attribute>
+<xsl:attribute name="style:font-weight-asian">
+ <xsl:value-of select="$font-weight"/>
+</xsl:attribute>
+<xsl:attribute name="style:font-weight-complex">
+ <xsl:variable name="b-cs-value">
+ <xsl:choose>
+ <xsl:when test="w:b-cs/@val">
+ <xsl:value-of select="w:b-cs/@val"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="local-name(w:b-cs)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- could be simplified: is "b-cs" actually a valid value of w:b-cs/@val -->
+ <xsl:choose>
+ <xsl:when test="$b-cs-value = 'on'">bold</xsl:when>
+ <xsl:when test="$b-cs-value = 'off'">normal</xsl:when>
+ <xsl:when test="$b-cs-value = 'b-cs'">bold</xsl:when>
+ <xsl:otherwise></xsl:otherwise>
+ </xsl:choose>
+</xsl:attribute>
+<xsl:variable name="i-value">
+ <xsl:choose>
+ <xsl:when test="w:i/@val">
+ <xsl:value-of select="w:i/@val"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="local-name(w:i)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+</xsl:variable>
+<!-- could be simplified: is "i" actually a valid value of w:i/@val ? -->
+<xsl:variable name="font-style">
+ <xsl:choose>
+ <xsl:when test="$i-value = 'on'">italic</xsl:when>
+ <xsl:when test="$i-value = 'off'">normal</xsl:when>
+ <xsl:when test="$i-value = 'i'">italic</xsl:when>
+ <xsl:otherwise></xsl:otherwise>
+ </xsl:choose>
+</xsl:variable>
+<xsl:attribute name="fo:font-style">
+ <xsl:value-of select="$font-style"/>
+</xsl:attribute>
+<xsl:attribute name="style:font-style-asian">
+ <xsl:value-of select="$font-style"/>
+</xsl:attribute>
+<xsl:attribute name="style:font-style-complex">
+ <xsl:variable name="i-cs-value">
+ <xsl:choose>
+ <xsl:when test="w:i-cs/@val">
+ <xsl:value-of select="w:i-cs/@val"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="local-name(w:i-cs)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- could be simplified: is "i-cs" actually a valid value of w:i-cs/@val -->
+ <xsl:choose>
+ <xsl:when test="$i-cs-value = 'on'">italic</xsl:when>
+ <xsl:when test="$i-cs-value = 'off'">normal</xsl:when>
+ <xsl:when test="$i-cs-value = 'i-cs'">italic</xsl:when>
+ <xsl:otherwise></xsl:otherwise>
+ </xsl:choose>
+</xsl:attribute>
+<xsl:attribute name="fo:text-transform">
+ <xsl:variable name="caps-value">
+ <xsl:choose>
+ <xsl:when test="w:caps/@val">
+ <xsl:value-of select="w:caps/@val"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="local-name(w:caps)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- could be simplified: is "caps" actually a valid value of w:caps/@val -->
+ <xsl:choose>
+ <xsl:when test="$caps-value = 'on'">uppercase</xsl:when>
+ <xsl:when test="$caps-value = 'off'">normal</xsl:when>
+ <xsl:when test="$caps-value = 'caps'">uppercase</xsl:when>
+ <xsl:otherwise></xsl:otherwise>
+ </xsl:choose>
+</xsl:attribute>
+<xsl:attribute name="fo:font-variant">
+ <xsl:variable name="small-caps-value">
+ <xsl:choose>
+ <xsl:when test="w:smallCaps/@val">
+ <xsl:value-of select="w:smallCaps/@val"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="local-name(w:smallCaps)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- could be simplified: is "smallCaps" actually a valid value of w:smallCaps/@val -->
+ <xsl:choose>
+ <xsl:when test="$small-caps-value = 'on'">small-caps</xsl:when>
+ <xsl:when test="$small-caps-value = 'off'">normal</xsl:when>
+ <xsl:when test="$small-caps-value = 'smallCaps'">small-caps</xsl:when>
+ <xsl:otherwise></xsl:otherwise>
+ </xsl:choose>
+</xsl:attribute>
+</xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_settings.xsl b/filter/source/xslt/import/wordml/wordml2ooo_settings.xsl
new file mode 100644
index 000000000..9f8ac81b0
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_settings.xsl
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt v">
+ <xsl:template match="w:docPr">
+ <office:settings>
+ <config:config-item-set config:name="view-settings">
+ <config:config-item config:name="InBrowseMode" config:type="boolean">
+ <xsl:choose>
+ <xsl:when test="w:view/@w:val = 'outline'">true</xsl:when>
+ <xsl:when test="w:view/@w:val = 'print'">false</xsl:when>
+ <!-- others: web, reading, normal, master-pages, none. glu -->
+ <xsl:otherwise>true</xsl:otherwise>
+ </xsl:choose>
+ </config:config-item>
+ <config:config-item-map-indexed config:name="Views">
+ <config:config-item-map-entry>
+ <xsl:if test="w:zoom">
+ <!-- VisibleRight and VisibleBottom are arbitrary positive numbers. ;) glu -->
+ <config:config-item config:name="VisibleRight" config:type="int">1</config:config-item>
+ <config:config-item config:name="VisibleBottom" config:type="int">1</config:config-item>
+ <xsl:choose>
+ <xsl:when test="w:zoom/@w:val = 'best-fit'">
+ <config:config-item config:name="ZoomType" config:type="short">3</config:config-item>
+ </xsl:when>
+ <xsl:when test="w:zoom/@w:val = 'full-page'">
+ <config:config-item config:name="ZoomType" config:type="short">2</config:config-item>
+ </xsl:when>
+ <xsl:when test="w:zoom/@w:val = 'text-fit'">
+ <config:config-item config:name="ZoomType" config:type="short">1</config:config-item>
+ </xsl:when>
+ <xsl:otherwise>
+ <config:config-item config:name="ZoomType" config:type="short">0</config:config-item>
+ </xsl:otherwise>
+ </xsl:choose>
+ <config:config-item config:name="ZoomFactor" config:type="short">
+ <xsl:value-of select="w:zoom/@w:percent"/>
+ </config:config-item>
+ </xsl:if>
+ </config:config-item-map-entry>
+ </config:config-item-map-indexed>
+ </config:config-item-set>
+ </office:settings>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_table.xsl b/filter/source/xslt/import/wordml/wordml2ooo_table.xsl
new file mode 100644
index 000000000..6bc520268
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_table.xsl
@@ -0,0 +1,1277 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt v">
+ <xsl:template match="w:style[@w:type='table']" mode="table">
+ <style:style style:family="table">
+ <xsl:attribute name="style:name">
+ <xsl:value-of select="concat('w',translate(@w:styleId,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ <xsl:if test="w:basedOn">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select="concat('w',translate(w:basedOn/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ <style:table-properties table:align="margins"/>
+ </style:style>
+ </xsl:template>
+ <xsl:template match="w:tblPr" mode="style">
+ <xsl:variable name="table-number">
+ <xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1" />
+ </xsl:variable>
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">
+ <xsl:text>Table</xsl:text>
+ <xsl:value-of select="$table-number"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">table</xsl:attribute>
+ <xsl:if test="w:tblStyle">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select="concat('w',translate(w:tblStyle/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="section-property-number" select="count(preceding::w:sectPr)"/>
+ <xsl:variable name="last-section-property" select="preceding::w:pPr/w:sectPr[1]"/>
+ <xsl:variable name="next-section-property" select="following::w:sectPr[1]"/>
+ <xsl:variable name="last-next-p-tbl" select="$last-section-property[last()]/following::*[name()='w:p' or name()='w:tbl']"/>
+ <xsl:choose>
+ <xsl:when test="not($next-section-property/w:type/@w:val = 'continuous') and generate-id($last-next-p-tbl[1]) = generate-id(..) and not(ancestor::w:sectPr or ancestor::w:styles)">
+ <xsl:attribute name="style:master-page-name">
+ <xsl:text>Standard</xsl:text>
+ <xsl:value-of select="$section-property-number + 1" />
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$table-number = 1 and not(preceding::w:p[ancestor::w:body])">
+ <xsl:attribute name="style:master-page-name">First_20_Page</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:element name="style:table-properties">
+ <xsl:choose>
+ <xsl:when test="w:jc/@w:val = 'left' or w:jc/@w:val = 'center' or w:jc/@w:val = 'right'">
+ <xsl:attribute name="table:align">
+ <xsl:value-of select="w:jc/@w:val"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="table:align">margins</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- adopt the width of table and column corresponding the width of page and margins. . -->
+ <xsl:variable name="sectPr" select="following::w:sectPr[1]"/>
+ <xsl:variable name="total-page-size" select="$sectPr/w:pgSz/@w:w"/>
+ <xsl:variable name="page-left-mar" select="$sectPr/w:pgMar/@w:left"/>
+ <xsl:variable name="page-right-mar" select="$sectPr/w:pgMar/@w:right"/>
+ <xsl:variable name="page-size-value" select="$total-page-size - $page-left-mar - $page-right-mar"/>
+ <xsl:variable name="page-size-inch">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat($page-size-value, 'twip') "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="gridcols" select="../w:tblGrid/w:gridCol"/>
+ <xsl:variable name="tblsize" select="sum($gridcols/@w:w)"/>
+ <xsl:variable name="table_indent">
+ <xsl:choose>
+ <xsl:when test="w:tblInd and w:tblInd/@w:w &gt; 0 ">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat(w:tblInd/@w:w, 'twip') "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="number( '0') "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="rel-tblsize">
+ <xsl:choose>
+ <xsl:when test="w:tblW/@w:type = 'pct'">
+ <xsl:value-of select="(number(w:tblW/@w:w ) div 5000) * $page-size-inch"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat($tblsize, 'twip')"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:width">
+ <xsl:value-of select="concat($rel-tblsize, 'in' )"/>
+ </xsl:attribute>
+ <xsl:variable name="tbl_margin_left">
+ <xsl:choose>
+ <xsl:when test="not(w:tblpPr ) ">
+ <xsl:choose>
+ <xsl:when test="w:bidiVisual">
+ <xsl:choose>
+ <xsl:when test=" number($page-size-inch - $table_indent - $rel-tblsize) &gt; 0">
+ <xsl:value-of select="$page-size-inch - $table_indent - $rel-tblsize"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>0</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$table_indent"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="w:tblpPr">
+ <!-- if the table is put into a draw:text-box, fo:margin-left and fo:margin-right should be 0 -->
+ <xsl:text>0</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="tbl_margin_right">
+ <xsl:choose>
+ <xsl:when test="not(w:tblpPr ) ">
+ <xsl:choose>
+ <xsl:when test="w:bidiVisual">
+ <xsl:value-of select="$table_indent"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test=" number($page-size-inch - $table_indent - $rel-tblsize) &gt; 0">
+ <xsl:value-of select="$page-size-inch - $table_indent - $rel-tblsize"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>0</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="w:tblpPr">
+ <!-- if the table is put into a draw:text-box, fo:margin-left and fo:margin-right should be 0 -->
+ <xsl:text>0</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="fo:margin-left">
+ <xsl:value-of select="concat( $tbl_margin_left, 'in')"/>
+ </xsl:attribute>
+ <xsl:attribute name="fo:margin-right">
+ <xsl:value-of select="concat($tbl_margin_right, 'in')"/>
+ </xsl:attribute>
+ <!-- If previous w:p has a page break, the table must have the page break attribute applied to it May need this for tables starting on new pages -->
+ <!-- <xsl:if test="parent::w:tbl/preceding-sibling::w:p[1][descendant::w:br/@w:type='page']">
+ <xsl:attribute name="fo:break-before">page</xsl:attribute></xsl:if> -->
+ <!-- initial values for tables-->
+ </xsl:element>
+ </xsl:element>
+ <!-- the following style is for converting Word table text wrapping to SO Writer. Since SO Writer has no table text wrapping feature, so we use the draw:text-box as a container and put the table in draw:text-box -->
+ <xsl:if test="w:tblpPr">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">TableFrame<xsl:number count="w:tblpPr" from="/w:wordDocument/w:body" level="any" format="1"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">graphic</xsl:attribute>
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select=" 'Frame' "/>
+ </xsl:attribute>
+ <xsl:element name="style:graphic-properties">
+ <xsl:if test="w:tblpPr/@w:leftFromText">
+ <xsl:variable name="left_margin_from_text">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat (w:tblpPr/@w:leftFromText, 'twip') "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:margin-left">
+ <xsl:value-of select="concat( $left_margin_from_text, 'in') "/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:tblpPr/@w:rightFromText">
+ <xsl:variable name="right_margin_from_text">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat (w:tblpPr/@w:rightFromText, 'twip') "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:margin-right">
+ <xsl:value-of select="concat( $right_margin_from_text, 'in') "/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:tblpPr/@w:topFromText">
+ <xsl:variable name="top_margin_from_text">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat (w:tblpPr/@w:topFromText, 'twip') "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:margin-top">
+ <xsl:value-of select="concat( $top_margin_from_text, 'in') "/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:tblpPr/@w:bottomFromText">
+ <xsl:variable name="bottom_margin_from_text">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat (w:tblpPr/@w:bottomFromText, 'twip') "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="fo:margin-bottom">
+ <xsl:value-of select="concat( $bottom_margin_from_text, 'in') "/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style:number-wrapped-paragraphs">
+ <xsl:text>no-limit</xsl:text>
+ </xsl:attribute>
+ <!--xsl:if test="w:tblpPr/@w:tblpYSpec" to get the vertical alignment-->
+ <xsl:variable name="vertical_alignment">
+ <xsl:choose>
+ <xsl:when test="w:tblpPr/@w:tblpYSpec = 'top' ">
+ <xsl:text>top</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:tblpYSpec = 'center' ">
+ <xsl:text>middle</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:tblpYSpec= 'bottom' ">
+ <xsl:text>bottom</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:tblpYSpec = 'inside' ">
+ <xsl:text>from-top</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:tblpYSpec= 'outside' ">
+ <xsl:text>top</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>from-top</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:vertical-pos">
+ <xsl:value-of select="$vertical_alignment"/>
+ </xsl:attribute>
+ <!--/xsl:if-->
+ <!--xsl:if test="w:tblpPr/@w:vertAnchor" to get the vertical anchor related area type -->
+ <xsl:variable name="frame_v_anchor">
+ <xsl:choose>
+ <xsl:when test="w:tblpPr/@w:vertAnchor = 'text' ">
+ <xsl:value-of select=" 'paragraph' "/>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:vertAnchor = 'margin' ">
+ <xsl:value-of select=" 'paragraph-content' "/>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:vertAnchor = 'page' ">
+ <xsl:value-of select="w:tblpPr/@w:vertAnchor"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" 'page-content' "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:vertical-rel">
+ <xsl:value-of select="$frame_v_anchor"/>
+ </xsl:attribute>
+ <!--/xsl:if-->
+ <!--xsl:if test="w:tblpPr/@w:tblpXSpec" to get the horizontal alignment-->
+ <xsl:variable name="horizental_alignment">
+ <xsl:choose>
+ <xsl:when test="w:tblpPr/@w:tblpXSpec = 'left' ">
+ <xsl:text>left</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:tblpXSpec = 'center' ">
+ <xsl:text>center</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:tblpXSpec = 'right' ">
+ <xsl:text>right</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:tblpXSpec = 'inside' ">
+ <xsl:text>from-left</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:tblpXSpec = 'outside' ">
+ <xsl:text>outside</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>left</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:horizontal-pos">
+ <xsl:value-of select="$horizental_alignment"/>
+ </xsl:attribute>
+ <!--/xsl:if-->
+ <!--xsl:if test="w:tblpPr/@w:horzAnchor" to get the horizental anchor related area type-->
+ <xsl:variable name="frame_h_anchor">
+ <xsl:choose>
+ <xsl:when test="w:tblpPr/@w:horzAnchor = 'text' ">
+ <xsl:value-of select=" 'paragraph' "/>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:horzAnchor = 'margin' ">
+ <xsl:value-of select=" 'page-content' "/>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:horzAnchor = 'page' ">
+ <xsl:value-of select="w:tblpPr/@w:horzAnchor"/>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:horzAnchor= 'inside' ">
+ <xsl:value-of select=" 'paragraph-start-margin' "/>
+ </xsl:when>
+ <xsl:when test="w:tblpPr/@w:horzAnchor= 'outside' ">
+ <xsl:value-of select=" 'paragraph-end-margin' "/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select=" 'paragraph-content' "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:horizontal-rel">
+ <xsl:value-of select="$frame_h_anchor"/>
+ </xsl:attribute>
+ <!--/xsl:if-->
+ <xsl:attribute name="fo:background-color">
+ <xsl:text>#ffffff</xsl:text>
+ </xsl:attribute>
+ <!-- xsl:attribute name="style:background-transparency"><xsl:text>100%</xsl:text></xsl:attribute -->
+ <xsl:attribute name="style:wrap">
+ <xsl:text>parallel</xsl:text>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:gridCol" mode="style">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:family">table-column</xsl:attribute>
+ <xsl:attribute name="style:name">Table<xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1"/>.C<xsl:number count="w:gridCol" from="/w:wordDocument/w:body" level="single" format="1"/>
+ </xsl:attribute>
+ <xsl:element name="style:table-column-properties">
+ <xsl:variable name="column_width">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat(@w:w, 'twip') "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:column-width">
+ <xsl:value-of select="concat($column_width,'in') "/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:trPr" mode="style">
+ <!-- to generate style:style of table-row height. -->
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:family">table-row</xsl:attribute>
+ <xsl:attribute name="style:name">Table<xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1"/>.R<xsl:number count="w:tr" from="/w:wordDocument/w:body" level="single" format="1"/>
+ </xsl:attribute>
+ <xsl:element name="style:table-row-properties">
+ <xsl:choose>
+ <xsl:when test="w:trHeight/@w:val">
+ <xsl:variable name="tbl_row_height">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat(w:trHeight/@w:val, 'twip') "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="style:min-row-height">
+ <xsl:value-of select="concat($tbl_row_height, 'in' )"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:tcPr" mode="style">
+ <style:style>
+ <xsl:attribute name="style:name">Table<xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1"/>.R<xsl:number count="w:tr" from="/w:wordDocument/w:body" level="single" format="1"/>C<xsl:number count="w:tc" from="/w:wordDocument/w:body" level="single" format="1"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">table-cell</xsl:attribute>
+ <xsl:variable name="rootStyle" select="ancestor::w:tbl/w:tblPr/w:tblStyle/@w:val"/>
+ <xsl:variable name="rootStyleNode" select="/w:wordDocument/w:styles/w:style[@w:styleId = $rootStyle]"/>
+ <xsl:element name="style:table-cell-properties">
+ <!-- cell background color start -->
+ <xsl:variable name="tbl_cell_background_color">
+ <xsl:choose>
+ <xsl:when test="w:shd/@w:fill">
+ <xsl:value-of select="w:shd/@w:fill"/>
+ </xsl:when>
+ <xsl:when test="$rootStyleNode/w:tblpr/w:shd/@w:fill">
+ <xsl:value-of select="$rootStyleNode/w:tblpr/w:shd/@w:fill"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test=" string-length($tbl_cell_background_color) &gt; 0 and not( $tbl_cell_background_color ='auto' )">
+ <xsl:attribute name="fo:background-color">
+ <xsl:value-of select="concat('#',$tbl_cell_background_color)"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <!--cell background color end -->
+ <!-- table cell vertical alignment start -->
+ <xsl:if test="w:vAlign">
+ <xsl:variable name="tbl_cell_alignment">
+ <xsl:choose>
+ <xsl:when test="w:vAlign/@w:val = 'top' ">
+ <xsl:text>top</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:vAlign/@w:val = 'center' ">
+ <xsl:text>middle</xsl:text>
+ </xsl:when>
+ <xsl:when test="w:vAlign/@w:val = 'bottom' ">
+ <xsl:text>bottom</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>automatic</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:vertical-align">
+ <xsl:value-of select="$tbl_cell_alignment"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!--table cell alignment end -->
+ <!-- cell margin start -->
+ <xsl:variable name="tblcell_leftmargin">
+ <xsl:choose>
+ <xsl:when test="w:tcMar/w:left">
+ <xsl:call-template name="convert2in_special">
+ <xsl:with-param name="original_value" select="concat(w:tcMar/w:left/@w:w , w:tcMar/w:left/@w:type) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$rootStyleNode/w:tblPr/w:tblCellMar/w:left">
+ <xsl:call-template name="convert2in_special">
+ <xsl:with-param name="original_value" select="concat($rootStyleNode/w:tblPr/w:tblCellMar/w:left/@w:w , $rootStyleNode/w:tblPr/w:tblCellMar/w:left/@w:type)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>0</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="tblcell_rightmargin">
+ <xsl:choose>
+ <xsl:when test="w:tcMar/w:right">
+ <xsl:call-template name="convert2in_special">
+ <xsl:with-param name="original_value" select="concat(w:tcMar/w:right/@w:w , w:tcMar/w:right/@w:type) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$rootStyleNode/w:tblPr/w:tblCellMar/w:right">
+ <xsl:call-template name="convert2in_special">
+ <xsl:with-param name="original_value" select="concat($rootStyleNode/w:tblPr/w:tblCellMar/w:right/@w:w , $rootStyleNode/w:tblPr/w:tblCellMar/w:right/@w:type)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>0</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="tblcell_topmargin">
+ <xsl:choose>
+ <xsl:when test="w:tcMar/w:top">
+ <xsl:call-template name="convert2in_special">
+ <xsl:with-param name="original_value" select="concat(w:tcMar/w:top/@w:w , w:tcMar/w:top/@w:type) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$rootStyleNode/w:tblPr/w:tblCellMar/w:top">
+ <xsl:call-template name="convert2in_special">
+ <xsl:with-param name="original_value" select="concat($rootStyleNode/w:tblPr/w:tblCellMar/w:top/@w:w , $rootStyleNode/w:tblPr/w:tblCellMar/w:top/@w:type)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>0</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="tblcell_bottommargin">
+ <xsl:choose>
+ <xsl:when test="w:tcMar/w:bottom">
+ <xsl:call-template name="convert2in_special">
+ <xsl:with-param name="original_value" select="concat(w:tcMar/w:bottom/@w:w , w:tcMar/w:bottom/@w:type) "/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$rootStyleNode/w:tblPr/w:tblCellMar/w:bottom">
+ <xsl:call-template name="convert2in_special">
+ <xsl:with-param name="original_value" select="concat($rootStyleNode/w:tblPr/w:tblCellMar/w:bottom/@w:w , $rootStyleNode/w:tblPr/w:tblCellMar/w:bottom/@w:type)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>0</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:if test="string-length($tblcell_leftmargin) &gt; 0 ">
+ <xsl:attribute name="fo:padding-left">
+ <xsl:value-of select="concat($tblcell_leftmargin, 'in' )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($tblcell_rightmargin) &gt; 0">
+ <xsl:attribute name="fo:padding-right">
+ <xsl:value-of select="concat($tblcell_rightmargin, 'in' )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($tblcell_topmargin) &gt; 0 ">
+ <xsl:attribute name="fo:padding-top">
+ <xsl:value-of select="concat($tblcell_topmargin, 'in' )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="string-length($tblcell_bottommargin) &gt; 0">
+ <xsl:attribute name="fo:padding-bottom">
+ <xsl:value-of select="concat($tblcell_bottommargin, 'in' )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- cell margin end -->
+ <xsl:variable name="row-position">
+ <xsl:number count="w:tr" from="/w:wordDocument/w:body" level="single" format="1"/>
+ </xsl:variable>
+ <!-- cell borders should be carefully converted. a little complex. glu :( -->
+ <xsl:variable name="Borders" select="ancestor::w:tbl/w:tblPr/w:tblBorders"/>
+ <xsl:choose>
+ <xsl:when test="$row-position &gt; 1">
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'top'"/>
+ <xsl:with-param name="style-position-0" select="w:tcBorders/w:top"/>
+ <xsl:with-param name="style-position-1" select="$Borders/w:insideH"/>
+ <xsl:with-param name="style-position-2" select="$rootStyleNode/w:tblPr/w:tblBorders/w:insideH"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'top'"/>
+ <xsl:with-param name="style-position-0" select="w:tcBorders/w:top"/>
+ <xsl:with-param name="style-position-1" select="$Borders/w:top"/>
+ <xsl:with-param name="style-position-2" select="$rootStyleNode/w:tblPr/w:tblBorders/w:top"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="count(ancestor::w:tr/following-sibling::w:tr) &gt; 0">
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'bottom'"/>
+ <xsl:with-param name="style-position-0" select="w:tcBorders/w:bottom"/>
+ <xsl:with-param name="style-position-1" select="$Borders/w:insideH"/>
+ <xsl:with-param name="style-position-2" select="$rootStyleNode/w:tblPr/w:tblBorders/w:insideH"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'bottom'"/>
+ <xsl:with-param name="style-position-0" select="w:tcBorders/w:bottom"/>
+ <xsl:with-param name="style-position-1" select="$Borders/w:bottom"/>
+ <xsl:with-param name="style-position-2" select="$rootStyleNode/w:tblPr/w:tblBorders/w:bottom"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="count(ancestor::w:tc/preceding-sibling::w:tc) &gt; 0">
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'left'"/>
+ <xsl:with-param name="style-position-0" select="w:tcBorders/w:left"/>
+ <xsl:with-param name="style-position-1" select="$Borders/w:insideV"/>
+ <xsl:with-param name="style-position-2" select="$rootStyleNode/w:tblPr/w:tblBorders/w:insideV"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'left'"/>
+ <xsl:with-param name="style-position-0" select="w:tcBorders/w:left"/>
+ <xsl:with-param name="style-position-1" select="$Borders/w:left"/>
+ <xsl:with-param name="style-position-2" select="$rootStyleNode/w:tblPr/w:tblBorders/w:left"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="count(ancestor::w:tc/following-sibling::w:tc) &gt; 0">
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'right'"/>
+ <xsl:with-param name="style-position-0" select="w:tcBorders/w:right"/>
+ <xsl:with-param name="style-position-1" select="$Borders/w:insideV"/>
+ <xsl:with-param name="style-position-2" select="$rootStyleNode/w:tblPr/w:tblBorders/w:insideV"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'right'"/>
+ <xsl:with-param name="style-position-0" select="w:tcBorders/w:right"/>
+ <xsl:with-param name="style-position-1" select="$Borders/w:right"/>
+ <xsl:with-param name="style-position-2" select="$rootStyleNode/w:tblPr/w:tblBorders/w:right"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </style:style>
+ </xsl:template>
+ <xsl:template name="get-table-border">
+ <xsl:param name="style-pos"/>
+ <xsl:param name="style-position-0"/>
+ <xsl:param name="style-position-1"/>
+ <xsl:param name="style-position-2"/>
+ <xsl:variable name="size-style">
+ <xsl:choose>
+ <xsl:when test="$style-position-0">
+ <xsl:value-of select="$style-position-0/@w:sz"/>
+ </xsl:when>
+ <xsl:when test="$style-position-1">
+ <xsl:value-of select="$style-position-1/@w:sz"/>
+ </xsl:when>
+ <xsl:when test="$style-position-2">
+ <xsl:value-of select="$style-position-2/@w:sz"/>
+ </xsl:when>
+ <xsl:otherwise>2</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="border-style">
+ <xsl:choose>
+ <xsl:when test="$style-position-0">
+ <xsl:value-of select="$style-position-0/@w:val"/>
+ </xsl:when>
+ <xsl:when test="$style-position-1">
+ <xsl:value-of select="$style-position-1/@w:val"/>
+ </xsl:when>
+ <xsl:when test="$style-position-2">
+ <xsl:value-of select="$style-position-2/@w:val"/>
+ </xsl:when>
+ <xsl:otherwise>single</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="color-border">
+ <xsl:choose>
+ <xsl:when test="$style-position-0 and string-length($style-position-0/@w:color) = 6">
+ <xsl:value-of select="$style-position-0/@w:color"/>
+ </xsl:when>
+ <xsl:when test="$style-position-0 and $style-position-0/@w:color = 'auto' and contains($border-style, 'set')">
+ <xsl:text>c0c0c0</xsl:text>
+ </xsl:when>
+ <xsl:when test="$style-position-1 and string-length($style-position-1/@w:color) = 6">
+ <xsl:value-of select="$style-position-1/@w:color"/>
+ </xsl:when>
+ <xsl:when test="$style-position-1 and $style-position-1/@w:color = 'auto' and contains($border-style, 'set')">
+ <xsl:text>c0c0c0</xsl:text>
+ </xsl:when>
+ <xsl:when test="$style-position-2 and string-length($style-position-2/@w:color) = 6">
+ <xsl:value-of select="$style-position-2/@w:color"/>
+ </xsl:when>
+ <xsl:when test="$style-position-2 and $style-position-2/@w:color = 'auto' and contains($border-style, 'set')">
+ <xsl:text>c0c0c0</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>000000</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- mapping border line widths. glu -->
+ <xsl:choose>
+ <xsl:when test="$border-style = 'nil' or $border-style = 'none'">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">hidden</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$border-style = 'single'">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 7">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.002cm solid #', $color-border)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 20">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.035cm solid #', $color-border)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 30">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.088cm solid #', $color-border)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 40">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.141cm solid #', $color-border)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.176cm solid #', $color-border)"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'double'">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 10">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.039cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.035cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 15">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.092cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 20">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.106cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.265cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'triple'">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 5">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.039cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.035cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 10">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.092cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">.002cm 0.088cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 15">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.106cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.265cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'thin-thick-small-gap' or $border-style = 'thick-thin-small-gap'">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'thin-thick-small-gap' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'thick-thin-small-gap' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 20">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.125cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 30">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.178cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.231cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'thin-thick-thin-small-gap'">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 20">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.178cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 40">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.231cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.318cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'thin-thick-medium-gap' or $border-style = 'thick-thin-medium-gap'">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 10">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.039cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.035cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 15">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.106cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 30">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'thin-thick-medium-gap' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'thick-thin-medium-gap' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.212cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.035cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.318cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="($border-style = 'thin-thick-medium-gap' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'thick-thin-medium-gap' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.141cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'thin-thick-thin-medium-gap'">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 10">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.039cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.035cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 15">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.106cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 30">
+ <xsl:choose>
+ <xsl:when test="$style-pos = 'left' or $style-pos = 'top'">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.212cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.035cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.318cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="$style-pos = 'left' or $style-pos = 'top'">
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.141cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'thin-thick-large-gap' or $border-style = 'thick-thin-large-gap'">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 7">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.092cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 10">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'thin-thick-large-gap' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'thick-thin-large-gap' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.125cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.092cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.002cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 15">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'thin-thick-large-gap' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'thick-thin-large-gap' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.125cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 30">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'thin-thick-large-gap' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'thick-thin-large-gap' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.178cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 40">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'thin-thick-large-gap' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'thick-thin-large-gap' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.231cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.318cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="($border-style = 'thin-thick-large-gap' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'thick-thin-large-gap' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.141cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$border-style = 'thin-thick-thin-large-gap'">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 5">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.125cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 10">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.178cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 20">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.231cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.318cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="contains( $border-style, 'wave') or $border-style = 'dash-dot-stroked'">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.106cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.035cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains( $border-style, 'three-d')">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 10">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.035cm solid #', $color-border)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 20">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.088cm solid #', $color-border)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 30">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.176cm solid #', $color-border)"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 40">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.265cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.318cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="contains( $border-style, 'set')">
+ <xsl:choose>
+ <xsl:when test="$size-style &lt; 7">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.092cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 10">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'outset' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'inset' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.092cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.002cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.125cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.035cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 15">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'outset' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'inset' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.125cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.035cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 30">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'outset' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'inset' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.178cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$size-style &lt; 40">
+ <xsl:choose>
+ <xsl:when test="($border-style = 'outset' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'inset' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.159cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.035cm 0.035cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.231cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.002cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.318cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="($border-style = 'outset' and ($style-pos = 'left' or $style-pos = 'top')) or ($border-style = 'inset' and ($style-pos = 'right' or $style-pos = 'bottom'))">
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.141cm 0.088cm 0.088cm</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">
+ <xsl:value-of select="concat('0.231cm double #', $color-border)"/>
+ </xsl:attribute>
+ <xsl:attribute name="{concat('style:border-line-width-',$style-pos)}">0.088cm 0.088cm 0.141cm</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="{concat('fo:border-', $style-pos)}">0.002cm solid #000000</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:tbl">
+ <xsl:choose>
+ <xsl:when test="w:tblPr/w:tblpPr">
+ <!-- if the table is surrounded by text then put the table into a draw:text-box -->
+ <xsl:element name="text:p">
+ <xsl:element name="draw:frame">
+ <xsl:attribute name="draw:style-name">
+ <xsl:text>TableFrame</xsl:text>
+ <xsl:number count="w:tblpPr" from="/w:wordDocument/w:body" level="any" format="1"/>
+ </xsl:attribute>
+ <xsl:attribute name="draw:name">TableFr<xsl:number count="w:tblpPr" from="/w:wordDocument/w:body" level="any" format="1"/>
+ </xsl:attribute>
+ <xsl:variable name="tbl_anchor_type">
+ <xsl:choose>
+ <xsl:when test="name(..) = 'w:tc' ">
+ <xsl:text>as-char</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>paragraph</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="text:anchor-type">
+ <xsl:value-of select="$tbl_anchor_type"/>
+ </xsl:attribute>
+ <xsl:variable name="tbl_draw_textbox_width">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <!-- adjust the width of draw:text-box containing a table with 20dxa + table-width -->
+ <xsl:with-param name="value" select="concat(string(number(sum(w:tblGrid/w:gridCol/@w:w) +20)), 'twip' )"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="svg:width">
+ <xsl:value-of select="concat ($tbl_draw_textbox_width, 'in') "/>
+ </xsl:attribute>
+ <xsl:if test="w:tblPr/w:tblpPr/@w:tblpX">
+ <xsl:variable name="x_distance_from_anchor">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat(w:tblPr/w:tblpPr/@w:tblpX, 'twip' ) "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="svg:x">
+ <xsl:value-of select="concat ($x_distance_from_anchor, 'in' )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:tblPr/w:tblpPr/@w:tblpY">
+ <xsl:variable name="y_distance_from_anchor">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="concat(w:tblPr/w:tblpPr/@w:tblpY, 'twip' ) "/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:attribute name="svg:y">
+ <xsl:value-of select="concat ($y_distance_from_anchor, 'in' )"/>
+ </xsl:attribute>
+ </xsl:if>
+ <!--create table in draw:text-box to produce table wrapping text effect-->
+ <xsl:element name="draw:text-box">
+ <xsl:element name="table:table">
+ <xsl:if test="w:tblPr">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:element>
+ <!--draw:text-box end -->
+ </xsl:element>
+ <!-- text:p end -->
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- if the table is not surrounded by text then put the table into a draw:text-box -->
+ <xsl:element name="table:table">
+ <xsl:if test="w:tblPr">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:tblGrid">
+ <xsl:apply-templates select="w:gridCol"/>
+ </xsl:template>
+ <xsl:template match="w:gridCol">
+ <xsl:element name="table:table-column">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1"/>.C<xsl:number count="w:gridCol" from="/w:wordDocument/w:body" level="single" format="1"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:tr">
+ <xsl:element name="table:table-row">
+ <!-- generate row in table and add attribute of table:style-name if the style:style exists. cp tom chen. -->
+ <xsl:if test="w:trPr/w:trHeight">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1"/>.R<xsl:number count="w:tr" from="/w:wordDocument/w:body" level="single" format="1"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:tc">
+ <xsl:element name="table:table-cell">
+ <xsl:attribute name="table:style-name">Table<xsl:number count="w:tbl" from="/w:wordDocument/w:body" level="any" format="1"/>.R<xsl:number count="w:tr" from="/w:wordDocument/w:body" level="single" format="1"/>C<xsl:number count="w:tc" from="/w:wordDocument/w:body" level="single" format="1"/>
+ </xsl:attribute>
+ <xsl:if test="w:tcPr/w:gridSpan and w:tcPr/w:gridSpan/@w:val &gt; 0">
+ <xsl:attribute name="table:number-columns-spanned">
+ <xsl:value-of select="w:tcPr/w:gridSpan/@w:val"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="convert2in_special">
+ <!-- this template is specially to deal with w:type ='dxa' situation -->
+ <xsl:param name="original_value"/>
+ <xsl:choose>
+ <xsl:when test="contains($original_value, 'dxa') ">
+ <xsl:variable name="table_measurement_new_value">
+ <xsl:value-of select="concat( substring-before($original_value,'dxa'), 'twip')"/>
+ </xsl:variable>
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="TargetMeasure" select="'in'"/>
+ <xsl:with-param name="value" select="$table_measurement_new_value"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/import/wordml/wordml2ooo_text.xsl b/filter/source/xslt/import/wordml/wordml2ooo_text.xsl
new file mode 100644
index 000000000..e2b94b3ec
--- /dev/null
+++ b/filter/source/xslt/import/wordml/wordml2ooo_text.xsl
@@ -0,0 +1,1049 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:w="http://schemas.microsoft.com/office/word/2003/wordml" xmlns:wx="http://schemas.microsoft.com/office/word/2003/auxHint" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:aml="http://schemas.microsoft.com/aml/2001/core" xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" exclude-result-prefixes="w wx aml o dt v">
+ <xsl:template name="create-default-paragraph-styles">
+ <xsl:variable name="default-paragraph-style" select="w:style[@w:default = 'on' and @w:type = 'paragraph']"/>
+ <xsl:if test="$default-paragraph-style">
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties>
+ <xsl:attribute name="style:tab-stop-distance">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(/w:wordDocument/w:docPr/w:defaultTabStop/@w:val,'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true">
+ <xsl:choose>
+ <xsl:when test="/w:wordDocument/w:fonts/w:defaultFonts">
+ <xsl:attribute name="style:font-name">
+ <xsl:value-of select="/w:wordDocument/w:fonts/w:defaultFonts/@w:ascii"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-name-asian">
+ <xsl:value-of select="/w:wordDocument/w:fonts/w:defaultFonts/@w:fareast"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-name-complex">
+ <xsl:value-of select="/w:wordDocument/w:fonts/w:defaultFonts/@w:cs"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:font-name">Times New Roman</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$default-paragraph-style/w:rPr/w:sz">
+ <xsl:attribute name="fo:font-size">
+ <xsl:value-of select="translate($default-paragraph-style/w:rPr/w:sz/@w:val,'Na','0') div 2"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian">
+ <xsl:value-of select="translate($default-paragraph-style/w:rPr/w:sz/@w:val,'Na','0') div 2"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$default-paragraph-style/w:rPr/w:sz-cs">
+ <xsl:attribute name="style:font-size-complex">
+ <xsl:value-of select="$default-paragraph-style/w:rPr/w:sz-cs/@w:val div 2"/>pt</xsl:attribute>
+ </xsl:if>
+ <!-- if not defined default font size in Word, make it out as 10pt. glu -->
+ <xsl:if test="not($default-paragraph-style/w:rPr/w:sz or w:rPr/w:sz-cs)">
+ <xsl:attribute name="fo:font-size">10pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian">10pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-complex">10pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$default-paragraph-style/w:rPr/w:lang">
+ <xsl:if test="$default-paragraph-style/w:rPr/w:lang/@w:val">
+ <xsl:attribute name="fo:language">
+ <xsl:choose>
+ <xsl:when test="contains($default-paragraph-style/w:rPr/w:lang/@w:val, '-')">
+ <xsl:value-of select="substring-before( $default-paragraph-style/w:rPr/w:lang/@w:val, '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$default-paragraph-style/w:rPr/w:lang/@w:val"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:value-of select="substring-before( $default-paragraph-style/w:rPr/w:lang/@w:val, '-')"/ -->
+ </xsl:attribute>
+ <xsl:attribute name="fo:country">
+ <xsl:choose>
+ <xsl:when test="contains($default-paragraph-style/w:rPr/w:lang/@w:val, '-')">
+ <xsl:value-of select="substring-before( $default-paragraph-style/w:rPr/w:lang/@w:val, '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$default-paragraph-style/w:rPr/w:lang/@w:val"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:value-of select="substring-after( $default-paragraph-style/w:rPr/w:lang/@w:val, '-')"/-->
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$default-paragraph-style/w:rPr/w:lang/@w:fareast">
+ <xsl:attribute name="style:language-asian">
+ <xsl:choose>
+ <xsl:when test="contains($default-paragraph-style/w:rPr/w:lang/@w:fareast, '-')">
+ <xsl:value-of select="substring-before( $default-paragraph-style/w:rPr/w:lang/@w:fareast, '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$default-paragraph-style/w:rPr/w:lang/@w:fareast"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:value-of select="substring-before( $default-paragraph-style/w:rPr/w:lang/@w:fareast, '-')"/-->
+ </xsl:attribute>
+ <xsl:attribute name="style:country-asian">
+ <xsl:choose>
+ <xsl:when test="contains($default-paragraph-style/w:rPr/w:lang/@w:fareast, '-')">
+ <xsl:value-of select="substring-before( $default-paragraph-style/w:rPr/w:lang/@w:fareast, '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$default-paragraph-style/w:rPr/w:lang/@w:fareast"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:value-of select="substring-after( $default-paragraph-style/w:rPr/w:lang/@w:fareast, '-')"/ -->
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$default-paragraph-style/w:rPr/w:lang/@w:bidi">
+ <xsl:attribute name="style:language-complex">
+ <xsl:choose>
+ <xsl:when test="contains( $default-paragraph-style/w:rPr/w:lang/@w:bidi, '-') ">
+ <xsl:value-of select="substring-after( $default-paragraph-style/w:rPr/w:lang/@w:bidi, '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$default-paragraph-style/w:rPr/w:lang/@w:bidi "/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:value-of select="substring-before( $default-paragraph-style/w:rPr/w:lang/@w:bidi, '-')"/-->
+ </xsl:attribute>
+ <xsl:attribute name="style:country-complex">
+ <xsl:choose>
+ <xsl:when test="contains($default-paragraph-style/w:rPr/w:lang/@w:bidi, '-')">
+ <xsl:value-of select="substring-after( $default-paragraph-style/w:rPr/w:lang/@w:bidi, '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$default-paragraph-style/w:rPr/w:lang/@w:bidi"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- xsl:value-of select="substring-after( $default-paragraph-style/w:rPr/w:lang/@w:bidi, '-')"/ -->
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </style:text-properties>
+ </style:default-style>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="create-default-text-styles">
+ <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/>
+ <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/>
+ <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text">
+ <style:text-properties style:font-name="StarSymbol" fo:font-size="9pt" style:font-name-asian="StarSymbol" style:font-size-asian="9pt" style:font-name-complex="StarSymbol" style:font-size-complex="9pt"/>
+ </style:style>
+ <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/>
+ <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text">
+ <style:text-properties style:text-position="super 58%"/>
+ </style:style>
+ </xsl:template>
+ <xsl:template match="w:p" mode="style">
+ <xsl:variable name="paragraph-number">
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="w:p" format="1"/>
+ </xsl:variable>
+ <xsl:variable name="section-property-number" select="count(preceding::w:sectPr)"/>
+ <xsl:variable name="last-section-property" select="preceding::w:pPr/w:sectPr[1]"/>
+ <xsl:variable name="next-section-property" select="following::w:sectPr[1]"/>
+ <style:style style:family="paragraph" style:name="P{$paragraph-number}">
+ <xsl:choose>
+ <xsl:when test="w:pPr/w:pStyle">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select="concat('w',translate(w:pPr/w:pStyle/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))" />
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:parent-style-name">wNormal</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:choose>
+ <xsl:when test="not($next-section-property/w:type/@w:val = 'continuous') and generate-id($last-section-property[last()]/following::w:p[1]) = generate-id(.) and not(ancestor::w:sectPr or ancestor::w:tbl)">
+ <xsl:attribute name="style:master-page-name">Standard-1<xsl:value-of select="$section-property-number + 1"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$paragraph-number = 1">
+ <xsl:attribute name="style:master-page-name">First_20_Page</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <style:paragraph-properties>
+ <xsl:apply-templates select="w:pPr"/>
+ </style:paragraph-properties>
+ <style:text-properties>
+ <xsl:apply-templates select="w:pPr/w:rPr"/>
+ <xsl:apply-templates select="w:rPr"/>
+ </style:text-properties>
+ </style:style>
+ <xsl:if test="w:r/w:br/@w:type='page'">
+ <style:style style:family="paragraph" style:name="P{$paragraph-number}page-break">
+ <xsl:if test="w:pPr/w:pStyle">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select="concat('w',translate(w:pPr/w:pStyle/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="generate-id($last-section-property[last()]/following::w:p[1]) = generate-id(.) and not(ancestor::w:sectPr or ancestor::w:tbl)">
+ <xsl:attribute name="style:master-page-name">Standard-1<xsl:value-of select="$section-property-number + 1"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$paragraph-number = 1">
+ <xsl:attribute name="style:master-page-name">First_20_Page</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <style:paragraph-properties fo:break-before="page">
+ <xsl:apply-templates select="w:pPr"/>
+ </style:paragraph-properties>
+ </style:style>
+ </xsl:if>
+ <xsl:if test="w:r/w:br/@w:type='column'">
+ <style:style style:family="paragraph" style:name="P{$paragraph-number}column-break">
+ <xsl:if test="w:pPr/w:pStyle">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select="concat('w',translate(w:pPr/w:pStyle/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="generate-id($last-section-property[last()]/following::w:p[1]) = generate-id(.) and not(ancestor::w:sectPr or ancestor::w:tbl)">
+ <xsl:attribute name="style:master-page-name">Standard-1<xsl:value-of select="$section-property-number + 1"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="$paragraph-number = 1">
+ <xsl:attribute name="style:master-page-name">First_20_Page</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <style:paragraph-properties fo:break-before="column">
+ <xsl:apply-templates select="w:pPr"/>
+ </style:paragraph-properties>
+ </style:style>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:pPr">
+ <xsl:if test="w:ind/@w:left">
+ <xsl:attribute name="fo:margin-left">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:ind/@w:left, 'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:ind/@w:right">
+ <xsl:attribute name="fo:margin-right">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:ind/@w:right, 'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:ind/@w:first-line">
+ <xsl:attribute name="fo:text-indent">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:ind/@w:first-line, 'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:ind/@w:hanging">
+ <xsl:attribute name="fo:text-indent">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat('-',w:ind/@w:hanging, 'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <!-- bi-directional support-->
+ <xsl:if test="w:bidi">
+ <xsl:choose>
+ <xsl:when test="w:bidi/@w:val = 'off'">
+ <xsl:attribute name="fo:text-align">start</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:writing-mode">rl-tb</xsl:attribute>
+ <xsl:attribute name="fo:text-align">end</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="w:jc">
+ <xsl:choose>
+ <xsl:when test="w:jc/@w:val = 'center'">
+ <xsl:attribute name="fo:text-align">center</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:jc/@w:val = 'left'">
+ <xsl:choose>
+ <xsl:when test="w:bidi and not(w:bidi/@w:val = 'off')">
+ <xsl:attribute name="fo:text-align">end</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:text-align">start</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="w:jc/@w:val = 'right'">
+ <xsl:choose>
+ <xsl:when test="w:bidi and not(w:bidi/@w:val = 'off')">
+ <xsl:attribute name="fo:text-align">start</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:text-align">end</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="fo:text-align">justify</xsl:attribute>
+ <xsl:attribute name="style:justify-single-word">false</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="w:spacing">
+ <xsl:choose>
+ <xsl:when test="w:spacing/@w:line-rule = 'at-least'">
+ <xsl:attribute name="style:line-height-at-least">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:spacing/@w:line, 'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:spacing/@w:line-rule = 'auto'">
+ <xsl:attribute name="fo:line-height">
+ <xsl:value-of select="round(w:spacing/@w:line div 240 * 100)"/>%</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:spacing/@w:line-rule = 'exact'">
+ <xsl:attribute name="fo:line-height">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:spacing/@w:line, 'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="w:spacing/@w:before">
+ <xsl:attribute name="fo:margin-top">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:spacing/@w:before, 'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:spacing/@w:after">
+ <xsl:attribute name="fo:margin-bottom">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:spacing/@w:after, 'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="w:shd">
+ <xsl:variable name="background-color">
+ <xsl:choose>
+ <xsl:when test="string-length(w:shd/@w:fill) = 6">
+ <xsl:value-of select="concat('#', w:shd/@w:fill)"/>
+ </xsl:when>
+ <xsl:otherwise>#000000</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="w:shd/@w:val = 'solid'">
+ <xsl:attribute name="fo:background-color">
+ <xsl:value-of select="$background-color"/>
+ </xsl:attribute>
+ </xsl:when>
+ <!-- patterns are necessary in the future. glu -->
+ <xsl:otherwise/>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="w:pageBreakBefore and not(w:pageBreakBefore/@w:val = 'off')">
+ <xsl:attribute name="fo:break-before">page</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:pageBreakBefore and w:pageBreakBefore/@w:val = 'off'">
+ <xsl:attribute name="fo:break-before">auto</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:keepNext">
+ <xsl:attribute name="fo:keep-with-next">always</xsl:attribute>
+ </xsl:if>
+ <!--
+ <xsl:if test="w:keepLines">
+ <xsl:attribute name="style:break-inside">avoid</xsl:attribute>
+ </xsl:if>
+ -->
+ <xsl:if test="w:widowControl='on'">
+ <xsl:attribute name="fo:widows">2</xsl:attribute>
+ <xsl:attribute name="fo:orphans">2</xsl:attribute>
+ </xsl:if>
+ <!--
+ <xsl:if test="w:suppressAutoHyphens">
+ <xsl:attribute name="fo:hyphenate">false</xsl:attribute>
+ </xsl:if>
+ -->
+ <xsl:if test="w:kinsoku/@w:val='off'">
+ <xsl:attribute name="style:line-break">normal</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:overflowPunct/@w:val='off'">
+ <xsl:attribute name="style:punctuation-wrap">simple</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:autoSpaceDE/@w:val='off' or w:autoSpaceDN/@w:val='off'">
+ <xsl:attribute name="style:text-autospace">none</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:textAlignment">
+ <xsl:choose>
+ <xsl:when test="w:textAlignment/@w:val='center'">
+ <xsl:attribute name="style:vertical-align">middle</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:textAlignment/@w:val='baseline'">
+ <xsl:attribute name="style:vertical-align">bottom</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:vertical-align">
+ <xsl:value-of select="w:textAlignment/@w:val"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="w:pBdr">
+ <xsl:if test="w:pBdr/w:top">
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'top'"/>
+ <xsl:with-param name="style-position-0" select="w:pBdr/w:top"/>
+ </xsl:call-template>
+ <xsl:attribute name="fo:padding-top">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pBdr/w:top/@w:space,'pt')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:pBdr/w:left">
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'left'"/>
+ <xsl:with-param name="style-position-0" select="w:pBdr/w:left"/>
+ </xsl:call-template>
+ <xsl:attribute name="fo:padding-left">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pBdr/w:left/@w:space,'pt')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:pBdr/w:right">
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'right'"/>
+ <xsl:with-param name="style-position-0" select="w:pBdr/w:right"/>
+ </xsl:call-template>
+ <xsl:attribute name="fo:padding-right">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pBdr/w:right/@w:space,'pt')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:pBdr/w:bottom">
+ <xsl:call-template name="get-table-border">
+ <xsl:with-param name="style-pos" select="'bottom'"/>
+ <xsl:with-param name="style-position-0" select="w:pBdr/w:bottom"/>
+ </xsl:call-template>
+ <xsl:attribute name="fo:padding-bottom">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:pBdr/w:bottom/@w:space,'pt')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:pBdr/*/@w:shadow='on'">
+ <xsl:attribute name="style:shadow">#000000 0.15cm 0.15cm</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="w:snapToGrid/@w:val='off'">
+ <xsl:attribute name="style:snap-to-layout-grid">false</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:tabs">
+ <xsl:element name="style:tab-stops">
+ <xsl:for-each select="w:tabs/w:tab">
+ <xsl:element name="style:tab-stop">
+ <xsl:attribute name="style:position">
+ <xsl:if test="@w:pos &lt; 0">
+ <xsl:message>
+ We meet a negative w:pos:<xsl:value-of select="@w:pos"/>.
+ </xsl:message>
+ <xsl:value-of select="'0cm'"/>
+ </xsl:if>
+ <xsl:if test="not(@w:pos &lt; 0)">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(@w:pos, 'twip')"/>
+ </xsl:call-template>cm</xsl:if>
+ </xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@w:val = 'decimal'">
+ <xsl:attribute name="style:type">char</xsl:attribute>
+ <xsl:attribute name="style:char">
+ <xsl:value-of select="' '"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@w:val = 'left' or @w:val = 'right' or @w:val = 'center' ">
+ <xsl:attribute name="style:type">
+ <xsl:value-of select="@w:val"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:type">char</xsl:attribute>
+ <xsl:attribute name="style:char">
+ <xsl:value-of select="' '"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- Detect leader chars in tabs (rp) -->
+ <xsl:choose>
+ <xsl:when test="@w:leader = 'hyphen'">
+ <xsl:attribute name="style:leader-style">solid</xsl:attribute>
+ <xsl:attribute name="style:leader-text">-</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@w:leader = 'underscore'">
+ <xsl:attribute name="style:leader-style">solid</xsl:attribute>
+ <xsl:attribute name="style:leader-text">_</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@w:leader = 'dot'">
+ <xsl:attribute name="style:leader-style">dotted</xsl:attribute>
+ <xsl:attribute name="style:leader-text">.</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <!-- end leader chars (rp) -->
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:if>
+ <xsl:apply-templates select="w:rPr" mode="paragraph-properties"/>
+ </xsl:template>
+ <xsl:template match="w:rPr" mode="style">
+ <xsl:element name="style:style">
+ <xsl:attribute name="style:name">T<xsl:number from="/w:wordDocument/w:body" level="any" count="w:rPr" format="1"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:family">text</xsl:attribute>
+ <xsl:if test="w:rStyle">
+ <xsl:attribute name="style:parent-style-name">
+ <xsl:value-of select="concat('w',translate(w:rStyle/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:element name="style:text-properties">
+
+ <xsl:apply-templates select="current()"/>
+ <!-- <xsl:call-template name="text-properties"/> -->
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:rPr">
+ <xsl:if test="w:rFonts">
+ <xsl:if test="w:rFonts/@w:ascii">
+ <xsl:attribute name="style:font-name">
+ <xsl:value-of select="w:rFonts/@w:ascii"/>
+ </xsl:attribute>
+ <xsl:if test="ancestor::w:body">
+ <xsl:attribute name="style:font-name-asian">
+ <xsl:value-of select="w:rFonts/@w:ascii"/>
+ </xsl:attribute>
+ <xsl:attribute name="style:font-name-complex">
+ <xsl:value-of select="w:rFonts/@w:ascii"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="ancestor::w:styles">
+ <xsl:if test="w:rFonts/@w:fareast">
+ <xsl:attribute name="style:font-name-asian">
+ <xsl:value-of select="w:rFonts/@w:fareast"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:rFonts/@w:cs">
+ <xsl:attribute name="style:font-name-complex">
+ <xsl:value-of select="w:rFonts/@w:cs"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="parent::w:r">
+ <xsl:if test="w:b">
+ <xsl:attribute name="fo:font-weight">bold</xsl:attribute>
+ <xsl:attribute name="style:font-weight-asian">bold</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:b-cs">
+ <xsl:attribute name="style:font-weight-complex">bold</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:i">
+ <xsl:attribute name="fo:font-style">italic</xsl:attribute>
+ <xsl:attribute name="style:font-style-asian">italic</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:i-cs">
+ <xsl:attribute name="style:font-style-complex">italic</xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="w:caps">
+ <xsl:attribute name="fo:text-transform">uppercase</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:smallCaps">
+ <xsl:attribute name="fo:font-variant">small-caps</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:strike">
+ <xsl:attribute name="style:text-line-through-style">solid</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:dstrike">
+ <xsl:attribute name="style:text-line-through-style">solid</xsl:attribute>
+ <xsl:attribute name="style:text-line-through-type">double</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:outline">
+ <xsl:attribute name="style:text-outline">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:shadow">
+ <xsl:attribute name="fo:text-shadow">1pt 1pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:imprint">
+ <xsl:attribute name="style:font-relief">engraved</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:emboss">
+ <xsl:attribute name="style:font-relief">embossed</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:vanish">
+ <xsl:attribute name="text:display">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:color[not(@w:val = 'auto')]">
+ <xsl:attribute name="fo:color">#<xsl:value-of select="w:color/@w:val"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:spacing">
+ <xsl:attribute name="fo:letter-spacing">
+ <xsl:call-template name="ConvertMeasure">
+ <xsl:with-param name="value" select="concat(w:spacing/@w:val,'twip')"/>
+ </xsl:call-template>cm</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:w/@w:val">
+ <xsl:attribute name="style:text-scale">
+ <xsl:value-of select="concat(w:w/@w:val, '%')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:vertAlign or w:position">
+ <xsl:variable name="height">
+ <xsl:choose>
+ <xsl:when test="w:vertAlign[@w:val = 'superscript' or @w:val = 'subscript']">58%</xsl:when>
+ <xsl:otherwise>100%</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="position">
+ <xsl:choose>
+ <xsl:when test="w:position">
+ <!-- con't get font height easily, so just set w:val as percentage. glu -->
+ <xsl:value-of select="concat( w:position/@w:val, '%')"/>
+ </xsl:when>
+ <xsl:when test="w:vertAlign[@w:val = 'superscript']">super</xsl:when>
+ <xsl:when test="w:vertAlign[@w:val = 'subscript']">sub</xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:attribute name="style:text-position">
+ <xsl:value-of select="concat($position, ' ', $height)"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:sz">
+ <xsl:attribute name="fo:font-size">
+ <xsl:value-of select="translate(w:sz/@w:val,'Na','0') div 2"/>pt</xsl:attribute>
+ <xsl:attribute name="style:font-size-asian">
+ <xsl:value-of select="translate(w:sz/@w:val,'Na','0') div 2"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:sz-cs">
+ <xsl:attribute name="style:font-size-complex">
+ <xsl:value-of select="w:sz-cs/@w:val div 2"/>pt</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:highlight">
+ <xsl:choose>
+ <xsl:when test="w:highlight/@w:val='black'">
+ <xsl:attribute name="fo:background-color">#000000</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='yellow'">
+ <xsl:attribute name="fo:background-color">#ffff00</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='green'">
+ <xsl:attribute name="fo:background-color">#00ff00</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='cyan'">
+ <xsl:attribute name="fo:background-color">#00ffff</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='magenta'">
+ <xsl:attribute name="fo:background-color">#ff00ff</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='blue'">
+ <xsl:attribute name="fo:background-color">#0000ff</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='red'">
+ <xsl:attribute name="fo:background-color">#ff0000</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='dark-blue'">
+ <xsl:attribute name="fo:background-color">#000080</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='dark-cyan'">
+ <xsl:attribute name="fo:background-color">#008080</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='dark-green'">
+ <xsl:attribute name="fo:background-color">#008000</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='dark-magenta'">
+ <xsl:attribute name="fo:background-color">#800080</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='dark-red'">
+ <xsl:attribute name="fo:background-color">#800000</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='dark-yellow'">
+ <xsl:attribute name="fo:background-color">#808000</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='dark-gray'">
+ <xsl:attribute name="fo:background-color">#808080</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:highlight/@w:val='light-gray'">
+ <xsl:attribute name="fo:background-color">#c0c0c0</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="w:u">
+ <xsl:if test="w:u/@w:val = 'thick' or contains(w:u/@w:val,'-heavy')">
+ <xsl:attribute name="style:text-underline-width">bold</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:u/@w:val = 'double' or contains(w:u/@w:val,'-double')">
+ <xsl:attribute name="style:text-underline-type">double</xsl:attribute>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="w:u/@w:val = 'words' or w:u/@w:val = 'single' or w:u/@w:val = 'thick' or w:u/@w:val = 'double'">
+ <xsl:attribute name="style:text-underline-style">solid</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains(w:u/@w:val , 'dotted')">
+ <xsl:attribute name="style:text-underline-style">dotted</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:u/@w:val = 'dashed-heavy' or w:u/@w:val = 'dash'">
+ <xsl:attribute name="style:text-underline-style">dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:u/@w:val = 'dash-long' or w:u/@w:val = 'dash-long-heavy'">
+ <xsl:attribute name="style:text-underline-style">long-dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:u/@w:val = 'dash-dot-heavy' or w:u/@w:val = 'dot-dash'">
+ <xsl:attribute name="style:text-underline-style">dot-dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:u/@w:val = 'dash-dot-dot-heavy' or w:u/@w:val = 'dot-dot-dash'">
+ <xsl:attribute name="style:text-underline-style">dot-dot-dash</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:u/@w:val = 'wavy-heavy' or w:u/@w:val = 'wavy-double' or w:u/@w:val = 'wavy'">
+ <xsl:attribute name="style:text-underline-style">wave</xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="string-length(style:text-underline-style) &gt; 0">
+ <xsl:attribute name="style:text-underline-style">
+ <xsl:value-of select="w:u/@w:val"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="w:u/@w:color and not(w:u/@w:color = 'auto')">
+ <xsl:attribute name="style:text-underline-color">#<xsl:value-of select="w:u/@w:color"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="w:effect[@w:val = 'blink-background']">
+ <xsl:attribute name="style:text-blinking">true</xsl:attribute>
+ </xsl:if>
+ <xsl:if test="w:shd and not(w:highlight)">
+ <xsl:if test="string-length(w:shd/@w:fill) = 6">
+ <xsl:attribute name="fo:background-color">#<xsl:value-of select="w:shd/@w:fill"/>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="w:em">
+ <xsl:choose>
+ <xsl:when test="w:em/@w:val = 'comma'">
+ <xsl:attribute name="style:text-emphasize">accent below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:em/@w:val = 'under-dot'">
+ <xsl:attribute name="style:text-emphasize">disc below</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:em/@w:val = 'dot' or w:em/@w:val = 'circle' ">
+ <xsl:attribute name="style:text-emphasize">
+ <xsl:value-of select=" concat(w:em/@w:val,' below') "/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style:text-emphasize">none</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="w:lang">
+ <xsl:if test="w:lang/@w:val">
+ <xsl:attribute name="fo:language">
+ <xsl:choose>
+ <xsl:when test="contains(w:lang/@w:val, '-')">
+ <xsl:value-of select="substring-before( w:lang/@w:val, '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="w:lang/@w:val"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:value-of select="substring-before( w:lang/@w:val, '-')"/-->
+ </xsl:attribute>
+ <xsl:attribute name="fo:country">
+ <xsl:choose>
+ <xsl:when test="contains(w:lang/@w:val, '-')">
+ <xsl:value-of select="substring-before( w:lang/@w:val, '-')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="w:lang/@w:val"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--xsl:value-of select="substring-after( w:lang/@w:val, '-')"/-->
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:rPr" mode="paragraph-properties">
+ <!-- right-to-left support-->
+ <xsl:if test="w:rtl and not(w:rtl/@w:val = 'off')">
+ <xsl:attribute name="style:writing-mode">rl-tb</xsl:attribute>
+ <xsl:attribute name="fo:text-align">end</xsl:attribute>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:p">
+ <xsl:choose>
+ <!-- because word treats page breaks as separate tags, we must split some paragraphs up so that we can
+ give the sub para a fo:break-before ="page" or column attribute. -->
+ <xsl:when test="w:r[w:br/@w:type='page' or w:br/@w:type='column']">
+ <xsl:call-template name="process-breaks-in-paragraph"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="process-common-paragraph"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="process-breaks-in-paragraph">
+ <xsl:variable name="textruns-with-break" select="w:r[w:br/@w:type='page' or w:br/@w:type='column']"/>
+ <xsl:call-template name="create-sub-paragraph">
+ <xsl:with-param name="textruns" select="$textruns-with-break[1]/preceding-sibling::w:r"/>
+ </xsl:call-template>
+ <xsl:for-each select="$textruns-with-break">
+ <xsl:variable name="break-position" select="position()"/>
+ <xsl:call-template name="create-sub-paragraph">
+ <!-- added following-sibling::w:fldSimple | following-sibling::w:hlink | following-sibling::aml:annotation to enable these elements to be processed when there are breaks happen G.Yang -->
+ <xsl:with-param name="textruns" select="following-sibling::w:r[not(w:br/@w:type='page' or w:br/@w:type='column') and (count(preceding::w:r[w:br/@w:type='page' or w:br/@w:type='column']) = $break-position)] | following-sibling::w:fldSimple[count(preceding::w:r[w:br/@w:type='page' or w:br/@w:type='column']) = $break-position] | following-sibling::w:hlink[count(preceding::w:r[w:br/@w:type='page' or w:br/@w:type='column']) = $break-position] | following-sibling::aml:annotation[count(preceding::w:r[w:br/@w:type='page' or w:br/@w:type='column']) = $break-position] "/>
+ <xsl:with-param name="textruns-with-break" select="current()"/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+ <xsl:template name="create-sub-paragraph">
+ <xsl:param name="textruns"/>
+ <xsl:param name="textruns-with-break"/>
+ <xsl:if test="$textruns or $textruns-with-break">
+ <xsl:variable name="curr-num">
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="w:p" format="1"/>
+ </xsl:variable>
+ <text:p>
+ <xsl:choose>
+ <xsl:when test="$textruns-with-break">
+ <xsl:attribute name="text:style-name">
+ <xsl:value-of select="concat('P',$curr-num,w:br/@w:type, '-break')"/>
+ </xsl:attribute>
+ <xsl:apply-templates select="$textruns-with-break"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="text:style-name">
+ <xsl:value-of select="concat( 'P', $curr-num)"/>
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:if test="$textruns">
+ <xsl:apply-templates select="$textruns"/>
+ </xsl:if>
+ </text:p>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template name="process-common-paragraph">
+ <xsl:variable name="heading-or-paragraph">
+ <xsl:choose>
+ <xsl:when test="key('heading-style', w:pPr/w:pStyle/@w:val)">text:h</xsl:when>
+ <xsl:otherwise>text:p</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="{$heading-or-paragraph}">
+ <xsl:if test="$heading-or-paragraph = 'text:h'">
+ <xsl:attribute name="text:outline-level">
+ <xsl:value-of select="key('heading-style',w:pPr/w:pStyle/@w:val)/w:pPr/w:outlineLvl/@w:val + 1"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:variable name="curr-num">
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="w:p" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name">
+ <xsl:value-of select="concat( 'P', $curr-num)"/>
+ </xsl:attribute>
+ <xsl:variable name="bookmark-and-paragraph" select="preceding::aml:annotation[(@w:type = 'Word.Bookmark.Start' or @w:type = 'Word.Bookmark.End') and not(ancestor::w:p)] | preceding::w:p"/>
+ <xsl:if test="count($bookmark-and-paragraph) &gt; 0 and name($bookmark-and-paragraph[last()]) = 'aml:annotation'">
+ <xsl:call-template name="create-bookmark">
+ <xsl:with-param name="bookmark-and-paragraph" select="$bookmark-and-paragraph"/>
+ <xsl:with-param name="position" select="count($bookmark-and-paragraph)"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:apply-templates mode="dispatch"/>
+ <xsl:if test="not(following::w:p)">
+ <xsl:apply-templates select="following::aml:annotation[(@w:type = 'Word.Bookmark.Start' or @w:type = 'Word.Bookmark.End') and not(ancestor::w:p)]"/>
+ </xsl:if>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template name="create-bookmark">
+ <xsl:param name="bookmark-and-paragraph"/>
+ <xsl:param name="position"/>
+ <xsl:choose>
+ <xsl:when test="name($bookmark-and-paragraph[$position]) = 'aml:annotation'">
+ <xsl:if test="$position &gt; 0">
+ <xsl:call-template name="create-bookmark">
+ <xsl:with-param name="bookmark-and-paragraph" select="$bookmark-and-paragraph"/>
+ <xsl:with-param name="position" select="$position - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="output-bookmark">
+ <xsl:with-param name="bookmark-and-paragraph" select="$bookmark-and-paragraph"/>
+ <xsl:with-param name="position" select="$position + 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="output-bookmark">
+ <xsl:param name="bookmark-and-paragraph"/>
+ <xsl:param name="position"/>
+ <xsl:apply-templates select="$bookmark-and-paragraph[$position]"/>
+ <xsl:if test="$position &lt; count($bookmark-and-paragraph)">
+ <xsl:call-template name="output-bookmark">
+ <xsl:with-param name="bookmark-and-paragraph" select="$bookmark-and-paragraph"/>
+ <xsl:with-param name="position" select="$position + 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+ <!-- WordML contains multiple w:t within one w:r, so in Star Writer text:span should correspond to w:t glu -->
+ <xsl:template match="w:r">
+ <xsl:choose>
+ <xsl:when test="(preceding-sibling::w:r) or (w:rPr)">
+ <!-- add this condition to prevent from printing the value of DATE, TIME, PRINTDATE, CREATEDATE, SAVEDATE, PAGE, NUMPAGES etc. fields in-between w:fldchar begin and w:fldchar end G.Yang.-->
+ <xsl:if test="not (preceding-sibling::w:r/w:instrText[substring(normalize-space(.),1,4) = 'DATE' or substring(normalize-space(.),1,4) = 'TIME' or substring(normalize-space(.),1,9) = 'PRINTDATE' or substring(normalize-space(.),1,10) = 'CREATEDATE' or substring(normalize-space(.),1,8) = 'SAVEDATE' or substring(normalize-space(.),1,4) = 'PAGE' or substring(normalize-space(.),1,8) = 'NUMPAGES' or substring(normalize-space(.),1,8) = 'NUMWORDS' or substring(normalize-space(.),1,8) = 'NUMCHARS' or substring(normalize-space(.),1,6) = 'REVNUM' or substring(normalize-space(.),1,7) = 'AUTONUM' or substring(normalize-space(.),1,10) = 'AUTONUMLGL' or substring(normalize-space(.),1,10) = 'AUTONUMOUT' or substring(normalize-space(.),1,3) = 'SEQ' or substring(normalize-space(.),1,6) = 'AUTHOR' or substring(normalize-space(.),1,5) = 'TITLE' or substring(normalize-space(.),1,7) = 'SUBJECT' or substring(normalize-space(.),1,8) = 'KEYWORDS' or substring(normalize-space(.),1,6) = 'FILLIN' or substring(normalize-space(.),1,11) = 'DOCPROPERTY' or substring(normalize-space(.),1,10) = 'MERGEFIELD' or substring(normalize-space(.),1,8) = 'MERGEREC' or substring(normalize-space(.),1,4) = 'NEXT' or substring( normalize-space(.),1,9) = 'HYPERLINK' or substring( normalize-space(.),1,3) = 'REF' ][1] and (following-sibling::w:r/w:fldChar[@w:fldCharType='end'] or ( not(preceding-sibling::w:r/w:fldChar[@w:fldCharType='end'] ) and parent::w:p/following-sibling::w:p/w:r/w:fldChar[@w:fldCharType='end'])) )">
+ <text:span>
+ <xsl:choose>
+ <xsl:when test="w:rPr/w:rStyle">
+ <xsl:attribute name="text:style-name">
+ <xsl:value-of select="concat('w', translate(w:rPr/w:rStyle/@w:val,' ~`!@#$%^*(&#x26;)+/,;?&lt;&gt;{}[]:','_'))"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="w:rPr">
+ <xsl:variable name="position">
+ <xsl:number from="/w:wordDocument/w:body" level="any" count="w:rPr" format="1"/>
+ </xsl:variable>
+ <xsl:attribute name="text:style-name">T<xsl:value-of select="$position + 1"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:apply-templates mode="dispatch"/>
+ </text:span>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- add this condition to prevent from printing the value of DATE, TIME, PRINTDATE, CREATEDATE, SAVEDATE, PAGE, NUMPAGES, etc. fields in-between w:fldchar begin and w:fldchar end G.Yang.-->
+ <xsl:if test="not( preceding-sibling::w:r/w:instrText[substring(normalize-space(.),1,4) = 'DATE' or substring(normalize-space(.),1,4) = 'TIME' or substring(normalize-space(.),1,9) = 'PRINTDATE' or substring(normalize-space(.),1,10) = 'CREATEDATE' or substring(normalize-space(.),1,8) = 'SAVEDATE' or substring(normalize-space(.),1,4) = 'PAGE' or substring(normalize-space(.),1,8) = 'NUMPAGES' or substring(normalize-space(.),1,8) = 'NUMWORDS' or substring(normalize-space(.),1,8) = 'NUMCHARS' or substring(normalize-space(.),1,6) = 'REVNUM' or substring(normalize-space(.),1,7) = 'AUTONUM' or substring(normalize-space(.),1,10) = 'AUTONUMLGL' or substring(normalize-space(.),1,10) = 'AUTONUMOUT' or substring(normalize-space(.),1,3) = 'SEQ' or substring(normalize-space(.),1,6) = 'AUTHOR' or substring(normalize-space(.),1,5) = 'TITLE' or substring(normalize-space(.),1,7) = 'SUBJECT' or substring(normalize-space(.),1,8) = 'KEYWORDS' or substring(normalize-space(.),1,6) = 'FILLIN' or substring(normalize-space(.),1,11) = 'DOCPROPERTY' or substring(normalize-space(.),1,10) = 'MERGEFIELD' or substring(normalize-space(.),1,8) = 'MERGEREC' or substring(normalize-space(.),1,4) = 'NEXT' or substring( normalize-space(.),1,9) = 'HYPERLINK' or substring( normalize-space(.),1,3) = 'REF' ][1] and (following-sibling::w:r/w:fldChar[@w:fldCharType='end'] or ( not(preceding-sibling::w:r/w:fldChar[@w:fldCharType='end'] ) and parent::w:p/following-sibling::w:p/w:r/w:fldChar[@w:fldCharType='end'])) )">
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="aml:annotation">
+ <xsl:choose>
+ <xsl:when test="@w:type = 'Word.Bookmark.Start'">
+ <text:bookmark-start text:name="{@w:name}"/>
+ </xsl:when>
+ <xsl:when test="@w:type = 'Word.Bookmark.End'">
+ <xsl:variable name="id" select="@aml:id"/>
+ <text:bookmark-end text:name="{preceding::aml:annotation[@aml:id = $id]/@w:name}"/>
+ </xsl:when>
+ <xsl:when test="@w:type = 'Word.Comment'">
+ <office:annotation office:display="true">
+ <dc:creator>
+ <xsl:value-of select="@aml:author"/>
+ </dc:creator>
+ <dc:date>
+ <xsl:value-of select="substring(@aml:createdate,1,10)"/>
+ </dc:date>
+ <xsl:apply-templates select="aml:content/w:p"/>
+ </office:annotation>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="w:hlink">
+ <xsl:element name="text:a">
+ <xsl:attribute name="xlink:type">simple</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test="@w:dest and @w:bookmark">
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="concat( @w:dest, concat('#', @w:bookmark) )"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@w:dest">
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="@w:dest"/>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:when test="@w:bookmark">
+ <xsl:attribute name="xlink:href">
+ <xsl:value-of select="concat('#', @w:bookmark)"/>
+ </xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ <xsl:if test="@w:target">
+ <xsl:attribute name="office:target-frame-name">
+ <xsl:value-of select="@w:target"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates mode="dispatch"/>
+ </xsl:element>
+ </xsl:template>
+ <xsl:template match="w:t">
+ <xsl:choose>
+ <xsl:when test="string(.) = ' ' ">
+ <xsl:element name="text:s"/>
+ </xsl:when>
+ <xsl:when test="contains(.,' ')">
+ <xsl:call-template name="replace-spaces">
+ <xsl:with-param name="curr-string" select="."/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template name="replace-spaces">
+ <xsl:param name="curr-string"/>
+ <xsl:if test="contains($curr-string,' ')">
+ <xsl:value-of select="substring-before($curr-string,' ')"/>
+ <text:s text:c="2"/>
+ <xsl:variable name="next-string" select="substring-after($curr-string,' ')"/>
+ <xsl:choose>
+ <xsl:when test="contains($next-string, ' ')">
+ <xsl:call-template name="replace-spaces">
+ <xsl:with-param name="curr-string" select="$next-string"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$next-string"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:tab">
+ <xsl:element name="text:tab"/>
+ </xsl:template>
+ <xsl:template match="w:br">
+ <xsl:if test="@w:type='text-wrapping' or not(@w:type)">
+ <text:line-break/>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="w:footnote">
+ <xsl:variable name="footnote-position">
+ <xsl:number from="/w:wordDocument/w:body" count="w:footnote" level="any"/>
+ </xsl:variable>
+ <text:note text:note-class="footnote" text:id="ftn{$footnote-position}">
+ <text:note-citation/>
+ <text:note-body>
+ <xsl:apply-templates mode="dispatch"/>
+ </text:note-body>
+ </text:note>
+ </xsl:template>
+ <xsl:template match="w:endnote">
+ <xsl:variable name="endnote-position">
+ <xsl:number from="/w:wordDocument/w:body" count="w:endnote" level="any" format="1"/>
+ </xsl:variable>
+ <text:endnote text:id="edn{$endnote-position}">
+ <text:endnote-body>
+ <xsl:apply-templates mode="dispatch"/>
+ </text:endnote-body>
+ </text:endnote>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/body.xsl b/filter/source/xslt/odf2xhtml/export/common/body.xsl
new file mode 100644
index 000000000..bcad3abd9
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/common/body.xsl
@@ -0,0 +1,428 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://xml.apache.org/xslt/java" xmlns:urlencoder="http://www.jclark.com/xt/java/java.net.URLEncoder" exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi java urlencoder">
+
+
+ <xsl:include href="table_of_content.xsl"/>
+
+
+ <!-- ****************** -->
+ <!-- *** Whitespace *** -->
+ <!-- ****************** -->
+
+ <xsl:template match="text:s">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="@text:c"/>
+ </xsl:call-template>
+ </xsl:template>
+
+
+ <!--write the number of 'whitespaces' -->
+ <xsl:template name="write-breakable-whitespace">
+ <xsl:param name="whitespaces"/>
+
+ <!--write two space chars as the normal white space character will be stripped
+ and the other is able to break -->
+ <xsl:text>&#160;</xsl:text>
+ <xsl:if test="$whitespaces >= 2">
+ <xsl:call-template name="write-breakable-whitespace-2">
+ <xsl:with-param name="whitespaces" select="$whitespaces - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+
+ <!--write the number of 'whitespaces' -->
+ <xsl:template name="write-breakable-whitespace-2">
+ <xsl:param name="whitespaces"/>
+ <!--write two space chars as the normal white space character will be stripped
+ and the other is able to break -->
+ <xsl:text> </xsl:text>
+ <xsl:if test="$whitespaces >= 2">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="$whitespaces - 1"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- currentSolution: 8 non-breakable-spaces instead of a TAB is an approximation.
+ Sometimes less spaces than 8 might be needed and the output might be more difficult to read-->
+ <xsl:template match="text:tab">
+ <xsl:param name="globalData"/>
+
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="8"/>
+ </xsl:call-template>
+ </xsl:template>
+
+
+
+ <!-- *************** -->
+ <!-- *** Textbox *** -->
+ <!-- *************** -->
+
+ <!-- ID / NAME of text-box -->
+ <xsl:template match="@draw:name">
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="number(substring(.,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(., '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(., '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:template>
+
+
+ <xsl:template match="text:line-break">
+ <xsl:param name="listIndent"/>
+
+ <xsl:element namespace="{$namespace}" name="br"/>
+
+ <!-- line breaks in lists need an indent similar to the list label -->
+ <xsl:if test="$listIndent">
+ <xsl:element namespace="{$namespace}" name="span">
+ <!-- some locales use , instead of . so replace it -->
+ <xsl:attribute name="style">margin-left:<xsl:value-of select="translate($listIndent, ',', '.')"/>cm</xsl:attribute>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+
+ <!-- currently there have to be an explicit call of the style attribute nodes, maybe the attributes nodes have no priority only order relevant-->
+ <xsl:template name="apply-styles-and-content">
+ <xsl:param name="globalData"/>
+ <xsl:param name="footnotePrefix" />
+ <xsl:apply-templates select="@*">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ <!-- the footnote symbol is the prefix for a footnote in the footer -->
+ <xsl:copy-of select="$footnotePrefix"/>
+ <xsl:apply-templates select="node()">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <!-- ******************* -->
+ <!-- *** References *** -->
+ <!-- ******************* -->
+
+ <xsl:template match="text:reference-ref | text:sequence-ref | text:bookmark-ref">
+ <xsl:param name="globalData"/>
+ <xsl:if test="*|text()">
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:attribute name="href">
+ <xsl:text>#</xsl:text>
+ <xsl:choose>
+ <xsl:when test="number(substring(@text:ref-name,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(@text:ref-name, '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(@text:ref-name, '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <xsl:apply-templates select="@* | node()">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="@text:name">
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="number(substring(.,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(., '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(., '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:template>
+
+ <xsl:template match="text:sequence">
+ <xsl:param name="globalData"/>
+
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:apply-templates select="@*" />
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="number(substring(@text:ref-name,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(@text:ref-name, '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(@text:ref-name, '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="text:reference-mark">
+ <xsl:param name="globalData"/>
+
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:apply-templates select="@*" />
+ <xsl:attribute name="id">
+ <xsl:choose>
+ <xsl:when test="number(substring(@text:name,1,1))">
+ <!-- Heuristic: If the first character is a number a 'a_' will be set
+ as prefix, as id have to be of type NMTOKEN -->
+ <xsl:value-of select="concat('a_',translate(@text:name, '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________'))"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="translate(@text:name, '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________')"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ </xsl:element>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <xsl:template match="text:reference-mark-start">
+ <xsl:param name="globalData"/>
+
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:apply-templates select="@*" />
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:bibliography-mark">
+ <xsl:param name="globalData"/>
+
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:apply-templates select="@* | node()">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- @text:title exist only in text:bibliography-mark -->
+ <xsl:template match="@text:title">
+ <xsl:attribute name="title">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <!-- @text:url exist only in text:bibliography-mark -->
+ <xsl:template match="@text:url">
+ <xsl:attribute name="href">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <xsl:template match="text:user-defined">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="office:annotation">
+ <xsl:element name="span">
+ <xsl:attribute name="title">annotation</xsl:attribute>
+ <xsl:attribute name="class">annotation_style_by_filter</xsl:attribute>
+ <xsl:apply-templates select="@*" />
+ <br/>
+ <xsl:text>[ANNOTATION:</xsl:text>
+ <br/>
+ <xsl:apply-templates select="*" mode="annotation"/>
+ <xsl:text>]</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:p" mode="annotation">
+ <br/>
+ <xsl:element name="span">
+ <xsl:text>NOTE: '</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>'</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="dc:creator" mode="annotation">
+ <br/>
+ <xsl:element name="span">
+ <xsl:attribute name="title">dc:creator</xsl:attribute>
+ <xsl:text>BY '</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>'</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="dc:date" mode="annotation">
+ <br/>
+ <xsl:element name="span">
+ <xsl:attribute name="title">dc:date</xsl:attribute>
+ <xsl:text>ON '</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>'</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="meta:date-string" mode="annotation">
+ <br/>
+ <xsl:element name="span">
+ <xsl:attribute name="title">meta-date-string</xsl:attribute>
+ <xsl:text>META DATE '</xsl:text>
+ <xsl:apply-templates />
+ <xsl:text>'</xsl:text>
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- *************** -->
+ <!-- *** HELPER *** -->
+ <!-- *************** -->
+
+
+ <xsl:template name="create-href">
+ <xsl:param name="href"/>
+ <xsl:param name="mimetype"/>
+
+ <xsl:choose>
+ <!-- internal OOo URL used in content tables -->
+ <xsl:when test="contains($href, '%7Coutline') or contains($href, '|outline')">
+ <!-- the simplest workaround for content tables in a single document is to create an anchor from every heading element.
+ Downside: multiple identical headings won't refer always to the first.
+ -->
+ <xsl:text>#</xsl:text>
+ <xsl:variable name="title">
+ <xsl:apply-templates mode="concatenate"/>
+ </xsl:variable>
+
+ <xsl:value-of select="concat('a_', translate(normalize-space($title), '.,;: %()[]/\+', '_____________'))"/>
+ </xsl:when>
+ <xsl:when test="self::draw:image[office:binary-data]">
+ <xsl:choose>
+ <xsl:when test="$mimetype">
+ <xsl:text>data:</xsl:text><xsl:value-of select="$mimetype"/><xsl:text>;base64,</xsl:text><xsl:value-of select="office:binary-data"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>data:image/*;base64,</xsl:text><xsl:value-of select="office:binary-data"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- in case of packed open office document -->
+ <xsl:when test="starts-with($sourceBaseURL, 'jar:') or $isPackageFormat">
+ <xsl:choose>
+ <!-- for images relative to open office document -->
+ <xsl:when test="starts-with($href, '../')">
+ <!-- creating an absolute http URL to the packed image file (removing the '.')-->
+ <xsl:value-of select="concat(substring-after(substring-before($sourceBaseURL, '!'), 'jar:'), '/', $href, $optionalURLSuffix)"/>
+ </xsl:when>
+ <!-- for absolute URLs & absolute paths -->
+ <xsl:when test="contains($href, ':') or starts-with($href, '/')">
+ <xsl:value-of select="concat($href, $optionalURLSuffix)"/>
+ </xsl:when>
+ <!-- for images jared in open office document -->
+ <xsl:otherwise>
+ <xsl:value-of select="concat($sourceBaseURL, $href, $optionalURLSuffix)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- for absolute URLs & Paths -->
+ <xsl:when test="contains($href, ':') or starts-with($href, '/')">
+ <xsl:value-of select="concat($href, $optionalURLSuffix)"/>
+ </xsl:when>
+ <!-- for relative URLs -->
+ <xsl:when test="starts-with($href, '#')">
+ <!-- intra document ref -->
+ <xsl:value-of select="$href"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($sourceBaseURL, $href, $optionalURLSuffix)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+ <xsl:template match="text()" mode="concatenate">
+ <xsl:value-of select="."/>
+ </xsl:template>
+ <xsl:template match="*" mode="concatenate">
+ <xsl:apply-templates mode="concatenate"/>
+ </xsl:template>
+
+
+ <!-- ******************** -->
+ <!-- *** Common Rules *** -->
+ <!-- ******************** -->
+
+ <!-- ignore / neglect the following elements -->
+ <xsl:template match="draw:custom-shape | draw:g | office:forms | text:alphabetical-index-mark | text:alphabetical-index-mark-end | text:alphabetical-index-mark-start | text:bibliography-source | text:number | text:reference-mark-end | text:sequence-decls | text:soft-page-break | text:table-of-content-source | text:tracked-changes | text:user-field-decls"/>
+
+ <!-- default template used by purpose-->
+ <xsl:template match="text:bibliography | text:change-end | text:change-start">
+ <xsl:param name="globalData"/>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- default template for not recognized elements -->
+ <xsl:template match="*">
+ <xsl:param name="globalData"/>
+ <xsl:message>Using default element rule for ODF element '<xsl:value-of select="name()"/>'.</xsl:message>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="@*"/>
+
+ <!-- allowing all matched text nodes -->
+ <xsl:template match="text()">
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl b/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl
new file mode 100644
index 000000000..bac0c5963
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/common/styles/style_collector.xsl
@@ -0,0 +1,832 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xforms="http://www.w3.org/2002/xforms"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xt="http://www.jclark.com/xt"
+ xmlns:common="http://exslt.org/common"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan">
+
+
+
+ <!-- ***************************************** -->
+ <!-- *** Gathering office style properties *** -->
+ <!-- ***************************************** -->
+
+ <!-- REASON FOR STYLESHEET:
+ In the OpenOffice documents styles are represented by a hierarchy.
+ (e.g. most styles are inherited from a default style).
+ Many other languages (as XHTML/CSS) do not support inherited styles.
+ The style inheritance have to be made flat/absolute for each style.
+
+ A further reason was, that the earlier style collection mechanism
+ had problems with CSS inline, which do not inherit from XML office defaults
+ nor font:family defaults as the style header does
+ (cp. stylesheet 'style_collector.xsl' and the 'write-default-styles' template)
+
+ RESULT OF STYLESHEET:
+ All styles will be returned in a variable containing styles with their inherited *:
+
+ <all-styles>
+ <style style:family="foo" style:name="x1">
+ <* fo:padding-left="0cm" fo:margin-right="0cm" />
+ </style>
+ <style style:family="muh" style:name="x2" >
+ <* fo:padding-left="3cm" ... />
+ </style>
+ ...
+
+ </all-styles>
+ -->
+
+
+ <xsl:template name="collect-global-odf-properties">
+ <!-- to access the variable as a node-set by XPATH expressions, it is necessary to convert it
+ from a result-tree-fragment (RTF) to a node set by a in a XSLT 1.0 non standardized function -->
+ <xsl:variable name="globalDataRTF">
+ <xsl:call-template name="collect-document-links-RTF" />
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="collect-style-properties">
+ <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="collect-style-properties">
+ <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="collect-style-properties">
+ <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+
+ <xsl:template name="collect-style-properties">
+ <xsl:param name="globalData" />
+
+ <!-- Add the input file references to the new collected style properties -->
+ <xsl:variable name="globalDataRTF">
+ <xsl:copy-of select="$globalData" />
+ <xsl:call-template name="collect-style-properties-RTF">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="map-odf-style-properties">
+ <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="map-odf-style-properties">
+ <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="map-odf-style-properties">
+ <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="collect-document-links-RTF">
+ <!-- works for zipped office files, unzipped office files as for flat filter single office file format as well -->
+ <xsl:variable name="documentLinksRTF">
+ <xsl:choose>
+ <xsl:when test="office:document-content">
+ <xsl:element name="styles-file" namespace="">
+ <xsl:copy-of select="document(concat($sourceBaseURL, 'styles.xml'), .)" />
+ </xsl:element>
+ <xsl:element name="meta-file" namespace="">
+ <xsl:copy-of select="document(concat($sourceBaseURL, 'meta.xml'), .)" />
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="styles-file" namespace="">
+ <xsl:copy-of select="/" />
+ </xsl:element>
+ <xsl:element name="meta-file" namespace="">
+ <xsl:copy-of select="/" />
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="collect-document-links">
+ <xsl:with-param name="documentLinks" select="common:node-set($documentLinksRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="collect-document-links">
+ <xsl:with-param name="documentLinks" select="xalan:nodeset($documentLinksRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="collect-document-links">
+ <xsl:with-param name="documentLinks" select="xt:node-set($documentLinksRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+
+ <xsl:template name="collect-document-links">
+ <xsl:param name="documentLinks" />
+
+ <xsl:element name="styles-file" namespace="">
+ <xsl:copy-of select="$documentLinks/styles-file/*" />
+ </xsl:element>
+
+ <xsl:element name="meta-file" namespace="">
+ <xsl:copy-of select="$documentLinks/meta-file/*" />
+ </xsl:element>
+
+ <xsl:copy-of select="$documentLinks/styles-file/*/office:styles" />
+ <xsl:copy-of select="$documentLinks/styles-file/*/office:font-face-decls" />
+
+ <!-- office:automatic-styles may be contained in two files (i.e. content.xml and styles.xml).
+ Wild card necessary as top level element differs from flat office files ("SampleName.fsxw") -->
+ <xsl:copy-of select="/*/office:automatic-styles" />
+
+ </xsl:template>
+
+
+ <xsl:template name="collect-style-properties-RTF">
+ <xsl:param name="globalData" />
+
+ <!--** DEFAULT STYLES: First adding some office defaults unwritten in XML -->
+ <xsl:variable name="defaultOfficeStyle-RTF">
+ <xsl:element name="style" namespace="">
+ <xsl:element name="style:properties" />
+ </xsl:element>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="collect-properties-defaults">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="defaultOfficeStyle" select="common:node-set($defaultOfficeStyle-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="collect-properties-defaults">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="defaultOfficeStyle" select="xalan:nodeset($defaultOfficeStyle-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="collect-properties-defaults">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="defaultOfficeStyle" select="xt:node-set($defaultOfficeStyle-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">ERROR: Function not found: 'Nodeset'</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="collect-properties-defaults">
+ <xsl:param name="globalData" />
+ <xsl:param name="defaultOfficeStyle" />
+
+ <!--** DEFAULT STYLES: Adding the default styles of a style:family, by adding each office:styles/style:default-style element **-->
+ <xsl:variable name="defaultFamilyStyles-RTF">
+ <xsl:for-each select="$globalData/office:styles/style:default-style">
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="@style:family" />
+ <xsl:call-template name="create-inherited-style-properties">
+ <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="collect-properties">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" />
+ <xsl:with-param name="defaultFamilyStyles" select="common:node-set($defaultFamilyStyles-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="collect-properties">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" />
+ <xsl:with-param name="defaultFamilyStyles" select="xalan:nodeset($defaultFamilyStyles-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="collect-properties">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="defaultOfficeStyle" select="$defaultOfficeStyle" />
+ <xsl:with-param name="defaultFamilyStyles" select="xt:node-set($defaultFamilyStyles-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="collect-properties">
+ <xsl:param name="globalData" />
+ <xsl:param name="defaultOfficeStyle" />
+ <xsl:param name="defaultFamilyStyles" />
+
+ <!--** traversee all style trees - branch after branch - collecting style properties **-->
+ <xsl:element name="all-doc-styles" namespace="">
+
+ <!-- Background Information:
+
+ There are two different types of styles in the Office:
+ 1) The office:styles from the user pre-defined style templates
+ 2) The automatic:styles, which are created whenever a user uses explicit style formatting.
+
+ The office:styles only have parent styles in the office:styles,
+ but automatic:styles may inherit from both office:styles and themself.
+ -->
+
+ <!--** traversee all office:styles trees beginning with the top-level styles **-->
+ <xsl:for-each select="$globalData/office:styles/style:style[not(@style:parent-style-name)]">
+ <!-- Looking for parents from style:family
+ <xsl:for-each select="$globalData/office:styles/style:style[@style:family=current()/@style:family][not(@style:parent-style-name)]"> -->
+ <xsl:choose>
+ <xsl:when test="$defaultFamilyStyles/style[@style:family=current()/@style:family]">
+ <xsl:call-template name="inherit-style-for-self-and-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="inheritedStyleProperties" select="$defaultFamilyStyles/style[@style:family=current()/@style:family]/*" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="inherit-style-for-self-and-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!--** creates a style element with style:name and style:family attribute and
+ an element representing the absolute style properties style:property ** -->
+ </xsl:for-each>
+
+ <!--** traversee all office:automatic-styles trees beginning with the top-level styles **-->
+ <xsl:for-each select="$globalData/office:automatic-styles/style:style[not(@style:parent-style-name)]">
+ <!--** creates a style element with style:name and style:family attribute and
+ an element representing the absolute style properties style:property ** -->
+ <xsl:choose>
+ <xsl:when test="$defaultFamilyStyles/style[@style:family=current()/@style:family]">
+ <xsl:call-template name="inherit-style-for-self-and-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="inheritedStyleProperties" select="$defaultFamilyStyles/style[@style:family=current()/@style:family]/*" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="inherit-style-for-self-and-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="inheritedStyleProperties" select="$defaultOfficeStyle/style/*" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:for-each>
+
+ </xsl:element>
+ <!-- debug output in case only styles should be given out (regression test) -->
+ <xsl:if test="$onlyStyleOutputEnabled">
+ <xsl:element name="defaultOfficeStyle" namespace="">
+ <xsl:copy-of select="$defaultOfficeStyle" />
+ </xsl:element>
+ <xsl:element name="defaultFamilyStyles" namespace="">
+ <xsl:copy-of select="$defaultFamilyStyles" />
+ </xsl:element>
+ </xsl:if>
+
+ </xsl:template>
+
+
+ <xsl:template name="inherit-style-for-self-and-children">
+ <xsl:param name="globalData" />
+ <xsl:param name="inheritedStyleProperties" />
+ <xsl:param name="searchOnlyInAutomaticStyles" />
+
+ <!--** create an absolute style by inheriting properties from the given parent properties **-->
+ <xsl:variable name="newStyleProperties-RTF">
+ <xsl:call-template name="create-inherited-style-properties">
+ <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" />
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:variable name="newStyleProperties" select="common:node-set($newStyleProperties-RTF)" />
+
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="@style:family" />
+ <xsl:copy-of select="@style:name" />
+ <xsl:copy-of select="$newStyleProperties" />
+ </xsl:element>
+
+ <xsl:choose>
+ <xsl:when test="$searchOnlyInAutomaticStyles">
+ <xsl:call-template name="get-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
+ <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!--** for all automatic-children of the current office:styles **-->
+ <xsl:call-template name="get-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
+ <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:variable name="newStyleProperties" select="xalan:nodeset($newStyleProperties-RTF)" />
+
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="@style:family" />
+ <xsl:copy-of select="@style:name" />
+ <xsl:copy-of select="$newStyleProperties" />
+ </xsl:element>
+
+ <xsl:choose>
+ <xsl:when test="$searchOnlyInAutomaticStyles">
+ <xsl:call-template name="get-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
+ <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!--** for all automatic-children of the current office:styles **-->
+ <xsl:call-template name="get-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
+ <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:variable name="newStyleProperties" select="xt:node-set($newStyleProperties-RTF)" />
+
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="@style:family" />
+ <xsl:copy-of select="@style:name" />
+ <xsl:copy-of select="$newStyleProperties" />
+ </xsl:element>
+
+ <xsl:choose>
+ <xsl:when test="$searchOnlyInAutomaticStyles">
+ <xsl:call-template name="get-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="true()" />
+ <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!--** for all automatic-children of the current office:styles **-->
+ <xsl:call-template name="get-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="false()" />
+ <xsl:with-param name="inheritedStyleProperties" select="$newStyleProperties/*" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="get-children">
+ <xsl:param name="globalData" />
+ <xsl:param name="searchOnlyInAutomaticStyles" />
+ <xsl:param name="inheritedStyleProperties" select="*" />
+
+<!-- QUESTION: Parent style is only unique by name and family, but what about cross family inheritance? -->
+ <!-- For each child style (that is every style which has the given parentStyleName as style:parent-style-name and the same style:family -->
+ <xsl:variable name="parentStyleFamily" select="@style:family" />
+ <xsl:variable name="parentStyleName" select="@style:name" />
+ <xsl:if test="not($searchOnlyInAutomaticStyles)">
+ <xsl:for-each select="$globalData/office:styles/style:style[@style:family=$parentStyleFamily and @style:parent-style-name=$parentStyleName]">
+ <xsl:call-template name="inherit-style-for-self-and-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="$searchOnlyInAutomaticStyles" />
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:if>
+ <xsl:for-each select="$globalData/office:automatic-styles/style:style[@style:family=$parentStyleFamily and @style:parent-style-name=$parentStyleName]">
+ <xsl:call-template name="inherit-style-for-self-and-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="inheritedStyleProperties" select="$inheritedStyleProperties" />
+ <xsl:with-param name="searchOnlyInAutomaticStyles" select="$searchOnlyInAutomaticStyles" />
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+
+
+ <xsl:template name="create-inherited-style-properties">
+ <xsl:param name="inheritedStyleProperties" />
+
+ <xsl:element name="style:properties">
+ <!-- Writing all inherited style properties -->
+ <xsl:for-each select="$inheritedStyleProperties/@*">
+ <xsl:sort select="name()" />
+ <xsl:copy-of select="." />
+ </xsl:for-each>
+
+ <!-- split border into border parts for better activation-check on style:joint-border feature -->
+ <xsl:if test="*/@fo:border">
+ <xsl:attribute name="fo:border-top"><xsl:value-of select="*/@fo:border"/></xsl:attribute>
+ <xsl:attribute name="fo:border-left"><xsl:value-of select="*/@fo:border"/></xsl:attribute>
+ <xsl:attribute name="fo:border-bottom"><xsl:value-of select="*/@fo:border"/></xsl:attribute>
+ <xsl:attribute name="fo:border-right"><xsl:value-of select="*/@fo:border"/></xsl:attribute>
+ </xsl:if>
+
+ <!--All current attributes will override already inserted attributes of the same name
+ XSLT Spec: "Adding an attribute to an element replaces any existing attribute of that element with the same expanded-name." -->
+ <xsl:for-each select="*/@*[name() != 'style:font-size-rel'][name() != 'fo:border']">
+ <xsl:copy-of select="." />
+ </xsl:for-each>
+
+ <xsl:if test="*/@style:font-size-rel">
+<!--
+ The intheritedStyleProperties should include an absolute Font Size, but
+ <style:properties
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ style:font-name="Courier New"
+ fo:language="en"
+ fo:country="US"
+ style:font-name-asian=Courier New"
+ style:font-name-complex="Courier New"/>
+-->
+ <xsl:variable name="fontSizeAbsolute">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="$inheritedStyleProperties/@fo:font-size" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:variable name="fontSizeRelative">
+ <xsl:call-template name="convert2pt">
+ <xsl:with-param name="value" select="*/@style:font-size-rel" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:attribute name="fo:font-size">
+ <xsl:value-of select="$fontSizeAbsolute + $fontSizeRelative"/>
+ <xsl:text>pt</xsl:text>
+ </xsl:attribute>
+ </xsl:if>
+
+ <!-- providing tabulator indentation -->
+ <xsl:copy-of select="$inheritedStyleProperties/style:tab-stops"/>
+ <xsl:copy-of select="*/style:tab-stops"/>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- debugging & testing purpose -->
+ <xsl:template name="write-collected-styles">
+ <xsl:param name="globalData" />
+
+ <xsl:message>&lt;all-doc-styles&gt;</xsl:message>
+ <xsl:for-each select="$globalData/all-doc-styles/style">
+ <xsl:message>&lt;style</xsl:message>
+ <xsl:message>style:family="<xsl:value-of select="current()/@style:family" />"&gt;</xsl:message>
+ <xsl:message>style:name="<xsl:value-of select="current()/@style:name" />" </xsl:message>
+ <xsl:message> &lt;*</xsl:message>
+ <xsl:for-each select="*/@*">
+ <xsl:message>
+ <xsl:text></xsl:text>
+ <xsl:value-of select="name()" />="<xsl:value-of select="." />"</xsl:message>
+ </xsl:for-each>
+ <xsl:message>/&gt;</xsl:message>
+ <xsl:message>&lt;/style&gt;</xsl:message>
+ </xsl:for-each>
+ <xsl:message>&lt;/all-doc-styles&gt;</xsl:message>
+ </xsl:template>
+
+ <xsl:template name="map-odf-style-properties">
+ <xsl:param name="globalData" />
+
+ <xsl:choose>
+ <!--+++++ DEBUG STYLE OUTPUT FOR REGRESSION TEST +++++-->
+ <!-- create styles file from the style variable (testing switch) -->
+ <xsl:when test="$onlyStyleOutputEnabled">
+
+ <xsl:element name="debug-output" namespace="">
+ <xsl:copy-of select="$globalData" />
+ <xsl:call-template name="map-odf-properties">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+
+ <!-- create XHTML file -->
+ <xsl:otherwise>
+ <!-- to access the variable like a node-set it is necessary to convert it
+ from a result-tree-fragment (RTF) to a node set using the James Clark extension -->
+ <xsl:variable name="globalDataRTF">
+ <!-- raw properties still needed for table width attribute creation -->
+ <xsl:copy-of select="$globalData" />
+ <xsl:call-template name="map-odf-properties">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="start-main">
+ <xsl:with-param name="globalData" select="common:node-set($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="start-main">
+ <xsl:with-param name="globalData" select="xalan:nodeset($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="start-main">
+ <xsl:with-param name="globalData" select="xt:node-set($globalDataRTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- REASON FOR TEMPLATE:
+ The OpenOffice style properties gathered in the variable 'globalData' have to be mapped to the CSS style format
+ -->
+ <xsl:template name="map-odf-properties">
+ <xsl:param name="globalData" />
+ <xsl:element name="all-styles" namespace="">
+ <xsl:for-each select="$globalData/all-doc-styles/style">
+ <xsl:sort select="@style:family" />
+ <xsl:sort select="@style:name" />
+
+ <xsl:call-template name="writeUsedStyles">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="style" select="."/>
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:key name="elementUsingStyle" match="*" use="@text:style-name | @draw:style-name | @draw:text-style-name | @table:style-name | @table:default-cell-style-name"/>
+ <xsl:key name="listLabelStyleInStyles" match="/*/office:styles/text:list-style/* |
+ /*/office:styles/style:graphic-properties/text:list-style/*" use="@text:style-name"/>
+
+ <xsl:key name="listLabelStyleInContent" match="/*/office:automatic-styles/text:list-style/* | /*/office:automatic-styles/style:graphic-properties/text:list-style/*" use="@text:style-name"/>
+
+
+ <xsl:variable name="documentRoot" select="/" />
+ <xsl:template name="writeUsedStyles">
+ <xsl:param name="globalData" />
+ <xsl:param name="style"/>
+
+ <!-- for-each changes the key environment from the previously globalData back to the document root -->
+ <xsl:for-each select="$documentRoot">
+ <!-- only styles, which are used in the content are written as CSS styles -->
+ <xsl:choose>
+ <xsl:when test="key('elementUsingStyle', $style/@style:name)/@* or key('listLabelStyleInContent', $style/@style:name)/@*">
+ <xsl:call-template name="writeUsedStyles2">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="style" select="$style" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="not(office:document-content)">
+ <xsl:if test="key('listLabelStyleInStyles', $style/@style:name)/@* or /*/office:styles/text:notes-configuration[@text:citation-style-name = $style/@style:name or /*/office:styles/@text:citation-body-style-name=$style/@style:name]">
+ <!-- if there are consecutive paragraphs with borders (OR background AND margin ), only the first and the last have the top/bottom border
+ unless style:join-border="false" -->
+ <xsl:call-template name="writeUsedStyles2">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="style" select="$style" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:for-each select="document($stylesFileURL)">
+ <xsl:if test="key('listLabelStyleInStyles', $style/@style:name)/@* or /*/office:styles/text:notes-configuration[@text:citation-style-name = $style/@style:name or /*/office:styles/@text:citation-body-style-name=$style/@style:name]">
+ <!-- if there are consecutive paragraphs with borders (OR background AND margin ), only the first and the last have the top/bottom border
+ unless style:join-border="false" -->
+ <xsl:call-template name="writeUsedStyles2">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="style" select="$style" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="writeUsedStyles2">
+ <xsl:param name="globalData" />
+ <xsl:param name="style"/>
+ <!-- activation-check on style:joint-border feature -->
+ <xsl:choose>
+ <xsl:when test="
+ $style/@style:family='paragraph'
+ and
+ (
+ $style/*/@fo:border-top
+ or
+ $style/*/@fo:border-bottom
+ )
+ and
+ (
+ not($style/*/@fo:border-top='none' and
+ $style/*/@fo:border-left='none' and
+ $style/*/@fo:border-right='none' and
+ $style/*/@fo:border-bottom='none')
+ )
+ and
+ (
+ not($style/*/@style:join-border)
+ or $style/*/@style:join-border = 'true'
+ )">
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="$style/@style:family" />
+ <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderStart')" /></xsl:attribute>
+ <xsl:element name="final-properties" namespace="">
+ <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-bottom')][not(name() = 'fo:padding-bottom')][not(name() = 'fo:margin-bottom')][not(name() = 'fo:margin')]">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-bottom' or name() = 'fo:margin']">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ <xsl:text> border-bottom-style:none; </xsl:text>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="$style/@style:family" />
+ <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderSides')" /></xsl:attribute>
+ <xsl:element name="final-properties" namespace="">
+ <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-top') and not(name() = 'fo:border-bottom')][not(name() = 'fo:padding-top') and not(name() = 'fo:padding-bottom')][not(name() = 'fo:margin-top') and not(name() = 'fo:margin-bottom')][not(name() = 'fo:margin')]">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-top' or name() = 'fo:margin-bottom' or name() = 'fo:margin']">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ <xsl:text> border-top-style:none; border-bottom-style:none; </xsl:text>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="$style/@style:family" />
+ <xsl:attribute name="style:name"><xsl:value-of select="concat($style/@style:name, '_borderEnd')" /></xsl:attribute>
+ <xsl:element name="final-properties" namespace="">
+ <xsl:apply-templates select="$style/*/@*[not(name() = 'fo:border-top')][not(name() = 'fo:padding-top')][not(name() = 'fo:margin-top')][not(name() = 'fo:margin')]">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ <xsl:apply-templates mode="paragraphMerge" select="$style/*/@*[name() = 'fo:margin-top' or name() = 'fo:margin']">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ <xsl:text> border-top-style:none;</xsl:text>
+ </xsl:element>
+ </xsl:element>
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="$style/@style:family" />
+ <xsl:copy-of select="$style/@style:name" />
+ <!-- the original name bears the trigger: 'mergedBorder' flag-->
+ <xsl:attribute name="mergedBorders"><xsl:value-of select="true()" /></xsl:attribute>
+ <xsl:element name="final-properties" namespace="">
+ <xsl:apply-templates select="$style/*/@*">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="not(key('listLabelStyleInStyles', $style/@style:name)/@*)">
+ <xsl:element name="style" namespace="">
+ <xsl:copy-of select="$style/@style:family" />
+ <xsl:copy-of select="$style/@style:name" />
+ <xsl:element name="final-properties" namespace="">
+ <xsl:apply-templates select="$style/*/@*">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="style" namespace="">
+ <xsl:attribute name="style:family">none</xsl:attribute>
+ <xsl:attribute name="style:name"><xsl:value-of select="$style/@style:name"/></xsl:attribute>
+ <xsl:element name="final-properties" namespace="">
+ <xsl:apply-templates select="$style/*/@*">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- workaround AOOO#119401 suspicious property fo:margin="100%" in paragraph style -->
+ <xsl:template match="@fo:margin[string(.) = '100%']" mode="paragraphMerge"/>
+
+ <xsl:template mode="paragraphMerge" match="@fo:margin | @fo:margin-top | @fo:margin-bottom | @fo:margin-left | @fo:margin-right">
+ <xsl:text>padding</xsl:text>
+ <xsl:value-of select="substring-after(name(), 'fo:margin')"/>
+ <xsl:text>:</xsl:text>
+ <!-- Map once erroneously used inch shortage 'inch' to CSS shortage 'in' -->
+ <xsl:choose>
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl b/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl
new file mode 100644
index 000000000..c81cc9a1e
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/common/styles/style_mapping_css.xsl
@@ -0,0 +1,380 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi">
+
+
+ <!-- *** Properties with a 'fo:' prefix *** -->
+ <xsl:template match="@fo:background-color">
+ <xsl:text>background-color:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@fo:border | @fo:border-top | @fo:border-bottom | @fo:border-left | @fo:border-right">
+ <xsl:variable name="borderType" select="substring-after(name(), ':')"/>
+ <xsl:choose>
+ <xsl:when test=". = 'none'">
+ <xsl:value-of select="$borderType"/>
+ <xsl:text>-style:none; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="borderWidth" select="substring-before(., ' ')"/>
+ <xsl:variable name="borderStyle" select="substring-before(substring-after(., ' '), ' ')"/>
+ <xsl:variable name="borderColor" select="substring-after(substring-after(., ' '), ' ')"/>
+
+ <!-- More information at template 'round-up-border-width' -->
+ <xsl:variable name="borderWidthFixed">
+ <xsl:call-template name="round-up-border-width">
+ <xsl:with-param name="borderWidth" select="$borderWidth"/>
+ <xsl:with-param name="multiplier">
+ <xsl:choose>
+ <xsl:when test="$borderStyle = 'double'">3</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:value-of select="$borderType"/>
+ <xsl:text>-width:</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$borderWidth = '0.05pt'">thin</xsl:when>
+ <xsl:otherwise><xsl:value-of select="$borderWidthFixed"/></xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ <xsl:value-of select="$borderType"/>
+ <xsl:text>-style:</xsl:text>
+ <xsl:value-of select="$borderStyle"/>
+ <xsl:text>; </xsl:text>
+ <xsl:value-of select="$borderType"/>
+ <xsl:text>-color:</xsl:text>
+ <xsl:value-of select="$borderColor"/>
+ <xsl:text>; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- NOTE: Still there have to be placed a <br clear='all' /> to disable the flow!!!!-->
+ <xsl:template match="@fo:clear">
+ <xsl:text>clear:both; </xsl:text>
+ </xsl:template>
+
+ <!-- text-shadow is a CSS2 feature and yet not common used in user-agents -->
+ <xsl:template match="@fo:color |@fo:font-size |@fo:font-style |@fo:font-weight |@fo:text-indent |@fo:text-shadow |@text:display">
+ <xsl:value-of select="substring-after(name(), ':')"/>
+ <xsl:text>:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <!-- text-shadow is a CSS2 feature and yet not common used in user-agents -->
+ <xsl:template match="@svg:font-family">
+ <xsl:value-of select="substring-after(name(), ':')"/>
+ <xsl:text>:"</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>"; </xsl:text>
+ </xsl:template>
+
+ <!-- workaround AOOO#119401 suspicious property fo:margin="100%" in paragraph style -->
+ <xsl:template match="@fo:margin[string(.) = '100%']"/>
+
+ <!-- Maps fo:margin as well fo:margin-top, fo:margin-bottom, fo:padding-left, fo:margin-right -->
+ <!-- Maps fo:padding as well fo:padding-top, fo:padding-bottom, fo:padding-left, fo:padding-right -->
+ <xsl:template match="@fo:letter-spacing | @fo:line-height | @fo:width |@fo:margin | @fo:margin-top | @fo:margin-bottom | @fo:margin-left | @fo:margin-right | @fo:padding | @fo:padding-top | @fo:padding-bottom | @fo:padding-left | @fo:padding-right">
+ <xsl:value-of select="local-name(.)"/>
+ <xsl:text>:</xsl:text>
+ <!-- Map once erroneously used inch shortage 'inch' to CSS shortage 'in' -->
+ <xsl:choose>
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@fo:text-align">
+ <!-- 'important' is necessary as table cell value alignment is decided by runtime over the valuetype
+ Otherwise a table cell style-class would always be outnumbered by the run-time alignment value -->
+ <xsl:choose>
+ <xsl:when test="contains(., 'start')">
+ <xsl:choose>
+ <xsl:when test="parent::*/@style:writing-mode and contains(parent::*/@style:writing-mode, 'rl')">
+ <xsl:text>text-align:right ! important; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>text-align:left ! important; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="contains(., 'end')">
+ <xsl:choose>
+ <xsl:when test="parent::*/@style:writing-mode and contains(parent::*/@style:writing-mode, 'rl')">
+ <xsl:text>text-align:right ! important;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>text-align:left ! important; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>text-align:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text> ! important; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="@style:vertical-align">
+ <xsl:choose>
+ <xsl:when test="contains(., 'bottom')">
+ <xsl:text>vertical-align:bottom; </xsl:text>
+ </xsl:when>
+ <xsl:when test="contains(., 'middle')">
+ <xsl:text>vertical-align:middle; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>vertical-align:top; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+<!-- *** Properties with a 'style:' prefix *** -->
+ <!-- NOTE: Can 'inside' | 'from-inside' better be handled:
+ <!ATTLIST * style:horizontal-pos (from-left|left|center|right|from-inside|inside|outside)#IMPLIED>-->
+ <xsl:template match="@style:horizontal-pos">
+ <xsl:choose>
+ <xsl:when test=".='left'">
+ <xsl:text>text-align:left; </xsl:text>
+ </xsl:when>
+ <xsl:when test=". = 'right'">
+ <xsl:text>text-align:right; </xsl:text>
+ </xsl:when>
+ <xsl:when test=".='center'">
+ <xsl:text>text-align:center; </xsl:text>
+ </xsl:when>
+ <!-- NOTE: currently other values are not used.
+ If the property value is from-left or from-inside,
+ the svg:x attribute associated with the frame element specifies
+ the horizontal position of the frame.
+ Otherwise the svg:x attribute is ignored for text documents.
+ -->
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="@style:column-width">
+ <xsl:text>width:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@style:text-underline-style">
+ <xsl:text>text-decoration:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test=".='none'">
+ <xsl:text>none ! important</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>underline</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@style:font-name">
+ <xsl:param name="globalData" />
+
+ <xsl:text>font-family:</xsl:text>
+ <xsl:variable name="content" select="."/>
+ <xsl:variable name="fontName" select="$globalData/office:font-face-decls/style:font-face[@style:name=$content]/@svg:font-family" />
+ <xsl:value-of select="$fontName"/>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@style:row-height">
+ <xsl:text>height:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+
+ <xsl:template match="@svg:strikethrough-position">
+ <xsl:if test="not(.='none')">
+ <xsl:text>text-decoration:line-through; </xsl:text>
+ </xsl:if>
+ </xsl:template>
+ <xsl:template match="@style:text-position">
+ <xsl:if test="contains(., 'sub')">
+ <xsl:text>vertical-align:sub; </xsl:text>
+ <xsl:if test="contains(., '%')">
+ <xsl:text>font-size:</xsl:text>
+ <xsl:value-of select="substring-after(., 'sub ')"/>
+ <xsl:text>;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ <xsl:if test="contains(., 'super')">
+ <xsl:text>vertical-align:super; </xsl:text>
+ <xsl:if test="contains(., '%')">
+ <xsl:text>font-size:</xsl:text>
+ <xsl:value-of select="substring-after(., 'super ')"/>
+ <xsl:text>;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="@style:vertical-pos">
+ <xsl:choose>
+ <xsl:when test=".='from-top'">
+ <xsl:text>vertical-align:top; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>vertical-align:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="@style:width">
+ <xsl:text>width:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test="contains(., 'inch')">
+ <xsl:value-of select="substring-before(.,'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>; </xsl:text>
+ </xsl:template>
+ <xsl:template match="@style:wrap">
+ <xsl:choose>
+ <xsl:when test=".='left'">
+ <xsl:text>float:right; </xsl:text>
+ </xsl:when>
+ <xsl:when test=".='right'">
+ <xsl:text>float:left; </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+ <xsl:template match="@style:writing-mode">
+ <xsl:text>writing-mode:</xsl:text>
+ <xsl:choose>
+ <xsl:when test=".='rl-tb'">
+ <xsl:text>horizontal-tb; direction:rtl; </xsl:text>
+ </xsl:when>
+ <xsl:when test=".='lr-tb'">
+ <xsl:text>horizontal-tb; direction:ltr; </xsl:text>
+ </xsl:when>
+ <xsl:when test=".='tb-rl'">
+ <xsl:text>vertical-rl; </xsl:text>
+ </xsl:when>
+ <xsl:when test=".='tb-lr'">
+ <xsl:text>vertical-lr; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>horizontal-tb; direction:ltr;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+ <!-- *** Properties with a no 'fo:' or 'style:' prefix *** -->
+ <xsl:template match="@table:align">
+ <xsl:choose>
+ <xsl:when test=".='left'">
+ <xsl:if test="not(../@fo:margin-left)">margin-left:0px; </xsl:if>
+ <xsl:text>margin-right:auto;</xsl:text></xsl:when>
+ <xsl:when test=".='right'">
+ <xsl:text>margin-left:auto</xsl:text>
+ <xsl:if test="not(../@fo:margin-right)">
+ ; margin-right: 0px;
+ </xsl:if>
+ </xsl:when>
+ <xsl:when test=".='center'">
+ margin-left:auto;margin-right:auto;
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>float:none; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="style:background-image">
+ <xsl:text>background-image:url(</xsl:text>
+ <xsl:value-of select="@xlink:href"/>
+ <xsl:text>); </xsl:text>
+ <xsl:choose>
+ <xsl:when test="@style:repeat = 'repeat'">
+ <xsl:text>background-repeat:repeat; </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>background-repeat:no-repeat; </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Changing border width measure to cm and enlarging border-width to the Mozilla browser(1.7)
+ visible minimum width
+ - 0.0133cm for solid style
+ - 0.0399cm for double style
+ as there are three border lines painted -->
+ <xsl:decimal-format name = "unifiedFormat" decimal-separator = "." />
+ <xsl:template name="round-up-border-width">
+ <xsl:param name="borderWidth"/>
+ <xsl:param name="multiplier"/>
+
+ <xsl:variable name="borderWidthByCentimeter">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$borderWidth"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="minimalBorderWidth" select="0.0133 * $multiplier"/>
+ <xsl:choose>
+ <xsl:when test="number($borderWidthByCentimeter) &lt; $minimalBorderWidth">
+ <xsl:value-of select="format-number($minimalBorderWidth,'0.######','unifiedFormat')"/>
+ <xsl:text>cm</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="format-number($borderWidthByCentimeter,'0.######','unifiedFormat')"/>
+ <xsl:text>cm</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/table/table.xsl b/filter/source/xslt/odf2xhtml/export/common/table/table.xsl
new file mode 100644
index 000000000..cfc1ebbc5
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/common/table/table.xsl
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xforms="http://www.w3.org/2002/xforms"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi">
+
+
+ <!-- table row handling -->
+ <xsl:include href="table_rows.xsl" />
+ <!-- table column handling -->
+ <xsl:include href="table_columns.xsl" />
+ <!-- table cell handling -->
+ <xsl:include href="table_cells.xsl" />
+
+ <xsl:param name="tableElement" select="'table'" />
+
+ <!-- ******************* -->
+ <!-- *** main table *** -->
+ <!-- ******************* -->
+
+
+ <xsl:template match="table:table" name="table:table">
+ <xsl:param name="globalData" />
+
+ <!-- The table will only be created if the table:scenario is active -->
+ <xsl:if test="not(table:scenario) or table:scenario/@table:is-active">
+ <xsl:call-template name="create-table">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+
+
+ <xsl:template name="create-table">
+ <xsl:param name="globalData" />
+
+ <!-- by default '1', for each new sub/inner/nested table the number counts one up -->
+ <xsl:variable name="tableLevel" select="count(ancestor-or-self::table:table)" />
+ <!-- collecting all visible "table:table-row" elements of the table -->
+ <xsl:variable name="allVisibleTableRows" select="table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')][count(ancestor-or-self::table:table) = $tableLevel] |
+ table:table-header-rows/descendant::table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')][count(ancestor-or-self::table:table) = $tableLevel] |
+ table:table-row-group/descendant::table:table-row[not(@table:visibility = 'collapse' or @table:visibility = 'filter')][count(ancestor-or-self::table:table) = $tableLevel]" />
+ <!-- As the alignment of a table is by 'align' attribute is deprecated and as the CSS 'float' attribute not well displayed,
+ we do a trick by encapsulating the table with an aligned 'div' element-->
+ <xsl:variable name="table-alignment" select="key('styles', @style:name = current()/@table:style-name)/*/@table:align" />
+ <xsl:choose>
+ <xsl:when test="string-length($table-alignment) != 0">
+ <xsl:element namespace="{$namespace}" name="div">
+ <xsl:attribute name="style">
+ <xsl:choose>
+ <xsl:when test='$table-alignment="left" or $table-alignment="margins"'>
+ <xsl:text>text-align:left</xsl:text>
+ </xsl:when>
+ <xsl:when test='$table-alignment="right"'>
+ <xsl:text>text-align:right</xsl:text>
+ </xsl:when>
+ <xsl:when test='$table-alignment="center"'>
+ <xsl:text>text-align:center</xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:call-template name="create-table-element">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-table-element">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="create-table-element">
+ <xsl:param name="globalData" />
+ <xsl:param name="allVisibleTableRows" />
+
+ <xsl:element namespace="{$namespace}" name="{$tableElement}">
+ <xsl:attribute name="border">0</xsl:attribute>
+ <xsl:attribute name="cellspacing">0</xsl:attribute>
+ <xsl:attribute name="cellpadding">0</xsl:attribute>
+ <xsl:choose>
+ <xsl:when test='name()="table:table"'>
+ <xsl:variable name="value" select="$globalData/all-doc-styles/style[@style:name = current()/@table:style-name]/*/@style:rel-width" />
+ <xsl:if test="$value">
+ <xsl:attribute name="width">
+ <xsl:value-of select="$value" />
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="width">100%</xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:apply-templates select="@table:style-name">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+
+ <xsl:call-template name="create-column-style-variable">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/table/table_cells.xsl b/filter/source/xslt/odf2xhtml/export/common/table/table_cells.xsl
new file mode 100644
index 000000000..3c884138b
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/common/table/table_cells.xsl
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xforms="http://www.w3.org/2002/xforms"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xt="http://www.jclark.com/xt"
+ xmlns:common="http://exslt.org/common"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan">
+
+
+ <!-- *********************************** -->
+ <!-- *** write repeating table cells *** -->
+ <!-- *********************************** -->
+
+
+ <!-- matching cells to give out -> covered table cells are not written out -->
+ <xsl:template match="table:table-cell">
+ <xsl:param name="globalData" />
+ <!-- position of the current input cell to get the correct column style (hidden are also counted)-->
+ <xsl:param name="allTableColumns" />
+ <xsl:param name="maxRowLength" />
+ <xsl:param name="tableDataType" />
+
+
+ <!-- The column position of the current cell has to be determined
+ to get the adequate column styles during later cell creation,
+ or hiding the cell when @table:visibility is not set to 'visible'.
+
+ The position is archived by adding up all table:number-columns-repeated of the preceding cells.
+ Step1: creating '$precedingCells/quantity/@table:number-columns-repeated').
+ Step2: sum(xxx:nodeset($precedingCells)/quantity) + 1 -->
+ <xsl:variable name="precedingCells">
+ <xsl:for-each select="preceding-sibling::*">
+ <xsl:choose>
+ <!-- maybe a parser is used, which reads the DTD files (e.g. Xerces),
+ then '1' is the default for 'table:number-columns-repeated' -->
+ <xsl:when test="not(@table:number-columns-repeated and @table:number-columns-repeated > 1)">
+ <xsl:element name="quantity" namespace="">
+ <xsl:text>1</xsl:text>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="quantity" namespace="">
+ <xsl:value-of select="@table:number-columns-repeated" />
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:variable>
+
+
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="create-table-cell">
+ <!-- position of the current input cell to get the correct column style (hidden are also counted)-->
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="precedingColumns" select="sum(common:node-set($precedingCells)/*)" />
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="create-table-cell">
+ <!-- position of the current input cell to get the correct column style (hidden are also counted)-->
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="precedingColumns" select="sum(xalan:nodeset($precedingCells)/*)" />
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="create-table-cell">
+ <!-- position of the current input cell to get the correct column style (hidden are also counted)-->
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="precedingColumns" select="sum(xt:node-set($precedingCells)/*)" />
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- current node is a table:table-cell -->
+ <xsl:template name="create-table-cell">
+ <!-- position of the current input cell to get the correct column style (hidden are also counted)-->
+ <xsl:param name="allTableColumns" />
+ <xsl:param name="globalData" />
+ <xsl:param name="maxRowLength" />
+ <xsl:param name="precedingColumns" select="0" />
+ <xsl:param name="tableDataType" />
+
+ <xsl:variable name="columnPosition" select="$precedingColumns + 1" />
+
+ <xsl:if test="$debugEnabled">
+ <xsl:message>
+ <xsl:text>
+ table:table-cell #</xsl:text>
+ <xsl:value-of select="$columnPosition" />
+ <xsl:text> has been entered with node value: </xsl:text>
+ <xsl:value-of select="." />
+ <xsl:text>
+ table:number-columns-repeated: </xsl:text>
+ <xsl:value-of select="@table:number-columns-repeated" />
+ <xsl:text>
+ maxRowLength: </xsl:text>
+ <xsl:value-of select="$maxRowLength" />
+ </xsl:message>
+ </xsl:if>
+
+ <!-- only non hidden column will be given out -->
+ <xsl:variable name="currentTableColumn" select="$allTableColumns/table:table-column[position() = $columnPosition]" />
+ <xsl:if test="$currentTableColumn[not(@table:visibility = 'collapse' or @table:visibility = 'filter')]">
+ <xsl:choose>
+ <!-- if parser reads DTD the default is set to '1' -->
+ <xsl:when test="@table:number-columns-repeated > 1">
+ <!-- writes multiple entries of a cell -->
+ <xsl:call-template name="repeat-write-cell">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="columnPosition" select="$columnPosition" />
+ <xsl:with-param name="currentTableColumn" select="$currentTableColumn" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="numberColumnsRepeated" select="@table:number-columns-repeated" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- writes an entry of a cell -->
+ <xsl:call-template name="write-cell">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="columnPosition" select="$columnPosition" />
+ <xsl:with-param name="currentTableColumn" select="$currentTableColumn" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template name="repeat-write-cell">
+ <xsl:param name="globalData" />
+ <xsl:param name="allTableColumns" />
+ <xsl:param name="columnPosition" />
+ <xsl:param name="currentTableColumn" />
+ <xsl:param name="maxRowLength" />
+ <xsl:param name="numberColumnsRepeated" />
+ <xsl:param name="tableDataType" />
+
+ <xsl:choose>
+ <!-- This is the current workaround for the flood of cells, simulation background by repeating cell -->
+ <xsl:when test="$numberColumnsRepeated > 1 and $maxRowLength > $columnPosition">
+
+ <!-- writes an entry of a cell -->
+ <xsl:call-template name="write-cell">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="columnPosition" select="$columnPosition" />
+ <xsl:with-param name="currentTableColumn" select="$currentTableColumn" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ <!-- repeat calling this method until all elements written out -->
+ <xsl:if test="$debugEnabled">
+ <xsl:message>+++++++++ cell repetition +++++++++</xsl:message>
+ </xsl:if>
+ <xsl:call-template name="repeat-write-cell">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="columnPosition" select="$columnPosition + 1" />
+ <xsl:with-param name="currentTableColumn" select="$allTableColumns/table:table-column[position() = ($columnPosition + 1)]" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="numberColumnsRepeated" select="$numberColumnsRepeated - 1" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- This is the current workaround for the flood of cells, simulation background by repeating cell -->
+ <!-- When the maxRowLength is reached a last entry of a cell is written -->
+ <xsl:call-template name="write-cell">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="columnPosition" select="$columnPosition" />
+ <xsl:with-param name="currentTableColumn" select="$currentTableColumn" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="write-cell">
+ <xsl:param name="globalData" />
+ <xsl:param name="allTableColumns" />
+ <xsl:param name="columnPosition" />
+ <xsl:param name="currentTableColumn" />
+ <xsl:param name="tableDataType" />
+
+ <!-- a non hidden column will be give out -->
+ <xsl:choose>
+ <xsl:when test="$currentTableColumn[not(@table:visibility = 'collapse' or @table:visibility = 'filter')]">
+ <xsl:call-template name="create-table-cell-content">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="columnPosition" select="$columnPosition" />
+ <xsl:with-param name="currentTableColumn" select="$currentTableColumn" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:when>
+ <!-- a hidden column -->
+ <xsl:otherwise>
+ <xsl:if test="$debugEnabled">
+ <xsl:message>table column is hidden!</xsl:message>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/table/table_columns.xsl b/filter/source/xslt/odf2xhtml/export/common/table/table_columns.xsl
new file mode 100644
index 000000000..f83302fa0
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/common/table/table_columns.xsl
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xforms="http://www.w3.org/2002/xforms"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:xt="http://www.jclark.com/xt"
+ xmlns:common="http://exslt.org/common"
+ xmlns:xalan="http://xml.apache.org/xalan"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan">
+
+ <xsl:param name="tableColumnElement" select="'col'" />
+
+ <!-- ******************************************** -->
+ <!-- *** Create table columns style variable *** -->
+ <!-- ******************************************** -->
+
+ <!-- current node is a table:table -->
+ <xsl:template name="create-column-style-variable">
+ <xsl:param name="globalData" />
+ <xsl:param name="allVisibleTableRows" />
+
+ <!-- all columns of the table -->
+ <xsl:variable name="allTableColumns" select="table:table-column |
+ table:table-column-group/descendant::table:table-column |
+ table:table-header-columns/descendant::table:table-column" />
+ <!-- allTableColumns: Containing all columns of the table, hidden and viewed.
+ - if a column is hidden, if table:visibility has the value 'collapse' or 'filter', otherwise the value is 'visible'
+ - if a column is being repeated, each repeated column is explicitly written as entry in this variable.
+ Later (during template "write-cell") the style of the column will be mixed with the cell-style by using
+ the position() of the column entry and comparing it with the iterating cell number. -->
+ <xsl:variable name="allTableColumns-RTF">
+ <xsl:for-each select="$allTableColumns">
+ <xsl:call-template name="adding-column-styles-entries">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="create-table-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ <xsl:with-param name="allTableColumns" select="common:node-set($allTableColumns-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="create-table-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ <xsl:with-param name="allTableColumns" select="xalan:nodeset($allTableColumns-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="create-table-children">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ <xsl:with-param name="allTableColumns" select="xt:node-set($allTableColumns-RTF)" />
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- current node is a table:table -->
+ <xsl:template name="create-table-children">
+ <xsl:param name="globalData" />
+ <xsl:param name="allVisibleTableRows" />
+ <xsl:param name="allTableColumns" />
+
+
+ <xsl:for-each select="$allTableColumns/table:table-column">
+ <xsl:if test="not(@table:visibility = 'collapse' or @table:visibility = 'filter')">
+
+ <xsl:call-template name="create-column-element">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:for-each>
+
+ <xsl:call-template name="create-table-rows">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- To be OVERWRITTEN -->
+ <xsl:template name="create-column-element" />
+
+ <!-- current node is a table:table-column -->
+ <xsl:template name="adding-column-styles-entries">
+ <xsl:param name="globalData" />
+ <xsl:param name="allTableColumns" />
+
+ <xsl:choose>
+ <!-- if parser reads DTD the default is set to '1' -->
+ <xsl:when test="not(@table:number-columns-repeated and @table:number-columns-repeated > 1)">
+ <!-- writes an entry of a column in the columns-variable -->
+ <xsl:copy-of select="." />
+ </xsl:when>
+ <!-- No higher repetition of cells greater than 99 for the last and second last column.
+ This is a workaround for some sample document (Waehrungsumrechner.sxc),
+ having 230 repeated columns in the second last column to emulate background -->
+ <!-- NOTE: Testcase with a table containing table:table-column-group and/or table:table-header-columns -->
+ <xsl:when test="(last() or (last() - 1)) and @table:number-columns-repeated &gt; 99">
+ <!-- writes an entry of a column in the columns-variable -->
+ <xsl:call-template name="repeat-adding-table-column">
+ <xsl:with-param name="numberColumnsRepeated" select="1" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- repeated columns will be written explicit several times in the variable-->
+ <xsl:call-template name="repeat-adding-table-column">
+ <xsl:with-param name="numberColumnsRepeated" select="@table:number-columns-repeated" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- WRITES THE REPEATED COLUMN STYLE EXPLICIT AS AN ELEMENT IN THE COLUMNS-VARIABLE -->
+ <!-- current node is a table:table-column -->
+ <xsl:template name="repeat-adding-table-column">
+ <xsl:param name="table:table-column" />
+ <xsl:param name="numberColumnsRepeated" />
+
+
+ <xsl:choose>
+ <xsl:when test="$numberColumnsRepeated > 1">
+ <!-- writes an entry of a column in the columns-variable -->
+ <xsl:copy-of select="." />
+ <!-- repeat calling this method until all elements written out -->
+ <xsl:call-template name="repeat-adding-table-column">
+ <xsl:with-param name="numberColumnsRepeated" select="$numberColumnsRepeated - 1" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- writes an entry of a column in the columns-variable -->
+ <xsl:copy-of select="." />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!--debugEnabled-START-->
+ <!-- giving out the 'allColumnStyle' variable:
+ For each 'table:table-column' of the 'allTableColumns' variable the style-name is given out.
+ In case of 'column-hidden-flag' attribute the text 'Column is hidden is given out.-->
+ <!-- current node is a table:table -->
+ <xsl:template name="table-debug-allTableColumns">
+ <xsl:param name="allTableColumns" />
+
+ <!-- debug output as table summary attribute in html -->
+ <xsl:attribute name="summary">
+ <xsl:call-template name="table-debug-column-out">
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ </xsl:call-template>
+ </xsl:attribute>
+ <!-- debug output to console -->
+ <xsl:message>
+ <xsl:call-template name="table-debug-column-out">
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ </xsl:call-template>
+ </xsl:message>
+ </xsl:template>
+
+ <!-- current node is a table:table -->
+ <xsl:template name="table-debug-column-out">
+ <xsl:param name="allTableColumns" />
+ <xsl:text>
+ DebugInformation: For each 'table:table-column' of the 'allTableColumns' variable the style-name is given out.
+ In case of table:visibility attribute unequal 'visible' the 'column is hidden' no text is given out.
+ </xsl:text>
+ <xsl:for-each select="$allTableColumns/table:table-column">
+ <xsl:choose>
+ <xsl:when test="@table:visibility = 'collapse' or @table:visibility = 'filter' ">
+ <xsl:text> </xsl:text><xsl:value-of select="@table:style-name" /><xsl:text>column is hidden</xsl:text><xsl:text></xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text> </xsl:text><xsl:value-of select="@table:style-name" /><xsl:text> </xsl:text><xsl:value-of select="@table:default-cell-style-name" /><xsl:text></xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+ <!--debugEnabled-END-->
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/table/table_rows.xsl b/filter/source/xslt/odf2xhtml/export/common/table/table_rows.xsl
new file mode 100644
index 000000000..2d6cd7285
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/common/table/table_rows.xsl
@@ -0,0 +1,203 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xforms="http://www.w3.org/2002/xforms"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi">
+
+
+ <xsl:param name="rowElement" select="'tr'" />
+
+ <!-- ********************************** -->
+ <!-- *** write repeating table rows *** -->
+ <!-- ********************************** -->
+
+ <!-- current node is a table:table -->
+ <xsl:template name="create-table-rows">
+ <xsl:param name="globalData" />
+ <xsl:param name="allVisibleTableRows" />
+ <xsl:param name="allTableColumns" />
+
+ <!-- Some Office Calc documents simulate a background by repeating one of the later cells until end of used space
+ (The value of "table:number-columns-repeated" is enormous). Writing out all these cells would be fatal in time
+ and output size. Therefore, this global variable shows us the longest row with content. -->
+ <xsl:variable name="maxRowLength" select="count($allTableColumns/table:table-column)" />
+ <xsl:if test="$debugEnabled">
+ <xsl:message>maxRowLength: <xsl:value-of select="$maxRowLength" /></xsl:message>
+ <xsl:call-template name="table-debug-allTableColumns">
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ </xsl:call-template>
+ </xsl:if>
+
+ <!-- a table is a table header, when it has a "table:table-header-rows" ancestor -->
+ <xsl:variable name="tableDataType">
+ <xsl:choose>
+ <xsl:when test="ancestor::table:table-header-rows">
+ <xsl:text>th</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>td</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- removes repetition of rows, most probably done for background emulating -->
+ <xsl:for-each select="$allVisibleTableRows">
+ <xsl:choose>
+ <xsl:when test="(last() or (last() - 1)) and @table:number-rows-repeated &gt; 99">
+ <xsl:call-template name="repeat-write-row">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="numberRowsRepeated" select="1" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="repeat-write-row">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="numberRowsRepeated" select="@table:number-rows-repeated" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:template>
+
+
+ <xsl:template name="repeat-write-row">
+ <xsl:param name="globalData" />
+ <xsl:param name="allTableColumns" />
+ <xsl:param name="numberRowsRepeated" select="1" />
+ <xsl:param name="maxRowLength" />
+ <xsl:param name="tableDataType" />
+
+ <xsl:choose>
+ <!-- write an entry of a row and repeat calling this method until all elements are written out -->
+ <xsl:when test="$numberRowsRepeated > 1 and table:table-cell">
+ <xsl:call-template name="write-row">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+
+ <!-- NOTE: take variable from the output of repeated write-row and iterate giving out the variable -->
+ <xsl:call-template name="repeat-write-row">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="numberRowsRepeated" select="$numberRowsRepeated - 1" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:when>
+ <!-- write a single entry of a row -->
+ <xsl:otherwise>
+ <xsl:call-template name="write-row">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="add-table-row-attributes">
+ <xsl:param name="globalData" />
+
+ <!-- writing the style of the row -->
+ <xsl:if test="@table:style-name">
+ <xsl:call-template name='add-style-properties'>
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="write-row">
+ <xsl:param name="globalData" />
+ <xsl:param name="allTableColumns" />
+ <xsl:param name="maxRowLength" />
+ <xsl:param name="tableDataType" />
+
+
+ <xsl:element namespace="{$namespace}" name="{$rowElement}">
+ <xsl:call-template name='add-table-row-attributes'>
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+
+ <xsl:if test="$debugEnabled">
+ <xsl:message>'tr' element has been added!</xsl:message>
+ </xsl:if>
+
+ <xsl:apply-templates select="table:table-cell">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ <xsl:with-param name="maxRowLength" select="$maxRowLength" />
+ <xsl:with-param name="tableDataType" select="$tableDataType" />
+ </xsl:apply-templates>
+
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- **************************** -->
+ <!-- *** HELPER: table styles *** -->
+ <!-- **************************** -->
+
+ <xsl:template name="add-style-properties">
+ <xsl:param name="globalData" />
+ <xsl:param name="allTableColumns" />
+ <xsl:param name="node-position" />
+
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate(@table:style-name, '. %()/\+', '')" />
+ </xsl:attribute>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl b/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl
new file mode 100644
index 000000000..f26e2cc0a
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/common/table_of_content.xsl
@@ -0,0 +1,579 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:java="http://xml.apache.org/xslt/java" xmlns:sxg="http://www.jclark.com/xt/java/org.openoffice.xslt.OOoMasterDocument" xmlns:common="http://exslt.org/common" xmlns:xt="http://www.jclark.com/xt" xmlns:xalan="http://xml.apache.org/xalan" exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi java sxg xt common xalan">
+
+ <!-- ****************************** -->
+ <!-- *** Table of Content *** -->
+ <!-- ****************************** -->
+
+ <xsl:param name="currentChildContentRef" />
+ <xsl:param name="contentTableHeadings" />
+ <xsl:param name="contentTableURL" />
+ <xsl:template match="text:table-of-content">
+ <xsl:param name="globalData"/>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <xsl:template match="text:index-body">
+ <xsl:param name="globalData"/>
+
+ <xsl:choose>
+ <xsl:when test="parent::table-of-content and */text:tab[1] or */*/text:tab[1]">
+ <xsl:call-template name="createIndexBodyTable">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="text:index-title" mode="content-table">
+ <xsl:param name="globalData"/>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template name="createIndexBodyTable">
+ <xsl:param name="globalData"/>
+ <xsl:variable name="allStyleTabStops-RTF">
+ <xsl:element name="style:tab-stops">
+ <xsl:call-template name="get-tab-stops">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="styleName" select="current()/@text:style-name"/>
+
+ <!--
+ Currently only the style of text:index-body is recognized, but not of a paragraph child containing the text:tab element!
+ <xsl:with-param name="styleName" select="descendant-or-self::*/@text:style-name"/>
+
+ The column width needs to be tabstop plus fo:margin-left paragraph-properties
+ -->
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:variable>
+ <xsl:element namespace="{$namespace}" name="table">
+
+ <xsl:attribute name="border">0</xsl:attribute>
+ <xsl:attribute name="cellspacing">0</xsl:attribute>
+ <xsl:attribute name="cellpadding">0</xsl:attribute>
+ <xsl:if test="parent::*/@text:style-name">
+ <!-- parent as index:body has no style -->
+ <xsl:variable name="value" select="$globalData/all-doc-styles/style[@style:name = current()/parent::*/@text:style-name]/*/@style:rel-width"/>
+ <xsl:if test="$value">
+ <xsl:attribute name="width">
+ <xsl:value-of select="$value"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate(parent::*/@text:style-name, '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+ </xsl:if>
+
+ <xsl:element namespace="{$namespace}" name="colgroup">
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="create-col-element">
+ <xsl:with-param name="lastNodePosition" select="count(common:node-set($allStyleTabStops-RTF)/style:tab-stops/style:tab-stop)"/>
+ <xsl:with-param name="allStyleTabStops" select="common:node-set($allStyleTabStops-RTF)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="create-col-element">
+ <xsl:with-param name="lastNodePosition" select="count(xalan:nodeset($allStyleTabStops-RTF)/style:tab-stops/style:tab-stop)"/>
+ <xsl:with-param name="allStyleTabStops" select="xalan:nodeset($allStyleTabStops-RTF)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="create-col-element">
+ <xsl:with-param name="lastNodePosition" select="count(xt:node-set($allStyleTabStops-RTF)/style:tab-stops/style:tab-stop)"/>
+ <xsl:with-param name="allStyleTabStops" select="xt:node-set($allStyleTabStops-RTF)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+
+ <!-- add table data -->
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:apply-templates mode="content-table">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="allStyleTabStops" select="common:node-set($allStyleTabStops-RTF)"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:apply-templates mode="content-table">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="allStyleTabStops" select="xalan:nodeset($allStyleTabStops-RTF)"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:apply-templates mode="content-table">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="allStyleTabStops" select="xt:node-set($allStyleTabStops-RTF)"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- ************************************************ -->
+ <!-- *** Create Table for Content Table Paragraph *** -->
+ <!-- ************************************************ -->
+
+ <!-- Usually the paragraphs in a content-table are ordered by tab-stops, which can not be displayed correctly by XHTML/CSS
+ Therefore they will be simulated by a table -->
+ <xsl:template match="text:p" mode="content-table">
+ <xsl:param name="globalData"/>
+ <xsl:param name="allStyleTabStops"/>
+
+ <!-- all elements before the first tabStop -->
+ <xsl:variable name="testNo-RTF">
+ <xsl:apply-templates select="node()" mode="cell-content"/>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:variable name="tabNodePositions" select="common:node-set($testNo-RTF)"/>
+ <xsl:element namespace="{$namespace}" name="tr">
+ <xsl:call-template name="create-td-elements">
+ <xsl:with-param name="lastNodePosition" select="count($allStyleTabStops/style:tab-stops/style:tab-stop)"/>
+ <xsl:with-param name="position" select="1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:variable name="tabNodePositions" select="xalan:nodeset($testNo-RTF)"/>
+ <xsl:element namespace="{$namespace}" name="tr">
+ <xsl:call-template name="create-td-elements">
+ <xsl:with-param name="lastNodePosition" select="count($allStyleTabStops/style:tab-stops/style:tab-stop)"/>
+ <xsl:with-param name="position" select="1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:variable name="tabNodePositions" select="xt:node-set($testNo-RTF)"/>
+ <xsl:element namespace="{$namespace}" name="tr">
+ <xsl:call-template name="create-td-elements">
+ <xsl:with-param name="lastNodePosition" select="count($allStyleTabStops/style:tab-stops/style:tab-stop)"/>
+ <xsl:with-param name="position" select="1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">ERROR: Function not found: nodeset</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Gathering all style:tab-stops from a style-hierarchy as siblings -->
+ <xsl:template name="get-tab-stops">
+ <xsl:param name="globalData"/>
+ <xsl:param name="styleName"/>
+ <xsl:variable name="tabStyle" select="key('styles', $styleName)"/>
+
+ <xsl:if test="$tabStyle/*/style:tab-stops/style:tab-stop/@style:position">
+ <xsl:for-each select="$tabStyle/*/style:tab-stops/style:tab-stop">
+ <xsl:copy-of select="."/>
+ </xsl:for-each>
+ </xsl:if>
+
+ <xsl:if test="$tabStyle/@style:parent-style-name">
+ <xsl:call-template name="get-tab-stops">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="styleName" select="$tabStyle/@style:parent-style-name"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="create-col-element">
+ <xsl:param name="lastNodePosition"/>
+ <xsl:param name="allStyleTabStops"/>
+
+ <xsl:for-each select="$allStyleTabStops/style:tab-stops/style:tab-stop">
+ <xsl:element namespace="{$namespace}" name="col">
+ <xsl:attribute name="style">
+ <xsl:text>width: </xsl:text>
+ <xsl:choose>
+ <xsl:when test="contains(@style:position, 'cm')">
+ <xsl:call-template name="create-cell-width">
+ <xsl:with-param name="width" select="number(substring-before(@style:position,'cm'))"/>
+ <xsl:with-param name="unit" select="'cm'"/>
+ <xsl:with-param name="position" select="position() - 1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains(@style:position, 'in')">
+ <xsl:call-template name="create-cell-width">
+ <xsl:with-param name="width" select="number(substring-before(@style:position,'in'))"/>
+ <xsl:with-param name="unit" select="'in'"/>
+ <xsl:with-param name="position" select="position() - 1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains(@style:position, 'ch')">
+ <xsl:call-template name="create-cell-width">
+ <xsl:with-param name="width" select="number(substring-before(@style:position,'ch'))"/>
+ <xsl:with-param name="unit" select="'ch'"/>
+ <xsl:with-param name="position" select="position() - 1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="contains(@style:position, 'pt')">
+ <xsl:call-template name="create-cell-width">
+ <xsl:with-param name="width" select="number(substring-before(@style:position,'pt'))"/>
+ <xsl:with-param name="unit" select="'pt'"/>
+ <xsl:with-param name="position" select="position() - 1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ </xsl:call-template>
+ </xsl:when>
+ </xsl:choose>
+
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:for-each>
+
+ </xsl:template>
+<!--
+Scenarios tabstops
+
+1) style:type of style:tab-stop is 'right' and earlier tabStop is not right
+ -> Earlier text-nodes and following text-nodes, will be put into an inner table, with two TD first aligned left, with preceding textnodes, the latter aligned right.
+
+2) style:type is 'right' and earlier tabStop is right
+ -> following text-nodes, will be put into a right aligned TD
+
+3) style:type is 'non-right' and earlier tabStop 'non-right' as well
+ -> put the preceding tab stops into a TD (left aligned is default)
+
+4) first style:type would have no right preceding tabStop
+ -> works well with first sceanrios 1 and 3
+
+5) last style:type would be a special case, if it would be left aligned, but this won't happen in our case... :D
+
+Scenarios unmatched:
+- text:styleposition 'center' will not be matched in our case (effort for nothing), there will be only 'right' and not 'right'
+- If the last tabStop is not from text:styleposition 'right', the length of the last cell is undefined and a document length must be found.
+ Not happens in our master document case. Also the algorithm below would have to be expanded (cp. scenario 5).
+
+-->
+ <xsl:template name="create-td-elements">
+ <xsl:param name="globalData"/>
+ <xsl:param name="lastNodePosition"/>
+ <xsl:param name="position"/>
+ <xsl:param name="allStyleTabStops"/>
+ <xsl:param name="tabNodePositions"/>
+
+ <xsl:variable name="currentTabStop" select="$allStyleTabStops/style:tab-stops/style:tab-stop[$position]"/>
+ <xsl:variable name="earlierTabStop" select="$allStyleTabStops/style:tab-stops/style:tab-stop[$position - 1]"/>
+ <xsl:choose>
+ <xsl:when test="not($currentTabStop/@style:position) and not($earlierTabStop/@style:position)">
+ <!-- in case no TAB STOP is being set -->
+ <xsl:element namespace="{$namespace}" name="td">
+ <xsl:element namespace="{$namespace}" name="p">
+ <xsl:if test="$position = 1">
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates mode="content-table">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$currentTabStop/@style:type = 'right'">
+ <xsl:choose>
+ <xsl:when test="$earlierTabStop/@style:type = 'right'">
+ <!--
+ 2) style:type is 'right' and earlier tabStop is right
+ -> following text-nodes, will be put into a right aligned TD -->
+ <xsl:element namespace="{$namespace}" name="td">
+ <xsl:attribute name="style">
+ <xsl:text>align: right</xsl:text>
+ </xsl:attribute>
+ <xsl:element namespace="{$namespace}" name="p">
+ <xsl:if test="$position = 1">
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="grab-cell-content-before-tab-stop">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="endingTabStopPosition" select="$position + 1"/>
+ <xsl:with-param name="lastNodePosition" select="$lastNodePosition"/>
+ <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element namespace="{$namespace}" name="td">
+ <xsl:element namespace="{$namespace}" name="p">
+ <xsl:if test="$position = 1">
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:call-template name="grab-cell-content-before-tab-stop">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="endingTabStopPosition" select="$position"/>
+ <xsl:with-param name="lastNodePosition" select="$lastNodePosition"/>
+ <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$earlierTabStop/@style:type = 'right'"></xsl:when>
+ <xsl:otherwise>
+ <!--
+ 3) style:type is 'non-right' and earlier tabStop 'non-right' as well
+ -> put the preceding tab stops into a TD (left aligned is default) -->
+ <xsl:element namespace="{$namespace}" name="p">
+ <xsl:if test="$position = 1">
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:element namespace="{$namespace}" name="td">
+ <xsl:call-template name="grab-cell-content-before-tab-stop">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="endingTabStopPosition" select="$position"/>
+ <xsl:with-param name="lastNodePosition" select="$lastNodePosition"/>
+ <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$position != $lastNodePosition">
+ <xsl:call-template name="create-td-elements">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="lastNodePosition" select="$lastNodePosition"/>
+ <xsl:with-param name="position" select="$position + 1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ <xsl:with-param name="tabNodePositions" select="$tabNodePositions"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="grab-cell-content-before-tab-stop">
+ <xsl:param name="globalData"/>
+ <xsl:param name="endingTabStopPosition"/>
+ <xsl:param name="tabNodePositions"/>
+ <xsl:param name="lastNodePosition"/>
+
+ <xsl:choose>
+ <xsl:when test="$endingTabStopPosition = 1">
+ <xsl:apply-templates mode="content-table" select="node()[position() &lt; $tabNodePositions/tab-stop-node-position[$endingTabStopPosition]]">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="$endingTabStopPosition > $lastNodePosition">
+ <xsl:apply-templates mode="content-table" select="node()[position() > $tabNodePositions/tab-stop-node-position[$endingTabStopPosition - 1]]">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="nodesOfNextColumn" select="node()[position() &lt; $tabNodePositions/tab-stop-node-position[$endingTabStopPosition]][position() &gt; $tabNodePositions/tab-stop-node-position[$endingTabStopPosition - 1]]"/>
+ <xsl:choose>
+ <xsl:when test="$nodesOfNextColumn != ''">
+ <xsl:apply-templates mode="content-table" select="$nodesOfNextColumn">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates mode="content-table">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- As the span width will be mapped to column width, the preceding span widths have to be subtracted -->
+ <xsl:template name="create-cell-width">
+ <xsl:param name="width"/>
+ <xsl:param name="unit"/>
+ <xsl:param name="position"/>
+ <xsl:param name="allStyleTabStops"/>
+
+ <xsl:choose>
+ <!-- beyond second width -->
+ <xsl:when test="$position > 1">
+ <xsl:call-template name="create-cell-width">
+ <xsl:with-param name="width" select="$width - number(substring-before($allStyleTabStops/style:tab-stops/style:tab-stop[$position]/@style:position,$unit))"/>
+ <xsl:with-param name="unit" select="$unit"/>
+ <xsl:with-param name="position" select="$position - 1"/>
+ <xsl:with-param name="allStyleTabStops" select="$allStyleTabStops"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- second width -->
+ <xsl:when test="$position = 1">
+ <xsl:value-of select="concat($width - number(substring-before($allStyleTabStops/style:tab-stops/style:tab-stop[$position]/@style:position,$unit)), $unit)"/>
+ </xsl:when>
+ <!-- first width -->
+ <xsl:otherwise>
+ <xsl:value-of select="concat($width, $unit)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- ************************************** -->
+ <!-- CREATION OF A CONTENT TABLE LINK -->
+ <!-- ************************************** -->
+
+ <xsl:key name="bookmark" match="text:bookmark | text:bookmark-start" use="@text:name"/>
+
+ <!-- content table link -->
+ <xsl:template match="text:a" mode="content-table">
+ <xsl:param name="globalData"/>
+
+ <xsl:variable name="name" select="substring(@xlink:href,2)"/>
+
+ <xsl:variable name="text">
+ <xsl:choose>
+ <!-- heuristic assumption that first in a content table row, there is numbering (if at all) and then the text,
+ furthermore that a tab will separate the to be neglected page number -->
+ <xsl:when test="text:tab">
+ <xsl:call-template name="write-text-without-line-numbers">
+ <xsl:with-param name="textCount" select="count(text())"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="text()"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- REFERENCE HANDLING - HREF -->
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:attribute name="href">
+ <xsl:text>#</xsl:text>
+ <xsl:choose>
+ <xsl:when test="key('bookmark',$name)">
+ <xsl:value-of select="$name"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select='concat("a_", translate(normalize-space($text), "&#xA;&amp;&lt;&gt;.,;: %()[]/\+", "_______________________________"))'/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+ <xsl:value-of select="$text"/>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- Heuristic: write out text separated by elements, leaving the last number out (mostly text number) -->
+ <xsl:template name="write-text-without-line-numbers">
+ <xsl:param name="textCount"/>
+ <xsl:param name="textNodeNumber" select="1"/>
+
+ <xsl:choose>
+ <xsl:when test="$textCount &gt; $textNodeNumber">
+ <xsl:value-of select="text()[$textNodeNumber]"/>
+ <xsl:call-template name="write-text-without-line-numbers">
+ <xsl:with-param name="textCount" select="$textCount"/>
+ <xsl:with-param name="textNodeNumber" select="$textNodeNumber + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:if test="not(number(text()[$textNodeNumber]) &gt; -1)">
+ <xsl:value-of select="text()[$textNodeNumber]"/>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:template>
+
+ <xsl:template match="text:s" mode="content-table">
+ <xsl:call-template name="write-breakable-whitespace">
+ <xsl:with-param name="whitespaces" select="@text:c"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- ******************** -->
+ <!-- *** Common Rules *** -->
+ <!-- ******************** -->
+
+ <xsl:template match="*" mode="content-table">
+ <xsl:param name="globalData"/>
+
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="*" mode="cell-content">
+ <xsl:if test="name() = 'text:tab' or *[name() = 'text:tab']">
+ <xsl:element name="tab-stop-node-position" namespace="">
+ <xsl:value-of select="position()"/>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="content-table">
+ <!-- Heuristic to remove page numbers (useless in HTML) in the content table
+ usually after a tab -->
+ <xsl:if test="name(preceding-sibling::*[1]) != 'text:tab' and not(number() &gt; -1)">
+ <xsl:value-of select="."/>
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
new file mode 100644
index 000000000..430b834b3
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/xhtml/body.xsl
@@ -0,0 +1,3022 @@
+<?xml version="1.0" encoding="UTF-8"?> <!-- -*- fill-column: 130; nxml-child-indent: 4; tab-width: 4; indent-tabs-mode: nil -*- -->
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xt="http://www.jclark.com/xt" xmlns:common="http://exslt.org/common" xmlns:xalan="http://xml.apache.org/xalan" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" exclude-result-prefixes="chart config dc dom dr3d draw fo form loext math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xt common xalan" xmlns="http://www.w3.org/1999/xhtml">
+
+
+ <!--+++++ INCLUDED XSL MODULES +++++-->
+
+ <!-- helper collection, to convert measures (e.g. inch to pixel using DPI (dots per inch) parameter)-->
+ <xsl:import href="../../common/measure_conversion.xsl"/>
+
+ <!-- common office body element handling -->
+ <xsl:import href="../common/body.xsl"/>
+
+ <!-- common table handling -->
+ <xsl:import href="../common/table/table.xsl"/>
+
+ <!-- xhtml table handling -->
+ <xsl:include href="table.xsl"/>
+
+ <!-- Useful in case of 'style:map', conditional formatting, where a style references to another -->
+ <xsl:key name="styles" match="/*/office:styles/style:style | /*/office:automatic-styles/style:style" use="@style:name"/>
+
+
+ <!-- ************ -->
+ <!-- *** body *** -->
+ <!-- ************ -->
+
+ <xsl:key match="style:style/@style:master-page-name" name="masterPage" use="'count'"/>
+ <xsl:key match="style:master-page" name="masterPageElements" use="@style:name"/>
+ <xsl:key match="style:page-layout" name="pageLayoutElements" use="@style:name"/>
+ <xsl:key name="writingModeStyles" match="/*/office:styles/style:style/style:paragraph-properties/@style:writing-mode | /*/office:automatic-styles/style:style/style:paragraph-properties/@style:writing-mode" use="'test'"/>
+ <xsl:template name="create-body">
+ <xsl:param name="globalData"/>
+ <xsl:call-template name="create-body.collect-page-properties">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <xsl:template name="create-body.collect-page-properties">
+ <xsl:param name="globalData"/>
+
+ <!-- approximation to find the correct master page style (with page dimensions) -->
+ <xsl:variable name="masterPageNames">
+ <!-- Loop over every style:style containing a @style:master-page-name attribute -->
+ <xsl:for-each select="key('masterPage','count')">
+ <!-- Check if this style is being used in the body -->
+ <xsl:if test="key('elementUsingStyle', ../@style:name)">
+ <!-- Check every master-page-name if it is not empty and return as ';' separated list -->
+ <xsl:if test="string-length(../@style:master-page-name) &gt; 0">
+ <xsl:value-of select="../@style:master-page-name"/>;
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <!-- Take the first of the masterpage list and get the according style:master-page element and find the @style:page-layout-name -->
+ <xsl:variable name="pageLayoutName" select="key('masterPageElements', substring-before($masterPageNames,';'))/@style:page-layout-name"/>
+ <xsl:variable name="pagePropertiesRTF">
+ <xsl:choose>
+ <xsl:when test="not($pageLayoutName) or $pageLayoutName = ''">
+ <xsl:copy-of select="$globalData/styles-file/*/office:automatic-styles/style:page-layout[1]/style:page-layout-properties"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Find the according style:page-layout and store the properties in a variable -->
+ <xsl:copy-of select="key('pageLayoutElements', $pageLayoutName)/style:page-layout-properties"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="create-body.create">
+ <xsl:with-param name="globalData" select="common:node-set($globalData)"/>
+ <xsl:with-param name="pageProperties" select="common:node-set($pagePropertiesRTF)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="create-body.create">
+ <xsl:with-param name="globalData" select="xalan:nodeset($globalData)"/>
+ <xsl:with-param name="pageProperties" select="xalan:nodeset($pagePropertiesRTF)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="create-body.create">
+ <xsl:with-param name="globalData" select="xt:node-set($globalData)"/>
+ <xsl:with-param name="pageProperties" select="xt:node-set($pagePropertiesRTF)"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="create-body.create">
+ <xsl:param name="globalData"/>
+ <xsl:param name="pageProperties"/>
+
+ <xsl:element name="body">
+ <!-- direction of text flow -->
+ <xsl:variable name="writingMode" select="$pageProperties/style:page-layout-properties/@style:writing-mode"/>
+ <xsl:choose>
+ <xsl:when test="$writingMode">
+ <xsl:choose>
+ <xsl:when test="contains($writingMode, 'lr')">
+ <xsl:attribute name="dir">ltr</xsl:attribute>
+ </xsl:when>
+ <xsl:when test="contains($writingMode, 'rl')">
+ <xsl:attribute name="dir">rtl</xsl:attribute>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- As CSS writing-mode is not implemented by all browsers, a heuristic is done -->
+ <xsl:variable name="writingModeTest" select="key('writingModeStyles', 'test')"/>
+ <xsl:if test="contains($writingModeTest, 'rl')">
+ <xsl:attribute name="dir">rtl</xsl:attribute>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ <!-- adapt page size -->
+ <xsl:variable name="pageWidth" select="$pageProperties/style:page-layout-properties/@fo:page-width"/>
+
+ <!-- multiple backgroundimages for different page styles (never used in html) -->
+ <xsl:variable name="backgroundImage" select="$pageProperties/style:page-layout-properties/style:background-image"/>
+ <!-- page margins & background image -->
+ <xsl:if test="$pageWidth or $pageProperties/style:page-layout-properties/@fo:* or $backgroundImage/@xlink:href">
+ <xsl:attribute name="style">
+ <xsl:if test="$pageWidth">
+ <xsl:text>max-width:</xsl:text>
+ <xsl:value-of select="$pageWidth"/>
+ <xsl:text>;</xsl:text>
+ </xsl:if>
+ <xsl:if test="$pageProperties/style:page-layout-properties/@fo:* or $backgroundImage/@xlink:href">
+ <xsl:apply-templates select="$pageProperties/style:page-layout-properties/@fo:*"/>
+ <xsl:if test="$backgroundImage/@xlink:href">
+ <xsl:text>background-image:url(</xsl:text>
+ <xsl:call-template name="create-href">
+ <xsl:with-param name="href" select="$backgroundImage/@xlink:href"/>
+ </xsl:call-template>
+ <xsl:text>);</xsl:text>
+
+ <xsl:if test="$backgroundImage/@style:repeat">
+ <xsl:choose>
+ <xsl:when test="$backgroundImage/@style:repeat = 'no-repeat'">
+ <xsl:text>background-repeat:no-repeat;</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>background-repeat:repeat;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ <xsl:if test="$backgroundImage/@style:position">
+ <xsl:text>background-position:</xsl:text>
+ <xsl:value-of select="$backgroundImage/@style:position"/>
+ <xsl:text>;</xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:if>
+ <!-- processing the content of the OpenDocument content file -->
+ <xsl:apply-templates select="/*/office:body/*">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+
+ </xsl:element>
+ </xsl:template>
+
+ <!-- processing the content of the OpenDocument content file -->
+ <xsl:template match="office:body/*">
+ <xsl:param name="globalData"/>
+
+ <!-- not using of 'apply-styles-and-content' as the content table information might have been added to 'globalData' variable -->
+ <xsl:apply-templates select="@text:style-name | @draw:style-name | @draw:text-style-name | @table:style-name"><!-- | @presentation:style-name -->
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+
+ <!-- writing the footer- and endnotes beyond the body -->
+ <xsl:call-template name="write-text-nodes">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- ******************************* -->
+ <!-- *** User Field Declarations *** -->
+ <!-- ******************************* -->
+
+ <xsl:template match="text:user-field-get | text:user-field-input">
+ <xsl:param name="globalData"/>
+
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+ <xsl:template match="text:conditional-text">
+ <xsl:param name="globalData"/>
+
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+ <!-- ODF text fields -->
+ <xsl:template match="text:author-initials | text:author-name | text:chapter | text:character-count | text:creation-date | text:creation-time | text:creator | text:date | text:description | text:editing-cycles | text:editing-duration | text:file-name | text:image-count | text:initial-creator | text:keywords | text:modification-date | text:modification-time | text:object-count | text:page-continuation | text:page-count | text:page-number | text:paragraph-count | text:print-date | text:print-time | text:printed-by | text:sender-city | text:sender-company | text:sender-country | text:sender-email | text:sender-fax | text:sender-firstname | text:sender-initials | text:sender-lastname | text:sender-phone-private | text:sender-phone-work | text:sender-position | text:sender-postal-code | text:sender-state-or-province | text:sender-street | text:sender-title | text:sheet-name | text:subject | text:table-count | text:time | text:title | text:user-defined | text:word-count">
+ <xsl:param name="globalData"/>
+
+ <xsl:element name="span">
+ <xsl:attribute name="title">
+ <xsl:value-of select="local-name()"/>
+ </xsl:attribute>
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+
+
+ <!-- *************** -->
+ <!-- *** Textbox *** -->
+ <!-- *************** -->
+
+ <xsl:template match="draw:text-box">
+ <xsl:param name="globalData"/>
+
+ <xsl:comment>Next 'div' was a 'draw:text-box'.</xsl:comment>
+ <xsl:element name="div">
+ <xsl:variable name="dimension">
+ <xsl:apply-templates select="@fo:min-width"/>
+ <xsl:apply-templates select="@fo:max-width"/>
+ <xsl:apply-templates select="@fo:min-height"/>
+ <xsl:apply-templates select="@fo:max-height"/>
+ </xsl:variable>
+ <xsl:if test="$dimension">
+ <xsl:attribute name="style">
+ <xsl:value-of select="$dimension"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:apply-templates select="@draw:name">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+
+ <xsl:apply-templates select="node()">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="@fo:min-width">
+ <xsl:text>min-width:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>;</xsl:text>
+ </xsl:template>
+ <xsl:template match="@fo:max-width">
+ <xsl:text>max-width:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>;</xsl:text>
+ </xsl:template>
+ <xsl:template match="@fo:min-height">
+ <xsl:text>min-height:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>;</xsl:text>
+ </xsl:template>
+ <xsl:template match="@fo:max-height">
+ <xsl:text>max-height:</xsl:text>
+ <xsl:value-of select="."/>
+ <xsl:text>;</xsl:text>
+ </xsl:template>
+
+
+ <!-- inline style helper for the 'div' boxes -->
+ <xsl:template name="svg:height">
+ <xsl:text>height:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test="contains(@svg:height, 'inch')">
+ <xsl:value-of select="substring-before(@svg:height, 'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@svg:height"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>;</xsl:text>
+ </xsl:template>
+
+ <!-- inline style helper for the 'div' boxes -->
+ <xsl:template name="svg:width">
+ <xsl:text>width:</xsl:text>
+ <xsl:choose>
+ <!-- changing the distance measure: inch to in -->
+ <xsl:when test="contains(@svg:width, 'inch')">
+ <xsl:value-of select="substring-before(@svg:width, 'ch')"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@svg:width"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>;</xsl:text>
+ </xsl:template>
+
+
+
+ <!-- ****************** -->
+ <!-- *** Paragraphs *** -->
+ <!-- ****************** -->
+
+ <xsl:template match="text:p | draw:page">
+ <xsl:param name="globalData"/>
+ <!-- The footnote symbol is the prefix for a footnote in the footer -->
+ <xsl:param name="footnotePrefix"/>
+ <!-- 1) In ODF sometimes the following children are nested
+ <text:p>
+ <draw:frame>
+ <draw:text-box>
+ <text:p>
+ Which results in a paragraphs (the last text:p) having a paragraph as its ancestor.
+ In HTML a 'p' can only have inline documents (no other 'p' as children'),
+ a 'div' will be given for the ancestors instead.
+ 2) ODF images are embedded in a paragraph, but CSS is not able to express a horizontal alignment for an HTML image (text:align is only valid for block elements).
+ A surrounding 'div' element taking over the image style solves that problem, but the div is invalid as child of a paragraph
+ Therefore the paragraph has to be exchanged with a HTML div element
+ -->
+ <!-- TODO page alignment fix - PART1 -->
+ <xsl:variable name="childText"><xsl:apply-templates mode="getAllTextChildren"/></xsl:variable>
+ <xsl:choose>
+ <xsl:when test="name() = 'text:p' and not(*) and (normalize-space($childText) = '')">
+ <!-- WorkAround: Test if the empty paragraph was added after an image, which OOO often does -->
+ <xsl:variable name="isFollowingImage">
+ <xsl:call-template name="follows-empty-paragraphs-and-image">
+ <xsl:with-param name="precedingElement" select="preceding-sibling::node()[1]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$isFollowingImage = 'no'">
+ <xsl:call-template name="create-paragraph">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="footnotePrefix" select="$footnotePrefix" />
+ </xsl:call-template>
+ </xsl:if>
+
+ </xsl:when>
+ <xsl:when test="draw:frame and ((normalize-space($childText) != '') or (((count(*) - count(text:soft-page-break)) &gt; 1)))">
+ <!-- If there is a 'draw:frame' child with text (not being whitespace alone) and more than the draw:frame alone and
+ not the draw:frame and a soft-page-break alone (which is quite often) -->
+
+ <!-- If there is a frame within the text:p or draw:page, its siblings are surrounded as well by a div and are floating (CSS float) -->
+ <!-- But it makes no sense to create floating if the frame is alone or only together with a soft-page-break not usable for HTML -->
+ <!-- The paragraph is written as DIV as there might be nested paragraphs (see above choose block) -->
+ <xsl:choose>
+ <xsl:when test="name() = 'text:p'">
+ <xsl:comment>Next 'div' was a 'text:p'.</xsl:comment>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:comment>Next 'div' was a 'draw:page'.</xsl:comment>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:element name="div">
+ <xsl:apply-templates select="@*">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ <!-- the footnote symbol is the prefix for a footnote in the footer -->
+ <xsl:copy-of select="$footnotePrefix"/>
+ <!-- deal with none draw:frame ahead of the <draw:frame> -->
+ <xsl:if test="name(node()[1]) != 'draw:frame'">
+ <xsl:apply-templates select="node()[1]" mode="frameFloating">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="previousFrameWidths" select="0"/>
+ <xsl:with-param name="previousFrameHeights" select="0"/>
+ <xsl:with-param name="leftPosition" select="0" />
+ <xsl:with-param name="stopAtFirstFrame" select="true()" />
+ <!-- TODO for me (Svante) - Not used, uncertain for now...
+ <xsl:with-param name="pageMarginLeft">
+ <xsl:call-template name="getPageMarginLeft"/>
+ </xsl:with-param>-->
+ </xsl:apply-templates>
+ </xsl:if>
+ <!-- start floating of frames (each take care of its siblings till next draw:frame) -->
+ <xsl:apply-templates select="draw:frame" mode="frameFloating">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="previousFrameWidths" select="0"/>
+ <xsl:with-param name="previousFrameHeights" select="0"/>
+ <xsl:with-param name="leftPosition" select="0"/>
+
+ <!-- TODO for me (Svante) - Not used, uncertain for now...
+ <xsl:with-param name="pageMarginLeft">
+ <xsl:call-template name="getPageMarginLeft"/>
+ </xsl:with-param>-->
+ </xsl:apply-templates>
+ </xsl:element>
+ <!-- after the last draw:frame sibling the CSS float is disabled
+ &#160; is an unbreakable whitespace to give content to the element and force a browser not to ignore the element -->
+ <div style="clear:both; line-height:0; width:0; height:0; margin:0; padding:0;">&#160;</div>
+ </xsl:when>
+ <xsl:when test="text:tab and not(ancestor::text:index-body)">
+ <!-- If there is a tabulator (ie. text:tab) within a paragraph, a heuristic for ODF tabulators creates a
+ span for every text:tab embracing the following text nodes aligning them according to the tabulator.
+ A line break or another text:tab starts a new text:span, line break even the tab counter for the line.
+ -->
+ <xsl:element name="p">
+ <xsl:apply-templates select="@*">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ <!-- start with first child of the paragraph -->
+ <xsl:variable name="firstChildNode" select="node()[1]" />
+ <xsl:apply-templates select="$firstChildNode" mode="tabHandling">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="tabStops" select="$globalData/all-doc-styles/style[@style:name = current()/@text:style-name]/*/style:tab-stops"/>
+ <xsl:with-param name="parentMarginLeft">
+ <!-- Styles of first paragraph in list item, including ancestor styles (inheritance) -->
+ <xsl:variable name="paragraphName" select="@text:style-name" />
+ <xsl:variable name="imageParagraphStyle" select="$globalData/all-styles/style[@style:name = $paragraphName]/final-properties"/>
+ <!-- Only the left margin of the first paragraph of a list item will be added to the margin of the complete list (all levels)-->
+<!-- TODO: left-margin in order with bidirectional -->
+ <xsl:choose>
+ <xsl:when test="contains($imageParagraphStyle, 'margin-left:')">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="normalize-space(substring-before(substring-after($imageParagraphStyle, 'margin-left:'), ';'))"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="pageMarginLeft">
+ <xsl:call-template name="getPageMarginLeft"/>
+ </xsl:with-param>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:when>
+ <xsl:when test="text:tab and text:a and ancestor::text:index-body">
+ <xsl:element name="p">
+ <xsl:apply-templates select="attribute::* | child::text:a">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <!-- !!Check if paragraph is empty!!
+ OOo writes out empty paragraphs layouted behind an image (= draw:image within draw:frame)
+ those have to be neglected in HTML -->
+ <xsl:when test="name() = 'text:p' and not($childText) and not(*)">
+ <xsl:variable name="isFollowingImage">
+ <xsl:call-template name="follows-empty-paragraphs-and-image">
+ <xsl:with-param name="precedingElement" select="preceding-sibling::node()[1]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:if test="$isFollowingImage = 'no'">
+ <xsl:call-template name="create-paragraph">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="footnotePrefix" select="$footnotePrefix" />
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-paragraph">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="footnotePrefix" select="$footnotePrefix" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Return the text -->
+ <xsl:template match="text()" mode="getAllTextChildren">
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+ <!-- A span will be created for every text:tab embracing the following text nodes.
+ A line break or another text:tab starts a new text:span -->
+ <xsl:template match="* | text()" mode="tabHandling">
+ <xsl:param name="globalData"/>
+ <xsl:param name="tabStops"/>
+ <!-- there can be multiple tabs in one line, tabNo guesses the one to apply. By default the first i.e. "1" -->
+ <xsl:param name="tabCount" select="0"/>
+ <xsl:param name="parentMarginLeft" />
+ <xsl:param name="pageMarginLeft" />
+
+<!-- TODO: EXCHANGE FOLLOWING SIBLING BY VARIABLE -->
+ <xsl:variable name="followingSiblingNode" select="following-sibling::node()[1]"/>
+
+
+ <!--
+ Every tabulator indents its following content, encapuslated in a span
+ element.
+
+ This template have two modes:
+
+ 1) Before the first tabulator it will match as usually paragraph content
+ to HTML.
+ 2) After the first paragraph it will always triggers two recursions.
+ One embraces the following content of a paragraph element into a span.
+ (tabContentHandling)
+ The other calls this template and will now ignore anything else than
+ TAB and LINE-BREAK.
+
+
+ The tabulators and linebreaks are being iterated, one by one to keep track of the tab number
+ -->
+
+
+ <xsl:choose>
+ <xsl:when test="name() = 'text:tab'">
+ <!-- every frame sibling have to be encapsulated within a div with left indent -->
+ <xsl:element name="span">
+ <xsl:choose>
+ <xsl:when test="count($tabStops/style:tab-stop) &gt; 0 and count($tabStops/style:tab-stop) &lt; 3">
+ <!-- only allow the heuristic when the style has less than 3 TABS -->
+ <!-- ignore heuristics if no TABS are defined -->
+ <xsl:attribute name="style">
+ <xsl:call-template name="createTabIndent">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="tabStops" select="$tabStops"/>
+ <xsl:with-param name="tabCount" select="$tabCount + 1"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ <xsl:with-param name="pageMarginLeft" select="$pageMarginLeft"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- if there are more than 3 TABS in the style, create a none-breakable-space as whitespace -->
+ <xsl:text>&#160;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="tabContentHandling">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="tabHandling">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="tabStops" select="$tabStops"/>
+ <xsl:with-param name="tabCount" select="$tabCount + 1"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ <xsl:with-param name="pageMarginLeft" select="$pageMarginLeft"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="name() = 'text:line-break'">
+ <!-- A line-break resets the tabCount to '0' -->
+ <br/>
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="tabHandling">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="tabStops" select="$tabStops"/>
+ <xsl:with-param name="tabCount" select="0"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ <xsl:with-param name="pageMarginLeft" select="$pageMarginLeft"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- only before the first tab all content is written out -->
+ <xsl:if test="$tabCount = 0">
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="tabHandling">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="tabStops" select="$tabStops"/>
+ <xsl:with-param name="tabCount" select="$tabCount"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ <xsl:with-param name="pageMarginLeft" select="$pageMarginLeft"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!--
+ This recursion creates the content of a tab (i.e. following siblings
+ till next TAB or LINE BREAK) and ends with the next
+ TAB, LINE-BREAK or with the end of the paragraph.
+ -->
+ <xsl:template match="* | text()" mode="tabContentHandling">
+ <xsl:param name="globalData"/>
+
+ <xsl:if test="(name() != 'text:tab') and (name() != 'text:line-break')">
+ <!-- Write out content -->
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ <!-- Apply for the next node -->
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="tabContentHandling">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="createTabIndent">
+ <xsl:param name="globalData"/>
+ <xsl:param name="tabStops"/>
+ <xsl:param name="tabCount"/>
+ <xsl:param name="parentMarginLeft" />
+ <xsl:param name="pageMarginLeft" />
+
+ <xsl:text>position:absolute;left:</xsl:text>
+ <xsl:variable name="tabPosition">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$tabStops/style:tab-stop[$tabCount]/@style:position"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="tabIndent">
+ <xsl:choose>
+ <xsl:when test="$tabStops/style:tab-stop[$tabCount]/@style:type = 'center'">
+ <!-- in case of style:type 'center' the text is even before the tab stop,
+ centered around the beginning. As I see currently no way in mapping this,
+ therefore I do some HEURISTIC (minus -2.5cm) -->
+ <xsl:value-of select="$tabPosition + $parentMarginLeft + $pageMarginLeft - 2.5"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$tabPosition + $parentMarginLeft + $pageMarginLeft"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!--<xsl:message>TAB: tabCount=
+ <xsl:value-of select="$tabCount"/>, tabPosition=
+ <xsl:value-of select="$tabPosition"/>, tabIndent=
+ <xsl:value-of select="$tabIndent"/>
+ </xsl:message>-->
+ <xsl:choose>
+ <xsl:when test="$tabIndent='NaN'">
+ <xsl:variable name="tabPositionTmp">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$tabStops/style:tab-stop[last()]/@style:position"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- Heuristic: for every tab that is more than specified give a further 1 cm -->
+ <xsl:value-of select="$parentMarginLeft + $tabPositionTmp + count($tabStops/style:tab-stop) - $tabCount"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$tabIndent"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>cm;</xsl:text>
+ <xsl:apply-templates select="$tabStops/style:tab-stop[$tabCount]/@style:type"/>
+ </xsl:template>
+
+ <!-- OOo writes out empty paragraphs layouted behind an image,
+ those have to be neglected in HTML
+ This method checks if an empty paragraph is of that kind! -->
+ <xsl:template name="follows-empty-paragraphs-and-image">
+ <xsl:param name="precedingElement" />
+ <xsl:param name="elementToCheck" select="1"/>
+ <xsl:choose>
+ <!-- OOo writes out empty paragraphs layouted behind the image,
+ those have to be neglected in HTML
+ <xsl:when test="name() = 'text:p' and (normalize-space($childText) = '')"> -->
+ <!-- WorkAround: Test if the empty paragraph was added after an image, which OOO often does -->
+ <xsl:when test="(name($precedingElement) = 'text:p' and not($precedingElement/text()) and not($precedingElement/*))">
+ <xsl:call-template name="follows-empty-paragraphs-and-image">
+ <xsl:with-param name="precedingElement" select="preceding-sibling::*[$elementToCheck]"/>
+ <xsl:with-param name="elementToCheck" select="$elementToCheck +1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$precedingElement/draw:frame">yes</xsl:when>
+ <xsl:otherwise>no</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="create-paragraph">
+ <xsl:param name="globalData"/>
+ <!-- the footnote symbol is the prefix for a footnote in the footer -->
+ <xsl:param name="footnotePrefix"/>
+
+ <!-- xhtml:p may only contain inline elements.
+ If there is one frame beyond, div must be used! -->
+ <xsl:variable name="elementName">
+ <xsl:choose>
+ <xsl:when test="descendant::draw:frame[1] or descendant::text:p[1]">div</xsl:when>
+ <xsl:otherwise>p</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:element name="{$elementName}">
+ <xsl:choose>
+ <!-- in ODF borders of paragraphs will be merged by default. Merging means the adjacent paragraphs are building a unit,
+ where only the first and the last will have a border to the surrounding (top / bottom border)
+ <xsl:variable name="precedingParagraphStyle" select="preceding-sibling::*[1][name() = 'text:p']/@text:style-name"/>
+ <xsl:variable name="followingParagraphStyle" select="following-sibling::*[1][name() = 'text:p']/@text:style-name"/>
+ -->
+ <xsl:when test="$globalData/all-styles/style[@style:name = current()/@text:style-name]/@mergedBorders">
+ <xsl:variable name="precedingParagraphStyle" select="preceding-sibling::*[1][name() = 'text:p']/@text:style-name"/>
+ <xsl:variable name="followingParagraphStyle" select="following-sibling::*[1][name() = 'text:p']/@text:style-name"/>
+ <xsl:choose>
+ <xsl:when test="$precedingParagraphStyle or $followingParagraphStyle">
+ <xsl:variable name="isPrecedingBorderParagraph" select="$globalData/all-styles/style[@style:name = $precedingParagraphStyle]/@mergedBorders"/>
+ <xsl:variable name="isFollowingBorderParagraph" select="$globalData/all-styles/style[@style:name = $followingParagraphStyle]/@mergedBorders"/>
+ <xsl:choose>
+ <xsl:when test="not($isPrecedingBorderParagraph) and $isFollowingBorderParagraph">
+ <xsl:attribute name="class">
+ <xsl:value-of select="concat(translate(@text:style-name, '.,;: %()[]/\+', '_____________'), '_borderStart')"/>
+ </xsl:attribute>
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:when test="$isPrecedingBorderParagraph and not($isFollowingBorderParagraph)">
+ <xsl:attribute name="class">
+ <xsl:value-of select="concat(translate(@text:style-name, '.,;: %()[]/\+', '_____________'), '_borderEnd')"/>
+ </xsl:attribute>
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <!-- inbetween paragraphs with border/margin -->
+ <xsl:when test="$isPrecedingBorderParagraph and $isFollowingBorderParagraph">
+ <xsl:attribute name="class">
+ <xsl:value-of select="concat(translate(@text:style-name, '.,;: %()[]/\+', '_____________'), '_borderSides')"/>
+ </xsl:attribute>
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="write-paragraph">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="write-paragraph">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="write-paragraph">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="footnotePrefix" select="$footnotePrefix" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template name="write-paragraph">
+ <xsl:param name="globalData"/>
+ <!-- the footnote symbol is the prefix for a footnote in the footer -->
+ <xsl:param name="footnotePrefix" />
+
+ <!-- empty paragraph tags does not provoke a carriage return,
+ therefore a non breakable space (&nbsp) have been inserted.-->
+ <xsl:choose>
+ <xsl:when test="node()">
+ <xsl:call-template name="apply-styles-and-content">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="footnotePrefix" select="$footnotePrefix" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="apply-styles-and-content">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="footnotePrefix" select="$footnotePrefix" />
+ </xsl:call-template>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="style:tab-stop/@style:type">
+ <xsl:text>text-align:</xsl:text>
+ <xsl:choose>
+ <xsl:when test=". = 'left'">left</xsl:when>
+ <xsl:when test=". = 'right'">right</xsl:when>
+ <xsl:when test=". = 'center'">center</xsl:when>
+ <xsl:otherwise>justify</xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>;</xsl:text>
+ </xsl:template>
+
+ <!-- As soon a frame is within a paragraph (text:p) or page:frame, every child element is floating (CSS) and worked out in sequence.
+ Accumulating prior frame width and adding parent's left margin -->
+ <!-- Matching all elements and text beyond a paragraph/text:page which are sibling of a draw:frame -->
+ <xsl:template match="* | text()" mode="frameFloating">
+ <xsl:param name="globalData"/>
+ <xsl:param name="previousFrameWidths" select="0"/>
+ <xsl:param name="previousFrameHeights" select="0" />
+ <xsl:param name="leftPosition" select="0" />
+ <xsl:param name="parentMarginLeft" />
+ <xsl:param name="stopAtFirstFrame" select="false()" />
+ <xsl:param name="tdf146264hack" select="false()" />
+
+ <xsl:choose>
+ <xsl:when test="name() = 'draw:frame' and not($stopAtFirstFrame)">
+
+ <!-- if the first node is a draw:frame create a div -->
+ <xsl:call-template name="createDrawFrame">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/>
+ <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ </xsl:call-template>
+ <!-- next elements will be called after the creation with the new indent (plus width of frame) -->
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="nextSiblingIsFrame" select="name(following-sibling::node()[1]) = 'draw:frame'"/>
+ <xsl:choose>
+ <xsl:when test="normalize-space(.) != ''">
+ <!-- every following frame sibling till the next draw:frame
+ have to be encapsulated within a div with left indent.
+ To be moved altogether according the indent (usually right) -->
+ <xsl:comment>Next 'div' added for floating.</xsl:comment>
+ <xsl:element name="div">
+ <xsl:attribute name="style">
+ <xsl:text>display:inline; position:relative; left:</xsl:text>
+ <xsl:value-of select="$leftPosition"/>
+ <xsl:text>cm;</xsl:text>
+ </xsl:attribute>
+ <!-- This xsl:if is the meat of the extremely ugly "fix" to tdf#146264. It probably has unintended
+ bad side-effects.
+ -->
+ <xsl:if test="not($tdf146264hack)">
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:if>
+ <!-- if it is a frame sibling it will be NOT encapsulated within the div (as already within one) -->
+ <xsl:if test="not($nextSiblingIsFrame)">
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/>
+ <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ <xsl:with-param name="leftPosition" select="$leftPosition"/>
+ <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" />
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:element>
+
+ <!-- Other draw:frame will be created outside of the div element -->
+ <xsl:if test="nextSiblingIsFrame and not(stopAtFirstFrame)">
+ <xsl:apply-templates select="following-sibling::draw:frame[1]" mode="frameFloating">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/>
+ <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ <xsl:with-param name="leftPosition" select="$leftPosition"/>
+ <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" />
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:apply-templates select=".">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ <xsl:if test="not($nextSiblingIsFrame)">
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/>
+ <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ <xsl:with-param name="leftPosition" select="$leftPosition"/>
+ <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" />
+ </xsl:apply-templates>
+ </xsl:if>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- A XML node other than text or element (e.g. comment) should not stop the recursion -->
+ <xsl:template match="comment()" mode="frameFloating">
+ <xsl:param name="globalData"/>
+ <xsl:param name="previousFrameWidths" select="0"/>
+ <xsl:param name="previousFrameHeights" select="0" />
+ <xsl:param name="leftPosition" />
+ <xsl:param name="parentMarginLeft" />
+ <xsl:param name="stopAtFirstFrame" select="false()" />
+
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeft"/>
+ <xsl:with-param name="leftPosition" select="$leftPosition"/>
+ <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" />
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+
+ <!-- As draw:frame may occur within more elements than in text:p and draw:page -->
+ <xsl:template match="draw:frame">
+ <xsl:param name="globalData"/>
+ <xsl:param name="previousFrameWidths" select="0"/>
+ <xsl:param name="previousFrameHeights" select="0" />
+ <xsl:param name="tdf146264hack" select="false()" />
+
+ <xsl:call-template name="createDrawFrame">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths"/>
+ <xsl:with-param name="previousFrameHeights" select="$previousFrameHeights"/>
+ <xsl:with-param name="tdf146264hack" select="$tdf146264hack"/>
+ </xsl:call-template>
+ <!-- after the last draw:frame sibling the CSS float is disabled -->
+ <xsl:if test="@text:anchor-type!='as-char'">
+ <div style="clear:both; line-height:0; width:0; height:0; margin:0; padding:0;">&#160;</div>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="getPageMarginLeft">
+ <!-- approximation to find the correct master page style (with page dimensions) -->
+ <xsl:variable name="masterPageNames">
+ <!-- Loop over every style:style containing a @style:master-page-name attribute -->
+ <xsl:for-each select="key('masterPage','count')">
+ <!-- Check if this style is being used in the body -->
+ <xsl:if test="key('elementUsingStyle', ../@style:name)">
+ <!-- Check every master-page-name if it is not empty and return as ';' separated list -->
+ <xsl:if test="string-length(../@style:master-page-name) &gt; 0">
+ <xsl:value-of select="../@style:master-page-name"/>;
+ </xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+ <!-- Take the first of the masterpage list and get the according style:master-page element and find the @style:page-layout-name -->
+ <xsl:variable name="pageLayoutName" select="key('masterPageElements', substring-before($masterPageNames,';'))/@style:page-layout-name"/>
+ <!-- Find the according style:page-layout and store the properties in a variable -->
+ <xsl:variable name="pageMarginLeftAttr" select="key('pageLayoutElements', $pageLayoutName)/style:page-layout-properties/@fo:margin-left"/>
+ <xsl:choose>
+ <xsl:when test="$pageMarginLeftAttr">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$pageMarginLeftAttr"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Elements and text aside of a draw:frame are floating, here a div is being created.
+ Either for a draw:frame or for text and other elements floating aside -->
+ <xsl:template name="createDrawFrame">
+ <xsl:param name="globalData"/>
+ <xsl:param name="previousFrameWidths" select="0"/>
+ <xsl:param name="previousFrameHeights" select="0" />
+ <xsl:param name="parentMarginLeft"/>
+ <xsl:param name="stopAtFirstFrame" select="false()" />
+ <xsl:param name="tdf146264hack" select="false()" />
+
+ <xsl:variable name="parentMarginLeftNew">
+ <xsl:choose>
+ <xsl:when test="string-length(normalize-space($parentMarginLeft)) &lt; 1">
+ <!-- Styles of first paragraph in list item, including ancestor styles (inheritance) -->
+ <xsl:variable name="paragraphName" select="parent::*/@text:style-name" />
+ <xsl:variable name="imageParagraphStyle" select="$globalData/all-styles/style[@style:name = $paragraphName]/final-properties"/>
+ <!-- Only the left margin of the first paragraph of a list item will be added to the margin of the complete list (all levels)-->
+ <xsl:choose>
+ <xsl:when test="contains($imageParagraphStyle, 'margin-left:')">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="normalize-space(substring-before(substring-after($imageParagraphStyle, 'margin-left:'), ';'))"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="normalize-space($parentMarginLeft)" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="svgWidth">
+ <xsl:choose>
+ <xsl:when test="@svg:width">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="@svg:width"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="svgX">
+ <xsl:choose>
+ <xsl:when test="@svg:x">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="@svg:x"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="leftPosition" select="$svgX - $parentMarginLeftNew - $previousFrameWidths"/>
+ <xsl:variable name="svgY">
+ <xsl:choose>
+ <xsl:when test="@svg:y">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="@svg:y"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- if the frame is anchored on a paragraph -->
+ <xsl:if test="@text:anchor-type='paragraph'">
+ <xsl:comment>Next 'div' is emulating the top height of a draw:frame.</xsl:comment>
+ <!-- When the svg:y is set relative to the paragraph content, the best way to emulate a positive height,
+ is to add an invisible division inbetween with a height.
+ Often text will flow into this 'gap', which is handled separately!
+ -->
+ <xsl:if test="$svgY &gt; 0">
+ <xsl:element name="div">
+ <xsl:attribute name="style">
+ <xsl:text>height:</xsl:text>
+ <xsl:value-of select="$svgY"/>
+ <xsl:text>cm;</xsl:text>
+ </xsl:attribute>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:element>
+ </xsl:if>
+ </xsl:if>
+ <xsl:call-template name="createDrawFrame2">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths + $svgWidth"/>
+ <xsl:with-param name="parentMarginLeftNew" select="$parentMarginLeftNew"/>
+ <xsl:with-param name="leftPosition" select="$leftPosition"/>
+ <xsl:with-param name="svgY" select="$svgY"/>
+ </xsl:call-template>
+ <xsl:apply-templates select="following-sibling::node()[1]" mode="frameFloating">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="previousFrameWidths" select="$previousFrameWidths + $svgWidth"/>
+ <xsl:with-param name="parentMarginLeft" select="$parentMarginLeftNew"/>
+ <xsl:with-param name="leftPosition" select="$leftPosition"/>
+ <xsl:with-param name="stopAtFirstFrame" select="$stopAtFirstFrame" />
+ <xsl:with-param name="tdf146264hack" select="$tdf146264hack" />
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template name="createDrawFrame2">
+ <xsl:param name="globalData"/>
+ <xsl:param name="previousFrameWidths" />
+ <xsl:param name="parentMarginLeftNew"/>
+ <xsl:param name="leftPosition" />
+ <xsl:param name="svgY" />
+
+ <xsl:variable name="elem-name">
+ <xsl:choose>
+ <xsl:when test="@text:anchor-type='as-char'">span</xsl:when>
+ <xsl:otherwise>div</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:comment>Next '
+ <xsl:value-of select="$elem-name"/>' is a draw:frame.
+ </xsl:comment>
+ <xsl:element name="{$elem-name}">
+ <xsl:choose>
+ <xsl:when test="draw:object/math:math">
+ <!-- draw:frame elements contain many data that are not
+ relevant for mathematical formulas and that may
+ cause incorrect rendering. Let's ignore the
+ replacement image and keep only the id attribute.
+ See fdo#66645 -->
+ <xsl:apply-templates select="@draw:name"/>
+ <xsl:apply-templates select="draw:object[1]"/><xsl:text> </xsl:text><!-- often trailing whitespace is missing -->
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:attribute name="style">
+ <xsl:call-template name="widthAndHeight"/>
+ <xsl:text> padding:0; </xsl:text>
+ <xsl:if test="@text:anchor-type!='as-char'">
+ <!-- all images float (CSS float relative) with a left position calculated by svg:x - parentMarginLeft - previousFrameWidths -->
+ <xsl:text> float:left; position:relative; left:</xsl:text>
+ <xsl:value-of select="$leftPosition"/>
+ <xsl:text>cm; </xsl:text>
+ <!-- if the frame is anchored on a char -->
+ <xsl:if test="@text:anchor-type='char'">
+ <xsl:text>top:</xsl:text>
+ <xsl:value-of select="$svgY"/>
+ <xsl:text>cm; </xsl:text>
+ </xsl:if>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:apply-templates select="@*">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="node()">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="svg:desc"/>
+
+ <xsl:template name="widthAndHeight">
+ <xsl:if test="@svg:height | @svg:width">
+ <xsl:choose>
+ <xsl:when test="not(@svg:width)">
+ <xsl:call-template name="svg:height"/>
+ </xsl:when>
+ <xsl:when test="not(@svg:height)">
+ <xsl:call-template name="svg:width"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="svg:height"/>
+ <xsl:call-template name="svg:width"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- ***************** -->
+ <!-- *** Text Span *** -->
+ <!-- ***************** -->
+
+ <xsl:template match="text:span">
+ <xsl:param name="globalData"/>
+
+ <xsl:choose>
+ <xsl:when test="draw:frame">
+ <!-- sometimes an ODF image is anchored as character and the
+ image frame appears within a span (which is not valid for HTML)
+ Heuristic: Neglecting the span assuming no text content aside
+ of frame within span -->
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:element name="span">
+ <xsl:call-template name="apply-styles-and-content">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+
+ <!-- **************** -->
+ <!-- *** Headings *** -->
+ <!-- **************** -->
+
+ <xsl:template match="text:h">
+ <xsl:param name="globalData"/>
+
+ <!-- no creation of empty headings (without text content) -->
+ <xsl:if test="text() or descendant::text()">
+ <!-- The URL linking of a table-of-content is due to a bug (cp. bug id# 102311) not mapped as URL in the XML.
+ Linking of the table-of-content can therefore only be achieved by a work-around in HTML -->
+ <xsl:call-template name="create-heading">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:template>
+
+ <!-- default matching for header elements -->
+ <xsl:template name="create-heading">
+ <xsl:param name="globalData"/>
+
+ <xsl:variable name="headingLevel">
+ <xsl:choose>
+ <xsl:when test="@text:outline-level &lt; 6">
+ <xsl:value-of select="@text:outline-level"/>
+ </xsl:when>
+ <xsl:otherwise>6</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="headertyp" select="concat('h', $headingLevel)"/>
+ <xsl:element name="{$headertyp}">
+ <!-- outline style 'text:min-label-width' is interpreted as a CSS 'margin-right' attribute
+ NOTE: Should be handled as CSS style in style header -->
+ <xsl:variable name="min-label" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/*/@text:min-label-width"/>
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate(@text:style-name, '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+
+ <xsl:call-template name="create-heading-anchor">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+
+ </xsl:template>
+
+ <xsl:template name="create-heading-anchor">
+ <xsl:param name="globalData"/>
+
+ <!-- writing out a heading number if desired.-->
+ <!-- if a corresponding 'text:outline-style' exist or is not empty -->
+ <xsl:choose>
+ <xsl:when test="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@style:num-format != '' and not(@text:is-list-header='true')">
+
+ <!-- Every heading element will get a unique anchor for its file, from its hierarchy level and name:
+ For example: The heading title 'My favorite heading' might get <a name="1_2_2_My_favorite_heading" /> -->
+ <!-- creating an anchor for referencing the heading (e.g. from content table) -->
+ <xsl:variable name="headingNumber">
+ <xsl:call-template name="get-heading-number">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:call-template name="create-heading-anchor2">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="headingNumber" select="$headingNumber"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="create-heading-anchor2">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <xsl:template name="get-heading-number">
+ <xsl:param name="globalData"/>
+
+ <!-- write number prefix -->
+ <xsl:value-of select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@style:num-prefix"/>
+ <xsl:call-template name="write-heading-number">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ <!-- write number suffix -->
+ <xsl:value-of select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@style:num-suffix"/>
+ </xsl:template>
+
+ <!-- creating an anchor for referencing the heading -->
+ <xsl:template name="create-heading-anchor2">
+ <xsl:param name="globalData"/>
+ <xsl:param name="headingNumber" />
+
+ <xsl:variable name="title">
+ <xsl:apply-templates mode="concatenate"/>
+ </xsl:variable>
+ <!-- REFERENCE HANDLING - ANCHOR -->
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:attribute name="id">
+ <xsl:value-of select="translate(concat('a_',normalize-space($headingNumber), '_', normalize-space($title)), '&#xA;&amp;&lt;&gt;–.,;: %()[]/\+', '____________________________')" disable-output-escaping="yes"/>
+ </xsl:attribute>
+
+ <xsl:element name="span">
+ <!-- Convert the "label-followed-by" to margins. According to ODF, possible values are: 'listtab', 'space', and 'nothing'.
+ 'space' seems not to be written out by LO, and for 'nothing' we obviously need do nothing.
+ NOTE: Should be handled as CSS style in style header -->
+ <xsl:variable name="currentOutlineLevel" select="@text:outline-level"/>
+ <xsl:variable name="labelFollowedBy" select="$globalData//office:document/office:styles/text:outline-style/text:outline-level-style[@text:level = $currentOutlineLevel]/style:list-level-properties[@text:list-level-position-and-space-mode='label-alignment']/style:list-level-label-alignment/@text:label-followed-by"/>
+
+ <!-- Add some margin, but only if there is a number preceding the heading. -->
+ <xsl:if test="$labelFollowedBy='listtab' and $headingNumber != ''">
+ <xsl:attribute name="class">
+ <xsl:text>heading_numbering</xsl:text>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:copy-of select="$headingNumber"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template name="write-heading-number">
+ <xsl:param name="globalData"/>
+
+ <!-- By default heading start with '1', the parameter 'textStartValue' will only be set, if the attribute @text:start-value exist -->
+ <xsl:choose>
+ <xsl:when test="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@text:start-value">
+ <xsl:call-template name="calc-heading-number">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="outlineLevel" select="@text:outline-level"/>
+ <xsl:with-param name="textStartValue" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = current()/@text:outline-level]/@text:start-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="calc-heading-number">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="outlineLevel" select="@text:outline-level"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!--
+ Find the correct heading no., which is the sum of 'text:start-value'
+ and preceding siblings of 'text:h' with the same 'text:outline-level' (until a text:outline-level with lower value is found).
+ If the 'text:start-value is not set the default value of '1' has to be taken.
+ If a heading number is found (e.g. text:outline-level='3') all heading numbers
+ for the higher levels have to be written out -->
+ <xsl:template name="calc-heading-number">
+ <xsl:param name="globalData"/>
+ <xsl:param name="outlineLevel"/><!-- text level of the heading -->
+ <xsl:param name="iOutlineLevel" select="1"/><!-- iterator, counts from 1 to the text level of the heading -->
+ <xsl:param name="textStartValue" select="1"/><!-- text level to start with, default is '1' -->
+
+ <xsl:choose>
+ <!-- iText levels counts up from '1' to outlineLevel
+ Which means writing a heading number from left to right -->
+ <xsl:when test="$iOutlineLevel &lt; $outlineLevel">
+
+ <!-- Write preceding heading numbers -->
+ <xsl:if test="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = ($iOutlineLevel)]/@style:num-format != ''">
+ <xsl:call-template name="writeNumber">
+ <xsl:with-param name="numberDigit">
+ <xsl:call-template name="calc-heading-digit">
+ <xsl:with-param name="value" select="0"/>
+ <xsl:with-param name="currentoutlineLevel" select="$iOutlineLevel"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="numberFormat" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = ($iOutlineLevel)]/@style:num-format"/>
+ </xsl:call-template>
+ </xsl:if>
+ <xsl:choose>
+ <xsl:when test="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = ($iOutlineLevel + 1)]/@text:start-value">
+ <xsl:call-template name="calc-heading-number">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="outlineLevel" select="$outlineLevel"/>
+ <xsl:with-param name="iOutlineLevel" select="$iOutlineLevel + 1"/>
+ <xsl:with-param name="textStartValue" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = ($iOutlineLevel + 1)]/@text:start-value"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="calc-heading-number">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="outlineLevel" select="$outlineLevel"/>
+ <xsl:with-param name="iOutlineLevel" select="$iOutlineLevel + 1"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Write preceding heading numbers -->
+ <xsl:call-template name="writeNumber">
+ <xsl:with-param name="numberDigit">
+ <xsl:call-template name="calc-heading-digit">
+ <xsl:with-param name="value" select="$textStartValue"/>
+ <xsl:with-param name="currentoutlineLevel" select="$iOutlineLevel"/>
+ </xsl:call-template>
+ </xsl:with-param>
+ <xsl:with-param name="numberFormat" select="$globalData/office:styles/text:outline-style/text:outline-level-style[@text:level = $iOutlineLevel]/@style:num-format"/>
+ <xsl:with-param name="last" select="true()"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="writeNumber">
+ <xsl:param name="numberDigit"/>
+ <xsl:param name="numberFormat"/>
+ <xsl:param name="last"/>
+
+ <xsl:choose>
+ <xsl:when test="not($numberFormat)">
+ <xsl:number value="$numberDigit" format="1."/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$last">
+ <xsl:number value="$numberDigit" format="{$numberFormat}"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:number value="$numberDigit" format="{$numberFormat}."/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="calc-heading-digit">
+ <xsl:param name="value"/>
+ <xsl:param name="currentoutlineLevel"/>
+ <xsl:param name="i" select="1"/>
+
+ <xsl:variable name="precedingHeading" select="preceding-sibling::text:h[@text:outline-level &lt;= $currentoutlineLevel][$i]"/>
+ <xsl:variable name="precedingoutlineLevel" select="$precedingHeading/@text:outline-level"/>
+ <!-- tdf#107696: if text:h has attribute "is-list-header" with "true" value, it mustn't be counted for numbering -->
+ <xsl:variable name="precedingoutlineLevel-is-list-header" select="$precedingHeading[@text:is-list-header='true']/@text:outline-level"/>
+ <xsl:choose>
+ <xsl:when test="($currentoutlineLevel = $precedingoutlineLevel) and (not($precedingoutlineLevel-is-list-header)) ">
+ <xsl:call-template name="calc-heading-digit">
+ <xsl:with-param name="value" select="$value + 1"/>
+ <xsl:with-param name="currentoutlineLevel" select="$currentoutlineLevel"/>
+ <xsl:with-param name="i" select="$i + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <!-- tdf#107696: case text:h has attribute "is-list-header" with "true" value, we don't increment value -->
+ <xsl:when test="($currentoutlineLevel = $precedingoutlineLevel) and ($precedingoutlineLevel-is-list-header) ">
+ <xsl:call-template name="calc-heading-digit">
+ <xsl:with-param name="value" select="$value"/>
+ <xsl:with-param name="currentoutlineLevel" select="$currentoutlineLevel"/>
+ <xsl:with-param name="i" select="$i + 1"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="$currentoutlineLevel &lt; $precedingoutlineLevel">
+ <xsl:message terminate="yes">this should not happen</xsl:message>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- Neglect Annotations -->
+ <xsl:template match="office:annotation" mode="concatenate"/>
+
+ <!-- Match text:placeholder child nodes (e.g. text) -->
+ <xsl:template match="text:placeholder">
+ <xsl:param name="globalData"/>
+
+ <xsl:call-template name="apply-styles-and-content">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- ************* -->
+ <!-- *** Link *** -->
+ <!-- ************* -->
+
+ <xsl:template match="text:a | draw:a">
+ <xsl:param name="globalData"/>
+
+ <xsl:call-template name="create-common-anchor-link">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:template>
+
+
+ <xsl:template name="create-common-anchor-link">
+ <xsl:param name="globalData"/>
+
+ <xsl:element name="a">
+ <xsl:attribute name="href">
+ <xsl:call-template name="create-href">
+ <xsl:with-param name="href" select="@xlink:href"/>
+ </xsl:call-template>
+ </xsl:attribute>
+ <xsl:call-template name="apply-styles-and-content">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+
+
+
+ <!-- ******************* -->
+ <!-- *** Image Link *** -->
+ <!-- ******************* -->
+
+ <!-- currently suggesting that all draw:object-ole elements are images -->
+ <xsl:template match="draw:image | draw:object-ole">
+ <xsl:param name="globalData"/>
+
+ <!-- If there is a replacement graphic, we take it (only exception is if the main image is svg).
+ The replacement graphic is a png which browsers are more likely able to render than the
+ original graphic which might have arbitrary formats. -->
+ <xsl:if test="(@loext:mime-type = 'image/svg+xml') or
+ (@draw:mime-type = 'image/svg+xml') or
+ (not(following-sibling::draw:image) and
+ not((preceding-sibling::draw:image[1]/@loext:mime-type = 'image/svg+xml')
+ or
+ (preceding-sibling::draw:image[1]/@draw:mime-type = 'image/svg+xml')))">
+ <xsl:choose>
+ <xsl:when test="ancestor::text:p or parent::text:span or parent::text:h or parent::draw:a or parent::text:a or text:ruby-base">
+ <!-- XHTML does not allow the mapped elements to contain paragraphs -->
+ <xsl:call-template name="create-image-element">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- images are embedded in a paragraph, but are in CSS not able to express a horizontal alignment for themself.
+ A 'div' element taking over the image style would solve that problem, but is invalid as child of a paragraph -->
+ <xsl:element name="p">
+ <xsl:apply-templates select="@draw:style-name">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+
+ <xsl:call-template name="create-image-element">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:template>
+
+ <xsl:template name="create-image-element">
+ <xsl:param name="globalData"/>
+
+ <xsl:element name="img">
+ <xsl:if test="../@svg:width or ../@svg:height">
+ <xsl:attribute name="style">
+ <xsl:if test="../@svg:height">
+ <xsl:text>height:</xsl:text>
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="../@svg:height"/>
+ </xsl:call-template>
+ <xsl:text>cm;</xsl:text>
+ </xsl:if>
+ <xsl:if test="../@svg:width">
+ <xsl:text>width:</xsl:text>
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="../@svg:width"/>
+ </xsl:call-template>
+ <xsl:text>cm;</xsl:text>
+ </xsl:if>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="alt">
+ <xsl:choose>
+ <xsl:when test="../svg:title">
+ <xsl:value-of select="../svg:title"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message>
+ Accessibility Warning:
+ No alternate text ('svg:title' element) set for
+ image '
+ <xsl:value-of select="@xlink:href"/>'!
+ </xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:attribute>
+
+ <xsl:attribute name="src">
+ <xsl:call-template name="create-href">
+ <xsl:with-param name="href" select="@xlink:href"/>
+ <xsl:with-param name="mimetype">
+ <xsl:choose>
+ <xsl:when test="@draw:mime-type">
+ <xsl:value-of select="@draw:mime-type"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@loext:mime-type"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:attribute>
+
+ <!-- style interpretation only, as no subelements are allowed for img in XHTML -->
+ <xsl:apply-templates select="@draw:style-name">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- ************ -->
+ <!-- *** list *** -->
+ <!-- ************ -->
+ <!--
+ Due to the requirements below the ODF list functionality is not handled by CSS, but the list labels calculated and written by XSLT.
+
+ REQUIREMENTS:
+ =============
+
+ A)
+ One significant difference between XHTML and Office List elements is that a list without text nodes but only further list children
+ would not show a list symbol in the Office, but in the browser from XHTML.
+
+ B)
+ Since OASIS Open Document XML (implemented in OOo2.0) only one parent type exists for list items
+ the 'text:list' element. The XHTML element 'ol', 'ul' will be chosen upon the list style type.
+
+ C)
+ An Office list may be spread over the whole document. Linked by their style and text:continue-numbering='true'.
+
+ D)
+ An Office list can use characters or images as list label.
+
+ E)
+ An Office list can have a prefix and suffix around the list label.
+
+ F)
+ An Office list style may have the attribute consecutive numbering, which resolves in a list counting for all levels
+
+ G)
+ An Office list may (re)start on any arbitrary value by using @text:start-value on the text:list-item
+
+ INDENTATION:
+ ============
+
+ The indent of a list label is not only calculated by using the text:space-before of the list level (listLevelStyle), but
+ as well taking the left margin of the first paragraph (or heading) of the list into account as long it is not negative.
+
+ | MARGIN LEFT | LABEL | CONTENT-PADDING
+ @text:space-before (1) | @text:min-label-width (1) | @text:min-label-distance (1)
+ | + @fo:left-margin (firstParagraph) | |
+
+
+ (1) all attributes belong to: text:list-style/$listLevelStyle/style:list-level-properties/@*
+ $listLevelStyle might be one of three choices:
+ 1) <text:list-level-style-number>
+ 2) <text:list-level-style-bullet>
+ 3) <text:list-level-style-image>
+
+ For example:
+ <text:list-style style:name="Appendix">
+ <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" style:num-prefix="Appendix " style:num-suffix=". " style:num-format="A" style:num-letter-sync="true">
+ <style:list-level-properties text:min-label-width="0.762cm" text:min-label-distance="0.127cm"/>
+ </text:list-level-style-number>
+ <text:list-level-style-number text:level="2" text:style-name="Zeichenformat" style:num-suffix="." style:num-format="1" text:display-levels="2">
+ <style:list-level-properties text:min-label-width="1.016cm"/>
+ </text:list-level-style-number>
+ -->
+ <xsl:key name="listStyles" match=" /*/office:styles/text:list-style | /*/office:automatic-styles/text:list-style | /*/office:styles/style:graphic-properties/text:list-style | /*/office:automatic-styles/style:graphic-properties/text:list-style | /*/office:styles/text:list-style | /*/office:automatic-styles/text:list-style | /*/office:styles/style:graphic-properties/text:list-style | /*/office:automatic-styles/style:graphic-properties/text:list-style" use="@style:name"/>
+
+ <!--
+ A text list may only have text:list-item and text:list-header as children.
+ -->
+ <xsl:template match="text:list">
+ <xsl:param name="globalData"/>
+ <xsl:param name="isListNumberingReset"/>
+ <xsl:param name="isNextLevelNumberingReset"/>
+ <xsl:param name="listLevel" select="count(ancestor::text:list) + 1"/>
+ <xsl:param name="listRestart" select="false()"/>
+ <xsl:param name="itemLabel" select="''"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName" select="@text:style-name"/>
+
+ <!-- To choose list type - get the list style, with the same 'text:style-name' and same 'text:level' >-->
+ <xsl:variable name="listStyleRTF">
+ <xsl:variable name="listStyleInContentFile" select="key('listStyles', $listStyleName)"/>
+ <xsl:choose>
+ <xsl:when test="$listStyleInContentFile">
+ <xsl:copy-of select="$listStyleInContentFile"/>
+ </xsl:when>
+ <xsl:when test="$globalData/office:styles/text:list-style[@style:name = $listStyleName]">
+ <xsl:copy-of select="$globalData/office:styles/text:list-style[@style:name = $listStyleName]"/>
+ </xsl:when>
+ <xsl:when test="$globalData/office:styles/style:graphic-properties/text:list-style[@style:name = $listStyleName]">
+ <xsl:copy-of select="$globalData/office:styles/style:graphic-properties/text:list-style[@style:name = $listStyleName]"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:choose>
+ <xsl:when test="function-available('common:node-set')">
+ <xsl:call-template name="create-list-type">
+ <xsl:with-param name="listStyle" select="common:node-set($listStyleRTF)" />
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xalan:nodeset')">
+ <xsl:call-template name="create-list-type">
+ <xsl:with-param name="listStyle" select="xalan:nodeset($listStyleRTF)" />
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="function-available('xt:node-set')">
+ <xsl:call-template name="create-list-type">
+ <xsl:with-param name="listStyle" select="xt:node-set($listStyleRTF)" />
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:message terminate="yes">The required node-set function was not found!</xsl:message>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="create-list-type">
+ <xsl:param name="globalData"/>
+ <xsl:param name="isListNumberingReset"/>
+ <xsl:param name="isNextLevelNumberingReset"/>
+ <xsl:param name="listLevel" />
+ <xsl:param name="listRestart" />
+ <xsl:param name="itemLabel"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName" />
+
+ <!-- $globalData/styles-file/*/office:styles/ -->
+ <xsl:variable name="listLevelStyle" select="$listStyle/*/*[@text:level = number($listLevel)]"/>
+ <!-- TODO: Access new list styles
+ <xsl:variable name="listLevelLabelAlignment1" select="$listLevelStyle/style:list-level-properties/style:list-level-label-alignment"/>-->
+ <xsl:variable name="listIndent">
+ <xsl:call-template name="getListIndent">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="firstPara" select="*[1]/*[name() = 'text:p' or name() = 'text:h'][1]"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <xsl:variable name="isEmptyList" select="not(*[1]/*[name() = 'text:h' or name() = 'text:p' or name() = 'text:name'])"/>
+ <xsl:variable name="listType">
+ <xsl:choose>
+ <!-- ordered list -->
+ <xsl:when test="name($listLevelStyle) = 'text:list-level-style-number'">
+ <xsl:text>ol</xsl:text>
+ </xsl:when>
+ <!-- unordered list (bullet or image) -->
+ <xsl:otherwise>
+ <xsl:text>ul</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:element name="{$listType}">
+ <xsl:apply-templates select="*[1]" mode="listItemSibling">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isListNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset">
+ <xsl:choose>
+ <xsl:when test="$isListNumberingReset">
+ <xsl:value-of select="true()"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- A list is empty if a text:list does not have a text:list-header or text:list-item (wildcard as only those can exist beyond a text:list), which contains a text:h or text:p -->
+ <xsl:value-of select="not($isEmptyList)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listRestart">
+ <xsl:choose>
+ <xsl:when test="$listRestart">
+ <xsl:value-of select="$listRestart"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- descendants restart their list numbering, when an ancestor is not empty -->
+ <xsl:value-of select="not($isEmptyList)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="minLabelDist">
+ <xsl:choose>
+ <xsl:when test="$listLevelStyle/*/@text:min-label-distance">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$listLevelStyle/*/@text:min-label-distance"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="minLabelWidth">
+ <xsl:choose>
+ <xsl:when test="$listLevelStyle/*/@text:min-label-width">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$listLevelStyle/*/@text:min-label-width"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:apply-templates>
+ </xsl:element>
+ </xsl:template>
+
+ <!-- See comment before text:list template -->
+ <xsl:template name="getListIndent">
+ <xsl:param name="globalData"/>
+ <xsl:param name="listLevelStyle"/>
+ <!-- The first paragraph of the list item (heading is special paragraph in ODF) -->
+ <xsl:param name="firstPara" />
+
+ <!-- Styles of first paragraph in list item, including ancestor styles (inheritance) -->
+ <xsl:variable name="firstParaStyles" select="$globalData/all-styles/style[@style:name = $firstPara/@text:style-name]/final-properties"/>
+
+ <!-- Only the left margin of the first paragraph of a list item will be added to the margin of the complete list (all levels)-->
+ <xsl:variable name="firstParaLeftMargin">
+ <xsl:choose>
+ <xsl:when test="contains($firstParaStyles, 'margin-left:')">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="normalize-space(substring-before(substring-after($firstParaStyles, 'margin-left:'), ';'))"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="spaceBefore">
+ <xsl:choose>
+ <xsl:when test="$listLevelStyle/*/@text:space-before">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="$listLevelStyle/*/@text:space-before"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- Only if the left-margin of the first paragraph is positive the sum
+ text:space-before and fo:left-margin is taken as list indent -->
+ <xsl:choose>
+ <xsl:when test="$firstParaLeftMargin &gt; 0">
+ <xsl:value-of select="$firstParaLeftMargin + $spaceBefore"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$spaceBefore"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <!-- ****************** -->
+ <!-- *** list item *** -->
+ <!-- ****************** -->
+<!--
+ Left margin of the complete list:
+ The space between left page and the list symbol (left-margin) is in the Office implemented by
+ the sum of three values:
+ 1) 'text:space-before', which is part of the 'text:list-style' element.
+ 2) 'margin:left' from the style of the first child (e.g. paragraph).
+ 3) 'fo:text-indent' the indent of the first line of some child (e.g. paragraph) (applied by CSS class style)
+
+ Possible list children:
+ <!ELEMENT text:list-item (text:p|text:h|text:list)+>
+
+ In the Office the list label before the text depends on two attributes:
+ - 'text:min-label-width': the distance between list label and all text of the list item.
+ - 'text:min-label-distance': the distance between list label and text of the first line,
+ only used, when text does not fit in text:min-label-width (ignored)
+
+-->
+ <xsl:template match="text:list-item | text:list-header" mode="listItemSibling">
+ <xsl:param name="globalData"/>
+ <xsl:param name="firstitemLabelWidth"/>
+ <xsl:param name="isEmptyList" select="not(*[name() = 'text:h' or name() = 'text:p' or name() = 'text:name'])"/>
+ <xsl:param name="isListNumberingReset"/>
+ <xsl:param name="isNextLevelNumberingReset"/>
+ <xsl:param name="itemNumber"/>
+ <xsl:param name="itemLabel"/>
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listLevelStyle"/>
+ <xsl:param name="listRestart"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName"/>
+ <xsl:param name="minLabelDist"/>
+ <xsl:param name="minLabelWidth"/>
+ <xsl:param name="listIndent" />
+
+ <!-- The text:list-header shall not be labeled. According to ODF specification (sect. 4.3.2):
+ "The <text:list-header> element represents a list header and is a special kind of list item. It
+ contains one or more paragraphs that are displayed before a list. The paragraphs are formatted
+ like list items but they do not have a preceding number or bullet." -->
+ <xsl:variable name="isListHeader" select="boolean(self::text:list-header)"/>
+
+ <xsl:variable name="listIndentNew">
+ <xsl:choose>
+ <xsl:when test="$listIndent">
+ <xsl:value-of select="$listIndent"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="getListIndent">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="firstPara" select="*[name() = 'text:p' or name() = 'text:h'][1]" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="itemNumberNew">
+ <xsl:if test="$listStyle/text:list-style/text:list-level-style-number">
+ <xsl:choose>
+ <xsl:when test="$isListHeader">0</xsl:when>
+ <xsl:when test="$isEmptyList">
+ <!-- An empty list item (no text:h/text:p as child), will not count as item and does not increment the count. -->
+ <xsl:variable name="tempItemNumber">
+ <xsl:choose>
+ <!-- siblings will be incremented by one -->
+ <xsl:when test="$itemNumber">
+ <xsl:if test="not($isListHeader)">
+ <xsl:value-of select="$itemNumber + 1"/>
+ </xsl:if>
+ </xsl:when>
+ <!-- if a higher list level had content the numbering starts with 1 -->
+ <xsl:when test="$isListNumberingReset and $listLevel &gt; 1">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="getItemNumber">
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:choose>
+ <!-- in case the empty list-item is the first list-item in document -->
+ <xsl:when test="$tempItemNumber = 1">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$tempItemNumber - 1"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="@text:start-value">
+ <xsl:value-of select="@text:start-value"/>
+ </xsl:when>
+ <!-- text:start-value from list level style will only be taken on the first list-item of a list -->
+ <xsl:when test="$listLevelStyle/@text:start-value and count(preceding-sibling::text:list-item) = 0">
+ <xsl:value-of select="$listLevelStyle/@text:start-value"/>
+ </xsl:when>
+ <!-- siblings will be incremented by one -->
+ <xsl:when test="$itemNumber">
+ <xsl:value-of select="$itemNumber + 1"/>
+ </xsl:when>
+ <!-- if a higher list level had content the numbering starts with 1 -->
+ <xsl:when test="$isListNumberingReset and $listLevel &gt; 1">
+ <xsl:value-of select="1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="getItemNumber">
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:variable name="itemLabelNew">
+ <xsl:if test="$listStyle/text:list-style/text:list-level-style-number">
+ <!--
+ A numbered label (e.g. 2.C.III) is created for every text:list-item/header.
+ Above list levels are listed in the label, if the list-style requires this. Levels are separated by @style:num-suffix
+ Formatation is dependent for every list level depth.
+ The label is passed from ancestor text:list-item/header and if required truncated.
+ The prefix/suffix (as well list level dependent) comes before and after the complete label (after truncation)
+ -->
+ <!-- Numbered label will be generated -->
+ <xsl:call-template name="createItemLabel">
+ <xsl:with-param name="itemNumber" select="$itemNumberNew"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listLevelsToDisplay">
+ <xsl:variable name="display" select="$listLevelStyle/@text:display-levels"/>
+ <xsl:choose>
+ <xsl:when test="$display">
+ <xsl:value-of select="$display"/>
+ </xsl:when>
+ <xsl:when test="$isListHeader">0</xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ </xsl:call-template>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:element name="li">
+ <xsl:choose>
+ <xsl:when test="$isEmptyList or $isListHeader">
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="itemLabel" select="$itemLabelNew"/>
+ <xsl:with-param name="listLevel" select="$listLevel + 1"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ </xsl:apply-templates>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Possible following children are text:h, text:p, list:text, text:soft-page-break -->
+ <xsl:apply-templates mode="list-item-children" select="*[1]">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isListHeader or $isNextLevelNumberingReset"/>
+ <!-- The new created label is given to the children -->
+ <xsl:with-param name="itemLabel" select="$itemLabelNew"/>
+ <xsl:with-param name="listLabelElement">
+ <xsl:choose>
+ <xsl:when test="name() = 'text:list-header'"/>
+ <xsl:otherwise>
+ <xsl:variable name="listLabelWidth">
+ <xsl:choose>
+ <xsl:when test="$minLabelWidth">
+ <xsl:value-of select="$minLabelWidth"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="listLevelLabelAlignment" select="$listLevelStyle/style:list-level-properties/style:list-level-label-alignment"/>
+ <xsl:variable name="listLevelTextIndent">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="string($listLevelLabelAlignment/@fo:text-indent)"/>
+ </xsl:call-template>
+ </xsl:variable>
+ <!-- TODO: Access new ODF 1.2 list styles
+ <xsl:variable name="listLevelTextIndent">
+ <xsl:call-template name="convert2cm">
+ <xsl:with-param name="value" select="string($listLevelLabelAlignment/@text:list-tab-stop-position)"/>
+ </xsl:call-template>
+ </xsl:variable> -->
+ <xsl:value-of select="-$listLevelTextIndent"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- Numbering is being done by this transformation creating a HTML span representing the number label
+ The html:span represents the list item/header label (e.g. 1.A.III)
+ As the html:span is usually an inline element is formatted by CSS as block element to use width upon it,
+ to disable the carriage return float:left is used and later neglected -->
+ <xsl:element name="span">
+ <xsl:if test="$listLevelStyle/@text:style-name">
+ <xsl:attribute name="class">
+ <xsl:value-of select="$listLevelStyle/@text:style-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style">
+ <xsl:text>display:block;float:</xsl:text>
+ <!-- TODO: Svante - copy this functionality for other used margin:left (in western country 'left') -->
+ <xsl:call-template name="getOppositeWritingDirection">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="paraStyleName" select="descendant-or-self::*/@text:style-name"/>
+ </xsl:call-template>
+ <xsl:text>;min-width:</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$listLabelWidth and not($listLabelWidth='') and not($listLabelWidth='NaN')">
+ <xsl:value-of select="translate($listLabelWidth,',','.')"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>cm;</xsl:text>
+ <xsl:if test="$minLabelDist &gt; 0">
+ <xsl:text>padding-right:</xsl:text><xsl:value-of select="$minLabelDist"/><xsl:text>cm;</xsl:text>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:variable name="labelContent">
+ <xsl:choose>
+ <xsl:when test="text:number">
+ <xsl:apply-templates select="text:number" mode="listnumber"/>
+ </xsl:when>
+ <xsl:when test="name($listLevelStyle) = 'text:list-level-style-bullet'">
+ <xsl:value-of select="$listLevelStyle/@style:num-prefix"/>
+ <xsl:value-of select="$listLevelStyle/@text:bullet-char"/>
+ <xsl:value-of select="$listLevelStyle/@style:num-suffix"/>
+ </xsl:when>
+ <xsl:when test="name($listLevelStyle) = 'text:list-level-style-number'">
+ <xsl:value-of select="$listLevelStyle/@style:num-prefix"/>
+ <xsl:value-of select="$itemLabelNew"/>
+ <xsl:value-of select="$listLevelStyle/@style:num-suffix"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Listing with image as bullets, taken from the list style's href -->
+ <xsl:value-of select="$listLevelStyle/@xlink:href"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <!-- Some browsers have problem with stand-alone elements (e.g. <span/>)
+ Therefore a comment is being inserted into an empty label -->
+ <xsl:choose>
+ <xsl:when test="$labelContent != ''">
+ <xsl:value-of select="$labelContent"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:comment>&#160;</xsl:comment>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="listLabelEmptyElement">
+ <xsl:element name="span">
+ <xsl:if test="$listLevelStyle/@text:style-name">
+ <xsl:attribute name="class">
+ <xsl:value-of select="$listLevelStyle/@text:style-name"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style">
+ <xsl:text>display:block;float:</xsl:text>
+ <xsl:call-template name="getOppositeWritingDirection">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="paraStyleName" select="descendant-or-self::*/@text:style-name"/>
+ </xsl:call-template>
+ <xsl:text>;min-width:</xsl:text>
+ <xsl:choose>
+ <xsl:when test="$minLabelWidth and not($minLabelWidth='') and not($minLabelWidth='NaN')">
+ <xsl:value-of select="translate($minLabelWidth,',','.')"/>
+ </xsl:when>
+ <xsl:otherwise>0</xsl:otherwise>
+ </xsl:choose>
+ <xsl:text>cm</xsl:text>
+ <xsl:if test="$minLabelDist &gt; 0">
+ <xsl:text>padding-right:</xsl:text><xsl:value-of select="$minLabelDist"/><xsl:text>cm;</xsl:text>
+ </xsl:if>
+ </xsl:attribute>
+ <xsl:comment>&#160;</xsl:comment>
+ </xsl:element>
+ </xsl:with-param>
+ <xsl:with-param name="listLevel" select="$listLevel + 1"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="listIndent" select="$listIndentNew"/>
+ <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/>
+ </xsl:apply-templates>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+ <xsl:apply-templates select="following-sibling::*[1]" mode="listItemSibling">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="itemNumber" select="$itemNumberNew"/>
+ <xsl:with-param name="listIndent">
+ <xsl:choose>
+ <xsl:when test="not($isEmptyList)">
+ <xsl:value-of select="$listIndentNew"/>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:with-param>
+ <!-- Receives the same parent label -->
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="minLabelDist" select="$minLabelDist"/>
+ <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template name="getOppositeWritingDirection">
+ <xsl:param name="globalData"/>
+ <xsl:param name="paraStyleName"/>
+
+ <xsl:variable name="imageParagraphStyle" select="$globalData/all-styles/style[@style:name = $paraStyleName]/final-properties"/>
+
+ <xsl:choose>
+ <xsl:when test="contains($imageParagraphStyle, 'writing-mode:')">
+ <xsl:choose>
+ <xsl:when test="contains(substring-before(substring-after($imageParagraphStyle, 'writing-mode:'), ';'), 'rl')">right</xsl:when>
+ <xsl:otherwise>left</xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>left</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="text:number" mode="listnumber">
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="text:number" mode="list-item-children">
+ <xsl:param name="globalData"/>
+ <xsl:param name="listLabelElement"/>
+ <xsl:param name="listLabelEmptyElement"/>
+ <xsl:param name="isEmptyList"/>
+ <xsl:param name="isListNumberingReset"/>
+ <xsl:param name="isNextLevelNumberingReset"/>
+ <xsl:param name="itemLabel"/>
+ <xsl:param name="itemNumber"/>
+ <xsl:param name="listIndent"/>
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listLevelStyle" />
+ <xsl:param name="listRestart"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName"/>
+ <xsl:param name="minLabelWidth"/>
+ <xsl:param name="minLabelDist"/>
+
+ <xsl:apply-templates mode="list-item-children" select="following-sibling::*[1]">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listLabelElement" select="$listLabelElement"/>
+ <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/>
+ <xsl:with-param name="minLabelDist" select="$minLabelDist"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- Each key element holds the set of all text:list-item/text:list-header of a certain level and a certain style -->
+ <xsl:key name="getListItemsByLevelAndStyle" use="concat(count(ancestor::text:list), ancestor::text:list/@text:style-name)" match="text:list-item | text:list-header"/>
+ <!-- Each key element holds the set of all text:list-item/text:list-header of a certain style -->
+ <xsl:key name="getListItemsByStyle" use="ancestor::text:list/@text:style-name" match="text:list-item | text:list-header"/>
+
+
+ <!-- The Numbering start value (or offset from regular counteing) is used at the first item of offset,
+ but have to be reused on following items with no text:start-value -->
+ <xsl:template name="getItemNumber">
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listLevelStyle"/>
+ <xsl:param name="listStyleName"/>
+ <xsl:param name="listStyle"/>
+
+ <xsl:call-template name="countListItemTillStartValue">
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="preceding::text:list-item[generate-id(key('getListItemsByLevelAndStyle', concat($listLevel, $listStyleName))) = generate-id(key('getListItemsByLevelAndStyle', concat(count(ancestor::text:list), ancestor::text:list/@text:style-name)))]"/>
+
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="preceding::text:list-item[generate-id(key('getListItemsByStyle', $listStyleName)) = generate-id(key('getListItemsByStyle', ancestor::text:list/@text:style-name))]"/>
+ </xsl:call-template>
+ </xsl:template>
+
+ <!-- When there is a text:start-value the last have to be found and added to the number -->
+ <xsl:template name="countListItemTillStartValue">
+ <xsl:param name="IteratorSameLevelAndStyle" select="1"/>
+ <xsl:param name="IteratorSameStyle" select="1"/>
+ <xsl:param name="itemNumber" select="1"/>
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listLevelStyle"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName"/>
+ <xsl:param name="precedingListItemsOfSameLevelAndStyle" />
+ <xsl:param name="precedingListItemsOfSameLevelAndStyleCount" select="count($precedingListItemsOfSameLevelAndStyle)"/>
+ <xsl:param name="precedingListItemsOfSameStyle" />
+ <xsl:param name="precedingListItemsOfSameStyleCount" select="count($precedingListItemsOfSameStyle)"/>
+ <!-- E.g.: If a list level 2 number is searched, a level 3 with content found with only a level 1 parent with content,
+ the level 3 gets a 'pseudoLevel' -->
+ <xsl:param name="pseudoLevel" select="0" />
+
+ <xsl:variable name="isListHeader" select="boolean(self::text:list-header)"/>
+ <xsl:variable name="isEmptyList" select="not(*[name() = 'text:h' or name() = 'text:p'])"/>
+
+ <!-- set the next of preceding list items. Starting from the current to the next previous text:list-item -->
+ <xsl:variable name="precedingListItemOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle[$precedingListItemsOfSameLevelAndStyleCount - $IteratorSameLevelAndStyle + 1]"/>
+ <xsl:variable name="precedingListItemOfSameStyle" select="$precedingListItemsOfSameStyle[$precedingListItemsOfSameStyleCount - $IteratorSameStyle + 1]"/>
+ <xsl:choose>
+ <xsl:when test="($precedingListItemOfSameStyle and $precedingListItemOfSameLevelAndStyle) or ($precedingListItemOfSameStyle and $listStyle/text:list-style/@text:consecutive-numbering)">
+ <xsl:for-each select="$precedingListItemOfSameStyle">
+ <xsl:choose>
+ <!-- if it is a higher list level element -->
+ <xsl:when test="$listStyle/text:list-style/@text:consecutive-numbering">
+
+ <xsl:call-template name="countListItem">
+ <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle" />
+ <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/>
+ <xsl:with-param name="pseudoLevel" select="$pseudoLevel" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- NOT CONSECUTIVE NUMBERING -->
+ <xsl:variable name="currentListLevel" select="count(ancestor::text:list)"/>
+ <xsl:choose>
+ <!-- IF IT IS A HIGHER LIST LEVEL ELEMENT -->
+ <xsl:when test="$currentListLevel &lt; $listLevel">
+ <xsl:choose>
+ <!-- if it has content the counting is ended -->
+ <xsl:when test="*[name() = 'text:h' or name() = 'text:p'] or $isListHeader">
+ <!-- TODO: Perhaps the children still have to be processed -->
+ <xsl:value-of select="$itemNumber + $pseudoLevel"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- if it is empty the counting continues -->
+ <xsl:call-template name="countListItemTillStartValue">
+ <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle" />
+ <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/>
+ <xsl:with-param name="pseudoLevel" select="$pseudoLevel" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <!-- IF IT IS A LIST LEVEL ELEMENT OF THE COUNTING LEVEL -->
+ <xsl:when test="$currentListLevel = $listLevel">
+ <xsl:call-template name="countListItem">
+ <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle" />
+ <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/>
+ <xsl:with-param name="pseudoLevel" select="$pseudoLevel" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- list item below the current level does not count -->
+ <xsl:call-template name="countListItemTillStartValue">
+ <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle" />
+ <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/>
+ <xsl:with-param name="pseudoLevel">
+ <xsl:choose>
+ <!-- empty list item does not count -->
+ <xsl:when test="not(*[name() = 'text:h' or name() = 'text:p']) or $isListHeader">
+ <xsl:value-of select="$pseudoLevel"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$itemNumber"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="countListItem">
+ <xsl:param name="IteratorSameLevelAndStyle"/>
+ <xsl:param name="IteratorSameStyle"/>
+ <xsl:param name="itemNumber"/>
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listLevelStyle"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName"/>
+ <xsl:param name="precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:param name="precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:param name="precedingListItemsOfSameStyle"/>
+ <xsl:param name="precedingListItemsOfSameStyleCount"/>
+ <xsl:param name="pseudoLevel" />
+
+ <xsl:variable name="isListHeader" select="boolean(self::text:list-header)"/>
+ <xsl:variable name="isEmptyList" select="not(*[name() = 'text:h' or name() = 'text:p'])"/>
+
+ <xsl:choose>
+ <xsl:when test="@text:start-value">
+ <xsl:choose>
+ <xsl:when test="$isEmptyList or $isListHeader">
+ <!-- empty list item does not count. neither does list header -->
+ <xsl:call-template name="countListItemTillStartValue">
+ <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle + 1" />
+ <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/>
+ <xsl:with-param name="pseudoLevel" select="$pseudoLevel" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$itemNumber + @text:start-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:when test="$listLevelStyle/@text:start-value">
+ <xsl:choose>
+ <xsl:when test="$isEmptyList or $isListHeader">
+ <!-- empty list item does not count. neither does list header -->
+ <xsl:call-template name="countListItemTillStartValue">
+ <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle + 1" />
+ <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/>
+ <xsl:with-param name="pseudoLevel" select="$pseudoLevel" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$itemNumber + $listLevelStyle/@text:start-value"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:choose>
+ <xsl:when test="$isEmptyList or $isListHeader">
+ <!-- empty list item does not count. neither does list header -->
+ <xsl:call-template name="countListItemTillStartValue">
+ <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle + 1" />
+ <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/>
+ <xsl:with-param name="pseudoLevel" select="$pseudoLevel" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- count on till you find a start-value or the end is reached -->
+ <xsl:call-template name="countListItemTillStartValue">
+ <xsl:with-param name="IteratorSameLevelAndStyle" select="$IteratorSameLevelAndStyle + 1" />
+ <xsl:with-param name="IteratorSameStyle" select="$IteratorSameStyle + 1"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber + 1"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyle" select="$precedingListItemsOfSameLevelAndStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameLevelAndStyleCount" select="$precedingListItemsOfSameLevelAndStyleCount"/>
+ <xsl:with-param name="precedingListItemsOfSameStyle" select="$precedingListItemsOfSameStyle"/>
+ <xsl:with-param name="precedingListItemsOfSameStyleCount" select="$precedingListItemsOfSameStyleCount"/>
+ <xsl:with-param name="pseudoLevel" select="0" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+ <!-- Creates the list label containing the number, which is separated by '.' between the levels.
+ Depending on the levels to display (listLevelsToDisplay) -->
+ <xsl:template name="createItemLabel">
+ <xsl:param name="itemLabel" select="''"/>
+ <xsl:param name="itemNumber" />
+ <xsl:param name="listLevel" />
+ <xsl:param name="listLevelStyle" />
+ <xsl:param name="listLevelsToDisplay" />
+
+ <xsl:choose>
+ <xsl:when test="$listLevelsToDisplay &lt; $listLevel">
+ <xsl:call-template name="truncLabel">
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber" />
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle" />
+ <xsl:with-param name="listLevelsToDisplay" select="$listLevelsToDisplay"/>
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:variable name="numberedSymbol">
+ <!-- only give out a number when number format is not empty -->
+ <xsl:if test="$listLevelStyle/@style:num-format != ''">
+ <xsl:number value="$itemNumber" format="{$listLevelStyle/@style:num-format}"/>
+ </xsl:if>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$listLevelsToDisplay != 1">
+ <xsl:value-of select="concat($itemLabel, $listLevelStyle/@style:num-prefix , $numberedSymbol, $listLevelStyle/@style:num-suffix)"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="concat($listLevelStyle/@style:num-prefix , $numberedSymbol, $listLevelStyle/@style:num-suffix)"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="truncLabel">
+ <xsl:param name="itemLabel" />
+ <xsl:param name="itemNumber" />
+ <xsl:param name="listLevel" />
+ <xsl:param name="listLevelStyle" />
+ <xsl:param name="listLevelsToDisplay" />
+ <xsl:param name="listStyle" />
+ <xsl:param name="listStyleName" />
+
+ <xsl:call-template name="createItemLabel">
+ <xsl:with-param name="itemLabel">
+ <xsl:if test="contains($itemLabel, '.')">
+ <xsl:value-of select="substring-after($itemLabel, '.')"/>
+ </xsl:if>
+ </xsl:with-param>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLevel" select="$listLevel - 1"/>
+ <xsl:with-param name="listLevelStyle" select="$listLevelStyle"/>
+ <xsl:with-param name="listLevelsToDisplay" select="$listLevelsToDisplay"/>
+ </xsl:call-template>
+ </xsl:template>
+
+
+ <xsl:template match="text:p" mode="list-item-children">
+ <xsl:param name="globalData"/>
+ <xsl:param name="listLabelElement"/>
+ <xsl:param name="listLabelEmptyElement"/>
+ <xsl:param name="isEmptyList"/>
+ <xsl:param name="isListNumberingReset"/>
+ <xsl:param name="isNextLevelNumberingReset"/>
+ <xsl:param name="itemLabel"/>
+ <xsl:param name="itemNumber"/>
+ <xsl:param name="listIndent"/>
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listRestart"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName"/>
+ <xsl:param name="minLabelDist"/>
+ <xsl:param name="minLabelWidth"/>
+
+ <!-- TODO page alignment fix - PART1 -->
+
+ <!-- xhtml:p may only contain inline elements.
+ If there is one frame beyond, div must be used! -->
+ <xsl:variable name="elementName">
+ <xsl:choose>
+ <xsl:when test="descendant::draw:frame[1] or descendant::text:p[1]">div</xsl:when>
+ <xsl:otherwise>p</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:element name="{$elementName}">
+ <xsl:call-template name="create-list-style">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <xsl:with-param name="styleName" select="@text:style-name"/>
+ </xsl:call-template>
+ <xsl:choose>
+ <xsl:when test="$listLabelElement">
+ <xsl:copy-of select="$listLabelElement"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$listLabelEmptyElement"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="listIndent" select="$minLabelWidth"/>
+ <xsl:with-param name="tdf146264hack" select="true()"/>
+ </xsl:apply-templates>
+ <!-- this span disables the float necessary to bring two block elements on one line. It contains a space as IE6 bug workaround -->
+ <span class="odfLiEnd"></span>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:element>
+
+ <xsl:apply-templates mode="list-item-children" select="following-sibling::*[1]">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <xsl:with-param name="minLabelDist" select="$minLabelDist"/>
+ <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <!-- Neglecting the left margin behavior for headings for now -->
+ <xsl:template match="text:h" mode="list-item-children">
+ <xsl:param name="globalData"/>
+ <xsl:param name="listLabelElement"/>
+ <xsl:param name="listLabelEmptyElement"/>
+ <xsl:param name="isEmptyList"/>
+ <xsl:param name="isListNumberingReset"/>
+ <xsl:param name="isNextLevelNumberingReset"/>
+ <xsl:param name="itemLabel"/>
+ <xsl:param name="itemNumber"/>
+ <xsl:param name="listIndent"/>
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listRestart"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName"/>
+ <xsl:param name="minLabelWidth"/>
+
+ <xsl:variable name="headingName" select="concat('h', $listLevel - 1)"/>
+ <xsl:element name="{$headingName}">
+ <xsl:call-template name="create-list-style">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <xsl:with-param name="styleName" select="@text:style-name"/>
+ </xsl:call-template>
+ <xsl:variable name="title">
+ <xsl:apply-templates mode="concatenate"/>
+ </xsl:variable>
+ <xsl:choose>
+ <xsl:when test="$listLabelElement">
+ <xsl:copy-of select="$listLabelElement"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$listLabelEmptyElement"/>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- REFERENCE HANDLING - ANCHOR -->
+ <xsl:element namespace="{$namespace}" name="a">
+ <xsl:attribute name="id">
+ <xsl:value-of select="translate(concat('a_',$listLabelElement, '_', normalize-space($title)), '&#xA;&amp;&lt;&gt;.,;: %()[]/\+', '___________________________')"/>
+ </xsl:attribute>
+ <xsl:apply-templates>
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="listIndent" select="$minLabelWidth"/>
+ </xsl:apply-templates>
+ </xsl:element>
+
+ <!-- this span disables the float necessary to bring two block elements on one line. It contains a space as IE6 bug workaround -->
+ <span class="odfLiEnd"></span>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:element>
+
+ <xsl:apply-templates mode="list-item-children" select="following-sibling::*[1]">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+
+ <xsl:template match="*" mode="list-item-children">
+ <xsl:param name="globalData"/>
+ <xsl:param name="isEmptyList"/>
+ <xsl:param name="listLabelEmptyElement"/>
+ <xsl:param name="isListNumberingReset"/>
+ <xsl:param name="isNextLevelNumberingReset"/>
+ <xsl:param name="itemLabel"/>
+ <xsl:param name="itemNumber"/>
+ <xsl:param name="listIndent"/>
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listRestart"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listStyleName"/>
+ <xsl:param name="minLabelWidth"/>
+
+ <xsl:apply-templates select="self::*">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ </xsl:apply-templates>
+
+ <xsl:apply-templates mode="list-item-children" select="following-sibling::*[1]">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listLabelEmptyElement" select="$listLabelEmptyElement"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listRestart" select="$listRestart"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <xsl:with-param name="minLabelWidth" select="$minLabelWidth"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="*" mode="listItemSibling">
+ <xsl:param name="globalData"/>
+ <xsl:param name="isEmptyList"/>
+ <xsl:param name="isListNumberingReset"/>
+ <xsl:param name="isNextLevelNumberingReset"/>
+ <xsl:param name="itemLabel"/>
+ <xsl:param name="itemNumber"/>
+ <xsl:param name="listIndent"/>
+ <xsl:param name="listLevel"/>
+ <xsl:param name="listRestart"/>
+ <xsl:param name="listStyle"/>
+ <xsl:param name="listLevelStyle"/>
+ <xsl:param name="listStyleName"/>
+
+ <xsl:apply-templates select="self::*">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <!-- receives the same parent label, only with a different itemNumber -->
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="following-sibling::*[1]" mode="listItemSibling">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="isEmptyList" select="$isEmptyList"/>
+ <xsl:with-param name="isListNumberingReset" select="$isListNumberingReset"/>
+ <xsl:with-param name="isNextLevelNumberingReset" select="$isNextLevelNumberingReset"/>
+ <xsl:with-param name="itemNumber" select="$itemNumber"/>
+ <xsl:with-param name="listIndent" select="$listIndent"/>
+ <!-- receives the same parent label, only with a different itemNumber -->
+ <xsl:with-param name="itemLabel" select="$itemLabel"/>
+ <xsl:with-param name="listLevel" select="$listLevel"/>
+ <xsl:with-param name="listStyle" select="$listStyle"/>
+ <xsl:with-param name="listStyleName" select="$listStyleName"/>
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <xsl:template match="text()" mode="list-item-children">
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+
+ <xsl:template name="create-list-style">
+ <xsl:param name="globalData"/>
+ <xsl:param name="listIndent" select="0"/>
+ <xsl:param name="styleName"/>
+
+ <xsl:if test="$styleName">
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate($styleName, '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:attribute name="style">
+ <xsl:text>margin-</xsl:text>
+ <xsl:call-template name="getOppositeWritingDirection">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="paraStyleName" select="descendant-or-self::*/@text:style-name"/>
+ </xsl:call-template>
+ <xsl:text>:</xsl:text>
+ <xsl:value-of select="$listIndent"/>
+ <xsl:text>cm;</xsl:text>
+ </xsl:attribute>
+ </xsl:template>
+
+
+ <!-- ********************************************** -->
+ <!-- *** Text Section (contains: draw:text-box) *** -->
+ <!-- ********************************************** -->
+
+ <xsl:template match="text:section">
+ <xsl:param name="globalData"/>
+
+ <xsl:if test="not(contains(@text:display, 'none'))">
+ <xsl:comment>Next 'div' was a 'text:section'.</xsl:comment>
+ <xsl:element name="div">
+ <xsl:call-template name="apply-styles-and-content">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+
+ <!-- Hidden text dependent on Office variables:
+ The text is not shown, if condition is 'true'.
+ Implemented solely for conditions as '<VARIABLE>==0' or '<VARIABLE>==1'
+ -->
+ <xsl:key match="text:variable-set" name="varSet" use="@text:name"/>
+ <xsl:template match="text:hidden-text">
+ <xsl:param name="globalData"/>
+
+ <xsl:variable name="varName" select="substring-before(@text:condition, '==')"/>
+ <xsl:variable name="varValue" select="substring-after(@text:condition, '==')"/>
+ <xsl:choose>
+ <xsl:when test="key('varSet', $varName)/@text:value != $varValue">
+ <xsl:value-of select="@text:string-value"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:comment>
+ <xsl:value-of select="$varName"/>
+ <xsl:value-of select="@text:string-value"/>
+ <xsl:value-of select="$varName"/>
+ </xsl:comment>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template match="@text:style-name | @draw:style-name | @draw:text-style-name | @table:style-name"><!-- | @presentation:style-name-->
+ <xsl:param name="globalData"/>
+
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate(., '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+ </xsl:template>
+
+
+ <!-- ***************** -->
+ <!-- *** Footnotes *** -->
+ <!-- ***************** -->
+
+ <xsl:template match="text:note">
+ <xsl:param name="globalData"/>
+
+ <!-- get style configuration -->
+ <xsl:variable name="footnoteConfig" select="$globalData/office:styles/text:notes-configuration[@text:note-class=current()/@text:note-class]" />
+
+ <xsl:variable name="titlePrefix">
+ <xsl:choose>
+ <xsl:when test="@text:note-class = 'footnote'">
+ <xsl:text>Footnote: </xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:text>Endnote: </xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <!-- write anchor -->
+ <xsl:element name="span">
+ <xsl:attribute name="class">
+ <xsl:value-of select="$footnoteConfig/@text:citation-body-style-name"/>
+ </xsl:attribute>
+ <xsl:attribute name="title">
+ <xsl:value-of select="$titlePrefix"/>
+ <xsl:apply-templates mode="textOnly" select="text:note-body"/>
+ </xsl:attribute>
+ <xsl:element name="a">
+ <xsl:attribute name="href">
+ <xsl:value-of select="concat('#', @text:id)"/>
+ </xsl:attribute>
+ <xsl:attribute name="id">
+ <xsl:value-of select="concat('body_', @text:id)"/>
+ </xsl:attribute>
+ <xsl:apply-templates mode="textOnly" select="text:note-citation"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="*" mode="textOnly">
+ <xsl:apply-templates select="* | text()" mode="textOnly" />
+ </xsl:template>
+
+ <xsl:template match="text()" mode="textOnly">
+ <xsl:value-of select="."/>
+ </xsl:template>
+
+ <!-- Useful in case of 'style:map', conditional formatting, where a style references to another -->
+ <xsl:key name="textNotes" match="text:note" use="@text:note-class"/>
+
+ <!-- writing the footer- and endnotes beyond the body -->
+ <xsl:template name="write-text-nodes">
+ <xsl:param name="globalData"/>
+
+ <!-- write footnote body -->
+ <xsl:for-each select="key('textNotes', 'footnote')">
+ <xsl:call-template name="write-text-node">
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="footnoteConfig" select="$globalData/office:styles/text:notes-configuration[@text:note-class=current()/@text:note-class]" />
+ </xsl:call-template>
+ </xsl:for-each>
+
+ <!-- write endnote body -->
+ <xsl:for-each select="key('textNotes', 'endnote')">
+ <xsl:call-template name="write-text-node">
+
+ <xsl:with-param name="globalData" select="$globalData"/>
+ <xsl:with-param name="footnoteConfig" select="$globalData/office:styles/text:notes-configuration[@text:note-class=current()/@text:note-class]" />
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:template>
+
+ <xsl:template name="write-text-node">
+ <xsl:param name="globalData"/>
+ <xsl:param name="footnoteConfig"/>
+
+ <xsl:apply-templates select="text:note-body/*[1]">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="footnotePrefix">
+ <xsl:element name="span">
+ <xsl:attribute name="class">footnodeNumber</xsl:attribute>
+ <xsl:element name="a">
+ <xsl:attribute name="class">
+ <xsl:value-of select="$footnoteConfig/@text:citation-style-name"/>
+ </xsl:attribute>
+ <xsl:attribute name="id">
+ <xsl:value-of select="@text:id"/>
+ </xsl:attribute>
+ <xsl:attribute name="href">
+ <xsl:value-of select="concat('#body_', @text:id)"/>
+ </xsl:attribute>
+ <xsl:apply-templates mode="textOnly" select="text:note-citation"/>
+ </xsl:element>
+ </xsl:element>
+ </xsl:with-param>
+ </xsl:apply-templates>
+ <xsl:apply-templates select="text:note-body/*[position()&gt;1]">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:apply-templates>
+ </xsl:template>
+
+ <!-- ***************** -->
+ <!-- *** Bookmarks *** -->
+ <!-- ***************** -->
+
+ <xsl:template match="text:bookmark|text:bookmark-start">
+ <xsl:element name="a">
+ <xsl:attribute name="id">
+ <xsl:value-of select="@text:name"/>
+ </xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="text:bookmark-end"/>
+
+ <!-- DISABLING this tab handling as the tab width is only relative
+ <xsl:template match="text:tab">
+ <xsl:param name="globalData"/>
+
+ <xsl:variable name="tabNo">
+ <xsl:choose>
+ <xsl:when test="preceding-sibling::text:line-break">
+ <xsl:call-template name="countTextTab"/>
+ </xsl:when>
+ <xsl:when test="preceding-sibling::text:tab">
+ <xsl:value-of select="count(preceding-sibling::text:tab)"/>
+ </xsl:when>
+ <xsl:otherwise>1</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:element name="span">
+ <xsl:attribute name="style">margin-left:<xsl:value-of select="$globalData/all-doc-styles/style[@style:name = current()/parent::*/@text:style-name]/*/style:tab-stops/style:tab-stop[$tabNo]/@style:position"/>;</xsl:attribute>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template name="countTextTab">
+ <xsl:param name="tabCount" select="1"/>
+ <xsl:param name="context" select="."/>
+
+ <xsl:choose>
+ <xsl:when test="preceding-sibling::*[1]">
+ <xsl:for-each select="preceding-sibling::*[1]">
+ <xsl:call-template name="countTextTab">
+ <xsl:with-param name="tabCout">
+ <xsl:choose>
+ <xsl:when test="name(.) = 'text:tab'">
+ <xsl:value-of select="$tabCount + 1"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$tabCount"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:with-param>
+ <xsl:with-param name="context" select="preceding-sibling::*[1]" />
+ </xsl:call-template>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="$tabCount"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+-->
+ <!-- MathML -->
+ <xsl:template match="draw:object[math:math]">
+ <xsl:apply-templates select="math:math" mode="math"/>
+ </xsl:template>
+
+ <xsl:template match="*" mode="math">
+ <xsl:element name="{local-name()}" namespace="http://www.w3.org/1998/Math/MathML">
+ <xsl:apply-templates select="@*|node()" mode="math"/>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template match="@*" mode="math">
+ <xsl:attribute name="{local-name()}">
+ <xsl:value-of select="."/>
+ </xsl:attribute>
+ </xsl:template>
+
+ <!-- our mathml should always be inline the text flow -->
+ <xsl:template match="@display" mode="math">
+ <xsl:attribute name="{local-name()}">inline</xsl:attribute>
+ </xsl:template>
+
+ <!-- Ignore semantic annotations -->
+ <xsl:template match="math:semantics" mode="math">
+ <xsl:apply-templates select="*[1]" mode="math"/>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl
new file mode 100644
index 000000000..2bd07d8d2
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/xhtml/header.xsl
@@ -0,0 +1,480 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xforms="http://www.w3.org/2002/xforms"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xforms xsd xsi"
+ xmlns="http://www.w3.org/1999/xhtml">
+
+ <!-- ************** -->
+ <!-- *** header *** -->
+ <!-- ************** -->
+
+ <xsl:template name="create-header">
+ <xsl:param name="globalData" />
+
+ <xsl:element name="head">
+ <xsl:attribute name="profile">http://dublincore.org/documents/dcmi-terms/</xsl:attribute>
+ <xsl:if test="$debugEnabled"><xsl:message>CSS helper variable will be created...</xsl:message></xsl:if>
+ <xsl:call-template name='xhtml-header-properties'>
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+
+ <xsl:if test="$debugEnabled"><xsl:message>CSS variable ready, header will be created...</xsl:message></xsl:if>
+ <!-- constructing the css header simulating inheritance of style-families by style order -->
+ <xsl:call-template name='create-css-styleheader'>
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ <xsl:if test="$debugEnabled"><xsl:message>CSS header creation finished!</xsl:message></xsl:if>
+ </xsl:element>
+
+ </xsl:template>
+
+ <!-- Creating a CSS style header from the collected styles of the 'globalData' parameter -->
+ <xsl:template name='create-css-styleheader'>
+ <xsl:param name="globalData" />
+
+ <xsl:element name="style">
+ <!-- https://validator.w3.org/unicorn:
+ The “type” attribute for the “style” element is not needed and should be omitted.
+ <xsl:attribute name="type">text/css</xsl:attribute> -->
+<xsl:text>
+ </xsl:text>
+ <xsl:call-template name='create-page-layout'>
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+<xsl:text>table { border-collapse:collapse; border-spacing:0; empty-cells:show }
+ </xsl:text>
+ <xsl:choose>
+ <xsl:when test="/*/office:body/office:spreadsheet"><xsl:text>td, th { vertical-align:top; font-size:10pt;}
+ </xsl:text></xsl:when>
+ <xsl:otherwise><xsl:text>td, th { vertical-align:top; font-size:12pt;}
+ </xsl:text></xsl:otherwise>
+ </xsl:choose>
+<xsl:text>h1, h2, h3, h4, h5, h6 { clear:both;}
+ </xsl:text>
+<xsl:choose>
+ <xsl:when test="/*/office:body/office:spreadsheet">
+ <xsl:text>p { white-space: nowrap; }
+ </xsl:text>
+ </xsl:when>
+</xsl:choose>
+<xsl:text>ol, ul { margin:0; padding:0;}
+ </xsl:text>
+<xsl:text>li { list-style: none; margin:0; padding:0;}
+ </xsl:text>
+<xsl:text>span.footnodeNumber { padding-right:1em; }
+ </xsl:text>
+<xsl:text>span.annotation_style_by_filter { font-size:95%; font-family:Arial; background-color:#fff000; margin:0; border:0; padding:0; }
+ </xsl:text>
+<!-- Simulate tabs. They are around 0.64cm in LO, we convert that to 0.8rem. -->
+<xsl:text>span.heading_numbering { margin-right: 0.8rem; }</xsl:text>
+<xsl:text>* { margin:0;}
+ </xsl:text>
+ <xsl:call-template name="write-mapped-CSS-styles">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+
+ <xsl:template name="write-mapped-CSS-styles">
+ <xsl:param name="globalData" />
+ <xsl:param name="emptyStyles"/>
+
+ <xsl:for-each select="$globalData/all-styles/style">
+ <xsl:if test="final-properties != ''">
+ <!-- NOTE: easy process, as only the style family in conjunction with the style name, makes the style unambiguous -->
+ <xsl:text>.</xsl:text><!--<xsl:value-of select="@style:family" /><xsl:text>:</xsl:text>--><xsl:value-of select="translate(@style:name, '.,;: %()[]/\+', '_____________')"/><xsl:text> { </xsl:text> <xsl:value-of select="final-properties" /><xsl:text>}
+ </xsl:text>
+ </xsl:if>
+
+ </xsl:for-each>
+ <!-- Otherwise all styles have been processed and the empty styles have to be given out -->
+ <xsl:text>/* ODF styles with no properties representable as CSS:
+ </xsl:text><xsl:for-each select="$globalData/all-styles/style[final-properties = '']"><xsl:value-of select="concat('.', @style:name, ' ')"/></xsl:for-each><xsl:text> { } */
+</xsl:text>
+ </xsl:template>
+
+ <!-- Creating CSS page layout based on first office master style -->
+ <xsl:template name='create-page-layout'>
+ <xsl:param name="globalData" />
+
+ <!-- approximation to find the correct master page style (with page dimensions) -->
+ <xsl:variable name="masterPageNames">
+ <!-- set context to styles.xml -->
+ <xsl:for-each select="$globalData/all-doc-styles/style">
+ <!-- Loop over every style:style containing a @style:master-page-name attribute -->
+ <xsl:for-each select="key('masterPage','count')">
+ <!-- set context to styles.xml -->
+ <xsl:for-each select="/*/office:body">
+ <!-- Check if this style is being used in the body -->
+ <xsl:if test="key('elementUsingStyle', ../@style:name)">
+ <!-- Check every master-page-name if it is not empty and return as ';' separated list -->
+ <xsl:if test="string-length(../@style:master-page-name) &gt; 0"><xsl:value-of select="../@style:master-page-name"/>;</xsl:if>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:for-each>
+ </xsl:variable>
+ <!-- Take the first of the masterpage list and get the according style:master-page element and find the @style:page-layout-name -->
+ <xsl:variable name="pageLayoutName" select="key('masterPageElements', substring-before($masterPageNames,';'))/@style:page-layout-name"/>
+ <!-- Find the according style:page-layout and store the properties in a variable -->
+ <xsl:variable name="pageProperties" select="key('pageLayoutElements', $pageLayoutName)/style:page-layout-properties"/>
+
+ <xsl:variable name="pageSize">
+ <xsl:call-template name="page-size">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="pageProperties" select="$pageProperties" />
+ </xsl:call-template>
+ <xsl:call-template name="page-margin">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="pageProperties" select="$pageProperties" />
+ </xsl:call-template>
+ </xsl:variable>
+
+ <xsl:if test="$pageSize and $pageSize!=''">
+<xsl:text>@page { </xsl:text>
+<xsl:value-of select="$pageSize"/>
+<xsl:text> }
+ </xsl:text>
+ </xsl:if>
+ </xsl:template>
+
+
+ <xsl:template name="page-size">
+ <xsl:param name="globalData" />
+ <xsl:param name="pageProperties" />
+
+ <xsl:variable name="printOrientation" select="$pageProperties/@style:print-orientation" />
+ <xsl:variable name="pageWidth" select="$pageProperties/@fo:page-width" />
+ <xsl:variable name="pageHeight" select="$pageProperties/@fo:page-height" />
+ <xsl:choose>
+ <xsl:when test="$pageWidth and $pageHeight">
+ <xsl:text>size: </xsl:text>
+ <xsl:value-of select="$pageWidth" />
+ <xsl:text> </xsl:text>
+ <xsl:value-of select="$pageHeight" />
+ <xsl:text>; </xsl:text>
+ </xsl:when>
+ <xsl:when test="$printOrientation">
+ <xsl:text>size: </xsl:text>
+ <xsl:value-of select="$printOrientation" />
+ <xsl:text>; </xsl:text>
+ </xsl:when>
+ </xsl:choose>
+ </xsl:template>
+
+ <xsl:template name="page-margin">
+ <xsl:param name="globalData" />
+ <xsl:param name="pageProperties" />
+
+ <xsl:variable name="marginTop" select="$pageProperties/@fo:margin-top" />
+ <xsl:if test="$marginTop">
+ <xsl:text>margin-top: </xsl:text>
+ <xsl:value-of select="$marginTop" />
+ <xsl:text>; </xsl:text>
+ </xsl:if>
+ <xsl:variable name="marginBottom" select="$pageProperties/@fo:margin-bottom" />
+ <xsl:if test="$marginBottom">
+ <xsl:text>margin-bottom: </xsl:text>
+ <xsl:value-of select="$marginBottom" />
+ <xsl:text>; </xsl:text>
+ </xsl:if>
+ <xsl:variable name="marginLeft" select="$pageProperties/@fo:margin-left" />
+ <xsl:if test="$marginLeft">
+ <xsl:text>margin-left: </xsl:text>
+ <xsl:value-of select="$marginLeft" />
+ <xsl:text>; </xsl:text>
+ </xsl:if>
+ <xsl:variable name="marginRight" select="$pageProperties/@fo:margin-right" />
+ <xsl:if test="$marginRight">
+ <xsl:text>margin-right: </xsl:text>
+ <xsl:value-of select="$marginRight" />
+ </xsl:if>
+ </xsl:template>
+
+ <!-- *************************** -->
+ <!-- *** Common XHTML header *** -->
+ <!-- *************************** -->
+
+ <xsl:template name='xhtml-header-properties'>
+ <xsl:param name="globalData" />
+
+ <xsl:variable name="netloc">
+ <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:user-defined">
+ <xsl:if test="./@meta:name='ODF.base'">
+ <xsl:value-of select="." />
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:user-defined">
+ <xsl:if test="./@meta:name='ODF.filename'">
+ <xsl:value-of select="." />
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <xsl:variable name="lang">
+ <xsl:choose>
+ <xsl:when test="$globalData/meta-file/*/office:meta/dc:language">
+ <xsl:value-of select="$globalData/meta-file/*/office:meta/dc:language" />
+ </xsl:when>
+ <xsl:otherwise>en-US</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="prov">
+ <xsl:choose>
+ <xsl:when test="$globalData/meta-file/*/office:meta/meta:printed-by">
+ <xsl:value-of select="concat('Printed by &quot;',$globalData/meta-file/*/office:meta/meta:printed-by,'&quot;[dc:publisher] on &quot;',$globalData/meta-file/*/office:meta/meta:print-date,'&quot;[dc:date] in &quot;',$lang,'&quot;[dc:language]')" />
+ </xsl:when>
+ <xsl:otherwise />
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:variable name="keywords">
+ <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:keyword">
+ <xsl:value-of select="." />
+ <xsl:if test="position() != last()">
+ <xsl:text>, </xsl:text>
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:variable>
+
+ <!-- explicit output content-type for low-tech browser (e.g. IE6) -->
+ <xsl:element name="meta">
+ <xsl:attribute name="http-equiv">Content-Type</xsl:attribute>
+ <xsl:attribute name="content">application/xhtml+xml; charset=utf-8</xsl:attribute>
+ </xsl:element>
+
+ <!-- title of document for browser frame title -->
+ <xsl:element name="title">
+ <xsl:attribute name="xml:lang">
+ <xsl:value-of select="$lang" />
+ </xsl:attribute>
+
+ <xsl:choose>
+ <xsl:when test="$globalData/meta-file/*/office:meta/dc:title">
+ <xsl:value-of select="$globalData/meta-file/*/office:meta/dc:title" />
+ </xsl:when>
+ <!-- providing the mandatory title is a workaround for an IE bug-->
+ <xsl:otherwise>
+ <xsl:text>- no title specified</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:element>
+
+ <!-- title, in DC syntax -->
+ <xsl:element name="meta">
+ <xsl:attribute name="name">DCTERMS.title</xsl:attribute>
+ <xsl:attribute name="content">
+ <xsl:value-of select="$globalData/meta-file/*/office:meta/dc:title" />
+ </xsl:attribute>
+ <xsl:attribute name="xml:lang">
+ <xsl:value-of select="$lang" />
+ </xsl:attribute>
+ </xsl:element>
+
+ <!-- the identifier for source (identifier) -->
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.identifier'" />
+ <xsl:with-param name="meta-data" select="translate($netloc, ' ','')" />
+ <xsl:with-param name="meta-enc" select="'DCTERMS.URI'" />
+ </xsl:call-template>
+
+ <!-- the language for source (language) -->
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.language'" />
+ <xsl:with-param name="meta-data" select="$lang" />
+ <xsl:with-param name="meta-enc" select="'DCTERMS.RFC4646'" />
+ </xsl:call-template>
+
+ <!-- a bit commercial (generator) -->
+ <xsl:element name="meta">
+ <xsl:attribute name="name">DCTERMS.source</xsl:attribute>
+ <xsl:attribute name="content">http://xml.openoffice.org/odf2xhtml</xsl:attribute>
+ </xsl:element>
+
+ <!-- the author of the input source (author) -->
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.creator'" />
+ <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/meta:initial-creator" />
+ </xsl:call-template>
+
+ <!-- creation-date of the input source (issued) -->
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.issued'" />
+ <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/meta:creation-date" />
+ <xsl:with-param name="meta-enc" select="'DCTERMS.W3CDTF'" />
+ </xsl:call-template>
+
+ <!-- name of last changing person of the input source (changedby) -->
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.contributor'" />
+ <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/dc:creator" />
+ </xsl:call-template>
+
+ <!-- last changing date of the input source (changed) -->
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.modified'" />
+ <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/dc:date" />
+ <xsl:with-param name="meta-enc" select="'DCTERMS.W3CDTF'" />
+ </xsl:call-template>
+
+ <!-- Last print, as provenance -->
+ <xsl:if test="$prov">
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.provenance'" />
+ <xsl:with-param name="meta-data" select="$prov" />
+ <xsl:with-param name="meta-lang" select="$lang" />
+ </xsl:call-template>
+ </xsl:if>
+
+ <!-- keywords about the input source (keywords) -->
+ <xsl:if test="($globalData/meta-file/*/office:meta/dc:subject != '') or ($keywords != '')">
+ <xsl:choose>
+ <xsl:when test="($globalData/meta-file/*/office:meta/dc:subject != '') and ($keywords != '')">
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.subject'" />
+ <xsl:with-param name="meta-data" select="normalize-space(concat($globalData/meta-file/*/office:meta/dc:subject,', ',$keywords))" />
+ <xsl:with-param name="meta-lang" select="$lang" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:when test="($globalData/meta-file/*/office:meta/dc:subject != '')">
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.subject'" />
+ <xsl:with-param name="meta-data" select="normalize-space($globalData/meta-file/*/office:meta/dc:subject)" />
+ <xsl:with-param name="meta-lang" select="$lang" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.subject'" />
+ <xsl:with-param name="meta-data" select="normalize-space($keywords)" />
+ <xsl:with-param name="meta-lang" select="$lang" />
+ </xsl:call-template>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+
+ <!-- detailed description about the input source (description) -->
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'DCTERMS.description'" />
+ <xsl:with-param name="meta-data" select="$globalData/meta-file/*/office:meta/dc:description" />
+ <xsl:with-param name="meta-lang" select="$lang" />
+ </xsl:call-template>
+
+
+ <!-- user defined use of DCTERM tags -->
+ <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:user-defined[starts-with(@meta:name,'DCTERMS.')][not(.='')]">
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="@meta:name" />
+ <xsl:with-param name="meta-data" select="." />
+ <!-- <xsl:with-param name="meta-lang" select="$lang" /> -->
+ </xsl:call-template>
+ </xsl:for-each>
+ <!-- user defined use of DC tags (legacy) -->
+ <xsl:for-each select="$globalData/meta-file/*/office:meta/meta:user-defined[starts-with(@meta:name,'DC.')][not(.='')]">
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="@meta:name" />
+ <xsl:with-param name="meta-data" select="." />
+ <!-- <xsl:with-param name="meta-lang" select="$lang" /> -->
+ </xsl:call-template>
+ </xsl:for-each>
+ <xsl:call-template name="add-meta-tag">
+ <xsl:with-param name="meta-name" select="'xsl:vendor'" />
+ <xsl:with-param name="meta-data" select="system-property('xsl:vendor')" />
+ </xsl:call-template>
+
+ <link rel="schema.DC" href="http://purl.org/dc/elements/1.1/" hreflang="en" />
+ <link rel="schema.DCTERMS" href="http://purl.org/dc/terms/" hreflang="en" />
+ <link rel="schema.DCTYPE" href="http://purl.org/dc/dcmitype/" hreflang="en" />
+ <link rel="schema.DCAM" href="http://purl.org/dc/dcam/" hreflang="en" />
+ <!-- W3C GRDDL Profile -->
+ <!--
+ <link rel="transformation" href="http://xml.openoffice.org/odf2xhtml/rdf-extract.xsl" />
+ -->
+
+ <!-- base URL of document for resolving relative links
+ NOTE: CHROME has a problem, with relative references as from content table, referencing to root directory instead of document
+ <xsl:element name="base">
+ <xsl:attribute name="href">-->
+ <!-- earlier 'targetURL' was used for an absolute reference of base provided by the Office (file URL)
+ <xsl:value-of select="$targetURL" />
+ now '.' let relative links work, even if document has been moved -->
+ <!--<xsl:text>.</xsl:text>
+ </xsl:attribute>
+ </xsl:element>-->
+ </xsl:template>
+
+ <!-- generic template for adding common meta tags -->
+ <xsl:template name="add-meta-tag">
+ <xsl:param name="meta-name" />
+ <xsl:param name="meta-data" />
+ <xsl:param name="meta-enc" />
+ <xsl:param name="meta-lang" />
+
+ <xsl:if test="$meta-data and $meta-data != ''">
+ <xsl:element name="meta">
+ <xsl:attribute name="name">
+ <xsl:value-of select="$meta-name" />
+ </xsl:attribute>
+ <xsl:attribute name="content">
+ <xsl:value-of select="$meta-data" />
+ </xsl:attribute>
+ <xsl:if test="$meta-enc">
+ <xsl:attribute name="scheme">
+ <xsl:value-of select="$meta-enc" />
+ </xsl:attribute>
+ </xsl:if>
+ <xsl:if test="$meta-lang">
+ <xsl:attribute name="xml:lang">
+ <xsl:value-of select="$meta-lang" />
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ </xsl:if>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl
new file mode 100644
index 000000000..196b85eae
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/xhtml/opendoc2xhtml.xsl
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+-->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xforms="http://www.w3.org/2002/xforms"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi xforms xsd xsi"
+ xmlns="http://www.w3.org/1999/xhtml">
+
+
+ <!--+++++ INCLUDED XSL MODULES +++++-->
+
+ <!-- inheritance of office style properties is resolved into absolute styles. Office properties gathered as elements -->
+ <xsl:include href="../common/styles/style_collector.xsl" />
+
+ <!-- mapping rules of office style properties to CSS/HTML properties -->
+ <xsl:include href="../common/styles/style_mapping_css.xsl" />
+
+ <!-- office header element handling especially for XHTML -->
+ <xsl:include href="header.xsl" />
+
+ <!-- office body element handling especially for XHTML -->
+ <xsl:include href="body.xsl" />
+
+
+ <xsl:output method = "xml"
+ encoding = "UTF-8"
+ media-type = "application/xhtml+xml"
+ indent = "no"
+ omit-xml-declaration = "no"
+ doctype-public = "-//W3C//DTD XHTML 1.1 plus MathML 2.0//EN"
+ doctype-system = "http://www.w3.org/Math/DTD/mathml2/xhtml-math11-f.dtd" />
+
+
+
+ <xsl:variable name="namespace" select="'http://www.w3.org/1999/xhtml'" />
+
+ <!--+++++ PARAMETER SECTION +++++-->
+
+ <!-- OPTIONAL: if the document content is provided in a directory structure. Opposite to a single flat XML stream -->
+ <xsl:param name="isPackageFormat" />
+
+ <!-- OPTIONAL: (MANDATORY: for all input document with relative external links): parameter is an absolute file URL to the target directory.
+ Relative links from the office document (e.g. to external graphics) will get this parameter as a prefix -->
+ <xsl:param name="targetBaseURL" select="'./'" />
+
+ <!-- OPTIONAL: (MANDATORY: for all input document with content table) : parameter is an absolute file URL to the target document.
+ Relative links to this office document (e.g. to internal anchor) will get this parameter as a prefix -->
+ <xsl:param name="targetURL" select="'./'" />
+
+ <!-- OPTIONAL: (MANDATORY: for input document with relative internal links)
+ To access contents of an office file (content like the meta.xml, styles.xml file or graphics) a URL could be chosen.
+ This could be even a JAR URL. The sourceBase of the content URL "jar:file:/C:/temp/Test.sxw!/content.xml" would be
+ "jar:file:/C:/temp/Test.sxw!/" for example.
+ When working with OpenOffice API a Package-URL encoded over HTTP can be used to access the jared contents of the jared document. -->
+ <xsl:param name="sourceBaseURL" select="'./'" />
+
+ <!-- OPTIONAL: (MANDATORY: for session management by URL rewriting)
+ Useful for WebApplications: if a HTTP session is not cookie based, URL rewriting is being used (the session is appended to the URL).
+ This URL session is used for example when links to graphics are created by XSLT. Otherwise the user have to log again in for every graphic he likes to see. -->
+ <xsl:param name="optionalURLSuffix" />
+
+ <!-- OPTIONAL: URL to office meta file (flat xml use the URL to the input file) -->
+ <xsl:param name="metaFileURL" />
+
+ <!-- OPTIONAL: URL to office meta file (flat xml use the URL to the input file) -->
+ <xsl:param name="stylesFileURL" />
+
+ <!-- OPTIONAL: DPI (dots per inch) the standard resolution of given pictures (necessary for the conversion of 'cm' into 'pixel')-->
+ <!-- Although many pictures have a 96 dpi resolution, a higher resolution give better results for common browsers -->
+ <!-- Cp. measure_conversion.xsl:
+ <xsl:param name="dpi" select="111" /> -->
+
+
+ <!-- OPTIONAL: in case of using a different processor than a JAVA XSLT, you can unable the Java functionality
+ (e.g. encoding chapter names for the content-table as href and anchors ) -->
+ <xsl:param name="java" select="true()" />
+ <xsl:param name="javaEnabled" select="boolean($java)" />
+
+ <!-- OPTIONAL: for activating the debug mode set the variable here to 'true()' or give any value from outside -->
+ <xsl:param name="debug" select="false()" />
+ <xsl:param name="debugEnabled" select="boolean($debug)" />
+ <xsl:param name="onlyStyleOutput" select="false()" />
+ <xsl:param name="onlyStyleOutputEnabled" select="boolean($onlyStyleOutput)" />
+
+ <!-- *************************************** -->
+ <!-- *** build the appropriate HTML file *** -->
+ <!-- *************************************** -->
+ <xsl:template match="/">
+ <!-- debug output of parameter value set -->
+ <xsl:if test="$debugEnabled">
+ <xsl:call-template name="debug-check-parameter" />
+ </xsl:if>
+ <xsl:message>XSL Vendor: '<xsl:value-of select="system-property('xsl:vendor')"/>'</xsl:message>
+ <!-- gathers style properties and
+ returns them as globalData parameter to the 'start-main' template -->
+ <xsl:call-template name="collect-global-odf-properties" />
+ </xsl:template>
+
+
+ <!-- *************************** -->
+ <!-- *** Built up XHTML file *** -->
+ <!-- *************************** -->
+ <xsl:template name="start-main">
+ <xsl:param name="globalData" />
+
+ <xsl:variable name="lang">
+ <xsl:choose>
+ <xsl:when test="$globalData/meta-file/*/office:meta/dc:language">
+ <xsl:value-of select="$globalData/meta-file/*/office:meta/dc:language" />
+ </xsl:when>
+ <xsl:otherwise>en-US</xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+
+ <xsl:element name="html">
+
+ <xsl:attribute name="lang"><xsl:value-of select="$lang"/></xsl:attribute>
+ <xsl:comment>This file was converted to xhtml by LibreOffice - see https://cgit.freedesktop.org/libreoffice/core/tree/filter/source/xslt for the code.</xsl:comment>
+ <xsl:call-template name='create-header'>
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+
+ <xsl:call-template name='create-body'>
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- debug purpose only:
+ verbose checking of the parameters of this template-->
+ <xsl:template name="debug-check-parameter">
+ <xsl:message>Parameter dpi: <xsl:value-of select="$dpi" /></xsl:message>
+ <xsl:message>Parameter metaFileURL: <xsl:value-of select="$metaFileURL" /></xsl:message>
+ <xsl:message>Parameter stylesFileURL: <xsl:value-of select="$stylesFileURL" /></xsl:message>
+ <xsl:message>Parameter sourceBaseURL: <xsl:value-of select="$sourceBaseURL" /></xsl:message>
+ <xsl:message>Parameter targetBaseURL: <xsl:value-of select="$targetBaseURL" /></xsl:message>
+ <xsl:message>Parameter onlyStyleOutputEnabled: <xsl:value-of select="$onlyStyleOutputEnabled" /></xsl:message>
+ <xsl:message>Parameter debugEnabled: <xsl:value-of select="$debugEnabled" /></xsl:message>
+ <xsl:message>Parameter java: <xsl:value-of select="$java" /></xsl:message>
+ <xsl:message>Parameter javaEnabled: <xsl:value-of select="$javaEnabled" /></xsl:message>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/filter/source/xslt/odf2xhtml/export/xhtml/table.xsl b/filter/source/xslt/odf2xhtml/export/xhtml/table.xsl
new file mode 100644
index 000000000..8448665d2
--- /dev/null
+++ b/filter/source/xslt/odf2xhtml/export/xhtml/table.xsl
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+<!--
+ For further documentation and updates visit http://xml.openoffice.org/odf2xhtml
+-->
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0"
+ xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:dom="http://www.w3.org/2001/xml-events"
+ xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0"
+ xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0"
+ xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
+ xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0"
+ xmlns:math="http://www.w3.org/1998/Math/MathML"
+ xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0"
+ xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0"
+ xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
+ xmlns:ooo="http://openoffice.org/2004/office"
+ xmlns:oooc="http://openoffice.org/2004/calc"
+ xmlns:ooow="http://openoffice.org/2004/writer"
+ xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0"
+ xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
+ xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
+ xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
+ xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
+ xmlns:xforms="http://www.w3.org/2002/xforms"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ exclude-result-prefixes="chart config dc dom dr3d draw fo form math meta number office ooo oooc ooow script style svg table text xforms xlink xsd xsi"
+ xmlns="http://www.w3.org/1999/xhtml">
+
+
+
+ <!-- current node is a table:table -->
+ <xsl:template name="create-table-children">
+ <xsl:param name="globalData" />
+ <xsl:param name="allVisibleTableRows" />
+ <xsl:param name="allTableColumns" />
+
+ <xsl:element name="colgroup">
+ <xsl:for-each select="$allTableColumns/table:table-column">
+ <xsl:if test="not(@table:visibility = 'collapse' or @table:visibility = 'filter')">
+ <xsl:element name="col">
+ <xsl:variable name="value" select="$globalData/all-doc-styles/style[@style:name = current()/@table:style-name]/*/@style:column-width" />
+ <xsl:if test="$value">
+ <xsl:attribute name="width">
+ <!-- using the absolute width, problems with the relative in browser (in OOo style:rel-column-width) -->
+ <xsl:call-template name="convert2px">
+ <xsl:with-param name="value" select="$globalData/all-doc-styles/style[@style:name = current()/@table:style-name]/*/@style:column-width" />
+ </xsl:call-template>
+ </xsl:attribute>
+ </xsl:if>
+ </xsl:element>
+ <!-- *** the column-style ***
+ <xsl:attribute name="width">
+ <xsl:variable name="currentColumnStyleName" select="$allTableColumns/table:table-column[position() = $columnPosition]/@table:style-name" />
+ <xsl:value-of select="$globalData/all-doc-styles/style[@style:name = $currentColumnStyleName]/*/@style:column-width" />
+ </xsl:attribute>-->
+ </xsl:if>
+ </xsl:for-each>
+ </xsl:element>
+
+ <xsl:call-template name="create-table-rows">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="allVisibleTableRows" select="$allVisibleTableRows" />
+ <xsl:with-param name="allTableColumns" select="$allTableColumns" />
+ </xsl:call-template>
+ </xsl:template>
+
+
+
+ <!-- Creating the content of a table content using CSS styles -->
+ <xsl:template name="create-table-cell-content">
+ <xsl:param name="tableDataType" />
+ <xsl:param name="globalData" />
+ <xsl:param name="allTableColumns" />
+ <xsl:param name="columnPosition" />
+ <xsl:param name="currentTableColumn" />
+
+ <xsl:element name="{$tableDataType}">
+
+ <!-- if parser reads DTD the default is set to '1' -->
+ <xsl:if test="@table:number-columns-spanned and @table:number-columns-spanned > 1">
+ <xsl:attribute name="colspan">
+ <xsl:value-of select="@table:number-columns-spanned" />
+ </xsl:attribute>
+ </xsl:if>
+ <!-- if parser reads DTD the default is set to '1' -->
+ <xsl:if test="@table:number-rows-spanned and @table:number-rows-spanned > 1">
+ <xsl:attribute name="rowspan">
+ <xsl:value-of select="@table:number-rows-spanned" />
+ </xsl:attribute>
+ </xsl:if>
+
+
+ <!-- *** the cell-style *** -->
+ <!-- The cell style has no conclusion with the column style, so we switch the order/priorities due to browser issues
+
+ The cell-style depends on two attributes:
+
+ 1) table:style-name - the style properties of cell. When they exist, a default alignment (cp. below) will be added for the
+ case of no alignment in the style exist.
+
+ 2) office:value-type - the value type of the table-cell giving the default alignments.
+ By default a string value is left aligned, all other are aligned:right.
+ -->
+ <xsl:choose>
+ <xsl:when test="@table:style-name">
+ <xsl:call-template name="set-styles">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="styleName" select="@table:style-name" />
+ <xsl:with-param name="currentTableColumn" select="$currentTableColumn" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- Cells without a style use the 'table:default-cell-style-name'
+ when there is no default cell style specified for the current column. -->
+ <xsl:variable name="defaultCellStyleName" select="$currentTableColumn/@table:default-cell-style-name" />
+ <xsl:choose>
+ <xsl:when test="$defaultCellStyleName">
+ <xsl:call-template name="set-styles">
+ <xsl:with-param name="globalData" select="$globalData" />
+ <xsl:with-param name="styleName" select="$defaultCellStyleName" />
+ <xsl:with-param name="currentTableColumn" select="$currentTableColumn" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <!-- No cell style exists, nor a default table cell style for the column -->
+ <xsl:attribute name="style">
+ <!-- sets cell alignment dependent of cell value type -->
+ <xsl:call-template name="set-cell-alignment" />
+ </xsl:attribute>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="$debugEnabled">
+ <xsl:message>A table cell '<xsl:value-of select="$tableDataType" />' element has been added!</xsl:message>
+ </xsl:if>
+
+ <!-- empty cell tags produce problems with width CSS style on itself other table cells as well
+ therefore a non breakable space (&nbsp;/&#160;) have been inserted.-->
+ <xsl:choose>
+ <xsl:when test="node()">
+ <xsl:call-template name="apply-styles-and-content">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:call-template name="apply-styles-and-content">
+ <xsl:with-param name="globalData" select="$globalData" />
+ </xsl:call-template>
+ <xsl:text>&#160;</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ </xsl:element>
+ </xsl:template>
+
+
+ <!-- Sets the cell alignment by the 'office:value-type' of the 'table:table-cell'.
+ Strings have a left alignment, other values right -->
+ <xsl:template name="set-cell-alignment">
+ <xsl:choose>
+ <xsl:when test="@office:value-type and not(@office:value-type = 'string')">text-align:right; </xsl:when>
+ <xsl:otherwise>text-align:left;</xsl:otherwise>
+ </xsl:choose>
+ </xsl:template>
+
+
+
+ <!-- Sets styles of a cell -->
+ <xsl:template name="set-styles">
+ <xsl:param name="globalData" />
+ <xsl:param name="styleName" />
+ <xsl:param name="currentTableColumn" />
+
+ <xsl:attribute name="style">
+ <!-- sets cell alignment dependent of cell value type -->
+ <xsl:call-template name="set-cell-alignment" />
+
+ <!-- set column style (disjunct of cell style) -->
+ <xsl:value-of select="$globalData/all-styles/style[@style:name = $currentTableColumn/@table:style-name]/final-properties" />
+
+ </xsl:attribute>
+
+ <!-- cell style header -->
+ <xsl:attribute name="class">
+ <xsl:value-of select="translate($styleName, '.,;: %()[]/\+', '_____________')"/>
+ </xsl:attribute>
+ </xsl:template>
+</xsl:stylesheet>
+
diff --git a/filter/source/xsltdialog/typedetectionexport.cxx b/filter/source/xsltdialog/typedetectionexport.cxx
new file mode 100644
index 000000000..30c4f894b
--- /dev/null
+++ b/filter/source/xsltdialog/typedetectionexport.cxx
@@ -0,0 +1,264 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <tools/urlobj.hxx>
+#include <tools/diagnose_ex.h>
+
+#include "typedetectionexport.hxx"
+#include "xmlfiltercommon.hxx"
+
+#include <comphelper/attributelist.hxx>
+#include <rtl/ref.hxx>
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::xml::sax;
+
+
+TypeDetectionExporter::TypeDetectionExporter( Reference< XComponentContext > const & xContext )
+: mxContext( xContext )
+{
+}
+
+static OUString createRelativeURL( std::u16string_view rFilterName, const OUString& rURL )
+{
+ if( !rURL.isEmpty() &&
+ !rURL.startsWith("http:") &&
+ !rURL.startsWith("https:") &&
+ !rURL.startsWith("jar:") &&
+ !rURL.startsWith("ftp:") )
+ {
+ INetURLObject aURL( rURL );
+ OUString aName(aURL.GetLastName());
+ if( aName.isEmpty() )
+ {
+ sal_Int32 nPos = rURL.lastIndexOf( '/' );
+ if( nPos == -1 )
+ {
+ aName = rURL;
+ }
+ else
+ {
+ aName = rURL.copy( nPos + 1 );
+ }
+ }
+
+ return OUString( OUString::Concat("vnd.sun.star.Package:") + rFilterName + "/" + aName );
+ }
+ else
+ {
+ return rURL;
+ }
+}
+
+void TypeDetectionExporter::doExport( const Reference< XOutputStream >& xOS, const std::vector<filter_info_impl*>& rFilters )
+{
+ try
+ {
+ static const OUStringLiteral sComponentData ( u"oor:component-data" );
+ static const OUStringLiteral sNode ( u"node" );
+ static const OUStringLiteral sName ( u"oor:name" );
+ static const OUStringLiteral sWhiteSpace ( u" " );
+ static const OUStringLiteral sUIName ( u"UIName" );
+ static const OUStringLiteral sComma ( u"," );
+ static const OUStringLiteral sDelim ( u";" );
+ static const OUStringLiteral sData ( u"Data" );
+ static const OUStringLiteral sDocTypePrefix ( u"doctype:" );
+ static const OUStringLiteral sFilterAdaptorService( u"com.sun.star.comp.Writer.XmlFilterAdaptor" );
+ static const OUStringLiteral sXSLTFilterService ( u"com.sun.star.documentconversion.XSLTFilter" );
+ static const OUStringLiteral sCdataAttribute ( u"CDATA" );
+
+
+ // set up sax writer and connect to given output stream
+ Reference< XWriter > xHandler = Writer::create( mxContext );
+ xHandler->setOutputStream( xOS );
+
+ rtl::Reference<::comphelper::AttributeList> pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( "xmlns:oor", sCdataAttribute, "http://openoffice.org/2001/registry" );
+ pAttrList->AddAttribute ( "xmlns:xs", sCdataAttribute, "http://www.w3.org/2001/XMLSchema" );
+ pAttrList->AddAttribute ( sName, sCdataAttribute, "TypeDetection" );
+ pAttrList->AddAttribute ( "oor:package", sCdataAttribute, "org.openoffice.Office" );
+
+ xHandler->startDocument();
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sComponentData, pAttrList );
+
+ // export types
+ {
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( sName, sCdataAttribute, "Types" );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sNode, pAttrList );
+
+ for (auto const& filter : rFilters)
+ {
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute( sName, sCdataAttribute, filter->maType );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sNode, pAttrList );
+ OUString sValue = "0" + sComma + sComma;
+ if( !filter->maDocType.isEmpty() )
+ {
+ sValue += sDocTypePrefix + filter->maDocType;
+ }
+ sValue += sComma + sComma + filter->maExtension + sComma +
+ OUString::number( filter->mnDocumentIconID ) + sComma;
+
+ addProperty( xHandler, sData, sValue );
+ addLocaleProperty( xHandler, sUIName, filter->maInterfaceName );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sNode );
+ }
+
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sNode );
+ }
+
+ // export filters
+ {
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( sName, sCdataAttribute, "Filters" );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sNode, pAttrList );
+
+ for (auto const& filter : rFilters)
+ {
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute( sName, sCdataAttribute, filter->maFilterName );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sNode, pAttrList );
+ addLocaleProperty( xHandler, sUIName, filter->maInterfaceName );
+
+ const application_info_impl* pAppInfo = getApplicationInfo( filter->maExportService );
+ OUString sValue =
+ "0" +
+ sComma +
+ filter->maType +
+ sComma +
+ filter->maDocumentService +
+ sComma +
+ sFilterAdaptorService +
+ sComma +
+ OUString::number( filter->maFlags ) +
+ sComma +
+ sXSLTFilterService +
+ sDelim +
+ OUString::boolean( filter->mbNeedsXSLT2 ) +
+ sDelim +
+ pAppInfo->maXMLImporter +
+ sDelim +
+ pAppInfo->maXMLExporter +
+ sDelim +
+ createRelativeURL( filter->maFilterName, filter->maImportXSLT ) +
+ sDelim +
+ createRelativeURL( filter->maFilterName, filter->maExportXSLT ) +
+ sDelim +
+ // entry DTD obsolete and removed, but delimiter kept
+ sDelim +
+ filter->maComment +
+ sComma +
+ "0" +
+ sComma +
+ createRelativeURL( filter->maFilterName, filter->maImportTemplate );
+ addProperty( xHandler, sData, sValue );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sNode );
+ }
+
+ xHandler->endElement( sNode );
+ }
+
+ // finish
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sComponentData );
+ xHandler->endDocument();
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void TypeDetectionExporter::addProperty( const Reference< XWriter >& xHandler, const OUString& rName, const OUString& rValue )
+{
+ try
+ {
+ static const OUStringLiteral sCdataAttribute( u"CDATA" );
+ static const OUStringLiteral sProp( u"prop" );
+ static const OUStringLiteral sValue( u"value" );
+ static const OUStringLiteral sWhiteSpace ( u" " );
+
+ rtl::Reference<::comphelper::AttributeList>pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( "oor:name", sCdataAttribute, rName );
+ pAttrList->AddAttribute ( "oor:type", sCdataAttribute, "xs:string" );
+
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sProp, pAttrList );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sValue, pAttrList );
+ xHandler->characters( rValue );
+ xHandler->endElement( sValue );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sProp );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void TypeDetectionExporter::addLocaleProperty( const Reference< XWriter >& xHandler, const OUString& rName, const OUString& rValue )
+{
+ try
+ {
+ static const OUStringLiteral sCdataAttribute( u"CDATA" );
+ static const OUStringLiteral sProp( u"prop" );
+ static const OUStringLiteral sValue( u"value" );
+ static const OUStringLiteral sWhiteSpace ( u" " );
+
+ rtl::Reference<::comphelper::AttributeList> pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( "oor:name", sCdataAttribute, rName );
+ pAttrList->AddAttribute ( "oor:type", sCdataAttribute, "xs:string" );
+
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sProp, pAttrList );
+ pAttrList = new ::comphelper::AttributeList;
+ pAttrList->AddAttribute ( "xml:lang", sCdataAttribute, "en-US" );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->startElement( sValue, pAttrList );
+ xHandler->characters( rValue );
+ xHandler->endElement( sValue );
+ xHandler->ignorableWhitespace ( sWhiteSpace );
+ xHandler->endElement( sProp );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/typedetectionexport.hxx b/filter/source/xsltdialog/typedetectionexport.hxx
new file mode 100644
index 000000000..a253540bb
--- /dev/null
+++ b/filter/source/xsltdialog/typedetectionexport.hxx
@@ -0,0 +1,41 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/xml/sax/XWriter.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+#include "xmlfilterjar.hxx"
+
+class TypeDetectionExporter
+{
+public:
+ explicit TypeDetectionExporter( css::uno::Reference< css::uno::XComponentContext > const & mxContext );
+
+ void doExport(const css::uno::Reference < css::io::XOutputStream >& xOS, const std::vector<filter_info_impl*>& rFilters );
+
+private:
+ static void addProperty( const css::uno::Reference< css::xml::sax::XWriter >& xWriter, const OUString& rName, const OUString& rValue );
+ static void addLocaleProperty( const css::uno::Reference< css::xml::sax::XWriter >& xWriter, const OUString& rName, const OUString& rValue );
+
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/typedetectionimport.cxx b/filter/source/xsltdialog/typedetectionimport.cxx
new file mode 100644
index 000000000..be5766927
--- /dev/null
+++ b/filter/source/xsltdialog/typedetectionimport.cxx
@@ -0,0 +1,316 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/XAttributeList.hpp>
+#include <tools/diagnose_ex.h>
+#include <rtl/ref.hxx>
+#include <o3tl/string_view.hxx>
+
+#include "typedetectionimport.hxx"
+#include "xmlfiltercommon.hxx"
+
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::xml::sax;
+using namespace com::sun::star;
+
+TypeDetectionImporter::TypeDetectionImporter()
+{
+}
+
+TypeDetectionImporter::~TypeDetectionImporter()
+{
+}
+
+void TypeDetectionImporter::doImport( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& xIS,
+ std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
+{
+ try
+ {
+ Reference< XParser > xParser = xml::sax::Parser::create( rxContext );
+
+ rtl::Reference<TypeDetectionImporter> pImporter = new TypeDetectionImporter;
+ xParser->setDocumentHandler( pImporter );
+
+ InputSource source;
+ source.aInputStream = xIS;
+
+ // start parsing
+ xParser->parseStream( source );
+
+ pImporter->fillFilterVector( rFilters );
+ }
+ catch( const Exception& /* e */ )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void TypeDetectionImporter::fillFilterVector( std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
+{
+ // create filter infos from imported filter nodes
+ for (auto const& filterNode : maFilterNodes)
+ {
+ std::unique_ptr<filter_info_impl> pFilter = createFilterForNode(filterNode.get());
+ if( pFilter )
+ rFilters.push_back( std::move(pFilter) );
+ }
+ maFilterNodes.clear();
+
+ // now delete type nodes
+ maTypeNodes.clear();
+}
+
+static std::u16string_view getSubdata( int index, sal_Unicode delimiter, std::u16string_view rData )
+{
+ sal_Int32 nLastIndex = 0;
+
+ size_t nNextIndex = rData.find( delimiter );
+
+ std::u16string_view aSubdata;
+
+ while( index )
+ {
+ nLastIndex = nNextIndex == std::u16string_view::npos ? 0 : nNextIndex + 1;
+ nNextIndex = rData.find( delimiter, nLastIndex );
+
+ index--;
+
+ if( (index > 0) && (nLastIndex == 0) )
+ return aSubdata;
+ }
+
+ if( nNextIndex == std::u16string_view::npos )
+ {
+ aSubdata = rData.substr( nLastIndex );
+ }
+ else
+ {
+ aSubdata = rData.substr( nLastIndex, nNextIndex - nLastIndex );
+ }
+
+ return aSubdata;
+}
+
+Node* TypeDetectionImporter::findTypeNode( const OUString& rType )
+{
+ auto aIter = std::find_if(maTypeNodes.begin(), maTypeNodes.end(),
+ [&rType](const std::unique_ptr<Node>& rxNode) { return rxNode->maName == rType; });
+ if (aIter != maTypeNodes.end())
+ return aIter->get();
+
+ return nullptr;
+}
+
+std::unique_ptr<filter_info_impl> TypeDetectionImporter::createFilterForNode( Node * pNode )
+{
+ std::unique_ptr<filter_info_impl> pFilter(new filter_info_impl);
+
+ pFilter->maFilterName = pNode->maName;
+ pFilter->maInterfaceName = pNode->maPropertyMap["UIName"];
+
+ OUString aData = pNode->maPropertyMap["Data"];
+
+ sal_Unicode aComma(',');
+
+ pFilter->maType = getSubdata( 1, aComma, aData );
+ pFilter->maDocumentService = getSubdata( 2, aComma, aData );
+
+ std::u16string_view aFilterService( getSubdata( 3, aComma, aData ) );
+ pFilter->maFlags = o3tl::toInt32(getSubdata( 4, aComma, aData ));
+
+ // parse filter user data
+ sal_Unicode aDelim(';');
+ std::u16string_view aFilterUserData( getSubdata( 5, aComma, aData ) );
+
+ std::u16string_view aAdapterService( getSubdata( 0, aDelim, aFilterUserData ) );
+ //Import/ExportService
+ pFilter->mbNeedsXSLT2 = OUString(getSubdata( 1, aDelim, aFilterUserData )).toBoolean();
+ pFilter->maImportService = getSubdata( 2, aDelim, aFilterUserData );
+ pFilter->maExportService = getSubdata( 3, aDelim, aFilterUserData );
+ pFilter->maImportXSLT = getSubdata( 4, aDelim, aFilterUserData );
+ pFilter->maExportXSLT = getSubdata( 5, aDelim, aFilterUserData );
+ pFilter->maComment = getSubdata( 7, aDelim, aFilterUserData );
+
+
+ pFilter->maImportTemplate = getSubdata( 7, aComma, aData );
+
+ Node* pTypeNode = findTypeNode( pFilter->maType );
+ if( pTypeNode )
+ {
+ OUString aTypeUserData( pTypeNode->maPropertyMap["Data"] );
+
+ pFilter->maDocType = getSubdata( 2, aComma, aTypeUserData );
+ pFilter->maExtension = getSubdata( 4, aComma, aTypeUserData );
+ pFilter->mnDocumentIconID = o3tl::toInt32(getSubdata( 5, aComma, aTypeUserData ));
+ }
+
+ bool bOk = true;
+
+ if( pTypeNode == nullptr )
+ bOk = false;
+
+ if( pFilter->maFilterName.isEmpty() )
+ bOk = false;
+
+ if( pFilter->maInterfaceName.isEmpty() )
+ bOk = false;
+
+ if( pFilter->maType.isEmpty() )
+ bOk = false;
+
+ if( pFilter->maFlags == 0 )
+ bOk = false;
+
+ if( aFilterService != u"com.sun.star.comp.Writer.XmlFilterAdaptor" )
+ bOk = false;
+
+ if( aAdapterService != u"com.sun.star.documentconversion.XSLTFilter" )
+ bOk = false;
+
+ if( pFilter->maExtension.isEmpty() )
+ bOk = false;
+
+ if( !bOk )
+ return nullptr;
+
+ return pFilter;
+}
+
+void SAL_CALL TypeDetectionImporter::startDocument( )
+{
+}
+
+void SAL_CALL TypeDetectionImporter::endDocument( )
+{
+}
+
+void SAL_CALL TypeDetectionImporter::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs )
+{
+ ImportState eNewState = e_Unknown;
+
+ if( maStack.empty() )
+ {
+ // #109668# support legacy name as well on import
+ if( aName == "oor:component-data" || aName == "oor:node" )
+ {
+ eNewState = e_Root;
+ }
+ }
+ else if( maStack.top() == e_Root )
+ {
+ if( aName == "node" )
+ {
+ OUString aNodeName( xAttribs->getValueByName( "oor:name" ) );
+
+ if( aNodeName == "Filters" )
+ {
+ eNewState = e_Filters;
+ }
+ else if( aNodeName == "Types" )
+ {
+ eNewState = e_Types;
+ }
+ }
+ }
+ else if( (maStack.top() == e_Filters) || (maStack.top() == e_Types) )
+ {
+ if( aName == "node" )
+ {
+ maNodeName = xAttribs->getValueByName( "oor:name" );
+
+ eNewState = (maStack.top() == e_Filters) ? e_Filter : e_Type;
+ }
+ }
+ else if( (maStack.top() == e_Filter) || (maStack.top() == e_Type))
+ {
+ if( aName == "prop" )
+ {
+ maPropertyName = xAttribs->getValueByName( "oor:name" );
+ eNewState = e_Property;
+ }
+ }
+ else if( maStack.top() == e_Property )
+ {
+ if( aName == "value" )
+ {
+ eNewState = e_Value;
+ maValue.clear();
+ }
+ }
+
+ maStack.push( eNewState );
+}
+void SAL_CALL TypeDetectionImporter::endElement( const OUString& /* aName */ )
+{
+ if( maStack.empty() )
+ return;
+
+ ImportState eCurrentState = maStack.top();
+ switch( eCurrentState )
+ {
+ case e_Filter:
+ case e_Type:
+ {
+ std::unique_ptr<Node> pNode(new Node);
+ pNode->maName = maNodeName;
+ pNode->maPropertyMap = maPropertyMap;
+ maPropertyMap.clear();
+
+ if( eCurrentState == e_Filter )
+ {
+ maFilterNodes.push_back( std::move(pNode) );
+ }
+ else
+ {
+ maTypeNodes.push_back( std::move(pNode) );
+ }
+ }
+ break;
+
+ case e_Property:
+ maPropertyMap[ maPropertyName ] = maValue;
+ break;
+ default: break;
+ }
+
+ maStack.pop();
+}
+void SAL_CALL TypeDetectionImporter::characters( const OUString& aChars )
+{
+ if( !maStack.empty() && maStack.top() == e_Value )
+ {
+ maValue += aChars;
+ }
+}
+void SAL_CALL TypeDetectionImporter::ignorableWhitespace( const OUString& /* aWhitespaces */ )
+{
+}
+void SAL_CALL TypeDetectionImporter::processingInstruction( const OUString& /* aTarget */, const OUString& /* aData */ )
+{
+}
+void SAL_CALL TypeDetectionImporter::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /* xLocator */ )
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/typedetectionimport.hxx b/filter/source/xsltdialog/typedetectionimport.hxx
new file mode 100644
index 000000000..3b69ef9af
--- /dev/null
+++ b/filter/source/xsltdialog/typedetectionimport.hxx
@@ -0,0 +1,92 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <cppuhelper/implbase.hxx>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+
+#include "xmlfilterjar.hxx"
+
+#include <map>
+#include <memory>
+#include <vector>
+#include <stack>
+
+namespace com::sun::star {
+ namespace xml::sax { class XAttributeList; }
+ namespace beans { struct PropertyValue; }
+}
+
+enum ImportState
+{
+ e_Root,
+ e_Filters,
+ e_Types,
+ e_Filter,
+ e_Type,
+ e_Property,
+ e_Value,
+ e_Unknown
+};
+
+typedef std::map<OUString, OUString> PropertyMap;
+
+struct Node
+{
+ OUString maName;
+ PropertyMap maPropertyMap;
+};
+
+class TypeDetectionImporter : public cppu::WeakImplHelper < css::xml::sax::XDocumentHandler >
+{
+public:
+ TypeDetectionImporter();
+ virtual ~TypeDetectionImporter() override;
+
+ static void doImport( const css::uno::Reference< css::uno::XComponentContext >& rxContext, const css::uno::Reference < css::io::XInputStream >& xOS,
+ std::vector< std::unique_ptr<filter_info_impl> >& rFilters );
+
+ virtual void SAL_CALL startDocument( ) override;
+ virtual void SAL_CALL endDocument( ) override;
+ virtual void SAL_CALL startElement( const OUString& aName, const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) override;
+ virtual void SAL_CALL endElement( const OUString& aName ) override;
+ virtual void SAL_CALL characters( const OUString& aChars ) override;
+ virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override;
+ virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override;
+ virtual void SAL_CALL setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override;
+
+private:
+ void fillFilterVector( std::vector< std::unique_ptr<filter_info_impl> >& rFilters );
+ std::unique_ptr<filter_info_impl> createFilterForNode( Node * pNode );
+ Node* findTypeNode( const OUString& rType );
+
+ std::stack< ImportState > maStack;
+ PropertyMap maPropertyMap;
+
+ std::vector< std::unique_ptr<Node> > maFilterNodes;
+ std::vector< std::unique_ptr<Node> > maTypeNodes;
+
+ OUString maValue;
+ OUString maNodeName;
+ OUString maPropertyName;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltercommon.hxx b/filter/source/xsltdialog/xmlfiltercommon.hxx
new file mode 100644
index 000000000..4ac225183
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltercommon.hxx
@@ -0,0 +1,83 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <unotools/resmgr.hxx>
+
+#include <string_view>
+#include <vector>
+
+
+extern OUString string_encode( const OUString & rText );
+extern OUString string_decode( const OUString & rText );
+
+bool copyStreams( const css::uno::Reference< css::io::XInputStream >& xIS, const css::uno::Reference< css::io::XOutputStream >& xOS );
+bool createDirectory( std::u16string_view rURL );
+
+
+class filter_info_impl
+{
+public:
+ OUString maFilterName;
+ OUString maType;
+ OUString maDocumentService;
+ OUString maInterfaceName;
+ OUString maComment;
+ OUString maExtension;
+ OUString maExportXSLT;
+ OUString maImportXSLT;
+ OUString maImportTemplate;
+ OUString maDocType;
+ OUString maImportService;
+ OUString maExportService;
+
+ sal_Int32 maFlags;
+ sal_Int32 maFileFormatVersion;
+ sal_Int32 mnDocumentIconID;
+
+ bool mbReadonly;
+
+ bool mbNeedsXSLT2;
+
+ filter_info_impl();
+ bool operator==( const filter_info_impl& ) const;
+
+ css::uno::Sequence< OUString > getFilterUserData() const;
+};
+
+
+struct application_info_impl
+{
+ OUString maDocumentService;
+ OUString maDocumentUIName;
+ OUString maXMLImporter;
+ OUString maXMLExporter;
+
+ application_info_impl(const char * pDocumentService, const OUString& rUINameRes, const char * mpXMLImporter, const char * mpXMLExporter);
+};
+
+
+extern std::vector< application_info_impl > const & getApplicationInfos();
+extern OUString getApplicationUIName( std::u16string_view rServiceName );
+extern const application_info_impl* getApplicationInfo( std::u16string_view rServiceName );
+OUString XsltResId(TranslateId pId);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfilterdialogcomponent.cxx b/filter/source/xsltdialog/xmlfilterdialogcomponent.cxx
new file mode 100644
index 000000000..6f4b1db34
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfilterdialogcomponent.cxx
@@ -0,0 +1,285 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <osl/mutex.hxx>
+
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/component.hxx>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/awt/XWindow.hpp>
+#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <vcl/svapp.hxx>
+
+#include "xmlfiltersettingsdialog.hxx"
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::frame;
+
+namespace {
+
+class XMLFilterDialogComponentBase
+{
+protected:
+ ::osl::Mutex maMutex;
+};
+
+
+class XMLFilterDialogComponent : public XMLFilterDialogComponentBase,
+ public OComponentHelper,
+ public css::ui::dialogs::XExecutableDialog,
+ public XServiceInfo,
+ public XInitialization,
+ public XTerminateListener
+{
+public:
+ explicit XMLFilterDialogComponent( const Reference< XComponentContext >& rxContext );
+
+ // XInterface
+ virtual Any SAL_CALL queryInterface( const Type& aType ) override;
+ virtual Any SAL_CALL queryAggregation( Type const & rType ) override;
+ virtual void SAL_CALL acquire() noexcept override;
+ virtual void SAL_CALL release() noexcept override;
+
+protected:
+ // XTypeProvider
+ virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() override;
+ virtual Sequence< Type > SAL_CALL getTypes() override;
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
+ virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override;
+
+ // XExecutableDialog
+ virtual void SAL_CALL setTitle( const OUString& aTitle ) override;
+ virtual sal_Int16 SAL_CALL execute( ) override;
+
+ // XInitialization
+ virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) override;
+
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination( const EventObject& Event ) override;
+ virtual void SAL_CALL notifyTermination( const EventObject& Event ) override;
+ virtual void SAL_CALL disposing( const EventObject& Source ) override;
+
+ /** Called in dispose method after the listeners were notified.
+ */
+ virtual void SAL_CALL disposing() override;
+
+private:
+ css::uno::Reference<css::awt::XWindow> mxParent; /// parent window
+ css::uno::Reference< XComponentContext > mxContext;
+
+ std::shared_ptr<XMLFilterSettingsDialog> mxDialog;
+};
+
+}
+
+XMLFilterDialogComponent::XMLFilterDialogComponent(const css::uno::Reference< XComponentContext >& rxContext)
+ : OComponentHelper(maMutex)
+ , mxContext(rxContext)
+{
+ Reference< XDesktop2 > xDesktop = Desktop::create( rxContext );
+ Reference< XTerminateListener > xListener( this );
+ xDesktop->addTerminateListener( xListener );
+}
+
+// XInterface
+Any SAL_CALL XMLFilterDialogComponent::queryInterface( const Type& aType )
+{
+ return OComponentHelper::queryInterface( aType );
+}
+
+
+Any SAL_CALL XMLFilterDialogComponent::queryAggregation( Type const & rType )
+{
+ if (rType == cppu::UnoType<css::ui::dialogs::XExecutableDialog>::get())
+ {
+ void * p = static_cast< css::ui::dialogs::XExecutableDialog * >( this );
+ return Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<XServiceInfo>::get())
+ {
+ void * p = static_cast< XServiceInfo * >( this );
+ return Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<XInitialization>::get())
+ {
+ void * p = static_cast< XInitialization * >( this );
+ return Any( &p, rType );
+ }
+ else if (rType == cppu::UnoType<XTerminateListener>::get())
+ {
+ void * p = static_cast< XTerminateListener * >( this );
+ return Any( &p, rType );
+ }
+ return OComponentHelper::queryAggregation( rType );
+}
+
+
+void SAL_CALL XMLFilterDialogComponent::acquire() noexcept
+{
+ OComponentHelper::acquire();
+}
+
+
+void SAL_CALL XMLFilterDialogComponent::release() noexcept
+{
+ OComponentHelper::release();
+}
+
+
+OUString SAL_CALL XMLFilterDialogComponent::getImplementationName()
+{
+ return "com.sun.star.comp.ui.XSLTFilterDialog";
+}
+
+Sequence< sal_Int8 > SAL_CALL XMLFilterDialogComponent::getImplementationId()
+{
+ static const comphelper::UnoIdInit implId;
+ return implId.getSeq();
+}
+
+
+Sequence< Type > XMLFilterDialogComponent::getTypes()
+{
+ return { cppu::UnoType<XComponent>::get(),
+ cppu::UnoType<XTypeProvider>::get(),
+ cppu::UnoType<XAggregation>::get(),
+ cppu::UnoType<XWeak>::get(),
+ cppu::UnoType<XServiceInfo>::get(),
+ cppu::UnoType<XInitialization>::get(),
+ cppu::UnoType<XTerminateListener>::get(),
+ cppu::UnoType<css::ui::dialogs::XExecutableDialog>::get() };
+}
+
+Sequence< OUString > SAL_CALL XMLFilterDialogComponent::getSupportedServiceNames()
+{
+ return { "com.sun.star.ui.dialogs.XSLTFilterDialog" };
+}
+
+sal_Bool SAL_CALL XMLFilterDialogComponent::supportsService(const OUString& ServiceName)
+{
+ return cppu::supportsService( this, ServiceName );
+}
+
+/** Called in dispose method after the listeners were notified.
+*/
+void SAL_CALL XMLFilterDialogComponent::disposing()
+{
+ ::SolarMutexGuard aGuard;
+
+ if (mxDialog)
+ mxDialog->response(RET_CLOSE);
+}
+
+
+// XTerminateListener
+void SAL_CALL XMLFilterDialogComponent::queryTermination( const EventObject& /* Event */ )
+{
+ ::SolarMutexGuard aGuard;
+ if (!mxDialog)
+ return;
+ mxDialog->present();
+}
+
+void SAL_CALL XMLFilterDialogComponent::notifyTermination( const EventObject& /* Event */ )
+{
+ {
+ ::SolarMutexGuard aGuard;
+ if (mxDialog)
+ mxDialog->response(RET_CLOSE);
+ }
+
+ // we are going down, so dispose us!
+ dispose();
+}
+
+void SAL_CALL XMLFilterDialogComponent::disposing( const EventObject& /* Source */ )
+{
+}
+
+void SAL_CALL XMLFilterDialogComponent::setTitle( const OUString& /* _rTitle */ )
+{
+}
+
+sal_Int16 SAL_CALL XMLFilterDialogComponent::execute()
+{
+ ::SolarMutexGuard aGuard;
+
+ bool bLaunch = false;
+ if (!mxDialog)
+ {
+ Reference< XComponent > xKeepAlive( this );
+ mxDialog = std::make_shared<XMLFilterSettingsDialog>(Application::GetFrameWeld(mxParent), mxContext);
+ bLaunch = true;
+ }
+
+ mxDialog->UpdateWindow();
+
+ if (!bLaunch)
+ {
+ mxDialog->present();
+ return 0;
+ }
+
+ weld::DialogController::runAsync(mxDialog, [this](sal_Int32)
+ {
+ mxDialog.reset();
+ });
+
+ return 0;
+}
+
+void SAL_CALL XMLFilterDialogComponent::initialize( const Sequence< Any >& aArguments )
+{
+ for(const Any& rArgument : aArguments)
+ {
+ PropertyValue aProperty;
+ if(rArgument >>= aProperty)
+ {
+ if( aProperty.Name == "ParentWindow" )
+ {
+ aProperty.Value >>= mxParent;
+ }
+ }
+ }
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_XSLTFilterDialog_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XMLFilterDialogComponent(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfilterjar.cxx b/filter/source/xsltdialog/xmlfilterjar.cxx
new file mode 100644
index 000000000..2366aa80e
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfilterjar.cxx
@@ -0,0 +1,361 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/io/XActiveDataControl.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XUnoTunnel.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+
+#include <comphelper/oslfile2streamwrap.hxx>
+#include <comphelper/storagehelper.hxx>
+#include <osl/file.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/streamwrap.hxx>
+#include <unotools/tempfile.hxx>
+#include <svl/urihelper.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/stream.hxx>
+#include <tools/urlobj.hxx>
+
+#include <rtl/uri.hxx>
+
+#include "xmlfiltercommon.hxx"
+#include "xmlfilterjar.hxx"
+#include "typedetectionexport.hxx"
+#include "typedetectionimport.hxx"
+
+using namespace osl;
+using namespace comphelper;
+using namespace com::sun::star;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::util;
+using namespace com::sun::star::container;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::io;
+
+using ::rtl::Uri;
+
+constexpr OUStringLiteral sVndSunStarPackage(u"vnd.sun.star.Package:");
+
+XMLFilterJarHelper::XMLFilterJarHelper( const Reference< XComponentContext >& rxContext )
+: mxContext( rxContext ),
+ sXSLTPath( "$(user)/xslt/" ),
+ sTemplatePath( "$(user)/template/" ),
+ sProgPath( "$(prog)/" )
+{
+ SvtPathOptions aOptions;
+ sProgPath = aOptions.SubstituteVariable( sProgPath );
+ sXSLTPath = aOptions.SubstituteVariable( sXSLTPath );
+ sTemplatePath = aOptions.SubstituteVariable( sTemplatePath );
+}
+
+static OUString encodeZipUri( const OUString& rURI )
+{
+ return Uri::encode( rURI, rtl_UriCharClassUric, rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8 );
+}
+
+/// @throws Exception
+static Reference< XInterface > addFolder( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, const OUString& rName )
+{
+ if ( rName == ".." || rName == "." )
+ throw lang::IllegalArgumentException();
+
+ Sequence< Any > aArgs{ Any(true) };
+
+ Reference< XInterface > xFolder( xFactory->createInstanceWithArguments(aArgs) );
+ Reference< XNamed > xNamed( xFolder, UNO_QUERY );
+ Reference< XChild > xChild( xFolder, UNO_QUERY );
+
+ if( xNamed.is() && xChild.is() )
+ {
+ OUString aName( encodeZipUri( rName ) );
+ xNamed->setName( aName );
+ xChild->setParent( xRootFolder );
+ }
+
+ return xFolder;
+}
+
+/// @throws Exception
+static void addFile_( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, Reference< XInputStream > const & xInput, const OUString& aName )
+{
+ Reference< XActiveDataSink > xSink( xFactory->createInstance(), UNO_QUERY );
+ Reference< XUnoTunnel > xTunnel( xSink, UNO_QUERY );
+ if( xSink.is() && xTunnel.is())
+ {
+ Reference< XNameContainer > xNameContainer(xRootFolder, UNO_QUERY );
+ xNameContainer->insertByName(encodeZipUri( aName ), Any(xTunnel));
+ xSink->setInputStream( xInput );
+ }
+}
+
+void XMLFilterJarHelper::addFile( Reference< XInterface > const & xRootFolder, Reference< XSingleServiceFactory > const & xFactory, const OUString& rSourceFile )
+{
+ if( rSourceFile.isEmpty() ||
+ rSourceFile.startsWith("http:") ||
+ rSourceFile.startsWith("https:") ||
+ rSourceFile.startsWith("jar:") ||
+ rSourceFile.startsWith("ftp:") )
+ return;
+
+ OUString aFileURL( rSourceFile );
+
+ if( !aFileURL.matchIgnoreAsciiCase("file://") )
+ {
+ aFileURL = URIHelper::SmartRel2Abs( INetURLObject(sProgPath), aFileURL, Link<OUString *, bool>(), false );
+ }
+
+ INetURLObject aURL( aFileURL );
+ OUString aName( aURL.getName() );
+
+ SvFileStream* pStream = new SvFileStream(aFileURL, StreamMode::READ );
+ Reference< XInputStream > xInput( new utl::OSeekableInputStreamWrapper( pStream, true ) );
+ addFile_( xRootFolder, xFactory, xInput, aName );
+}
+
+bool XMLFilterJarHelper::savePackage( const OUString& rPackageURL, const std::vector<filter_info_impl*>& rFilters )
+{
+ try
+ {
+ osl::File::remove( rPackageURL );
+
+ // create the package jar file
+
+ Sequence< Any > aArguments{ Any(rPackageURL),
+ // let ZipPackage be used ( no manifest.xml is required )
+ Any(beans::NamedValue(
+ "StorageFormat", Any(OUString(ZIP_STORAGE_FORMAT_STRING)))) };
+
+ Reference< XHierarchicalNameAccess > xIfc(
+ mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.packages.comp.ZipPackage",
+ aArguments, mxContext ), UNO_QUERY );
+
+ if( xIfc.is() )
+ {
+ Reference< XSingleServiceFactory > xFactory( xIfc, UNO_QUERY );
+
+ // get root zip folder
+ Reference< XInterface > xRootFolder;
+ xIfc->getByHierarchicalName( "/" ) >>= xRootFolder;
+
+ // export filters files
+ for (auto const& filter : rFilters)
+ {
+ Reference< XInterface > xFilterRoot( addFolder( xRootFolder, xFactory, filter->maFilterName ) );
+
+ if( xFilterRoot.is() )
+ {
+ if( !filter->maExportXSLT.isEmpty() )
+ addFile( xFilterRoot, xFactory, filter->maExportXSLT );
+ try
+ {
+ if( !filter->maImportXSLT.isEmpty() )
+ addFile( xFilterRoot, xFactory, filter->maImportXSLT );
+ }
+ catch(const css::container::ElementExistException&)
+ {
+ // in case of same named import / export XSLT the latter
+ // is ignored
+ TOOLS_WARN_EXCEPTION("filter.xslt", "same named xslt filter exception!");
+ }
+
+ if( !filter->maImportTemplate.isEmpty() )
+ addFile( xFilterRoot, xFactory, filter->maImportTemplate );
+ }
+ }
+
+ // create TypeDetection.xcu
+ utl::TempFile aTempFile;
+ aTempFile.EnableKillingFile();
+ OUString aTempFileURL( aTempFile.GetURL() );
+
+ {
+ osl::File aOutputFile( aTempFileURL );
+ (void)aOutputFile.open(osl_File_OpenFlag_Write);
+ Reference< XOutputStream > xOS( new OSLOutputStreamWrapper( aOutputFile ) );
+
+ TypeDetectionExporter aExporter( mxContext );
+ aExporter.doExport(xOS,rFilters);
+ }
+
+ Reference< XInputStream > XIS( new utl::OSeekableInputStreamWrapper( new SvFileStream(aTempFileURL, StreamMode::READ ), true ) );
+ addFile_( xRootFolder, xFactory, XIS, "TypeDetection.xcu" );
+
+ Reference< XChangesBatch > xBatch( xIfc, UNO_QUERY );
+ if( xBatch.is() )
+ xBatch->commitChanges();
+
+ return true;
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ osl::File::remove( rPackageURL );
+
+ return false;
+}
+
+
+void XMLFilterJarHelper::openPackage( const OUString& rPackageURL,
+ std::vector< std::unique_ptr<filter_info_impl> >& rFilters )
+{
+ try
+ {
+ // create the package jar file
+
+ // let ZipPackage be used ( no manifest.xml is required )
+ beans::NamedValue aArg;
+ aArg.Name = "StorageFormat";
+ aArg.Value <<= OUString(ZIP_STORAGE_FORMAT_STRING);
+ Sequence< Any > aArguments{ Any(rPackageURL), Any(aArg) };
+
+ Reference< XHierarchicalNameAccess > xIfc(
+ mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.packages.comp.ZipPackage",
+ aArguments, mxContext ), UNO_QUERY );
+
+ if( xIfc.is() )
+ {
+ // get root zip folder
+ Reference< XInterface > xRootFolder;
+ xIfc->getByHierarchicalName( "/" ) >>= xRootFolder;
+
+ OUString szTypeDetection("TypeDetection.xcu");
+ if( xIfc->hasByHierarchicalName( szTypeDetection ) )
+ {
+ Reference< XActiveDataSink > xTypeDetection;
+ xIfc->getByHierarchicalName( szTypeDetection ) >>= xTypeDetection;
+
+ if( xTypeDetection.is() )
+ {
+ Reference< XInputStream > xIS( xTypeDetection->getInputStream() );
+
+ std::vector< std::unique_ptr<filter_info_impl> > aFilters;
+ TypeDetectionImporter::doImport( mxContext, xIS, aFilters );
+
+ // copy all files used by the filters imported from the
+ // typedetection to office/user/xslt
+ for (auto& filter : aFilters)
+ {
+ if( copyFiles( xIfc, filter.get() ) )
+ {
+ rFilters.push_back(std::move(filter));
+ }
+ else
+ {
+ // failed to copy all files
+ filter.reset();
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+bool XMLFilterJarHelper::copyFiles( const Reference< XHierarchicalNameAccess >& xIfc, filter_info_impl* pFilter )
+{
+ bool bOk = copyFile( xIfc, pFilter->maExportXSLT, sXSLTPath );
+
+ if( bOk )
+ bOk = copyFile( xIfc, pFilter->maImportXSLT, sXSLTPath );
+
+ if( bOk )
+ bOk = copyFile( xIfc, pFilter->maImportTemplate, sTemplatePath );
+
+ return bOk;
+}
+
+bool XMLFilterJarHelper::copyFile( const Reference< XHierarchicalNameAccess >& xIfc, OUString& rURL, std::u16string_view rTargetURL )
+{
+ if( !rURL.matchIgnoreAsciiCase( sVndSunStarPackage ) )
+ return true;
+
+ try
+ {
+ OUString szPackagePath( encodeZipUri( rURL.copy( sVndSunStarPackage.getLength() ) ) );
+
+ if ( ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, u".." )
+ || ::comphelper::OStorageHelper::PathHasSegment( szPackagePath, u"." ) )
+ throw lang::IllegalArgumentException();
+
+ if( xIfc->hasByHierarchicalName( szPackagePath ) )
+ {
+ Reference< XActiveDataSink > xFileEntry;
+ xIfc->getByHierarchicalName( szPackagePath ) >>= xFileEntry;
+
+ if( xFileEntry.is() )
+ {
+ Reference< XInputStream > xIS( xFileEntry->getInputStream() );
+
+ INetURLObject aBaseURL( rTargetURL );
+
+ rURL = URIHelper::SmartRel2Abs( aBaseURL, szPackagePath, Link<OUString *, bool>(), false );
+
+ if( !rURL.isEmpty() )
+ {
+ // create output directory if needed
+ if( !createDirectory( rURL ) )
+ return false;
+
+ ::osl::File file(rURL);
+ ::osl::FileBase::RC rc =
+ file.open(osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
+ if (::osl::FileBase::E_EXIST == rc) {
+ rc = file.open(osl_File_OpenFlag_Write);
+ if (::osl::FileBase::E_None == rc) {
+ file.setSize(0); // #i97170# truncate
+ }
+ }
+ if (::osl::FileBase::E_None != rc) {
+ throw RuntimeException();
+ }
+ Reference< XOutputStream > const xOS(
+ new comphelper::OSLOutputStreamWrapper(file));
+
+ return copyStreams( xIS, xOS );
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfilterjar.hxx b/filter/source/xsltdialog/xmlfilterjar.hxx
new file mode 100644
index 000000000..d634bb6c4
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfilterjar.hxx
@@ -0,0 +1,52 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <memory>
+#include <vector>
+
+class filter_info_impl;
+
+class XMLFilterJarHelper
+{
+public:
+ explicit XMLFilterJarHelper( const css::uno::Reference< css::uno::XComponentContext >& rxContext );
+
+ bool savePackage( const OUString& rPackageURL, const std::vector<filter_info_impl*>& rFilters );
+ void openPackage( const OUString& rPackageURL, std::vector< std::unique_ptr<filter_info_impl> >& rFilters );
+
+private:
+ /// @throws css::uno::Exception
+ void addFile( css::uno::Reference< css::uno::XInterface > const & xRootFolder, css::uno::Reference< css::lang::XSingleServiceFactory > const & xFactory, const OUString& rSourceFile );
+
+ static bool copyFile( const css::uno::Reference< css::container::XHierarchicalNameAccess >& xIfc, OUString& rURL, std::u16string_view rTargetURL );
+ bool copyFiles( const css::uno::Reference< css::container::XHierarchicalNameAccess >& xIfc, filter_info_impl* pFilter );
+
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+
+ OUString sXSLTPath;
+ OUString sTemplatePath;
+ OUString sProgPath;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx
new file mode 100644
index 000000000..62a8513d7
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.cxx
@@ -0,0 +1,1384 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/util/XFlushable.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+
+#include <comphelper/propertyvalue.hxx>
+#include <o3tl/string_view.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/urlobj.hxx>
+#include <unotools/pathoptions.hxx>
+#include <unotools/resmgr.hxx>
+#include <unotools/streamwrap.hxx>
+#include <osl/file.hxx>
+#include <o3tl/enumrange.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <tools/stream.hxx>
+
+#include <rtl/uri.hxx>
+
+#include <algorithm>
+#include <memory>
+
+#include <strings.hrc>
+#include "xmlfiltersettingsdialog.hxx"
+#include "xmlfiltertabdialog.hxx"
+#include "xmlfiltertestdialog.hxx"
+#include "xmlfilterjar.hxx"
+#include <strings.hxx>
+
+using namespace osl;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace com::sun::star::container;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::util;
+
+using ::rtl::Uri;
+
+OUString XsltResId(TranslateId aId)
+{
+ return Translate::get(aId, Translate::Create("flt"));
+}
+
+XMLFilterSettingsDialog::XMLFilterSettingsDialog(weld::Window* pParent,
+ const css::uno::Reference<css::uno::XComponentContext>& rxContext)
+ : GenericDialogController(pParent, "filter/ui/xmlfiltersettings.ui", "XMLFilterSettingsDialog")
+ , mxContext( rxContext )
+ , m_sTemplatePath("$(user)/template/")
+ , m_sDocTypePrefix("doctype:")
+ , m_xPBNew(m_xBuilder->weld_button("new"))
+ , m_xPBEdit(m_xBuilder->weld_button("edit"))
+ , m_xPBTest(m_xBuilder->weld_button("test"))
+ , m_xPBDelete(m_xBuilder->weld_button("delete"))
+ , m_xPBSave(m_xBuilder->weld_button("save"))
+ , m_xPBOpen(m_xBuilder->weld_button("open"))
+ , m_xPBClose(m_xBuilder->weld_button("close"))
+ , m_xFilterListBox(m_xBuilder->weld_tree_view("filterlist"))
+{
+ m_xFilterListBox->set_selection_mode(SelectionMode::Multiple);
+
+ m_xFilterListBox->set_size_request(m_xFilterListBox->get_approximate_digit_width() * 65,
+ m_xFilterListBox->get_height_rows(12));
+
+ m_xFilterListBox->connect_changed( LINK( this, XMLFilterSettingsDialog, SelectionChangedHdl_Impl ) );
+ m_xFilterListBox->connect_row_activated( LINK( this, XMLFilterSettingsDialog, DoubleClickHdl_Impl ) );
+ m_xFilterListBox->set_accessible_name(XsltResId(STR_XML_FILTER_LISTBOX));
+
+ m_xPBNew->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBEdit->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBTest->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBDelete->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBSave->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBOpen->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+ m_xPBClose->connect_clicked(LINK( this, XMLFilterSettingsDialog, ClickHdl_Impl ) );
+
+ try
+ {
+ mxFilterContainer.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", rxContext ), UNO_QUERY );
+ mxTypeDetection.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", rxContext ), UNO_QUERY );
+ mxExtendedTypeDetection.set( rxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.ExtendedTypeDetectionFactory", rxContext ), UNO_QUERY );
+
+ SvtPathOptions aOptions;
+ m_sTemplatePath = aOptions.SubstituteVariable( m_sTemplatePath );
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+XMLFilterSettingsDialog::~XMLFilterSettingsDialog()
+{
+}
+
+IMPL_LINK(XMLFilterSettingsDialog, ClickHdl_Impl, weld::Button&, rButton, void)
+{
+ // tdf#122171 block closing libreoffice until the following dialog is dismissed
+ incBusy();
+
+ if (m_xPBNew.get() == &rButton)
+ {
+ onNew();
+ }
+ else if (m_xPBEdit.get() == &rButton)
+ {
+ onEdit();
+ }
+ else if (m_xPBTest.get() == &rButton)
+ {
+ onTest();
+ }
+ else if (m_xPBDelete.get() == &rButton)
+ {
+ onDelete();
+ }
+ else if (m_xPBSave.get() == &rButton)
+ {
+ onSave();
+ }
+ else if (m_xPBOpen.get() == &rButton)
+ {
+ onOpen();
+ }
+
+ decBusy();
+
+ if (m_xPBClose.get() == &rButton)
+ m_xDialog->response(RET_CLOSE);
+}
+
+IMPL_LINK_NOARG(XMLFilterSettingsDialog, SelectionChangedHdl_Impl, weld::TreeView&, void)
+{
+ updateStates();
+}
+
+IMPL_LINK_NOARG(XMLFilterSettingsDialog, DoubleClickHdl_Impl, weld::TreeView&, bool)
+{
+ onEdit();
+ return true;
+}
+
+void XMLFilterSettingsDialog::UpdateWindow()
+{
+ m_xFilterListBox->grab_focus();
+ disposeFilterList();
+ m_xFilterListBox->clear();
+ initFilterList();
+ updateStates();
+}
+
+void XMLFilterSettingsDialog::updateStates()
+{
+ std::vector<int> aRows = m_xFilterListBox->get_selected_rows();
+
+ bool bHasSelection = !aRows.empty();
+
+ bool bMultiSelection = aRows.size() > 1;
+ bool bIsReadonly = false;
+ bool bIsDefault = false;
+ if (bHasSelection)
+ {
+ filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(aRows[0]));
+ bIsReadonly = pInfo->mbReadonly;
+
+ for( auto nFact : o3tl::enumrange<SvtModuleOptions::EFactory>())
+ {
+ OUString sDefault = maModuleOpt.GetFactoryDefaultFilter(nFact);
+ if( sDefault == pInfo->maFilterName )
+ {
+ bIsDefault = true;
+ break;
+ }
+ }
+ }
+ m_xPBEdit->set_sensitive( bHasSelection && !bMultiSelection && !bIsReadonly);
+ m_xPBTest->set_sensitive( bHasSelection && !bMultiSelection );
+ m_xPBDelete->set_sensitive( bHasSelection && !bMultiSelection && !bIsReadonly && !bIsDefault);
+ m_xPBSave->set_sensitive( bHasSelection );
+}
+
+/** is called when the user clicks on the "New" button */
+void XMLFilterSettingsDialog::onNew()
+{
+ filter_info_impl aTempInfo;
+
+ // create a unique filter name
+ aTempInfo.maFilterName = createUniqueFilterName(XsltResId(STR_DEFAULT_FILTER_NAME));
+
+ // init default extension
+ aTempInfo.maExtension = STR_DEFAULT_EXTENSION;
+
+ // set default ui name
+ aTempInfo.maInterfaceName = createUniqueInterfaceName(XsltResId(STR_DEFAULT_UI_NAME));
+
+ // set default application
+ aTempInfo.maDocumentService = "com.sun.star.text.TextDocument";
+
+ // execute XML Filter Dialog
+ XMLFilterTabDialog aDlg(m_xDialog.get(), mxContext, &aTempInfo);
+ if (aDlg.run() == RET_OK)
+ {
+ // insert the new filter
+ insertOrEdit( aDlg.getNewFilterInfo() );
+ }
+}
+
+/** is called when the user clicks on the "Edit" Button */
+void XMLFilterSettingsDialog::onEdit()
+{
+ // get selected filter info
+ filter_info_impl* pOldInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_selected_id());
+ if (!pOldInfo)
+ return;
+
+ // execute XML Filter Dialog
+ XMLFilterTabDialog aDlg(m_xDialog.get(), mxContext, pOldInfo);
+ if (aDlg.run() == RET_OK)
+ {
+ filter_info_impl* pNewInfo = aDlg.getNewFilterInfo();
+
+ if( !(*pOldInfo == *pNewInfo) )
+ {
+ // change filter
+ insertOrEdit( pNewInfo, pOldInfo );
+ }
+ }
+}
+
+/** helper to create a sequence of strings from an extensions strings
+ "ext1;ext2;ext3" will become { "ext1", "ext2", "ext3" } */
+static Sequence< OUString > createExtensionsSequence( const OUString& rExtensions )
+{
+ // first count how many extensions we have inside the string
+ int nExtensions = 0;
+
+ int nLength = rExtensions.getLength();
+ if( nLength )
+ {
+ // a non empty string has at least one extension
+ nExtensions++;
+
+ // now count the delimiters ';'
+ const sal_Unicode * pString = rExtensions.getStr();
+ int i;
+ for( i = 0; i < nLength; i++, pString++ )
+ {
+ if( *pString == ';' )
+ nExtensions++;
+ }
+ }
+
+ Sequence< OUString > aExtensions( nExtensions );
+ auto aExtensionsRange = asNonConstRange(aExtensions);
+
+ // extract the extensions from the source string and fill the sequence
+
+ int nLastIndex = 0;
+ int nCurrentIndex = 0;
+ int i;
+
+ for( i = 0; i < nExtensions; i++ )
+ {
+ nLastIndex = rExtensions.indexOf( ';', nLastIndex );
+
+ if( nLastIndex == -1 )
+ {
+ aExtensionsRange[i] = rExtensions.copy( nCurrentIndex );
+ break;
+ }
+ else
+ {
+ aExtensionsRange[i] = rExtensions.copy( nCurrentIndex, nLastIndex - nCurrentIndex );
+ nCurrentIndex = nLastIndex + 1;
+ nLastIndex = nCurrentIndex;
+ }
+ }
+
+ return aExtensions;
+}
+
+/** checks if the given name is unique inside the filter factory. If not,
+ numbers are added until the returned name is unique */
+OUString XMLFilterSettingsDialog::createUniqueFilterName( const OUString& rFilterName )
+{
+ OUString aFilterName( rFilterName );
+
+ sal_Int32 nId = 2;
+
+ while( mxFilterContainer->hasByName( aFilterName ) )
+ {
+ aFilterName = rFilterName + " " + OUString::number( nId++ );
+ }
+
+ return aFilterName;
+}
+
+/** checks if the given name is unique inside the type detection. If not,
+ numbers are added until the returned name is unique */
+OUString XMLFilterSettingsDialog::createUniqueTypeName( const OUString& rTypeName )
+{
+ OUString aTypeName( rTypeName );
+
+ sal_Int32 nId = 2;
+
+ while( mxFilterContainer->hasByName( aTypeName ) )
+ {
+ aTypeName = rTypeName + " " + OUString::number( nId++ );
+ }
+
+ return aTypeName;
+}
+
+/** checks if the given name is a unique ui name inside the filter factory. If not,
+ numbers are added until the returned name is unique */
+OUString XMLFilterSettingsDialog::createUniqueInterfaceName( const OUString& rInterfaceName )
+{
+ sal_Int32 nDefaultNumber = 0;
+
+ try
+ {
+ const Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
+
+ Sequence< PropertyValue > aValues;
+ for( OUString const & filterName : aFilterNames)
+ {
+ Any aAny( mxFilterContainer->getByName( filterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ const sal_Int32 nValueCount( aValues.getLength() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 nValue;
+
+ for( nValue = 0; nValue < nValueCount; nValue++, pValues++ )
+ {
+ if ( pValues->Name == "UIName" )
+ {
+ OUString aInterfaceName;
+ pValues->Value >>= aInterfaceName;
+
+
+ // see if this filter matches our default filter name
+ if( aInterfaceName.match( rInterfaceName ) )
+ {
+ // if yes, make sure we generate a unique name with a higher number
+ // this is dump but fast
+ sal_Int32 nNumber = o3tl::toInt32(aInterfaceName.subView( rInterfaceName.getLength() ));
+ if( nNumber >= nDefaultNumber )
+ nDefaultNumber = nNumber + 1;
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ OUString aInterfaceName( rInterfaceName );
+ if( nDefaultNumber )
+ {
+ aInterfaceName += " " + OUString::number( nDefaultNumber );
+ }
+
+ return aInterfaceName;
+}
+
+/** inserts a new filter into the ui and configuration if pOldInfo is NULL.
+ If pOldInfo is not null, the old filter will be replaced with the new settings */
+bool XMLFilterSettingsDialog::insertOrEdit( filter_info_impl* pNewInfo, const filter_info_impl* pOldInfo )
+{
+ bool bOk = true;
+
+ if( pOldInfo )
+ {
+ // see if we need to update the type name
+ if( pOldInfo->maFilterName != pNewInfo->maFilterName )
+ {
+ if( pOldInfo->maType == pOldInfo->maFilterName )
+ {
+ pNewInfo->maType.clear();
+ }
+ }
+
+ // see if we need to clean up old stuff first
+ try
+ {
+ // if filter name changed, we need to remove the old filter first
+ if( pOldInfo->maFilterName != pNewInfo->maFilterName )
+ mxFilterContainer->removeByName( pOldInfo->maFilterName );
+
+ // if type name changed, we need to remove the old type first
+ if( pOldInfo->maType != pNewInfo->maType )
+ mxTypeDetection->removeByName( pOldInfo->maType );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+
+ filter_info_impl* pFilterEntry( nullptr );
+
+ if( bOk )
+ {
+ // create or copy filter info
+ if( pOldInfo )
+ {
+ // change existing filter entry in filter list box
+ pFilterEntry = const_cast<filter_info_impl*>(pOldInfo);
+ *pFilterEntry = *pNewInfo;
+ }
+ else
+ {
+ // add new entry to filter list box
+ pFilterEntry = new filter_info_impl( *pNewInfo );
+ }
+ }
+
+ // check if we need to copy the template
+ if( bOk && !pFilterEntry->maImportTemplate.isEmpty() )
+ {
+ if( !pFilterEntry->maImportTemplate.matchIgnoreAsciiCase( m_sTemplatePath ) )
+ {
+ INetURLObject aSourceURL( pFilterEntry->maImportTemplate );
+ if (!aSourceURL.GetLastName().isEmpty())
+ {
+ OUString aDestURL = m_sTemplatePath + pFilterEntry->maFilterName + "/";
+ if( createDirectory( aDestURL ) )
+ {
+ aDestURL += aSourceURL.GetLastName();
+
+ SvFileStream aInputStream(pFilterEntry->maImportTemplate, StreamMode::READ );
+ Reference< XInputStream > xIS( new utl::OInputStreamWrapper( aInputStream ) );
+ SvFileStream aOutputStream(aDestURL, StreamMode::WRITE );
+ Reference< XOutputStream > xOS( new utl::OOutputStreamWrapper( aOutputStream ) );
+
+ if( copyStreams( xIS, xOS ) )
+ pFilterEntry->maImportTemplate = aDestURL;
+ }
+ }
+ }
+ }
+
+ if( bOk )
+ {
+ if( pFilterEntry->maType.isEmpty() )
+ {
+ pFilterEntry->maType = createUniqueTypeName( pNewInfo->maFilterName );
+ }
+
+ // update import/export flags
+ if( !pFilterEntry->maImportXSLT.isEmpty() )
+ {
+ pFilterEntry->maFlags |= 1;
+ }
+ else
+ {
+ pFilterEntry->maFlags &= ~1;
+ }
+
+ if( !pFilterEntry->maExportXSLT.isEmpty() )
+ {
+ pFilterEntry->maFlags |= 2;
+ }
+ else
+ {
+ pFilterEntry->maFlags &= ~2;
+ }
+ pFilterEntry->maFlags |= 0x80040;
+
+ // 2. create user data for filter entry
+ Sequence< OUString > aUserData( pFilterEntry->getFilterUserData());
+
+ // 3. create property values for filter entry
+ Sequence< PropertyValue > aFilterData{
+ comphelper::makePropertyValue("Type", pFilterEntry->maType),
+ comphelper::makePropertyValue("UIName", pFilterEntry->maInterfaceName),
+ comphelper::makePropertyValue("DocumentService", pFilterEntry->maDocumentService),
+ comphelper::makePropertyValue("FilterService", OUString( "com.sun.star.comp.Writer.XmlFilterAdaptor" )),
+ comphelper::makePropertyValue("Flags", pFilterEntry->maFlags),
+ comphelper::makePropertyValue("UserData", aUserData),
+ comphelper::makePropertyValue("FileFormatVersion", pFilterEntry->maFileFormatVersion),
+ comphelper::makePropertyValue("TemplateName", pFilterEntry->maImportTemplate)
+ };
+
+ // 4. insert new or replace existing filter
+ try
+ {
+ Any aAny( aFilterData );
+ if( mxFilterContainer->hasByName( pFilterEntry->maFilterName ) )
+ {
+ mxFilterContainer->replaceByName( pFilterEntry->maFilterName, aAny );
+ }
+ else
+ {
+ mxFilterContainer->insertByName( pFilterEntry->maFilterName, aAny );
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+
+ // 5. prepare type information
+ if( bOk )
+ {
+ OUString aDocType;
+ if( !pFilterEntry->maDocType.match( m_sDocTypePrefix ) )
+ {
+ aDocType = m_sDocTypePrefix + pFilterEntry->maDocType;
+ }
+ else
+ {
+ aDocType = pFilterEntry->maDocType;
+ }
+ if (aDocType == m_sDocTypePrefix)
+ aDocType.clear();
+
+ Sequence< PropertyValue > aValues{
+ comphelper::makePropertyValue("UIName", pFilterEntry->maInterfaceName),
+ comphelper::makePropertyValue("ClipboardFormat", aDocType),
+ comphelper::makePropertyValue("DocumentIconID", pFilterEntry->mnDocumentIconID),
+ comphelper::makePropertyValue("Extensions", createExtensionsSequence( pFilterEntry->maExtension ))
+ };
+
+ // the detect service will only be registered, if a doctype/search token was specified
+ if (aDocType.getLength() > m_sDocTypePrefix.getLength())
+ {
+ aValues.realloc(5);
+ auto pValues = aValues.getArray();
+ pValues[4].Name = "DetectService";
+ pValues[4].Value <<= OUString( "com.sun.star.comp.filters.XMLFilterDetect" );
+ }
+
+ // 6. insert new or replace existing type information
+ if( mxTypeDetection.is() )
+ {
+ try
+ {
+ Any aAny( aValues );
+ if( mxTypeDetection->hasByName( pFilterEntry->maType ) )
+ {
+ mxTypeDetection->replaceByName( pFilterEntry->maType, aAny );
+ }
+ else
+ {
+ mxTypeDetection->insertByName( pFilterEntry->maType, aAny );
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+
+ if( bOk )
+ {
+ try
+ {
+ Reference< XFlushable > xFlushable( mxTypeDetection, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+
+ if( !bOk )
+ {
+ // we failed to add the type, so lets remove the filter
+ try
+ {
+ mxFilterContainer->removeByName( pFilterEntry->maFilterName );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+ }
+ else // bOk
+ {
+ try
+ {
+ Reference< XFlushable > xFlushable( mxFilterContainer, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ bOk = false;
+ }
+
+ if( !bOk )
+ {
+ // we failed to add the filter, so lets remove the type
+ try
+ {
+ mxTypeDetection->removeByName( pFilterEntry->maType );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ }
+ }
+ }
+
+ if( bOk )
+ {
+ if( mxExtendedTypeDetection.is() )
+ {
+ OUString sFilterDetectService( "com.sun.star.comp.filters.XMLFilterDetect" );
+ if( mxExtendedTypeDetection->hasByName( sFilterDetectService ) )
+ {
+ Sequence< PropertyValue > aSequence;
+ if( mxExtendedTypeDetection->getByName( sFilterDetectService ) >>= aSequence )
+ {
+ auto aSequenceRange = asNonConstRange(aSequence);
+ sal_Int32 nCount = aSequence.getLength();
+ sal_Int32 nIndex;
+ for( nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ if ( aSequence[nIndex].Name == "Types" )
+ {
+ Sequence< OUString > aTypes;
+ if( aSequence[nIndex].Value >>= aTypes )
+ {
+ sal_Int32 nStrCount = aTypes.getLength();
+ sal_Int32 nStr;
+ for( nStr = 0; nStr < nStrCount; nStr++ )
+ {
+ if( aTypes[nStr] == pFilterEntry->maType )
+ break;
+ }
+
+ if( nStr == nStrCount )
+ {
+ aTypes.realloc( nStrCount + 1 );
+ aTypes.getArray()[nStrCount] = pFilterEntry->maType;
+
+ aSequenceRange[nIndex].Value <<= aTypes;
+
+ mxExtendedTypeDetection->replaceByName( sFilterDetectService, Any( aSequence ) );
+
+ Reference< XFlushable > xFlushable( mxExtendedTypeDetection, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+ }
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // update ui
+ if( bOk )
+ {
+ if( pOldInfo )
+ {
+ changeEntry( pFilterEntry );
+ }
+ else
+ {
+ addFilterEntry( pFilterEntry );
+ maFilterVector.push_back( std::unique_ptr<filter_info_impl>(pFilterEntry) );
+ }
+ }
+
+ return bOk;
+}
+
+/** is called when the user clicks the "Test" button */
+void XMLFilterSettingsDialog::onTest()
+{
+ // get the first selected filter
+ filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_selected_id());
+ if (pInfo)
+ {
+ XMLFilterTestDialog aDlg(m_xDialog.get(), mxContext);
+ aDlg.test( *pInfo );
+ }
+}
+
+void XMLFilterSettingsDialog::onDelete()
+{
+ int nIndex = m_xFilterListBox->get_selected_index();
+ if (nIndex == -1)
+ return;
+ filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(nIndex));
+ if (pInfo)
+ {
+ OUString aMessage(XsltResId(STR_WARN_DELETE));
+ aMessage = aMessage.replaceFirst( "%s", pInfo->maFilterName );
+
+ std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::YesNo,
+ aMessage));
+ xWarn->set_default_response(RET_YES);
+ if (xWarn->run() == RET_YES)
+ {
+ try
+ {
+ if( mxFilterContainer->hasByName( pInfo->maFilterName ) )
+ {
+ mxFilterContainer->removeByName( pInfo->maFilterName );
+
+ bool bTypeStillUsed = false;
+
+ // now loop over all filter and see if someone else uses the same type
+ Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
+ OUString* pFilterName = aFilterNames.getArray();
+
+ const sal_Int32 nCount = aFilterNames.getLength();
+ sal_Int32 nFilter;
+ Sequence< PropertyValue > aValues;
+
+ for( nFilter = 0; (nFilter < nCount) && !bTypeStillUsed; nFilter++, pFilterName++ )
+ {
+ Any aAny( mxFilterContainer->getByName( *pFilterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ const sal_Int32 nValueCount( aValues.getLength() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 nValue;
+
+ for (nValue = 0; nValue < nValueCount; nValue++, pValues++)
+ {
+ if ( pValues->Name == "Type" )
+ {
+ OUString aType;
+ pValues->Value >>= aType;
+ if( aType == pInfo->maType )
+ bTypeStillUsed = true;
+
+ break;
+ }
+ }
+ }
+
+ // if the type is not used anymore, remove it also
+ if( !bTypeStillUsed )
+ {
+ if( mxTypeDetection->hasByName( pInfo->maType ) )
+ {
+ mxTypeDetection->removeByName( pInfo->maType );
+ }
+ }
+
+ Reference< XFlushable > xFlushable( mxFilterContainer, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+
+ xFlushable.set( mxTypeDetection, UNO_QUERY );
+ if( xFlushable.is() )
+ xFlushable->flush();
+
+ // now remove entry from ui
+ m_xFilterListBox->remove(nIndex);
+
+ // and delete the filter entry
+ maFilterVector.erase(std::find_if( maFilterVector.begin(), maFilterVector.end(),
+ [&] (std::unique_ptr<filter_info_impl> const & p)
+ { return p.get() == pInfo; }));
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+ }
+ }
+
+ updateStates();
+}
+
+void XMLFilterSettingsDialog::onSave()
+{
+ std::vector<filter_info_impl*> aFilters;
+
+ int nFilters = 0;
+
+ m_xFilterListBox->selected_foreach([&](weld::TreeIter& rEntry){
+ filter_info_impl* pInfo = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(rEntry));
+ aFilters.push_back(pInfo);
+ ++nFilters;
+ return false;
+ });
+
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION,
+ FileDialogFlags::NONE, m_xDialog.get());
+ aDlg.SetContext(sfx2::FileDialogHelper::XMLFilterSettings);
+
+ OUString aExtensions( "*.jar" );
+ OUString aFilterName = XsltResId(STR_FILTER_PACKAGE) +
+ " (" + aExtensions + ")";
+
+ aDlg.AddFilter( aFilterName, aExtensions );
+
+ if ( aDlg.Execute() != ERRCODE_NONE )
+ return;
+
+ XMLFilterJarHelper aJarHelper( mxContext );
+ aJarHelper.savePackage( aDlg.GetPath(), aFilters );
+
+ INetURLObject aURL( aDlg.GetPath() );
+
+ OUString sPlaceholder( "%s" );
+
+ OUString aMsg;
+ if( nFilters > 0 )
+ {
+ aMsg = XsltResId(STR_FILTERS_HAVE_BEEN_SAVED);
+ aMsg = aMsg.replaceFirst( sPlaceholder, OUString::number( nFilters ) );
+ aMsg = aMsg.replaceFirst(sPlaceholder, aURL.GetLastName());
+ }
+ else
+ {
+ aMsg = XsltResId(STR_FILTER_HAS_BEEN_SAVED);
+ aMsg = aMsg.replaceFirst( sPlaceholder, (*aFilters.begin())->maFilterName );
+ aMsg = aMsg.replaceFirst(sPlaceholder, aURL.GetLastName());
+ }
+
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ aMsg));
+ xInfoBox->run();
+}
+
+void XMLFilterSettingsDialog::onOpen()
+{
+ std::vector< std::unique_ptr<filter_info_impl> > aFilters;
+
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_xDialog.get());
+ aDlg.SetContext(sfx2::FileDialogHelper::XMLFilterSettings);
+
+ OUString aExtensions( "*.jar" );
+ OUString aFilterName = XsltResId(STR_FILTER_PACKAGE) +
+ " (" + aExtensions + ")";
+
+ aDlg.AddFilter( aFilterName, aExtensions );
+
+ if ( aDlg.Execute() != ERRCODE_NONE )
+ return;
+
+ OUString aURL( aDlg.GetPath() );
+
+ XMLFilterJarHelper aJarHelper( mxContext );
+ aJarHelper.openPackage( aURL, aFilters );
+
+ int nFilters = 0;
+ for (auto& filter : aFilters)
+ {
+ if( insertOrEdit(filter.get()) )
+ {
+ aFilterName = filter->maFilterName;
+ nFilters++;
+ }
+
+ filter.reset();
+ }
+
+ disposeFilterList();
+ initFilterList();
+
+ OUString sPlaceholder( "%s" );
+ OUString aMsg;
+ if( nFilters == 0 )
+ {
+ INetURLObject aURLObj( aURL );
+ aMsg = XsltResId(STR_NO_FILTERS_FOUND);
+ aMsg = aMsg.replaceFirst(sPlaceholder, aURLObj.GetLastName());
+ }
+ else if( nFilters == 1 )
+ {
+ aMsg = XsltResId(STR_FILTER_INSTALLED);
+ aMsg = aMsg.replaceFirst( sPlaceholder, aFilterName );
+
+ }
+ else
+ {
+ aMsg = XsltResId(STR_FILTERS_INSTALLED);
+ aMsg = aMsg.replaceFirst( sPlaceholder, OUString::number( nFilters ) );
+ }
+
+ std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Info, VclButtonsType::Ok,
+ aMsg));
+ xInfoBox->run();
+}
+
+void XMLFilterSettingsDialog::disposeFilterList()
+{
+ maFilterVector.clear();
+ m_xFilterListBox->clear();
+}
+
+void XMLFilterSettingsDialog::initFilterList()
+{
+ if( mxFilterContainer.is() )
+ {
+ const Sequence< OUString > aFilterNames( mxFilterContainer->getElementNames() );
+
+ Sequence< PropertyValue > aValues;
+
+ std::unique_ptr<filter_info_impl> pTempFilter( new filter_info_impl );
+ Sequence< OUString > aUserData;
+
+ for( OUString const & filterName : aFilterNames )
+ {
+ aUserData.realloc(0);
+
+ try
+ {
+ Any aAny( mxFilterContainer->getByName( filterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ OUString aFilterService;
+ pTempFilter->maFilterName = filterName;
+
+ const sal_Int32 nValueCount( aValues.getLength() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 nValue;
+
+ for( nValue = 0; nValue < nValueCount; nValue++, pValues++ )
+ {
+ if ( pValues->Name == "Type" )
+ {
+ pValues->Value >>= pTempFilter->maType;
+ }
+ else if ( pValues->Name == "UIName" )
+ {
+ pValues->Value >>= pTempFilter->maInterfaceName;
+ }
+ else if ( pValues->Name == "DocumentService" )
+ {
+ pValues->Value >>= pTempFilter->maDocumentService;
+ }
+ else if ( pValues->Name == "FilterService" )
+ {
+ pValues->Value >>= aFilterService;
+ }
+ else if ( pValues->Name == "Flags" )
+ {
+ pValues->Value >>= pTempFilter->maFlags;
+ }
+ else if ( pValues->Name == "UserData" )
+ {
+ pValues->Value >>= aUserData;
+ }
+ else if ( pValues->Name == "FileFormatVersion" )
+ {
+ pValues->Value >>= pTempFilter->maFileFormatVersion;
+ }
+ else if ( pValues->Name == "TemplateName" )
+ {
+ pValues->Value >>= pTempFilter->maImportTemplate;
+ }
+ else if ( pValues->Name == "Finalized" )
+ {
+ pValues->Value >>= pTempFilter->mbReadonly;
+ }
+ }
+
+ // if this is not a XmlFilterAdaptor entry, skip it
+ if( aFilterService != "com.sun.star.comp.Writer.XmlFilterAdaptor" )
+ continue;
+
+
+ // if we don't have the needed user data, skip it
+ if( aUserData.getLength() < 6 )
+ continue;
+
+ // if this is not an XSLTFilter entry, skip it
+ if( aUserData[0] != "com.sun.star.documentconversion.XSLTFilter" )
+ continue;
+
+ // get filter information from userdata
+ pTempFilter->mbNeedsXSLT2 = aUserData[1].toBoolean();
+ pTempFilter->maImportService = aUserData[2];
+ pTempFilter->maExportService = aUserData[3];
+ pTempFilter->maImportXSLT = aUserData[4];
+ pTempFilter->maExportXSLT = aUserData[5];
+ if( aUserData.getLength() >= 8 )
+ pTempFilter->maComment = aUserData[7];
+
+ // get type information
+ if( mxTypeDetection.is() )
+ {
+ try
+ {
+ aAny = mxTypeDetection->getByName( pTempFilter->maType );
+ Sequence< PropertyValue > aValues2;
+
+ if( aAny >>= aValues2 )
+ {
+ const sal_Int32 nValueCount2( aValues2.getLength() );
+ PropertyValue* pValues2 = aValues2.getArray();
+ sal_Int32 nValue2;
+
+ for( nValue2 = 0; nValue2 < nValueCount2; nValue2++, pValues2++ )
+ {
+ if ( pValues2->Name == "ClipboardFormat" )
+ {
+ OUString aDocType;
+ pValues2->Value >>= aDocType;
+
+ if( aDocType.match( m_sDocTypePrefix ) )
+ aDocType = aDocType.copy( m_sDocTypePrefix.getLength() );
+
+ pTempFilter->maDocType = aDocType;
+ }
+ else if ( pValues2->Name == "Extensions" )
+ {
+ Sequence< OUString > aExtensions;
+ if( pValues2->Value >>= aExtensions )
+ {
+ pTempFilter->maExtension.clear();
+
+ sal_Int32 nCount3( aExtensions.getLength() );
+ OUString* pExtensions = aExtensions.getArray();
+ sal_Int32 n;
+ for( n = 0; n < nCount3; n++ )
+ {
+ if( n > 0 )
+ pTempFilter->maExtension += ";";
+ pTempFilter->maExtension += *pExtensions++;
+ }
+ }
+ }
+ else if ( pValues2->Name == "DocumentIconID" )
+ {
+ pValues2->Value >>= pTempFilter->mnDocumentIconID;
+ }
+ else if ( pValues2->Name == "Finalized" )
+ {
+ // both the filter and the type may be finalized
+ bool bTemp = false;
+ pValues2->Value >>= bTemp;
+ pTempFilter->mbReadonly |= bTemp;
+ }
+ }
+ }
+ }
+ catch( const css::container::NoSuchElementException& )
+ {
+ OSL_FAIL( "Type not found, user error?" ); // TODO: error?
+ }
+ }
+
+ // add entry to internal container and to ui filter list box
+ maFilterVector.push_back( std::unique_ptr<filter_info_impl>(pTempFilter.get()) );
+ addFilterEntry( pTempFilter.release() );
+
+
+ pTempFilter.reset( new filter_info_impl );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ }
+ }
+
+ if (m_xFilterListBox->n_children())
+ {
+ m_xFilterListBox->columns_autosize();
+ m_xFilterListBox->select(0);
+ }
+}
+
+application_info_impl::application_info_impl( const char * pDocumentService, const OUString& rUINameRes, const char * mpXMLImporter, const char * mpXMLExporter )
+: maDocumentService( pDocumentService, strlen( pDocumentService ), RTL_TEXTENCODING_ASCII_US ),
+ maDocumentUIName(Translate::ExpandVariables(rUINameRes)),
+ maXMLImporter( mpXMLImporter, strlen( mpXMLImporter ), RTL_TEXTENCODING_ASCII_US ),
+ maXMLExporter( mpXMLExporter, strlen( mpXMLExporter ), RTL_TEXTENCODING_ASCII_US )
+{
+}
+
+std::vector< application_info_impl > const & getApplicationInfos()
+{
+ static std::vector< application_info_impl > const aInfos
+ {
+ { "com.sun.star.text.TextDocument",
+ STR_APPL_NAME_WRITER,
+ "com.sun.star.comp.Writer.XMLImporter",
+ "com.sun.star.comp.Writer.XMLExporter" },
+
+ { "com.sun.star.sheet.SpreadsheetDocument",
+ STR_APPL_NAME_CALC,
+ "com.sun.star.comp.Calc.XMLImporter",
+ "com.sun.star.comp.Calc.XMLExporter" },
+
+ { "com.sun.star.presentation.PresentationDocument",
+ STR_APPL_NAME_IMPRESS,
+ "com.sun.star.comp.Impress.XMLImporter",
+ "com.sun.star.comp.Impress.XMLExporter" },
+
+ { "com.sun.star.drawing.DrawingDocument",
+ STR_APPL_NAME_DRAW,
+ "com.sun.star.comp.Draw.XMLImporter",
+ "com.sun.star.comp.Draw.XMLExporter" },
+
+ // --- oasis file formats...
+ { "com.sun.star.text.TextDocument",
+ STR_APPL_NAME_OASIS_WRITER,
+ "com.sun.star.comp.Writer.XMLOasisImporter",
+ "com.sun.star.comp.Writer.XMLOasisExporter" },
+
+ { "com.sun.star.sheet.SpreadsheetDocument",
+ STR_APPL_NAME_OASIS_CALC,
+ "com.sun.star.comp.Calc.XMLOasisImporter",
+ "com.sun.star.comp.Calc.XMLOasisExporter" },
+
+ { "com.sun.star.presentation.PresentationDocument",
+ STR_APPL_NAME_OASIS_IMPRESS,
+ "com.sun.star.comp.Impress.XMLOasisImporter",
+ "com.sun.star.comp.Impress.XMLOasisExporter" },
+
+ { "com.sun.star.drawing.DrawingDocument",
+ STR_APPL_NAME_OASIS_DRAW,
+ "com.sun.star.comp.Draw.XMLOasisImporter",
+ "com.sun.star.comp.Draw.XMLOasisExporter" },
+ };
+
+ return aInfos;
+}
+
+const application_info_impl* getApplicationInfo( std::u16string_view rServiceName )
+{
+ std::vector< application_info_impl > const & rInfos = getApplicationInfos();
+ for (auto const& info : rInfos)
+ {
+ if( rServiceName == info.maXMLExporter ||
+ rServiceName == info.maXMLImporter)
+ {
+ return &info;
+ }
+ }
+ return nullptr;
+}
+
+OUString getApplicationUIName( std::u16string_view rServiceName )
+{
+ const application_info_impl* pInfo = getApplicationInfo( rServiceName );
+ if( pInfo )
+ {
+ return pInfo->maDocumentUIName;
+ }
+ else
+ {
+ OUString aRet = XsltResId(STR_UNKNOWN_APPLICATION);
+ if( !rServiceName.empty() )
+ {
+ aRet += OUString::Concat(" (") + rServiceName + ")";
+ }
+ return aRet;
+ }
+}
+
+/** adds a new filter info entry to the ui filter list */
+void XMLFilterSettingsDialog::addFilterEntry( const filter_info_impl* pInfo )
+{
+ int nRow = m_xFilterListBox->n_children();
+ OUString sId(weld::toId(pInfo));
+ m_xFilterListBox->append(sId, pInfo->maFilterName);
+ m_xFilterListBox->set_text(nRow, getEntryString(pInfo), 1);
+}
+
+void XMLFilterSettingsDialog::changeEntry( const filter_info_impl* pInfo )
+{
+ const int nCount = m_xFilterListBox->n_children();
+ for(int nPos = 0; nPos < nCount; ++nPos)
+ {
+ filter_info_impl* pEntry = weld::fromId<filter_info_impl*>(m_xFilterListBox->get_id(nPos));
+ if (pEntry == pInfo)
+ {
+ m_xFilterListBox->set_text(nPos, pInfo->maFilterName, 0);
+ m_xFilterListBox->set_text(nPos, getEntryString(pInfo), 1);
+ break;
+ }
+ }
+}
+
+OUString XMLFilterSettingsDialog::getEntryString( const filter_info_impl* pInfo )
+{
+ OUString aEntryStr;
+ if ( !pInfo->maExportService.isEmpty() )
+ aEntryStr = getApplicationUIName( pInfo->maExportService );
+ else
+ aEntryStr = getApplicationUIName( pInfo->maImportService );
+ aEntryStr += " - ";
+
+ if( pInfo->maFlags & 1 )
+ {
+ if( pInfo->maFlags & 2 )
+ {
+ aEntryStr += XsltResId(STR_IMPORT_EXPORT);
+ }
+ else
+ {
+ aEntryStr += XsltResId(STR_IMPORT_ONLY);
+ }
+ }
+ else if( pInfo->maFlags & 2 )
+ {
+ aEntryStr += XsltResId(STR_EXPORT_ONLY);
+ }
+ else
+ {
+ aEntryStr += XsltResId(STR_UNDEFINED_FILTER);
+ }
+
+ return aEntryStr;
+}
+
+filter_info_impl::filter_info_impl()
+ : maFlags(0x00080040)
+ , maFileFormatVersion(0)
+ , mnDocumentIconID(0)
+ , mbReadonly(false)
+ , mbNeedsXSLT2(false)
+{
+}
+
+bool filter_info_impl::operator==( const filter_info_impl& r ) const
+{
+ return maFilterName == r.maFilterName &&
+ maType == r.maType &&
+ maDocumentService == r.maDocumentService &&
+ maInterfaceName == r.maInterfaceName &&
+ maComment == r.maComment &&
+ maExtension == r.maExtension &&
+ maDocType == r.maDocType &&
+ maExportXSLT == r.maExportXSLT &&
+ maImportXSLT == r.maImportXSLT &&
+ maExportService == r.maExportService &&
+ maImportService == r.maImportService &&
+ maImportTemplate == r.maImportTemplate &&
+ maFlags == r.maFlags &&
+ maFileFormatVersion == r.maFileFormatVersion &&
+ mbNeedsXSLT2 == r.mbNeedsXSLT2;
+}
+
+
+Sequence< OUString > filter_info_impl::getFilterUserData() const
+{
+ return
+ {
+ "com.sun.star.documentconversion.XSLTFilter",
+ OUString::boolean( mbNeedsXSLT2 ),
+ maImportService,
+ maExportService,
+ maImportXSLT,
+ maExportXSLT,
+ maComment
+ };
+}
+
+OUString string_encode( const OUString & rText )
+{
+ static constexpr auto uricNoSlash = rtl::createUriCharClass(
+ u8"!$&'()*+-.0123456789:=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~");
+
+
+ return
+ Uri::encode( rText, uricNoSlash.data(), rtl_UriEncodeCheckEscapes, RTL_TEXTENCODING_UTF8 );
+}
+
+OUString string_decode( const OUString & rText )
+{
+ return Uri::decode( rText, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
+}
+
+bool copyStreams( const Reference< XInputStream >& xIS, const Reference< XOutputStream >& xOS )
+{
+ try
+ {
+ sal_Int32 nBufferSize = 512;
+ Sequence< sal_Int8 > aDataBuffer(nBufferSize);
+
+ sal_Int32 nRead;
+ do
+ {
+ nRead = xIS->readBytes( aDataBuffer, nBufferSize );
+
+ if( nRead )
+ {
+ if( nRead < nBufferSize )
+ {
+ nBufferSize = nRead;
+ aDataBuffer.realloc(nRead);
+ }
+
+ xOS->writeBytes( aDataBuffer );
+ }
+ }
+ while( nRead );
+
+ xOS->flush();
+
+ return true;
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ return false;
+}
+
+bool createDirectory( std::u16string_view rURL )
+{
+ size_t nLastIndex = sizeof( "file:///" ) - 2;
+ while( nLastIndex != std::u16string_view::npos )
+ {
+ nLastIndex = rURL.find( '/', nLastIndex + 1);
+ if( nLastIndex != std::u16string_view::npos )
+ {
+ OUString aDirURL( rURL.substr( 0, nLastIndex ) );
+ Directory aDir( aDirURL );
+ Directory::RC rc = aDir.open();
+ if( rc == Directory::E_NOENT )
+ rc = osl::Directory::create( aDirURL );
+
+ if( rc != Directory::E_None )
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx b/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx
new file mode 100644
index 000000000..c555e8b16
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltersettingsdialog.hxx
@@ -0,0 +1,97 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <vcl/weld.hxx>
+#include <vcl/locktoplevels.hxx>
+#include <unotools/moduleoptions.hxx>
+
+#include "xmlfiltercommon.hxx"
+
+class XMLFilterSettingsDialog : public weld::GenericDialogController
+{
+public:
+ XMLFilterSettingsDialog(weld::Window* pParent,
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+ virtual ~XMLFilterSettingsDialog() override;
+
+ DECL_LINK(ClickHdl_Impl, weld::Button&, void );
+ DECL_LINK(SelectionChangedHdl_Impl, weld::TreeView&, void);
+ DECL_LINK(DoubleClickHdl_Impl, weld::TreeView&, bool);
+
+ void UpdateWindow();
+
+ void present() { m_xDialog->present(); }
+
+ void onNew();
+ void onEdit();
+ void onTest();
+ void onDelete();
+ void onSave();
+ void onOpen();
+
+ void updateStates();
+private:
+ void initFilterList();
+ void disposeFilterList();
+
+ void incBusy() { maBusy.incBusy(m_xDialog.get()); }
+ void decBusy() { maBusy.decBusy(); }
+
+ bool insertOrEdit( filter_info_impl* pNewInfo, const filter_info_impl* pOldInfo = nullptr );
+
+ OUString createUniqueFilterName( const OUString& rUIName );
+ OUString createUniqueTypeName( const OUString& rTypeName );
+ OUString createUniqueInterfaceName( const OUString& rInterfaceName );
+
+ /** adds a new filter info entry to the ui filter list */
+ void addFilterEntry( const filter_info_impl* pInfo );
+
+ void changeEntry( const filter_info_impl* pInfo );
+
+ static OUString getEntryString( const filter_info_impl* pInfo );
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::container::XNameContainer > mxFilterContainer;
+ css::uno::Reference< css::container::XNameContainer > mxTypeDetection;
+ css::uno::Reference< css::container::XNameContainer > mxExtendedTypeDetection;
+
+ std::vector< std::unique_ptr<filter_info_impl> > maFilterVector;
+
+ TopLevelWindowLocker maBusy;
+
+ OUString m_sTemplatePath;
+ OUString m_sDocTypePrefix;
+
+ SvtModuleOptions maModuleOpt;
+
+ std::unique_ptr<weld::Button> m_xPBNew;
+ std::unique_ptr<weld::Button> m_xPBEdit;
+ std::unique_ptr<weld::Button> m_xPBTest;
+ std::unique_ptr<weld::Button> m_xPBDelete;
+ std::unique_ptr<weld::Button> m_xPBSave;
+ std::unique_ptr<weld::Button> m_xPBOpen;
+ std::unique_ptr<weld::Button> m_xPBClose;
+ std::unique_ptr<weld::TreeView> m_xFilterListBox;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabdialog.cxx b/filter/source/xsltdialog/xmlfiltertabdialog.cxx
new file mode 100644
index 000000000..ea73c486a
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabdialog.cxx
@@ -0,0 +1,263 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <comphelper/fileurl.hxx>
+#include <tools/diagnose_ex.h>
+#include <vcl/svapp.hxx>
+#include <vcl/weld.hxx>
+#include <osl/file.hxx>
+#include <unotools/resmgr.hxx>
+
+#include <strings.hrc>
+#include "xmlfiltertabdialog.hxx"
+#include "xmlfiltertabpagebasic.hxx"
+#include "xmlfiltertabpagexslt.hxx"
+#include "xmlfiltercommon.hxx"
+
+using namespace com::sun::star::uno;
+using namespace com::sun::star::container;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::lang;
+
+XMLFilterTabDialog::XMLFilterTabDialog(weld::Window *pParent,
+ const Reference< XComponentContext >& rxContext, const filter_info_impl* pInfo)
+ : GenericDialogController(pParent, "filter/ui/xsltfilterdialog.ui", "XSLTFilterDialog")
+ , mxContext(rxContext)
+ , m_xTabCtrl(m_xBuilder->weld_notebook("tabcontrol"))
+ , m_xOKBtn(m_xBuilder->weld_button("ok"))
+ , mpBasicPage(new XMLFilterTabPageBasic(m_xTabCtrl->get_page("general")))
+ , mpXSLTPage(new XMLFilterTabPageXSLT(m_xTabCtrl->get_page("transformation"), m_xDialog.get()))
+{
+ mpOldInfo = pInfo;
+ mpNewInfo.reset( new filter_info_impl( *mpOldInfo ) );
+
+ OUString aTitle(m_xDialog->get_title());
+ aTitle = aTitle.replaceAll("%s", mpNewInfo->maFilterName);
+ m_xDialog->set_title(aTitle);
+
+ m_xOKBtn->connect_clicked( LINK( this, XMLFilterTabDialog, OkHdl ) );
+
+ mpBasicPage->SetInfo( mpNewInfo.get() );
+ mpXSLTPage->SetInfo( mpNewInfo.get() );
+}
+
+XMLFilterTabDialog::~XMLFilterTabDialog()
+{
+}
+
+bool XMLFilterTabDialog::onOk()
+{
+ mpXSLTPage->FillInfo( mpNewInfo.get() );
+ mpBasicPage->FillInfo( mpNewInfo.get() );
+
+ OString sErrorPage;
+ TranslateId pErrorId;
+ weld::Widget* pFocusWindow = nullptr;
+ OUString aReplace1;
+ OUString aReplace2;
+
+ // 1. see if the filter name is ok
+ if( (mpNewInfo->maFilterName.isEmpty()) || (mpNewInfo->maFilterName != mpOldInfo->maFilterName) )
+ {
+ // if the user deleted the filter name, we reset the original filter name
+ if( mpNewInfo->maFilterName.isEmpty() )
+ {
+ mpNewInfo->maFilterName = mpOldInfo->maFilterName;
+ }
+ else
+ {
+ try
+ {
+ Reference< XNameAccess > xFilterContainer( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", mxContext ), UNO_QUERY );
+ if( xFilterContainer.is() )
+ {
+ if( xFilterContainer->hasByName( mpNewInfo->maFilterName ) )
+ {
+ sErrorPage = "general";
+ pErrorId = STR_ERROR_FILTER_NAME_EXISTS;
+ pFocusWindow = mpBasicPage->m_xEDFilterName.get();
+ aReplace1 = mpNewInfo->maFilterName;
+ }
+
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+ }
+ }
+
+ // 2. see if the interface name is ok
+ if( (mpNewInfo->maInterfaceName.isEmpty()) || (mpNewInfo->maInterfaceName != mpOldInfo->maInterfaceName) )
+ {
+ // if the user deleted the interface name, we reset the original filter name
+ if( mpNewInfo->maInterfaceName.isEmpty() )
+ {
+ mpNewInfo->maInterfaceName = mpOldInfo->maInterfaceName;
+ }
+ else
+ {
+ try
+ {
+ Reference< XNameAccess > xFilterContainer( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", mxContext ), UNO_QUERY );
+ if( xFilterContainer.is() )
+ {
+ Sequence< OUString > aFilterNames( xFilterContainer->getElementNames() );
+ OUString* pFilterName = aFilterNames.getArray();
+
+ const sal_Int32 nCount = aFilterNames.getLength();
+ sal_Int32 nFilter;
+
+ Sequence< PropertyValue > aValues;
+ for( nFilter = 0; (nFilter < nCount) && !pErrorId; nFilter++, pFilterName++ )
+ {
+ Any aAny( xFilterContainer->getByName( *pFilterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ const sal_Int32 nValueCount( aValues.getLength() );
+ PropertyValue* pValues = aValues.getArray();
+ sal_Int32 nValue;
+
+ for( nValue = 0; (nValue < nValueCount) && !pErrorId; nValue++, pValues++ )
+ {
+ if ( pValues->Name == "UIName" )
+ {
+ OUString aInterfaceName;
+ pValues->Value >>= aInterfaceName;
+ if( aInterfaceName == mpNewInfo->maInterfaceName )
+ {
+ sErrorPage = "general";
+ pErrorId = STR_ERROR_TYPE_NAME_EXISTS;
+ pFocusWindow = mpBasicPage->m_xEDInterfaceName.get();
+ aReplace1 = mpNewInfo->maInterfaceName;
+ aReplace2 = *pFilterName;
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+ }
+ }
+
+ if (!pErrorId)
+ {
+ // 4. see if the export xslt is valid
+ if( (mpNewInfo->maExportXSLT != mpOldInfo->maExportXSLT) && comphelper::isFileUrl( mpNewInfo->maExportXSLT ) )
+ {
+ osl::File aFile( mpNewInfo->maExportXSLT );
+ osl::File::RC aRC = aFile.open( osl_File_OpenFlag_Read );
+ if( aRC != osl::File::E_None )
+ {
+ pErrorId = STR_ERROR_EXPORT_XSLT_NOT_FOUND;
+ sErrorPage = "transformation";
+ pFocusWindow = mpXSLTPage->m_xEDExportXSLT->getWidget();
+ }
+ }
+ }
+
+ if (!pErrorId)
+ {
+ // 5. see if the import xslt is valid
+ if( (mpNewInfo->maImportXSLT != mpOldInfo->maImportXSLT) && comphelper::isFileUrl( mpNewInfo->maImportXSLT ) )
+ {
+ osl::File aFile( mpNewInfo->maImportXSLT );
+ osl::File::RC aRC = aFile.open( osl_File_OpenFlag_Read );
+ if( aRC != osl::File::E_None )
+ {
+ pErrorId = STR_ERROR_IMPORT_XSLT_NOT_FOUND;
+ sErrorPage = "transformation";
+ pFocusWindow = mpXSLTPage->m_xEDImportTemplate->getWidget();
+ }
+ }
+ }
+
+ // see if we have at least an import or an export xslt
+ if((mpNewInfo->maImportXSLT.isEmpty()) && (mpNewInfo->maExportXSLT.isEmpty()) )
+ {
+ pErrorId = STR_ERROR_EXPORT_XSLT_NOT_FOUND;
+ sErrorPage = "transformation";
+ pFocusWindow = mpXSLTPage->m_xEDExportXSLT->getWidget();
+ }
+
+ if (!pErrorId)
+ {
+ // 6. see if the import template is valid
+ if( (mpNewInfo->maImportTemplate != mpOldInfo->maImportTemplate) && comphelper::isFileUrl( mpNewInfo->maImportTemplate ) )
+ {
+ osl::File aFile( mpNewInfo->maImportTemplate );
+ osl::File::RC aRC = aFile.open( osl_File_OpenFlag_Read );
+ if( aRC != osl::File::E_None )
+ {
+ pErrorId = STR_ERROR_IMPORT_TEMPLATE_NOT_FOUND;
+ sErrorPage = "transformation";
+ pFocusWindow = mpXSLTPage->m_xEDImportTemplate->getWidget();
+ }
+ }
+ }
+
+ if (pErrorId)
+ {
+ m_xTabCtrl->set_current_page(sErrorPage);
+
+ OUString aMessage(XsltResId(pErrorId));
+
+ if( aReplace2.getLength() )
+ {
+ aMessage = aMessage.replaceAll( "%s1", aReplace1 );
+ aMessage = aMessage.replaceAll( "%s2", aReplace2 );
+ }
+ else if( aReplace1.getLength() )
+ {
+ aMessage = aMessage.replaceAll( "%s", aReplace1 );
+ }
+
+ std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_xDialog.get(),
+ VclMessageType::Warning, VclButtonsType::Ok,
+ aMessage));
+ xBox->run();
+
+ if( pFocusWindow )
+ pFocusWindow->grab_focus();
+
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+}
+
+IMPL_LINK_NOARG(XMLFilterTabDialog, OkHdl, weld::Button&, void)
+{
+ if( onOk() )
+ m_xDialog->response(RET_OK);
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabdialog.hxx b/filter/source/xsltdialog/xmlfiltertabdialog.hxx
new file mode 100644
index 000000000..e764102b0
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabdialog.hxx
@@ -0,0 +1,54 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <vcl/weld.hxx>
+
+class filter_info_impl;
+class XMLFilterTabPageBasic;
+class XMLFilterTabPageXSLT;
+
+class XMLFilterTabDialog : public weld::GenericDialogController
+{
+public:
+ XMLFilterTabDialog(weld::Window *pParent, const css::uno::Reference< css::uno::XComponentContext >& rxContext, const filter_info_impl* pInfo);
+ virtual ~XMLFilterTabDialog() override;
+
+ bool onOk();
+
+ filter_info_impl* getNewFilterInfo() const { return mpNewInfo.get(); }
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+
+ DECL_LINK(OkHdl, weld::Button&, void);
+
+ const filter_info_impl* mpOldInfo;
+ std::unique_ptr<filter_info_impl> mpNewInfo;
+
+ std::unique_ptr<weld::Notebook> m_xTabCtrl;
+ std::unique_ptr<weld::Button> m_xOKBtn;
+
+ std::unique_ptr<XMLFilterTabPageBasic> mpBasicPage;
+ std::unique_ptr<XMLFilterTabPageXSLT> mpXSLTPage;
+};
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabpagebasic.cxx b/filter/source/xsltdialog/xmlfiltertabpagebasic.cxx
new file mode 100644
index 000000000..63b969a2f
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabpagebasic.cxx
@@ -0,0 +1,128 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <rtl/ustrbuf.hxx>
+#include <vcl/svapp.hxx>
+#include "xmlfiltercommon.hxx"
+#include "xmlfiltertabpagebasic.hxx"
+
+XMLFilterTabPageBasic::XMLFilterTabPageBasic(weld::Widget* pPage)
+ : m_xBuilder(Application::CreateBuilder(pPage, "filter/ui/xmlfiltertabpagegeneral.ui"))
+ , m_xContainer(m_xBuilder->weld_widget("XmlFilterTabPageGeneral"))
+ , m_xEDFilterName(m_xBuilder->weld_entry("filtername"))
+ , m_xCBApplication(m_xBuilder->weld_combo_box("application"))
+ , m_xEDInterfaceName(m_xBuilder->weld_entry("interfacename"))
+ , m_xEDExtension(m_xBuilder->weld_entry("extension"))
+ , m_xEDDescription(m_xBuilder->weld_text_view("description"))
+{
+ m_xEDDescription->set_size_request(-1, m_xEDDescription->get_height_rows(4));
+
+ std::vector< application_info_impl > const & rInfos = getApplicationInfos();
+ for (auto const& info : rInfos)
+ {
+ OUString aEntry( info.maDocumentUIName );
+ m_xCBApplication->append_text( aEntry );
+ }
+}
+
+XMLFilterTabPageBasic::~XMLFilterTabPageBasic()
+{
+}
+
+static OUString checkExtensions( const OUString& rExtensions )
+{
+ const sal_Unicode* pSource = rExtensions.getStr();
+ sal_Int32 nCount = rExtensions.getLength();
+
+ OUStringBuffer aRet;
+ while( nCount-- )
+ {
+ switch(*pSource)
+ {
+ case u',':
+ aRet.append(";");
+ break;
+ case u'.':
+ case u'*':
+ break;
+ default:
+ aRet.append( *pSource );
+ }
+
+ pSource++;
+ }
+
+ return aRet.makeStringAndClear();
+}
+
+void XMLFilterTabPageBasic::FillInfo( filter_info_impl* pInfo )
+{
+ if( !pInfo )
+ return;
+
+ if( !m_xEDFilterName->get_text().isEmpty() )
+ pInfo->maFilterName = m_xEDFilterName->get_text();
+
+ if( !m_xCBApplication->get_active_text().isEmpty() )
+ pInfo->maDocumentService = m_xCBApplication->get_active_text();
+
+ if( !m_xEDInterfaceName->get_text().isEmpty() )
+ pInfo->maInterfaceName = m_xEDInterfaceName->get_text();
+
+ if( !m_xEDExtension->get_text().isEmpty() )
+ pInfo->maExtension = checkExtensions( m_xEDExtension->get_text() );
+
+ pInfo->maComment = string_encode( m_xEDDescription->get_text() );
+
+ if( pInfo->maDocumentService.isEmpty() )
+ return;
+
+ std::vector< application_info_impl > const & rInfos = getApplicationInfos();
+ for (auto const& info : rInfos)
+ {
+ if( pInfo->maDocumentService == info.maDocumentUIName )
+ {
+ pInfo->maDocumentService = info.maDocumentService;
+ pInfo->maExportService = info.maXMLExporter;
+ pInfo->maImportService = info.maXMLImporter;
+ break;
+ }
+ }
+}
+
+void XMLFilterTabPageBasic::SetInfo(const filter_info_impl* pInfo)
+{
+ if( !pInfo )
+ return;
+
+ m_xEDFilterName->set_text( string_decode(pInfo->maFilterName) );
+ /*
+ if( pInfo->maDocumentService.getLength() )
+ maCBApplication.set_text( getApplicationUIName( pInfo->maDocumentService ) );
+ */
+ if( !pInfo->maExportService.isEmpty() )
+ m_xCBApplication->set_entry_text( getApplicationUIName( pInfo->maExportService ) );
+ else
+ m_xCBApplication->set_entry_text( getApplicationUIName( pInfo->maImportService ) );
+ m_xEDInterfaceName->set_text( string_decode(pInfo->maInterfaceName) );
+ m_xEDExtension->set_text( pInfo->maExtension );
+ m_xEDDescription->set_text( string_decode( pInfo->maComment ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx b/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx
new file mode 100644
index 000000000..c11a4c69e
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabpagebasic.hxx
@@ -0,0 +1,43 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+
+class filter_info_impl;
+
+class XMLFilterTabPageBasic
+{
+public:
+ explicit XMLFilterTabPageBasic(weld::Widget* pPage);
+ ~XMLFilterTabPageBasic();
+
+ void FillInfo( filter_info_impl* pInfo );
+ void SetInfo(const filter_info_impl* pInfo);
+
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Widget> m_xContainer;
+ std::unique_ptr<weld::Entry> m_xEDFilterName;
+ std::unique_ptr<weld::ComboBox> m_xCBApplication;
+ std::unique_ptr<weld::Entry> m_xEDInterfaceName;
+ std::unique_ptr<weld::Entry> m_xEDExtension;
+ std::unique_ptr<weld::TextView> m_xEDDescription;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabpagexslt.cxx b/filter/source/xsltdialog/xmlfiltertabpagexslt.cxx
new file mode 100644
index 000000000..4d758da28
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabpagexslt.cxx
@@ -0,0 +1,165 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <sfx2/filedlghelper.hxx>
+#include <unotools/pathoptions.hxx>
+#include <osl/file.hxx>
+#include <svl/urihelper.hxx>
+#include <vcl/svapp.hxx>
+
+#include "xmlfiltercommon.hxx"
+#include "xmlfiltertabpagexslt.hxx"
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+XMLFilterTabPageXSLT::XMLFilterTabPageXSLT(weld::Widget* pPage, weld::Dialog* pDialog)
+ : sInstPath( "$(prog)/" )
+ , m_pDialog(pDialog)
+ , m_xBuilder(Application::CreateBuilder(pPage, "filter/ui/xmlfiltertabpagetransformation.ui"))
+ , m_xContainer(m_xBuilder->weld_widget("XmlFilterTabPageTransformation"))
+ , m_xEDDocType(m_xBuilder->weld_entry("doc"))
+ , m_xEDExportXSLT(new SvtURLBox(m_xBuilder->weld_combo_box("xsltexport")))
+ , m_xPBExprotXSLT(m_xBuilder->weld_button("browseexport"))
+ , m_xEDImportXSLT(new SvtURLBox(m_xBuilder->weld_combo_box("xsltimport")))
+ , m_xPBImportXSLT(m_xBuilder->weld_button("browseimport"))
+ , m_xEDImportTemplate(new SvtURLBox(m_xBuilder->weld_combo_box("tempimport")))
+ , m_xPBImportTemplate(m_xBuilder->weld_button("browsetemp"))
+ , m_xCBNeedsXSLT2(m_xBuilder->weld_check_button("filtercb"))
+{
+ SvtPathOptions aOptions;
+ sInstPath = aOptions.SubstituteVariable( sInstPath );
+
+ m_xPBExprotXSLT->connect_clicked( LINK ( this, XMLFilterTabPageXSLT, ClickBrowseHdl_Impl ) );
+ m_xPBImportXSLT->connect_clicked( LINK ( this, XMLFilterTabPageXSLT, ClickBrowseHdl_Impl ) );
+ m_xPBImportTemplate->connect_clicked( LINK ( this, XMLFilterTabPageXSLT, ClickBrowseHdl_Impl ) );
+}
+
+XMLFilterTabPageXSLT::~XMLFilterTabPageXSLT()
+{
+}
+
+void XMLFilterTabPageXSLT::FillInfo( filter_info_impl* pInfo )
+{
+ if( pInfo )
+ {
+ pInfo->maDocType = m_xEDDocType->get_text();
+ pInfo->maExportXSLT = GetURL(*m_xEDExportXSLT);
+ pInfo->maImportXSLT = GetURL(*m_xEDImportXSLT);
+ pInfo->maImportTemplate = GetURL(*m_xEDImportTemplate);
+ pInfo->mbNeedsXSLT2 = m_xCBNeedsXSLT2->get_active();
+ }
+}
+
+void XMLFilterTabPageXSLT::SetInfo(const filter_info_impl* pInfo)
+{
+ if( pInfo )
+ {
+ m_xEDDocType->set_text( pInfo->maDocType );
+
+ SetURL( *m_xEDExportXSLT, pInfo->maExportXSLT );
+ SetURL( *m_xEDImportXSLT, pInfo->maImportXSLT );
+ SetURL( *m_xEDImportTemplate, pInfo->maImportTemplate );
+ m_xCBNeedsXSLT2->set_active(pInfo->mbNeedsXSLT2);
+ }
+}
+
+void XMLFilterTabPageXSLT::SetURL( SvtURLBox& rURLBox, const OUString& rURL )
+{
+ OUString aPath;
+
+ if( rURL.matchIgnoreAsciiCase( "file://" ) )
+ {
+ osl::FileBase::getSystemPathFromFileURL( rURL, aPath );
+
+ rURLBox.SetBaseURL( rURL );
+ rURLBox.set_entry_text( aPath );
+ }
+ else if( rURL.matchIgnoreAsciiCase( "http://" ) ||
+ rURL.matchIgnoreAsciiCase( "https://" ) ||
+ rURL.matchIgnoreAsciiCase( "ftp://" ) )
+ {
+ rURLBox.SetBaseURL( rURL );
+ rURLBox.set_entry_text( rURL );
+ }
+ else if( !rURL.isEmpty() )
+ {
+ OUString aURL = URIHelper::SmartRel2Abs( INetURLObject(sInstPath), rURL, Link<OUString *, bool>(), false );
+ osl::FileBase::getSystemPathFromFileURL( aURL, aPath );
+
+ rURLBox.SetBaseURL( aURL );
+ rURLBox.set_entry_text( aPath );
+ }
+ else
+ {
+ rURLBox.SetBaseURL( sInstPath );
+ rURLBox.set_entry_text( "" );
+ }
+}
+
+OUString XMLFilterTabPageXSLT::GetURL(const SvtURLBox& rURLBox)
+{
+ OUString aURL;
+ OUString aStrPath(rURLBox.get_active_text());
+ if( aStrPath.matchIgnoreAsciiCase( "http://" ) ||
+ aStrPath.matchIgnoreAsciiCase( "https://" ) ||
+ aStrPath.matchIgnoreAsciiCase( "ftp://" ) )
+ {
+ return aStrPath;
+ }
+ else
+ {
+ osl::FileBase::getFileURLFromSystemPath( aStrPath, aURL );
+ }
+
+ return aURL;
+}
+
+IMPL_LINK ( XMLFilterTabPageXSLT, ClickBrowseHdl_Impl, weld::Button&, rButton, void )
+{
+ SvtURLBox* pURLBox;
+
+ if( &rButton == m_xPBExprotXSLT.get() )
+ {
+ pURLBox = m_xEDExportXSLT.get();
+ }
+ else if( &rButton == m_xPBImportXSLT.get() )
+ {
+ pURLBox = m_xEDImportXSLT.get();
+ }
+ else
+ {
+ pURLBox = m_xEDImportTemplate.get();
+ }
+
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_pDialog);
+
+ aDlg.SetDisplayDirectory(GetURL(*pURLBox));
+
+ if (aDlg.Execute() == ERRCODE_NONE)
+ {
+ OUString aURL(aDlg.GetPath());
+ SetURL(*pURLBox, aURL);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx b/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx
new file mode 100644
index 000000000..52538a834
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertabpagexslt.hxx
@@ -0,0 +1,56 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <vcl/weld.hxx>
+#include <svtools/inettbc.hxx>
+
+class filter_info_impl;
+
+class XMLFilterTabPageXSLT
+{
+private:
+ void SetURL(SvtURLBox& rURLBox, const OUString& rURL);
+ static OUString GetURL(const SvtURLBox& rURLBox);
+
+ OUString sInstPath;
+
+public:
+ explicit XMLFilterTabPageXSLT(weld::Widget* pPage, weld::Dialog* pDialog);
+ ~XMLFilterTabPageXSLT();
+
+ void FillInfo( filter_info_impl* pInfo );
+ void SetInfo(const filter_info_impl* pInfo);
+
+ DECL_LINK( ClickBrowseHdl_Impl, weld::Button&, void );
+
+ weld::Dialog* m_pDialog;
+ std::unique_ptr<weld::Builder> m_xBuilder;
+ std::unique_ptr<weld::Widget> m_xContainer;
+ std::unique_ptr<weld::Entry> m_xEDDocType;
+ std::unique_ptr<SvtURLBox> m_xEDExportXSLT;
+ std::unique_ptr<weld::Button> m_xPBExprotXSLT;
+ std::unique_ptr<SvtURLBox> m_xEDImportXSLT;
+ std::unique_ptr<weld::Button> m_xPBImportXSLT;
+ std::unique_ptr<SvtURLBox> m_xEDImportTemplate;
+ std::unique_ptr<weld::Button> m_xPBImportTemplate;
+ std::unique_ptr<weld::CheckButton> m_xCBNeedsXSLT2;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertestdialog.cxx b/filter/source/xsltdialog/xmlfiltertestdialog.cxx
new file mode 100644
index 000000000..ca38ab547
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertestdialog.cxx
@@ -0,0 +1,697 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XGraphicStorageHandler.hpp>
+#include <com/sun/star/document/XEmbeddedObjectResolver.hpp>
+#include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/system/SystemShellExecute.hpp>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <com/sun/star/task/InteractionHandler.hpp>
+#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
+#include <com/sun/star/xml/XImportFilter.hpp>
+#include <com/sun/star/xml/XExportFilter.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+
+#include <comphelper/oslfile2streamwrap.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/filedlghelper.hxx>
+#include <osl/file.hxx>
+#include <unotools/tempfile.hxx>
+#include <tools/diagnose_ex.h>
+#include <tools/debug.hxx>
+#include <tools/urlobj.hxx>
+#include <comphelper/processfactory.hxx>
+
+#include "xmlfiltercommon.hxx"
+#include "xmlfiltertestdialog.hxx"
+
+
+using namespace utl;
+using namespace osl;
+using namespace comphelper;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::container;
+using namespace com::sun::star::document;
+using namespace com::sun::star::frame;
+using namespace com::sun::star::task;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+using namespace com::sun::star::system;
+using namespace com::sun::star::xml;
+using namespace com::sun::star::xml::sax;
+
+namespace {
+
+class GlobalEventListenerImpl : public ::cppu::WeakImplHelper< css::document::XDocumentEventListener >
+{
+public:
+ explicit GlobalEventListenerImpl( XMLFilterTestDialog* pDialog );
+
+ // XDocumentEventListener
+ virtual void SAL_CALL documentEventOccured( const css::document::DocumentEvent& Event ) override;
+
+ // lang::XEventListener
+ virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override;
+private:
+ XMLFilterTestDialog* mpDialog;
+};
+
+}
+
+GlobalEventListenerImpl::GlobalEventListenerImpl( XMLFilterTestDialog* pDialog )
+: mpDialog( pDialog )
+{
+}
+
+void SAL_CALL GlobalEventListenerImpl::documentEventOccured( const css::document::DocumentEvent& Event )
+{
+ ::SolarMutexGuard aGuard;
+ if( Event.EventName == "OnFocus" || Event.EventName == "OnUnload" )
+ {
+ Reference< XComponent > xComp( Event.Source, UNO_QUERY );
+ mpDialog->updateCurrentDocumentButtonState( &xComp );
+ }
+}
+
+void SAL_CALL GlobalEventListenerImpl::disposing( const css::lang::EventObject& /* Source */ )
+{
+}
+
+/** returns true if the given component supports the given service */
+static bool checkComponent( Reference< XComponent > const & rxComponent, const OUString& rServiceName )
+{
+ try
+ {
+ Reference< XServiceInfo > xInfo( rxComponent, UNO_QUERY );
+ if( xInfo.is() )
+ {
+ if( xInfo->supportsService( rServiceName ) )
+ {
+ // special case for impress documents which supports same service as draw documents
+ if ( rServiceName == "com.sun.star.drawing.DrawingDocument" )
+ {
+ // so if we want a draw we need to check if it's not an impress
+ if( !xInfo->supportsService("com.sun.star.presentation.PresentationDocument") )
+ return true;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ return false;
+}
+
+XMLFilterTestDialog::XMLFilterTestDialog(weld::Window* pParent,
+ const Reference<XComponentContext>& rxContext)
+ : GenericDialogController(pParent, "filter/ui/testxmlfilter.ui", "TestXMLFilterDialog")
+ , mxContext(rxContext)
+ , m_xExport(m_xBuilder->weld_widget("export"))
+ , m_xFTExportXSLTFile(m_xBuilder->weld_label("exportxsltfile"))
+ , m_xPBExportBrowse(m_xBuilder->weld_button("exportbrowse"))
+ , m_xPBCurrentDocument(m_xBuilder->weld_button("currentdocument"))
+ , m_xFTNameOfCurrentFile(m_xBuilder->weld_label("currentfilename"))
+ , m_xImport(m_xBuilder->weld_widget("import"))
+ , m_xFTImportXSLTFile(m_xBuilder->weld_label("importxsltfile"))
+ , m_xFTImportTemplate(m_xBuilder->weld_label("templateimport"))
+ , m_xFTImportTemplateFile(m_xBuilder->weld_label("importxslttemplate"))
+ , m_xCBXDisplaySource(m_xBuilder->weld_check_button("displaysource"))
+ , m_xPBImportBrowse(m_xBuilder->weld_button("importbrowse"))
+ , m_xPBRecentFile(m_xBuilder->weld_button("recentfile"))
+ , m_xFTNameOfRecentFile(m_xBuilder->weld_label("recentfilename"))
+ , m_xPBClose(m_xBuilder->weld_button("close"))
+{
+ m_xPBExportBrowse->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+ m_xPBCurrentDocument->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+ m_xPBImportBrowse->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+ m_xPBRecentFile->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+ m_xPBClose->connect_clicked(LINK( this, XMLFilterTestDialog, ClickHdl_Impl ) );
+
+ m_sDialogTitle = m_xDialog->get_title();
+
+ try
+ {
+ mxGlobalBroadcaster = theGlobalEventBroadcaster::get(mxContext);
+ mxGlobalEventListener = new GlobalEventListenerImpl( this );
+ mxGlobalBroadcaster->addDocumentEventListener( mxGlobalEventListener );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+XMLFilterTestDialog::~XMLFilterTestDialog()
+{
+ try
+ {
+ if( mxGlobalBroadcaster.is() )
+ mxGlobalBroadcaster->removeDocumentEventListener( mxGlobalEventListener );
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void XMLFilterTestDialog::test( const filter_info_impl& rFilterInfo )
+{
+ m_xFilterInfo.reset(new filter_info_impl( rFilterInfo ));
+
+ m_sImportRecentFile.clear();
+
+ initDialog();
+
+ m_xDialog->run();
+}
+
+static OUString getFileNameFromURL( std::u16string_view rURL )
+{
+ INetURLObject aURL( rURL );
+ OUString aName( aURL.getName(INetURLObject::LAST_SEGMENT, true, INetURLObject::DecodeMechanism::WithCharset) );
+ return aName;
+}
+
+void XMLFilterTestDialog::updateCurrentDocumentButtonState( Reference< XComponent > const * pRef /* = NULL */ )
+{
+ if( pRef && pRef->is() )
+ {
+ if( checkComponent( *pRef, m_xFilterInfo->maDocumentService ) )
+ mxLastFocusModel = *pRef;
+ }
+
+ bool bExport = (m_xFilterInfo->maFlags & 2) == 2;
+ Reference< XComponent > xCurrentDocument;
+ if( bExport )
+ xCurrentDocument = getFrontMostDocument( m_xFilterInfo->maDocumentService );
+ m_xPBCurrentDocument->set_sensitive( bExport && xCurrentDocument.is() );
+ m_xFTNameOfCurrentFile->set_sensitive( bExport && xCurrentDocument.is() );
+
+ if( !xCurrentDocument.is() )
+ return;
+
+ OUString aTitle;
+ Reference< XDocumentPropertiesSupplier > xDPS( xCurrentDocument, UNO_QUERY );
+ if( xDPS.is() )
+ {
+ Reference< XDocumentProperties > xProps( xDPS->getDocumentProperties() );
+ if( xProps.is() )
+ {
+ aTitle = xProps->getTitle();
+ }
+ }
+
+ if( aTitle.isEmpty() )
+ {
+ Reference< XStorable > xStorable( xCurrentDocument, UNO_QUERY );
+ if( xStorable.is() )
+ {
+ if( xStorable->hasLocation() )
+ {
+ OUString aURL( xStorable->getLocation() );
+ aTitle = getFileNameFromURL( aURL );
+ }
+ }
+ }
+
+ m_xFTNameOfCurrentFile->set_label( aTitle );
+}
+
+void XMLFilterTestDialog::initDialog()
+{
+ DBG_ASSERT( m_xFilterInfo, "i need a filter I can test!" );
+ if( nullptr == m_xFilterInfo )
+ return;
+
+ OUString aTitle( m_sDialogTitle );
+ aTitle = aTitle.replaceFirst( "%s", m_xFilterInfo->maFilterName );
+ m_xDialog->set_title( aTitle );
+
+ bool bImport = (m_xFilterInfo->maFlags & 1) == 1;
+ bool bExport = (m_xFilterInfo->maFlags & 2) == 2;
+
+ updateCurrentDocumentButtonState();
+
+ m_xExport->set_sensitive(bExport);
+ m_xFTExportXSLTFile->set_label( getFileNameFromURL( m_xFilterInfo->maExportXSLT ) );
+
+
+ m_xImport->set_sensitive(bImport);
+ m_xFTImportTemplate->set_sensitive(bImport && !m_xFilterInfo->maImportTemplate.isEmpty());
+ m_xFTImportTemplateFile->set_sensitive(bImport && !m_xFilterInfo->maImportTemplate.isEmpty());
+ m_xPBRecentFile->set_sensitive(bImport && !m_sImportRecentFile.isEmpty());
+ m_xFTNameOfRecentFile->set_sensitive(bImport && !m_sImportRecentFile.isEmpty());
+
+ m_xFTImportXSLTFile->set_label( getFileNameFromURL( m_xFilterInfo->maImportXSLT ) );
+ m_xFTImportTemplateFile->set_label( getFileNameFromURL( m_xFilterInfo->maImportTemplate ) );
+ m_xFTNameOfRecentFile->set_label( getFileNameFromURL( m_sImportRecentFile ) );
+}
+
+void XMLFilterTestDialog::onExportBrowse()
+{
+ try
+ {
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_xDialog.get());
+
+ Reference< XNameAccess > xFilterContainer( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.FilterFactory", mxContext ), UNO_QUERY );
+ Reference< XNameAccess > xTypeDetection( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.document.TypeDetection", mxContext ), UNO_QUERY );
+ if( xFilterContainer.is() && xTypeDetection.is() )
+ {
+ const Sequence< OUString > aFilterNames( xFilterContainer->getElementNames() );
+
+ for( OUString const & filterName : aFilterNames )
+ {
+ Sequence< PropertyValue > aValues;
+
+ Any aAny( xFilterContainer->getByName( filterName ) );
+ if( !(aAny >>= aValues) )
+ continue;
+
+ OUString aInterfaceName;
+ OUString aType, aService;
+ sal_Int32 nFlags( 0 );
+
+ int nFound = 0;
+
+ for( const PropertyValue& rValue : std::as_const(aValues) )
+ {
+ if ( rValue.Name == "Type" )
+ {
+ rValue.Value >>= aType;
+ nFound |= 1;
+ }
+ else if ( rValue.Name == "DocumentService" )
+ {
+ rValue.Value >>= aService;
+ nFound |= 2;
+ }
+ else if ( rValue.Name == "Flags" )
+ {
+ rValue.Value >>= nFlags;
+ nFound |= 4;
+ }
+ else if ( rValue.Name == "UIName" )
+ {
+ rValue.Value >>= aInterfaceName;
+ nFound |= 8;
+ }
+
+ if (nFound == 15)
+ break;
+ }
+
+ if( (nFound == 15) && (!aType.isEmpty() && aService == m_xFilterInfo->maDocumentService) )
+ {
+ // see if this filter is not suppressed in dialog
+ if( (nFlags & 0x1000) == 0 )
+ {
+ aAny = xTypeDetection->getByName( aType );
+ Sequence< PropertyValue > aValues2;
+
+ if( aAny >>= aValues2 )
+ {
+ OUString aExtension;
+ for( const PropertyValue& rProp : std::as_const(aValues2) )
+ {
+ if ( rProp.Name == "Extensions" )
+ {
+ Sequence< OUString > aExtensions;
+ if( rProp.Value >>= aExtensions )
+ {
+ const sal_Int32 nCount( aExtensions.getLength() );
+ OUString* pExtensions = aExtensions.getArray();
+ sal_Int32 n;
+ for( n = 0; n < nCount; n++ )
+ {
+ if( n > 0 )
+ aExtension += ";";
+ aExtension += "*." + *pExtensions++;
+ }
+ }
+ }
+ }
+
+ OUString aFilterName( aInterfaceName + " (" + aExtension + ")" );
+
+ aDlg.AddFilter( aFilterName, aExtension );
+
+ if( (nFlags & 0x100) == 0x100 )
+ aDlg.SetCurrentFilter( aFilterName );
+ }
+ }
+ }
+
+ }
+ }
+
+ aDlg.SetDisplayDirectory( m_sExportRecentFile );
+
+ if ( aDlg.Execute() == ERRCODE_NONE )
+ {
+ m_sExportRecentFile = aDlg.GetPath();
+
+ Reference< XDesktop2 > xLoader = Desktop::create( mxContext );
+ Reference< XInteractionHandler2 > xInter = InteractionHandler::createWithParent(mxContext, nullptr);
+ Sequence< PropertyValue > aArguments{ comphelper::makePropertyValue("InteractionHandler",
+ xInter) };
+ Reference< XComponent > xComp( xLoader->loadComponentFromURL( m_sExportRecentFile, "_default", 0, aArguments ) );
+ if( xComp.is() )
+ {
+ doExport( xComp );
+ }
+ }
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ initDialog();
+}
+
+void XMLFilterTestDialog::onExportCurrentDocument()
+{
+ doExport( getFrontMostDocument( m_xFilterInfo->maDocumentService ) );
+}
+
+void XMLFilterTestDialog::doExport( const Reference< XComponent >& xComp )
+{
+ try
+ {
+ Reference< XStorable > xStorable( xComp, UNO_QUERY );
+ if( xStorable.is() )
+ {
+ OUString const ext(".xml");
+ utl::TempFile aTempFile(u"", true, &ext);
+ OUString aTempFileURL( aTempFile.GetURL() );
+
+ const application_info_impl* pAppInfo = getApplicationInfo( m_xFilterInfo->maExportService );
+ if( pAppInfo )
+ {
+ File aOutputFile( aTempFileURL );
+ (void)aOutputFile.open( osl_File_OpenFlag_Write );
+
+ // create xslt exporter
+ Reference< XOutputStream > xIS( new comphelper::OSLOutputStreamWrapper( aOutputFile ) );
+ int bUseDocType = m_xFilterInfo->maDocType.isEmpty() ? 0 : 1;
+ Sequence< PropertyValue > aSourceData( 2 + bUseDocType );
+ auto pSourceData = aSourceData.getArray();
+ int i = 0;
+
+
+ pSourceData[i ].Name = "OutputStream";
+ pSourceData[i++].Value <<= xIS;
+
+ pSourceData[i].Name = "Indent";
+ pSourceData[i++].Value <<= true;
+
+ if( bUseDocType )
+ {
+ pSourceData[i ].Name = "DocType_Public";
+ pSourceData[i++].Value <<= m_xFilterInfo->maDocType;
+ }
+
+ Reference< XExportFilter > xExporter( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.documentconversion.XSLTFilter", mxContext ), UNO_QUERY );
+ Reference< XDocumentHandler > xHandler( xExporter, UNO_QUERY );
+ if( xHandler.is() )
+ {
+ Sequence< OUString > aFilterUserData( m_xFilterInfo->getFilterUserData() );
+ xExporter->exporter( aSourceData, aFilterUserData );
+
+ Reference< XMultiServiceFactory > xDocFac( xComp, UNO_QUERY );
+
+ Reference< XEmbeddedObjectResolver > xObjectResolver;
+ Reference<XGraphicStorageHandler> xGraphicStorageHandler;
+
+ if( xDocFac.is() )
+ {
+ try
+ {
+ xGraphicStorageHandler.set(xDocFac->createInstance("com.sun.star.document.ExportGraphicStorageHandler"), UNO_QUERY);
+ xObjectResolver.set( xDocFac->createInstance("com.sun.star.document.ExportEmbeddedObjectResolver"), UNO_QUERY );
+ }
+ catch( const Exception& )
+ {
+ }
+ }
+
+ Sequence< Any > aArgs( 1 + ( xGraphicStorageHandler.is() ? 1 : 0 ) + ( xObjectResolver.is() ? 1 : 0 ) );
+ Any* pArgs = aArgs.getArray();
+ if (xGraphicStorageHandler.is())
+ *pArgs++ <<= xGraphicStorageHandler;
+
+ if (xObjectResolver.is())
+ *pArgs++ <<= xObjectResolver;
+
+ // *pArgs++ <<= xInfoSet;
+ *pArgs <<= xHandler;
+
+ Reference< XFilter > xFilter( mxContext->getServiceManager()->createInstanceWithArgumentsAndContext( pAppInfo->maXMLExporter, aArgs, mxContext ), UNO_QUERY );
+ if( xFilter.is() )
+ {
+ Reference< XExporter > xExporter2( xFilter, UNO_QUERY );
+ if( xExporter2.is() )
+ {
+ xExporter2->setSourceDocument( xComp );
+
+ Sequence< PropertyValue > aDescriptor{comphelper::makePropertyValue(
+ "FileName", aTempFileURL) };
+
+ if( xFilter->filter( aDescriptor ) )
+ displayXMLFile( aTempFileURL );
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+void XMLFilterTestDialog::displayXMLFile( const OUString& rURL )
+{
+ Reference< XSystemShellExecute > xSystemShellExecute(
+ SystemShellExecute::create(comphelper::getProcessComponentContext()) );
+ xSystemShellExecute->execute( rURL, OUString(), SystemShellExecuteFlags::URIS_ONLY );
+}
+
+void XMLFilterTestDialog::onImportBrowse()
+{
+ // Open Fileopen-Dialog
+ ::sfx2::FileDialogHelper aDlg(
+ css::ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
+ FileDialogFlags::NONE, m_xDialog.get());
+ OUString aFilterName( m_xFilterInfo->maInterfaceName );
+ OUString aExtensions;
+
+ int nLastIndex = 0;
+ int nCurrentIndex = 0;
+ for( int i = 0; nLastIndex != -1; i++ )
+ {
+ nLastIndex = m_xFilterInfo->maExtension.indexOf( ';', nLastIndex );
+
+ if( i > 0 )
+ aExtensions += ";";
+
+ aExtensions += "*.";
+
+ if( nLastIndex == -1 )
+ {
+
+ aExtensions += m_xFilterInfo->maExtension.subView( nCurrentIndex );
+ }
+ else
+ {
+ aExtensions += m_xFilterInfo->maExtension.subView( nCurrentIndex, nLastIndex - nCurrentIndex );
+ nCurrentIndex = nLastIndex + 1;
+ nLastIndex = nCurrentIndex;
+ }
+ }
+
+ aFilterName += " (" + aExtensions + ")";
+
+ aDlg.AddFilter( aFilterName, aExtensions );
+ aDlg.SetDisplayDirectory( m_sImportRecentFile );
+
+ if ( aDlg.Execute() == ERRCODE_NONE )
+ {
+ m_sImportRecentFile = aDlg.GetPath();
+ import( m_sImportRecentFile );
+ }
+
+ initDialog();
+}
+
+void XMLFilterTestDialog::import( const OUString& rURL )
+{
+ try
+ {
+ Reference< XDesktop2 > xLoader = Desktop::create( mxContext );
+ Reference< XInteractionHandler2 > xInter = InteractionHandler::createWithParent(mxContext, nullptr);
+
+ Sequence< PropertyValue > aArguments{
+ comphelper::makePropertyValue("FilterName", m_xFilterInfo->maFilterName),
+ comphelper::makePropertyValue("InteractionHandler", xInter)
+ };
+
+ xLoader->loadComponentFromURL( rURL, "_default", 0, aArguments );
+
+ if( m_xCBXDisplaySource->get_active() )
+ {
+ OUString const ext(".xml");
+ TempFile aTempFile(u"", true, &ext);
+ OUString aTempFileURL( aTempFile.GetURL() );
+
+ Reference< XImportFilter > xImporter( mxContext->getServiceManager()->createInstanceWithContext( "com.sun.star.documentconversion.XSLTFilter", mxContext ), UNO_QUERY );
+ if( xImporter.is() )
+ {
+ osl::File aInputFile( rURL );
+ (void)aInputFile.open( osl_File_OpenFlag_Read );
+
+ Reference< XInputStream > xIS( new comphelper::OSLInputStreamWrapper( aInputFile ) );
+
+ Sequence< PropertyValue > aSourceData{
+ comphelper::makePropertyValue("InputStream", xIS),
+ comphelper::makePropertyValue("FileName", rURL),
+ comphelper::makePropertyValue("Indent", true)
+ };
+
+ Reference< XWriter > xWriter = Writer::create( mxContext );
+
+ File aOutputFile( aTempFileURL );
+ (void)aOutputFile.open( osl_File_OpenFlag_Write );
+
+ Reference< XOutputStream > xOS( new OSLOutputStreamWrapper( aOutputFile ) );
+ xWriter->setOutputStream( xOS );
+
+ Sequence< OUString > aFilterUserData( m_xFilterInfo->getFilterUserData() );
+ xImporter->importer( aSourceData, xWriter, aFilterUserData );
+ }
+
+ displayXMLFile( aTempFileURL );
+ }
+ }
+ catch(const Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+}
+
+IMPL_LINK(XMLFilterTestDialog, ClickHdl_Impl, weld::Button&, rButton, void )
+{
+ if (m_xPBExportBrowse.get() == &rButton)
+ {
+ onExportBrowse();
+ }
+ else if (m_xPBCurrentDocument.get() == &rButton)
+ {
+ onExportCurrentDocument();
+ }
+ else if (m_xPBImportBrowse.get() == &rButton)
+ {
+ onImportBrowse();
+ }
+ else if (m_xPBRecentFile.get() == &rButton)
+ {
+ import( m_sImportRecentFile );
+ }
+ else if (m_xPBClose.get() == &rButton)
+ {
+ m_xDialog->response(RET_CLOSE);
+ }
+}
+
+/** returns the front most open component that supports the given service */
+Reference< XComponent > XMLFilterTestDialog::getFrontMostDocument( const OUString& rServiceName )
+{
+ Reference< XComponent > xRet;
+
+ try
+ {
+ Reference< XDesktop2 > xDesktop = Desktop::create( mxContext );
+ Reference< XComponent > xTest( mxLastFocusModel );
+ if( checkComponent( xTest, rServiceName ) )
+ {
+ xRet = xTest;
+ }
+ else
+ {
+ xTest = xDesktop->getCurrentComponent();
+
+ if( checkComponent( xTest, rServiceName ) )
+ {
+ xRet = xTest;
+ }
+ else
+ {
+ Reference< XEnumerationAccess > xAccess( xDesktop->getComponents() );
+ if( xAccess.is() )
+ {
+ Reference< XEnumeration > xEnum( xAccess->createEnumeration() );
+ if( xEnum.is() )
+ {
+ while( xEnum->hasMoreElements() )
+ {
+ if( (xEnum->nextElement() >>= xTest) && xTest.is() )
+ {
+ if( checkComponent( xTest, rServiceName ) )
+ {
+ xRet = xTest;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ catch( const Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ }
+
+ return xRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xmlfiltertestdialog.hxx b/filter/source/xsltdialog/xmlfiltertestdialog.hxx
new file mode 100644
index 000000000..bce1e19e1
--- /dev/null
+++ b/filter/source/xsltdialog/xmlfiltertestdialog.hxx
@@ -0,0 +1,81 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#pragma once
+
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/document/XDocumentEventBroadcaster.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <cppuhelper/weakref.hxx>
+#include <vcl/weld.hxx>
+
+class filter_info_impl;
+
+class XMLFilterTestDialog : public weld::GenericDialogController
+{
+public:
+ XMLFilterTestDialog(weld::Window* pParent,
+ const css::uno::Reference< css::uno::XComponentContext >& rxContext);
+ virtual ~XMLFilterTestDialog() override;
+
+ void test( const filter_info_impl& rFilterInfo );
+
+ void updateCurrentDocumentButtonState( css::uno::Reference< css::lang::XComponent > const * pRef = nullptr );
+
+private:
+ DECL_LINK(ClickHdl_Impl, weld::Button&, void);
+
+ void onExportBrowse();
+ void onExportCurrentDocument();
+ void onImportBrowse();
+ void initDialog();
+
+ css::uno::Reference< css::lang::XComponent > getFrontMostDocument( const OUString& rServiceName );
+ void import( const OUString& rURL );
+ static void displayXMLFile( const OUString& rURL );
+ void doExport( const css::uno::Reference< css::lang::XComponent >& xComp );
+
+private:
+ css::uno::Reference< css::uno::XComponentContext > mxContext;
+ css::uno::Reference< css::document::XDocumentEventBroadcaster > mxGlobalBroadcaster;
+ css::uno::Reference< css::document::XDocumentEventListener > mxGlobalEventListener;
+ css::uno::WeakReference< css::lang::XComponent > mxLastFocusModel;
+
+ OUString m_sImportRecentFile;
+ OUString m_sExportRecentFile;
+ std::unique_ptr<filter_info_impl> m_xFilterInfo;
+ OUString m_sDialogTitle;
+
+ std::unique_ptr<weld::Widget> m_xExport;
+ std::unique_ptr<weld::Label> m_xFTExportXSLTFile;
+ std::unique_ptr<weld::Button> m_xPBExportBrowse;
+ std::unique_ptr<weld::Button> m_xPBCurrentDocument;
+ std::unique_ptr<weld::Label> m_xFTNameOfCurrentFile;
+ std::unique_ptr<weld::Widget> m_xImport;
+ std::unique_ptr<weld::Label> m_xFTImportXSLTFile;
+ std::unique_ptr<weld::Label> m_xFTImportTemplate;
+ std::unique_ptr<weld::Label> m_xFTImportTemplateFile;
+ std::unique_ptr<weld::CheckButton> m_xCBXDisplaySource;
+ std::unique_ptr<weld::Button> m_xPBImportBrowse;
+ std::unique_ptr<weld::Button> m_xPBRecentFile;
+ std::unique_ptr<weld::Label> m_xFTNameOfRecentFile;
+ std::unique_ptr<weld::Button> m_xPBClose;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltdialog/xsltdlg.component b/filter/source/xsltdialog/xsltdlg.component
new file mode 100644
index 000000000..6d4a693f3
--- /dev/null
+++ b/filter/source/xsltdialog/xsltdlg.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.ui.XSLTFilterDialog"
+ constructor="filter_XSLTFilterDialog_get_implementation">
+ <service name="com.sun.star.ui.dialogs.XSLTFilterDialog"/>
+ </implementation>
+</component>
diff --git a/filter/source/xsltfilter/LibXSLTTransformer.cxx b/filter/source/xsltfilter/LibXSLTTransformer.cxx
new file mode 100644
index 000000000..1a7c34805
--- /dev/null
+++ b/filter/source/xsltfilter/LibXSLTTransformer.cxx
@@ -0,0 +1,571 @@
+/* -*- 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 <algorithm>
+#include <cstring>
+#include <map>
+#include <optional>
+#include <string_view>
+#include <utility>
+#include <vector>
+#include <libxml/parser.h>
+#include <libxml/xmlIO.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+#include <libxml/xmlstring.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/variables.h>
+#include <libxslt/extensions.h>
+#include <libexslt/exslt.h>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <osl/file.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XStreamListener.hpp>
+
+#include "LibXSLTTransformer.hxx"
+#include "OleHandler.hxx"
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using ::std::pair;
+
+namespace XSLT
+{
+ const char* const LibXSLTTransformer::PARAM_SOURCE_URL = "sourceURL";
+ const char* const LibXSLTTransformer::PARAM_SOURCE_BASE_URL =
+ "sourceBaseURL";
+ const char* const LibXSLTTransformer::PARAM_TARGET_URL = "targetURL";
+ const char* const LibXSLTTransformer::PARAM_TARGET_BASE_URL =
+ "targetBaseURL";
+ const char* const LibXSLTTransformer::PARAM_DOCTYPE_PUBLIC = "publicType";
+
+ const sal_Int32 Reader::OUTPUT_BUFFER_SIZE = 4096;
+
+ const sal_Int32 Reader::INPUT_BUFFER_SIZE = 4096;
+
+ namespace {
+
+ /**
+ * ParserInputBufferCallback forwards IO call-backs to libxml stream IO.
+ */
+ struct ParserInputBufferCallback
+ {
+ static int
+ on_read(void * context, char * buffer, int len)
+ {
+ Reader * tmp = static_cast<Reader*> (context);
+ return tmp->read(buffer, len);
+ }
+ static int
+ on_close(void * )
+ {
+ return 0;
+ }
+ };
+ /**
+ * ParserOutputBufferCallback forwards IO call-backs to libxml stream IO.
+ */
+ struct ParserOutputBufferCallback
+ {
+ static int
+ on_write(void * context, const char * buffer, int len)
+ {
+ Reader * tmp = static_cast<Reader*> (context);
+ return tmp->write(buffer, len);
+ }
+ static int
+ on_close(void * context)
+ {
+ Reader * tmp = static_cast<Reader*> (context);
+ tmp->closeOutput();
+ return 0;
+ }
+ };
+ /**
+ * ExtFuncOleCB forwards XPath extension function calls registered with libxslt to the OleHandler instance that actually
+ * provides the implementation for those functions.
+ *
+ * The OLE extension module currently supplies two functions
+ * insertByName: registers an OLE object to be later inserted into the output tree.
+ * getByName: reads a previously registered OLE object and returns a base64 encoded string representation.
+ */
+ struct ExtFuncOleCB
+ {
+ static void *
+ init(xsltTransformContextPtr, const xmlChar*)
+ {
+ return nullptr;
+ }
+ static void
+ insertByName(xmlXPathParserContextPtr ctxt, int nargs)
+ {
+ xsltTransformContextPtr tctxt;
+ void *data;
+ if (nargs != 2) {
+ xsltGenericError(xsltGenericErrorContext,
+ "insertByName: requires exactly 2 arguments\n");
+ return;
+ }
+ tctxt = xsltXPathGetTransformContext(ctxt);
+ if (tctxt == nullptr) {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltExtFunctionTest: failed to get the transformation context\n");
+ return;
+ }
+ // XXX: someone with better knowledge of libxslt might come up with a better
+ // idea to pass the OleHandler than by attaching it to tctxt->_private. See also
+ // below.
+ data = tctxt->_private;
+ if (data == nullptr) {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltExtFunctionTest: failed to get module data\n");
+ return;
+ }
+ OleHandler * oh = static_cast<OleHandler*> (data);
+
+ xmlXPathObjectPtr value = valuePop(ctxt);
+ value = ensureStringValue(value, ctxt);
+ xmlXPathObjectPtr streamName = valuePop(ctxt);
+ streamName = ensureStringValue(streamName, ctxt);
+
+ oh->insertByName(OStringToOUString(reinterpret_cast<char*>(streamName->stringval), RTL_TEXTENCODING_UTF8),
+ std::string_view(reinterpret_cast<char*>(value->stringval)));
+ valuePush(ctxt, xmlXPathNewCString(""));
+ }
+
+ static xmlXPathObjectPtr ensureStringValue(xmlXPathObjectPtr obj, const xmlXPathParserContextPtr ctxt)
+ {
+ if (obj->type != XPATH_STRING) {
+ valuePush(ctxt, obj);
+ xmlXPathStringFunction(ctxt, 1);
+ obj = valuePop(ctxt);
+ }
+ return obj;
+ }
+
+ static void getByName(xmlXPathParserContextPtr ctxt, int nargs)
+ {
+ xsltTransformContextPtr tctxt;
+ void *data;
+ if (nargs != 1) {
+ xsltGenericError(xsltGenericErrorContext,
+ "getByName: requires exactly 1 argument\n");
+ return;
+ }
+
+ tctxt = xsltXPathGetTransformContext(ctxt);
+ if (tctxt == nullptr) {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltExtFunctionTest: failed to get the transformation context\n");
+ return;
+ }
+ // XXX: someone with better knowledge of libxslt might come up with a better
+ // idea to pass the OleHandler than by attaching it to tctxt->_private
+ data = tctxt->_private;
+ if (data == nullptr) {
+ xsltGenericError(xsltGenericErrorContext,
+ "xsltExtFunctionTest: failed to get module data\n");
+ return;
+ }
+ OleHandler * oh = static_cast<OleHandler*> (data);
+ xmlXPathObjectPtr streamName = valuePop(ctxt);
+ streamName = ensureStringValue(streamName, ctxt);
+ const OString content = oh->getByName(OStringToOUString(reinterpret_cast<char*>(streamName->stringval), RTL_TEXTENCODING_UTF8));
+ valuePush(ctxt, xmlXPathNewCString(content.getStr()));
+ xmlXPathFreeObject(streamName);
+ }
+ };
+
+ }
+
+ Reader::Reader(LibXSLTTransformer* transformer) :
+ Thread("LibXSLTTransformer"), m_transformer(transformer),
+ m_readBuf(INPUT_BUFFER_SIZE), m_writeBuf(OUTPUT_BUFFER_SIZE),
+ m_tcontext(nullptr)
+ {
+ LIBXML_TEST_VERSION;
+ }
+ ;
+
+ int
+ Reader::read(char * buffer, int len)
+ {
+ // const char *ptr = (const char *) context;
+ if (buffer == nullptr || len < 0)
+ return -1;
+ sal_Int32 n;
+ css::uno::Reference<XInputStream> xis = m_transformer->getInputStream();
+ n = xis->readBytes(m_readBuf, len);
+ if (n > 0)
+ {
+ memcpy(buffer, m_readBuf.getArray(), n);
+ }
+ return n;
+ }
+
+ int
+ Reader::write(const char * buffer, int len)
+ {
+ if (buffer == nullptr || len < 0)
+ return -1;
+ if (len > 0)
+ {
+ css::uno::Reference<XOutputStream> xos = m_transformer->getOutputStream();
+ sal_Int32 writeLen = len;
+ sal_Int32 bufLen = ::std::min(writeLen, OUTPUT_BUFFER_SIZE);
+ const sal_uInt8* memPtr =
+ reinterpret_cast<const sal_uInt8*> (buffer);
+ while (writeLen > 0)
+ {
+ sal_Int32 n = ::std::min(writeLen, bufLen);
+ m_writeBuf.realloc(n);
+ memcpy(m_writeBuf.getArray(), memPtr,
+ static_cast<size_t> (n));
+ xos->writeBytes(m_writeBuf);
+ memPtr += n;
+ writeLen -= n;
+ }
+ }
+ return len;
+ }
+
+ void
+ Reader::closeOutput()
+ {
+ css::uno::Reference<XOutputStream> xos = m_transformer->getOutputStream();
+ if (xos.is())
+ {
+ xos->flush();
+ xos->closeOutput();
+ }
+ m_transformer->done();
+ }
+
+ void
+ Reader::execute()
+ {
+ OSL_ASSERT(m_transformer != nullptr);
+ OSL_ASSERT(m_transformer->getInputStream().is());
+ OSL_ASSERT(m_transformer->getOutputStream().is());
+ OSL_ASSERT(!m_transformer->getStyleSheetURL().isEmpty() || !m_transformer->getStyleSheetText().isEmpty());
+ ::std::map<const char*, OString> pmap = m_transformer->getParameters();
+ ::std::vector< const char* > params( pmap.size() * 2 + 1 ); // build parameters
+ int paramIndex = 0;
+ for (auto const& elem : pmap)
+ {
+ params[paramIndex++] = elem.first;
+ params[paramIndex++] = elem.second.getStr();
+ }
+ params[paramIndex] = nullptr;
+ xmlDocPtr doc = xmlReadIO(&ParserInputBufferCallback::on_read,
+ &ParserInputBufferCallback::on_close,
+ static_cast<void*> (this), nullptr, nullptr, 0);
+ xsltStylesheetPtr styleSheet = nullptr;
+ if (m_transformer->getStyleSheetURL().getLength())
+ styleSheet = xsltParseStylesheetFile(
+ reinterpret_cast<const xmlChar *>(m_transformer->getStyleSheetURL().getStr()));
+ else if (m_transformer->getStyleSheetText().getLength())
+ {
+ xmlDocPtr styleSheetDoc = xmlReadMemory(
+ m_transformer->getStyleSheetText().getStr(),
+ m_transformer->getStyleSheetText().getLength(),
+ "noname.xml", nullptr, 0);
+
+ styleSheet = xsltParseStylesheetDoc(styleSheetDoc);
+ }
+
+ if (!styleSheet)
+ {
+ m_transformer->error("No stylesheet was created");
+ }
+
+ xmlDocPtr result = nullptr;
+ exsltRegisterAll();
+ registerExtensionModule();
+#ifdef DEBUG_FILTER_LIBXSLTTRANSFORMER
+ xsltSetGenericDebugFunc(stderr, NULL);
+ xsltDebugDumpExtensions(NULL);
+#endif
+ std::optional<OleHandler> oh(std::in_place, m_transformer->getComponentContext());
+ if (styleSheet)
+ {
+ xsltTransformContextPtr tcontext = xsltNewTransformContext(
+ styleSheet, doc);
+ {
+ std::scoped_lock<std::mutex> g(m_mutex);
+ m_tcontext = tcontext;
+ }
+ oh->registercontext(m_tcontext);
+ xsltQuoteUserParams(m_tcontext, params.data());
+ result = xsltApplyStylesheetUser(styleSheet, doc, nullptr, nullptr, nullptr,
+ m_tcontext);
+ }
+
+ if (result)
+ {
+ xmlCharEncodingHandlerPtr encoder = xmlGetCharEncodingHandler(
+ XML_CHAR_ENCODING_UTF8);
+ xmlOutputBufferPtr outBuf = xmlAllocOutputBuffer(encoder);
+ outBuf->context = static_cast<void *> (this);
+ outBuf->writecallback = &ParserOutputBufferCallback::on_write;
+ outBuf->closecallback = &ParserOutputBufferCallback::on_close;
+ xsltSaveResultTo(outBuf, result, styleSheet);
+ (void)xmlOutputBufferClose(outBuf);
+ }
+ else
+ {
+ xmlErrorPtr lastErr = xmlGetLastError();
+ OUString msg;
+ if (lastErr)
+ msg = OStringToOUString(lastErr->message, RTL_TEXTENCODING_UTF8);
+ else
+ msg = "Unknown XSLT transformation error";
+
+ m_transformer->error(msg);
+ }
+ oh.reset();
+ xsltFreeStylesheet(styleSheet);
+ xsltTransformContextPtr tcontext = nullptr;
+ {
+ std::scoped_lock<std::mutex> g(m_mutex);
+ std::swap(m_tcontext, tcontext);
+ }
+ xsltFreeTransformContext(tcontext);
+ xmlFreeDoc(doc);
+ xmlFreeDoc(result);
+ }
+
+ void
+ Reader::registerExtensionModule()
+ {
+ const xmlChar* oleModuleURI = reinterpret_cast<const xmlChar *>(EXT_MODULE_OLE_URI);
+ xsltRegisterExtModule(oleModuleURI, &ExtFuncOleCB::init, nullptr);
+ xsltRegisterExtModuleFunction(
+ reinterpret_cast<const xmlChar*>("insertByName"),
+ oleModuleURI,
+ &ExtFuncOleCB::insertByName);
+ xsltRegisterExtModuleFunction(
+ reinterpret_cast<const xmlChar*>("getByName"),
+ oleModuleURI,
+ &ExtFuncOleCB::getByName);
+
+ }
+
+ void Reader::forceStateStopped()
+ {
+ std::scoped_lock<std::mutex> g(m_mutex);
+ if (!m_tcontext)
+ return;
+ //tdf#100057 If we force a cancel, libxslt will of course just keep on going unless something
+ //tells it to stop. Here we force the stopped state so that libxslt will stop processing
+ //and so Reader::execute will complete and we can join cleanly
+ m_tcontext->state = XSLT_STATE_STOPPED;
+ }
+
+ Reader::~Reader()
+ {
+ }
+
+ LibXSLTTransformer::LibXSLTTransformer(
+ css::uno::Reference<XComponentContext> xContext) :
+ m_xContext(std::move(xContext))
+ {
+ }
+
+ // XServiceInfo
+ sal_Bool LibXSLTTransformer::supportsService(const OUString& sServiceName)
+ {
+ return cppu::supportsService(this, sServiceName);
+ }
+ OUString LibXSLTTransformer::getImplementationName()
+ {
+ return "com.sun.star.comp.documentconversion.XSLTFilter";
+ }
+ css::uno::Sequence< OUString > LibXSLTTransformer::getSupportedServiceNames()
+ {
+ return { "com.sun.star.documentconversion.XSLTFilter" };
+ }
+
+ void
+ LibXSLTTransformer::setInputStream(
+ const css::uno::Reference<XInputStream>& inputStream)
+ {
+ m_rInputStream = inputStream;
+ }
+
+ css::uno::Reference<XInputStream>
+ LibXSLTTransformer::getInputStream()
+ {
+ return m_rInputStream;
+ }
+
+ void
+ LibXSLTTransformer::setOutputStream(
+ const css::uno::Reference<XOutputStream>& outputStream)
+ {
+ m_rOutputStream = outputStream;
+ }
+
+ css::uno::Reference<XOutputStream>
+ LibXSLTTransformer::getOutputStream()
+ {
+ return m_rOutputStream;
+ }
+
+ void
+ LibXSLTTransformer::addListener(const css::uno::Reference<XStreamListener>& listener)
+ {
+ m_listeners.push_front(listener);
+ }
+
+ void
+ LibXSLTTransformer::removeListener(
+ const css::uno::Reference<XStreamListener>& listener)
+ {
+ m_listeners.erase( std::remove(m_listeners.begin(), m_listeners.end(), listener ), m_listeners.end() );
+ }
+
+ void
+ LibXSLTTransformer::start()
+ {
+ for (const css::uno::Reference<XStreamListener>& xl : m_listeners)
+ {
+ xl->started();
+ }
+ OSL_ENSURE(!m_Reader.is(), "Somebody forgot to call terminate *and* holds a reference to this LibXSLTTransformer instance");
+ m_Reader = new Reader(this);
+ m_Reader->launch();
+ }
+
+ void
+ LibXSLTTransformer::error(const OUString& msg)
+ {
+ Any arg;
+ arg <<= Exception(msg, *this);
+ for (const css::uno::Reference<XStreamListener>& xl : m_listeners)
+ {
+ if (xl.is())
+ {
+ xl->error(arg);
+ }
+ }
+ }
+
+ void
+ LibXSLTTransformer::done()
+ {
+ for (const css::uno::Reference<XStreamListener>& xl : m_listeners)
+ {
+ if (xl.is())
+ {
+ xl->closed();
+ }
+ }
+ }
+
+ void
+ LibXSLTTransformer::terminate()
+ {
+ if (m_Reader.is())
+ {
+ m_Reader->terminate();
+ m_Reader->forceStateStopped();
+ m_Reader->join();
+ }
+ m_Reader.clear();
+ m_parameters.clear();
+ }
+
+ void
+ LibXSLTTransformer::initialize(const Sequence<Any>& args)
+ {
+ Sequence<Any> params;
+ if (!(args[0] >>= params))
+ { // backward compatibility for old clients using createInstance
+ params = args;
+ }
+ xmlSubstituteEntitiesDefault(0);
+ m_parameters.clear();
+ for (const Any& p : std::as_const(params))
+ {
+ NamedValue nv;
+ p >>= nv;
+ OString nameUTF8 = OUStringToOString(nv.Name,
+ RTL_TEXTENCODING_UTF8);
+ OUString value;
+ OString valueUTF8;
+ if (nv.Value >>= value)
+ {
+ valueUTF8 = OUStringToOString(value,
+ RTL_TEXTENCODING_UTF8);
+ }
+ else
+ {
+ // ignore non-string parameters
+ continue;
+ }
+ if (nameUTF8 == "StylesheetURL")
+ {
+ m_styleSheetURL = valueUTF8;
+ }
+ if (nameUTF8 == "StylesheetText")
+ {
+ m_styleSheetText = valueUTF8;
+ }
+ else if (nameUTF8 == "SourceURL")
+ {
+ m_parameters.insert(pair<const char*, OString> (
+ PARAM_SOURCE_URL, valueUTF8));
+ }
+ else if (nameUTF8 == "SourceBaseURL")
+ {
+ m_parameters.insert(pair<const char*, OString> (
+ PARAM_SOURCE_BASE_URL, valueUTF8));
+ }
+ else if (nameUTF8 == "TargetURL")
+ {
+ m_parameters.insert(pair<const char*, OString> (
+ PARAM_TARGET_URL, valueUTF8));
+ }
+ else if (nameUTF8 == "TargetBaseURL")
+ {
+ m_parameters.insert(pair<const char*, OString> (
+ PARAM_TARGET_BASE_URL, valueUTF8));
+ }
+ else if (nameUTF8 == "DoctypePublic")
+ {
+ m_parameters.insert(pair<const char*, OString> (
+ PARAM_DOCTYPE_PUBLIC, valueUTF8));
+ }
+ }
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_LibXSLTTransformer_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XSLT::LibXSLTTransformer(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+
diff --git a/filter/source/xsltfilter/LibXSLTTransformer.hxx b/filter/source/xsltfilter/LibXSLTTransformer.hxx
new file mode 100644
index 000000000..8696bda6a
--- /dev/null
+++ b/filter/source/xsltfilter/LibXSLTTransformer.hxx
@@ -0,0 +1,185 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <deque>
+#include <map>
+#include <mutex>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlIO.h>
+#include <libxslt/transform.h>
+#include <libxml/xpathInternals.h>
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+
+#include <rtl/ref.hxx>
+
+#include <salhelper/thread.hxx>
+
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XStreamListener.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/xml/xslt/XXSLTTransformer.hpp>
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+
+using ::std::map;
+
+#define EXT_MODULE_OLE_URI "http://libreoffice.org/2011/xslt/ole"
+
+namespace XSLT
+{
+
+ class LibXSLTTransformer;
+
+ /*
+ * Reader provides a worker thread to perform the actual transformation.
+ * It pipes the streams provided by a LibXSLTTransformer
+ * instance through libxslt.
+ */
+ class Reader : public salhelper::Thread
+ {
+ public:
+ Reader(LibXSLTTransformer* transformer);
+ int read(char * buffer, int len);
+ int write(const char * buffer, int len);
+ void forceStateStopped();
+ void closeOutput();
+
+ private:
+ virtual ~Reader() override;
+
+ static const sal_Int32 OUTPUT_BUFFER_SIZE;
+ static const sal_Int32 INPUT_BUFFER_SIZE;
+ rtl::Reference<LibXSLTTransformer> m_transformer;
+ Sequence<sal_Int8> m_readBuf;
+ Sequence<sal_Int8> m_writeBuf;
+
+ std::mutex m_mutex;
+ xsltTransformContextPtr m_tcontext;
+
+ virtual void execute() override;
+ static void registerExtensionModule();
+ };
+
+ /*
+ * LibXSLTTransformer provides a transforming pipe service to XSLTFilter.
+ *
+ * It implements XActiveDataSource, XActiveDataSink and XActiveDataControl
+ * to consume data. It also notifies upstream of important events such as
+ * begin and end of the transformation and of any errors that occur during
+ * transformation.
+ *
+ * TODO: Error reporting leaves room for improvement, currently.
+ *
+ * The actual transformation is done by a worker thread.
+ *
+ * See Reader below.
+ */
+ class LibXSLTTransformer : public WeakImplHelper<css::xml::xslt::XXSLTTransformer, css::lang::XServiceInfo>
+ {
+ private:
+ static const char* const PARAM_SOURCE_URL;
+ static const char* const PARAM_SOURCE_BASE_URL;
+ static const char* const PARAM_TARGET_URL;
+ static const char* const PARAM_TARGET_BASE_URL;
+ static const char* const PARAM_DOCTYPE_PUBLIC;
+
+ // the UNO ServiceFactory
+ css::uno::Reference<css::uno::XComponentContext> m_xContext;
+
+ css::uno::Reference<XInputStream> m_rInputStream;
+
+ css::uno::Reference<XOutputStream> m_rOutputStream;
+
+ typedef ::std::deque<css::uno::Reference<XStreamListener> > ListenerList;
+
+ ListenerList m_listeners;
+
+ OString m_styleSheetURL;
+ OString m_styleSheetText;
+
+ ::std::map<const char *, OString> m_parameters;
+
+ rtl::Reference<Reader> m_Reader;
+
+ protected:
+ virtual ~LibXSLTTransformer() override {
+ if (m_Reader.is()) {
+ m_Reader->terminate();
+ m_Reader->forceStateStopped();
+ m_Reader->join();
+ }
+ }
+
+ public:
+
+ // ctor...
+ LibXSLTTransformer(css::uno::Reference<css::uno::XComponentContext> x);
+
+ // XServiceInfo
+ virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override;
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XActiveDataSink
+ virtual void SAL_CALL
+ setInputStream(const css::uno::Reference<XInputStream>& inputStream) override;
+ virtual css::uno::Reference<XInputStream> SAL_CALL
+ getInputStream() override;
+ // XActiveDataSource
+ virtual void SAL_CALL
+ setOutputStream(const css::uno::Reference<XOutputStream>& outputStream) override;
+ virtual css::uno::Reference<XOutputStream> SAL_CALL
+ getOutputStream() override;
+ // XActiveDataControl
+ virtual void SAL_CALL
+ addListener(const css::uno::Reference<XStreamListener>& listener) override;
+ virtual void SAL_CALL
+ removeListener(const css::uno::Reference<XStreamListener>& listener) override;
+ virtual void SAL_CALL
+ start() override;
+ virtual void SAL_CALL
+ terminate() override;
+ virtual void SAL_CALL
+ initialize(const Sequence<Any>& params) override;
+
+ void
+ done();
+
+ void
+ error(const OUString& msg);
+
+ const OString&
+ getStyleSheetURL() const { return m_styleSheetURL; }
+
+ const OString& getStyleSheetText() const { return m_styleSheetText; }
+
+ const ::std::map<const char*, OString>&
+ getParameters() const { return m_parameters; }
+
+ const css::uno::Reference<css::uno::XComponentContext>&
+ getComponentContext() const {
+ return m_xContext;
+ }
+
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltfilter/OleHandler.cxx b/filter/source/xsltfilter/OleHandler.cxx
new file mode 100644
index 000000000..bb2089935
--- /dev/null
+++ b/filter/source/xsltfilter/OleHandler.cxx
@@ -0,0 +1,214 @@
+/* -*- 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 <rtl/ustrbuf.hxx>
+
+#include <package/Inflater.hxx>
+#include <package/Deflater.hxx>
+
+#include <cppuhelper/factory.hxx>
+#include <comphelper/base64.hxx>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/io/TempFile.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include "OleHandler.hxx"
+#include <optional>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::embed;
+
+
+namespace XSLT
+{
+ Reference<XStream> OleHandler::createTempFile() {
+ Reference<XStream> tempFile = TempFile::create(m_xContext);
+ OSL_ASSERT(tempFile.is());
+ return tempFile;
+ }
+
+ void OleHandler::ensureCreateRootStorage()
+ {
+ if (m_storage == nullptr || m_rootStream == nullptr)
+ {
+ m_rootStream = createTempFile();
+ Sequence<Any> args{ Any(m_rootStream->getInputStream()) };
+
+ Reference<XNameContainer> cont(
+ Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW)
+ ->createInstanceWithArguments("com.sun.star.embed.OLESimpleStorage", args), UNO_QUERY);
+ m_storage = cont;
+ }
+ }
+
+ void OleHandler::initRootStorageFromBase64(std::string_view content)
+ {
+ Sequence<sal_Int8> oleData;
+ ::comphelper::Base64::decode(oleData, OStringToOUString(
+ content, RTL_TEXTENCODING_UTF8));
+ m_rootStream = createTempFile();
+ Reference<XOutputStream> xOutput = m_rootStream->getOutputStream();
+ xOutput->writeBytes(oleData);
+ xOutput->flush();
+ //Get the input stream and seek to begin
+ Reference<XSeekable> xSeek(m_rootStream->getInputStream(), UNO_QUERY);
+ xSeek->seek(0);
+
+ //create a com.sun.star.embed.OLESimpleStorage from the temp stream
+ Sequence<Any> args{ Any(xSeek) };
+ Reference<XNameContainer> cont(
+ Reference<XMultiServiceFactory>(m_xContext->getServiceManager(), UNO_QUERY_THROW)
+ ->createInstanceWithArguments("com.sun.star.embed.OLESimpleStorage", args), UNO_QUERY);
+ m_storage = cont;
+ }
+
+ OString
+ OleHandler::encodeSubStorage(const OUString& streamName)
+ {
+ if (!m_storage || !m_storage->hasByName(streamName))
+ {
+ return "Not Found:";// + streamName;
+ }
+
+ Reference<XInputStream> subStream(m_storage->getByName(streamName), UNO_QUERY);
+ if (!subStream.is())
+ {
+ return "Not Found:";// + streamName;
+ }
+ //The first four byte are the length of the uncompressed data
+ Sequence<sal_Int8> aLength(4);
+ Reference<XSeekable> xSeek(subStream, UNO_QUERY);
+ xSeek->seek(0);
+ //Get the uncompressed length
+ int readbytes = subStream->readBytes(aLength, 4);
+ if (4 != readbytes)
+ {
+ return "Can not read the length.";
+ }
+ sal_Int32 const oleLength = (static_cast<sal_uInt8>(aLength[0]) << 0U)
+ | (static_cast<sal_uInt8>(aLength[1]) << 8U)
+ | (static_cast<sal_uInt8>(aLength[2]) << 16U)
+ | (static_cast<sal_uInt8>(aLength[3]) << 24U);
+ if (oleLength < 0)
+ {
+ return "invalid oleLength";
+ }
+ Sequence<sal_Int8> content(oleLength);
+ //Read all bytes. The compressed length should be less than the uncompressed length
+ readbytes = subStream->readBytes(content, oleLength);
+ if (oleLength < readbytes)
+ {
+ return "oleLength";// +oleLength + readBytes;
+ }
+
+ // Decompress the bytes
+ std::optional< ::ZipUtils::Inflater> decompresser(std::in_place, false);
+ decompresser->setInput(content);
+ Sequence<sal_Int8> result(oleLength);
+ decompresser->doInflateSegment(result, 0, oleLength);
+ decompresser->end();
+ decompresser.reset();
+ //return the base64 string of the uncompressed data
+ OUStringBuffer buf(oleLength);
+ ::comphelper::Base64::encode(buf, result);
+ return OUStringToOString(buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
+ }
+
+ void
+ OleHandler::insertByName(const OUString& streamName, std::string_view content)
+ {
+ if ( streamName == "oledata.mso" )
+ {
+ initRootStorageFromBase64(content);
+ }
+ else
+ {
+ ensureCreateRootStorage();
+ insertSubStorage(streamName, content);
+ }
+ }
+
+ OString
+ OleHandler::getByName(const OUString& streamName)
+ {
+ if ( streamName == "oledata.mso" )
+ {
+ //get the length and seek to 0
+ Reference<XSeekable> xSeek (m_rootStream, UNO_QUERY);
+ int oleLength = static_cast<int>(xSeek->getLength());
+ xSeek->seek(0);
+ //read all bytes
+ Reference<XInputStream> xInput = m_rootStream->getInputStream();
+ Sequence<sal_Int8> oledata(oleLength);
+ xInput->readBytes(oledata, oleLength);
+ //return the base64 encoded string
+ OUStringBuffer buf(oleLength);
+ ::comphelper::Base64::encode(buf, oledata);
+ return OUStringToOString(buf.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US);
+ }
+ return encodeSubStorage(streamName);
+ }
+
+ void
+ OleHandler::insertSubStorage(const OUString& streamName, std::string_view content)
+ {
+ //decode the base64 string
+ Sequence<sal_Int8> oledata;
+ ::comphelper::Base64::decode(oledata,
+ OStringToOUString(content, RTL_TEXTENCODING_ASCII_US));
+ //create a temp stream to write data to
+ Reference<XStream> subStream = createTempFile();
+ Reference<XInputStream> xInput = subStream->getInputStream();
+ Reference<XOutputStream> xOutput = subStream->getOutputStream();
+ //write the length to the temp stream
+ Sequence<sal_Int8> header{
+ static_cast<sal_Int8>((oledata.getLength() >> 0) & 0xFF),
+ static_cast<sal_Int8>((oledata.getLength() >> 8) & 0xFF),
+ static_cast<sal_Int8>((oledata.getLength() >> 16) & 0xFF),
+ static_cast<sal_Int8>((oledata.getLength() >> 24) & 0xFF)
+ };
+ xOutput->writeBytes(header);
+
+ // Compress the bytes
+ Sequence<sal_Int8> output(oledata.getLength());
+ std::optional< ::ZipUtils::Deflater> compresser(std::in_place, sal_Int32(3), false);
+ compresser->setInputSegment(oledata);
+ compresser->finish();
+ int compressedDataLength = compresser->doDeflateSegment(output, oledata.getLength());
+ compresser.reset();
+ //realloc the data length
+ output.realloc(compressedDataLength);
+
+ //write the compressed data to the temp stream
+ xOutput->writeBytes(output);
+ //seek to 0
+ Reference<XSeekable> xSeek(xInput, UNO_QUERY);
+ xSeek->seek(0);
+
+ //insert the temp stream as a sub stream and use an XTransactedObject to commit it immediately
+ Reference<XTransactedObject> xTransact(m_storage, UNO_QUERY);
+ Any entry;
+ entry <<= xInput;
+ m_storage->insertByName(streamName, entry);
+ xTransact->commit();
+ }
+
+
+}
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+
diff --git a/filter/source/xsltfilter/OleHandler.hxx b/filter/source/xsltfilter/OleHandler.hxx
new file mode 100644
index 000000000..d59429aac
--- /dev/null
+++ b/filter/source/xsltfilter/OleHandler.hxx
@@ -0,0 +1,93 @@
+/* -*- 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/.
+ */
+
+#pragma once
+#include <cstdio>
+#include <cstring>
+#include <map>
+#include <string_view>
+#include <utility>
+#include <vector>
+#include <iostream>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlIO.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+#include <libxslt/variables.h>
+
+#include <cppuhelper/factory.hxx>
+#include <osl/module.h>
+#include <osl/file.hxx>
+#include <osl/process.h>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XInitialization.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XStream.hpp>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::io;
+
+namespace XSLT
+{
+ /*
+ * OleHandler provides implementations for the XSLT extension functions used by the WordML 2003 XSLT filters.
+ *
+ * The extension functions takes base64 encoded string representations of embedded OLE objects provided by the XML filter framework,
+ * stores them into a com.sun.star.embed.OLESimpleStorage and retrieves them later as individual base64 OLE objects.
+ *
+ * The implementation is ported from the former Java based implementation XSLTOleExtrater (sic)
+ *
+ * I believe the whole thing should provide round-trip editing of embedded OLE objects.
+ * I'm not sure if it currently does anything meaningful, because the Java implementation seems to be broken both in OOo and LibO.
+ *
+ */
+ class OleHandler
+ {
+ public:
+ OleHandler(css::uno::Reference<XComponentContext> xContext)
+ : m_xContext(std::move(xContext))
+ , m_tcontext(nullptr)
+ {
+ }
+ ~OleHandler()
+ {
+ if (m_tcontext)
+ m_tcontext->_private = nullptr;
+ }
+ void insertByName(const OUString& streamName, std::string_view content);
+ OString getByName(const OUString& streamName);
+ void registercontext(xsltTransformContextPtr context)
+ {
+ assert(context);
+ m_tcontext = context;
+ m_tcontext->_private = this;
+ }
+
+ private:
+ css::uno::Reference<XComponentContext> m_xContext;
+ css::uno::Reference<XNameContainer> m_storage;
+ css::uno::Reference<XStream> m_rootStream;
+ xsltTransformContextPtr m_tcontext;
+
+ void ensureCreateRootStorage();
+ OString encodeSubStorage(const OUString& streamName);
+ void insertSubStorage(const OUString& streamName, std::string_view content);
+ void initRootStorageFromBase64(std::string_view content);
+ css::uno::Reference<XStream> createTempFile();
+ };
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltfilter/XSLTFilter.cxx b/filter/source/xsltfilter/XSLTFilter.cxx
new file mode 100644
index 000000000..1052a3816
--- /dev/null
+++ b/filter/source/xsltfilter/XSLTFilter.cxx
@@ -0,0 +1,659 @@
+/* -*- 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <cppuhelper/factory.hxx>
+#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <sax/tools/documenthandleradapter.hxx>
+
+#include <osl/diagnose.h>
+#include <osl/time.h>
+#include <osl/conditn.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/diagnose_ex.h>
+#include <sal/log.hxx>
+#include <rtl/ref.hxx>
+
+#include <comphelper/interaction.hxx>
+
+#include <com/sun/star/lang/EventObject.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+
+#include <com/sun/star/uno/Any.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/XDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
+#include <com/sun/star/xml/sax/XFastParser.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/xml/XImportFilter.hpp>
+#include <com/sun/star/xml/XImportFilter2.hpp>
+#include <com/sun/star/xml/XExportFilter.hpp>
+
+#include <com/sun/star/util/theMacroExpander.hpp>
+
+#include <com/sun/star/io/Pipe.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/io/XActiveDataSource.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XStreamListener.hpp>
+#include <com/sun/star/util/PathSubstitution.hpp>
+#include <com/sun/star/util/XStringSubstitution.hpp>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/xml/xslt/XSLT2Transformer.hpp>
+#include <com/sun/star/xml/xslt/XSLTTransformer.hpp>
+#include <utility>
+
+#define TRANSFORMATION_TIMEOUT_SEC 60
+
+using namespace ::cppu;
+using namespace ::osl;
+using namespace ::sax;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::registry;
+using namespace ::com::sun::star::xml;
+using namespace ::com::sun::star::xml::sax;
+using namespace ::com::sun::star::util;
+using namespace ::com::sun::star::task;
+
+namespace XSLT
+{
+ namespace {
+
+ class XSLTFilter;
+ class XSLTFilterStreamListener : public WeakImplHelper<XStreamListener>
+ {
+ public:
+ XSLTFilterStreamListener(XSLTFilter& rParent) : m_rParent(rParent) {}
+
+ // XStreamListener
+ virtual void SAL_CALL
+ error(const Any& a) override;
+ virtual void SAL_CALL
+ closed() override;
+ virtual void SAL_CALL
+ terminated() override;
+ virtual void SAL_CALL
+ started() override;
+ virtual void SAL_CALL
+ disposing(const EventObject& e) override;
+ private:
+ XSLTFilter& m_rParent;
+ };
+
+ /*
+ * XSLTFilter reads flat XML streams from the XML filter framework and passes
+ * them to an XSLT transformation service. XSLT transformation errors are
+ * reported to XSLTFilter.
+ *
+ * Currently, our transformation service is libxslt based, so it
+ * only supports XSLT 1.0. There is a possibility to use XSLT 2.0
+ * supporting service from an extension for a specific filter; the
+ * service must support com.sun.star.xml.xslt.XSLT2Transformer.
+ */
+ class XSLTFilter : public WeakImplHelper<XImportFilter, XImportFilter2, XExportFilter,
+ ExtendedDocumentHandlerAdapter, XServiceInfo>
+ {
+ friend class XSLTFilterStreamListener;
+ private:
+
+ // the UNO ServiceFactory
+ css::uno::Reference<XComponentContext> m_xContext;
+
+ // DocumentHandler interface of the css::xml::sax::Writer service
+ css::uno::Reference<XOutputStream> m_rOutputStream;
+
+ css::uno::Reference<xslt::XXSLTTransformer> m_tcontrol;
+
+ osl::Condition m_cTransformed;
+ bool m_bTerminated;
+ bool m_bError;
+
+ OUString m_aExportBaseUrl;
+
+ OUString
+ rel2abs(const OUString&);
+ OUString
+ expandUrl(const OUString&);
+
+ css::uno::Reference<xslt::XXSLTTransformer> impl_createTransformer(const OUString& rTransformer, const Sequence<Any>& rArgs);
+
+ public:
+
+ // ctor...
+ explicit XSLTFilter(css::uno::Reference<XComponentContext> x);
+
+ // XServiceInfo
+ virtual sal_Bool SAL_CALL supportsService(const OUString& sServiceName) override;
+ virtual OUString SAL_CALL getImplementationName() override;
+ virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
+
+ // XImportFilter
+ virtual sal_Bool SAL_CALL
+ importer(const Sequence<PropertyValue>& aSourceData, const css::uno::Reference<
+ XDocumentHandler>& xHandler,
+ const Sequence<OUString>& msUserData) override;
+
+ // XImportFilter2
+ virtual sal_Bool SAL_CALL
+ importer(const Sequence<PropertyValue>& aSourceData, const css::uno::Reference<
+ XFastParser>& xFastParser,
+ const Sequence<OUString>& msUserData) override;
+
+ // XExportFilter
+ virtual sal_Bool SAL_CALL
+ exporter(const Sequence<PropertyValue>& aSourceData, const Sequence<
+ OUString>& msUserData) override;
+
+ // XDocumentHandler
+ virtual void SAL_CALL
+ startDocument() override;
+ virtual void SAL_CALL
+ endDocument() override;
+ };
+
+ }
+
+ XSLTFilter::XSLTFilter(css::uno::Reference<XComponentContext> x):
+ m_xContext(std::move(x)), m_bTerminated(false), m_bError(false)
+ {}
+
+ void
+ XSLTFilterStreamListener::disposing(const EventObject&)
+ {
+ }
+
+ // XServiceInfo
+ sal_Bool XSLTFilter::supportsService(const OUString& sServiceName)
+ {
+ return cppu::supportsService(this, sServiceName);
+ }
+ OUString XSLTFilter::getImplementationName()
+ {
+ return "com.sun.star.comp.documentconversion.XSLTFilter";
+ }
+ css::uno::Sequence< OUString > XSLTFilter::getSupportedServiceNames()
+ {
+ return { "com.sun.star.documentconversion.XSLTFilter" };
+ }
+
+ OUString
+ XSLTFilter::expandUrl(const OUString& sUrl)
+ {
+ OUString sExpandedUrl;
+ try
+ {
+ css::uno::Reference<XMacroExpander>
+ xMacroExpander = theMacroExpander::get(m_xContext);
+ sExpandedUrl = xMacroExpander->expandMacros(sUrl);
+ sal_Int32 nPos = sExpandedUrl.indexOf( "vnd.sun.star.expand:" );
+ if (nPos != -1)
+ sExpandedUrl = sExpandedUrl.copy(nPos + 20);
+ }
+ catch (const Exception&)
+ {
+ }
+ return sExpandedUrl;
+ }
+
+ css::uno::Reference<xslt::XXSLTTransformer>
+ XSLTFilter::impl_createTransformer(const OUString& rTransformer, const Sequence<Any>& rArgs)
+ {
+ css::uno::Reference<xslt::XXSLTTransformer> xTransformer;
+
+ // check if the filter needs XSLT-2.0-capable transformer
+ // COMPATIBILITY: libreoffice 3.5/3.6 used to save the impl.
+ // name of the XSLT 2.0 transformation service there, so check
+ // for that too (it is sufficient to check that there is _a_
+ // service name there)
+ if (rTransformer.toBoolean() || rTransformer.startsWith("com.sun."))
+ {
+ try
+ {
+ xTransformer = xslt::XSLT2Transformer::create(m_xContext, rArgs);
+ }
+ catch (const Exception&)
+ {
+ // TODO: put a dialog telling about the need to install
+ // xslt2-transformer extension here
+ SAL_WARN("filter.xslt", "could not create XSLT 2.0 transformer");
+ throw;
+ }
+ }
+
+ // instantiation of XSLT 2.0 transformer service failed, or the
+ // filter does not need it
+ if (!xTransformer.is())
+ {
+ xTransformer = xslt::XSLTTransformer::create(m_xContext, rArgs);
+ }
+
+ return xTransformer;
+ }
+
+ void
+ XSLTFilterStreamListener::started()
+ {
+ m_rParent.m_cTransformed.reset();
+ }
+ void
+ XSLTFilterStreamListener::error(const Any& a)
+ {
+ SAL_WARN("filter.xslt", "XSLTFilter::error was called: " << exceptionToString(a));
+ m_rParent.m_bError = true;
+ m_rParent.m_cTransformed.set();
+ }
+ void
+ XSLTFilterStreamListener::closed()
+ {
+ m_rParent.m_cTransformed.set();
+ }
+ void
+ XSLTFilterStreamListener::terminated()
+ {
+ m_rParent.m_bTerminated = true;
+ m_rParent.m_cTransformed.set();
+ }
+
+ OUString
+ XSLTFilter::rel2abs(const OUString& s)
+ {
+
+ css::uno::Reference<XStringSubstitution>
+ subs(css::util::PathSubstitution::create(m_xContext));
+ OUString aWorkingDir(subs->getSubstituteVariableValue( "$(progurl)" ));
+ INetURLObject aObj(aWorkingDir);
+ aObj.setFinalSlash();
+ bool bWasAbsolute;
+ INetURLObject aURL = aObj.smartRel2Abs(s, bWasAbsolute, false,
+ INetURLObject::EncodeMechanism::WasEncoded, RTL_TEXTENCODING_UTF8, true);
+ return aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ }
+
+ sal_Bool
+ XSLTFilter::importer(const Sequence<PropertyValue>& aSourceData,
+ const css::uno::Reference<XDocumentHandler>& xHandler, const Sequence<
+ OUString>& msUserData)
+ {
+ if (msUserData.getLength() < 5)
+ return false;
+
+ OUString udStyleSheet = rel2abs(msUserData[4]);
+
+ // get information from media descriptor
+ // the input stream that represents the imported file
+ // is most important here since we need to supply it to
+ // the sax parser that drives the supplied document handler
+ OUString aName, aURL;
+ css::uno::Reference<XInputStream> xInputStream;
+ css::uno::Reference<XInteractionHandler> xInterActionHandler;
+ for (const auto& sourceDataItem : aSourceData)
+ {
+ aName = sourceDataItem.Name;
+ Any value = sourceDataItem.Value;
+ if ( aName == "InputStream" )
+ value >>= xInputStream;
+ else if ( aName == "URL" )
+ value >>= aURL;
+ else if ( aName == "InteractionHandler" )
+ value >>= xInterActionHandler;
+ }
+ OSL_ASSERT(xInputStream.is());
+ if (!xInputStream.is())
+ return false;
+
+ // create transformer
+ Sequence<Any> args{ Any(NamedValue("StylesheetURL", Any(expandUrl(udStyleSheet)))),
+ Any(NamedValue("SourceURL", Any(aURL))),
+ Any(NamedValue("SourceBaseURL", Any(INetURLObject(aURL).getBase()))) };
+ m_tcontrol = impl_createTransformer(msUserData[1], args);
+
+ OSL_ASSERT(xHandler.is());
+ OSL_ASSERT(xInputStream.is());
+ OSL_ASSERT(m_tcontrol.is());
+ if (xHandler.is() && xInputStream.is() && m_tcontrol.is())
+ {
+ try
+ {
+ css::uno::Reference<css::io::XSeekable> xSeek(xInputStream, UNO_QUERY);
+ if (xSeek.is())
+ xSeek->seek(0);
+
+ // we want to be notified when the processing is done...
+ m_tcontrol->addListener(new XSLTFilterStreamListener(*this));
+
+ // connect input to transformer
+ m_tcontrol->setInputStream(xInputStream);
+
+ // create pipe
+ css::uno::Reference<XOutputStream> pipeout =
+ Pipe::create(m_xContext);
+ css::uno::Reference<XInputStream> pipein(pipeout, UNO_QUERY);
+
+ //connect transformer to pipe
+ m_tcontrol->setOutputStream(pipeout);
+
+ // connect pipe to sax parser
+ InputSource aInput;
+ aInput.sSystemId = aURL;
+ aInput.sPublicId = aURL;
+ aInput.aInputStream = pipein;
+
+ css::uno::Reference< css::xml::sax::XFastParser > xFastParser = dynamic_cast<
+ css::xml::sax::XFastParser* >( xHandler.get() );
+
+ // transform
+ m_tcontrol->start();
+ TimeValue timeout = { TRANSFORMATION_TIMEOUT_SEC, 0};
+ osl::Condition::Result result(m_cTransformed.wait(&timeout));
+ while (osl::Condition::result_timeout == result) {
+ if (xInterActionHandler.is()) {
+ Sequence<Any> excArgs(0);
+ css::ucb::InteractiveAugmentedIOException exc(
+ "Timeout!",
+ static_cast< OWeakObject * >( this ),
+ InteractionClassification_ERROR,
+ css::ucb::IOErrorCode_GENERAL,
+ excArgs);
+ Any r;
+ r <<= exc;
+ rtl::Reference<::comphelper::OInteractionRequest> pRequest = new ::comphelper::OInteractionRequest(r);
+ rtl::Reference<::comphelper::OInteractionRetry> pRetry = new ::comphelper::OInteractionRetry;
+ rtl::Reference<::comphelper::OInteractionAbort> pAbort = new ::comphelper::OInteractionAbort;
+ pRequest->addContinuation(pRetry);
+ pRequest->addContinuation(pAbort);
+ xInterActionHandler->handle(pRequest);
+ if (pAbort->wasSelected()) {
+ m_bError = true;
+ m_cTransformed.set();
+ }
+ }
+ result = m_cTransformed.wait(&timeout);
+ };
+ if (!m_bError) {
+ if( xFastParser.is() )
+ xFastParser->parseStream( aInput );
+ else
+ {
+ // create SAX parser that will read the document file
+ // and provide events to xHandler passed to this call
+ css::uno::Reference<XParser> xSaxParser = Parser::create(m_xContext);
+ // set doc handler
+ xSaxParser->setDocumentHandler(xHandler);
+ xSaxParser->parseStream( aInput );
+ }
+ }
+ m_tcontrol->terminate();
+ return !m_bError;
+ }
+ catch( const Exception& )
+ {
+ // something went wrong
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ sal_Bool
+ XSLTFilter::importer(const Sequence<PropertyValue>& aSourceData,
+ const css::uno::Reference<XFastParser>& xFastParser, const Sequence<
+ OUString>& msUserData)
+ {
+ if (msUserData.getLength() < 5)
+ return false;
+
+ OUString udStyleSheet = rel2abs(msUserData[4]);
+
+ // get information from media descriptor
+ // the input stream that represents the imported file
+ // is most important here since we need to supply it to
+ // the sax parser that drives the supplied document handler
+ sal_Int32 nLength = aSourceData.getLength();
+ OUString aName, aURL;
+ css::uno::Reference<XInputStream> xInputStream;
+ css::uno::Reference<XInteractionHandler> xInterActionHandler;
+ for (sal_Int32 i = 0; i < nLength; i++)
+ {
+ aName = aSourceData[i].Name;
+ Any value = aSourceData[i].Value;
+ if ( aName == "InputStream" )
+ value >>= xInputStream;
+ else if ( aName == "URL" )
+ value >>= aURL;
+ else if ( aName == "InteractionHandler" )
+ value >>= xInterActionHandler;
+ }
+ OSL_ASSERT(xInputStream.is());
+ if (!xInputStream.is())
+ return false;
+
+ // create transformer
+ Sequence<Any> args{ Any(NamedValue("StylesheetURL", Any(expandUrl(udStyleSheet)))),
+ Any(NamedValue("SourceURL", Any(aURL))),
+ Any(NamedValue("SourceBaseURL", Any(INetURLObject(aURL).getBase()))) };
+ m_tcontrol = impl_createTransformer(msUserData[1], args);
+
+ assert(xFastParser.is());
+ OSL_ASSERT(xInputStream.is());
+ OSL_ASSERT(m_tcontrol.is());
+ if (xFastParser.is() && xInputStream.is() && m_tcontrol.is())
+ {
+ try
+ {
+ css::uno::Reference<css::io::XSeekable> xSeek(xInputStream, UNO_QUERY);
+ if (xSeek.is())
+ xSeek->seek(0);
+
+ // we want to be notified when the processing is done...
+ m_tcontrol->addListener(new XSLTFilterStreamListener(*this));
+
+ // connect input to transformer
+ m_tcontrol->setInputStream(xInputStream);
+
+ // create pipe
+ css::uno::Reference<XOutputStream> pipeout =
+ Pipe::create(m_xContext);
+ css::uno::Reference<XInputStream> pipein(pipeout, UNO_QUERY);
+
+ //connect transformer to pipe
+ m_tcontrol->setOutputStream(pipeout);
+
+ // connect pipe to sax parser
+ InputSource aInput;
+ aInput.sSystemId = aURL;
+ aInput.sPublicId = aURL;
+ aInput.aInputStream = pipein;
+
+ // transform
+ m_tcontrol->start();
+ TimeValue timeout = { TRANSFORMATION_TIMEOUT_SEC, 0};
+ osl::Condition::Result result(m_cTransformed.wait(&timeout));
+ while (osl::Condition::result_timeout == result) {
+ if (xInterActionHandler.is()) {
+ Sequence<Any> excArgs(0);
+ css::ucb::InteractiveAugmentedIOException exc(
+ "Timeout!",
+ static_cast< OWeakObject * >( this ),
+ InteractionClassification_ERROR,
+ css::ucb::IOErrorCode_GENERAL,
+ excArgs);
+ Any r;
+ r <<= exc;
+ rtl::Reference<::comphelper::OInteractionRequest> pRequest = new ::comphelper::OInteractionRequest(r);
+ rtl::Reference<::comphelper::OInteractionRetry> pRetry = new ::comphelper::OInteractionRetry;
+ rtl::Reference<::comphelper::OInteractionAbort> pAbort = new ::comphelper::OInteractionAbort;
+ pRequest->addContinuation(pRetry);
+ pRequest->addContinuation(pAbort);
+ xInterActionHandler->handle(pRequest);
+ if (pAbort->wasSelected()) {
+ m_bError = true;
+ m_cTransformed.set();
+ }
+ }
+ result = m_cTransformed.wait(&timeout);
+ };
+ if (!m_bError)
+ xFastParser->parseStream( aInput );
+ m_tcontrol->terminate();
+ return !m_bError;
+ }
+ catch( const Exception& )
+ {
+ // something went wrong
+ TOOLS_WARN_EXCEPTION("filter.xslt", "");
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ sal_Bool
+ XSLTFilter::exporter(const Sequence<PropertyValue>& aSourceData,
+ const Sequence<OUString>& msUserData)
+ {
+ if (msUserData.getLength() < 6)
+ return false;
+
+ // get interesting values from user data
+ OUString udStyleSheet = rel2abs(msUserData[5]);
+
+ // read source data
+ // we are especially interested in the output stream
+ // since that is where our xml-writer will push the data
+ // from its data-source interface
+ OUString aName, sURL;
+ OUString aDoctypePublic;
+ // css::uno::Reference<XOutputStream> rOutputStream;
+ sal_Int32 nLength = aSourceData.getLength();
+ for (sal_Int32 i = 0; i < nLength; i++)
+ {
+ aName = aSourceData[i].Name;
+ if ( aName == "DocType_Public" )
+ aSourceData[i].Value >>= aDoctypePublic;
+ else if ( aName == "OutputStream" )
+ aSourceData[i].Value >>= m_rOutputStream;
+ else if ( aName == "URL" )
+ aSourceData[i].Value >>= sURL;
+ }
+
+ if (!getDelegate().is())
+ {
+ // get the document writer
+ setDelegate(css::uno::Reference<XExtendedDocumentHandler>(
+ Writer::create(m_xContext),
+ UNO_QUERY_THROW));
+ }
+
+ // create transformer
+ INetURLObject ineturl(sURL);
+ ineturl.removeSegment();
+ m_aExportBaseUrl = ineturl.GetMainURL(INetURLObject::DecodeMechanism::NONE);
+ Sequence<Any> args{ Any(NamedValue("StylesheetURL", Any(expandUrl(udStyleSheet)))),
+ Any(NamedValue("TargetURL", Any(sURL))),
+ Any(NamedValue("DoctypePublic", Any(aDoctypePublic))),
+ Any(NamedValue("TargetBaseURL", Any(m_aExportBaseUrl))) };
+ m_tcontrol = impl_createTransformer(msUserData[1], args);
+
+ OSL_ASSERT(m_rOutputStream.is());
+ OSL_ASSERT(m_tcontrol.is());
+ if (m_tcontrol.is() && m_rOutputStream.is())
+ {
+ // we want to be notified when the processing is done...
+ m_tcontrol->addListener(new XSLTFilterStreamListener(*this));
+
+ // create pipe
+ css::uno::Reference<XOutputStream> pipeout =
+ Pipe::create(m_xContext);
+ css::uno::Reference<XInputStream> pipein(pipeout, UNO_QUERY);
+
+ // connect sax writer to pipe
+ css::uno::Reference<XActiveDataSource> xmlsource(getDelegate(),
+ UNO_QUERY);
+ xmlsource->setOutputStream(pipeout);
+
+ // connect pipe to transformer
+ m_tcontrol->setInputStream(pipein);
+
+ // connect transformer to output
+ m_tcontrol->setOutputStream(m_rOutputStream);
+
+ // we will start receiving events after returning 'true'.
+ // we will start the transformation as soon as we receive the startDocument
+ // event.
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ // for the DocumentHandler implementation, we just proxy the
+ // events to the XML writer that we created upon the output stream
+ // that was provided by the XMLFilterAdapter
+ void
+ XSLTFilter::startDocument()
+ {
+ ExtendedDocumentHandlerAdapter::startDocument();
+ m_tcontrol->start();
+ }
+
+ void
+ XSLTFilter::endDocument()
+ {
+ ExtendedDocumentHandlerAdapter::endDocument();
+ // wait for the transformer to finish
+ m_cTransformed.wait();
+ m_tcontrol->terminate();
+ if (m_bError || m_bTerminated)
+ throw RuntimeException();
+ }
+
+
+}
+
+// Component management
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+filter_XSLTFilter_get_implementation(
+ css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
+{
+ return cppu::acquire(new XSLT::XSLTFilter(context));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/filter/source/xsltfilter/xsltfilter.component b/filter/source/xsltfilter/xsltfilter.component
new file mode 100644
index 000000000..e4298a7a0
--- /dev/null
+++ b/filter/source/xsltfilter/xsltfilter.component
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" environment="@CPPU_ENV@"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.comp.documentconversion.XSLTFilter"
+ constructor="filter_XSLTFilter_get_implementation">
+ <service name="com.sun.star.documentconversion.XSLTFilter"/>
+ </implementation>
+ <implementation name="com.sun.star.comp.documentconversion.LibXSLTTransformer"
+ constructor="filter_LibXSLTTransformer_get_implementation">
+ <service name="com.sun.star.xml.xslt.XSLTTransformer"/>
+ </implementation>
+</component>
diff --git a/filter/uiconfig/ui/pdfgeneralpage.ui b/filter/uiconfig/ui/pdfgeneralpage.ui
new file mode 100644
index 000000000..844e3c341
--- /dev/null
+++ b/filter/uiconfig/ui/pdfgeneralpage.ui
@@ -0,0 +1,1038 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkSizeGroup"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">1</property>
+ <property name="upper">100</property>
+ <property name="value">90</property>
+ <property name="step-increment">1</property>
+ <property name="page-increment">10</property>
+ </object>
+ <!-- n-columns=2 n-rows=1 -->
+ <object class="GtkGrid" id="PdfGeneralPage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="column-spacing">24</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=5 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="all">
+ <property name="label" translatable="yes" context="pdfgeneralpage|all">_All</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="all-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|all">Exports all defined print ranges. If no print range is defined, exports the entire document.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="range">
+ <property name="label" translatable="yes" context="pdfgeneralpage|range">_Pages:</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">all</property>
+ <accessibility>
+ <relation type="label-for" target="pages"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="range-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|range">Exports the pages you type in the box.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="selection">
+ <property name="label" translatable="yes" context="pdfgeneralpage|selection">_Selection</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">all</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="selection-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|selection">Exports the current selection.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="pages">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="width-chars">5</property>
+ <property name="truncate-multiline">True</property>
+ <accessibility>
+ <relation type="labelled-by" target="range"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="pages-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|pages">Exports the pages you type in the box.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="slides">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|slides">Slides:</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="viewpdf">
+ <property name="label" translatable="yes" context="pdfgeneralpage|viewpdf">_View PDF after export</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="viewpdf-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|viewpdf">Open the exported document in the system default PDF viewer.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="selectedsheets">
+ <property name="can-focus">False</property>
+ <property name="no-show-all">True</property>
+ <property name="halign">start</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|selectedsheets">_Selection/Selected sheet(s)</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|label1">Range</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=3 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">3</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="losslesscompress">
+ <property name="label" translatable="yes" context="pdfgeneralpage|losslesscompress">_Lossless compression</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="losslesscompress-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|losslesscompress">Selects a lossless compression of images. All pixels are preserved.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="reduceresolution">
+ <property name="label" translatable="yes" context="pdfgeneralpage|reduceresolution">Reduce ima_ge resolution to:</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <accessibility>
+ <relation type="label-for" target="resolution"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="reduceresolution-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|reduceresolution">Select to resample or down-size the images to a lower number of pixels per inch.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="resolution">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="has-entry">True</property>
+ <items>
+ <item translatable="yes" context="pdfgeneralpage|resolution">75 DPI</item>
+ <item translatable="yes" context="pdfgeneralpage|resolution">150 DPI</item>
+ <item translatable="yes" context="pdfgeneralpage|resolution">300 DPI</item>
+ <item translatable="yes" context="pdfgeneralpage|resolution">600 DPI</item>
+ <item translatable="yes" context="pdfgeneralpage|resolution">1200 DPI</item>
+ </items>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="comboboxtext-entry">
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="text" translatable="yes" context="pdfgeneralpage|comboboxtext-entry">75 DPI</property>
+ <property name="truncate-multiline">True</property>
+ </object>
+ </child>
+ <accessibility>
+ <relation type="labelled-by" target="reduceresolution"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="resolution-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|resolution">Select the target resolution for the images.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="qualityframe">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <object class="GtkSpinButton" id="quality">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="adjustment">adjustment1</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="quality-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|quality">Enter the quality level for JPEG compression.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">3</property>
+ <child>
+ <object class="GtkRadioButton" id="jpegcompress">
+ <property name="label" translatable="yes" context="pdfgeneralpage|jpegcompress">_JPEG compression</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">losslesscompress</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="jpegcompress-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|jpegcompress">Select a JPEG compression level. With a high quality level, almost all pixels are preserved. With a low quality level, some pixels are lost and artifacts are introduced, but file sizes are reduced.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|label6">_Quality:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">quality</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|label2">Images</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=2 n-rows=2 -->
+ <object class="GtkGrid" id="grid7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">3</property>
+ <property name="column-spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="watermark">
+ <property name="label" translatable="yes" context="pdfgeneralpage|watermark">Sign with _watermark</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="watermark-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|watermark">Add a centered, vertical, light green watermark text to the page background. The watermark is not part of the source document.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="watermarkentry">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="watermarkentry-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|watermarkentry">Insert the text for the watermark signature.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="watermarklabel">
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|watermarklabel">Text:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">watermarkentry</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|label3">Watermark</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-end">6</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=6 -->
+ <object class="GtkGrid" id="grid10">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">3</property>
+ <child>
+ <object class="GtkCheckButton" id="embed">
+ <property name="label" translatable="yes" context="pdfgeneralpage|embed">Hybrid PDF (em_bed ODF file)</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|embed|tooltip_text">Creates a PDF that is easily editable in %PRODUCTNAME</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="embed-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|embed">This setting enables you to export the document as a .pdf file containing two file formats: PDF and ODF.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="tagged">
+ <property name="label" translatable="yes" context="pdfgeneralpage|tagged">_Tagged PDF (add document structure)</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|tagged|tooltip_text">Includes a document's content structure information in a PDF</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="tagged-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|tagged">Select to write PDF tags. This can increase file size by huge amounts.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="forms">
+ <property name="label" translatable="yes" context="pdfgeneralpage|forms">Create PDF for_m</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|forms|tooltip_text">Creates a PDF with fields that can be filled out</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="forms-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|forms">Choose to create a PDF form. This can be filled out and printed by the user of the PDF document.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=2 -->
+ <object class="GtkGrid" id="formsframe">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">18</property>
+ <property name="hexpand">True</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <object class="GtkCheckButton" id="allowdups">
+ <property name="label" translatable="yes" context="pdfgeneralpage|allowdups">Allow duplicate field _names</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="allowdups-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|allowdups">Allows you to use the same field name for multiple fields in the generated PDF file. If disabled, field names will be exported using generated unique names.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="format">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <items>
+ <item translatable="yes" context="pdfgeneralpage|format">FDF</item>
+ <item translatable="yes" context="pdfgeneralpage|format">PDF</item>
+ <item translatable="yes" context="pdfgeneralpage|format">HTML</item>
+ <item translatable="yes" context="pdfgeneralpage|format">XML</item>
+ </items>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="format-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|format">Select the format of submitting forms from within the PDF file.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="submitformatbox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">baseline</property>
+ <property name="margin-top">1</property>
+ <property name="vexpand">True</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|label7">Submit _format:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">format</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=2 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="pdfa">
+ <property name="label" translatable="yes" context="pdfgeneralpage|pdfa">Archive (P_DF/A, ISO 19005)</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|pdfa|tooltip_text">Creates an ISO 19005-2 compliant PDF file, ideal for long-term document preservation</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="pdfa-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|pdfa">Converts to the PDF/A-2b or PDF/A-1b format. This is defined as an electronic document file format for long term preservation. All fonts that were used in the source document will be embedded into the generated PDF file. PDF tags will be written.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=1 -->
+ <object class="GtkGrid" id="pdfagrid">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">18</property>
+ <property name="hexpand">True</property>
+ <property name="column-spacing">14</property>
+ <child>
+ <object class="GtkComboBoxText" id="pdfaversion">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="active">3</property>
+ <items>
+ <item id="1" context="pdfgeneralpage|pdfaversion">PDF/A-1b</item>
+ <item id="2" context="pdfgeneralpage|pdfaversion">PDF/A-2b</item>
+ <item id="3" context="pdfgeneralpage|pdfaversion">PDF/A-3b</item>
+ </items>
+ <accessibility>
+ <relation type="labelled-by" target="pdfaversionlabel"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="pdfabox">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="pdfaversionlabel">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="halign">start</property>
+ <property name="valign">baseline</property>
+ <property name="vexpand">True</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|pdfaversion">PDF_/A version:</property>
+ <property name="use-underline">True</property>
+ <accessibility>
+ <relation type="label-for" target="pdfaversion"/>
+ </accessibility>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="pdfua">
+ <property name="label" translatable="yes" context="pdfgeneralpage|pdfua">Universal Accessibilit_y (PDF/UA)</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="tooltip-text" translatable="yes" context="pdfgeneralpage|pdfua|tooltip_text">Creates a universal accessibility-compliant PDF file that follows the requirements of PDF/UA (ISO 14289) specifications.</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="pdfua-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|pdfua">Creates a universal accessibility-complying PDF file that follows the requirements of PDF/UA (ISO 14289) specifications.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|label4">General</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=9 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">3</property>
+ <child>
+ <object class="GtkCheckButton" id="bookmarks">
+ <property name="label" translatable="yes" context="pdfgeneralpage|bookmarks">Export outl_ines</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="bookmarks-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|bookmarks">Select to export bookmarks of Writer documents as PDF bookmarks. Bookmarks are created for all outline paragraphs (Tools - Chapter Numbering) and for all table of contents entries for which you did assign hyperlinks in the source document.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="exportplaceholders">
+ <property name="label" translatable="yes" context="pdfgeneralpage|exportplaceholders">Expo_rt placeholders</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="exportplaceholders-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|exportplaceholders">Export the placeholders fields visual markings only. The exported placeholder is ineffective.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="comments">
+ <property name="label" translatable="yes" context="pdfgeneralpage|comments">Comm_ents as PDF annotations</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="comments-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|comments">Select to export comments of Writer and Calc documents as PDF annotations.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="emptypages">
+ <property name="label" translatable="yes" context="pdfgeneralpage|emptypages">Exp_ort automatically inserted blank pages</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="emptypages-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|emptypages">If switched on, automatically inserted blank pages are exported to the PDF file. This is best if you are printing the pdf file double-sided. Example: In a book a chapter paragraph style is set to always start with an odd numbered page. If the previous chapter ends on an odd page, then an even numbered blank page is normally automatically inserted. This option controls whether to export that even numbered page or not.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">7</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="usereferencexobject">
+ <property name="label" translatable="yes" context="pdfgeneralpage|usereferencexobject">Use reference XObjects</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="usereferencexobject-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|usereferencexobject">When the option is enabled, then the reference XObject markup is used: viewers have to support this markup to show vector images. Otherwise a fallback bitmap is shown in the viewer.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">8</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="hiddenpages">
+ <property name="label" translatable="yes" context="pdfgeneralpage|hiddenpages">Export _hidden pages</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="hiddenpages-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|hiddenpages">Exports document hidden slides.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="notes">
+ <property name="label" translatable="yes" context="pdfgeneralpage|notes">Export _notes pages</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="notes-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|notes">Export also the Notes pages view at the end of the exported PDF presentation document.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="onlynotes">
+ <property name="label" translatable="yes" context="pdfgeneralpage|onlynotes">Export onl_y notes pages</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="margin-start">18</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="onlynotes-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|onlynotes">Exports only the Notes page views.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="singlepagesheets">
+ <property name="label" translatable="yes" context="pdfgeneralpage|singlepagesheets">Whole sheet export</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="halign">start</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="singlepagesheets-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfgeneralpage|extended_tip|singlepagessheets">Ignores each sheet’s paper size, print ranges and shown/hidden status and puts every sheet (even hidden sheets) on exactly one page, which is exactly as small or large as needed to fit the whole contents of the sheet.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">6</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfgeneralpage|label9">Structure</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="comboBoxSizegroup">
+ <widgets>
+ <widget name="format"/>
+ <widget name="pdfaversion"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="pdfSizeGroup">
+ <widgets>
+ <widget name="submitformatbox"/>
+ <widget name="pdfabox"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroupLabel">
+ <widgets>
+ <widget name="all"/>
+ <widget name="range"/>
+ <widget name="selection"/>
+ <widget name="losslesscompress"/>
+ <widget name="box3"/>
+ <widget name="reduceresolution"/>
+ <widget name="watermark"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroupWidget">
+ <widgets>
+ <widget name="pages"/>
+ <widget name="qualityframe"/>
+ <widget name="resolution"/>
+ <widget name="watermarkentry"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/pdflinkspage.ui b/filter/uiconfig/ui/pdflinkspage.ui
new file mode 100644
index 000000000..892f72864
--- /dev/null
+++ b/filter/uiconfig/ui/pdflinkspage.ui
@@ -0,0 +1,197 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="PdfLinksPage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=3 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <child>
+ <object class="GtkCheckButton" id="export">
+ <property name="label" translatable="yes" context="pdflinkspage|export">Export outlines as named destinations</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="export-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdflinkspage|extended_tip|export">Enable the checkbox to export the names of objects in your document as valid bookmark targets. This allows you to link to those objects by name from other documents.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="convert">
+ <property name="label" translatable="yes" context="pdflinkspage|convert">_Convert document references to PDF targets</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="convert-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdflinkspage|extended_tip|convert">Enable this checkbox to convert the URLs referencing other ODF files to PDF files with the same name. In the referencing URLs the extensions .odt, .odp, .ods, .odg, and .odm are converted to the extension .pdf.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="exporturl">
+ <property name="label" translatable="yes" context="pdflinkspage|exporturl">Export _URLs relative to file system</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="exporturl-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdflinkspage|extended_tip|exporturl">Enable this checkbox to export URLs to other documents as relative URLs in the file system. See "relative hyperlinks" in the Help.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdflinkspage|label1">General</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=3 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <child>
+ <object class="GtkRadioButton" id="default">
+ <property name="label" translatable="yes" context="pdflinkspage|default">Default mode</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="active">True</property>
+ <property name="draw-indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="default-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdflinkspage|extended_tip|default">Links from your PDF document to other documents will be handled as it is specified in your operating system.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="openpdf">
+ <property name="label" translatable="yes" context="pdflinkspage|openpdf">Open with PDF reader application</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">default</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="openpdf-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdflinkspage|extended_tip|openpdf">Cross-document links are opened with the PDF reader application that currently shows the document. The PDF reader application must be able to handle the specified file type inside the hyperlink.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="openinternet">
+ <property name="label" translatable="yes" context="pdflinkspage|openinternet">Open _with Internet browser</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">False</property>
+ <property name="use-underline">True</property>
+ <property name="draw-indicator">True</property>
+ <property name="group">default</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="openinternet-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdflinkspage|extended_tip|openinternet">Cross-document links are opened with the Internet browser. The Internet browser must be able to handle the specified file type inside the hyperlink.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdflinkspage|label5">Cross-document Links</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/pdfoptionsdialog.ui b/filter/uiconfig/ui/pdfoptionsdialog.ui
new file mode 100644
index 000000000..e47f774af
--- /dev/null
+++ b/filter/uiconfig/ui/pdfoptionsdialog.ui
@@ -0,0 +1,399 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="PdfOptionsDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="pdfoptionsdialog|PdfOptionsDialog">PDF Options</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes" context="stock">_Reset</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="pdfoptionsdialog|ok">E_xport</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable_popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="general">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfoptionsdialog|general">General</property>
+ </object>
+ <packing>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="initialview">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfoptionsdialog|initialview">Initial View</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="userinterface">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfoptionsdialog|userinterface">User Interface</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="links">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfoptionsdialog|links">Links</property>
+ </object>
+ <packing>
+ <property name="position">3</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="security">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfoptionsdialog|security">Security</property>
+ </object>
+ <packing>
+ <property name="position">4</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="digitalsignatures">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfoptionsdialog|digitalsignatures">Digital Signatures</property>
+ </object>
+ <packing>
+ <property name="position">5</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/pdfsecuritypage.ui b/filter/uiconfig/ui/pdfsecuritypage.ui
new file mode 100644
index 000000000..324513f1a
--- /dev/null
+++ b/filter/uiconfig/ui/pdfsecuritypage.ui
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="PdfSecurityPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkButton" id="setpassword">
+ <property name="label" translatable="yes" context="pdfsecuritypage|setpassword">Set _Passwords…</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="halign">start</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="setpassword-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|setpassword">Click to open a dialog where you enter the passwords.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="userpwdset">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label5">Open password set</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label6">PDF document will be encrypted</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="userpwdunset">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label7">No open password set</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label8">PDF document will not be encrypted</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="userpwdpdfa">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <child>
+ <object class="GtkLabel" id="label30">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label30">PDF document will not be encrypted due to PDF/A export.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ownerpwdset">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <child>
+ <object class="GtkLabel" id="label9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label9">Permission password set</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label11">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label11">PDF document will be restricted</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ownerpwdunset">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label12">No permission password set</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label13">PDF document will be unrestricted</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="ownerpwdpdfa">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <child>
+ <object class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label14">PDF document will not be restricted due to PDF/A export.</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="setpasswordstitle">
+ <property name="can_focus">False</property>
+ <property name="no_show_all">True</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|setpasswordstitle">Set Passwords</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">7</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label2">File Encryption and Permission</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="printing">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid7">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="printnone">
+ <property name="label" translatable="yes" context="pdfsecuritypage|printnone">_Not permitted</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">printhigh</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="printnone-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|printnone">Printing the document is not permitted.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="printlow">
+ <property name="label" translatable="yes" context="pdfsecuritypage|printlow">_Low resolution (150 dpi)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">printhigh</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="printlow-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|printlow">The document can only be printed in low resolution (150 dpi). Not all PDF readers honor this setting.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="printhigh">
+ <property name="label" translatable="yes" context="pdfsecuritypage|printhigh">_High resolution</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="printhigh-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|printhigh">The document can be printed in high resolution.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label1">Printing</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="changes">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid8">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="changenone">
+ <property name="label" translatable="yes" context="pdfsecuritypage|changenone">No_t permitted</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">changeany</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="changenone-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|changenone">No changes of the content are permitted.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="changeinsdel">
+ <property name="label" translatable="yes" context="pdfsecuritypage|changeinsdel">_Inserting, deleting, and rotating pages</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">changeany</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="changeinsdel-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|changeinsdel">Only inserting, deleting, and rotating pages is permitted.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="changeform">
+ <property name="label" translatable="yes" context="pdfsecuritypage|changeform">_Filling in form fields</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">changeany</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="changeform-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|changeform">Only filling in form fields is permitted.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="changecomment">
+ <property name="label" translatable="yes" context="pdfsecuritypage|changecomment">_Commenting, filling in form fields</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">changeany</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="changecomment-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|changecomment">Only commenting and filling in form fields is permitted.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="changeany">
+ <property name="label" translatable="yes" context="pdfsecuritypage|changeany">_Any except extracting pages</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="changeany-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|changeany">All changes are permitted, except extracting pages.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label3">Changes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="content">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid9">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="enablecopy">
+ <property name="label" translatable="yes" context="pdfsecuritypage|enablecopy">Ena_ble copying of content</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="enablecopy-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|enablecopy">Select to enable copying of content to the clipboard.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="enablea11y">
+ <property name="label" translatable="yes" context="pdfsecuritypage|enablea11y">Enable text access for acce_ssibility tools</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="enablea11y-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsecuritypage|extended_tip|enablea11y">Select to enable text access for accessibility tools.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfsecuritypage|label4">Content</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="userpwdset"/>
+ <widget name="userpwdunset"/>
+ <widget name="userpwdpdfa"/>
+ <widget name="ownerpwdset"/>
+ <widget name="ownerpwdunset"/>
+ <widget name="ownerpwdpdfa"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/pdfsignpage.ui b/filter/uiconfig/ui/pdfsignpage.ui
new file mode 100644
index 000000000..691c264db
--- /dev/null
+++ b/filter/uiconfig/ui/pdfsignpage.ui
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkFrame" id="PdfSignPage">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border-width">6</property>
+ <property name="label-xalign">0</property>
+ <property name="shadow-type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=2 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <!-- n-columns=2 n-rows=2 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfsignpage|label2">Use this certificate to digitally sign PDF documents:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">cert</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="cert">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="cert-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsignpage|extended_tip|cert">Allows you to select a certificate to be used for signing this PDF export.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="SelectClear">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">6</property>
+ <child>
+ <object class="GtkButton" id="select">
+ <property name="label" translatable="yes" context="pdfsignpage|select">Select...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="valign">center</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="select-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsignpage|extended_tip|select">Opens the Select X.509 Certificate dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="clear">
+ <property name="label" translatable="yes" context="pdfsignpage|clear">_Clear</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="valign">center</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=5 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <object class="GtkEntry" id="password">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="visibility">False</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="password-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsignpage|extended_tip|password">Enter the password used for protecting the private key associated with the selected certificate.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="location">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="location-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsignpage|extended_tip|location">These three fields allow you to optionally enter additional information about the digital signature that will be applied to the PDF (Where, by whom and why it was made). It will be embedded in the appropriate PDF fields and will be visible to anyone viewing the PDF. Each or all of the three fields may be left blank.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="contact">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="contact-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsignpage|extended_tip|contact">These three fields allow you to optionally enter additional information about the digital signature that will be applied to the PDF (Where, by whom and why it was made). It will be embedded in the appropriate PDF fields and will be visible to anyone viewing the PDF. Each or all of the three fields may be left blank.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="reason">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates-default">True</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="reason-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfsignpage|extended_tip|reason">These three fields allow you to optionally enter additional information about the digital signature that will be applied to the PDF (Where, by whom and why it was made). It will be embedded in the appropriate PDF fields and will be visible to anyone viewing the PDF. Each or all of the three fields may be left blank.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="tsa">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="active">0</property>
+ <items>
+ <item translatable="yes" context="pdfsignpage|tsa">None</item>
+ </items>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label7">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfsignpage|label7">Certificate password:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">password</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label12">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfsignpage|label12">Location:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">location</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label13">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfsignpage|label13">Contact information:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">contact</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label14">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfsignpage|label14">Reason:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">reason</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label15">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfsignpage|label15">Time Stamp Authority:</property>
+ <property name="use-underline">True</property>
+ <property name="mnemonic-widget">tsa</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="pdfsignpage|label1">Certificate</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="SelectClear"/>
+ <widget name="label7"/>
+ <widget name="label12"/>
+ <widget name="label13"/>
+ <widget name="label14"/>
+ <widget name="label15"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/pdfuserinterfacepage.ui b/filter/uiconfig/ui/pdfuserinterfacepage.ui
new file mode 100644
index 000000000..8a26abc85
--- /dev/null
+++ b/filter/uiconfig/ui/pdfuserinterfacepage.ui
@@ -0,0 +1,381 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">1</property>
+ <property name="upper">10</property>
+ <property name="value">1</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="PdfUserInterfacePage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">12</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="center">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|center">_Center window on screen</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="center-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|center">Select to generate a PDF file that is shown in a reader window centered on screen.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="resize">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|resize">_Resize window to initial page</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="resize-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|resize">Select to generate a PDF file that is shown in a window displaying the whole initial page.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="open">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|open">_Open in full screen mode</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="open-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|open">Select to generate a PDF file that is shown in a full screen reader window in front of all other windows.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="display">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|display">_Display document title</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="display-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|display">Select to generate a PDF file that is shown with the document title in the reader's title bar.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|label1">Window Options</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="toolbar">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|toolbar">Hide _toolbar</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="toolbar-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|toolbar">Select to hide the reader's toolbar when the document is active.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="menubar">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|menubar">Hide _menubar</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="menubar-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|menubar">Select to hide the reader's menu bar when the document is active.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="window">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|window">Hide _window controls</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="window-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|window">Select to hide the reader's controls when the document is active.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|label2">User Interface Options</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkCheckButton" id="effects">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|effects">_Use transition effects</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="effects-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|effects">Select to export Impress slide transition effects to respective PDF effects.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|label3">Transitions</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="allbookmarks">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|allbookmarks">Show _All</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="allbookmarks-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|allbookmarks">Select to show all bookmark levels when the reader opens the PDF file.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="visiblebookmark">
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|visiblebookmark">_Visible levels:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">allbookmarks</property>
+ <accessibility>
+ <relation type="label-for" target="visiblelevel"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="visiblebookmark-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|visiblebookmark">Select to show bookmark levels down to the selected level when the reader opens the PDF file.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="visiblelevel">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="adjustment">adjustment1</property>
+ <accessibility>
+ <relation type="labelled-by" target="visiblebookmark"/>
+ </accessibility>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="visiblelevel-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfuserinterfacepage|extended_tip|visiblelevel">Select to show bookmark levels down to the selected level when the reader opens the PDF file.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfuserinterfacepage|label4">Collapse Outlines</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/pdfviewpage.ui b/filter/uiconfig/ui/pdfviewpage.ui
new file mode 100644
index 000000000..97cfb5341
--- /dev/null
+++ b/filter/uiconfig/ui/pdfviewpage.ui
@@ -0,0 +1,491 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="lower">1</property>
+ <property name="upper">2147483647</property>
+ <property name="value">1</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="lower">50</property>
+ <property name="upper">1600</property>
+ <property name="value">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="PdfViewPage">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="border_width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="frame2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="pageonly">
+ <property name="label" translatable="yes" context="pdfviewpage|pageonly">_Page only</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="pageonly-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|pageonly">Select to generate a PDF file that shows only the page contents.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="outline">
+ <property name="label" translatable="yes" context="pdfviewpage|outline">Outl_ine and page</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">pageonly</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="outline-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|outline">Select to generate a PDF file that shows a bookmarks palette and the page contents.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="thumbs">
+ <property name="label" translatable="yes" context="pdfviewpage|thumbs">_Thumbnails and page</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">pageonly</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="thumbs-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|thumbs">Select to generate a PDF file that shows a thumbnails palette and the page contents.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfviewpage|label4">Open on pa_ge:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">page</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="page">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustment1</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="page-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|page">Select to show the given page when the reader opens the PDF file.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfviewpage|label2">Panes</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="fitdefault">
+ <property name="label" translatable="yes" context="pdfviewpage|fitdefault">_Default</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="fitdefault-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|fitdefault">Select to generate a PDF file that shows the page contents without zooming. If the reader software is configured to use a zoom factor by default, the page shows with that zoom factor.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="fitwin">
+ <property name="label" translatable="yes" context="pdfviewpage|fitwin">_Fit in window</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">fitdefault</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="fitwin-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|fitwin">Select to generate a PDF file that shows the page zoomed to fit entirely into the reader's window.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="fitwidth">
+ <property name="label" translatable="yes" context="pdfviewpage|fitwidth">Fit _width</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">fitdefault</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="fitwidth-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|fitwidth">Select to generate a PDF file that shows the page zoomed to fit the width of the reader's window.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="fitvis">
+ <property name="label" translatable="yes" context="pdfviewpage|fitvis">Fit _visible</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">fitdefault</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="fitvis-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|fitvis">Select to generate a PDF file that shows the text and graphics on the page zoomed to fit the reader's window.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkRadioButton" id="fitzoom">
+ <property name="label" translatable="yes" context="pdfviewpage|fitzoom">_Zoom factor:</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">fitdefault</property>
+ <accessibility>
+ <relation type="label-for" target="zoom"/>
+ </accessibility>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="fitzoom-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|fitzoom">Select a given zoom factor when the reader opens the PDF file.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkSpinButton" id="zoom">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="activates_default">True</property>
+ <property name="adjustment">adjustment2</property>
+ <accessibility>
+ <relation type="labelled-by" target="fitzoom"/>
+ </accessibility>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="zoom-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|zoom">Select a given zoom factor when the reader opens the PDF file.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfviewpage|label3">Magnification</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="frame1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkRadioButton" id="defaultlayout">
+ <property name="label" translatable="yes" context="pdfviewpage|defaultlayout">D_efault</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="defaultlayout-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|defaultlayout">Select to generate a PDF file that shows the pages according to the layout setting of the reader software.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="singlelayout">
+ <property name="label" translatable="yes" context="pdfviewpage|singlelayout">_Single page</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">defaultlayout</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="singlelayout-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|singlelayout">Select to generate a PDF file that shows one page at a time.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="contlayout">
+ <property name="label" translatable="yes" context="pdfviewpage|contlayout">C_ontinuous</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">defaultlayout</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="contlayout-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|contlayout">Select to generate a PDF file that shows pages in a continuous vertical column.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkRadioButton" id="contfacinglayout">
+ <property name="label" translatable="yes" context="pdfviewpage|contfacinglayout">Co_ntinuous facing</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">defaultlayout</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="contfacinglayout-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|contfacinglayout">Select to generate a PDF file that shows pages side by side in a continuous column. For more than two pages, the first page is displayed on the right.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="firstonleft">
+ <property name="label" translatable="yes" context="pdfviewpage|firstonleft">First page is _left</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="margin_top">6</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="firstonleft-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="pdfviewpage|extended_tip|firstonleft">Select to generate a PDF file that shows pages side by side in a continuous column. For more than two pages, the first page is displayed on the left. You must enable support for complex text layout on Language settings - Languages in the Options dialog box.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="pdfviewpage|label1">Page Layout</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroupLabels">
+ <widgets>
+ <widget name="label4"/>
+ <widget name="fitzoom"/>
+ </widgets>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroupWidgets">
+ <widgets>
+ <widget name="page"/>
+ <widget name="zoom"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/testxmlfilter.ui b/filter/uiconfig/ui/testxmlfilter.ui
new file mode 100644
index 000000000..b9a5b7188
--- /dev/null
+++ b/filter/uiconfig/ui/testxmlfilter.ui
@@ -0,0 +1,411 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="TestXMLFilterDialog">
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="title" translatable="yes" context="testxmlfilter|TestXMLFilterDialog">Test XML Filter: %s</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default_width">0</property>
+ <property name="default_height">0</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="close">
+ <property name="label" translatable="yes" context="stock">_Close</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="can_default">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack_type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkFrame" id="export">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="testxmlfilter|label3">XSLT for export</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="testxmlfilter|label4">Transform document</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="exportbrowse">
+ <property name="label" translatable="yes" context="testxmlfilter|exportbrowse">Browse...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="exportbrowse-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|exportbrowse">Locate the file that you want to apply the XML export filter to. The XML code of the transformed file is opened in your default XML editor after transformation.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="currentdocument">
+ <property name="label" translatable="yes" context="testxmlfilter|currentdocument">Current Document</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="currentdocument-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|currentdocument">The front-most open file that matches the XML filter criteria will be used to test the filter. The current XML export filter transforms the file and the resulting XML code is displayed in the XML Filter output window.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="exportxsltfile">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="exportxsltfile-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|exportxsltfile">Displays the file name of the XSLT filter that you entered on the Transformation tab page.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="currentfilename">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="width_chars">52</property>
+ <property name="xalign">1</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="currentfilename-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|currentfilename">Displays the file name of the document that you want to use to test the XSLT filter.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="testxmlfilter|label1">Export</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkFrame" id="import">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label_xalign">0</property>
+ <property name="shadow_type">none</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <property name="margin-start">12</property>
+ <property name="margin-top">6</property>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="testxmlfilter|label5">XSLT for import</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="importbrowse">
+ <property name="label" translatable="yes" context="testxmlfilter|importbrowse">Browse...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="importbrowse-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|importbrowse">Opens a file selection dialog. The selected file is opened using the current XML import filter.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="recentfile">
+ <property name="label" translatable="yes" context="testxmlfilter|recentfile">Recent File</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="recentfile-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|recentfile">Re-opens the document that was last opened with this dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="templateimport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="testxmlfilter|templateimport">Template for import</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="importxsltfile">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="importxsltfile-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|importxsltfile">Displays the file name of the XSLT filter that you entered on the Transformation tab page.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="displaysource">
+ <property name="label" translatable="yes" context="testxmlfilter|displaysource">Display source</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="displaysource-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|displaysource">Opens the XML source of the selected document in your default XML editor after importing.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="label" translatable="yes" context="testxmlfilter|label6">Transform file</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="importxslttemplate">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="importxslttemplate-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|importxslttemplate">Displays the file name of the template that you entered on the Transformation tab page.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="recentfilename">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="width_chars">52</property>
+ <property name="xalign">1</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="recentfilename-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|recentfilename">Re-opens the document that was last opened with this dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">5</property>
+ <property name="width">2</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="label">
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="testxmlfilter|label2">Import</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-7">close</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child type="titlebar">
+ <placeholder/>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="TestXMLFilterDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="testxmlfilter|extended_tip|TestXMLFilterDialog">Tests the XSLT stylesheets used by the selected XML filter.</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="exportbrowse"/>
+ <widget name="currentdocument"/>
+ <widget name="importbrowse"/>
+ <widget name="recentfile"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/warnpdfdialog.ui b/filter/uiconfig/ui/warnpdfdialog.ui
new file mode 100644
index 000000000..21b455f00
--- /dev/null
+++ b/filter/uiconfig/ui/warnpdfdialog.ui
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore1">
+ <columns>
+ <!-- column-name image -->
+ <column type="GdkPixbuf"/>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkMessageDialog" id="WarnPDFDialog">
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="title" translatable="yes" context="warnpdfdialog|WarnPDFDialog">Problems During PDF Export</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="type-hint">dialog</property>
+ <property name="skip-taskbar-hint">True</property>
+ <property name="message-type">warning</property>
+ <property name="buttons">ok</property>
+ <property name="text" translatable="yes" context="warnpdfdialog|WarnPDFDialog">During PDF export the following problems occurred:</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="messagedialog-vbox">
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="messagedialog-action_area">
+ <property name="can-focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=2 n-rows=1 -->
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="column-spacing">12</property>
+ <property name="column-homogeneous">True</property>
+ <child>
+ <object class="GtkLabel" id="message">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="wrap">True</property>
+ <property name="width-chars">30</property>
+ <property name="max-width-chars">30</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkTreeView" id="errors">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore1</property>
+ <property name="headers-visible">False</property>
+ <property name="headers-clickable">False</property>
+ <property name="search-column">1</property>
+ <property name="show-expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="treeview-selection1"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn1">
+ <child>
+ <object class="GtkCellRendererPixbuf" id="cellrenderertext1"/>
+ <attributes>
+ <attribute name="pixbuf">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn2">
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderertext2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/xmlfiltersettings.ui b/filter/uiconfig/ui/xmlfiltersettings.ui
new file mode 100644
index 000000000..f6fa60bc9
--- /dev/null
+++ b/filter/uiconfig/ui/xmlfiltersettings.ui
@@ -0,0 +1,294 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkTreeStore" id="liststore3">
+ <columns>
+ <!-- column-name text -->
+ <column type="gchararray"/>
+ <!-- column-name text2 -->
+ <column type="gchararray"/>
+ <!-- column-name id -->
+ <column type="gchararray"/>
+ </columns>
+ </object>
+ <object class="GtkDialog" id="XMLFilterSettingsDialog">
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="title" translatable="yes" context="xmlfiltersettings|XMLFilterSettingsDialog">XML Filter Settings</property>
+ <property name="resizable">False</property>
+ <property name="default-width">0</property>
+ <property name="default-height">0</property>
+ <property name="type-hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can-focus">False</property>
+ <property name="layout-style">end</property>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="help-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|help">Displays the help page for this dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="close">
+ <property name="label" translatable="yes" context="stock">_Close</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="can-default">True</property>
+ <property name="has-default">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="close-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|close">Closes the dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="spacing">12</property>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow-type">in</property>
+ <child>
+ <object class="GtkTreeView" id="filterlist">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="model">liststore3</property>
+ <property name="search-column">0</property>
+ <property name="show-expanders">False</property>
+ <child internal-child="selection">
+ <object class="GtkTreeSelection" id="Macro Library List-selection2"/>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn3">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="xmlfiltersettings|header_name">Name</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer1"/>
+ <attributes>
+ <attribute name="text">0</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkTreeViewColumn" id="treeviewcolumn4">
+ <property name="resizable">True</property>
+ <property name="spacing">6</property>
+ <property name="title" translatable="yes" context="xmlfiltersettings|header_type">Type</property>
+ <child>
+ <object class="GtkCellRendererText" id="cellrenderer2"/>
+ <attributes>
+ <attribute name="text">1</attribute>
+ </attributes>
+ </child>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="filterlist-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|filterlist">Select one or more filters, then click one of the buttons.</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox" id="buttonbox1">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">3</property>
+ <property name="homogeneous">True</property>
+ <property name="layout-style">start</property>
+ <child>
+ <object class="GtkButton" id="new">
+ <property name="label" translatable="yes" context="xmlfiltersettings|new">_New...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="new-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|new">Opens a dialog for creating a new filter.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="edit">
+ <property name="label" translatable="yes" context="xmlfiltersettings|edit">_Edit...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="edit-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|edit">Opens a dialog for editing the selected filter.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="test">
+ <property name="label" translatable="yes" context="xmlfiltersettings|test">_Test XSLTs...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="test-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|test">Opens a dialog for testing the selected filter.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="delete">
+ <property name="label" translatable="yes" context="xmlfiltersettings|delete">_Delete...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="delete-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|delete">Deletes the selected file after you confirm the dialog that follows.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="save">
+ <property name="label" translatable="yes" context="xmlfiltersettings|save">_Save as Package...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="save-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|save">Displays a Save as dialog to save the selected file as an XSLT filter package (*.jar).</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="open">
+ <property name="label" translatable="yes" context="xmlfiltersettings|open">_Open Package...</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="open-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|open">Displays an Open dialog to open a filter from an XSLT filter package (*.jar).</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-11">help</action-widget>
+ <action-widget response="-7">close</action-widget>
+ </action-widgets>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="XMLFilterSettingsDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltersettings|extended_tip|XMLFilterSettingsDialog">Opens the XML Filter Settings dialog, where you can create, edit, delete, and test filters to import and to export XML files.</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/xmlfiltertabpagegeneral.ui b/filter/uiconfig/ui/xmlfiltertabpagegeneral.ui
new file mode 100644
index 000000000..df227613a
--- /dev/null
+++ b/filter/uiconfig/ui/xmlfiltertabpagegeneral.ui
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="XmlFilterTabPageGeneral">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="spacing">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagegeneral|label2">_Filter name:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">filtername</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagegeneral|label3">_Application:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">application</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagegeneral|label4">_Name of file type:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">interfacename</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagegeneral|label5">File _extension:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">extension</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagegeneral|label6">Comment_s:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">description</property>
+ <property name="xalign">1</property>
+ <property name="yalign">0</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="filtername">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">start</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">38</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="filtername-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagegeneral|extended_tip|filtername">Enter the name that you want to display in the list box of the XML Filter Settings dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="extension">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">start</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">6</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="extension-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagegeneral|extended_tip|extension">Enter the file extension to use when you open a file without specifying a filter. The file extension is used to determine which filter to use.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="interfacename">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="halign">start</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">38</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="interfacename-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagegeneral|extended_tip|interfacename">Enter the name that you want to display in the File type box in file dialogs.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="application">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="halign">start</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry" id="comboboxtext-entry">
+ <property name="can_focus">True</property>
+ <property name="truncate-multiline">True</property>
+ <property name="activates_default">True</property>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="application-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagegeneral|extended_tip|application">Select the application that you want to use with the filter.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkTextView" id="description">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="description-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagegeneral|extended_tip|description">Enter a comment (optional).</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">4</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="XmlFilterTabPageGeneral-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagegeneral|extended_tip|XmlFilterTabPageGeneral">Enter or edit general information for an XML filter.</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <widgets>
+ <widget name="filtername"/>
+ <widget name="interfacename"/>
+ <widget name="application"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/xmlfiltertabpagetransformation.ui b/filter/uiconfig/ui/xmlfiltertabpagetransformation.ui
new file mode 100644
index 000000000..7f5bbbc09
--- /dev/null
+++ b/filter/uiconfig/ui/xmlfiltertabpagetransformation.ui
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.36.0 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkBox" id="XmlFilterTabPageTransformation">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">6</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid" id="grid1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">12</property>
+ <child>
+ <object class="GtkLabel" id="label2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagetransformation|label2">_DocType:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">doc</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="doc">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="activates_default">True</property>
+ <property name="width_chars">32</property>
+ <property name="truncate-multiline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="doc-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagetransformation|extended_tip|doc">Enter the DOCTYPE of the XML file.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagetransformation|label4">_XSLT for export:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">xsltexport</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="browseexport">
+ <property name="label" translatable="yes" context="xmlfiltertabpagetransformation|browseexport">Brows_e...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="browseexport-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagetransformation|extended_tip|browseexport">Opens a file selection dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label5">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagetransformation|label5">XSLT _for import:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">xsltimport</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="browseimport">
+ <property name="label" translatable="yes" context="xmlfiltertabpagetransformation|browseimport">B_rowse...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="browseimport-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagetransformation|extended_tip|browseimport">Opens a file selection dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label6">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes" context="xmlfiltertabpagetransformation|label6">Template for _import:</property>
+ <property name="use_underline">True</property>
+ <property name="mnemonic_widget">tempimport</property>
+ <property name="xalign">1</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="browsetemp">
+ <property name="label" translatable="yes" context="xmlfiltertabpagetransformation|browsetemp">Browse...</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="browsetemp-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagetransformation|extended_tip|browsetemp">Opens a file selection dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">2</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="xsltexport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ <property name="truncate-multiline">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="xsltexport-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagetransformation|extended_tip|xsltexport">If this is an export filter, enter the file name of the XSLT stylesheet that you want to use for exporting.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="xsltimport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ <property name="truncate-multiline">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="xsltimport-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagetransformation|extended_tip|xsltimport">If this is an import filter, enter the file name of the XSLT stylesheet that you want to use for importing.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkComboBoxText" id="tempimport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="hexpand">True</property>
+ <property name="has_entry">True</property>
+ <child internal-child="entry">
+ <object class="GtkEntry">
+ <property name="truncate-multiline">True</property>
+ <property name="can_focus">True</property>
+ </object>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="tempimport-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagetransformation|extended_tip|tempimport">Enter the name of the template that you want to use for importing. In the template, styles are defined to display XML tags.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">3</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="filtercb">
+ <property name="label" translatable="yes" context="xmlfiltertabpagetransformation|filtercb">The filter needs XSLT 2.0 processor</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="XmlFilterTabPageTransformation-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xmlfiltertabpagetransformation|extended_tip|XmlFilterTabPageTransformation">Enter or edit file information for an XML filter.</property>
+ </object>
+ </child>
+ </object>
+ <object class="GtkSizeGroup" id="sizegroup1">
+ <property name="mode">both</property>
+ <widgets>
+ <widget name="XmlFilterTabPageTransformation"/>
+ </widgets>
+ </object>
+</interface>
diff --git a/filter/uiconfig/ui/xsltfilterdialog.ui b/filter/uiconfig/ui/xsltfilterdialog.ui
new file mode 100644
index 000000000..2da5c670d
--- /dev/null
+++ b/filter/uiconfig/ui/xsltfilterdialog.ui
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.38.2 -->
+<interface domain="flt">
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkDialog" id="XSLTFilterDialog">
+ <property name="can-focus">False</property>
+ <property name="border-width">6</property>
+ <property name="title" translatable="yes" context="xsltfilterdialog|XSLTFilterDialog">XML Filter: %s</property>
+ <property name="resizable">False</property>
+ <property name="modal">True</property>
+ <property name="default-width">0</property>
+ <property name="default-height">0</property>
+ <property name="type-hint">dialog</property>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog-vbox1">
+ <property name="can-focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">12</property>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can-focus">False</property>
+ <property name="layout-style">end</property>
+ <child>
+ <object class="GtkButton" id="ok">
+ <property name="label" translatable="yes" context="stock">_OK</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="can-default">True</property>
+ <property name="has-default">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="cancel">
+ <property name="label" translatable="yes" context="stock">_Cancel</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="help">
+ <property name="label" translatable="yes" context="stock">_Help</property>
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="receives-default">True</property>
+ <property name="use-underline">True</property>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="help-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xsltfilterdialog|extended_tip|help">Displays the help page for this dialog.</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ <property name="secondary">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="pack-type">end</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="tabcontrol">
+ <property name="visible">True</property>
+ <property name="can-focus">True</property>
+ <property name="hexpand">True</property>
+ <property name="vexpand">True</property>
+ <property name="scrollable">True</property>
+ <property name="enable-popup">True</property>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="general">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="xsltfilterdialog|general">General</property>
+ </object>
+ <packing>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ <child>
+ <!-- n-columns=1 n-rows=1 -->
+ <object class="GtkGrid">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="transformation">
+ <property name="visible">True</property>
+ <property name="can-focus">False</property>
+ <property name="label" translatable="yes" context="xsltfilterdialog|transformation">Transformation</property>
+ </object>
+ <packing>
+ <property name="position">1</property>
+ <property name="tab-fill">False</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="-5">ok</action-widget>
+ <action-widget response="-6">cancel</action-widget>
+ <action-widget response="-11">help</action-widget>
+ </action-widgets>
+ <child internal-child="accessible">
+ <object class="AtkObject" id="XSLTFilterDialog-atkobject">
+ <property name="AtkObject::accessible-description" translatable="yes" context="xsltfilterdialog|extended_tip|XSLTFilterDialog">Opens a dialog for creating a new filter.</property>
+ </object>
+ </child>
+ </object>
+</interface>