diff --git a/composer.lock b/composer.lock index 702f993..baf8e75 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "dompdf/dompdf", - "version": "v2.0.4", + "version": "v2.0.7", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f" + "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/ab0123052b42ad0867348f25df8c228f1ece8f14", + "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14", "shasum": "" }, "require": { @@ -25,7 +25,7 @@ "ext-mbstring": "*", "masterminds/html5": "^2.0", "phenx/php-font-lib": ">=0.5.4 <1.0.0", - "phenx/php-svg-lib": ">=0.3.3 <1.0.0", + "phenx/php-svg-lib": ">=0.5.2 <1.0.0", "php": "^7.1 || ^8.0" }, "require-dev": { @@ -64,22 +64,22 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v2.0.4" + "source": "https://github.com/dompdf/dompdf/tree/v2.0.7" }, - "time": "2023-12-12T20:19:39+00:00" + "time": "2024-04-15T12:40:33+00:00" }, { "name": "masterminds/html5", - "version": "2.8.1", + "version": "2.9.0", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", "shasum": "" }, "require": { @@ -87,7 +87,7 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" }, "type": "library", "extra": { @@ -131,29 +131,29 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" }, - "time": "2023-05-10T11:58:31+00:00" + "time": "2024-03-31T07:05:07+00:00" }, { "name": "phenx/php-font-lib", - "version": "0.5.4", + "version": "0.5.6", "source": { "type": "git", "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4" + "reference": "a1681e9793040740a405ac5b189275059e2a9863" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/dd448ad1ce34c63d09baccd05415e361300c35b4", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a1681e9793040740a405ac5b189275059e2a9863", + "reference": "a1681e9793040740a405ac5b189275059e2a9863", "shasum": "" }, "require": { "ext-mbstring": "*" }, "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5" + "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" }, "type": "library", "autoload": { @@ -163,7 +163,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "LGPL-2.1-or-later" ], "authors": [ { @@ -175,22 +175,22 @@ "homepage": "https://github.com/PhenX/php-font-lib", "support": { "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/0.5.4" + "source": "https://github.com/dompdf/php-font-lib/tree/0.5.6" }, - "time": "2021-12-17T19:44:54+00:00" + "time": "2024-01-29T14:45:26+00:00" }, { "name": "phenx/php-svg-lib", - "version": "0.5.2", + "version": "0.5.4", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "732faa9fb4309221e2bd9b2fda5de44f947133aa" + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/732faa9fb4309221e2bd9b2fda5de44f947133aa", - "reference": "732faa9fb4309221e2bd9b2fda5de44f947133aa", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691", + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691", "shasum": "" }, "require": { @@ -209,7 +209,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "LGPL-3.0-or-later" ], "authors": [ { @@ -221,9 +221,9 @@ "homepage": "https://github.com/PhenX/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.2" + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4" }, - "time": "2024-02-07T12:49:40+00:00" + "time": "2024-04-08T12:52:34+00:00" }, { "name": "sabberworm/php-css-parser", diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index a72151c..7824d8f 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -45,35 +45,34 @@ class ClassLoader /** @var \Closure(string):void */ private static $includeFile; - /** @var ?string */ + /** @var string|null */ private $vendorDir; // PSR-4 /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixLengthsPsr4 = array(); /** - * @var array[] - * @psalm-var array> + * @var array> */ private $prefixDirsPsr4 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr4 = array(); // PSR-0 /** - * @var array[] - * @psalm-var array> + * List of PSR-0 prefixes + * + * Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2'))) + * + * @var array>> */ private $prefixesPsr0 = array(); /** - * @var array[] - * @psalm-var array + * @var list */ private $fallbackDirsPsr0 = array(); @@ -81,8 +80,7 @@ class ClassLoader private $useIncludePath = false; /** - * @var string[] - * @psalm-var array + * @var array */ private $classMap = array(); @@ -90,21 +88,20 @@ class ClassLoader private $classMapAuthoritative = false; /** - * @var bool[] - * @psalm-var array + * @var array */ private $missingClasses = array(); - /** @var ?string */ + /** @var string|null */ private $apcuPrefix; /** - * @var self[] + * @var array */ private static $registeredLoaders = array(); /** - * @param ?string $vendorDir + * @param string|null $vendorDir */ public function __construct($vendorDir = null) { @@ -113,7 +110,7 @@ public function __construct($vendorDir = null) } /** - * @return string[] + * @return array> */ public function getPrefixes() { @@ -125,8 +122,7 @@ public function getPrefixes() } /** - * @return array[] - * @psalm-return array> + * @return array> */ public function getPrefixesPsr4() { @@ -134,8 +130,7 @@ public function getPrefixesPsr4() } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirs() { @@ -143,8 +138,7 @@ public function getFallbackDirs() } /** - * @return array[] - * @psalm-return array + * @return list */ public function getFallbackDirsPsr4() { @@ -152,8 +146,7 @@ public function getFallbackDirsPsr4() } /** - * @return string[] Array of classname => path - * @psalm-return array + * @return array Array of classname => path */ public function getClassMap() { @@ -161,8 +154,7 @@ public function getClassMap() } /** - * @param string[] $classMap Class to filename map - * @psalm-param array $classMap + * @param array $classMap Class to filename map * * @return void */ @@ -179,24 +171,25 @@ public function addClassMap(array $classMap) * Registers a set of PSR-0 directories for a given prefix, either * appending or prepending to the ones previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 root directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 root directories + * @param bool $prepend Whether to prepend the directories * * @return void */ public function add($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { if ($prepend) { $this->fallbackDirsPsr0 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr0 ); } else { $this->fallbackDirsPsr0 = array_merge( $this->fallbackDirsPsr0, - (array) $paths + $paths ); } @@ -205,19 +198,19 @@ public function add($prefix, $paths, $prepend = false) $first = $prefix[0]; if (!isset($this->prefixesPsr0[$first][$prefix])) { - $this->prefixesPsr0[$first][$prefix] = (array) $paths; + $this->prefixesPsr0[$first][$prefix] = $paths; return; } if ($prepend) { $this->prefixesPsr0[$first][$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixesPsr0[$first][$prefix] ); } else { $this->prefixesPsr0[$first][$prefix] = array_merge( $this->prefixesPsr0[$first][$prefix], - (array) $paths + $paths ); } } @@ -226,9 +219,9 @@ public function add($prefix, $paths, $prepend = false) * Registers a set of PSR-4 directories for a given namespace, either * appending or prepending to the ones previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories - * @param bool $prepend Whether to prepend the directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories + * @param bool $prepend Whether to prepend the directories * * @throws \InvalidArgumentException * @@ -236,17 +229,18 @@ public function add($prefix, $paths, $prepend = false) */ public function addPsr4($prefix, $paths, $prepend = false) { + $paths = (array) $paths; if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirsPsr4 = array_merge( - (array) $paths, + $paths, $this->fallbackDirsPsr4 ); } else { $this->fallbackDirsPsr4 = array_merge( $this->fallbackDirsPsr4, - (array) $paths + $paths ); } } elseif (!isset($this->prefixDirsPsr4[$prefix])) { @@ -256,18 +250,18 @@ public function addPsr4($prefix, $paths, $prepend = false) throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length; - $this->prefixDirsPsr4[$prefix] = (array) $paths; + $this->prefixDirsPsr4[$prefix] = $paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( - (array) $paths, + $paths, $this->prefixDirsPsr4[$prefix] ); } else { // Append directories for an already registered namespace. $this->prefixDirsPsr4[$prefix] = array_merge( $this->prefixDirsPsr4[$prefix], - (array) $paths + $paths ); } } @@ -276,8 +270,8 @@ public function addPsr4($prefix, $paths, $prepend = false) * Registers a set of PSR-0 directories for a given prefix, * replacing any others previously set for this prefix. * - * @param string $prefix The prefix - * @param string[]|string $paths The PSR-0 base directories + * @param string $prefix The prefix + * @param list|string $paths The PSR-0 base directories * * @return void */ @@ -294,8 +288,8 @@ public function set($prefix, $paths) * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * - * @param string $prefix The prefix/namespace, with trailing '\\' - * @param string[]|string $paths The PSR-4 base directories + * @param string $prefix The prefix/namespace, with trailing '\\' + * @param list|string $paths The PSR-4 base directories * * @throws \InvalidArgumentException * @@ -481,9 +475,9 @@ public function findFile($class) } /** - * Returns the currently registered loaders indexed by their corresponding vendor directories. + * Returns the currently registered loaders keyed by their corresponding vendor directories. * - * @return self[] + * @return array */ public static function getRegisteredLoaders() { diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 6b784da..cb0c7e9 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -2,17 +2,17 @@ "packages": [ { "name": "dompdf/dompdf", - "version": "v2.0.4", - "version_normalized": "2.0.4.0", + "version": "v2.0.7", + "version_normalized": "2.0.7.0", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f" + "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/093f2d9739cec57428e39ddadedfd4f3ae862c0f", - "reference": "093f2d9739cec57428e39ddadedfd4f3ae862c0f", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/ab0123052b42ad0867348f25df8c228f1ece8f14", + "reference": "ab0123052b42ad0867348f25df8c228f1ece8f14", "shasum": "" }, "require": { @@ -20,7 +20,7 @@ "ext-mbstring": "*", "masterminds/html5": "^2.0", "phenx/php-font-lib": ">=0.5.4 <1.0.0", - "phenx/php-svg-lib": ">=0.3.3 <1.0.0", + "phenx/php-svg-lib": ">=0.5.2 <1.0.0", "php": "^7.1 || ^8.0" }, "require-dev": { @@ -36,7 +36,7 @@ "ext-imagick": "Improves image processing performance", "ext-zlib": "Needed for pdf stream compression" }, - "time": "2023-12-12T20:19:39+00:00", + "time": "2024-04-15T12:40:33+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -61,23 +61,23 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v2.0.4" + "source": "https://github.com/dompdf/dompdf/tree/v2.0.7" }, "install-path": "../dompdf/dompdf" }, { "name": "masterminds/html5", - "version": "2.8.1", - "version_normalized": "2.8.1.0", + "version": "2.9.0", + "version_normalized": "2.9.0.0", "source": { "type": "git", "url": "https://github.com/Masterminds/html5-php.git", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf" + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f47dcf3c70c584de14f21143c55d9939631bc6cf", - "reference": "f47dcf3c70c584de14f21143c55d9939631bc6cf", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", + "reference": "f5ac2c0b0a2eefca70b2ce32a5809992227e75a6", "shasum": "" }, "require": { @@ -85,9 +85,9 @@ "php": ">=5.3.0" }, "require-dev": { - "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" }, - "time": "2023-05-10T11:58:31+00:00", + "time": "2024-03-31T07:05:07+00:00", "type": "library", "extra": { "branch-alias": { @@ -131,32 +131,32 @@ ], "support": { "issues": "https://github.com/Masterminds/html5-php/issues", - "source": "https://github.com/Masterminds/html5-php/tree/2.8.1" + "source": "https://github.com/Masterminds/html5-php/tree/2.9.0" }, "install-path": "../masterminds/html5" }, { "name": "phenx/php-font-lib", - "version": "0.5.4", - "version_normalized": "0.5.4.0", + "version": "0.5.6", + "version_normalized": "0.5.6.0", "source": { "type": "git", "url": "https://github.com/dompdf/php-font-lib.git", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4" + "reference": "a1681e9793040740a405ac5b189275059e2a9863" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/dd448ad1ce34c63d09baccd05415e361300c35b4", - "reference": "dd448ad1ce34c63d09baccd05415e361300c35b4", + "url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a1681e9793040740a405ac5b189275059e2a9863", + "reference": "a1681e9793040740a405ac5b189275059e2a9863", "shasum": "" }, "require": { "ext-mbstring": "*" }, "require-dev": { - "symfony/phpunit-bridge": "^3 || ^4 || ^5" + "symfony/phpunit-bridge": "^3 || ^4 || ^5 || ^6" }, - "time": "2021-12-17T19:44:54+00:00", + "time": "2024-01-29T14:45:26+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -166,7 +166,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "LGPL-2.1-or-later" ], "authors": [ { @@ -178,23 +178,23 @@ "homepage": "https://github.com/PhenX/php-font-lib", "support": { "issues": "https://github.com/dompdf/php-font-lib/issues", - "source": "https://github.com/dompdf/php-font-lib/tree/0.5.4" + "source": "https://github.com/dompdf/php-font-lib/tree/0.5.6" }, "install-path": "../phenx/php-font-lib" }, { "name": "phenx/php-svg-lib", - "version": "0.5.1", - "version_normalized": "0.5.1.0", + "version": "0.5.4", + "version_normalized": "0.5.4.0", "source": { "type": "git", "url": "https://github.com/dompdf/php-svg-lib.git", - "reference": "8a8a1ebcf6aea861ef30197999f096f7bd4b4456" + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8a8a1ebcf6aea861ef30197999f096f7bd4b4456", - "reference": "8a8a1ebcf6aea861ef30197999f096f7bd4b4456", + "url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/46b25da81613a9cf43c83b2a8c2c1bdab27df691", + "reference": "46b25da81613a9cf43c83b2a8c2c1bdab27df691", "shasum": "" }, "require": { @@ -205,7 +205,7 @@ "require-dev": { "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5" }, - "time": "2023-12-11T20:56:08+00:00", + "time": "2024-04-08T12:52:34+00:00", "type": "library", "installation-source": "dist", "autoload": { @@ -215,7 +215,7 @@ }, "notification-url": "https://packagist.org/downloads/", "license": [ - "LGPL-3.0" + "LGPL-3.0-or-later" ], "authors": [ { @@ -227,23 +227,23 @@ "homepage": "https://github.com/PhenX/php-svg-lib", "support": { "issues": "https://github.com/dompdf/php-svg-lib/issues", - "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.1" + "source": "https://github.com/dompdf/php-svg-lib/tree/0.5.4" }, "install-path": "../phenx/php-svg-lib" }, { "name": "sabberworm/php-css-parser", - "version": "8.4.0", - "version_normalized": "8.4.0.0", + "version": "v8.5.1", + "version_normalized": "8.5.1.0", "source": { "type": "git", - "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30" + "url": "https://github.com/MyIntervals/PHP-CSS-Parser.git", + "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/e41d2140031d533348b2192a83f02d8dd8a71d30", - "reference": "e41d2140031d533348b2192a83f02d8dd8a71d30", + "url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/4a3d572b0f8b28bb6fd016ae8bbfc445facef152", + "reference": "4a3d572b0f8b28bb6fd016ae8bbfc445facef152", "shasum": "" }, "require": { @@ -251,14 +251,18 @@ "php": ">=5.6.20" }, "require-dev": { - "codacy/coverage": "^1.4", - "phpunit/phpunit": "^4.8.36" + "phpunit/phpunit": "^5.7.27" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" }, - "time": "2021-12-11T13:40:54+00:00", + "time": "2024-02-15T16:41:13+00:00", "type": "library", + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, "installation-source": "dist", "autoload": { "psr-4": { @@ -272,6 +276,14 @@ "authors": [ { "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" } ], "description": "Parser for CSS Files written in PHP", @@ -282,8 +294,8 @@ "stylesheet" ], "support": { - "issues": "https://github.com/sabberworm/PHP-CSS-Parser/issues", - "source": "https://github.com/sabberworm/PHP-CSS-Parser/tree/8.4.0" + "issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues", + "source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v8.5.1" }, "install-path": "../sabberworm/php-css-parser" } diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 8a90be1..5a56c48 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => '__root__', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '036eaf95ca56dc9a137d3577502c9bb71cb386a6', + 'reference' => '049d3306649200b4fa2b208bf1f4832d348647e8', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -13,52 +13,52 @@ '__root__' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '036eaf95ca56dc9a137d3577502c9bb71cb386a6', + 'reference' => '049d3306649200b4fa2b208bf1f4832d348647e8', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false, ), 'dompdf/dompdf' => array( - 'pretty_version' => 'v2.0.4', - 'version' => '2.0.4.0', - 'reference' => '093f2d9739cec57428e39ddadedfd4f3ae862c0f', + 'pretty_version' => 'v2.0.7', + 'version' => '2.0.7.0', + 'reference' => 'ab0123052b42ad0867348f25df8c228f1ece8f14', 'type' => 'library', 'install_path' => __DIR__ . '/../dompdf/dompdf', 'aliases' => array(), 'dev_requirement' => false, ), 'masterminds/html5' => array( - 'pretty_version' => '2.8.1', - 'version' => '2.8.1.0', - 'reference' => 'f47dcf3c70c584de14f21143c55d9939631bc6cf', + 'pretty_version' => '2.9.0', + 'version' => '2.9.0.0', + 'reference' => 'f5ac2c0b0a2eefca70b2ce32a5809992227e75a6', 'type' => 'library', 'install_path' => __DIR__ . '/../masterminds/html5', 'aliases' => array(), 'dev_requirement' => false, ), 'phenx/php-font-lib' => array( - 'pretty_version' => '0.5.4', - 'version' => '0.5.4.0', - 'reference' => 'dd448ad1ce34c63d09baccd05415e361300c35b4', + 'pretty_version' => '0.5.6', + 'version' => '0.5.6.0', + 'reference' => 'a1681e9793040740a405ac5b189275059e2a9863', 'type' => 'library', 'install_path' => __DIR__ . '/../phenx/php-font-lib', 'aliases' => array(), 'dev_requirement' => false, ), 'phenx/php-svg-lib' => array( - 'pretty_version' => '0.5.1', - 'version' => '0.5.1.0', - 'reference' => '8a8a1ebcf6aea861ef30197999f096f7bd4b4456', + 'pretty_version' => '0.5.4', + 'version' => '0.5.4.0', + 'reference' => '46b25da81613a9cf43c83b2a8c2c1bdab27df691', 'type' => 'library', 'install_path' => __DIR__ . '/../phenx/php-svg-lib', 'aliases' => array(), 'dev_requirement' => false, ), 'sabberworm/php-css-parser' => array( - 'pretty_version' => '8.4.0', - 'version' => '8.4.0.0', - 'reference' => 'e41d2140031d533348b2192a83f02d8dd8a71d30', + 'pretty_version' => 'v8.5.1', + 'version' => '8.5.1.0', + 'reference' => '4a3d572b0f8b28bb6fd016ae8bbfc445facef152', 'type' => 'library', 'install_path' => __DIR__ . '/../sabberworm/php-css-parser', 'aliases' => array(), diff --git a/vendor/dompdf/dompdf/VERSION b/vendor/dompdf/dompdf/VERSION index 2165f8f..6a0ca2d 100644 --- a/vendor/dompdf/dompdf/VERSION +++ b/vendor/dompdf/dompdf/VERSION @@ -1 +1 @@ -2.0.4 +2.0.7 \ No newline at end of file diff --git a/vendor/dompdf/dompdf/composer.json b/vendor/dompdf/dompdf/composer.json index 268a81e..435c670 100644 --- a/vendor/dompdf/dompdf/composer.json +++ b/vendor/dompdf/dompdf/composer.json @@ -29,7 +29,7 @@ "ext-mbstring": "*", "masterminds/html5": "^2.0", "phenx/php-font-lib": ">=0.5.4 <1.0.0", - "phenx/php-svg-lib": ">=0.3.3 <1.0.0" + "phenx/php-svg-lib": ">=0.5.2 <1.0.0" }, "require-dev": { "ext-json": "*", diff --git a/vendor/dompdf/dompdf/src/Adapter/GD.php b/vendor/dompdf/dompdf/src/Adapter/GD.php index 269beb9..1e8bfbb 100644 --- a/vendor/dompdf/dompdf/src/Adapter/GD.php +++ b/vendor/dompdf/dompdf/src/Adapter/GD.php @@ -467,12 +467,17 @@ public function rectangle($x1, $y1, $w, $h, $color, $width, $style = [], $cap = imagesetthickness($this->get_image(), $width); if ($c === IMG_COLOR_STYLED) { - imagepolygon($this->get_image(), [ + $points = [ $x1, $y1, $x1 + $w, $y1, $x1 + $w, $y1 + $h, $x1, $y1 + $h - ], $c); + ]; + if (version_compare(PHP_VERSION, "8.1.0", "<")) { + imagepolygon($this->get_image(), $points, count($points)/2, $c); + } else { + imagepolygon($this->get_image(), $points, $c); + } } else { imagerectangle($this->get_image(), $x1, $y1, $x1 + $w, $y1 + $h, $c); } @@ -570,9 +575,17 @@ public function polygon($points, $color, $width = null, $style = [], $fill = fal imagesetthickness($this->get_image(), isset($width) ? $width : 0); if ($fill) { - imagefilledpolygon($this->get_image(), $points, $c); + if (version_compare(PHP_VERSION, "8.1.0", "<")) { + imagefilledpolygon($this->get_image(), $points, count($points)/2, $c); + } else { + imagefilledpolygon($this->get_image(), $points, $c); + } } else { - imagepolygon($this->get_image(), $points, $c); + if (version_compare(PHP_VERSION, "8.1.0", "<")) { + imagepolygon($this->get_image(), $points, count($points)/2, $c); + } else { + imagepolygon($this->get_image(), $points, $c); + } } } diff --git a/vendor/dompdf/dompdf/src/Options.php b/vendor/dompdf/dompdf/src/Options.php index c065bff..ee4010a 100644 --- a/vendor/dompdf/dompdf/src/Options.php +++ b/vendor/dompdf/dompdf/src/Options.php @@ -83,6 +83,13 @@ class Options "https://" => ["rules" => []] ]; + /** + * Operational artifact (log files, temporary files) path validation + * + * @var callable + */ + private $artifactPathValidation = null; + /** * @var string */ @@ -335,6 +342,8 @@ public function __construct(array $attributes = null) $this->setAllowedProtocols(["file://", "http://", "https://"]); + $this->setArtifactPathValidation([$this, "validateArtifactPath"]); + if (null !== $attributes) { $this->set($attributes); } @@ -361,6 +370,8 @@ public function set($attributes, $value = null) $this->setChroot($value); } elseif ($key === 'allowedProtocols') { $this->setAllowedProtocols($value); + } elseif ($key === 'artifactPathValidation') { + $this->setArtifactPathValidation($value); } elseif ($key === 'logOutputFile' || $key === 'log_output_file') { $this->setLogOutputFile($value); } elseif ($key === 'defaultMediaType' || $key === 'default_media_type') { @@ -428,6 +439,8 @@ public function get($key) return $this->getChroot(); } elseif ($key === 'allowedProtocols') { return $this->getAllowedProtocols(); + } elseif ($key === 'artifactPathValidation') { + return $this->getArtifactPathValidation(); } elseif ($key === 'logOutputFile' || $key === 'log_output_file') { return $this->getLogOutputFile(); } elseif ($key === 'defaultMediaType' || $key === 'default_media_type') { @@ -592,6 +605,24 @@ public function addAllowedProtocol(string $protocol, callable ...$rules) return $this; } + /** + * @return array + */ + public function getArtifactPathValidation() + { + return $this->artifactPathValidation; + } + + /** + * @param callable $validator + * @return $this + */ + public function setArtifactPathValidation($validator) + { + $this->artifactPathValidation = $validator; + return $this; + } + /** * @return array */ @@ -848,7 +879,9 @@ public function getDpi() */ public function setFontCache($fontCache) { - $this->fontCache = $fontCache; + if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($fontCache, "fontCache") === true) { + $this->fontCache = $fontCache; + } return $this; } @@ -866,7 +899,9 @@ public function getFontCache() */ public function setFontDir($fontDir) { - $this->fontDir = $fontDir; + if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($fontDir, "fontDir") === true) { + $this->fontDir = $fontDir; + } return $this; } @@ -1035,7 +1070,9 @@ public function isRemoteEnabled() */ public function setLogOutputFile($logOutputFile) { - $this->logOutputFile = $logOutputFile; + if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($logOutputFile, "logOutputFile") === true) { + $this->logOutputFile = $logOutputFile; + } return $this; } @@ -1053,7 +1090,9 @@ public function getLogOutputFile() */ public function setTempDir($tempDir) { - $this->tempDir = $tempDir; + if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($tempDir, "tempDir") === true) { + $this->tempDir = $tempDir; + } return $this; } @@ -1071,7 +1110,9 @@ public function getTempDir() */ public function setRootDir($rootDir) { - $this->rootDir = $rootDir; + if (!is_callable($this->artifactPathValidation) || ($this->artifactPathValidation)($rootDir, "rootDir") === true) { + $this->rootDir = $rootDir; + } return $this; } @@ -1105,6 +1146,16 @@ public function getHttpContext() return $this->httpContext; } + + public function validateArtifactPath(?string $path, string $option) + { + $parsed_uri = parse_url($path); + if ($parsed_uri === false || (array_key_exists("scheme", $parsed_uri) && strtolower($parsed_uri["scheme"]) === "phar")) { + return false; + } + return true; + } + public function validateLocalUri(string $uri) { if ($uri === null || strlen($uri) === 0) { diff --git a/vendor/masterminds/html5/README.md b/vendor/masterminds/html5/README.md index e80dec5..fb6e562 100644 --- a/vendor/masterminds/html5/README.md +++ b/vendor/masterminds/html5/README.md @@ -30,7 +30,7 @@ HTML5 provides the following features. - Interoperability with [QueryPath](https://github.com/technosophos/querypath) - Runs on **PHP** 5.3.0 or newer -[![Build Status](https://travis-ci.org/Masterminds/html5-php.png?branch=master)](https://travis-ci.org/Masterminds/html5-php) +[![CI](https://github.com/Masterminds/html5-php/actions/workflows/ci.yaml/badge.svg)](https://github.com/Masterminds/html5-php/actions/workflows/ci.yaml) [![Latest Stable Version](https://poser.pugx.org/masterminds/html5/v/stable.png)](https://packagist.org/packages/masterminds/html5) [![Code Coverage](https://scrutinizer-ci.com/g/Masterminds/html5-php/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/Masterminds/html5-php/?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Masterminds/html5-php/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/Masterminds/html5-php/?branch=master) diff --git a/vendor/masterminds/html5/composer.json b/vendor/masterminds/html5/composer.json index 69f5da0..35b4a57 100644 --- a/vendor/masterminds/html5/composer.json +++ b/vendor/masterminds/html5/composer.json @@ -24,7 +24,7 @@ "php" : ">=5.3.0" }, "require-dev": { - "phpunit/phpunit" : "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8" + "phpunit/phpunit" : "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9" }, "autoload": { "psr-4": {"Masterminds\\": "src"} diff --git a/vendor/masterminds/html5/src/HTML5/Elements.php b/vendor/masterminds/html5/src/HTML5/Elements.php index 1632dcf..5d8cfd4 100644 --- a/vendor/masterminds/html5/src/HTML5/Elements.php +++ b/vendor/masterminds/html5/src/HTML5/Elements.php @@ -71,6 +71,24 @@ class Elements */ const BLOCK_ONLY_INLINE = 128; + /** + * Elements with optional end tags that cause auto-closing of previous and parent tags, + * as example most of the table related tags, see https://www.w3.org/TR/html401/struct/tables.html + * Structure is as follows: + * TAG-NAME => [PARENT-TAG-NAME-TO-CLOSE1, PARENT-TAG-NAME-TO-CLOSE2, ...]. + * + * Order is important, after auto-closing one parent with might have to close also their parent. + * + * @var array + */ + public static $optionalEndElementsParentsToClose = array( + 'tr' => array('td', 'tr'), + 'td' => array('td', 'th'), + 'th' => array('td', 'th'), + 'tfoot' => array('td', 'th', 'tr', 'tbody', 'thead'), + 'tbody' => array('td', 'th', 'tr', 'thead'), + ); + /** * The HTML5 elements as defined in http://dev.w3.org/html5/markup/elements.html. * diff --git a/vendor/masterminds/html5/src/HTML5/Parser/DOMTreeBuilder.php b/vendor/masterminds/html5/src/HTML5/Parser/DOMTreeBuilder.php index 293d83e..d165b66 100644 --- a/vendor/masterminds/html5/src/HTML5/Parser/DOMTreeBuilder.php +++ b/vendor/masterminds/html5/src/HTML5/Parser/DOMTreeBuilder.php @@ -359,6 +359,16 @@ public function startTag($name, $attributes = array(), $selfClosing = false) $this->onlyInline = null; } + // some elements as table related tags might have optional end tags that force us to auto close multiple tags + // https://www.w3.org/TR/html401/struct/tables.html + if ($this->current instanceof \DOMElement && isset(Elements::$optionalEndElementsParentsToClose[$lname])) { + foreach (Elements::$optionalEndElementsParentsToClose[$lname] as $parentElName) { + if ($this->current instanceof \DOMElement && $this->current->tagName === $parentElName) { + $this->autoclose($parentElName); + } + } + } + try { $prefix = ($pos = strpos($lname, ':')) ? substr($lname, 0, $pos) : ''; diff --git a/vendor/masterminds/html5/src/HTML5/Parser/StringInputStream.php b/vendor/masterminds/html5/src/HTML5/Parser/StringInputStream.php index 0c213fe..75b0886 100644 --- a/vendor/masterminds/html5/src/HTML5/Parser/StringInputStream.php +++ b/vendor/masterminds/html5/src/HTML5/Parser/StringInputStream.php @@ -183,6 +183,7 @@ public function getColumnOffset() * * @return string The current character. */ + #[\ReturnTypeWillChange] public function current() { return $this->data[$this->char]; @@ -192,6 +193,7 @@ public function current() * Advance the pointer. * This is part of the Iterator interface. */ + #[\ReturnTypeWillChange] public function next() { ++$this->char; @@ -200,6 +202,7 @@ public function next() /** * Rewind to the start of the string. */ + #[\ReturnTypeWillChange] public function rewind() { $this->char = 0; @@ -210,6 +213,7 @@ public function rewind() * * @return bool Whether the current pointer location is valid. */ + #[\ReturnTypeWillChange] public function valid() { return $this->char < $this->EOF; @@ -324,6 +328,7 @@ public function peek() return false; } + #[\ReturnTypeWillChange] public function key() { return $this->char; diff --git a/vendor/phenx/php-font-lib/.github/workflows/phpunit.yml b/vendor/phenx/php-font-lib/.github/workflows/phpunit.yml deleted file mode 100644 index 82eeb85..0000000 --- a/vendor/phenx/php-font-lib/.github/workflows/phpunit.yml +++ /dev/null @@ -1,44 +0,0 @@ -name: PHPUnit tests - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - php-version: - - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - php-version: - - "5.4" - - "5.5" - - "5.6" - - "7.0" - - "7.1" - - "7.2" - - "7.3" - - "7.4" - - "8.0" - - "8.1" - - steps: - - - uses: actions/checkout@v2 - - - name: Install PHP - uses: "shivammathur/setup-php@v2" - with: - php-version: "${{ matrix.php-version }}" - coverage: "none" - ini-values: "zend.assertions=1" - - - name: Install Composer dependencies - run: composer install --no-progress --ansi - - - name: Run tests ${{ matrix.php-version }} - run: SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 bin/simple-phpunit --color=always diff --git a/vendor/phenx/php-font-lib/.htaccess b/vendor/phenx/php-font-lib/.htaccess deleted file mode 100644 index d02bd68..0000000 --- a/vendor/phenx/php-font-lib/.htaccess +++ /dev/null @@ -1 +0,0 @@ -#deny from all \ No newline at end of file diff --git a/vendor/phenx/php-font-lib/README.md b/vendor/phenx/php-font-lib/README.md index 0fa24ee..df8edfe 100644 --- a/vendor/phenx/php-font-lib/README.md +++ b/vendor/phenx/php-font-lib/README.md @@ -8,15 +8,15 @@ This library can be used to: * Extract advanced info (horizontal metrics, glyph names, glyph shapes, etc) * Make an Adobe Font Metrics (AFM) file from a font -You can find a demo GUI [here](http://pxd.me/php-font-lib/www/font_explorer.html). - This project was initiated by the need to read font files in the [DOMPDF project](https://github.com/dompdf/dompdf). Usage Example ------------- -``` -$font = \FontLib\Font::load('../../fontfile.ttf'); +### Base font information + +```php +$font = \FontLib\Font::load('fontfile.ttf'); $font->parse(); // for getFontWeight() to work this call must be done first! echo $font->getFontName() .'
'; echo $font->getFontSubfamily() .'
'; @@ -25,4 +25,26 @@ echo $font->getFontFullName() .'
'; echo $font->getFontVersion() .'
'; echo $font->getFontWeight() .'
'; echo $font->getFontPostscriptName() .'
'; +$font->close(); +``` + +### Font Metrics Generation + +```php +$font = FontLib\Font::load('fontfile.ttf'); +$font->parse(); +$font->saveAdobeFontMetrics('fontfile.ufm'); +``` + +### Create a font subset + +```php +$font = FontLib\Font::load('fontfile.ttf'); +$font->parse(); +$font->setSubset("abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ.:,;' (!?)+-*/== 1234567890"); // characters to include +$font->reduce(); +touch('fontfile.subset.ttf'); +$font->open('fontfile.subset.ttf', FontLib\BinaryStream::modeReadWrite); +$font->encode(array("OS/2")); +$font->close(); ``` diff --git a/vendor/phenx/php-font-lib/bower.json b/vendor/phenx/php-font-lib/bower.json deleted file mode 100644 index 0a4a45b..0000000 --- a/vendor/phenx/php-font-lib/bower.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "php-font-lib", - "version": "0.3.1", - "license": "LGPL-3.0", - "keywords": [ - "font", - "parse", - "export", - "truetype", - "opentype", - "woff" - ], - "homepage": "https://github.com/PhenX/php-font-lib", - "_release": "0.3.1", - "_resolution": { - "type": "version", - "tag": "v0.3.1", - "commit": "d13682b7e27d14a6323c441426f3dde1cd86c751" - }, - "_source": "https://github.com/PhenX/php-font-lib.git", - "_target": "*", - "_originalSource": "https://github.com/PhenX/php-font-lib.git" -} \ No newline at end of file diff --git a/vendor/phenx/php-font-lib/composer.json b/vendor/phenx/php-font-lib/composer.json index 29b0653..97b42b8 100644 --- a/vendor/phenx/php-font-lib/composer.json +++ b/vendor/phenx/php-font-lib/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "A library to read, parse, export and make subsets of different types of font files.", "homepage": "https://github.com/PhenX/php-font-lib", - "license": "LGPL-3.0", + "license": "LGPL-2.1-or-later", "authors": [ { "name": "Fabien Ménager", @@ -27,6 +27,6 @@ "ext-mbstring": "*" }, "require-dev": { - "symfony/phpunit-bridge" : "^3 || ^4 || ^5" + "symfony/phpunit-bridge" : "^3 || ^4 || ^5 || ^6" } } diff --git a/vendor/phenx/php-font-lib/index.php b/vendor/phenx/php-font-lib/index.php deleted file mode 100644 index 7ed173a..0000000 --- a/vendor/phenx/php-font-lib/index.php +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/vendor/phenx/php-font-lib/src/FontLib/AdobeFontMetrics.php b/vendor/phenx/php-font-lib/src/FontLib/AdobeFontMetrics.php index e75385f..613117d 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/AdobeFontMetrics.php +++ b/vendor/phenx/php-font-lib/src/FontLib/AdobeFontMetrics.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -33,7 +33,7 @@ function write($file, $encoding = null) { if ($encoding) { $encoding = preg_replace("/[^a-z0-9-_]/", "", $encoding); - $map_file = dirname(__FILE__) . "/../maps/$encoding.map"; + $map_file = dirname(__FILE__) . "/../../maps/$encoding.map"; if (!file_exists($map_file)) { throw new \Exception("Unknown encoding ($encoding)"); } @@ -48,7 +48,7 @@ function write($file, $encoding = null) { $this->startSection("FontMetrics", 4.1); $this->addPair("Notice", "Converted by PHP-font-lib"); - $this->addPair("Comment", "https://github.com/PhenX/php-font-lib"); + $this->addPair("Comment", "https://github.com/dompdf/php-font-lib"); $encoding_scheme = ($encoding ? $encoding : "FontSpecific"); $this->addPair("EncodingScheme", $encoding_scheme); @@ -75,12 +75,50 @@ function write($file, $encoding = null) { if (isset($hhea["ascent"])) { $this->addPair("FontHeightOffset", $font->normalizeFUnit($hhea["lineGap"])); - $this->addPair("Ascender", $font->normalizeFUnit($hhea["ascent"])); - $this->addPair("Descender", $font->normalizeFUnit($hhea["descent"])); } else { $this->addPair("FontHeightOffset", $font->normalizeFUnit($os2["typoLineGap"])); + } + + $glyf = $font->getData("glyf"); + $glyphIndexArray = $font->getUnicodeCharMap(); + $hasGlyphs = $glyf instanceof glyf && is_array($glyphIndexArray); + + // capHeight is based on capital H + if ($hasGlyphs && \array_key_exists(72, $glyphIndexArray)) { + $upperH = $glyf[$glyphIndexArray[72]]; + $upperH->parseData(); + $this->addPair("CapHeight", $font->normalizeFUnit($upperH->yMax)); + } + + // xHeight is based on lowercase x + if ($hasGlyphs && \array_key_exists(120, $glyphIndexArray)) { + $lowerX = $glyf[$glyphIndexArray[120]]; + $lowerX->parseData(); + $this->addPair("XHeight", $font->normalizeFUnit($lowerX->yMax)); + } + + // ascender is based on lowercase d + if ($hasGlyphs && \array_key_exists(100, $glyphIndexArray)) { + $lowerD = $glyf[$glyphIndexArray[100]]; + $lowerD->parseData(); + $this->addPair("Ascender", $font->normalizeFUnit($lowerD->yMax)); + } elseif (isset($hhea["ascent"])) { + $this->addPair("Ascender", $font->normalizeFUnit($hhea["ascent"])); + } + else { $this->addPair("Ascender", $font->normalizeFUnit($os2["typoAscender"])); + } + + // descender is based on lowercase p + if ($hasGlyphs && \array_key_exists(112, $glyphIndexArray)) { + $lowerP = $glyf[$glyphIndexArray[112]]; + $lowerP->parseData(); + $this->addPair("Descender", $font->normalizeFUnit($lowerP->yMin)); + } elseif (isset($hhea["descent"])) { + $this->addPair("Descender", $font->normalizeFUnit($hhea["descent"])); + } + else { $this->addPair("Descender", -abs($font->normalizeFUnit($os2["typoDescender"]))); } @@ -92,8 +130,6 @@ function write($file, $encoding = null) { $font->normalizeFUnit($head["yMax"]), )); - $glyphIndexArray = $font->getUnicodeCharMap(); - if ($glyphIndexArray) { $hmtx = $font->getData("hmtx"); $names = $font->getData("post", "names"); diff --git a/vendor/phenx/php-font-lib/src/FontLib/Autoloader.php b/vendor/phenx/php-font-lib/src/FontLib/Autoloader.php deleted file mode 100644 index cd30545..0000000 --- a/vendor/phenx/php-font-lib/src/FontLib/Autoloader.php +++ /dev/null @@ -1,43 +0,0 @@ - - * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License - */ - -namespace FontLib; - -/** - * Autoloads FontLib classes - * - * @package php-font-lib - */ -class Autoloader { - const PREFIX = 'FontLib'; - - /** - * Register the autoloader - */ - public static function register() { - spl_autoload_register(array(new self, 'autoload')); - } - - /** - * Autoloader - * - * @param string - */ - public static function autoload($class) { - $prefixLength = strlen(self::PREFIX); - if (0 === strncmp(self::PREFIX, $class, $prefixLength)) { - $file = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, $prefixLength)); - $file = realpath(__DIR__ . (empty($file) ? '' : DIRECTORY_SEPARATOR) . $file . '.php'); - if (file_exists($file)) { - require_once $file; - } - } - } -} - -Autoloader::register(); \ No newline at end of file diff --git a/vendor/phenx/php-font-lib/src/FontLib/BinaryStream.php b/vendor/phenx/php-font-lib/src/FontLib/BinaryStream.php index c7eb52f..5e170c6 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/BinaryStream.php +++ b/vendor/phenx/php-font-lib/src/FontLib/BinaryStream.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/EOT/File.php b/vendor/phenx/php-font-lib/src/FontLib/EOT/File.php index f51d876..55933eb 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/EOT/File.php +++ b/vendor/phenx/php-font-lib/src/FontLib/EOT/File.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/EOT/Header.php b/vendor/phenx/php-font-lib/src/FontLib/EOT/Header.php index 960e36a..2730c80 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/EOT/Header.php +++ b/vendor/phenx/php-font-lib/src/FontLib/EOT/Header.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/EncodingMap.php b/vendor/phenx/php-font-lib/src/FontLib/EncodingMap.php index 2acdebc..02e7ca4 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/EncodingMap.php +++ b/vendor/phenx/php-font-lib/src/FontLib/EncodingMap.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Font.php b/vendor/phenx/php-font-lib/src/FontLib/Font.php index e13a653..3f6a784 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Font.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Font.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Glyph/Outline.php b/vendor/phenx/php-font-lib/src/FontLib/Glyph/Outline.php index 639ff60..efb2de5 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Glyph/Outline.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Glyph/Outline.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $ @@ -48,7 +48,7 @@ class Outline extends BinaryStream { static function init(glyf $table, $offset, $size, BinaryStream $font) { $font->seek($offset); - if ($font->readInt16() > -1) { + if ($size === 0 || $font->readInt16() > -1) { /** @var OutlineSimple $glyph */ $glyph = new OutlineSimple($table, $offset, $size); } diff --git a/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComponent.php b/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComponent.php index 9cafaf4..fa75c2a 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComponent.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComponent.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComposite.php b/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComposite.php index 8ab0d2c..eb3da91 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComposite.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineComposite.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $ @@ -129,6 +129,11 @@ function parseData() { $this->components[] = $component; } while ($flags & self::MORE_COMPONENTS); + if ($flags & self::WE_HAVE_INSTRUCTIONS) { + $numInstr = $font->readUInt16(); + $instr = $font->read($numInstr); + $this->components[count($this->components) - 1]->instructions = pack('n', $numInstr) . $instr; + } } function encode() { @@ -171,6 +176,8 @@ function encode() { if ($_i < count($this->components) - 1) { $flags |= self::MORE_COMPONENTS; + } elseif($_component->instructions !== null) { + $flags |= self::WE_HAVE_INSTRUCTIONS; } $size += $font->writeUInt16($flags); @@ -214,6 +221,10 @@ function encode() { } } + if($_component->instructions !== null) { + $size += $font->write($_component->instructions, strlen($_component->instructions)); + } + return $size; } diff --git a/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineSimple.php b/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineSimple.php index 56b2fb4..c0c5c85 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineSimple.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Glyph/OutlineSimple.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License * @version $Id: Font_Table_glyf.php 46 2012-04-02 20:22:38Z fabien.menager $ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Header.php b/vendor/phenx/php-font-lib/src/FontLib/Header.php index cbf137e..df308b3 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Header.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Header.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/OpenType/File.php b/vendor/phenx/php-font-lib/src/FontLib/OpenType/File.php index 9c6df96..0b46df9 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/OpenType/File.php +++ b/vendor/phenx/php-font-lib/src/FontLib/OpenType/File.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/OpenType/TableDirectoryEntry.php b/vendor/phenx/php-font-lib/src/FontLib/OpenType/TableDirectoryEntry.php index dd75a3e..d8f0f6e 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/OpenType/TableDirectoryEntry.php +++ b/vendor/phenx/php-font-lib/src/FontLib/OpenType/TableDirectoryEntry.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/DirectoryEntry.php b/vendor/phenx/php-font-lib/src/FontLib/Table/DirectoryEntry.php index 54a67af..b41fdd0 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/DirectoryEntry.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/DirectoryEntry.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -49,20 +49,8 @@ static function computeChecksum($data) { $data = str_pad($data, $len + (4 - $mod), "\0"); } - $len = mb_strlen($data, '8bit'); - - $hi = 0x0000; - $lo = 0x0000; - - for ($i = 0; $i < $len; $i += 4) { - $hi += (ord($data[$i]) << 8) + ord($data[$i + 1]); - $lo += (ord($data[$i + 2]) << 8) + ord($data[$i + 3]); - $hi += $lo >> 16; - $lo = $lo & 0xFFFF; - $hi = $hi & 0xFFFF; - } - - return ($hi << 8) + $lo; + $table = unpack("N*", $data); + return array_sum($table); } function __construct(File $font) { @@ -93,6 +81,14 @@ function encode($entry_offset) { $this->offset = $table_offset; $table_length = $data->encode(); + $font->seek($table_offset + $table_length); + $pad = 0; + $mod = $table_length % 4; + if ($mod != 0) { + $pad = 4 - $mod; + $font->write(str_pad("", $pad, "\0"), $pad); + } + $font->seek($table_offset); $table_data = $font->read($table_length); @@ -105,7 +101,7 @@ function encode($entry_offset) { Font::d("Bytes written = $table_length"); - $font->seek($table_offset + $table_length); + $font->seek($table_offset + $table_length + $pad); } /** diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Table.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Table.php index b127112..57328dd 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Table.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Table.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/cmap.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/cmap.php index 7db77e1..02788ef 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/cmap.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/cmap.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -26,6 +26,18 @@ class cmap extends Table { "offset" => self::uint32, ); + private static $subtable_v2_format = array( + "length" => self::uint16, + "language" => self::uint16 + ); + + private static $subtable_v2_format_subheader = array( + "firstCode" => self::uint16, + "entryCount" => self::uint16, + "idDelta" => self::int16, + "idRangeOffset" => self::uint16 + ); + private static $subtable_v4_format = array( "length" => self::uint16, "language" => self::uint16, @@ -38,7 +50,7 @@ class cmap extends Table { private static $subtable_v12_format = array( "length" => self::uint32, "language" => self::uint32, - "ngroups" => self::uint32 + "ngroups" => self::uint32 ); protected function _parse() { @@ -60,99 +72,170 @@ protected function _parse() { $subtable["format"] = $font->readUInt16(); - // @todo Only CMAP version 4 and 12 - if (($subtable["format"] != 4) && ($subtable["format"] != 12)) { - unset($data["subtables"][$i]); - $data["numberSubtables"]--; - continue; - } - - if ($subtable["format"] == 12) { - - $font->readUInt16(); - - $subtable += $font->unpack(self::$subtable_v12_format); - - $glyphIndexArray = array(); - $endCodes = array(); - $startCodes = array(); - - for ($p = 0; $p < $subtable['ngroups']; $p++) { - - $startCode = $startCodes[] = $font->readUInt32(); - $endCode = $endCodes[] = $font->readUInt32(); - $startGlyphCode = $font->readUInt32(); - - for ($c = $startCode; $c <= $endCode; $c++) { - $glyphIndexArray[$c] = $startGlyphCode; - $startGlyphCode++; + switch ($subtable["format"]) { + case 0: + case 6: + case 8: + case 10: + case 13: + case 14: + unset($data["subtables"][$i]); + $data["numberSubtables"]--; + continue 2; + + case 2: + $subtable += $font->unpack(self::$subtable_v2_format); + + $subHeaderKeys = array_map(function($val) { return $val / 8; }, $font->readUInt16Many(256)); + $subHeaders = array(); + + $glyphIdArray = array(); + $maxSubHeaderIndex = max($subHeaderKeys); + for ($i = 0; $i <= $maxSubHeaderIndex; $i++) { + $subHeader = $font->unpack(self::$subtable_v2_format_subheader); + $offset = $font->pos(); + $subHeader["glyphIdArrayOffset"] = $offset + $subHeader["idRangeOffset"] - 2; + $subHeaders[$i] = $subHeader; + + if (!\array_key_exists($subHeader["glyphIdArrayOffset"], $glyphIdArray) || count($glyphIdArray[$subHeader["glyphIdArrayOffset"]]) < $subHeader["entryCount"]) { + $font->seek($subHeader["glyphIdArrayOffset"]); + $glyphIdArray[$subHeader["glyphIdArrayOffset"]] = $font->readUInt16Many($subHeader["entryCount"]); + $font->seek($offset); + } } - } - - $subtable += array( - "startCode" => $startCodes, - "endCode" => $endCodes, - "glyphIndexArray" => $glyphIndexArray, - ); - - } - else if ($subtable["format"] == 4) { - - $subtable += $font->unpack(self::$subtable_v4_format); - - $segCount = $subtable["segCountX2"] / 2; - $subtable["segCount"] = $segCount; - $endCode = $font->readUInt16Many($segCount); - - $font->readUInt16(); // reservedPad - - $startCode = $font->readUInt16Many($segCount); - $idDelta = $font->readInt16Many($segCount); - - $ro_start = $font->pos(); - $idRangeOffset = $font->readUInt16Many($segCount); - - $glyphIndexArray = array(); - for ($i = 0; $i < $segCount; $i++) { - $c1 = $startCode[$i]; - $c2 = $endCode[$i]; - $d = $idDelta[$i]; - $ro = $idRangeOffset[$i]; - - if ($ro > 0) { - $font->seek($subtable["offset"] + 2 * $i + $ro); + $glyphIndexArray = array(); + foreach ($subHeaderKeys as $highByte => $subHeaderKey) { + $subHeader = $subHeaders[$subHeaderKey]; + if ($subHeaderKey === 0) { + $c = $highByte; + if ($c < $subHeader["firstCode"] || $c >= ($subHeader["firstCode"] + $subHeader["entryCount"])) { + $glyphIndexArray[$c] = 0; + continue; + } + $c = $highByte; + $index = $c - $subHeader["firstCode"]; + $glyphId = $glyphIdArray[$subHeader["glyphIdArrayOffset"]][$index]; + if ($glyphId === 0) { + $glyphIndexArray[$c] = 0; + } else { + $glyphIndexArray[$c] = ($glyphId + $subHeader["idDelta"]) & 0xFFFF; + } + } else { + for ($index = 0; $index < $subHeader["entryCount"]; $index++) { + $c = null; + $lowByte = $subHeader["firstCode"] + $index; + $c = (($highByte & 0xFF) << 8) | ($lowByte & 0xFF); + $glyphId = $glyphIdArray[$subHeader["glyphIdArrayOffset"]][$index]; + if ($glyphId === 0) { + $glyphIndexArray[$c] = 0; + } else { + $glyphIndexArray[$c] = ($glyphId + $subHeader["idDelta"]) & 0xFFFF; + } + } + } } - for ($c = $c1; $c <= $c2; $c++) { - if ($ro == 0) { - $gid = ($c + $d) & 0xFFFF; + $subtable += array( + "subHeaderKeys" => $subHeaderKeys, + "subHeaders" => $subHeaders, + "glyphIdArray" => $glyphIdArray, + "glyphIndexArray" => $glyphIndexArray + ); + + break; + + case 4: + $subtable += $font->unpack(self::$subtable_v4_format); + + $segCount = $subtable["segCountX2"] / 2; + $subtable["segCount"] = $segCount; + + $endCode = $font->readUInt16Many($segCount); + + $font->readUInt16(); // reservedPad + + $startCode = $font->readUInt16Many($segCount); + $idDelta = $font->readInt16Many($segCount); + + $ro_start = $font->pos(); + $idRangeOffset = $font->readUInt16Many($segCount); + + $glyphIndexArray = array(); + for ($i = 0; $i < $segCount; $i++) { + $c1 = $startCode[$i]; + $c2 = $endCode[$i]; + $d = $idDelta[$i]; + $ro = $idRangeOffset[$i]; + + if ($ro > 0) { + $font->seek($subtable["offset"] + 2 * $i + $ro); } - else { - $offset = ($c - $c1) * 2 + $ro; - $offset = $ro_start + 2 * $i + $offset; - - $font->seek($offset); - $gid = $font->readUInt16(); - - if ($gid != 0) { - $gid = ($gid + $d) & 0xFFFF; + + for ($c = $c1; $c <= $c2; $c++) { + if ($c === 0xFFFF) { + continue; + } + + if ($ro == 0) { + $gid = ($c + $d) & 0xFFFF; + } + else { + $offset = ($c - $c1) * 2 + $ro; + $offset = $ro_start + 2 * $i + $offset; + + $gid = 0; + if ($font->seek($offset) === true) { + $gid = $font->readUInt16(); + } + + if ($gid != 0) { + $gid = ($gid + $d) & 0xFFFF; + } + } + + if ($gid >= 0) { + $glyphIndexArray[$c] = $gid; } } - - if ($gid > 0) { - $glyphIndexArray[$c] = $gid; + } + + $subtable += array( + "endCode" => $endCode, + "startCode" => $startCode, + "idDelta" => $idDelta, + "idRangeOffset" => $idRangeOffset, + "glyphIndexArray" => $glyphIndexArray + ); + break; + + case 12: + $font->readUInt16(); + + $subtable += $font->unpack(self::$subtable_v12_format); + + $glyphIndexArray = array(); + $endCodes = array(); + $startCodes = array(); + + for ($p = 0; $p < $subtable['ngroups']; $p++) { + + $startCode = $startCodes[] = $font->readUInt32(); + $endCode = $endCodes[] = $font->readUInt32(); + $startGlyphCode = $font->readUInt32(); + + for ($c = $startCode; $c <= $endCode; $c++) { + $glyphIndexArray[$c] = $startGlyphCode; + $startGlyphCode++; } } - } - - $subtable += array( - "endCode" => $endCode, - "startCode" => $startCode, - "idDelta" => $idDelta, - "idRangeOffset" => $idRangeOffset, - "glyphIndexArray" => $glyphIndexArray, - ); + + $subtable += array( + "startCode" => $startCodes, + "endCode" => $endCodes, + "glyphIndexArray" => $glyphIndexArray, + ); + break; } } @@ -196,7 +279,7 @@ function _encode() { $prevGid = $gid; } - $segments[][] = array(0xFFFF, 0xFFFF); + $segments[][] = array(0xFFFF, null); $startCode = array(); $endCode = array(); @@ -282,7 +365,7 @@ function _encode() { $subtable["length"] = $length - $length_before; $font->seek($before_subheader); - $length += $font->pack(self::$subtable_v4_format, $subtable); + $font->pack(self::$subtable_v4_format, $subtable); $font->seek($after_subtable); } diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/cvt.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/cvt.php new file mode 100644 index 0000000..cec9ee4 --- /dev/null +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/cvt.php @@ -0,0 +1,27 @@ + + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + */ + +namespace FontLib\Table\Type; +use FontLib\Table\Table; + +/** + * `cvt ` font table. + * + * @package php-font-lib + */ +class cvt extends Table { + private $rawData; + protected function _parse() { + $font = $this->getFont(); + $font->seek($this->entry->offset); + $this->rawData = $font->read($this->entry->length); + } + function _encode() { + return $this->getFont()->write($this->rawData, $this->entry->length); + } +} \ No newline at end of file diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/fpgm.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/fpgm.php new file mode 100644 index 0000000..3c37c18 --- /dev/null +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/fpgm.php @@ -0,0 +1,27 @@ + + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + */ + +namespace FontLib\Table\Type; +use FontLib\Table\Table; + +/** + * `fpgm` font table. + * + * @package php-font-lib + */ +class fpgm extends Table { + private $rawData; + protected function _parse() { + $font = $this->getFont(); + $font->seek($this->entry->offset); + $this->rawData = $font->read($this->entry->length); + } + function _encode() { + return $this->getFont()->write($this->rawData, $this->entry->length); + } +} \ No newline at end of file diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/glyf.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/glyf.php index 1fbec3f..8e47f14 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/glyf.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/glyf.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -48,7 +48,7 @@ public function getGlyphIDs($gids = array()) { return array_unique(array_merge($gids, $glyphIDs)); } - public function toHTML() { + public function toHTML($n = 500) { $max = 160; $font = $this->getFont(); @@ -74,8 +74,6 @@ public function toHTML() { $height = round($height / $ratio); } - $n = 500; - $s = "

" . "Only the first $n simple glyphs are shown (" . count($this->data) . " total)
Simple glyph
Composite glyph
@@ -111,6 +109,11 @@ public function toHTML() { $name = isset($names[$g]) ? $names[$g] : sprintf("uni%04x", $char); $char = $char ? "&#{$glyphIndexArray[$g]};" : ""; + if ($char === "" && empty($shape["SVGContours"])) { + $n++; + continue; + } + $s .= "
$g $char @@ -143,7 +146,16 @@ protected function _encode() { $length = 0; foreach ($subset as $gid) { $loca[] = $length; - $length += $data[$gid]->encode(); + + $bytes = $data[$gid]->encode(); + + $pad = 0; + $mod = $bytes % 4; + if ($mod != 0) { + $pad = 4 - $mod; + $font->write(str_pad("", $pad, "\0"), $pad); + } + $length += $bytes + $pad; } $loca[] = $length; // dummy loca diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/head.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/head.php index 6349f14..0686508 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/head.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/head.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -43,4 +43,9 @@ protected function _parse() { throw new Exception("Incorrect magic number (" . dechex($this->data["magicNumber"]) . ")"); } } + + function _encode() { + $this->data["checkSumAdjustment"] = 0; + return parent::_encode(); + } } \ No newline at end of file diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/hhea.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/hhea.php index dc60a14..cd69040 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/hhea.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/hhea.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/hmtx.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/hmtx.php index 76e3307..ef985bb 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/hmtx.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/hmtx.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -35,8 +35,14 @@ protected function _parse() { } if ($numOfLongHorMetrics < $numGlyphs) { - $lastWidth = end($data); - $data = array_pad($data, $numGlyphs, $lastWidth); + $lastWidth = end($data)[0]; + $numLeft = $numGlyphs - $numOfLongHorMetrics; + $metrics = $font->readUInt16Many($numLeft); + for($i = 0; $i < $numLeft; $i++) { + $gid = $numOfLongHorMetrics + $i; + $leftSideBearing = isset($metrics[$i]) ? $metrics[$i] : 0; + $data[$gid] = array($lastWidth, $leftSideBearing); + } } $this->data = $data; diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/kern.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/kern.php index 9875946..538d8b2 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/kern.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/kern.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/loca.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/loca.php index cbc2a20..25453f7 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/loca.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/loca.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/maxp.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/maxp.php index b4ebae0..c69da3c 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/maxp.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/maxp.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/name.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/name.php index 794824d..acdda7a 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/name.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/name.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -150,11 +150,49 @@ protected function _parse() { $records[] = $record; } + $system_encodings = mb_list_encodings(); + $system_encodings = array_change_key_case(array_fill_keys($system_encodings, true), CASE_UPPER); + $names = array(); foreach ($records as $record) { $font->seek($tableOffset + $data["stringOffset"] + $record->offset); - $s = $font->read($record->length); - $record->string = Font::UTF16ToUTF8($s); + $record->stringRaw = $font->read($record->length); + + $encoding = null; + switch ($record->platformID) { + case 3: + switch ($record->platformSpecificID) { + case 2: + if (\array_key_exists("SJIS", $system_encodings)) { + $encoding = "SJIS"; + } + break; + case 3: + if (\array_key_exists("GB18030", $system_encodings)) { + $encoding = "GB18030"; + } + break; + case 4: + if (\array_key_exists("BIG-5", $system_encodings)) { + $encoding = "BIG-5"; + } + break; + case 5: + if (\array_key_exists("UHC", $system_encodings)) { + $encoding = "UHC"; + } + break; + } + break; + } + if ($encoding === null) { + $encoding = "UTF-16"; + } + + $record->string = mb_convert_encoding($record->stringRaw, "UTF-8", $encoding); + if (strpos($record->string, "\0") !== false) { + $record->string = str_replace("\0", "", $record->string); + } $names[$record->nameID] = $record; } @@ -168,22 +206,33 @@ protected function _encode() { /** @var nameRecord[] $records */ $records = $this->data["records"]; - $count_records = count($records); + $count_records = \count($records); $this->data["count"] = $count_records; - $this->data["stringOffset"] = 6 + $count_records * 12; // 6 => uint16 * 3, 12 => sizeof self::$record_format + $this->data["stringOffset"] = 6 + ($count_records * 12); // 6 => uint16 * 3, 12 => sizeof self::$record_format $length = $font->pack(self::$header_format, $this->data); $offset = 0; + + /** @var nameRecord[] $records_to_encode */ + $records_to_encode = array(); foreach ($records as $record) { - $record->length = mb_strlen($record->getUTF16(), "8bit"); - $record->offset = $offset; - $offset += $record->length; - $length += $font->pack(nameRecord::$format, (array)$record); + $encoded_record = new nameRecord(); + $encoded_record->platformID = 3; + $encoded_record->platformSpecificID = 1; + $encoded_record->languageID = $record->languageID; + $encoded_record->nameID = $record->nameID; + $encoded_record->offset = $offset; + $encoded_record->string = $record->string; + $encoded_record->length = mb_strlen($encoded_record->getUTF16(), "8bit"); + $records_to_encode[] = $encoded_record; + + $offset += $encoded_record->length; + $length += $font->pack(nameRecord::$format, (array)$encoded_record); } - foreach ($records as $record) { + foreach ($records_to_encode as $record) { $str = $record->getUTF16(); $length += $font->write($str, mb_strlen($str, "8bit")); } diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/nameRecord.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/nameRecord.php index 2073c20..fe22ba3 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/nameRecord.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/nameRecord.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -23,6 +23,7 @@ class nameRecord extends BinaryStream { public $length; public $offset; public $string; + public $stringRaw; public static $format = array( "platformID" => self::uint16, diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/os2.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/os2.php index 19a3e21..276de0d 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/os2.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/os2.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/post.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/post.php index 030a942..1160c0b 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/post.php +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/post.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/Table/Type/prep.php b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/prep.php new file mode 100644 index 0000000..c82c17d --- /dev/null +++ b/vendor/phenx/php-font-lib/src/FontLib/Table/Type/prep.php @@ -0,0 +1,30 @@ + + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + */ + +namespace FontLib\Table\Type; + +use FontLib\Table\Table; + +/** + * `prep` font table. + * + * @package php-font-lib + */ +class prep extends Table +{ + private $rawData; + protected function _parse() { + $font = $this->getFont(); + $font->seek($this->entry->offset); + $this->rawData = $font->read($this->entry->length); + } + function _encode() { + return $this->getFont()->write($this->rawData, $this->entry->length); + } +} diff --git a/vendor/phenx/php-font-lib/src/FontLib/TrueType/Collection.php b/vendor/phenx/php-font-lib/src/FontLib/TrueType/Collection.php index 460ef4d..a6afa4f 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/TrueType/Collection.php +++ b/vendor/phenx/php-font-lib/src/FontLib/TrueType/Collection.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/TrueType/File.php b/vendor/phenx/php-font-lib/src/FontLib/TrueType/File.php index 3594479..b1c7cd8 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/TrueType/File.php +++ b/vendor/phenx/php-font-lib/src/FontLib/TrueType/File.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -101,6 +101,72 @@ class File extends BinaryStream { "Ccaron", "ccaron", "dmacron" ); + private function uniord (string $c, string $encoding = null) { + if (function_exists("mb_ord")) { + if (PHP_VERSION_ID < 80000 && $encoding === null) { + // in PHP < 8 the encoding argument, if supplied, must be a valid encoding + $encoding = "UTF-8"; + } + return mb_ord($c, $encoding); + } + + if ($encoding != "UTF-8" && $encoding !== null) { + $c = mb_convert_encoding($c, "UTF-8", $encoding); + } + + $length = mb_strlen(mb_substr($c, 0, 1), '8bit'); + $ord = false; + $bytes = []; + $numbytes = 1; + for ($i = 0; $i < $length; $i++) { + $o = \ord($c[$i]); // get one string character at time + if (\count($bytes) === 0) { // get starting octect + if ($o <= 0x7F) { + $ord = $o; + $numbytes = 1; + } elseif (($o >> 0x05) === 0x06) { // 2 bytes character (0x06 = 110 BIN) + $bytes[] = ($o - 0xC0) << 0x06; + $numbytes = 2; + } elseif (($o >> 0x04) === 0x0E) { // 3 bytes character (0x0E = 1110 BIN) + $bytes[] = ($o - 0xE0) << 0x0C; + $numbytes = 3; + } elseif (($o >> 0x03) === 0x1E) { // 4 bytes character (0x1E = 11110 BIN) + $bytes[] = ($o - 0xF0) << 0x12; + $numbytes = 4; + } else { + $ord = false; + break; + } + } elseif (($o >> 0x06) === 0x02) { // bytes 2, 3 and 4 must start with 0x02 = 10 BIN + $bytes[] = $o - 0x80; + if (\count($bytes) === $numbytes) { + // compose UTF-8 bytes to a single unicode value + $o = $bytes[0]; + for ($j = 1; $j < $numbytes; $j++) { + $o += ($bytes[$j] << (($numbytes - $j - 1) * 0x06)); + } + if ((($o >= 0xD800) and ($o <= 0xDFFF)) or ($o >= 0x10FFFF)) { + // The definition of UTF-8 prohibits encoding character numbers between + // U+D800 and U+DFFF, which are reserved for use with the UTF-16 + // encoding form (as surrogate pairs) and do not directly represent + // characters. + return false; + } else { + $ord = $o; // add char to array + } + // reset data for next char + $bytes = []; + $numbytes = 1; + } + } else { + $ord = false; + break; + } + } + + return $ord; + } + function getTable() { $this->parseTableEntries(); @@ -157,7 +223,7 @@ function utf8toUnicode($str) { function getUnicodeCharMap() { $subtable = null; foreach ($this->getData("cmap", "subtables") as $_subtable) { - if ($_subtable["platformID"] == 0 || $_subtable["platformID"] == 3 && $_subtable["platformSpecificID"] == 1) { + if ($_subtable["platformID"] == 0 || ($_subtable["platformID"] == 3 && $_subtable["platformSpecificID"] == 1)) { $subtable = $_subtable; break; } @@ -167,6 +233,51 @@ function getUnicodeCharMap() { return $subtable["glyphIndexArray"]; } + $system_encodings = mb_list_encodings(); + $system_encodings = array_change_key_case(array_fill_keys($system_encodings, true), CASE_UPPER); + foreach ($this->getData("cmap", "subtables") as $_subtable) { + $encoding = null; + switch ($_subtable["platformID"]) { + case 3: + switch ($_subtable["platformSpecificID"]) { + case 2: + if (\array_key_exists("SJIS", $system_encodings)) { + $encoding = "SJIS"; + } + break; + case 3: + if (\array_key_exists("GB18030", $system_encodings)) { + $encoding = "GB18030"; + } + break; + case 4: + if (\array_key_exists("BIG-5", $system_encodings)) { + $encoding = "BIG-5"; + } + break; + case 5: + if (\array_key_exists("UHC", $system_encodings)) { + $encoding = "UHC"; + } + break; + } + break; + } + if ($encoding) { + $glyphIndexArray = array(); + foreach ($_subtable["glyphIndexArray"] as $c => $gid) { + $str = trim(pack("N", $c)); + if (\strlen($str) > 0) { + $ord = $this->uniord($str, $encoding); + if ($ord > 0) { + $glyphIndexArray[$ord] = $gid; + } + } + } + return $glyphIndexArray; + } + } + return null; } @@ -199,11 +310,11 @@ function setSubset($subset) { /** @var glyf $glyf */ $glyf = $this->getTableObject("glyf"); - $gids = $glyf->getGlyphIDs($gids); - - sort($gids); - - $this->glyph_subset = $gids; + if ($glyf) { + $gids = $glyf->getGlyphIDs($gids); + sort($gids); + $this->glyph_subset = $gids; + } $this->glyph_all = array_values($glyphIndexArray); // FIXME } @@ -217,13 +328,12 @@ function getSubset() { function encode($tags = array()) { if (!self::$raw) { - $tags = array_merge(array("head", "hhea", "cmap", "hmtx", "maxp", "glyf", "loca", "name", "post"), $tags); + $tags = array_merge(array("head", "hhea", "cmap", "hmtx", "maxp", "glyf", "loca", "name", "post", "cvt ", "fpgm", "prep"), $tags); } else { $tags = array_keys($this->directory); } - $num_tables = count($tags); $n = 16; // @todo Font::d("Tables : " . implode(", ", $tags)); @@ -239,7 +349,14 @@ function encode($tags = array()) { $entries[$tag] = $this->directory[$tag]; } + $num_tables = count($entries); + $exponent = floor(log($num_tables, 2)); + $power_of_two = pow(2, $exponent); + $this->header->data["numTables"] = $num_tables; + $this->header->data["searchRange"] = $power_of_two * 16; + $this->header->data["entrySelector"] = log($power_of_two, 2); + $this->header->data["rangeShift"] = $num_tables * 16 - $this->header->data["searchRange"]; $this->header->encode(); $directory_offset = $this->pos(); @@ -326,7 +443,10 @@ protected function readTable($tag) { * @return Table */ public function getTableObject($name) { - return $this->data[$name]; + if (\array_key_exists($name, $this->data)) { + return $this->data[$name]; + } + return null; } public function setTableObject($name, Table $data) { diff --git a/vendor/phenx/php-font-lib/src/FontLib/TrueType/Header.php b/vendor/phenx/php-font-lib/src/FontLib/TrueType/Header.php index 7ff79cc..652e66f 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/TrueType/Header.php +++ b/vendor/phenx/php-font-lib/src/FontLib/TrueType/Header.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/TrueType/TableDirectoryEntry.php b/vendor/phenx/php-font-lib/src/FontLib/TrueType/TableDirectoryEntry.php index fc4fe55..9cf4489 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/TrueType/TableDirectoryEntry.php +++ b/vendor/phenx/php-font-lib/src/FontLib/TrueType/TableDirectoryEntry.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/WOFF/File.php b/vendor/phenx/php-font-lib/src/FontLib/WOFF/File.php index 4668c23..2c6dff4 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/WOFF/File.php +++ b/vendor/phenx/php-font-lib/src/FontLib/WOFF/File.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/WOFF/Header.php b/vendor/phenx/php-font-lib/src/FontLib/WOFF/Header.php index 65a6f14..9911c97 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/WOFF/Header.php +++ b/vendor/phenx/php-font-lib/src/FontLib/WOFF/Header.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-font-lib/src/FontLib/WOFF/TableDirectoryEntry.php b/vendor/phenx/php-font-lib/src/FontLib/WOFF/TableDirectoryEntry.php index eb67c9c..5f66311 100644 --- a/vendor/phenx/php-font-lib/src/FontLib/WOFF/TableDirectoryEntry.php +++ b/vendor/phenx/php-font-lib/src/FontLib/WOFF/TableDirectoryEntry.php @@ -1,7 +1,7 @@ * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ diff --git a/vendor/phenx/php-svg-lib/README.md b/vendor/phenx/php-svg-lib/README.md index 2b8e6f6..ff3c921 100644 --- a/vendor/phenx/php-svg-lib/README.md +++ b/vendor/phenx/php-svg-lib/README.md @@ -1,7 +1,6 @@ # SVG file parsing / rendering library -[![Build Status](https://github.com/phenx/php-svg-lib/workflows/test/badge.svg)](https://github.com/phenx/php-svg-lib/actions) - +[![Build Status](https://github.com/dompdf/php-svg-lib/actions/workflows/test.yml/badge.svg)](https://github.com/dompdf/php-svg-lib/actions/workflows/test.yml) [![Latest Stable Version](https://poser.pugx.org/phenx/php-svg-lib/v/stable)](https://packagist.org/packages/phenx/php-svg-lib) [![Total Downloads](https://poser.pugx.org/phenx/php-svg-lib/downloads)](https://packagist.org/packages/phenx/php-svg-lib) @@ -10,4 +9,4 @@ The main purpose of this lib is to rasterize SVG to a surface which can be an image or a PDF for example, through a `\Svg\Surface` PHP interface. -This project was initialized by the need to render SVG documents inside PDF files for the [DomPdf](http://dompdf.github.io) project. +This project was initialized by the need to render SVG documents inside PDF files for the [DomPdf](https://github.com/dompdf/dompdf) project. diff --git a/vendor/phenx/php-svg-lib/SECURITY.md b/vendor/phenx/php-svg-lib/SECURITY.md deleted file mode 100644 index af4afc0..0000000 --- a/vendor/phenx/php-svg-lib/SECURITY.md +++ /dev/null @@ -1,16 +0,0 @@ -# Security Policy - -## Supported Versions - -Because of limited resources and general compatibility -between versions only the [latest release](https://github.com/dompdf/php-svg-lib/releases) of Dompdf -is actively supported. - -## Reporting a Vulnerability - -In order to give the community time to respond and patch -we strongly urge you report all security issues privately. -New vulnerabilities can be reported through the GitHub -[Security Advisories](https://github.com/dompdf/php-svg-lib/security/advisories) -feature. If you have any questions email us at security@dompdf.org and -we will respond ASAP. diff --git a/vendor/phenx/php-svg-lib/composer.json b/vendor/phenx/php-svg-lib/composer.json index a6ed9c5..910a0a1 100644 --- a/vendor/phenx/php-svg-lib/composer.json +++ b/vendor/phenx/php-svg-lib/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "A library to read, parse and export to PDF SVG files.", "homepage": "https://github.com/PhenX/php-svg-lib", - "license": "LGPL-3.0", + "license": "LGPL-3.0-or-later", "authors": [ { "name": "Fabien Ménager", diff --git a/vendor/phenx/php-svg-lib/src/Svg/Document.php b/vendor/phenx/php-svg-lib/src/Svg/Document.php index 309875b..b6448f3 100644 --- a/vendor/phenx/php-svg-lib/src/Svg/Document.php +++ b/vendor/phenx/php-svg-lib/src/Svg/Document.php @@ -23,6 +23,7 @@ use Svg\Tag\Polyline; use Svg\Tag\Rect; use Svg\Tag\Stop; +use Svg\Tag\Symbol; use Svg\Tag\Text; use Svg\Tag\StyleTag; use Svg\Tag\UseTag; @@ -30,6 +31,7 @@ class Document extends AbstractTag { protected $filename; + protected $_defs_depth = 0; public $inDefs = false; protected $x; @@ -80,6 +82,31 @@ public function __construct() { } + /** + * Increase the nesting level for defs-like elements + * + * @return int + */ + public function enterDefs () { + $this->_defs_depth++; + $this->inDefs = true; + return $this->_defs_depth; + } + + /** + * Decrease the nesting level for defs-like elements + * + * @return int + */ + public function exitDefs () { + $this->_defs_depth--; + if ($this->_defs_depth < 0) { + $this->_defs_depth = 0; + } + $this->inDefs = ($this->_defs_depth > 0 ? true : false); + return $this->_defs_depth; + } + /** * @return SurfaceInterface */ @@ -133,6 +160,7 @@ function ($parser, $name) {} break; } } + xml_parse($parser, "", true); xml_parser_free($parser); @@ -202,7 +230,7 @@ protected function before($attributes) { $surface = $this->getSurface(); - $style = new DefaultStyle(); + $style = new DefaultStyle($this); $style->inherit($this); $style->fromAttributes($attributes); @@ -213,6 +241,7 @@ protected function before($attributes) public function render(SurfaceInterface $surface) { + $this->_defs_depth = 0; $this->inDefs = false; $this->surface = $surface; @@ -256,7 +285,7 @@ private function _tagStart($parser, $name, $attributes) switch (strtolower($name)) { case 'defs': - $this->inDefs = true; + $this->enterDefs(); return; case 'svg': @@ -322,10 +351,14 @@ private function _tagStart($parser, $name, $attributes) break; case 'g': - case 'symbol': $tag = new Group($this, $name); break; + case 'symbol': + $this->enterDefs(); + $tag = new Symbol($this, $name); + break; + case 'clippath': $tag = new ClipPath($this, $name); break; @@ -375,9 +408,14 @@ function _tagEnd($parser, $name) $tag = null; switch (strtolower($name)) { case 'defs': - $this->inDefs = false; + $this->exitDefs(); return; + case 'symbol': + $this->exitDefs(); + $tag = array_pop($this->stack); + break; + case 'svg': case 'path': case 'rect': @@ -393,7 +431,6 @@ function _tagEnd($parser, $name) case 'style': case 'text': case 'g': - case 'symbol': case 'clippath': case 'use': case 'a': @@ -401,7 +438,7 @@ function _tagEnd($parser, $name) break; } - if (!$this->inDefs && $tag) { + if ((!$this->inDefs && $tag) || $tag instanceof StyleTag) { $tag->handleEnd(); } } diff --git a/vendor/phenx/php-svg-lib/src/Svg/Style.php b/vendor/phenx/php-svg-lib/src/Svg/Style.php index 514f546..5234d47 100644 --- a/vendor/phenx/php-svg-lib/src/Svg/Style.php +++ b/vendor/phenx/php-svg-lib/src/Svg/Style.php @@ -18,6 +18,7 @@ class Style const TYPE_ANGLE = 4; const TYPE_NUMBER = 5; + private $_document; private $_parentStyle; public $color; @@ -43,6 +44,12 @@ class Style public $fontStyle = 'normal'; public $textAnchor = 'start'; + public function __construct($document = null) { + if ($document !== null) { + $this->_document = $document; + } + } + protected function getStyleMap() { return array( @@ -139,16 +146,6 @@ public function fromStyleSheets(AbstractTag $tag, $attributes) { break; } } - - if ( - \array_key_exists("font-family", $styles) - && ( - \strtolower(\substr($this->href, 0, 7)) === "phar://" - || ($this->document->allowExternalReferences === false && \strtolower(\substr($this->href, 0, 5)) !== "data:") - ) - ) { - unset($style["font-family"]); - } } } @@ -172,7 +169,7 @@ protected function fillStyles($styles) $value = $this->color; } } - if ($value !== null && $value[3] !== 1 && array_key_exists("{$from}-opacity", $style_map) === true) { + if (is_array($value) && $value[3] !== 1.0 && array_key_exists("{$from}-opacity", $style_map) === true) { $styles["{$from}-opacity"] = $value[3]; } break; @@ -185,6 +182,16 @@ protected function fillStyles($styles) $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; } @@ -212,6 +219,10 @@ static function parseColor($color) 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]); @@ -227,7 +238,7 @@ static function parseColor($color) return self::getQuad($color); } - // RGB color + // HSL color if (strpos($color, "hsl") !== false) { $quad = self::getQuad($color, true); @@ -304,7 +315,8 @@ static function parseColor($color) return null; } - return trim(substr($color, $i + 1, $j - $i - 1)); + //FIXME: gradients not supported? + return null; // trim(substr($color, $i + 1, $j - $i - 1)); } return null; @@ -321,7 +333,7 @@ static function getQuad($color, $percent = false) { $quad = preg_split("/\\s*[,\\/]\\s*/", trim(substr($color, $i + 1, $j - $i - 1))); if (!isset($quad[3])) { - $quad[3] = 1; + $quad[3] = "1"; } if (count($quad) != 3 && count($quad) != 4) { @@ -335,11 +347,13 @@ static function getQuad($color, $percent = false) { if ($quad[$c][strlen($quad[$c]) - 1] === "%") { $quad[$c] = floatval($quad[$c]) / 100; } else { - $quad[$c] = $quad[$c] / 255; + $quad[$c] = floatval($quad[$c]) / 255; } } else { if ($quad[$c][strlen($quad[$c]) - 1] === "%") { - $quad[$c] = round(floatval($quad[$c]) * 2.55); + $quad[$c] = floatval($quad[$c]) * 2.55; + } else { + $quad[$c] = floatval($quad[$c]); } } } @@ -349,7 +363,7 @@ static function getQuad($color, $percent = false) { static function parseHexColor($hex) { - $c = array(0, 0, 0, 1); + $c = array(0.0, 0.0, 0.0, 1.0); // #FFFFFF if (isset($hex[6])) { diff --git a/vendor/phenx/php-svg-lib/src/Svg/Surface/CPdf.php b/vendor/phenx/php-svg-lib/src/Svg/Surface/CPdf.php index caa28a8..e24f6f2 100644 --- a/vendor/phenx/php-svg-lib/src/Svg/Surface/CPdf.php +++ b/vendor/phenx/php-svg-lib/src/Svg/Surface/CPdf.php @@ -1044,7 +1044,7 @@ protected function getFontSubsettingTag(array $font): string } } - return 'SUB' . str_pad($base_26, 3 , 'A', STR_PAD_LEFT); + return 'SUB' . str_pad($base_26, 3, 'A', STR_PAD_LEFT); } /** @@ -1314,7 +1314,7 @@ protected function o_toUnicode($id, $action) $res = "\n$id 0 obj\n"; $res .= "<>\n"; - $res .= "stream\n" . $stream . "\nendstream" . "\nendobj";; + $res .= "stream\n" . $stream . "\nendstream" . "\nendobj"; return $res; } @@ -1724,14 +1724,14 @@ protected function o_info($id, $action, $options = '') // dates must be outputted as-is, without Unicode transformations if ($k !== 'CreationDate' && $k !== 'ModDate') { - $v = $this->filterText($v, true, false); + $v = $this->utf8toUtf16BE($v); } if ($encrypted) { $v = $this->ARC4($v); } - $res .= $v; + $res .= $this->filterText($v, false, false); $res .= ")\n"; } @@ -2356,8 +2356,7 @@ protected function o_xobject($id, $action, $options = '') $res = "\n$id 0 obj\n<< /Type /XObject\n"; foreach ($o["info"] as $k => $v) { - switch($k) - { + switch ($k) { case 'Subtype': $res .= "/Subtype /$v\n"; break; @@ -2410,7 +2409,7 @@ protected function o_xobject($id, $action, $options = '') } $res .= "/Length " . mb_strlen($tmp, '8bit') . " >>\n"; - $res .= "stream\n" . $tmp . "\nendstream" . "\nendobj";; + $res .= "stream\n" . $tmp . "\nendstream" . "\nendobj"; return $res; } @@ -2448,7 +2447,7 @@ protected function o_acroform($id, $action, $options = '') $res = "\n$id 0 obj\n<<"; foreach ($o["info"] as $k => $v) { - switch($k) { + switch ($k) { case 'Fields': $res .= " /Fields ["; foreach ($v as $i) { @@ -2552,7 +2551,7 @@ protected function o_field($id, $action, $options = '') $res .= ">>\n"; break; case 'T': - if($encrypted) { + if ($encrypted) { $v = $this->filterText($this->ARC4($v), false, false); } $res .= "/T ($v)\n"; @@ -2595,7 +2594,7 @@ protected function o_sig($id, $action, $options = '') $pos = strpos($content, sprintf("/ByteRange [ %'.010d", $id)); $len = strlen('/ByteRange [ ********** ********** ********** ********** ]'); $rangeStartPos = $pos + $len + 1 + 10; // before '<' - $content = substr_replace($content, str_pad(sprintf('/ByteRange [ 0 %u %u %u ]', $rangeStartPos, $rangeStartPos + $sign_maxlen + 2, $content_len - 2 - $sign_maxlen - $rangeStartPos ), $len, ' ', STR_PAD_RIGHT), $pos, $len); + $content = substr_replace($content, str_pad(sprintf('/ByteRange [ 0 %u %u %u ]', $rangeStartPos, $rangeStartPos + $sign_maxlen + 2, $content_len - 2 - $sign_maxlen - $rangeStartPos), $len, ' ', STR_PAD_RIGHT), $pos, $len); $fuid = uniqid(); $tmpInput = $this->tmp . "/pkcs7.tmp." . $fuid . '.in'; @@ -2659,7 +2658,7 @@ protected function o_sig($id, $action, $options = '') $o = &$this->objects[$id]; foreach ($o['info'] as $k => $v) { - switch($k) { + switch ($k) { case 'Name': case 'Location': case 'Reason': @@ -2785,7 +2784,7 @@ protected function o_indirect_references($id, $action, $options = null) case 'out': $res = "\n$id 0 obj << "; - foreach($this->objects[$id]['info'] as $referenceObjName => $referenceObjId) { + foreach ($this->objects[$id]['info'] as $referenceObjName => $referenceObjId) { $res .= "/$referenceObjName $referenceObjId 0 R "; } @@ -2851,16 +2850,18 @@ protected function o_embedded_file_dictionary($id, $action, $options = null) break; case 'out': $info = &$this->objects[$id]['info']; + $filename = $this->utf8toUtf16BE($info['filename']); + $description = $this->utf8toUtf16BE($info['description']); if ($this->encrypted) { $this->encryptInit($id); - $filename = $this->ARC4($info['filename']); - $description = $this->ARC4($info['description']); - } else { - $filename = $info['filename']; - $description = $info['description']; + $filename = $this->ARC4($filename); + $description = $this->ARC4($description); } + $filename = $this->filterText($filename, false, false); + $description = $this->filterText($description, false, false); + $res = "\n$id 0 obj <>"; $res .= " /F ($filename) /UF ($filename) /Desc ($description)"; @@ -3241,11 +3242,11 @@ private function openFont($font) { // assume that $font contains the path and file but not the extension $name = basename($font); - $dir = dirname($font) . '/'; + $dir = dirname($font); $fontcache = $this->fontcache; if ($fontcache == '') { - $fontcache = rtrim($dir, DIRECTORY_SEPARATOR."/\\"); + $fontcache = $dir; } //$name filename without folder and extension of font metrics @@ -3262,36 +3263,22 @@ private function openFont($font) $metrics_name = "$name.ufm"; } - $cache_name = "$metrics_name.php"; + $cache_name = "$metrics_name.json"; $this->addMessage("metrics: $metrics_name, cache: $cache_name"); if (file_exists($fontcache . '/' . $cache_name)) { - $this->addMessage("openFont: php file exists $fontcache/$cache_name"); - $this->fonts[$font] = require($fontcache . '/' . $cache_name); - - if (!isset($this->fonts[$font]['_version_']) || $this->fonts[$font]['_version_'] != $this->fontcacheVersion) { - // if the font file is old, then clear it out and prepare for re-creation - $this->addMessage('openFont: clear out, make way for new version.'); - $this->fonts[$font] = null; - unset($this->fonts[$font]); - } - } else { - $old_cache_name = "php_$metrics_name"; - if (file_exists($fontcache . '/' . $old_cache_name)) { - $this->addMessage( - "openFont: php file doesn't exist $fontcache/$cache_name, creating it from the old format" - ); - $old_cache = file_get_contents($fontcache . '/' . $old_cache_name); - file_put_contents($fontcache . '/' . $cache_name, 'openFont($font); - return; + $this->addMessage("openFont: json metrics file exists $fontcache/$cache_name"); + $cached_font_info = json_decode(file_get_contents($fontcache . '/' . $cache_name), true); + if (!isset($cached_font_info['_version_']) || $cached_font_info['_version_'] != $this->fontcacheVersion) { + $this->addMessage('openFont: font cache is out of date, regenerating'); + } else { + $this->fonts[$font] = $cached_font_info; } } - if (!isset($this->fonts[$font]) && file_exists($dir . $metrics_name)) { + if (!isset($this->fonts[$font]) && file_exists("$dir/$metrics_name")) { // then rebuild the php_.afm file from the .afm file - $this->addMessage("openFont: build php file from $dir$metrics_name"); + $this->addMessage("openFont: build php file from $dir/$metrics_name"); $data = []; // 20 => 'space' @@ -3306,7 +3293,7 @@ private function openFont($font) $cidtogid = str_pad('', 256 * 256 * 2, "\x00"); } - $file = file($dir . $metrics_name); + $file = file("$dir/$metrics_name"); foreach ($file as $rowA) { $row = trim($rowA); @@ -3460,7 +3447,7 @@ private function openFont($font) //Because of potential trouble with php safe mode, expect that the folder already exists. //If not existing, this will hit performance because of missing cached results. if (is_dir($fontcache) && is_writable($fontcache)) { - file_put_contents($fontcache . '/' . $cache_name, 'fonts[$font])) { $this->addMessage("openFont: no font file found for $font. Do you need to run load_font.php?"); } - - //pre_r($this->messages); } /** @@ -3479,7 +3464,7 @@ private function openFont($font) * note that encoding='none' will need to be used for symbolic fonts * and 'differences' => an array of mappings between numbers 0->255 and character names. * - * @param $fontName + * @param string $fontName * @param string $encoding * @param bool $set * @param bool $isSubsetting @@ -3627,8 +3612,8 @@ private function addContent($content) /** * sets the color for fill operations * - * @param $color - * @param bool $force + * @param array $color + * @param bool $force */ function setColor($color, $force = false) { @@ -3652,7 +3637,7 @@ function setColor($color, $force = false) /** * sets the color for fill operations * - * @param $fillRule + * @param string $fillRule */ function setFillRule($fillRule) { @@ -3666,8 +3651,8 @@ function setFillRule($fillRule) /** * sets the color for stroke operations * - * @param $color - * @param bool $force + * @param array $color + * @param bool $force */ function setStrokeColor($color, $force = false) { @@ -3818,11 +3803,11 @@ function setFillTransparency($mode, $opacity) /** * draw a line from one set of coordinates to another * - * @param $x1 - * @param $y1 - * @param $x2 - * @param $y2 - * @param bool $stroke + * @param float $x1 + * @param float $y1 + * @param float $x2 + * @param float $y2 + * @param bool $stroke */ function line($x1, $y1, $x2, $y2, $stroke = true) { @@ -3836,14 +3821,14 @@ function line($x1, $y1, $x2, $y2, $stroke = true) /** * draw a bezier curve based on 4 control points * - * @param $x0 - * @param $y0 - * @param $x1 - * @param $y1 - * @param $x2 - * @param $y2 - * @param $x3 - * @param $y3 + * @param float $x0 + * @param float $y0 + * @param float $x1 + * @param float $y1 + * @param float $x2 + * @param float $y2 + * @param float $x3 + * @param float $y3 */ function curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3) { @@ -3857,13 +3842,13 @@ function curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3) /** * draw a part of an ellipse * - * @param $x0 - * @param $y0 - * @param $astart - * @param $afinish - * @param $r1 - * @param int $r2 - * @param int $angle + * @param float $x0 + * @param float $y0 + * @param float $astart + * @param float $afinish + * @param float $r1 + * @param float $r2 + * @param float $angle * @param int $nSeg */ function partEllipse($x0, $y0, $astart, $afinish, $r1, $r2 = 0, $angle = 0, $nSeg = 8) @@ -3874,14 +3859,14 @@ function partEllipse($x0, $y0, $astart, $afinish, $r1, $r2 = 0, $angle = 0, $nSe /** * draw a filled ellipse * - * @param $x0 - * @param $y0 - * @param $r1 - * @param int $r2 - * @param int $angle + * @param float $x0 + * @param float $y0 + * @param float $r1 + * @param float $r2 + * @param float $angle * @param int $nSeg - * @param int $astart - * @param int $afinish + * @param float $astart + * @param float $afinish */ function filledEllipse($x0, $y0, $r1, $r2 = 0, $angle = 0, $nSeg = 8, $astart = 0, $afinish = 360) { @@ -3889,8 +3874,8 @@ function filledEllipse($x0, $y0, $r1, $r2 = 0, $angle = 0, $nSeg = 8, $astart = } /** - * @param $x - * @param $y + * @param float $x + * @param float $y */ function lineTo($x, $y) { @@ -3898,8 +3883,8 @@ function lineTo($x, $y) } /** - * @param $x - * @param $y + * @param float $x + * @param float $y */ function moveTo($x, $y) { @@ -3909,12 +3894,12 @@ function moveTo($x, $y) /** * draw a bezier curve based on 4 control points * - * @param $x1 - * @param $y1 - * @param $x2 - * @param $y2 - * @param $x3 - * @param $y3 + * @param float $x1 + * @param float $y1 + * @param float $x2 + * @param float $y2 + * @param float $x3 + * @param float $y3 */ function curveTo($x1, $y1, $x2, $y2, $x3, $y3) { @@ -3923,6 +3908,11 @@ function curveTo($x1, $y1, $x2, $y2, $x3, $y3) /** * draw a bezier curve based on 4 control points + * + * @param float $cpx + * @param float $cpy + * @param float $x + * @param float $y */ function quadTo($cpx, $cpy, $x, $y) { @@ -3950,18 +3940,18 @@ function endPath() * nSeg is not allowed to be less than 2, as this will simply draw a line (and will even draw a * pretty crappy shape at 2, as we are approximating with bezier curves. * - * @param $x0 - * @param $y0 - * @param $r1 - * @param int $r2 - * @param int $angle - * @param int $nSeg - * @param int $astart - * @param int $afinish - * @param bool $close - * @param bool $fill - * @param bool $stroke - * @param bool $incomplete + * @param float $x0 + * @param float $y0 + * @param float $r1 + * @param float $r2 + * @param float $angle + * @param int $nSeg + * @param float $astart + * @param float $afinish + * @param bool $close + * @param bool $fill + * @param bool $stroke + * @param bool $incomplete */ function ellipse( $x0, @@ -4075,11 +4065,11 @@ function ellipse( * (2,1) is 2 on, 1 off, 2 on, 1 off.. etc * phase is a modifier on the dash pattern which is used to shift the point at which the pattern starts. * - * @param int $width + * @param float $width * @param string $cap * @param string $join - * @param string $dash - * @param int $phase + * @param array $dash + * @param int $phase */ function setLineStyle($width = 1, $cap = '', $join = '', $dash = '', $phase = 0) { @@ -4113,19 +4103,19 @@ function setLineStyle($width = 1, $cap = '', $join = '', $dash = '', $phase = 0) /** * draw a polygon, the syntax for this is similar to the GD polygon command * - * @param $p - * @param $np - * @param bool $f + * @param float[] $p + * @param bool $fill */ - function polygon($p, $np, $f = false) + public function polygon(array $p, bool $fill = false): void { $this->addContent(sprintf("\n%.3F %.3F m ", $p[0], $p[1])); - for ($i = 2; $i < $np * 2; $i = $i + 2) { + $n = count($p); + for ($i = 2; $i < $n; $i = $i + 2) { $this->addContent(sprintf("%.3F %.3F l ", $p[$i], $p[$i + 1])); } - if ($f) { + if ($fill) { $this->addContent(' f'); } else { $this->addContent(' S'); @@ -4136,10 +4126,10 @@ function polygon($p, $np, $f = false) * a filled rectangle, note that it is the width and height of the rectangle which are the secondary parameters, not * the coordinates of the upper-right corner * - * @param $x1 - * @param $y1 - * @param $width - * @param $height + * @param float $x1 + * @param float $y1 + * @param float $width + * @param float $height */ function filledRectangle($x1, $y1, $width, $height) { @@ -4150,10 +4140,10 @@ function filledRectangle($x1, $y1, $width, $height) * draw a rectangle, note that it is the width and height of the rectangle which are the secondary parameters, not * the coordinates of the upper-right corner * - * @param $x1 - * @param $y1 - * @param $width - * @param $height + * @param float $x1 + * @param float $y1 + * @param float $width + * @param float $height */ function rectangle($x1, $y1, $width, $height) { @@ -4164,10 +4154,10 @@ function rectangle($x1, $y1, $width, $height) * draw a rectangle, note that it is the width and height of the rectangle which are the secondary parameters, not * the coordinates of the upper-right corner * - * @param $x1 - * @param $y1 - * @param $width - * @param $height + * @param float $x1 + * @param float $y1 + * @param float $width + * @param float $height */ function rect($x1, $y1, $width, $height) { @@ -4279,8 +4269,10 @@ public function addFormField($type, $name, $x0, $y0, $x1, $y1, $ff = 0, $size = $color = implode(' ', $color) . ' rg'; $currentFontNum = $this->currentFontNum; - $font = array_filter($this->objects[$this->currentNode]['info']['fonts'], - function($item) use ($currentFontNum) { return $item['fontNum'] == $currentFontNum; }); + $font = array_filter( + $this->objects[$this->currentNode]['info']['fonts'], + function ($item) use ($currentFontNum) { return $item['fontNum'] == $currentFontNum; } + ); $this->o_acroform($this->acroFormId, 'font', ['objNum' => $font[0]['objNum'], 'fontNum' => $font[0]['fontNum']]); @@ -4395,10 +4387,10 @@ function restore() /** * draw a clipping rectangle, all the elements added after this will be clipped * - * @param $x1 - * @param $y1 - * @param $width - * @param $height + * @param float $x1 + * @param float $y1 + * @param float $width + * @param float $height */ function clippingRectangle($x1, $y1, $width, $height) { @@ -4409,14 +4401,14 @@ function clippingRectangle($x1, $y1, $width, $height) /** * draw a clipping rounded rectangle, all the elements added after this will be clipped * - * @param $x1 - * @param $y1 - * @param $w - * @param $h - * @param $rTL - * @param $rTR - * @param $rBR - * @param $rBL + * @param float $x1 + * @param float $y1 + * @param float $w + * @param float $h + * @param float $rTL + * @param float $rTR + * @param float $rBR + * @param float $rBL */ function clippingRectangleRounded($x1, $y1, $w, $h, $rTL, $rTR, $rBR, $rBL) { @@ -4456,6 +4448,25 @@ function clippingRectangleRounded($x1, $y1, $w, $h, $rTL, $rTR, $rBR, $rBL) $this->addContent(" W n"); } + /** + * draw a clipping polygon, the syntax for this is similar to the GD polygon command + * + * @param float[] $p + */ + public function clippingPolygon(array $p): void + { + $this->save(); + + $this->addContent(sprintf("\n%.3F %.3F m ", $p[0], $p[1])); + + $n = count($p); + for ($i = 2; $i < $n; $i = $i + 2) { + $this->addContent(sprintf("%.3F %.3F l ", $p[$i], $p[$i + 1])); + } + + $this->addContent("W n"); + } + /** * ends the last clipping shape */ @@ -4672,10 +4683,11 @@ function stream($filename = "document.pdf", $options = []) /** * return the height in units of the current font in the given size * - * @param $size - * @return float|int + * @param float $size + * + * @return float */ - function getFontHeight($size) + public function getFontHeight(float $size): float { if (!$this->numFonts) { $this->selectFont($this->defaultFont); @@ -4707,10 +4719,11 @@ function getFontHeight($size) } /** - * @param $size - * @return float|int + * @param float $size + * + * @return float */ - function getFontXHeight($size) + public function getFontXHeight(float $size): float { if (!$this->numFonts) { $this->selectFont($this->defaultFont); @@ -4733,10 +4746,11 @@ function getFontXHeight($size) * if you add this number to the baseline, you get the level of the bottom of the font * it is in the pdf user units * - * @param $size - * @return float|int + * @param float $size + * + * @return float */ - function getFontDescender($size) + public function getFontDescender(float $size): float { // note that this will most likely return a negative value if (!$this->numFonts) { @@ -4753,8 +4767,6 @@ function getFontDescender($size) * filter the text, this is applied to all text just before being inserted into the pdf document * it escapes the various things that need to be escaped, and so on * - * @access private - * * @param $text * @param bool $bom * @param bool $convert_encoding @@ -4774,7 +4786,7 @@ function filterText($text, $bom = true, $convert_encoding = true) //$text = html_entity_decode($text, ENT_QUOTES); $text = mb_convert_encoding($text, self::$targetEncoding, 'UTF-8'); } - } else if ($bom) { + } elseif ($bom) { $text = $this->utf8toUtf16BE($text, $bom); } @@ -4789,12 +4801,7 @@ function filterText($text, $bom = true, $convert_encoding = true) * based on the excellent TCPDF code by Nicola Asuni and the * RFC for UTF-8 at http://www.faqs.org/rfcs/rfc3629.html * - * @access private - * @author Orion Richardson - * @since January 5, 2008 - * * @param string $text UTF-8 string to process - * * @return array UTF-8 codepoints array for the string */ function utf8toCodePointsArray(&$text) @@ -4864,13 +4871,8 @@ function utf8toCodePointsArray(&$text) * based on the excellent TCPDF code by Nicola Asuni and the * RFC for UTF-8 at http://www.faqs.org/rfcs/rfc3629.html * - * @access private - * @author Orion Richardson - * @since January 5, 2008 - * * @param string $text UTF-8 string to process * @param boolean $bom whether to add the byte order marker - * * @return string UTF-16 result string */ function utf8toUtf16BE(&$text, $bom = true) @@ -4945,8 +4947,8 @@ function concatMatches($matches) /** * register text for font subsetting * - * @param $font - * @param $text + * @param string $font + * @param string $text */ function registerText($font, $text) { @@ -4955,7 +4957,8 @@ function registerText($font, $text) } if (!isset($this->stringSubsets[$font])) { - $this->stringSubsets[$font] = []; + $base_subset = "\u{fffd}\u{fffe}\u{ffff}"; + $this->stringSubsets[$font] = $this->utf8toCodePointsArray($base_subset); } $this->stringSubsets[$font] = array_unique( @@ -4966,14 +4969,14 @@ function registerText($font, $text) /** * add text to the document, at a specified location, size and angle on the page * - * @param $x - * @param $y - * @param $size - * @param $text - * @param int $angle - * @param int $wordSpaceAdjust - * @param int $charSpaceAdjust - * @param bool $smallCaps + * @param float $x + * @param float $y + * @param float $size + * @param string $text + * @param float $angle + * @param float $wordSpaceAdjust + * @param float $charSpaceAdjust + * @param bool $smallCaps */ function addText($x, $y, $size, $text, $angle = 0, $wordSpaceAdjust = 0, $charSpaceAdjust = 0, $smallCaps = false) { @@ -5086,13 +5089,14 @@ function addText($x, $y, $size, $text, $angle = 0, $wordSpaceAdjust = 0, $charSp * calculate how wide a given text string will be on a page, at a given size. * this can be called externally, but is also used by the other class functions * - * @param float $size + * @param float $size * @param string $text - * @param float $word_spacing - * @param float $char_spacing + * @param float $wordSpacing + * @param float $charSpacing + * * @return float */ - function getTextWidth($size, $text, $word_spacing = 0, $char_spacing = 0) + public function getTextWidth(float $size, string $text, float $wordSpacing = 0.0, float $charSpacing = 0.0): float { static $ord_cache = []; @@ -5107,9 +5111,6 @@ function getTextWidth($size, $text, $word_spacing = 0, $char_spacing = 0) $text = str_replace(["\r", "\n"], "", $text); - // converts a number or a float to a string so it can get the width - $text = "$text"; - // hmm, this is where it all starts to get tricky - use the font information to // calculate the width of each character, add them up and convert to user units $w = 0; @@ -5136,14 +5137,14 @@ function getTextWidth($size, $text, $word_spacing = 0, $char_spacing = 0) // add additional padding for space if (isset($current_font['codeToName'][$char]) && $current_font['codeToName'][$char] === 'space') { // Space - $w += $word_spacing * $space_scale; + $w += $wordSpacing * $space_scale; } } } // add additional char spacing - if ($char_spacing != 0) { - $w += $char_spacing * $space_scale * count($unicode); + if ($charSpacing != 0) { + $w += $charSpacing * $space_scale * count($unicode); } } else { @@ -5171,14 +5172,14 @@ function getTextWidth($size, $text, $word_spacing = 0, $char_spacing = 0) // add additional padding for space if (isset($current_font['codeToName'][$char]) && $current_font['codeToName'][$char] === 'space') { // Space - $w += $word_spacing * $space_scale; + $w += $wordSpacing * $space_scale; } } } // add additional char spacing - if ($char_spacing != 0) { - $w += $char_spacing * $space_scale * $len; + if ($charSpacing != 0) { + $w += $charSpacing * $space_scale * $len; } } @@ -5418,12 +5419,12 @@ public function addEmbeddedFile(string $filepath, string $embeddedFilename, stri } /** - * add content to the documents info object + * Add content to the documents info object * - * @param $label - * @param int $value + * @param string|array $label + * @param string $value */ - function addInfo($label, $value = 0) + public function addInfo($label, string $value = ""): void { // this will only work if the label is one of the valid ones. // modify this so that arrays can be passed as well. @@ -5431,7 +5432,7 @@ function addInfo($label, $value = 0) // else assume that they are both scalar, anything else will probably error if (is_array($label)) { foreach ($label as $l => $v) { - $this->o_info($this->infoObject, $l, $v); + $this->o_info($this->infoObject, $l, (string) $v); } } else { $this->o_info($this->infoObject, $label, $value); @@ -5568,7 +5569,7 @@ function addImagePng(&$img, $file, $x, $y, $w = 0.0, $h = 0.0, $is_mask = false, protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) { // generate images - $img = imagecreatefrompng($file); + $img = @imagecreatefrompng($file); if ($img === false) { return; @@ -5617,7 +5618,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $alpha_channel->writeimage($tempfile_alpha); // Cast to 8bit+palette - $imgalpha_ = imagecreatefrompng($tempfile_alpha); + $imgalpha_ = @imagecreatefrompng($tempfile_alpha); imagecopy($imgalpha, $imgalpha_, 0, 0, 0, 0, $wpx, $hpx); imagedestroy($imgalpha_); imagepng($imgalpha, $tempfile_alpha); @@ -5630,7 +5631,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $color_channels->compositeimage($gmagick, \Gmagick::COMPOSITE_COPYBLUE, 0, 0); $color_channels->writeimage($tempfile_plain); - $imgplain = imagecreatefrompng($tempfile_plain); + $imgplain = @imagecreatefrompng($tempfile_plain); } // Use PECL imagick + ImageMagic to process transparent PNG images elseif (extension_loaded("imagick")) { @@ -5653,7 +5654,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $imagick->setFormat('png'); // Get opacity channel (negative of alpha channel) - if ($imagick->getImageAlphaChannel() !== 0) { + if ($imagick->getImageAlphaChannel()) { $alpha_channel = $imagickClonable ? clone $imagick : $imagick->clone(); $alpha_channel->separateImageChannel(\Imagick::CHANNEL_ALPHA); // Since ImageMagick7 negate invert transparency as default @@ -5663,7 +5664,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $alpha_channel->writeImage($tempfile_alpha); // Cast to 8bit+palette - $imgalpha_ = imagecreatefrompng($tempfile_alpha); + $imgalpha_ = @imagecreatefrompng($tempfile_alpha); imagecopy($imgalpha, $imgalpha_, 0, 0, 0, 0, $wpx, $hpx); imagedestroy($imgalpha_); imagepng($imgalpha, $tempfile_alpha); @@ -5679,7 +5680,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $color_channels->compositeImage($imagick, \Imagick::COMPOSITE_COPYBLUE, 0, 0); $color_channels->writeImage($tempfile_plain); - $imgplain = imagecreatefrompng($tempfile_plain); + $imgplain = @imagecreatefrompng($tempfile_plain); } else { // allocated colors cache $allocated_colors = []; diff --git a/vendor/phenx/php-svg-lib/src/Svg/Tag/AbstractTag.php b/vendor/phenx/php-svg-lib/src/Svg/Tag/AbstractTag.php index 9fa6793..c74e0eb 100644 --- a/vendor/phenx/php-svg-lib/src/Svg/Tag/AbstractTag.php +++ b/vendor/phenx/php-svg-lib/src/Svg/Tag/AbstractTag.php @@ -59,7 +59,7 @@ public function handle($attributes) { $this->attributes = $attributes; - if (!$this->getDocument()->inDefs) { + if (!$this->getDocument()->inDefs || $this instanceof StyleTag) { $this->before($attributes); $this->start($attributes); } @@ -67,7 +67,7 @@ public function handle($attributes) public function handleEnd() { - if (!$this->getDocument()->inDefs) { + if (!$this->getDocument()->inDefs || $this instanceof StyleTag) { $this->end(); $this->after(); } @@ -119,7 +119,7 @@ public function getStyle() * @return Style */ protected function makeStyle($attributes) { - $style = new Style(); + $style = new Style($this->document); $style->inherit($this); $style->fromStyleSheets($this, $attributes); $style->fromAttributes($attributes); @@ -189,6 +189,97 @@ protected function applyTransform($attributes) } } + /** + * Apply a viewBox transform to the element + * + * @param array $attributes + */ + protected function applyViewbox($attributes) { + if (!isset($attributes["viewbox"])) { + return; + } + + $surface = $this->document->getSurface(); + $viewBox = preg_split('/[\s,]+/is', trim($attributes['viewbox'])); + if (count($viewBox) != 4) { + return; + } + + // Computing the equivalent transform of an SVG viewport + // https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform + + // 1. Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the viewBox attribute respectively. + [$vbX, $vbY, $vbWidth, $vbHeight] = $viewBox; + + if ($vbWidth < 0 || $vbHeight < 0) { + return; + } + + // correct solution is to not render, for now scaling to 0 below + //if ($vbWidth == 0 || $vbHeight == 0) { + //} + + // 2. Let e-x, e-y, e-width, e-height be the position and size of the element respectively. + $eX = $attributes["x"] ?? 0; + $eY = $attributes["y"] ?? 0; + $eWidth = $attributes["width"] ?? $this->document->getWidth(); + $eHeight = $attributes["height"] ?? $this->document->getHeight(); + + // 3. Let align be the align value of preserveAspectRatio, or 'xMidYMid' if preserveAspectRatio is not defined. + $preserveAspectRatio = explode(" ", $attributes["preserveAspectRatio"] ?? "xMidYMid meet"); + $align = $preserveAspectRatio[0]; + + // 4. Let meetOrSlice be the meetOrSlice value of preserveAspectRatio, or 'meet' if preserveAspectRatio is not defined or if meetOrSlice is missing from this value. + $meetOrSlice = $meetOrSlice ?? "meet"; + + // 5. Initialize scale-x to e-width/vb-width. + $scaleX = $vbWidth == 0 ? 0 : ($eWidth / $vbWidth); + + // 6. Initialize scale-y to e-height/vb-height. + $scaleY = $vbHeight == 0 ? 0 : ($eHeight / $vbHeight); + + // 7. If align is not 'none' and meetOrSlice is 'meet', set the larger of scale-x and scale-y to the smaller. + if ($align !== "none" && $meetOrSlice === "meet") { + $scaleX = min($scaleX, $scaleY); + $scaleY = min($scaleX, $scaleY); + } + + // 8. Otherwise, if align is not 'none' and meetOrSlice is 'slice', set the smaller of scale-x and scale-y to the larger. + elseif ($align !== "none" && $meetOrSlice === "slice") { + $scaleX = max($scaleX, $scaleY); + $scaleY = max($scaleX, $scaleY); + } + + // 9. Initialize translate-x to e-x - (vb-x * scale-x). + $translateX = $eX - ($vbX * $scaleX); + + // 10. Initialize translate-y to e-y - (vb-y * scale-y) + $translateY = $eY - ($vbY * $scaleY); + + // 11. If align contains 'xMid', add (e-width - vb-width * scale-x) / 2 to translate-x. + if (strpos($align, "xMid") !== false) { + $translateX += ($eWidth - $vbWidth * $scaleX) / 2; + } + + // 12. If align contains 'xMax', add (e-width - vb-width * scale-x) to translate-x. + if (strpos($align, "xMax") !== false) { + $translateX += ($eWidth - $vbWidth * $scaleX); + } + + // 13. If align contains 'yMid', add (e-height - vb-height * scale-y) / 2 to translate-y. + if (strpos($align, "yMid") !== false) { + $translateX += ($eHeight - $vbHeight * $scaleY) / 2; + } + + // 14. If align contains 'yMax', add (e-height - vb-height * scale-y) to translate-y. + if (strpos($align, "yMid") !== false) { + $translateX += ($eHeight - $vbHeight * $scaleY); + } + + $surface->translate($translateX, $translateY); + $surface->scale($scaleX, $scaleY); + } + /** * Convert the given size for the context of this current tag. * Takes a pixel-based reference, which is usually specific to the context of the size, diff --git a/vendor/phenx/php-svg-lib/src/Svg/Tag/Image.php b/vendor/phenx/php-svg-lib/src/Svg/Tag/Image.php index 8cbfccd..de397c4 100644 --- a/vendor/phenx/php-svg-lib/src/Svg/Tag/Image.php +++ b/vendor/phenx/php-svg-lib/src/Svg/Tag/Image.php @@ -58,7 +58,11 @@ public function start($attributes) $this->document->getSurface()->transform(1, 0, 0, -1, 0, $height); - if (\strtolower(\substr($this->href, 0, 7)) === "phar://" || ($this->document->allowExternalReferences === false && \strtolower(\substr($this->href, 0, 5) !== "data:"))) { + $scheme = \strtolower(parse_url($this->href, PHP_URL_SCHEME) ?: ""); + if ( + $scheme === "phar" || \strtolower(\substr($this->href, 0, 7)) === "phar://" + || ($this->document->allowExternalReferences === false && $scheme !== "data") + ) { return; } diff --git a/vendor/phenx/php-svg-lib/src/Svg/Tag/Path.php b/vendor/phenx/php-svg-lib/src/Svg/Tag/Path.php index 3dce7a6..a2a4c5b 100644 --- a/vendor/phenx/php-svg-lib/src/Svg/Tag/Path.php +++ b/vendor/phenx/php-svg-lib/src/Svg/Tag/Path.php @@ -449,7 +449,12 @@ function drawArc(SurfaceInterface $surface, $fx, $fy, $coords) $toX = $tx - $fx; $toY = $ty - $fy; - if ($toX + $toY === 0) { + if ((float)($toX + $toY) === 0.0) { + return; + } + + if ((float)abs($rx) == 0.0 || (float)abs($ry) === 0.0) { + $surface->lineTo($tx, $ty); return; } diff --git a/vendor/phenx/php-svg-lib/src/Svg/Tag/Symbol.php b/vendor/phenx/php-svg-lib/src/Svg/Tag/Symbol.php new file mode 100644 index 0000000..d00e7ab --- /dev/null +++ b/vendor/phenx/php-svg-lib/src/Svg/Tag/Symbol.php @@ -0,0 +1,34 @@ + + * @license GNU LGPLv3+ http://www.gnu.org/copyleft/lesser.html + */ + +namespace Svg\Tag; + +use Svg\Style; + +class Symbol extends AbstractTag +{ + protected function before($attributes) + { + $surface = $this->document->getSurface(); + + $surface->save(); + + $style = $this->makeStyle($attributes); + + $this->setStyle($style); + $surface->setStyle($style); + + $this->applyViewbox($attributes); + $this->applyTransform($attributes); + } + + protected function after() + { + $this->document->getSurface()->restore(); + } +} \ No newline at end of file diff --git a/vendor/phenx/php-svg-lib/src/Svg/Tag/UseTag.php b/vendor/phenx/php-svg-lib/src/Svg/Tag/UseTag.php index 9e71d59..cb669b9 100644 --- a/vendor/phenx/php-svg-lib/src/Svg/Tag/UseTag.php +++ b/vendor/phenx/php-svg-lib/src/Svg/Tag/UseTag.php @@ -48,10 +48,6 @@ protected function before($attributes) $link = $attributes["href"] ?? $attributes["xlink:href"]; $this->reference = $document->getDef($link); - if ($this->reference) { - $this->reference->before($attributes); - } - $surface = $document->getSurface(); $surface->save(); @@ -63,11 +59,6 @@ protected function after() { return; } parent::after(); - - if ($this->reference) { - $this->reference->after(); - } - $this->getDocument()->getSurface()->restore(); } @@ -84,19 +75,22 @@ public function handle($attributes) return; } + $originalAttributes = array_merge($this->reference->attributes); + $originalStyle = $this->reference->getStyle(); $mergedAttributes = $this->reference->attributes; - $attributesToNotMerge = ['x', 'y', 'width', 'height', 'href', 'xlink:href', 'id']; + $attributesToNotMerge = ['x', 'y', 'width', 'height', 'href', 'xlink:href', 'id', 'style']; foreach ($attributes as $attrKey => $attrVal) { if (!in_array($attrKey, $attributesToNotMerge) && !isset($mergedAttributes[$attrKey])) { $mergedAttributes[$attrKey] = $attrVal; } } + $mergedAttributes['style'] = ($attributes['style'] ?? '') . ';' . ($mergedAttributes['style'] ?? ''); - $this->reference->handle($mergedAttributes); + $this->_handle($this->reference, $mergedAttributes); - foreach ($this->reference->children as $_child) { - $_attributes = array_merge($_child->attributes, $mergedAttributes); - $_child->handle($_attributes); + $this->reference->attributes = $originalAttributes; + if ($originalStyle !== null) { + $this->reference->setStyle($originalStyle); } } @@ -107,16 +101,32 @@ public function handleEnd() return; } + if ($this->reference) { + $this->_handleEnd($this->reference); + } + parent::handleEnd(); + } - if (!$this->reference) { - return; + private function _handle($tag, $attributes) { + $tag->handle($attributes); + foreach ($tag->children as $child) { + $originalAttributes = array_merge($child->attributes); + $originalStyle = $child->getStyle(); + $mergedAttributes = $child->attributes; + $mergedAttributes['style'] = ($attributes['style'] ?? '') . ';' . ($mergedAttributes['style'] ?? ''); + $this->_handle($child, $mergedAttributes); + $child->attributes = $originalAttributes; + if ($originalStyle !== null) { + $child->setStyle($originalStyle); + } } + } - $this->reference->handleEnd(); - - foreach ($this->reference->children as $_child) { - $_child->handleEnd(); + private function _handleEnd($tag) { + foreach ($tag->children as $child) { + $this->_handleEnd($child); } + $tag->handleEnd(); } } diff --git a/vendor/sabberworm/php-css-parser/CHANGELOG.md b/vendor/sabberworm/php-css-parser/CHANGELOG.md index a23fd0e..302cf1d 100644 --- a/vendor/sabberworm/php-css-parser/CHANGELOG.md +++ b/vendor/sabberworm/php-css-parser/CHANGELOG.md @@ -1,4 +1,41 @@ -# Revision History +# Changelog + +All notable changes to this project will be documented in this file. +This project adheres to [Semantic Versioning](https://semver.org/). + +## x.y.z + +### Added + +### Changed + +### Deprecated + +### Removed + +### Fixed + +## 8.5.1 + +### Fixed + +- Fix (regression) failure to parse at-rules with strict parsing (#456) + +## 8.5.0 + +### Added + +- Add a method to get an import's media queries (#384) +- Add more unit tests (#381, #382) + +### Fixed + +- Retain CSSList and Rule comments when rendering CSS (#351) +- Replace invalid `turns` unit with `turn` (#350) +- Also allow string values for rules (#348) +- Fix invalid calc parsing (#169) +- Handle scientific notation when parsing sizes (#179) +- Fix PHP 8.1 compatibility in `ParserState::strsplit()` (#344) ## 8.4.0 diff --git a/vendor/sabberworm/php-css-parser/README.md b/vendor/sabberworm/php-css-parser/README.md index 66fb1c6..90428cb 100644 --- a/vendor/sabberworm/php-css-parser/README.md +++ b/vendor/sabberworm/php-css-parser/README.md @@ -33,7 +33,7 @@ The resulting CSS document structure can be manipulated prior to being output. #### Charset -The charset option is used only if no `@charset` declaration is found in the CSS file. UTF-8 is the default, so you won’t have to create a settings object at all if you don’t intend to change that. +The charset option will only be used if the CSS file does not contain an `@charset` declaration. UTF-8 is the default, so you won’t have to create a settings object at all if you don’t intend to change that. ```php $settings = \Sabberworm\CSS\Settings::create() @@ -43,7 +43,7 @@ $parser = new \Sabberworm\CSS\Parser($css, $settings); #### Strict parsing -To have the parser choke on invalid rules, supply a thusly configured `\Sabberworm\CSS\Settings` object: +To have the parser throw an exception when encountering invalid/unknown constructs (as opposed to trying to ignore them and carry on parsing), supply a thusly configured `\Sabberworm\CSS\Settings` object: ```php $parser = new \Sabberworm\CSS\Parser( @@ -52,6 +52,8 @@ $parser = new \Sabberworm\CSS\Parser( ); ``` +Note that this will also disable a workaround for parsing the unquoted variant of the legacy IE-specific `filter` rule. + #### Disable multibyte functions To achieve faster parsing, you can choose to have PHP-CSS-Parser use regular string functions instead of `mb_*` functions. This should work fine in most cases, even for UTF-8 files, as all the multibyte characters are in string literals. Still it’s not recommended using this with input you have no control over as it’s not thoroughly covered by test cases. @@ -67,12 +69,9 @@ The resulting data structure consists mainly of five basic types: `CSSList`, `Ru #### CSSList -`CSSList` represents a generic CSS container, most likely containing declaration blocks (rule sets with a selector), but it may also contain at-rules, charset declarations, etc. `CSSList` has the following concrete subtypes: - -* `Document` – representing the root of a CSS file. -* `MediaQuery` – represents a subsection of a `CSSList` that only applies to an output device matching the contained media query. +`CSSList` represents a generic CSS container, most likely containing declaration blocks (rule sets with a selector), but it may also contain at-rules, charset declarations, etc. -To access the items stored in a `CSSList` – like the document you got back when calling `$parser->parse()` –, use `getContents()`, then iterate over that collection and use instanceof to check whether you’re dealing with another `CSSList`, a `RuleSet`, a `Import` or a `Charset`. +To access the items stored in a `CSSList` – like the document you got back when calling `$parser->parse()` –, use `getContents()`, then iterate over that collection and use `instanceof` to check whether you’re dealing with another `CSSList`, a `RuleSet`, a `Import` or a `Charset`. To append a new item (selector, media query, etc.) to an existing `CSSList`, construct it using the constructor for this class and use the `append($oItem)` method. @@ -80,16 +79,16 @@ To append a new item (selector, media query, etc.) to an existing `CSSList`, con `RuleSet` is a container for individual rules. The most common form of a rule set is one constrained by a selector. The following concrete subtypes exist: -* `AtRuleSet` – for generic at-rules which do not match the ones specifically mentioned like `@import`, `@charset` or `@media`. A common example for this is `@font-face`. +* `AtRuleSet` – for generic at-rules for generic at-rules which are not covered by specific classes, i.e., not `@import`, `@charset` or `@media`. A common example for this is `@font-face`. * `DeclarationBlock` – a `RuleSet` constrained by a `Selector`; contains an array of selector objects (comma-separated in the CSS) as well as the rules to be applied to the matching elements. Note: A `CSSList` can contain other `CSSList`s (and `Import`s as well as a `Charset`), while a `RuleSet` can only contain `Rule`s. -If you want to manipulate a `RuleSet`, use the methods `addRule(Rule $rule)`, `getRules()` and `removeRule($rule)` (which accepts either a `Rule` instance or a rule name; optionally suffixed by a dash to remove all related rules). +If you want to manipulate a `RuleSet`, use the methods `addRule(Rule $rule)`, `getRules()` and `removeRule($rule)` (which accepts either a `Rule` or a rule name; optionally suffixed by a dash to remove all related rules). #### Rule -`Rule`s just have a key (the rule) and a value. These values are all instances of a `Value`. +`Rule`s just have a string key (the rule) and a `Value`. #### Value @@ -98,19 +97,21 @@ If you want to manipulate a `RuleSet`, use the methods `addRule(Rule $rule)`, `g * `Size` – consists of a numeric `size` value and a unit. * `Color` – colors can be input in the form #rrggbb, #rgb or schema(val1, val2, …) but are always stored as an array of ('s' => val1, 'c' => val2, 'h' => val3, …) and output in the second form. * `CSSString` – this is just a wrapper for quoted strings to distinguish them from keywords; always output with double quotes. -* `URL` – URLs in CSS; always output in URL("") notation. +* `URL` – URLs in CSS; always output in `URL("")` notation. + +There is another abstract subclass of `Value`, `ValueList`: A `ValueList` represents a lists of `Value`s, separated by some separation character (mostly `,`, whitespace, or `/`). -There is another abstract subclass of `Value`, `ValueList`. A `ValueList` represents a lists of `Value`s, separated by some separation character (mostly `,`, whitespace, or `/`). There are two types of `ValueList`s: +There are two types of `ValueList`s: -* `RuleValueList` – The default type, used to represent all multi-valued rules like `font: bold 12px/3 Helvetica, Verdana, sans-serif;` (where the value would be a whitespace-separated list of the primitive value `bold`, a slash-separated list and a comma-separated list). +* `RuleValueList` – The default type, used to represent all multivalued rules like `font: bold 12px/3 Helvetica, Verdana, sans-serif;` (where the value would be a whitespace-separated list of the primitive value `bold`, a slash-separated list and a comma-separated list). * `CSSFunction` – A special kind of value that also contains a function name and where the values are the function’s arguments. Also handles equals-sign-separated argument lists like `filter: alpha(opacity=90);`. #### Convenience methods -There are a few convenience methods on Document to ease finding, manipulating and deleting rules: +There are a few convenience methods on `Document` to ease finding, manipulating and deleting rules: -* `getAllDeclarationBlocks()` – does what it says; no matter how deeply nested your selectors are. Aliased as `getAllSelectors()`. -* `getAllRuleSets()` – does what it says; no matter how deeply nested your rule sets are. +* `getAllDeclarationBlocks()` – does what it says; no matter how deeply nested the selectors are. Aliased as `getAllSelectors()`. +* `getAllRuleSets()` – does what it says; no matter how deeply nested the rule sets are. * `getAllValues()` – finds all `Value` objects inside `Rule`s. ## To-Do @@ -156,7 +157,7 @@ $cssDocument = $parser->parse(); foreach($cssDocument->getAllRuleSets() as $oRuleSet) { // Note that the added dash will make this remove all rules starting with // `font-` (like `font-size`, `font-weight`, etc.) as well as a potential - // `font-rule`. + // `font` rule. $oRuleSet->removeRule('font-'); $oRuleSet->removeRule('cursor'); } @@ -214,7 +215,8 @@ html, body { ``` -#### Structure (`var_dump()`) +
+ Structure (var_dump()) ```php class Sabberworm\CSS\CSSList\Document#4 (2) { @@ -435,6 +437,7 @@ class Sabberworm\CSS\CSSList\Document#4 (2) { } ``` +
#### Output (`render()`) @@ -458,7 +461,8 @@ html, body {font-size: 1.6em;} ``` -#### Structure (`var_dump()`) +
+ Structure (var_dump()) ```php class Sabberworm\CSS\CSSList\Document#4 (2) { @@ -603,6 +607,7 @@ class Sabberworm\CSS\CSSList\Document#4 (2) { } ``` +
#### Output (`render()`) diff --git a/vendor/sabberworm/php-css-parser/composer.json b/vendor/sabberworm/php-css-parser/composer.json index e192dd5..cf15a94 100644 --- a/vendor/sabberworm/php-css-parser/composer.json +++ b/vendor/sabberworm/php-css-parser/composer.json @@ -12,6 +12,14 @@ "authors": [ { "name": "Raphael Schweikert" + }, + { + "name": "Oliver Klee", + "email": "github@oliverklee.de" + }, + { + "name": "Jake Hotson", + "email": "jake.github@qzdesign.co.uk" } ], "require": { @@ -19,8 +27,7 @@ "ext-iconv": "*" }, "require-dev": { - "phpunit/phpunit": "^4.8.36", - "codacy/coverage": "^1.4" + "phpunit/phpunit": "^5.7.27" }, "suggest": { "ext-mbstring": "for parsing UTF-8 CSS" @@ -35,6 +42,11 @@ "Sabberworm\\CSS\\Tests\\": "tests/" } }, + "extra": { + "branch-alias": { + "dev-main": "9.0.x-dev" + } + }, "scripts": { "ci": [ "@ci:static" diff --git a/vendor/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php b/vendor/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php index 218adb9..598fefc 100644 --- a/vendor/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php +++ b/vendor/sabberworm/php-css-parser/src/CSSList/AtRuleBlockList.php @@ -61,13 +61,14 @@ public function __toString() */ public function render(OutputFormat $oOutputFormat) { + $sResult = $oOutputFormat->comments($this); + $sResult .= $oOutputFormat->sBeforeAtRuleBlock; $sArgs = $this->sArgs; if ($sArgs) { $sArgs = ' ' . $sArgs; } - $sResult = $oOutputFormat->sBeforeAtRuleBlock; $sResult .= "@{$this->sType}$sArgs{$oOutputFormat->spaceBeforeOpeningBrace()}{"; - $sResult .= parent::render($oOutputFormat); + $sResult .= $this->renderListContents($oOutputFormat); $sResult .= '}'; $sResult .= $oOutputFormat->sAfterAtRuleBlock; return $sResult; diff --git a/vendor/sabberworm/php-css-parser/src/CSSList/CSSList.php b/vendor/sabberworm/php-css-parser/src/CSSList/CSSList.php index 946740a..603f662 100644 --- a/vendor/sabberworm/php-css-parser/src/CSSList/CSSList.php +++ b/vendor/sabberworm/php-css-parser/src/CSSList/CSSList.php @@ -24,10 +24,10 @@ use Sabberworm\CSS\Value\Value; /** - * A `CSSList` is the most generic container available. Its contents include `RuleSet` as well as other `CSSList` - * objects. + * This is the most generic container available. It can contain `DeclarationBlock`s (rule sets with a selector), + * `RuleSet`s as well as other `CSSList` objects. * - * Also, it may contain `Import` and `Charset` objects stemming from at-rules. + * It can also contain `Import` and `Charset` objects stemming from at-rules. */ abstract class CSSList implements Renderable, Commentable { @@ -69,8 +69,9 @@ public static function parseList(ParserState $oParserState, CSSList $oList) $oParserState = new ParserState($oParserState, Settings::create()); } $bLenientParsing = $oParserState->getSettings()->bLenientParsing; + $aComments = []; while (!$oParserState->isEnd()) { - $comments = $oParserState->consumeWhiteSpace(); + $aComments = array_merge($aComments, $oParserState->consumeWhiteSpace()); $oListItem = null; if ($bLenientParsing) { try { @@ -86,11 +87,12 @@ public static function parseList(ParserState $oParserState, CSSList $oList) return; } if ($oListItem) { - $oListItem->setComments($comments); + $oListItem->addComments($aComments); $oList->append($oListItem); } - $oParserState->consumeWhiteSpace(); + $aComments = $oParserState->consumeWhiteSpace(); } + $oList->addComments($aComments); if (!$bIsRoot && !$bLenientParsing) { throw new SourceException("Unexpected end of document", $oParserState->currentLine()); } @@ -125,22 +127,19 @@ private static function parseListItem(ParserState $oParserState, CSSList $oList) $oParserState->currentLine() ); } - $oParserState->setCharset($oAtRule->getCharset()->getString()); + $oParserState->setCharset($oAtRule->getCharset()); } return $oAtRule; } elseif ($oParserState->comes('}')) { - if (!$oParserState->getSettings()->bLenientParsing) { - throw new UnexpectedTokenException('CSS selector', '}', 'identifier', $oParserState->currentLine()); - } else { - if ($bIsRoot) { - if ($oParserState->getSettings()->bLenientParsing) { - return DeclarationBlock::parse($oParserState); - } else { - throw new SourceException("Unopened {", $oParserState->currentLine()); - } + if ($bIsRoot) { + if ($oParserState->getSettings()->bLenientParsing) { + return DeclarationBlock::parse($oParserState); } else { - return null; + throw new SourceException("Unopened {", $oParserState->currentLine()); } + } else { + // End of list + return null; } } else { return DeclarationBlock::parse($oParserState, $oList); @@ -172,10 +171,10 @@ private static function parseAtRule(ParserState $oParserState) $oParserState->consumeUntil([';', ParserState::EOF], true, true); return new Import($oLocation, $sMediaQuery ?: null, $iIdentifierLineNum); } elseif ($sIdentifier === 'charset') { - $sCharset = CSSString::parse($oParserState); + $oCharsetString = CSSString::parse($oParserState); $oParserState->consumeWhiteSpace(); $oParserState->consumeUntil([';', ParserState::EOF], true, true); - return new Charset($sCharset, $iIdentifierLineNum); + return new Charset($oCharsetString, $iIdentifierLineNum); } elseif (self::identifierIs($sIdentifier, 'keyframes')) { $oResult = new KeyFrame($iIdentifierLineNum); $oResult->setVendorKeyFrame($sIdentifier); @@ -272,7 +271,7 @@ public function prepend($oItem) } /** - * Appends an item to tje list of contents. + * Appends an item to the list of contents. * * @param RuleSet|CSSList|Import|Charset $oItem * @@ -402,7 +401,7 @@ public function __toString() /** * @return string */ - public function render(OutputFormat $oOutputFormat) + protected function renderListContents(OutputFormat $oOutputFormat) { $sResult = ''; $bIsFirst = true; @@ -442,6 +441,8 @@ public function render(OutputFormat $oOutputFormat) abstract public function isRootList(); /** + * Returns the stored items. + * * @return array */ public function getContents() diff --git a/vendor/sabberworm/php-css-parser/src/CSSList/Document.php b/vendor/sabberworm/php-css-parser/src/CSSList/Document.php index 91ab2c6..bad9983 100644 --- a/vendor/sabberworm/php-css-parser/src/CSSList/Document.php +++ b/vendor/sabberworm/php-css-parser/src/CSSList/Document.php @@ -11,8 +11,8 @@ use Sabberworm\CSS\Value\Value; /** - * The root `CSSList` of a parsed file. Contains all top-level CSS contents, mostly declaration blocks, - * but also any at-rules encountered. + * This class represents the root of a parsed CSS file. It contains all top-level CSS contents: mostly declaration + * blocks, but also any at-rules encountered (`Import` and `Charset`). */ class Document extends CSSBlockList { @@ -37,7 +37,8 @@ public static function parse(ParserState $oParserState) } /** - * Gets all `DeclarationBlock` objects recursively. + * Gets all `DeclarationBlock` objects recursively, no matter how deeply nested the selectors are. + * Aliased as `getAllSelectors()`. * * @return array */ @@ -62,7 +63,7 @@ public function getAllSelectors() } /** - * Returns all `RuleSet` objects found recursively in the tree. + * Returns all `RuleSet` objects recursively found in the tree, no matter how deeply nested the rule sets are. * * @return array */ @@ -75,7 +76,7 @@ public function getAllRuleSets() } /** - * Returns all `Value` objects found recursively in the tree. + * Returns all `Value` objects found recursively in `Rule`s in the tree. * * @param CSSList|RuleSet|string $mElement * the `CSSList` or `RuleSet` to start the search from (defaults to the whole document). @@ -102,7 +103,7 @@ public function getAllValues($mElement = null, $bSearchInFunctionArguments = fal } /** - * Returns all `Selector` objects found recursively in the tree. + * Returns all `Selector` objects with the requested specificity found recursively in the tree. * * Note that this does not yield the full `DeclarationBlock` that the selector belongs to * (and, currently, there is no way to get to that). @@ -159,7 +160,7 @@ public function render(OutputFormat $oOutputFormat = null) if ($oOutputFormat === null) { $oOutputFormat = new OutputFormat(); } - return parent::render($oOutputFormat); + return $oOutputFormat->comments($this) . $this->renderListContents($oOutputFormat); } /** diff --git a/vendor/sabberworm/php-css-parser/src/CSSList/KeyFrame.php b/vendor/sabberworm/php-css-parser/src/CSSList/KeyFrame.php index d9420e9..caef7b3 100644 --- a/vendor/sabberworm/php-css-parser/src/CSSList/KeyFrame.php +++ b/vendor/sabberworm/php-css-parser/src/CSSList/KeyFrame.php @@ -72,8 +72,9 @@ public function __toString() */ public function render(OutputFormat $oOutputFormat) { - $sResult = "@{$this->vendorKeyFrame} {$this->animationName}{$oOutputFormat->spaceBeforeOpeningBrace()}{"; - $sResult .= parent::render($oOutputFormat); + $sResult = $oOutputFormat->comments($this); + $sResult .= "@{$this->vendorKeyFrame} {$this->animationName}{$oOutputFormat->spaceBeforeOpeningBrace()}{"; + $sResult .= $this->renderListContents($oOutputFormat); $sResult .= '}'; return $sResult; } diff --git a/vendor/sabberworm/php-css-parser/src/OutputFormat.php b/vendor/sabberworm/php-css-parser/src/OutputFormat.php index 595d306..96f26e1 100644 --- a/vendor/sabberworm/php-css-parser/src/OutputFormat.php +++ b/vendor/sabberworm/php-css-parser/src/OutputFormat.php @@ -143,6 +143,13 @@ class OutputFormat */ public $bIgnoreExceptions = false; + /** + * Render comments for lists and RuleSets + * + * @var bool + */ + public $bRenderComments = false; + /** * @var OutputFormatter|null */ @@ -314,8 +321,12 @@ public static function create() public static function createCompact() { $format = self::create(); - $format->set('Space*Rules', "")->set('Space*Blocks', "")->setSpaceAfterRuleName('') - ->setSpaceBeforeOpeningBrace('')->setSpaceAfterSelectorSeparator(''); + $format->set('Space*Rules', "") + ->set('Space*Blocks', "") + ->setSpaceAfterRuleName('') + ->setSpaceBeforeOpeningBrace('') + ->setSpaceAfterSelectorSeparator('') + ->setRenderComments(false); return $format; } @@ -327,8 +338,11 @@ public static function createCompact() public static function createPretty() { $format = self::create(); - $format->set('Space*Rules', "\n")->set('Space*Blocks', "\n") - ->setSpaceBetweenBlocks("\n\n")->set('SpaceAfterListArgumentSeparator', ['default' => '', ',' => ' ']); + $format->set('Space*Rules', "\n") + ->set('Space*Blocks', "\n") + ->setSpaceBetweenBlocks("\n\n") + ->set('SpaceAfterListArgumentSeparator', ['default' => '', ',' => ' ']) + ->setRenderComments(true); return $format; } } diff --git a/vendor/sabberworm/php-css-parser/src/OutputFormatter.php b/vendor/sabberworm/php-css-parser/src/OutputFormatter.php index 535feca..501d15d 100644 --- a/vendor/sabberworm/php-css-parser/src/OutputFormatter.php +++ b/vendor/sabberworm/php-css-parser/src/OutputFormatter.php @@ -2,6 +2,7 @@ namespace Sabberworm\CSS; +use Sabberworm\CSS\Comment\Commentable; use Sabberworm\CSS\Parsing\OutputException; class OutputFormatter @@ -211,6 +212,29 @@ public function removeLastSemicolon($sString) return implode(';', $sString); } + /** + * + * @param array $aComments + * + * @return string + */ + public function comments(Commentable $oCommentable) + { + if (!$this->oFormat->bRenderComments) { + return ''; + } + + $sResult = ''; + $aComments = $oCommentable->getComments(); + $iLastCommentIndex = count($aComments) - 1; + + foreach ($aComments as $i => $oComment) { + $sResult .= $oComment->render($this->oFormat); + $sResult .= $i === $iLastCommentIndex ? $this->spaceAfterBlocks() : $this->spaceBetweenBlocks(); + } + return $sResult; + } + /** * @param string $sSpaceString * diff --git a/vendor/sabberworm/php-css-parser/src/Parser.php b/vendor/sabberworm/php-css-parser/src/Parser.php index f3b0493..e582cfa 100644 --- a/vendor/sabberworm/php-css-parser/src/Parser.php +++ b/vendor/sabberworm/php-css-parser/src/Parser.php @@ -17,7 +17,7 @@ class Parser private $oParserState; /** - * @param string $sText + * @param string $sText the complete CSS as text (i.e., usually the contents of a CSS file) * @param Settings|null $oParserSettings * @param int $iLineNo the line number (starting from 1, not from 0) */ @@ -30,6 +30,8 @@ public function __construct($sText, Settings $oParserSettings = null, $iLineNo = } /** + * Sets the charset to be used if the CSS does not contain an `@charset` declaration. + * * @param string $sCharset * * @return void @@ -40,6 +42,8 @@ public function setCharset($sCharset) } /** + * Returns the charset that is used if the CSS does not contain an `@charset` declaration. + * * @return void */ public function getCharset() @@ -49,6 +53,8 @@ public function getCharset() } /** + * Parses the CSS provided to the constructor and creates a `Document` from it. + * * @return Document * * @throws SourceException diff --git a/vendor/sabberworm/php-css-parser/src/Parsing/Anchor.php b/vendor/sabberworm/php-css-parser/src/Parsing/Anchor.php new file mode 100644 index 0000000..93789e2 --- /dev/null +++ b/vendor/sabberworm/php-css-parser/src/Parsing/Anchor.php @@ -0,0 +1,34 @@ +iPosition = $iPosition; + $this->oParserState = $oParserState; + } + + /** + * @return void + */ + public function backtrack() + { + $this->oParserState->setPosition($this->iPosition); + } +} diff --git a/vendor/sabberworm/php-css-parser/src/Parsing/ParserState.php b/vendor/sabberworm/php-css-parser/src/Parsing/ParserState.php index e7d85ee..7a99f32 100644 --- a/vendor/sabberworm/php-css-parser/src/Parsing/ParserState.php +++ b/vendor/sabberworm/php-css-parser/src/Parsing/ParserState.php @@ -33,6 +33,8 @@ class ParserState private $iCurrentPosition; /** + * will only be used if the CSS does not contain an `@charset` declaration + * * @var string */ private $sCharset; @@ -48,7 +50,7 @@ class ParserState private $iLineNo; /** - * @param string $sText + * @param string $sText the complete CSS as text (i.e., usually the contents of a CSS file) * @param int $iLineNo */ public function __construct($sText, Settings $oParserSettings, $iLineNo = 1) @@ -61,6 +63,8 @@ public function __construct($sText, Settings $oParserSettings, $iLineNo = 1) } /** + * Sets the charset to be used if the CSS does not contain an `@charset` declaration. + * * @param string $sCharset * * @return void @@ -75,6 +79,8 @@ public function setCharset($sCharset) } /** + * Returns the charset that is used if the CSS does not contain an `@charset` declaration. + * * @return string */ public function getCharset() @@ -106,6 +112,24 @@ public function getSettings() return $this->oParserSettings; } + /** + * @return \Sabberworm\CSS\Parsing\Anchor + */ + public function anchor() + { + return new Anchor($this->iCurrentPosition, $this); + } + + /** + * @param int $iPosition + * + * @return void + */ + public function setPosition($iPosition) + { + $this->iCurrentPosition = $iPosition; + } + /** * @param bool $bIgnoreCase * @@ -115,12 +139,15 @@ public function getSettings() */ public function parseIdentifier($bIgnoreCase = true) { + if ($this->isEnd()) { + throw new UnexpectedEOFException('', '', 'identifier', $this->iLineNo); + } $sResult = $this->parseCharacter(true); if ($sResult === null) { throw new UnexpectedTokenException($sResult, $this->peek(5), 'identifier', $this->iLineNo); } $sCharacter = null; - while (($sCharacter = $this->parseCharacter(true)) !== null) { + while (!$this->isEnd() && ($sCharacter = $this->parseCharacter(true)) !== null) { if (preg_match('/[a-zA-Z0-9\x{00A0}-\x{FFFF}_-]/Sux', $sCharacter)) { $sResult .= $sCharacter; } else { @@ -204,7 +231,7 @@ public function parseCharacter($bIsForIdentifier) */ public function consumeWhiteSpace() { - $comments = []; + $aComments = []; do { while (preg_match('/\\s/isSu', $this->peek()) === 1) { $this->consume(1); @@ -214,16 +241,16 @@ public function consumeWhiteSpace() $oComment = $this->consumeComment(); } catch (UnexpectedEOFException $e) { $this->iCurrentPosition = $this->iLength; - return; + return $aComments; } } else { $oComment = $this->consumeComment(); } if ($oComment !== false) { - $comments[] = $oComment; + $aComments[] = $oComment; } } while ($oComment !== false); - return $comments; + return $aComments; } /** diff --git a/vendor/sabberworm/php-css-parser/src/Property/Charset.php b/vendor/sabberworm/php-css-parser/src/Property/Charset.php index 3ee0c3d..26e1b25 100644 --- a/vendor/sabberworm/php-css-parser/src/Property/Charset.php +++ b/vendor/sabberworm/php-css-parser/src/Property/Charset.php @@ -4,6 +4,7 @@ use Sabberworm\CSS\Comment\Comment; use Sabberworm\CSS\OutputFormat; +use Sabberworm\CSS\Value\CSSString; /** * Class representing an `@charset` rule. @@ -16,9 +17,9 @@ class Charset implements AtRule { /** - * @var string + * @var CSSString */ - private $sCharset; + private $oCharset; /** * @var int @@ -31,12 +32,12 @@ class Charset implements AtRule protected $aComments; /** - * @param string $sCharset + * @param CSSString $oCharset * @param int $iLineNo */ - public function __construct($sCharset, $iLineNo = 0) + public function __construct(CSSString $oCharset, $iLineNo = 0) { - $this->sCharset = $sCharset; + $this->oCharset = $oCharset; $this->iLineNo = $iLineNo; $this->aComments = []; } @@ -50,13 +51,14 @@ public function getLineNo() } /** - * @param string $sCharset + * @param string|CSSString $oCharset * * @return void */ public function setCharset($sCharset) { - $this->sCharset = $sCharset; + $sCharset = $sCharset instanceof CSSString ? $sCharset : new CSSString($sCharset); + $this->oCharset = $sCharset; } /** @@ -64,7 +66,7 @@ public function setCharset($sCharset) */ public function getCharset() { - return $this->sCharset; + return $this->oCharset->getString(); } /** @@ -80,7 +82,7 @@ public function __toString() */ public function render(OutputFormat $oOutputFormat) { - return "@charset {$this->sCharset->render($oOutputFormat)};"; + return "{$oOutputFormat->comments($this)}@charset {$this->oCharset->render($oOutputFormat)};"; } /** @@ -96,7 +98,7 @@ public function atRuleName() */ public function atRuleArgs() { - return $this->sCharset; + return $this->oCharset; } /** diff --git a/vendor/sabberworm/php-css-parser/src/Property/Import.php b/vendor/sabberworm/php-css-parser/src/Property/Import.php index a225301..d715a7a 100644 --- a/vendor/sabberworm/php-css-parser/src/Property/Import.php +++ b/vendor/sabberworm/php-css-parser/src/Property/Import.php @@ -83,7 +83,7 @@ public function __toString() */ public function render(OutputFormat $oOutputFormat) { - return "@import " . $this->oLocation->render($oOutputFormat) + return $oOutputFormat->comments($this) . "@import " . $this->oLocation->render($oOutputFormat) . ($this->sMediaQuery === null ? '' : ' ' . $this->sMediaQuery) . ';'; } @@ -134,4 +134,12 @@ public function setComments(array $aComments) { $this->aComments = $aComments; } + + /** + * @return string + */ + public function getMediaQuery() + { + return $this->sMediaQuery; + } } diff --git a/vendor/sabberworm/php-css-parser/src/Rule/Rule.php b/vendor/sabberworm/php-css-parser/src/Rule/Rule.php index c1ea6df..fc00c88 100644 --- a/vendor/sabberworm/php-css-parser/src/Rule/Rule.php +++ b/vendor/sabberworm/php-css-parser/src/Rule/Rule.php @@ -13,8 +13,9 @@ use Sabberworm\CSS\Value\Value; /** - * RuleSets contains Rule objects which always have a key and a value. - * In CSS, Rules are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];” + * `Rule`s just have a string key (the rule) and a 'Value'. + * + * In CSS, `Rule`s are expressed as follows: “key: value[0][0] value[0][1], value[1][0] value[1][1];” */ class Rule implements Renderable, Commentable { @@ -24,7 +25,7 @@ class Rule implements Renderable, Commentable private $sRule; /** - * @var RuleValueList|null + * @var RuleValueList|string|null */ private $mValue; @@ -171,7 +172,7 @@ public function getRule() } /** - * @return RuleValueList|null + * @return RuleValueList|string|null */ public function getValue() { @@ -179,7 +180,7 @@ public function getValue() } /** - * @param RuleValueList|null $mValue + * @param RuleValueList|string|null $mValue * * @return void */ @@ -346,8 +347,8 @@ public function __toString() */ public function render(OutputFormat $oOutputFormat) { - $sResult = "{$this->sRule}:{$oOutputFormat->spaceAfterRuleName()}"; - if ($this->mValue instanceof Value) { //Can also be a ValueList + $sResult = "{$oOutputFormat->comments($this)}{$this->sRule}:{$oOutputFormat->spaceAfterRuleName()}"; + if ($this->mValue instanceof Value) { // Can also be a ValueList $sResult .= $this->mValue->render($oOutputFormat); } else { $sResult .= $this->mValue; diff --git a/vendor/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php b/vendor/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php index 88bc5bd..aab6d79 100644 --- a/vendor/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php +++ b/vendor/sabberworm/php-css-parser/src/RuleSet/AtRuleSet.php @@ -6,7 +6,10 @@ use Sabberworm\CSS\Property\AtRule; /** - * A RuleSet constructed by an unknown at-rule. `@font-face` rules are rendered into AtRuleSet objects. + * This class represents rule sets for generic at-rules which are not covered by specific classes, i.e., not + * `@import`, `@charset` or `@media`. + * + * A common example for this is `@font-face`. */ class AtRuleSet extends RuleSet implements AtRule { @@ -61,12 +64,13 @@ public function __toString() */ public function render(OutputFormat $oOutputFormat) { + $sResult = $oOutputFormat->comments($this); $sArgs = $this->sArgs; if ($sArgs) { $sArgs = ' ' . $sArgs; } - $sResult = "@{$this->sType}$sArgs{$oOutputFormat->spaceBeforeOpeningBrace()}{"; - $sResult .= parent::render($oOutputFormat); + $sResult .= "@{$this->sType}$sArgs{$oOutputFormat->spaceBeforeOpeningBrace()}{"; + $sResult .= $this->renderRules($oOutputFormat); $sResult .= '}'; return $sResult; } diff --git a/vendor/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php b/vendor/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php index c27cdd4..b218bd8 100644 --- a/vendor/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php +++ b/vendor/sabberworm/php-css-parser/src/RuleSet/DeclarationBlock.php @@ -19,7 +19,10 @@ use Sabberworm\CSS\Value\Value; /** - * Declaration blocks are the parts of a CSS file which denote the rules belonging to a selector. + * This class represents a `RuleSet` constrained by a `Selector`. + * + * It contains an array of selector objects (comma-separated in the CSS) as well as the rules to be applied to the + * matching elements. * * Declaration blocks usually appear directly inside a `Document` or another `CSSList` (mostly a `MediaQuery`). */ @@ -562,6 +565,7 @@ public function expandListStyleShorthand() public function createShorthandProperties(array $aProperties, $sShorthand) { $aRules = $this->getRulesAssoc(); + $oRule = null; $aNewValues = []; foreach ($aProperties as $sProperty) { if (!isset($aRules[$sProperty])) { @@ -582,7 +586,7 @@ public function createShorthandProperties(array $aProperties, $sShorthand) $this->removeRule($sProperty); } } - if (count($aNewValues)) { + if ($aNewValues !== [] && $oRule instanceof Rule) { $oNewRule = new Rule($sShorthand, $oRule->getLineNo(), $oRule->getColNo()); foreach ($aNewValues as $mValue) { $oNewRule->addValue($mValue); @@ -812,18 +816,19 @@ public function __toString() */ public function render(OutputFormat $oOutputFormat) { + $sResult = $oOutputFormat->comments($this); if (count($this->aSelectors) === 0) { // If all the selectors have been removed, this declaration block becomes invalid throw new OutputException("Attempt to print declaration block with missing selector", $this->iLineNo); } - $sResult = $oOutputFormat->sBeforeDeclarationBlock; + $sResult .= $oOutputFormat->sBeforeDeclarationBlock; $sResult .= $oOutputFormat->implode( $oOutputFormat->spaceBeforeSelectorSeparator() . ',' . $oOutputFormat->spaceAfterSelectorSeparator(), $this->aSelectors ); $sResult .= $oOutputFormat->sAfterDeclarationBlockSelectors; $sResult .= $oOutputFormat->spaceBeforeOpeningBrace() . '{'; - $sResult .= parent::render($oOutputFormat); + $sResult .= $this->renderRules($oOutputFormat); $sResult .= '}'; $sResult .= $oOutputFormat->sAfterDeclarationBlock; return $sResult; diff --git a/vendor/sabberworm/php-css-parser/src/RuleSet/RuleSet.php b/vendor/sabberworm/php-css-parser/src/RuleSet/RuleSet.php index 9404bb0..adb9be9 100644 --- a/vendor/sabberworm/php-css-parser/src/RuleSet/RuleSet.php +++ b/vendor/sabberworm/php-css-parser/src/RuleSet/RuleSet.php @@ -12,8 +12,13 @@ use Sabberworm\CSS\Rule\Rule; /** - * RuleSet is a generic superclass denoting rules. The typical example for rule sets are declaration block. - * However, unknown At-Rules (like `@font-face`) are also rule sets. + * This class is a container for individual 'Rule's. + * + * The most common form of a rule set is one constrained by a selector, i.e., a `DeclarationBlock`. + * However, unknown `AtRule`s (like `@font-face`) are rule sets as well. + * + * If you want to manipulate a `RuleSet`, use the methods `addRule(Rule $rule)`, `getRules()` and `removeRule($rule)` + * (which accepts either a `Rule` or a rule name; optionally suffixed by a dash to remove all related rules). */ abstract class RuleSet implements Renderable, Commentable { @@ -266,23 +271,24 @@ public function __toString() /** * @return string */ - public function render(OutputFormat $oOutputFormat) + protected function renderRules(OutputFormat $oOutputFormat) { $sResult = ''; $bIsFirst = true; + $oNextLevel = $oOutputFormat->nextLevel(); foreach ($this->aRules as $aRules) { foreach ($aRules as $oRule) { - $sRendered = $oOutputFormat->safely(function () use ($oRule, $oOutputFormat) { - return $oRule->render($oOutputFormat->nextLevel()); + $sRendered = $oNextLevel->safely(function () use ($oRule, $oNextLevel) { + return $oRule->render($oNextLevel); }); if ($sRendered === null) { continue; } if ($bIsFirst) { $bIsFirst = false; - $sResult .= $oOutputFormat->nextLevel()->spaceBeforeRules(); + $sResult .= $oNextLevel->spaceBeforeRules(); } else { - $sResult .= $oOutputFormat->nextLevel()->spaceBetweenRules(); + $sResult .= $oNextLevel->spaceBetweenRules(); } $sResult .= $sRendered; } diff --git a/vendor/sabberworm/php-css-parser/src/Settings.php b/vendor/sabberworm/php-css-parser/src/Settings.php index 7b85809..79d9980 100644 --- a/vendor/sabberworm/php-css-parser/src/Settings.php +++ b/vendor/sabberworm/php-css-parser/src/Settings.php @@ -11,7 +11,8 @@ class Settings { /** * Multi-byte string support. - * If true (mbstring extension must be enabled), will use (slower) `mb_strlen`, `mb_convert_case`, `mb_substr` + * + * If `true` (`mbstring` extension must be enabled), will use (slower) `mb_strlen`, `mb_convert_case`, `mb_substr` * and `mb_strpos` functions. Otherwise, the normal (ASCII-Only) functions will be used. * * @var bool @@ -19,15 +20,14 @@ class Settings public $bMultibyteSupport; /** - * The default charset for the CSS if no `@charset` rule is found. Defaults to utf-8. + * The default charset for the CSS if no `@charset` declaration is found. Defaults to utf-8. * * @var string */ public $sDefaultCharset = 'utf-8'; /** - * Lenient parsing. When used (which is true by default), the parser will not choke - * on unexpected tokens but simply ignore them. + * Whether the parser silently ignore invalid rules instead of choking on them. * * @var bool */ @@ -47,6 +47,11 @@ public static function create() } /** + * Enables/disables multi-byte string support. + * + * If `true` (`mbstring` extension must be enabled), will use (slower) `mb_strlen`, `mb_convert_case`, `mb_substr` + * and `mb_strpos` functions. Otherwise, the normal (ASCII-Only) functions will be used. + * * @param bool $bMultibyteSupport * * @return self fluent interface @@ -58,6 +63,8 @@ public function withMultibyteSupport($bMultibyteSupport = true) } /** + * Sets the charset to be used if the CSS does not contain an `@charset` declaration. + * * @param string $sDefaultCharset * * @return self fluent interface @@ -69,6 +76,8 @@ public function withDefaultCharset($sDefaultCharset) } /** + * Configures whether the parser should silently ignore invalid rules. + * * @param bool $bLenientParsing * * @return self fluent interface @@ -80,6 +89,8 @@ public function withLenientParsing($bLenientParsing = true) } /** + * Configures the parser to choke on invalid rules. + * * @return self fluent interface */ public function beStrict() diff --git a/vendor/sabberworm/php-css-parser/src/Value/CSSFunction.php b/vendor/sabberworm/php-css-parser/src/Value/CSSFunction.php index e6b8c11..300dc3e 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/CSSFunction.php +++ b/vendor/sabberworm/php-css-parser/src/Value/CSSFunction.php @@ -3,7 +3,12 @@ namespace Sabberworm\CSS\Value; use Sabberworm\CSS\OutputFormat; +use Sabberworm\CSS\Parsing\ParserState; +/** + * A `CSSFunction` represents a special kind of value that also contains a function name and where the values are the + * function’s arguments. It also handles equals-sign-separated argument lists like `filter: alpha(opacity=90);`. + */ class CSSFunction extends ValueList { /** @@ -28,6 +33,26 @@ public function __construct($sName, $aArguments, $sSeparator = ',', $iLineNo = 0 parent::__construct($aArguments, $sSeparator, $iLineNo); } + /** + * @param ParserState $oParserState + * @param bool $bIgnoreCase + * + * @return CSSFunction + * + * @throws SourceException + * @throws UnexpectedEOFException + * @throws UnexpectedTokenException + */ + public static function parse(ParserState $oParserState, $bIgnoreCase = false) + { + $mResult = $oParserState->parseIdentifier($bIgnoreCase); + $oParserState->consume('('); + $aArguments = Value::parseValue($oParserState, ['=', ' ', ',']); + $mResult = new CSSFunction($mResult, $aArguments, ',', $oParserState->currentLine()); + $oParserState->consume(')'); + return $mResult; + } + /** * @return string */ diff --git a/vendor/sabberworm/php-css-parser/src/Value/CSSString.php b/vendor/sabberworm/php-css-parser/src/Value/CSSString.php index 9fafedd..da498d4 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/CSSString.php +++ b/vendor/sabberworm/php-css-parser/src/Value/CSSString.php @@ -8,6 +8,11 @@ use Sabberworm\CSS\Parsing\UnexpectedEOFException; use Sabberworm\CSS\Parsing\UnexpectedTokenException; +/** + * This class is a wrapper for quoted strings to distinguish them from keywords. + * + * `CSSString`s always output with double quotes. + */ class CSSString extends PrimitiveValue { /** diff --git a/vendor/sabberworm/php-css-parser/src/Value/CalcFunction.php b/vendor/sabberworm/php-css-parser/src/Value/CalcFunction.php index 5c92e0c..5ffd071 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/CalcFunction.php +++ b/vendor/sabberworm/php-css-parser/src/Value/CalcFunction.php @@ -19,20 +19,35 @@ class CalcFunction extends CSSFunction const T_OPERATOR = 2; /** + * @param ParserState $oParserState + * @param bool $bIgnoreCase + * * @return CalcFunction * * @throws UnexpectedTokenException * @throws UnexpectedEOFException */ - public static function parse(ParserState $oParserState) + public static function parse(ParserState $oParserState, $bIgnoreCase = false) { $aOperators = ['+', '-', '*', '/']; - $sFunction = trim($oParserState->consumeUntil('(', false, true)); + $sFunction = $oParserState->parseIdentifier(); + if ($oParserState->peek() != '(') { + // Found ; or end of line before an opening bracket + throw new UnexpectedTokenException('(', $oParserState->peek(), 'literal', $oParserState->currentLine()); + } elseif (!in_array($sFunction, ['calc', '-moz-calc', '-webkit-calc'])) { + // Found invalid calc definition. Example calc (... + throw new UnexpectedTokenException('calc', $sFunction, 'literal', $oParserState->currentLine()); + } + $oParserState->consume('('); $oCalcList = new CalcRuleValueList($oParserState->currentLine()); $oList = new RuleValueList(',', $oParserState->currentLine()); $iNestingLevel = 0; $iLastComponentType = null; while (!$oParserState->comes(')') || $iNestingLevel > 0) { + if ($oParserState->isEnd() && $iNestingLevel === 0) { + break; + } + $oParserState->consumeWhiteSpace(); if ($oParserState->comes('(')) { $iNestingLevel++; @@ -83,7 +98,9 @@ public static function parse(ParserState $oParserState) $oParserState->consumeWhiteSpace(); } $oList->addListComponent($oCalcList); - $oParserState->consume(')'); + if (!$oParserState->isEnd()) { + $oParserState->consume(')'); + } return new CalcFunction($sFunction, $oList, ',', $oParserState->currentLine()); } } diff --git a/vendor/sabberworm/php-css-parser/src/Value/Color.php b/vendor/sabberworm/php-css-parser/src/Value/Color.php index 8dc5296..1cf00cc 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/Color.php +++ b/vendor/sabberworm/php-css-parser/src/Value/Color.php @@ -7,6 +7,10 @@ use Sabberworm\CSS\Parsing\UnexpectedEOFException; use Sabberworm\CSS\Parsing\UnexpectedTokenException; +/** + * `Color's can be input in the form #rrggbb, #rgb or schema(val1, val2, …) but are always stored as an array of + * ('s' => val1, 'c' => val2, 'h' => val3, …) and output in the second form. + */ class Color extends CSSFunction { /** @@ -19,12 +23,15 @@ public function __construct(array $aColor, $iLineNo = 0) } /** + * @param ParserState $oParserState + * @param bool $bIgnoreCase + * * @return Color|CSSFunction * * @throws UnexpectedEOFException * @throws UnexpectedTokenException */ - public static function parse(ParserState $oParserState) + public static function parse(ParserState $oParserState, $bIgnoreCase = false) { $aColor = []; if ($oParserState->comes('#')) { diff --git a/vendor/sabberworm/php-css-parser/src/Value/RuleValueList.php b/vendor/sabberworm/php-css-parser/src/Value/RuleValueList.php index 5d533a7..8fe88b6 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/RuleValueList.php +++ b/vendor/sabberworm/php-css-parser/src/Value/RuleValueList.php @@ -2,6 +2,11 @@ namespace Sabberworm\CSS\Value; +/** + * This class is used to represent all multivalued rules like `font: bold 12px/3 Helvetica, Verdana, sans-serif;` + * (where the value would be a whitespace-separated list of the primitive value `bold`, a slash-separated list + * and a comma-separated list). + */ class RuleValueList extends ValueList { /** diff --git a/vendor/sabberworm/php-css-parser/src/Value/Size.php b/vendor/sabberworm/php-css-parser/src/Value/Size.php index b3801dc..36a3238 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/Size.php +++ b/vendor/sabberworm/php-css-parser/src/Value/Size.php @@ -7,6 +7,9 @@ use Sabberworm\CSS\Parsing\UnexpectedEOFException; use Sabberworm\CSS\Parsing\UnexpectedTokenException; +/** + * A `Size` consists of a numeric `size` value and a unit. + */ class Size extends PrimitiveValue { /** @@ -24,7 +27,7 @@ class Size extends PrimitiveValue /** * @var array */ - const NON_SIZE_UNITS = ['deg', 'grad', 'rad', 's', 'ms', 'turns', 'Hz', 'kHz']; + const NON_SIZE_UNITS = ['deg', 'grad', 'rad', 's', 'ms', 'turn', 'Hz', 'kHz']; /** * @var array>|null @@ -74,9 +77,16 @@ public static function parse(ParserState $oParserState, $bIsColorComponent = fal if ($oParserState->comes('-')) { $sSize .= $oParserState->consume('-'); } - while (is_numeric($oParserState->peek()) || $oParserState->comes('.')) { + while (is_numeric($oParserState->peek()) || $oParserState->comes('.') || $oParserState->comes('e', true)) { if ($oParserState->comes('.')) { $sSize .= $oParserState->consume('.'); + } elseif ($oParserState->comes('e', true)) { + $sLookahead = $oParserState->peek(1, 1); + if (is_numeric($sLookahead) || $sLookahead === '+' || $sLookahead === '-') { + $sSize .= $oParserState->consume(2); + } else { + break; // Reached the unit part of the number like "em" or "ex" + } } else { $sSize .= $oParserState->consume(1); } diff --git a/vendor/sabberworm/php-css-parser/src/Value/URL.php b/vendor/sabberworm/php-css-parser/src/Value/URL.php index 1467d50..cdb911c 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/URL.php +++ b/vendor/sabberworm/php-css-parser/src/Value/URL.php @@ -8,6 +8,9 @@ use Sabberworm\CSS\Parsing\UnexpectedEOFException; use Sabberworm\CSS\Parsing\UnexpectedTokenException; +/** + * This class represents URLs in CSS. `URL`s always output in `URL("")` notation. + */ class URL extends PrimitiveValue { /** @@ -33,11 +36,21 @@ public function __construct(CSSString $oURL, $iLineNo = 0) */ public static function parse(ParserState $oParserState) { - $bUseUrl = $oParserState->comes('url', true); + $oAnchor = $oParserState->anchor(); + $sIdentifier = ''; + for ($i = 0; $i < 3; $i++) { + $sChar = $oParserState->parseCharacter(true); + if ($sChar === null) { + break; + } + $sIdentifier .= $sChar; + } + $bUseUrl = $oParserState->streql($sIdentifier, 'url'); if ($bUseUrl) { - $oParserState->consume('url'); $oParserState->consumeWhiteSpace(); $oParserState->consume('('); + } else { + $oAnchor->backtrack(); } $oParserState->consumeWhiteSpace(); $oResult = new URL(CSSString::parse($oParserState), $oParserState->currentLine()); diff --git a/vendor/sabberworm/php-css-parser/src/Value/Value.php b/vendor/sabberworm/php-css-parser/src/Value/Value.php index 66cb9fd..ce6d579 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/Value.php +++ b/vendor/sabberworm/php-css-parser/src/Value/Value.php @@ -8,6 +8,10 @@ use Sabberworm\CSS\Parsing\UnexpectedTokenException; use Sabberworm\CSS\Renderable; +/** + * Abstract base class for specific classes of CSS values: `Size`, `Color`, `CSSString` and `URL`, and another + * abstract subclass `ValueList`. + */ abstract class Value implements Renderable { /** @@ -39,8 +43,9 @@ public static function parseValue(ParserState $oParserState, array $aListDelimit //Build a list of delimiters and parsed values while ( !($oParserState->comes('}') || $oParserState->comes(';') || $oParserState->comes('!') - || $oParserState->comes(')') - || $oParserState->comes('\\')) + || $oParserState->comes(')') + || $oParserState->comes('\\') + || $oParserState->isEnd()) ) { if (count($aStack) > 0) { $bFoundDelimiter = false; @@ -101,16 +106,25 @@ public static function parseValue(ParserState $oParserState, array $aListDelimit */ public static function parseIdentifierOrFunction(ParserState $oParserState, $bIgnoreCase = false) { - $sResult = $oParserState->parseIdentifier($bIgnoreCase); + $oAnchor = $oParserState->anchor(); + $mResult = $oParserState->parseIdentifier($bIgnoreCase); if ($oParserState->comes('(')) { - $oParserState->consume('('); - $aArguments = Value::parseValue($oParserState, ['=', ' ', ',']); - $sResult = new CSSFunction($sResult, $aArguments, ',', $oParserState->currentLine()); - $oParserState->consume(')'); + $oAnchor->backtrack(); + if ($oParserState->streql('url', $mResult)) { + $mResult = URL::parse($oParserState); + } elseif ( + $oParserState->streql('calc', $mResult) + || $oParserState->streql('-webkit-calc', $mResult) + || $oParserState->streql('-moz-calc', $mResult) + ) { + $mResult = CalcFunction::parse($oParserState); + } else { + $mResult = CSSFunction::parse($oParserState, $bIgnoreCase); + } } - return $sResult; + return $mResult; } /** @@ -133,13 +147,6 @@ public static function parsePrimitiveValue(ParserState $oParserState) $oValue = Size::parse($oParserState); } elseif ($oParserState->comes('#') || $oParserState->comes('rgb', true) || $oParserState->comes('hsl', true)) { $oValue = Color::parse($oParserState); - } elseif ($oParserState->comes('url', true)) { - $oValue = URL::parse($oParserState); - } elseif ( - $oParserState->comes('calc', true) || $oParserState->comes('-webkit-calc', true) - || $oParserState->comes('-moz-calc', true) - ) { - $oValue = CalcFunction::parse($oParserState); } elseif ($oParserState->comes("'") || $oParserState->comes('"')) { $oValue = CSSString::parse($oParserState); } elseif ($oParserState->comes("progid:") && $oParserState->getSettings()->bLenientParsing) { diff --git a/vendor/sabberworm/php-css-parser/src/Value/ValueList.php b/vendor/sabberworm/php-css-parser/src/Value/ValueList.php index af5348b..a93acc7 100644 --- a/vendor/sabberworm/php-css-parser/src/Value/ValueList.php +++ b/vendor/sabberworm/php-css-parser/src/Value/ValueList.php @@ -4,6 +4,12 @@ use Sabberworm\CSS\OutputFormat; +/** + * A `ValueList` represents a lists of `Value`s, separated by some separation character + * (mostly `,`, whitespace, or `/`). + * + * There are two types of `ValueList`s: `RuleValueList` and `CSSFunction` + */ abstract class ValueList extends Value { /**