README.md
1# Office Open XML (ooxml) Support
2
3Support for Office Open XML, the office XML-format designed by Microsoft.
4
5## DrawingML Custom shapes and presets
6
7Custom shapes are part of DrawingML and are different to binary ppt
8and VML in older formats.
9The import happens in `oox/source/drawingml`, where they are
10imported as LO's enhanced custom shape's. see
11`offapi/com/sun/star/drawing/CustomShape.idl` and
12`offapi/com/sun/star/drawing/EnhancedCustomShape*.idl`
13Check `CustomShapeProperties::pushToPropSet()` and see
14how custom shape properties are converted.
15
16Preset shapes are custom shapes whose guides and handles
17have been defined in OOXML specification. By specifying
18preset type and the adjustment values, the reset can
19be taken from the shape definition.
20
21example of drawingml preset:
22```xml
23 <a:prstGeom prst="star5">
24 <a:avLst/>
25 </a:prstGeom>
26```
27
28example of drawingml custom shape (equal to star5 preset):
29```xml
30 <avLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
31 <gd name="adj" fmla="val 19098" />
32 <gd name="hf" fmla="val 105146" />
33 <gd name="vf" fmla="val 110557" />
34 </avLst>
35 <gdLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
36 <gd name="a" fmla="pin 0 adj 50000" />
37 <gd name="swd2" fmla="*/ wd2 hf 100000" />
38 <gd name="shd2" fmla="*/ hd2 vf 100000" />
39 <gd name="svc" fmla="*/ vc vf 100000" />
40 <gd name="dx1" fmla="cos swd2 1080000" />
41 <gd name="dx2" fmla="cos swd2 18360000" />
42 <gd name="dy1" fmla="sin shd2 1080000" />
43 <gd name="dy2" fmla="sin shd2 18360000" />
44 <gd name="x1" fmla="+- hc 0 dx1" />
45 <gd name="x2" fmla="+- hc 0 dx2" />
46 <gd name="x3" fmla="+- hc dx2 0" />
47 <gd name="x4" fmla="+- hc dx1 0" />
48 <gd name="y1" fmla="+- svc 0 dy1" />
49 <gd name="y2" fmla="+- svc 0 dy2" />
50 <gd name="iwd2" fmla="*/ swd2 a 50000" />
51 <gd name="ihd2" fmla="*/ shd2 a 50000" />
52 <gd name="sdx1" fmla="cos iwd2 20520000" />
53 <gd name="sdx2" fmla="cos iwd2 3240000" />
54 <gd name="sdy1" fmla="sin ihd2 3240000" />
55 <gd name="sdy2" fmla="sin ihd2 20520000" />
56 <gd name="sx1" fmla="+- hc 0 sdx1" />
57 <gd name="sx2" fmla="+- hc 0 sdx2" />
58 <gd name="sx3" fmla="+- hc sdx2 0" />
59 <gd name="sx4" fmla="+- hc sdx1 0" />
60 <gd name="sy1" fmla="+- svc 0 sdy1" />
61 <gd name="sy2" fmla="+- svc 0 sdy2" />
62 <gd name="sy3" fmla="+- svc ihd2 0" />
63 <gd name="yAdj" fmla="+- svc 0 ihd2" />
64 </gdLst>
65 <ahLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
66 <ahXY gdRefY="adj" minY="0" maxY="50000">
67 <pos x="hc" y="yAdj" />
68 </ahXY>
69 </ahLst>
70 <cxnLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
71 <cxn ang="3cd4">
72 <pos x="hc" y="t" />
73 </cxn>
74 <cxn ang="cd2">
75 <pos x="x1" y="y1" />
76 </cxn>
77 <cxn ang="cd4">
78 <pos x="x2" y="y2" />
79 </cxn>
80 <cxn ang="cd4">
81 <pos x="x3" y="y2" />
82 </cxn>
83 <cxn ang="0">
84 <pos x="x4" y="y1" />
85 </cxn>
86 </cxnLst>
87 <rect l="sx1" t="sy1" r="sx4" b="sy3" xmlns="http://schemas.openxmlformats.org/drawingml/2006/main" />
88 <pathLst xmlns="http://schemas.openxmlformats.org/drawingml/2006/main">
89 <path>
90 <moveTo>
91 <pt x="x1" y="y1" />
92 </moveTo>
93 <lnTo>
94 <pt x="sx2" y="sy1" />
95 </lnTo>
96 <lnTo>
97 <pt x="hc" y="t" />
98 </lnTo>
99 <lnTo>
100 <pt x="sx3" y="sy1" />
101 </lnTo>
102 <lnTo>
103 <pt x="x4" y="y1" />
104 </lnTo>
105 <lnTo>
106 <pt x="sx4" y="sy2" />
107 </lnTo>
108 <lnTo>
109 <pt x="x3" y="y2" />
110 </lnTo>
111 <lnTo>
112 <pt x="hc" y="sy3" />
113 </lnTo>
114 <lnTo>
115 <pt x="x2" y="y2" />
116 </lnTo>
117 <lnTo>
118 <pt x="sx1" y="sy2" />
119 </lnTo>
120 <close />
121 </path>
122 </pathLst>
123```
124
125we needed to extend our custom shapes for missing features and so 5
126new segment commands were added. `G` command for arcto drawingml record
127and `H` `I` `J` `K` commands for darken, darkenless, lighten, lightenless
128records. the commands are save into ODF in special namespace drawooo,
129which is extension not yet in the standard. Thorsten suggested to put
130it in such a namespace and keep original (incomplete) geometry for
131backward compatibility, before we can extend the ODF. that's why you
132will see 2 of them in cases where some of the new commands was
133needed.
134
135In order to convert preset shapes to LO's enhanced custom shape,
136we need to load shape definition of preset shapes. The procedure
137to convert the definition from OOXML spec for LO is documented
138in `oox/source/drawingml/customshapes/README.md`.
139The `oox/source/drawingml/customshapes/generate.sh` script generate pptx
140files for single presets and also for all presets
141`cshape-all.pptx`. The `cshape-all.pptx` file is then loaded into Impress
142build with debug enabled in `oox` and the command line output contains
143information. The generated definition is `oox-drawingml-cs-presets`.
144
145Check `CustomShapeProperties::initializePresetDataMap()` to see how
146generated presets data are loaded into LO.
147While importing presets, we prefix the name with "ooxml-" so
148that we can detect it on export as save it again as preset.
149
150The generated pptx files
151can be used when debugging bugs in custom shapes import/export. also
152the cshape-all.pptx can be used to test the round trips. there's small
153problem with these pptx as they cannot be imported into powerpoint,
154but that can be fixed quickly. when fixed, we can use it to
155test powerpoint odp export and see how complete it is regarding
156custom shapes. OpenXML SDK might help when fixing `cshape-all.pptx`
157
158<https://github.com/OfficeDev/Open-XML-SDK>
159
160Also, "OOXML Viewer VSCode Extension" is a useful tool for debugging
161OOXML documents.
162
163<https://github.com/yuenm18/ooxml-viewer-vscode>
164
165## Export
166Here is how LO's enhanced custom shapes are exported:
167
168* Shape name is `ooxml-*` - they are imported from ooxml, export as is.
169* Denylist - ODF presets that has OOXML equivalent.
170 We convert adjustment values case by case. Microsoft Office
171 is rather strict about adjustment values, either none of them
172 are provided so that default values are taken, or the exact set
173 of handles have to be provided. In some cases we are converting
174 from the preset with less handles to the one with more handles
175 so that default values suitable for the odf one need to be
176 provided.
177* Allowlist - ODF presets that has OOXML equivalent but looks a bit
178different, export them as `PolyPolygon`.
179
180Check Andras Timar's presentation[1] and `ShapeExport::WriteCustomShape()`
181for further detail.
182
183## Future Works
184Because we have to make sure that all the roundtrips
185like PPTX --> ODP --> PPTX work correctly and doesn't lose data.
186the only problematic part is probably saving custom shapes (ie. not
187presets) to PPTX. that part of code predates work on custom shapes
188and is unable to export general custom shapes yet. It will need a bit
189of work as LO has more complex equations than `DrawingML`. other parts
190should work OK, PPTX --> ODP should work and don't lose any
191data. presets should already survive PPTX --> ODP --> PPTX roundtrip
192
193[1] <https://archive.fosdem.org/2016/schedule/event/drawingml/attachments/slides/1184/export/events/attachments/drawingml/slides/1184/andras_timar_fosdem_2016.pdf>
194
README.vars
1Environment variables in oox:
2
3- ppt:
4
5 - OOX_NO_SMARTART_WARNING - don't warn on SmartArts missing their DrawingML fallback
6