function svg_apply_css_funcs($element, &$raw_data) { // Setup functions for using on values. // Note using custom versions of svg-*-gradient(). static $functions; if (!$functions) { $functions = new \stdClass(); $functions->fill = new Functions(array('svg-linear-gradient' => 'CssCrush\\svg_fn_linear_gradient', 'svg-radial-gradient' => 'CssCrush\\svg_fn_radial_gradient', 'pattern' => 'CssCrush\\svg_fn_pattern')); $functions->generic = new Functions(array_diff_key(Crush::$process->functions->register, $functions->fill->register)); } foreach ($raw_data as $property => &$value) { $value = $functions->generic->apply($value); // Only capturing fills for fill and stoke properties. if ($property === 'fill' || $property === 'stroke') { $value = $functions->fill->apply($value, $element); // If the value is a color with alpha component we split the color // and set the corresponding *-opacity property because Webkit doesn't // support rgba()/hsla() in SVG. if ($components = Color::colorSplit($value)) { list($color, $opacity) = $components; $raw_data[$property] = $color; if ($opacity < 1) { $raw_data += array("{$property}-opacity" => $opacity); } } } } }
function parse_gradient_color_stops(array $color_stop_args) { $offsets = array(); $colors = array(); $offset_patt = '~ +([\\d\\.]+%)$~'; $last_index = count($color_stop_args) - 1; foreach ($color_stop_args as $index => $color_arg) { if (preg_match($offset_patt, $color_arg, $m)) { $offsets[] = floatval($m[1]); $color = preg_replace($offset_patt, '', $color_arg); } else { if ($index === 0) { $offsets[] = 0; } elseif ($index === $last_index) { $offsets[] = 100; } else { $offsets[] = null; } $color = $color_arg; } // For hsla()/rgba() extract alpha component from color values and // convert to hsl()/rgb(). // Webkit doesn't support them for SVG colors. $colors[] = Color::colorSplit($color); } // For unspecified color offsets fill in the blanks. $next_index_not_null = 0; $prev_index_not_null = 0; $n = count($offsets); foreach ($offsets as $index => $offset) { if (!isset($offset)) { // Scan for next non-null offset. for ($i = $index; $i < $n; $i++) { if (isset($offsets[$i])) { $next_index_not_null = $i; break; } } // Get the difference between previous 'not null' offset and the next 'not null' offset. // Divide by the number of null offsets to get a value for padding between them. $padding_increment = ($offsets[$next_index_not_null] - $offsets[$prev_index_not_null]) / ($next_index_not_null - $index + 1); $padding = $padding_increment; for ($i = $index; $i < $n; $i++) { if (isset($offsets[$i])) { break; } // Replace the null offset with the new padded value. $offsets[$i] = $offsets[$prev_index_not_null] + $padding; // Bump the padding for the next null offset. $padding += $padding_increment; } } else { $prev_index_not_null = $index; } } $stops = ''; foreach (array_combine($offsets, $colors) as $offset => $color) { list($color_value, $opacity) = $color; $stop_opacity = $opacity < 1 ? " stop-opacity=\"{$opacity}\"" : ''; $stops .= "<stop offset=\"{$offset}%\" stop-color=\"{$color_value}\"{$stop_opacity}/>"; } return $stops; }