2424use PhpOffice \PhpWord \Exception \CopyFileException ;
2525use PhpOffice \PhpWord \Exception \CreateTemporaryFileException ;
2626use PhpOffice \PhpWord \Exception \Exception ;
27+ use PhpOffice \PhpWord \Shared \Converter ;
2728use PhpOffice \PhpWord \Shared \Text ;
2829use PhpOffice \PhpWord \Shared \XMLWriter ;
2930use PhpOffice \PhpWord \Shared \ZipArchive ;
@@ -570,11 +571,28 @@ private function prepareImageAttrs($replaceImage, $varInlineArgs)
570571 $ width = $ this ->chooseImageDimension ($ width , $ varInlineArgs ['width ' ] ?? null , 115 );
571572 $ height = $ this ->chooseImageDimension ($ height , $ varInlineArgs ['height ' ] ?? null , 70 );
572573
573- $ imageData = @getimagesize ($ imgPath );
574- if (!is_array ($ imageData )) {
575- throw new Exception (sprintf ('Invalid image: %s ' , $ imgPath ));
574+ $ mime = mime_content_type ($ imgPath );
575+ if ($ mime !== 'image/svg+xml ' ) {
576+ $ imageData = @getimagesize ($ imgPath );
577+ if (!is_array ($ imageData )) {
578+ throw new Exception (sprintf ('Invalid image: %s ' , $ imgPath ));
579+ }
580+ [$ actualWidth , $ actualHeight , $ imageType ] = $ imageData ;
581+ } else {
582+ $ content = file_get_contents ($ imgPath );
583+ if (!$ content ) {
584+ throw new Exception (sprintf ('Invalid image: %s ' , $ imgPath ));
585+ }
586+ $ svgXml = simplexml_load_string ($ content );
587+ if (!$ svgXml ) {
588+ throw new Exception (sprintf ('Invalid image: %s ' , $ imgPath ));
589+ }
590+ $ svgAttributes = $ svgXml ->attributes ();
591+ $ actualWidth = $ svgAttributes ->width ;
592+ $ actualHeight = $ svgAttributes ->height ;
593+ $ actualWidth = is_numeric ($ actualWidth ) ? $ actualWidth . 'px ' : $ actualWidth ;
594+ $ actualHeight = is_numeric ($ actualHeight ) ? $ actualHeight . 'px ' : $ actualHeight ;
576595 }
577- [$ actualWidth , $ actualHeight , $ imageType ] = $ imageData ;
578596
579597 // fix aspect ratio (by default)
580598 if (null === $ ratio && isset ($ varInlineArgs ['ratio ' ])) {
@@ -586,9 +604,11 @@ private function prepareImageAttrs($replaceImage, $varInlineArgs)
586604
587605 $ imageAttrs = [
588606 'src ' => $ imgPath ,
589- 'mime ' => image_type_to_mime_type ( $ imageType ) ,
607+ 'mime ' => $ mime ,
590608 'width ' => $ width ,
591609 'height ' => $ height ,
610+ 'originalWidth ' => $ actualWidth ,
611+ 'originalHeight ' => $ actualHeight ,
592612 ];
593613
594614 return $ imageAttrs ;
@@ -606,6 +626,7 @@ private function addImageToRelations($partFileName, $rid, $imgPath, $imageMimeTy
606626 'image/png ' => 'png ' ,
607627 'image/bmp ' => 'bmp ' ,
608628 'image/gif ' => 'gif ' ,
629+ 'image/svg+xml ' => 'svg ' ,
609630 ];
610631
611632 // get image embed name
@@ -681,6 +702,48 @@ public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEM
681702 // define templates
682703 // result can be verified via "Open XML SDK 2.5 Productivity Tool" (http://www.microsoft.com/en-us/download/details.aspx?id=30425)
683704 $ imgTpl = '<w:pict><v:shape type="#_x0000_t75" style="width:{WIDTH};height:{HEIGHT}" stroked="f" filled="f"><v:imagedata r:id="{RID}" o:title=""/></v:shape></w:pict> ' ;
705+ // use drawing for svg, see https://www.datypic.com/sc/ooxml/e-w_drawing-1.html
706+ $ svgTpl = '<w:drawing>
707+ <wp:inline distT="0" distB="0" distL="0" distR="0">
708+ <wp:extent cx="{WIDTH}" cy="{HEIGHT}"/>
709+ <wp:effectExtent l="0" t="0" r="0" b="0"/>
710+ <wp:docPr id="{ID}" name="{NAME}"/>
711+ <wp:cNvGraphicFramePr>
712+ <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/>
713+ </wp:cNvGraphicFramePr>
714+ <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
715+ <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture">
716+ <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture">
717+ <pic:nvPicPr>
718+ <pic:cNvPr id="{ID}" name="{NAME}"/>
719+ <pic:cNvPicPr/>
720+ </pic:nvPicPr>
721+ <pic:blipFill>
722+ <a:blip>
723+ <a:extLst>
724+ <a:ext uri="{96DAC541-7B7A-43D3-8B79-37D633B846F1}">
725+ <asvg:svgBlip xmlns:asvg="http://schemas.microsoft.com/office/drawing/2016/SVG/main" r:embed="{RID}"/>
726+ </a:ext>
727+ </a:extLst>
728+ </a:blip>
729+ <a:stretch>
730+ <a:fillRect/>
731+ </a:stretch>
732+ </pic:blipFill>
733+ <pic:spPr>
734+ <a:xfrm>
735+ <a:off x="0" y="0"/>
736+ <a:ext cx="{WIDTH}" cy="{HEIGHT}"/>
737+ </a:xfrm>
738+ <a:prstGeom prst="rect">
739+ <a:avLst/>
740+ </a:prstGeom>
741+ </pic:spPr>
742+ </pic:pic>
743+ </a:graphicData>
744+ </a:graphic>
745+ </wp:inline>
746+ </w:drawing> ' ;
684747
685748 $ i = 0 ;
686749 foreach ($ searchParts as $ partFileName => &$ partContent ) {
@@ -702,7 +765,57 @@ public function setImageValue($search, $replace, $limit = self::MAXIMUM_REPLACEM
702765
703766 // replace preparations
704767 $ this ->addImageToRelations ($ partFileName , $ rid , $ imgPath , $ preparedImageAttrs ['mime ' ]);
705- $ xmlImage = str_replace (['{RID} ' , '{WIDTH} ' , '{HEIGHT} ' ], [$ rid , $ preparedImageAttrs ['width ' ], $ preparedImageAttrs ['height ' ]], $ imgTpl );
768+ if ($ preparedImageAttrs ['mime ' ] !== 'image/svg+xml ' ) {
769+ $ xmlImage = str_replace (['{RID} ' , '{WIDTH} ' , '{HEIGHT} ' ], [$ rid , $ preparedImageAttrs ['width ' ], $ preparedImageAttrs ['height ' ]], $ imgTpl );
770+ } else {
771+ $ width = Converter::cssToEmu ($ preparedImageAttrs ['width ' ]);
772+ $ height = Converter::cssToEmu ($ preparedImageAttrs ['height ' ]);
773+ if ($ width === null ) {
774+ if (preg_match ('/^[+-]?([0-9]+\.?[0-9]*)?(em|ex|%)$/i ' , $ preparedImageAttrs ['width ' ], $ matches )) {
775+ $ size = (float ) ($ matches [1 ]);
776+ $ unit = $ matches [2 ];
777+ switch ($ unit ) {
778+ case 'ex ' :
779+ $ size = $ size * 2 ;
780+
781+ // no break
782+ case 'em ' :
783+ $ width = $ size * 152400 ;
784+
785+ break ;
786+ case '% ' :
787+ $ width = Converter::cssToEmu ($ preparedImageAttrs ['originalWidth ' ]) * $ size ;
788+
789+ break ;
790+ }
791+ } else {
792+ $ width = Converter::cssToEmu ($ preparedImageAttrs ['originalWidth ' ]);
793+ }
794+ }
795+ if ($ height === null ) {
796+ if (preg_match ('/^[+-]?([0-9]+\.?[0-9]*)?(em|ex|%)$/i ' , $ preparedImageAttrs ['height ' ], $ matches )) {
797+ $ size = (float ) ($ matches [1 ]);
798+ $ unit = $ matches [2 ];
799+ switch ($ unit ) {
800+ case 'ex ' :
801+ $ size *= 2 ;
802+
803+ // no break
804+ case 'em ' :
805+ $ height = $ size * 152400 ;
806+
807+ break ;
808+ case '% ' :
809+ $ height = Converter::cssToEmu ($ preparedImageAttrs ['originalHeight ' ]) * $ size ;
810+
811+ break ;
812+ }
813+ } else {
814+ $ height = Converter::cssToEmu ($ preparedImageAttrs ['originalHeight ' ]);
815+ }
816+ }
817+ $ xmlImage = str_replace (['{RID} ' , '{WIDTH} ' , '{HEIGHT} ' , '{ID} ' , '{NAME} ' ], [$ rid , (string ) $ width , (string ) $ height , $ imgIndex , 'graphic ' ], $ svgTpl );
818+ }
706819
707820 // replace variable
708821 $ varNameWithArgsFixed = static ::ensureMacroCompleted ($ varNameWithArgs );
0 commit comments