File "Style.php"
Full Path: /home/clickysoft/public_html/jmapi5.clickysoft.net/vendor/phenx/php-svg-lib/src/Svg/Style.php
File size: 18.78 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* @package php-svg-lib
* @link http://github.com/PhenX/php-svg-lib
* @author Fabien Ménager <fabien.menager@gmail.com>
* @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html
*/
namespace Svg;
use Svg\Tag\AbstractTag;
class Style
{
const TYPE_COLOR = 1;
const TYPE_LENGTH = 2;
const TYPE_NAME = 3;
const TYPE_ANGLE = 4;
const TYPE_NUMBER = 5;
private $_document;
private $_parentStyle;
public $color;
public $opacity;
public $display;
public $fill;
public $fillOpacity;
public $fillRule;
public $stroke;
public $strokeOpacity;
public $strokeLinecap;
public $strokeLinejoin;
public $strokeMiterlimit;
public $strokeWidth;
public $strokeDasharray;
public $strokeDashoffset;
public $fontFamily = 'serif';
public $fontSize = 12;
public $fontWeight = 'normal';
public $fontStyle = 'normal';
public $textAnchor = 'start';
public function __construct($document = null) {
if ($document !== null) {
$this->_document = $document;
}
}
protected function getStyleMap()
{
return array(
'color' => array('color', self::TYPE_COLOR),
'opacity' => array('opacity', self::TYPE_NUMBER),
'display' => array('display', self::TYPE_NAME),
'fill' => array('fill', self::TYPE_COLOR),
'fill-opacity' => array('fillOpacity', self::TYPE_NUMBER),
'fill-rule' => array('fillRule', self::TYPE_NAME),
'stroke' => array('stroke', self::TYPE_COLOR),
'stroke-dasharray' => array('strokeDasharray', self::TYPE_NAME),
'stroke-dashoffset' => array('strokeDashoffset', self::TYPE_NUMBER),
'stroke-linecap' => array('strokeLinecap', self::TYPE_NAME),
'stroke-linejoin' => array('strokeLinejoin', self::TYPE_NAME),
'stroke-miterlimit' => array('strokeMiterlimit', self::TYPE_NUMBER),
'stroke-opacity' => array('strokeOpacity', self::TYPE_NUMBER),
'stroke-width' => array('strokeWidth', self::TYPE_NUMBER),
'font-family' => array('fontFamily', self::TYPE_NAME),
'font-size' => array('fontSize', self::TYPE_NUMBER),
'font-weight' => array('fontWeight', self::TYPE_NAME),
'font-style' => array('fontStyle', self::TYPE_NAME),
'text-anchor' => array('textAnchor', self::TYPE_NAME),
);
}
/**
* @param $attributes
*
* @return Style
*/
public function fromAttributes($attributes)
{
$this->fillStyles($attributes);
if (isset($attributes["style"])) {
$styles = self::parseCssStyle($attributes["style"]);
$this->fillStyles($styles);
}
}
public function inherit(AbstractTag $tag) {
$group = $tag->getParentGroup();
if ($group) {
$parent_style = $group->getStyle();
$this->_parentStyle = $parent_style;
foreach ($parent_style as $_key => $_value) {
if ($_value !== null) {
$this->$_key = $_value;
}
}
}
}
public function fromStyleSheets(AbstractTag $tag, $attributes) {
$class = isset($attributes["class"]) ? preg_split('/\s+/', trim($attributes["class"])) : null;
$stylesheets = $tag->getDocument()->getStyleSheets();
$styles = array();
foreach ($stylesheets as $_sc) {
/** @var \Sabberworm\CSS\RuleSet\DeclarationBlock $_decl */
foreach ($_sc->getAllDeclarationBlocks() as $_decl) {
/** @var \Sabberworm\CSS\Property\Selector $_selector */
foreach ($_decl->getSelectors() as $_selector) {
$_selector = $_selector->getSelector();
// Match class name
if ($class !== null) {
foreach ($class as $_class) {
if ($_selector === ".$_class") {
/** @var \Sabberworm\CSS\Rule\Rule $_rule */
foreach ($_decl->getRules() as $_rule) {
$styles[$_rule->getRule()] = $_rule->getValue() . "";
}
break 2;
}
}
}
// Match tag name
if ($_selector === $tag->tagName) {
/** @var \Sabberworm\CSS\Rule\Rule $_rule */
foreach ($_decl->getRules() as $_rule) {
$styles[$_rule->getRule()] = $_rule->getValue() . "";
}
break;
}
}
}
}
$this->fillStyles($styles);
}
protected function fillStyles($styles)
{
$style_map = $this->getStyleMap();
foreach ($style_map as $from => $spec) {
if (isset($styles[$from])) {
list($to, $type) = $spec;
$value = null;
switch ($type) {
case self::TYPE_COLOR:
$value = self::parseColor($styles[$from]);
if ($value === "currentcolor") {
if ($type === "color") {
$value = $this->_parentStyle->color;
} else {
$value = $this->color;
}
}
if (is_array($value) && $value[3] !== 1.0 && array_key_exists("{$from}-opacity", $style_map) === true) {
$styles["{$from}-opacity"] = $value[3];
}
break;
case self::TYPE_NUMBER:
$value = ($styles[$from] === null) ? null : (float)$styles[$from];
break;
default:
$value = $styles[$from];
}
if ($from === "font-family") {
$scheme = \strtolower(parse_url($value, PHP_URL_SCHEME) ?: "");
if (
$scheme === "phar" || \strtolower(\substr($value, 0, 7)) === "phar://"
|| ($this->_document !== null && $this->_document->allowExternalReferences === false && $scheme !== "data")
) {
continue;
}
}
if ($value !== null) {
$this->$to = $value;
}
}
}
}
static function parseColor($color)
{
$color = strtolower(trim($color));
$parts = preg_split('/[^,]\s+/', $color, 2);
if (count($parts) == 2) {
$color = $parts[1];
} else {
$color = $parts[0];
}
if ($color === "none") {
return "none";
}
if ($color === "currentcolor") {
return "currentcolor";
}
if ($color === "transparent") {
return [0.0, 0.0, 0.0, 0.0];
}
// SVG color name
if (isset(self::$colorNames[$color])) {
return self::parseHexColor(self::$colorNames[$color]);
}
// Hex color
if ($color[0] === "#") {
return self::parseHexColor($color);
}
// RGB color
if (strpos($color, "rgb") !== false) {
return self::getQuad($color);
}
// HSL color
if (strpos($color, "hsl") !== false) {
$quad = self::getQuad($color, true);
if ($quad == null) {
return null;
}
list($h, $s, $l, $a) = $quad;
$r = $l;
$g = $l;
$b = $l;
$v = ($l <= 0.5) ? ($l * (1.0 + $s)) : ($l + $s - $l * $s);
if ($v > 0) {
$m = $l + $l - $v;
$sv = ($v - $m) / $v;
$h *= 6.0;
$sextant = floor($h);
$fract = $h - $sextant;
$vsf = $v * $sv * $fract;
$mid1 = $m + $vsf;
$mid2 = $v - $vsf;
switch ($sextant) {
case 0:
$r = $v;
$g = $mid1;
$b = $m;
break;
case 1:
$r = $mid2;
$g = $v;
$b = $m;
break;
case 2:
$r = $m;
$g = $v;
$b = $mid1;
break;
case 3:
$r = $m;
$g = $mid2;
$b = $v;
break;
case 4:
$r = $mid1;
$g = $m;
$b = $v;
break;
case 5:
$r = $v;
$g = $m;
$b = $mid2;
break;
}
}
$a = $a * 255;
return array(
$r * 255.0,
$g * 255.0,
$b * 255.0,
$a
);
}
// Gradient
if (strpos($color, "url(#") !== false) {
$i = strpos($color, "(");
$j = strpos($color, ")");
// Bad url format
if ($i === false || $j === false) {
return null;
}
//FIXME: gradients not supported?
return null; // trim(substr($color, $i + 1, $j - $i - 1));
}
return null;
}
static function getQuad($color, $percent = false) {
$i = strpos($color, "(");
$j = strpos($color, ")");
// Bad color value
if ($i === false || $j === false) {
return null;
}
$quad = preg_split("/\\s*[,\\/]\\s*/", trim(substr($color, $i + 1, $j - $i - 1)));
if (!isset($quad[3])) {
$quad[3] = "1";
}
if (count($quad) != 3 && count($quad) != 4) {
return null;
}
foreach (array_keys($quad) as $c) {
$quad[$c] = trim($quad[$c]);
if ($percent) {
if ($quad[$c][strlen($quad[$c]) - 1] === "%") {
$quad[$c] = floatval($quad[$c]) / 100;
} else {
$quad[$c] = floatval($quad[$c]) / 255;
}
} else {
if ($quad[$c][strlen($quad[$c]) - 1] === "%") {
$quad[$c] = floatval($quad[$c]) * 2.55;
} else {
$quad[$c] = floatval($quad[$c]);
}
}
}
return $quad;
}
static function parseHexColor($hex)
{
$c = array(0.0, 0.0, 0.0, 1.0);
// #FFFFFF
if (isset($hex[6])) {
$c[0] = hexdec(substr($hex, 1, 2));
$c[1] = hexdec(substr($hex, 3, 2));
$c[2] = hexdec(substr($hex, 5, 2));
if (isset($hex[7])) {
$alpha = substr($hex, 7, 2);
if (ctype_xdigit($alpha)) {
$c[3] = round(hexdec($alpha)/255, 2);
}
}
} else {
$c[0] = hexdec($hex[1] . $hex[1]);
$c[1] = hexdec($hex[2] . $hex[2]);
$c[2] = hexdec($hex[3] . $hex[3]);
if (isset($hex[4])) {
if (ctype_xdigit($hex[4])) {
$c[3] = round(hexdec($hex[4] . $hex[4])/255, 2);
}
}
}
return $c;
}
/**
* Simple CSS parser
*
* @param $style
*
* @return array
*/
static function parseCssStyle($style)
{
$matches = array();
preg_match_all("/([a-z-]+)\\s*:\\s*([^;$]+)/si", $style, $matches, PREG_SET_ORDER);
$styles = array();
foreach ($matches as $match) {
$styles[$match[1]] = $match[2];
}
return $styles;
}
static $colorNames = array(
'antiquewhite' => '#FAEBD7',
'aqua' => '#00FFFF',
'aquamarine' => '#7FFFD4',
'beige' => '#F5F5DC',
'black' => '#000000',
'blue' => '#0000FF',
'brown' => '#A52A2A',
'cadetblue' => '#5F9EA0',
'chocolate' => '#D2691E',
'cornflowerblue' => '#6495ED',
'crimson' => '#DC143C',
'darkblue' => '#00008B',
'darkgoldenrod' => '#B8860B',
'darkgreen' => '#006400',
'darkmagenta' => '#8B008B',
'darkorange' => '#FF8C00',
'darkred' => '#8B0000',
'darkseagreen' => '#8FBC8F',
'darkslategray' => '#2F4F4F',
'darkviolet' => '#9400D3',
'deepskyblue' => '#00BFFF',
'dodgerblue' => '#1E90FF',
'firebrick' => '#B22222',
'forestgreen' => '#228B22',
'fuchsia' => '#FF00FF',
'gainsboro' => '#DCDCDC',
'gold' => '#FFD700',
'gray' => '#808080',
'green' => '#008000',
'greenyellow' => '#ADFF2F',
'hotpink' => '#FF69B4',
'indigo' => '#4B0082',
'khaki' => '#F0E68C',
'lavenderblush' => '#FFF0F5',
'lemonchiffon' => '#FFFACD',
'lightcoral' => '#F08080',
'lightgoldenrodyellow' => '#FAFAD2',
'lightgreen' => '#90EE90',
'lightsalmon' => '#FFA07A',
'lightskyblue' => '#87CEFA',
'lightslategray' => '#778899',
'lightyellow' => '#FFFFE0',
'lime' => '#00FF00',
'limegreen' => '#32CD32',
'magenta' => '#FF00FF',
'maroon' => '#800000',
'mediumaquamarine' => '#66CDAA',
'mediumorchid' => '#BA55D3',
'mediumseagreen' => '#3CB371',
'mediumspringgreen' => '#00FA9A',
'mediumvioletred' => '#C71585',
'midnightblue' => '#191970',
'mintcream' => '#F5FFFA',
'moccasin' => '#FFE4B5',
'navy' => '#000080',
'olive' => '#808000',
'orange' => '#FFA500',
'orchid' => '#DA70D6',
'palegreen' => '#98FB98',
'palevioletred' => '#D87093',
'peachpuff' => '#FFDAB9',
'pink' => '#FFC0CB',
'powderblue' => '#B0E0E6',
'purple' => '#800080',
'red' => '#FF0000',
'royalblue' => '#4169E1',
'salmon' => '#FA8072',
'seagreen' => '#2E8B57',
'sienna' => '#A0522D',
'silver' => '#C0C0C0',
'skyblue' => '#87CEEB',
'slategray' => '#708090',
'springgreen' => '#00FF7F',
'steelblue' => '#4682B4',
'tan' => '#D2B48C',
'teal' => '#008080',
'thistle' => '#D8BFD8',
'turquoise' => '#40E0D0',
'violetred' => '#D02090',
'white' => '#FFFFFF',
'yellow' => '#FFFF00',
'aliceblue' => '#f0f8ff',
'azure' => '#f0ffff',
'bisque' => '#ffe4c4',
'blanchedalmond' => '#ffebcd',
'blueviolet' => '#8a2be2',
'burlywood' => '#deb887',
'chartreuse' => '#7fff00',
'coral' => '#ff7f50',
'cornsilk' => '#fff8dc',
'cyan' => '#00ffff',
'darkcyan' => '#008b8b',
'darkgray' => '#a9a9a9',
'darkgrey' => '#a9a9a9',
'darkkhaki' => '#bdb76b',
'darkolivegreen' => '#556b2f',
'darkorchid' => '#9932cc',
'darksalmon' => '#e9967a',
'darkslateblue' => '#483d8b',
'darkslategrey' => '#2f4f4f',
'darkturquoise' => '#00ced1',
'deeppink' => '#ff1493',
'dimgray' => '#696969',
'dimgrey' => '#696969',
'floralwhite' => '#fffaf0',
'ghostwhite' => '#f8f8ff',
'goldenrod' => '#daa520',
'grey' => '#808080',
'honeydew' => '#f0fff0',
'indianred' => '#cd5c5c',
'ivory' => '#fffff0',
'lavender' => '#e6e6fa',
'lawngreen' => '#7cfc00',
'lightblue' => '#add8e6',
'lightcyan' => '#e0ffff',
'lightgray' => '#d3d3d3',
'lightgrey' => '#d3d3d3',
'lightpink' => '#ffb6c1',
'lightseagreen' => '#20b2aa',
'lightslategrey' => '#778899',
'lightsteelblue' => '#b0c4de',
'linen' => '#faf0e6',
'mediumblue' => '#0000cd',
'mediumpurple' => '#9370db',
'mediumslateblue' => '#7b68ee',
'mediumturquoise' => '#48d1cc',
'mistyrose' => '#ffe4e1',
'navajowhite' => '#ffdead',
'oldlace' => '#fdf5e6',
'olivedrab' => '#6b8e23',
'orangered' => '#ff4500',
'palegoldenrod' => '#eee8aa',
'paleturquoise' => '#afeeee',
'papayawhip' => '#ffefd5',
'peru' => '#cd853f',
'plum' => '#dda0dd',
'rosybrown' => '#bc8f8f',
'saddlebrown' => '#8b4513',
'sandybrown' => '#f4a460',
'seashell' => '#fff5ee',
'slateblue' => '#6a5acd',
'slategrey' => '#708090',
'snow' => '#fffafa',
'tomato' => '#ff6347',
'violet' => '#ee82ee',
'wheat' => '#f5deb3',
'whitesmoke' => '#f5f5f5',
'yellowgreen' => '#9acd32',
);
}