summaryrefslogtreecommitdiffstats
path: root/filter/source
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/source
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/source')
-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
647 files changed, 171094 insertions, 0 deletions
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>