Skip to content

Commit d462edc

Browse files
committed
draft handleSVGTagStart function
1 parent 047e974 commit d462edc

File tree

1 file changed

+145
-9
lines changed

1 file changed

+145
-9
lines changed

src/SVG.php

Lines changed: 145 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)