@@ -42,6 +42,12 @@ public function write(): void
4242 if (!$ element instanceof ImageElement) {
4343 return ;
4444 }
45+ $ ext = strtolower (pathinfo ($ element ->getSource (), PATHINFO_EXTENSION ));
46+ if ($ ext === 'svg ' ) {
47+ $ this ->writeSvgDrawing ($ xmlWriter , $ element );
48+
49+ return ;
50+ }
4551
4652 if ($ element ->isWatermark ()) {
4753 $ this ->writeWatermark ($ xmlWriter , $ element );
@@ -127,4 +133,136 @@ private function writeWatermark(XMLWriter $xmlWriter, ImageElement $element): vo
127133 $ xmlWriter ->endElement (); // w:p
128134 }
129135 }
136+
137+ private function writeSvgDrawing (XMLWriter $ xmlWriter , ImageElement $ element ): void
138+ {
139+ $ rId = $ element ->getRelationId () + ($ element ->isInSection () ? 6 : 0 );
140+
141+ $ style = $ element ->getStyle ();
142+ // dimensions px, fallback sur getSvgDimensions()
143+ $ pxW = $ style ->getWidth () ?: 0 ;
144+ $ pxH = $ style ->getHeight () ?: 0 ;
145+ if ($ pxW <= 0 || $ pxH <= 0 ) {
146+ [$ pxW , $ pxH ] = $ element ->getSvgDimensions ($ element ->getSource ());
147+ }
148+ $ cx = \PhpOffice \PhpWord \Shared \Drawing::pixelsToEmu ($ pxW );
149+ $ cy = \PhpOffice \PhpWord \Shared \Drawing::pixelsToEmu ($ pxH );
150+
151+ // <w:p> + align
152+ if (!$ this ->withoutP ) {
153+ $ xmlWriter ->startElement ('w:p ' );
154+ (new ImageStyleWriter ($ xmlWriter , $ style ))->writeAlignment ();
155+ }
156+ // <w:r>
157+ $ xmlWriter ->startElement ('w:r ' );
158+ // <w:drawing>
159+ $ xmlWriter ->startElement ('w:drawing ' );
160+
161+ // <wp:inline> avec déclarations xmlns comme python-docx-oss
162+ $ xmlWriter ->startElement ('wp:inline ' );
163+ $ xmlWriter ->writeAttribute ('xmlns:a ' , 'http://schemas.openxmlformats.org/drawingml/2006/main ' );
164+ $ xmlWriter ->writeAttribute ('xmlns:pic ' , 'http://schemas.openxmlformats.org/drawingml/2006/picture ' );
165+ $ xmlWriter ->writeAttribute ('xmlns:asvg ' , 'http://schemas.microsoft.com/office/drawing/2016/SVG/main ' );
166+
167+ // <wp:extent>
168+ $ xmlWriter ->startElement ('wp:extent ' );
169+ $ xmlWriter ->writeAttribute ('cx ' , (string ) $ cx );
170+ $ xmlWriter ->writeAttribute ('cy ' , (string ) $ cy );
171+ $ xmlWriter ->endElement ();
172+
173+ // <wp:docPr>
174+ $ xmlWriter ->startElement ('wp:docPr ' );
175+ $ xmlWriter ->writeAttribute ('id ' , '1 ' );
176+ $ xmlWriter ->writeAttribute ('name ' , 'Picture 1 ' );
177+ $ xmlWriter ->endElement ();
178+
179+ // <wp:cNvGraphicFramePr>
180+ $ xmlWriter ->startElement ('wp:cNvGraphicFramePr ' );
181+ $ xmlWriter ->startElement ('a:graphicFrameLocks ' );
182+ $ xmlWriter ->writeAttribute ('noChangeAspect ' , '1 ' );
183+ $ xmlWriter ->endElement ();
184+ $ xmlWriter ->endElement ();
185+
186+ // <a:graphic>
187+ $ xmlWriter ->startElement ('a:graphic ' );
188+ // <a:graphicData uri=".../picture">
189+ $ xmlWriter ->startElement ('a:graphicData ' );
190+ $ xmlWriter ->writeAttribute (
191+ 'uri ' ,
192+ 'http://schemas.openxmlformats.org/drawingml/2006/picture '
193+ );
194+
195+ // <pic:pic>
196+ $ xmlWriter ->startElement ('pic:pic ' );
197+
198+ // <pic:nvPicPr>
199+ $ xmlWriter ->startElement ('pic:nvPicPr ' );
200+ $ xmlWriter ->startElement ('pic:cNvPr ' );
201+ $ xmlWriter ->writeAttribute ('id ' , '0 ' );
202+ $ xmlWriter ->writeAttribute ('name ' , basename ($ element ->getSource ()));
203+ $ xmlWriter ->endElement ();
204+ $ xmlWriter ->startElement ('pic:cNvPicPr ' );
205+ $ xmlWriter ->endElement ();
206+ $ xmlWriter ->endElement ();
207+
208+ // <pic:blipFill>
209+ $ xmlWriter ->startElement ('pic:blipFill ' );
210+ $ xmlWriter ->startElement ('a:blip ' );
211+ // uniquement extLst avec svgBlip
212+ $ xmlWriter ->startElement ('a:extLst ' );
213+ $ xmlWriter ->startElement ('a:ext ' );
214+ $ xmlWriter ->writeAttribute (
215+ 'uri ' ,
216+ '{96DAC541-7B7A-43D3-8B79-37D633B846F1} '
217+ );
218+ $ xmlWriter ->startElement ('asvg:svgBlip ' );
219+ $ xmlWriter ->writeAttribute (
220+ 'r:embed ' ,
221+ 'rId ' . $ rId
222+ );
223+ $ xmlWriter ->endElement (); // asvg:svgBlip
224+ $ xmlWriter ->endElement (); // a:ext
225+ $ xmlWriter ->endElement (); // a:extLst
226+ $ xmlWriter ->endElement (); // a:blip
227+
228+ // <a:stretch><a:fillRect/>
229+ $ xmlWriter ->startElement ('a:stretch ' );
230+ $ xmlWriter ->startElement ('a:fillRect ' );
231+ $ xmlWriter ->endElement ();
232+ $ xmlWriter ->endElement ();
233+
234+ $ xmlWriter ->endElement (); // pic:blipFill
235+
236+ // <pic:spPr>
237+ $ xmlWriter ->startElement ('pic:spPr ' );
238+ $ xmlWriter ->startElement ('a:xfrm ' );
239+ $ xmlWriter ->startElement ('a:off ' );
240+ $ xmlWriter ->writeAttribute ('x ' , '0 ' );
241+ $ xmlWriter ->writeAttribute ('y ' , '0 ' );
242+ $ xmlWriter ->endElement ();
243+ $ xmlWriter ->startElement ('a:ext ' );
244+ $ xmlWriter ->writeAttribute ('cx ' , (string ) $ cx );
245+ $ xmlWriter ->writeAttribute ('cy ' , (string ) $ cy );
246+ $ xmlWriter ->endElement ();
247+ $ xmlWriter ->endElement ();
248+ $ xmlWriter ->startElement ('a:prstGeom ' );
249+ $ xmlWriter ->writeAttribute ('prst ' , 'rect ' );
250+ $ xmlWriter ->endElement ();
251+ $ xmlWriter ->endElement (); // pic:spPr
252+
253+ $ xmlWriter ->endElement (); // pic:pic
254+
255+ $ xmlWriter ->endElement (); // a:graphicData
256+ $ xmlWriter ->endElement (); // a:graphic
257+
258+ $ xmlWriter ->endElement (); // wp:inline
259+
260+ $ xmlWriter ->endElement (); // w:drawing
261+ $ xmlWriter ->endElement (); // w:r
262+
263+ // </w:p>
264+ if (!$ this ->withoutP ) {
265+ $ xmlWriter ->endElement ();
266+ }
267+ }
130268}
0 commit comments