@@ -2358,8 +2358,8 @@ protected function parseSVGTagENDtext(int $soid): void
23582358 *
23592359 * @param string $parser The XML parser calling the handler.
23602360 * @param string $name Name of the element for which this handler is called.
2361- * @param TSVGAttributes $attribs Associative array with the element's attributes.
2362- * @param array<float> $ctm Current transformation matrix (optional).
2361+ * @param TSVGAttribs $attribs Associative array with the element's attributes.
2362+ * @param TTMatrix $ctm Current transformation matrix (optional).
23632363 *
23642364 * @return void
23652365 *
@@ -2369,7 +2369,7 @@ protected function handleSVGTagStart(
23692369 string $ parser ,
23702370 string $ name ,
23712371 array $ attribs ,
2372- array $ ctm = [],
2372+ array $ ctm = [1 , 0 , 0 , 1 , 0 , 0 ], // identity matrix
23732373 ): void {
23742374 $ name = $ this ->removeTagNamespace ($ name );
23752375
@@ -2378,12 +2378,122 @@ protected function handleSVGTagStart(
23782378 return ;
23792379 }
23802380
2381+ if ($ this ->svgobjs [$ soid ]['clipmode ' ]) {
2382+ $ this ->svgobjs [$ soid ]['clippaths ' ][] = [
2383+ 'name ' => $ name ,
2384+ 'attribs ' => $ attribs ,
2385+ 'tm ' => $ this ->svgobjs [$ soid ]['cliptm ' ],
2386+ ];
2387+ return ;
2388+ }
2389+
2390+ if (
2391+ $ this ->svgobjs [$ soid ]['defsmode ' ]
2392+ && !in_array ($ name , ['clipPath ' , 'linearGradient ' , 'radialGradient ' , 'stop ' ])
2393+ ) {
2394+ if (!isset ($ this ->svgobjs [$ soid ]['clippaths ' ])) {
2395+ $ this ->svgobjs [$ soid ]['clippaths ' ] = [];
2396+ }
2397+
2398+ if (isset ($ attribs ['attr ' ]['id ' ])) {
2399+ $ attribs ['child ' ] = [];
2400+ $ this ->svgobjs [$ soid ]['defs ' ][$ attribs ['attr ' ]['id ' ]] = [
2401+ 'name ' => $ name ,
2402+ 'attr ' => $ attribs ,
2403+ ];
2404+ return ;
2405+ }
2406+
2407+ if (end ($ this ->svgobjs [$ soid ]['defs ' ]) !== false ) {
2408+ $ last_svgdefs_id = key ($ this ->svgobjs [$ soid ]['defs ' ]);
2409+ if (
2410+ !empty ($ this ->svgobjs [$ soid ]['defs ' ][$ last_svgdefs_id ]['attr ' ]['child ' ])
2411+ && is_array ($ this ->svgobjs [$ soid ]['defs ' ][$ last_svgdefs_id ]['attr ' ]['child ' ])
2412+ ) {
2413+ $ attribs ['attr ' ]['id ' ] = 'DF_ ' .
2414+ (count ($ this ->svgobjs [$ soid ]['defs ' ][$ last_svgdefs_id ]['attr ' ]['child ' ]) + 1 );
2415+ $ this ->svgobjs [$ soid ]['defs ' ][$ last_svgdefs_id ]['attr ' ]['child ' ][$ attribs ['attr ' ]['id ' ]] = [
2416+ 'name ' => $ name ,
2417+ 'attr ' => $ attribs ,
2418+ ];
2419+ return ;
2420+ }
2421+ }
2422+
2423+ return ;
2424+ }
2425+
2426+ $ this ->svgobjs [$ soid ]['clipmode ' ] = ($ parser == 'clip-path ' );
2427+
2428+ // process style
2429+
2430+ $ prev_svgstyle = $ this ->svgobjs [$ soid ]['styles ' ][max (0 , (count ($ this ->svgobjs [$ soid ]['styles ' ]) - 1 ))];
2431+ $ svgstyle = $ this ->svgobjs [$ soid ]['styles ' ][0 ]; // set default style
2432+
2433+ if (
2434+ $ this ->svgobjs [$ soid ]['clipmode ' ] &&
2435+ !isset ($ attribs ['attr ' ]['fill ' ]) &&
2436+ (!isset ($ attribs ['attr ' ]['style ' ]) ||
2437+ (!preg_match ('/[;\"\s]{1}fill[\s]*:[\s]*([^;\"]*)/si ' , $ attribs ['attr ' ]['style ' ], $ attrval )))
2438+ ) {
2439+ // default fill attribute for clipping
2440+ $ attribs ['attr ' ]['fill ' ] = 'none ' ;
2441+ }
2442+
2443+ if (
2444+ isset ($ attribs ['attr ' ]['style ' ]) &&
2445+ !empty ($ attribs ['attr ' ]['style ' ]) &&
2446+ ($ attribs ['attr ' ]['style ' ][0 ] != '; ' )
2447+ ) {
2448+ // fix style for regular expression
2449+ $ attribs ['attr ' ]['style ' ] = '; ' . $ attribs ['attr ' ]['style ' ];
2450+ }
2451+
2452+ foreach ($ prev_svgstyle as $ key => $ val ) {
2453+ if (in_array ($ key , self ::SVGINHPROP )) {
2454+ // inherit previous value
2455+ $ svgstyle [$ key ] = $ val ;
2456+ }
2457+ if (!empty ($ attribs ['attr ' ][$ key ])) {
2458+ // specific attribute settings
2459+ if ($ attribs ['attr ' ][$ key ] == 'inherit ' ) {
2460+ $ svgstyle [$ key ] = $ val ;
2461+ } else {
2462+ $ svgstyle [$ key ] = $ attribs ['attr ' ][$ key ];
2463+ }
2464+ } elseif (!empty ($ attribs ['attr ' ]['style ' ])) {
2465+ // CSS style syntax
2466+ $ attrval = [];
2467+ if (
2468+ preg_match (
2469+ '/[;\"\s]{1} ' . $ key . '[\s]*:[\s]*([^;\"]*)/si ' ,
2470+ $ attribs ['attr ' ]['style ' ],
2471+ $ attrval
2472+ )
2473+ && isset ($ attrval [1 ])
2474+ ) {
2475+ if ($ attrval [1 ] == 'inherit ' ) {
2476+ $ svgstyle [$ key ] = $ val ;
2477+ } else {
2478+ $ svgstyle [$ key ] = $ attrval [1 ];
2479+ }
2480+ }
2481+ }
2482+ }
2483+
23812484 $ tmx = $ ctm ;
2382- if (empty ($ tmx )) {
2383- $ tmx = [ 1 , 0 , 0 , 1 , 0 , 0 ] ;
2485+ if (! empty ($ attribs [ ' attr ' ][ ' transform ' ] )) {
2486+ $ tmx = $ this -> graph -> getCtmProduct ( $ tmx , $ this -> getSVGTransformMatrix ( $ attribs [ ' attr ' ][ ' transform ' ])) ;
23842487 }
23852488
2386- //@TODO
2489+ $ svgstyle ['transfmatrix ' ] = $ tmx ;
2490+
2491+ $ this ->svgobjs [$ soid ]['textmode ' ]['invisible ' ] = (
2492+ ($ svgstyle ['visibility ' ] == 'hidden ' ) ||
2493+ ($ svgstyle ['visibility ' ] == 'collapse ' ) ||
2494+ ($ svgstyle ['display ' ] == 'none ' ));
2495+
2496+ // process tags
23872497
23882498 match ($ name ) {
23892499 'defs ' => $ this ->parseSVGTagSTARTdefs ($ soid ),
@@ -2407,7 +2517,28 @@ protected function handleSVGTagStart(
24072517 default => null ,
24082518 };
24092519
2410- //@TODO
2520+ // process child elements
2521+
2522+ if (empty ($ attribs ['child ' ])) {
2523+ return ;
2524+ }
2525+
2526+ $ children = $ attribs ['child ' ];
2527+ unset($ attribs ['child ' ]);
2528+
2529+ foreach ($ children as $ child ) {
2530+ if (empty ($ child ['attr ' ]) || !is_array ($ child ['attr ' ]) || !is_string ($ child ['name ' ])) {
2531+ continue ;
2532+ }
2533+ if (empty ($ child ['attr ' ]['closing_tag ' ])) {
2534+ $ this ->handleSVGTagStart ('child-tag ' , $ child ['name ' ], $ child ['attr ' ]); // @phpstan-ignore argument.type
2535+ continue ;
2536+ }
2537+ if (isset ($ child ['attr ' ]['content ' ])) {
2538+ $ this ->svgobjs [$ soid ]['text ' ] = $ child ['attr ' ]['content ' ];
2539+ }
2540+ $ this ->handleSVGTagEnd ('child-tag ' , $ child ['name ' ]);
2541+ }
24112542 }
24122543
24132544 /**
@@ -2438,8 +2569,13 @@ protected function parseSVGTagSTARTclipPath(int $soid, array $tmx = [])
24382569
24392570 $ this ->svgobjs [$ soid ]['clipmode ' ] = true ;
24402571
2441- $ tmx = $ tmx ; // @phpstan-ignore-line
2442- //@TODO
2572+ if (empty ($ this ->svgobjs [$ soid ]['clipid ' ])) {
2573+ $ this ->svgobjs [$ soid ]['clipid ' ] = 'CP_ ' . (count ($ this ->svgobjs [$ soid ]['cliptm ' ]) + 1 );
2574+ }
2575+
2576+ $ cid = $ this ->svgobjs [$ soid ]['clipid ' ];
2577+ $ this ->svgobjs [$ soid ]['clippaths ' ][$ cid ] = [];
2578+ $ this ->svgobjs [$ soid ]['cliptm ' ][$ cid ] = $ tmx ;
24432579 }
24442580
24452581 /**
0 commit comments