From f6b6ef8702ed2497118554fab8d66533b3b9b760 Mon Sep 17 00:00:00 2001 From: Eduardo Mozart de Oliveira <2974895+eduardomozart@users.noreply.github.com> Date: Tue, 7 Nov 2023 11:25:54 -0300 Subject: [PATCH 1/2] Update mPDF to latest 8.0 stable There's some known issues with PHP 8, like exporting PDF files with SVG gradients, that was already fixed on newer mPDF versions from 8.0 branch. --- composer.lock | 42 +- vendor/composer/ClassLoader.php | 96 ++-- vendor/composer/installed.json | 42 +- vendor/composer/installed.php | 10 +- vendor/mpdf/mpdf/.github/CONTRIBUTING.md | 41 +- vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE.md | 22 - .../mpdf/.github/ISSUE_TEMPLATE/Bug_report.md | 29 ++ .../.github/ISSUE_TEMPLATE/Feature_request.md | 8 + .../mpdf/.github/ISSUE_TEMPLATE/config.yml | 7 + .../mpdf/mpdf/.github/workflows/coverage.yml | 42 ++ vendor/mpdf/mpdf/.github/workflows/cs.yml | 43 ++ vendor/mpdf/mpdf/.github/workflows/tests.yml | 52 ++ vendor/mpdf/mpdf/CHANGELOG.md | 13 + vendor/mpdf/mpdf/README.md | 35 +- vendor/mpdf/mpdf/composer.json | 51 +- vendor/mpdf/mpdf/src/Barcode.php | 50 +- vendor/mpdf/mpdf/src/Barcode/Codabar.php | 11 +- vendor/mpdf/mpdf/src/Barcode/Code11.php | 26 +- vendor/mpdf/mpdf/src/Barcode/Code128.php | 53 +- vendor/mpdf/mpdf/src/Barcode/Code39.php | 12 +- vendor/mpdf/mpdf/src/Barcode/Code93.php | 10 +- vendor/mpdf/mpdf/src/Barcode/EanExt.php | 2 +- vendor/mpdf/mpdf/src/Barcode/EanUpc.php | 5 +- vendor/mpdf/mpdf/src/Barcode/I25.php | 8 +- vendor/mpdf/mpdf/src/Barcode/Msi.php | 8 +- vendor/mpdf/mpdf/src/Barcode/S25.php | 8 +- vendor/mpdf/mpdf/src/Cache.php | 9 +- vendor/mpdf/mpdf/src/Color/ColorConverter.php | 36 +- .../mpdf/mpdf/src/Config/ConfigVariables.php | 5 +- vendor/mpdf/mpdf/src/CssManager.php | 20 +- vendor/mpdf/mpdf/src/Form.php | 2 - vendor/mpdf/mpdf/src/FpdiTrait.php | 63 +-- vendor/mpdf/mpdf/src/Gradient.php | 63 ++- vendor/mpdf/mpdf/src/Image/ImageProcessor.php | 75 ++- .../mpdf/mpdf/src/Image/ImageTypeGuesser.php | 4 + vendor/mpdf/mpdf/src/Image/Svg.php | 466 ++++++++++++++---- vendor/mpdf/mpdf/src/Mpdf.php | 216 +++++--- vendor/mpdf/mpdf/src/Otl.php | 17 +- vendor/mpdf/mpdf/src/OtlDump.php | 4 +- vendor/mpdf/mpdf/src/Pdf/Protection.php | 2 +- vendor/mpdf/mpdf/src/RemoteContentFetcher.php | 6 +- vendor/mpdf/mpdf/src/ServiceFactory.php | 19 +- vendor/mpdf/mpdf/src/Shaper/Indic.php | 2 +- vendor/mpdf/mpdf/src/TTFontFile.php | 16 +- vendor/mpdf/mpdf/src/TTFontFileAnalysis.php | 2 +- vendor/mpdf/mpdf/src/Tag.php | 5 +- vendor/mpdf/mpdf/src/Tag/BarCode.php | 21 +- vendor/mpdf/mpdf/src/Tag/BlockTag.php | 3 +- vendor/mpdf/mpdf/src/Tag/Img.php | 1 - vendor/mpdf/mpdf/src/Tag/Table.php | 9 + vendor/mpdf/mpdf/src/Tag/Tag.php | 4 +- vendor/mpdf/mpdf/src/Tag/Td.php | 17 +- vendor/mpdf/mpdf/src/Tag/Tr.php | 2 + vendor/mpdf/mpdf/src/Utils/Arrays.php | 8 + vendor/mpdf/mpdf/src/Writer/BaseWriter.php | 1 - vendor/mpdf/mpdf/src/Writer/FontWriter.php | 1 - vendor/mpdf/mpdf/src/Writer/FormWriter.php | 1 - .../mpdf/mpdf/src/Writer/MetadataWriter.php | 1 - 58 files changed, 1283 insertions(+), 544 deletions(-) delete mode 100644 vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE.md create mode 100644 vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/Bug_report.md create mode 100644 vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/Feature_request.md create mode 100644 vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/config.yml create mode 100644 vendor/mpdf/mpdf/.github/workflows/coverage.yml create mode 100644 vendor/mpdf/mpdf/.github/workflows/cs.yml create mode 100644 vendor/mpdf/mpdf/.github/workflows/tests.yml diff --git a/composer.lock b/composer.lock index 60bacabb..c66b74c8 100644 --- a/composer.lock +++ b/composer.lock @@ -8,33 +8,33 @@ "packages": [ { "name": "mpdf/mpdf", - "version": "v8.0.7", + "version": "v8.0.17", "source": { "type": "git", "url": "https://github.com/mpdf/mpdf.git", - "reference": "7daf07f15334ed59a276bd52131dcca48794cdbd" + "reference": "5f64118317c8145c0abc606b310aa0a66808398a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/7daf07f15334ed59a276bd52131dcca48794cdbd", - "reference": "7daf07f15334ed59a276bd52131dcca48794cdbd", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/5f64118317c8145c0abc606b310aa0a66808398a", + "reference": "5f64118317c8145c0abc606b310aa0a66808398a", "shasum": "" }, "require": { "ext-gd": "*", "ext-mbstring": "*", "myclabs/deep-copy": "^1.7", - "paragonie/random_compat": "^1.4|^2.0|9.99.99", - "php": "^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0", - "psr/log": "^1.0", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0", + "psr/log": "^1.0 || ^2.0", "setasign/fpdi": "^2.1" }, "require-dev": { - "mockery/mockery": "^0.9.5", - "mpdf/qrcode": "^1.0.0", - "phpunit/phpunit": "^5.0", + "mockery/mockery": "^1.3.0", + "mpdf/qrcode": "^1.1.0", "squizlabs/php_codesniffer": "^3.5.0", - "tracy/tracy": "^2.4" + "tracy/tracy": "^2.4", + "yoast/phpunit-polyfills": "^1.0" }, "suggest": { "ext-bcmath": "Needed for generation of some types of barcodes", @@ -42,11 +42,6 @@ "ext-zlib": "Needed for compression of embedded resources, such as fonts" }, "type": "library", - "extra": { - "branch-alias": { - "dev-development": "7.x-dev" - } - }, "autoload": { "psr-4": { "Mpdf\\": "src/" @@ -73,7 +68,18 @@ "php", "utf-8" ], - "time": "2020-07-15T09:48:00+00:00" + "support": { + "docs": "http://mpdf.github.io", + "issues": "https://github.com/mpdf/mpdf/issues", + "source": "https://github.com/mpdf/mpdf" + }, + "funding": [ + { + "url": "https://www.paypal.me/mpdf", + "type": "custom" + } + ], + "time": "2022-01-20T10:51:40+00:00" }, { "name": "mpdf/qrcode", @@ -311,5 +317,5 @@ "platform-overrides": { "php": "7.2" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index a72151c7..7824d8f7 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 2fe9c257..12b00b9b 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -2,47 +2,42 @@ "packages": [ { "name": "mpdf/mpdf", - "version": "v8.0.7", - "version_normalized": "8.0.7.0", + "version": "v8.0.17", + "version_normalized": "8.0.17.0", "source": { "type": "git", "url": "https://github.com/mpdf/mpdf.git", - "reference": "7daf07f15334ed59a276bd52131dcca48794cdbd" + "reference": "5f64118317c8145c0abc606b310aa0a66808398a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/mpdf/mpdf/zipball/7daf07f15334ed59a276bd52131dcca48794cdbd", - "reference": "7daf07f15334ed59a276bd52131dcca48794cdbd", + "url": "https://api.github.com/repos/mpdf/mpdf/zipball/5f64118317c8145c0abc606b310aa0a66808398a", + "reference": "5f64118317c8145c0abc606b310aa0a66808398a", "shasum": "" }, "require": { "ext-gd": "*", "ext-mbstring": "*", "myclabs/deep-copy": "^1.7", - "paragonie/random_compat": "^1.4|^2.0|9.99.99", - "php": "^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0", - "psr/log": "^1.0", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0", + "psr/log": "^1.0 || ^2.0", "setasign/fpdi": "^2.1" }, "require-dev": { - "mockery/mockery": "^0.9.5", - "mpdf/qrcode": "^1.0.0", - "phpunit/phpunit": "^5.0", + "mockery/mockery": "^1.3.0", + "mpdf/qrcode": "^1.1.0", "squizlabs/php_codesniffer": "^3.5.0", - "tracy/tracy": "^2.4" + "tracy/tracy": "^2.4", + "yoast/phpunit-polyfills": "^1.0" }, "suggest": { "ext-bcmath": "Needed for generation of some types of barcodes", "ext-xml": "Needed mainly for SVG manipulation", "ext-zlib": "Needed for compression of embedded resources, such as fonts" }, - "time": "2020-07-15T09:48:00+00:00", + "time": "2022-01-20T10:51:40+00:00", "type": "library", - "extra": { - "branch-alias": { - "dev-development": "7.x-dev" - } - }, "installation-source": "dist", "autoload": { "psr-4": { @@ -70,6 +65,17 @@ "php", "utf-8" ], + "support": { + "docs": "http://mpdf.github.io", + "issues": "https://github.com/mpdf/mpdf/issues", + "source": "https://github.com/mpdf/mpdf" + }, + "funding": [ + { + "url": "https://www.paypal.me/mpdf", + "type": "custom" + } + ], "install-path": "../mpdf/mpdf" }, { diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 87247289..41dd26d4 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'splitbrain/dw2pdf', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '0680251b39194f10d53b3b0a54d928c151819766', + 'reference' => '7d636181fc5bb007c30530a67e7c156f19ded673', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -11,9 +11,9 @@ ), 'versions' => array( 'mpdf/mpdf' => array( - 'pretty_version' => 'v8.0.7', - 'version' => '8.0.7.0', - 'reference' => '7daf07f15334ed59a276bd52131dcca48794cdbd', + 'pretty_version' => 'v8.0.17', + 'version' => '8.0.17.0', + 'reference' => '5f64118317c8145c0abc606b310aa0a66808398a', 'type' => 'library', 'install_path' => __DIR__ . '/../mpdf/mpdf', 'aliases' => array(), @@ -67,7 +67,7 @@ 'splitbrain/dw2pdf' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '0680251b39194f10d53b3b0a54d928c151819766', + 'reference' => '7d636181fc5bb007c30530a67e7c156f19ded673', 'type' => 'library', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/vendor/mpdf/mpdf/.github/CONTRIBUTING.md b/vendor/mpdf/mpdf/.github/CONTRIBUTING.md index 35e0e60b..eef6959a 100644 --- a/vendor/mpdf/mpdf/.github/CONTRIBUTING.md +++ b/vendor/mpdf/mpdf/.github/CONTRIBUTING.md @@ -7,12 +7,33 @@ Issue tracker The Issue tracker serves mainly as a place to report bugs and request new features. Please do not abuse it as a general questions or troubleshooting location. -For these questions you can always use the -[mpdf tag](https://stackoverflow.com/questions/tagged/mpdf) at [Stack Overflow](https://stackoverflow.com/). +General troubleshooting +------------- + +For these questions please use [Discussions](https://github.com/mpdf/mpdf/discussions). Add your enquiry +to appropriate category and as always, include a reproducible code example when applicable (see code example guidelines below). + +You can also use the [mpdf tag](https://stackoverflow.com/questions/tagged/mpdf) +at [Stack Overflow](https://stackoverflow.com/) +as the StackOverflow user base is more likely to answer you in a timely manner. +When doing so, make sure you comply to StackOverflow question guidelines. + +Bug reports +------------- + +* Bug reports **MUST** contain a small example in php/html that reproduces the bug. +* The code example **MUST** be reproducible by copy&paste assuming composer dependencies are installed. That means: + * No calling unrelated funcions, + * an actual final HTML code has to be present, pasting a template file is not enough, + * if the bug considers import or fonts, example source PDF/TTF/etc files have to be included. +* Failing to provide necessary information or not using the issue template will cause the issue to be closed until required information is provided. +* Please report one feature or one bug per issue. + +Feature requests +------------- + +Feature requests have to be labeled as such and have to include reasoning for the change in question. -* Please provide a small example in php/html that reproduces your situation -* Please report one feature or one bug per issue -* Failing to provide necessary information or not using the issue template may cause the issue to be closed without consideration. Pull requests ------------- @@ -20,17 +41,13 @@ Pull requests Pull requests should be always based on the default [development](https://github.com/mpdf/mpdf/tree/development) branch except for backports to older versions. -Some guidelines: +Guidelines: * Use an aptly named feature branch for the Pull request. - * Only files and lines affecting the scope of the Pull request must be affected. - * Make small, *atomic* commits that keep the smallest possible related code changes together. - -* Code should be accompanied by a unit test testing expected behaviour. - -* To be incorporated, the PR must contain a change in the CHANGELOG.md file describing itself +* Code must be accompanied by a unit test testing expected behaviour whenever possible. +* To be incorporated, the PR should contain a change in the CHANGELOG.md file describing itself When updating a PR, do not create a new one, just `git push --force` to your former feature branch, the PR will update itself. diff --git a/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE.md b/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 4aca9f8d..00000000 --- a/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,22 +0,0 @@ -> Please use https://stackoverflow.com/questions/tagged/mpdf for all your general questions or troubleshooting! -> For contributing here, please see the guideline: https://github.com/mpdf/mpdf/blob/development/.github/CONTRIBUTING.md -> -> *Warning*: Failing to provide necessary information may cause the issue to be closed without consideration - -### I found this bug / would like to have this new functionality - -### This is mPDF and PHP version and environment (server/fpm/cli etc) I am using - -### This is a PHP code snippet I use - -``` - + +### I found this bug + +### This is mPDF and PHP version and environment (server/fpm/cli etc) I am using + +### This is the PHP code snippet I use + +``` + diff --git a/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/config.yml b/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..901d9c25 --- /dev/null +++ b/vendor/mpdf/mpdf/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,7 @@ +contact_links: + - name: General questions and troubleshooting ❓ + url: https://github.com/mpdf/mpdf/discussions + about: You can use Github Discussions for general questions and troubleshooting. Please note that asking at Stack Overflow will probably be more successful. + - name: QA at Stack Overflow ❓ + url: https://stackoverflow.com/questions/tagged/mpdf + about: Ask at Stack Overflow for a greater chance of a quick and correct answer to your questions. Make sure to comply to SO rules, terms and conditions. diff --git a/vendor/mpdf/mpdf/.github/workflows/coverage.yml b/vendor/mpdf/mpdf/.github/workflows/coverage.yml new file mode 100644 index 00000000..13b1207b --- /dev/null +++ b/vendor/mpdf/mpdf/.github/workflows/coverage.yml @@ -0,0 +1,42 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +name: "Code coverage" + +on: + push: + branches: + - "development" + - "coverage" + +jobs: + + coverage: + + name: "Code coverage" + + runs-on: ${{ matrix.operating-system }} + + strategy: + matrix: + php-version: + - "7.4" + + operating-system: [ubuntu-latest] + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "xdebug" + php-version: "${{ matrix.php-version }}" + extensions: "mbstring, gd, bcmath, bz2" + tools: composer:v2 + + - name: "Install dependencies" + run: "composer install --no-interaction --no-progress" + + - name: "Code coverage" + run: composer coverage diff --git a/vendor/mpdf/mpdf/.github/workflows/cs.yml b/vendor/mpdf/mpdf/.github/workflows/cs.yml new file mode 100644 index 00000000..ff003e01 --- /dev/null +++ b/vendor/mpdf/mpdf/.github/workflows/cs.yml @@ -0,0 +1,43 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +name: "Coding standard check" + +on: + pull_request: + push: + branches: + - "development" + - "test" + +jobs: + + cs: + + name: "Coding standard" + + runs-on: ${{ matrix.operating-system }} + + strategy: + matrix: + php-version: + - "7.4" + + operating-system: [ubuntu-latest] + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + extensions: "mbstring" + tools: composer:v2 + + - name: "Install dependencies" + run: "composer install --no-interaction --no-progress" + + - name: "CS" + run: composer cs diff --git a/vendor/mpdf/mpdf/.github/workflows/tests.yml b/vendor/mpdf/mpdf/.github/workflows/tests.yml new file mode 100644 index 00000000..ff64a816 --- /dev/null +++ b/vendor/mpdf/mpdf/.github/workflows/tests.yml @@ -0,0 +1,52 @@ +# https://help.github.com/en/categories/automating-your-workflow-with-github-actions + +name: "CI" + +on: + pull_request: + push: + branches: + - "master" + - "development" + - "test" + +jobs: + + tests: + + name: "Tests" + + runs-on: ${{ matrix.operating-system }} + + strategy: + fail-fast: false + matrix: + php-version: + - "5.6" + - "7.0" + - "7.1" + - "7.2" + - "7.3" + - "7.4" + - "8.0" + - "8.1" + operating-system: [ubuntu-latest, windows-latest] + + steps: + - name: "Checkout" + uses: "actions/checkout@v2" + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "${{ matrix.php-version }}" + extensions: "mbstring, gd, bcmath, bz2" + tools: composer:v2 + ini-values: error_reporting=-1 + + - name: "Install dependencies" + run: "composer install --no-interaction --no-progress" + + - name: "Tests" + run: composer test diff --git a/vendor/mpdf/mpdf/CHANGELOG.md b/vendor/mpdf/mpdf/CHANGELOG.md index 77bb294a..9c184e29 100644 --- a/vendor/mpdf/mpdf/CHANGELOG.md +++ b/vendor/mpdf/mpdf/CHANGELOG.md @@ -23,6 +23,19 @@ mPDF 8.0.x * Fixed CMYK colors in text-shadow (#1115, @lexilya) * Skip non supported wrappers when resolving paths (#1204, @MarkVaughn) * Fixed SVGs using a style tag, has styles ignored ( Requires ext-dom ) (#450, @antman3351) +* Allows `{nb}`, `{nbpg}`, `{PAGENO}` and `{DATE ...}` substitution in body (#172 and #267, @Dasc3er) +* Cache now creates a dedicated subdirectory `/mpdf`. +* It is possible to disable automatic cache cleanup with `cacheCleanupInterval` config variable +* PHP 8.0 is supported since 8.0.10 (#1263) +* Fix: First header of named page is added twice (@antman3351, #1320) +* Added `curlExecutionTimeout` configuration variable allowing to `CURLOPT_TIMEOUT` when fetching remote content +* Fix: Not all combinations were generated for more than three compound classes (@JeppeKnockaert) +* Added `quiet_zone_left` and `quiet_zone_right` to barcodes which support quiet zones in order to customize its width +* Updated `CssManager` to use the `RemoteContentFetcher` class instead of `curl` natively (@greew) +* Added optional `continue2pages` parameter to `SetDocTemplate` method, allowing a template to continue the last 2 pages alternately (@bmg-ruudv) +* Ensure that all digits of a string are hexadecimal before decoding in ColorConverter (@derklaro) +* Fix: Using mpdf in phar package leads to weird errors (#1504, @sandreas) +* WEBP images support (#1525) mPDF 8.0.0 =========================== diff --git a/vendor/mpdf/mpdf/README.md b/vendor/mpdf/mpdf/README.md index b0709ee3..366ddace 100644 --- a/vendor/mpdf/mpdf/README.md +++ b/vendor/mpdf/mpdf/README.md @@ -5,12 +5,11 @@ It is based on [FPDF](http://www.fpdf.org/) and [HTML2FPDF](http://html2fpdf.sou under the [GNU GPL v2 licence](LICENSE.txt). [![Latest Stable Version](https://poser.pugx.org/mpdf/mpdf/v/stable)](https://packagist.org/packages/mpdf/mpdf) -[![Build Status](https://travis-ci.org/mpdf/mpdf.svg?branch=development)](https://travis-ci.org/mpdf/mpdf) [![Total Downloads](https://poser.pugx.org/mpdf/mpdf/downloads)](https://packagist.org/packages/mpdf/mpdf) [![License](https://poser.pugx.org/mpdf/mpdf/license)](https://packagist.org/packages/mpdf/mpdf) -> Note: If you are viewing this file on mPDF GitHub repository homepage or on Packagist, please note that +> ⚠ If you are viewing this file on mPDF GitHub repository homepage or on Packagist, please note that > the default repository branch is `development` which can differ from the last stable release. Requirements @@ -19,10 +18,11 @@ Requirements PHP versions and extensions --------------------------- -- `mPDF >=7.0` is supported on PHP `^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0` +- `mPDF >=7.0` is supported on `PHP ^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0` - `PHP 7.3` is supported since `mPDF v7.1.7` - `PHP 7.4` is supported since `mPDF v8.0.4` - +- `PHP 8.0` is supported since `mPDF v8.0.10` +- `PHP 8.1` is supported as of `mPDF v8.0.13` PHP `mbstring` and `gd` extensions have to be loaded. @@ -89,7 +89,7 @@ $mpdf = new \Mpdf\Mpdf(['tempDir' => __DIR__ . '/tmp']); ``` -By default, the temporary directory will be inside vendor directory and will have correct permissions from +By default, the temporary directory will be inside vendor directory and will have write permissions from `post_install` composer script. For more information about custom temporary directory see the note on @@ -99,17 +99,36 @@ in the section on Installation & Setup in the [manual][1]. If you have problems, please read the section on [troubleshooting](https://mpdf.github.io/troubleshooting/known-issues.html) in the manual. +About CSS support and development state +======================================= + +mPDF as a whole is a quite dated software. Nowadays, better alternatives are available, albeit not written in PHP. + +Use mPDF if you cannot use non-PHP approach to generate PDF files or if you want to leverage some of the benefits of mPDF +over browser approach – color handling, pre-print, barcodes support, headers and footers, page numbering, TOCs, etc. +But beware that a HTML/CSS template tailored for mPDF might be necessary. + +If you are looking for state of the art CSS support, mirroring existing HTML pages to PDF, use headless Chrome. + +mPDF will still be updated to enhance some internal capabilities and to support newer versions of PHP, +but better and/or newer CSS support will most likely not be implemented. + Online manual ============= Online manual is available at https://mpdf.github.io/. -For general questions or troubleshooting please use the [mpdf tag](https://stackoverflow.com/questions/tagged/mpdf) at Stack Overflow (and not the project's issue tracker). +General troubleshooting +============= + +For general questions or troubleshooting please use [Discussions](https://github.com/mpdf/mpdf/discussions). + +You can also use the [mpdf tag](https://stackoverflow.com/questions/tagged/mpdf) at Stack Overflow as the StackOverflow user base is more likely to answer you in a timely manner. Contributing ============ -Please read before submitting issues and pull requests the [CONTRIBUTING.md](https://github.com/mpdf/mpdf/blob/development/.github/CONTRIBUTING.md) file. +Before submitting issues and pull requests please read the [CONTRIBUTING.md](https://github.com/mpdf/mpdf/blob/development/.github/CONTRIBUTING.md) file. Unit Testing ============ @@ -119,7 +138,7 @@ Unit testing for mPDF is done using [PHPUnit](https://phpunit.de/). To get started, run `composer install` from the command line while in the mPDF root directory (you'll need [composer installed first](https://getcomposer.org/download/)). -To execute tests, run `vendor/bin/phpunit` from the command line while in the mPDF root directory. +To execute tests, run `composer test` from the command line while in the mPDF root directory. Any assistance writing unit tests for mPDF is greatly appreciated. If you'd like to help, please note that any PHP file located in the `/tests/` directory will be autoloaded when unit testing. diff --git a/vendor/mpdf/mpdf/composer.json b/vendor/mpdf/mpdf/composer.json index 425d955a..c93e87d2 100644 --- a/vendor/mpdf/mpdf/composer.json +++ b/vendor/mpdf/mpdf/composer.json @@ -1,15 +1,10 @@ { - "name": "mpdf/mpdf", "type": "library", - "description": "PHP library generating PDF files from UTF-8 encoded HTML", - "keywords": ["php", "pdf", "utf-8"], "homepage": "https://mpdf.github.io", - "license": ["GPL-2.0-only"], - "authors": [ { "name": "Matěj Humpál", @@ -20,67 +15,45 @@ "role": "Developer (retired)" } ], - "support": { - "issues": "https://github.com/mpdf/mpdf/issues", "source": "https://github.com/mpdf/mpdf", "docs": "http://mpdf.github.io" - }, - "require": { - - "php": "^5.6 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0", - + "php": "^5.6 || ^7.0 || ~8.0.0 || ~8.1.0", "ext-gd": "*", "ext-mbstring": "*", - - "psr/log": "^1.0", - "setasign/fpdi": "^2.1", - "paragonie/random_compat": "^1.4|^2.0|9.99.99", - "myclabs/deep-copy": "^1.7" - + "myclabs/deep-copy": "^1.7", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "psr/log": "^1.0 || ^2.0", + "setasign/fpdi": "^2.1" }, - "require-dev": { - - "phpunit/phpunit": "^5.0", - "mockery/mockery": "^0.9.5", + "mockery/mockery": "^1.3.0", + "mpdf/qrcode": "^1.1.0", "squizlabs/php_codesniffer": "^3.5.0", "tracy/tracy": "^2.4", - "mpdf/qrcode": "^1.0.0" - + "yoast/phpunit-polyfills": "^1.0" }, - "suggest": { - "ext-bcmath": "Needed for generation of some types of barcodes", "ext-zlib": "Needed for compression of embedded resources, such as fonts", "ext-xml": "Needed mainly for SVG manipulation" - }, - "autoload": { - "psr-4": { "Mpdf\\": "src/" } - }, - "autoload-dev": { - "psr-4": { "Mpdf\\": "tests/Mpdf" }, - "files": [ "src/functions-dev.php" ] - }, - "scripts": { "post-install-cmd": [ "php -r \"chmod('./tmp', 0777);\"" @@ -89,11 +62,7 @@ "test": "@php vendor/bin/phpunit", "coverage": "@php vendor/bin/phpunit --coverage-text" }, - - "extra": { - "branch-alias": { - "dev-development": "7.x-dev" - } + "config": { + "sort-packages": true } - } diff --git a/vendor/mpdf/mpdf/src/Barcode.php b/vendor/mpdf/mpdf/src/Barcode.php index 97054b47..1af897b6 100644 --- a/vendor/mpdf/mpdf/src/Barcode.php +++ b/vendor/mpdf/mpdf/src/Barcode.php @@ -5,9 +5,9 @@ class Barcode { - public function getBarcodeArray($code, $type, $pr = '') + public function getBarcodeArray($code, $type, $pr = '', $quiet_zone_left = null, $quiet_zone_right = null) { - $barcode = $this->getBarcode($code, $type, $pr); + $barcode = $this->getBarcode($code, $type, $pr, $quiet_zone_left, $quiet_zone_right); return $barcode ? $barcode->getData() : false; } @@ -24,7 +24,7 @@ public function getChecksum($code, $type) * * @return \Mpdf\Barcode\BarcodeInterface */ - public function getBarcode($code, $type, $pr = 0.0) + public function getBarcode($code, $type, $pr = 0.0, $quiet_zone_left = null, $quiet_zone_right = null) { switch (strtoupper($type)) { case 'ISBN': @@ -73,70 +73,70 @@ public function getBarcode($code, $type, $pr = 0.0) return new Barcode\Postnet($code, $xdim, ((25.4 / $bpi) - $xdim) / $xdim, true); case 'C93': // CODE 93 - USS-93 - return new Barcode\Code93($code); + return new Barcode\Code93($code, $quiet_zone_left, $quiet_zone_right); case 'CODE11': // CODE 11 - return new Barcode\Code11($code, ($pr > 0) ? $pr : 3); + return new Barcode\Code11($code, ($pr > 0) ? $pr : 3, $quiet_zone_left, $quiet_zone_right); case 'MSI': // MSI (Variation of Plessey code) - return new Barcode\Msi($code, false); + return new Barcode\Msi($code, false, $quiet_zone_left, $quiet_zone_right); case 'MSI+': // MSI + CHECKSUM (modulo 11) - return new Barcode\Msi($code, true); + return new Barcode\Msi($code, true, $quiet_zone_left, $quiet_zone_right); case 'CODABAR': // CODABAR - return new Barcode\Codabar($code, ($pr > 0) ? $pr : 2.5); + return new Barcode\Codabar($code, ($pr > 0) ? $pr : 2.5, $quiet_zone_left, $quiet_zone_right); case 'C128A': // CODE 128 A - return new Barcode\Code128($code, 'A'); + return new Barcode\Code128($code, 'A', false, $quiet_zone_left, $quiet_zone_right); case 'C128B': // CODE 128 B - return new Barcode\Code128($code, 'B'); + return new Barcode\Code128($code, 'B', false, $quiet_zone_left, $quiet_zone_right); case 'C128C': // CODE 128 C - return new Barcode\Code128($code, 'C'); + return new Barcode\Code128($code, 'C', false, $quiet_zone_left, $quiet_zone_right); case 'C128RAW': // CODE 128 RAW -- code is a space separated list of codes with startcode but without checkdigit,stop,end ex: "105 12 34" - return new Barcode\Code128($code, 'RAW'); + return new Barcode\Code128($code, 'RAW', false, $quiet_zone_left, $quiet_zone_right); case 'EAN128A': // EAN 128 A - return new Barcode\Code128($code, 'A', true); + return new Barcode\Code128($code, 'A', true, $quiet_zone_left, $quiet_zone_right); case 'EAN128B': // EAN 128 B - return new Barcode\Code128($code, 'B', true); + return new Barcode\Code128($code, 'B', true, $quiet_zone_left, $quiet_zone_right); case 'EAN128C': // EAN 128 C - return new Barcode\Code128($code, 'C', true); + return new Barcode\Code128($code, 'C', true, $quiet_zone_left, $quiet_zone_right); case 'C39': // CODE 39 - ANSI MH10.8M-1983 - USD-3 - 3 of 9. - return new Barcode\Code39($this->sanitizeCode($code), ($pr > 0) ? $pr : 2.5, false, false); + return new Barcode\Code39($this->sanitizeCode($code), ($pr > 0) ? $pr : 2.5, false, false, $quiet_zone_left, $quiet_zone_right); case 'C39+': // CODE 39 with checksum - return new Barcode\Code39($this->sanitizeCode($code), ($pr > 0) ? $pr : 2.5, false, true); + return new Barcode\Code39($this->sanitizeCode($code), ($pr > 0) ? $pr : 2.5, false, true, $quiet_zone_left, $quiet_zone_right); case 'C39E': // CODE 39 EXTENDED - return new Barcode\Code39($this->sanitizeCode($code), ($pr > 0) ? $pr : 2.5, true, false); + return new Barcode\Code39($this->sanitizeCode($code), ($pr > 0) ? $pr : 2.5, true, false, $quiet_zone_left, $quiet_zone_right); case 'C39E+': // CODE 39 EXTENDED + CHECKSUM - return new Barcode\Code39($this->sanitizeCode($code), ($pr > 0) ? $pr : 2.5, true, true); + return new Barcode\Code39($this->sanitizeCode($code), ($pr > 0) ? $pr : 2.5, true, true, $quiet_zone_left, $quiet_zone_right); case 'S25': // Standard 2 of 5 - return new Barcode\S25($code, false); + return new Barcode\S25($code, false, $quiet_zone_left, $quiet_zone_right); case 'S25+': // Standard 2 of 5 + CHECKSUM - return new Barcode\S25($code, true); + return new Barcode\S25($code, true, $quiet_zone_left, $quiet_zone_right); case 'I25': // Interleaved 2 of 5 - return new Barcode\I25($code, 0, ($pr > 0) ? $pr : 2.5, false); + return new Barcode\I25($code, 0, ($pr > 0) ? $pr : 2.5, false, $quiet_zone_left, $quiet_zone_right); case 'I25+': // Interleaved 2 of 5 + CHECKSUM - return new Barcode\I25($code, 0, ($pr > 0) ? $pr : 2.5, true); + return new Barcode\I25($code, 0, ($pr > 0) ? $pr : 2.5, true, $quiet_zone_left, $quiet_zone_right); case 'I25B': // Interleaved 2 of 5 + Bearer bars - return new Barcode\I25($code, 2, ($pr > 0) ? $pr : 2.5, false); + return new Barcode\I25($code, 2, ($pr > 0) ? $pr : 2.5, false, $quiet_zone_left, $quiet_zone_right); case 'I25B+': // Interleaved 2 of 5 + CHECKSUM + Bearer bars - return new Barcode\I25($code, 2, ($pr > 0) ? $pr : 2.5, true); + return new Barcode\I25($code, 2, ($pr > 0) ? $pr : 2.5, true, $quiet_zone_left, $quiet_zone_right); } return false; diff --git a/vendor/mpdf/mpdf/src/Barcode/Codabar.php b/vendor/mpdf/mpdf/src/Barcode/Codabar.php index e05e370d..6fae06b0 100644 --- a/vendor/mpdf/mpdf/src/Barcode/Codabar.php +++ b/vendor/mpdf/mpdf/src/Barcode/Codabar.php @@ -13,14 +13,14 @@ class Codabar extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\Bar * @param string $code * @param float $printRatio */ - public function __construct($code, $printRatio) + public function __construct($code, $printRatio, $quiet_zone_left = null, $quiet_zone_right = null) { $this->init($code, $printRatio); $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) - $this->data['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) - $this->data['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) + $this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 10); // LEFT light margin = x X-dim (spec.) + $this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 10); // RIGHT light margin = x X-dim (spec.) $this->data['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) } @@ -60,10 +60,13 @@ private function init($code, $printRatio) $len = strlen($code); for ($i = 0; $i < $len; ++$i) { + if (!isset($chr[$code[$i]])) { - throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" CODABAR barcode value', $code[$i])); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODABAR barcode value "%s"', $code[$i], $code)); } + $seq = $chr[$code[$i]]; + for ($j = 0; $j < 8; ++$j) { if (($j % 2) == 0) { $t = true; // bar diff --git a/vendor/mpdf/mpdf/src/Barcode/Code11.php b/vendor/mpdf/mpdf/src/Barcode/Code11.php index f95245f6..21de7ff9 100644 --- a/vendor/mpdf/mpdf/src/Barcode/Code11.php +++ b/vendor/mpdf/mpdf/src/Barcode/Code11.php @@ -13,14 +13,14 @@ class Code11 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\Barc * @param string $code * @param float $printRatio */ - public function __construct($code, $printRatio) + public function __construct($code, $printRatio, $quiet_zone_left = null, $quiet_zone_right = null) { $this->init($code, $printRatio); $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) - $this->data['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) - $this->data['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) + $this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 10); // LEFT light margin = x X-dim (spec.) + $this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 10); // RIGHT light margin = x X-dim (spec.) $this->data['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) } @@ -105,24 +105,22 @@ private function init($code, $printRatio) $len += 3; for ($i = 0; $i < $len; ++$i) { + if (!isset($chr[$code[$i]])) { - throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE11 barcode value', $code[$i])); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE11 barcode value "%s"', $code[$i], $code)); } + $seq = $chr[$code[$i]]; + for ($j = 0; $j < 6; ++$j) { - if (($j % 2) == 0) { - $t = true; // bar - } else { - $t = false; // space - } + + $t = $j % 2 === 0; $x = $seq[$j]; - if ($x == 2) { - $w = $printRatio; - } else { - $w = 1; - } + $w = ($x == 2) ? $printRatio : 1; + $bararray['bcode'][$k] = ['t' => $t, 'w' => $w, 'h' => 1, 'p' => 0]; $bararray['maxw'] += $w; + ++$k; } } diff --git a/vendor/mpdf/mpdf/src/Barcode/Code128.php b/vendor/mpdf/mpdf/src/Barcode/Code128.php index e12f4d84..f73bf310 100644 --- a/vendor/mpdf/mpdf/src/Barcode/Code128.php +++ b/vendor/mpdf/mpdf/src/Barcode/Code128.php @@ -16,14 +16,14 @@ class Code128 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\Bar * @param string $type * @param bool $ean */ - public function __construct($code, $type = 'B', $ean = false) + public function __construct($code, $type = 'B', $ean = false, $quiet_zone_left = null, $quiet_zone_right = null) { $this->init($code, $type, $ean); $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) - $this->data['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) - $this->data['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) + $this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 10); // LEFT light margin = x X-dim (spec.) + $this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 10); // RIGHT light margin = x X-dim (spec.) $this->data['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) } @@ -148,11 +148,16 @@ protected function init($code, $type, $ean) ]; switch (strtoupper($type)) { + case 'RAW': + $newCode=''; $startid = false; + foreach (explode(" ", $code) as $v) { + if (is_numeric($v) && round($v, 0) == $v) { + if ($v>=0 && $v<=105) { if ($startid===false) { $startid=$v; @@ -160,57 +165,80 @@ protected function init($code, $type, $ean) $newCode.=chr($v); } } else { - throw new \Mpdf\Barcode\BarcodeException('Invalid CODE128RAW barcode value. 0-105 needed'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid CODE128RAW barcode value "%s". 0-105 needed', $code)); } + } else { //double spaces generates empty $v any other is not allowed if ($v!='') { - throw new \Mpdf\Barcode\BarcodeException('Invalid CODE128RAW barcode value. 0-105 needed'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid CODE128RAW barcode value "%s". 0-105 needed', $code)); } } } - if ($startid<103 || $startid>105) { - throw new \Mpdf\Barcode\BarcodeException('Invalid CODE128RAW startid value. Must 103,104 or 105 (for A,B or C)'); + + if ($startid < 103 || $startid > 105) { + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid CODE128RAW startid value "%s". Must be 103, 104 or 105 (for A, B or C)', $startid)); } + $keys=''; + for ($i = 0; $i <= 105; ++$i) { $keys .= chr($i); } + $code=$newCode; + break; + case 'A': + $startid = 103; $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_'; + for ($i = 0; $i < 32; ++$i) { $keys .= chr($i); } + break; + case 'B': + $startid = 104; + $keys = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~' . chr(127); + break; + case 'C': + $startid = 105; $keys = ''; + if ((strlen($code) % 2) != 0) { // The length of barcode value must be even ($code). You must pad the number with zeros throw new \Mpdf\Barcode\BarcodeException('Invalid CODE128C barcode value'); } + for ($i = 0; $i <= 99; ++$i) { $keys .= chr($i); } + $newCode = ''; $hclen = (strlen($code) / 2); + for ($i = 0; $i < $hclen; ++$i) { if ($code[2 * $i]<"0" || $code[2 * $i]>"9" || $code[2 * $i + 1]<"0" || $code[2 * $i + 1]>"9") { - throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE128C barcode value', $code[$i])); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE128C barcode value "%s"', $code[$i], $code)); } $newCode .= chr((int) ($code[2 * $i] . $code[2 * $i + 1])); } + $code = $newCode; + break; + default: - throw new \Mpdf\Barcode\BarcodeException('Invalid CODE128 barcode type'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid CODE128 barcode type "%s"', $type)); } // calculate check character @@ -220,17 +248,19 @@ protected function init($code, $type, $ean) if ($ean) { $code = chr(102) . $code; } + $clen = strlen($code); for ($i = 0; $i < $clen; ++$i) { if ($ean && $i == 0) { $sum += 102; } else { if (strpos($keys, $code[$i]) === false) { - throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE128'.$type.' barcode value', $code[$i])); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE128%s barcode value "%s"', $code[$i], $type, $code)); } $sum += (strpos($keys, $code[$i]) * ($i + 1)); } } + $check = ($sum % 103); $checkdigit = $check; @@ -250,8 +280,9 @@ protected function init($code, $type, $ean) $seq = $chr[$ck]; } else { // invalid character - throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE128C barcode value', $code[$i])); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE128C barcode value "%s"', $code[$i], $code)); } + for ($j = 0; $j < 6; ++$j) { if (($j % 2) == 0) { $t = true; // bar diff --git a/vendor/mpdf/mpdf/src/Barcode/Code39.php b/vendor/mpdf/mpdf/src/Barcode/Code39.php index 6d130825..a8e39775 100644 --- a/vendor/mpdf/mpdf/src/Barcode/Code39.php +++ b/vendor/mpdf/mpdf/src/Barcode/Code39.php @@ -14,14 +14,14 @@ class Code39 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\Barc * @param bool $extended * @param bool $checksum */ - public function __construct($code, $printRatio, $extended = false, $checksum = false) + public function __construct($code, $printRatio, $extended = false, $checksum = false, $quiet_zone_left = null, $quiet_zone_right = null) { $this->init($code, $printRatio, $extended, $checksum); $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) - $this->data['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) - $this->data['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) + $this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 10); // LEFT light margin = x X-dim (spec.) + $this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 10); // RIGHT light margin = x X-dim (spec.) $this->data['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) } @@ -91,7 +91,7 @@ private function init($code, $printRatio, $extended, $checksum) } if ($code === false) { - throw new \Mpdf\Barcode\BarcodeException('Invalid CODE39 barcode value'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid CODE39 barcode value "%s"', $code)); } if ($checksum) { @@ -109,7 +109,7 @@ private function init($code, $printRatio, $extended, $checksum) $char = $code[$i]; if (!isset($chr[$char])) { // invalid character - throw new \Mpdf\Barcode\BarcodeException('Invalid CODE39 barcode value'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid CODE39 barcode value "%s"', $code)); } for ($j = 0; $j < 9; ++$j) { if (($j % 2) == 0) { @@ -187,7 +187,7 @@ protected function encodeExt($code) for ($i = 0; $i < $clen; ++$i) { if (ord($code[$i]) > 127) { - throw new \Mpdf\Barcode\BarcodeException('Invalid CODE39 barcode value'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid CODE39 barcode value "%s"', $code)); } $code_ext .= $encode[$code[$i]]; diff --git a/vendor/mpdf/mpdf/src/Barcode/Code93.php b/vendor/mpdf/mpdf/src/Barcode/Code93.php index a3f7b25c..1a08d8c8 100644 --- a/vendor/mpdf/mpdf/src/Barcode/Code93.php +++ b/vendor/mpdf/mpdf/src/Barcode/Code93.php @@ -12,14 +12,14 @@ class Code93 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\Barc /** * @param string $code */ - public function __construct($code) + public function __construct($code, $quiet_zone_left = null, $quiet_zone_right = null) { $this->init($code); $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) - $this->data['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) - $this->data['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) + $this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 10); // LEFT light margin = x X-dim (spec.) + $this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 10); // RIGHT light margin = x X-dim (spec.) $this->data['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) } @@ -120,7 +120,7 @@ private function init($code) for ($i = 0; $i < $clen; ++$i) { if (ord($code[$i]) > 127) { - throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in Code93 barcode value', $code[$i])); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in CODE93 barcode value "%s"', $code[$i], $code)); } $code_ext .= $encode[$code[$i]]; } @@ -138,7 +138,7 @@ private function init($code) $char = ord($code[$i]); if (!isset($chr[$char])) { // invalid character - throw new \Mpdf\Barcode\BarcodeException('Invalid CODE93 barcode value'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid CODE93 barcode value "%s"', $code)); } for ($j = 0; $j < 6; ++$j) { if (($j % 2) == 0) { diff --git a/vendor/mpdf/mpdf/src/Barcode/EanExt.php b/vendor/mpdf/mpdf/src/Barcode/EanExt.php index 21044a79..b336b1c2 100644 --- a/vendor/mpdf/mpdf/src/Barcode/EanExt.php +++ b/vendor/mpdf/mpdf/src/Barcode/EanExt.php @@ -46,7 +46,7 @@ private function init($code, $length = 5) $r = (3 * ($code[0] + $code[2] + $code[4])) + (9 * ($code[1] + $code[3])); $r %= 10; } else { - throw new \Mpdf\Barcode\BarcodeException('Invalid EAN barcode value'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid EAN barcode value "%s"', $code)); } // Convert digits to bars diff --git a/vendor/mpdf/mpdf/src/Barcode/EanUpc.php b/vendor/mpdf/mpdf/src/Barcode/EanUpc.php index d4eab703..e122422d 100644 --- a/vendor/mpdf/mpdf/src/Barcode/EanUpc.php +++ b/vendor/mpdf/mpdf/src/Barcode/EanUpc.php @@ -36,7 +36,7 @@ public function __construct($code, $length, $leftMargin, $rightMargin, $xDim, $b private function init($code, $length) { if (preg_match('/[\D]+/', $code)) { - throw new \Mpdf\Barcode\BarcodeException('Invalid EAN UPC barcode value'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid EAN UPC barcode value "%s"', $code)); } $upce = false; @@ -81,7 +81,7 @@ private function init($code, $length) $checkdigit = $r; } elseif ($r !== (int) $code[$dataLength]) { // Wrong checkdigit - throw new \Mpdf\Barcode\BarcodeException('Invalid EAN UPC barcode value'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid EAN UPC barcode value "%s"', $code)); } if ($length == 12) { @@ -126,6 +126,7 @@ private function init($code, $length) } } } + if ($invalidUpce) { throw new \Mpdf\Barcode\BarcodeException('UPC-A cannot produce a valid UPC-E barcode'); } diff --git a/vendor/mpdf/mpdf/src/Barcode/I25.php b/vendor/mpdf/mpdf/src/Barcode/I25.php index d18db74a..28465569 100644 --- a/vendor/mpdf/mpdf/src/Barcode/I25.php +++ b/vendor/mpdf/mpdf/src/Barcode/I25.php @@ -16,14 +16,14 @@ class I25 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\Barcode * @param float $printRatio * @param bool $checksum */ - public function __construct($code, $topBottomMargin, $printRatio, $checksum = false) + public function __construct($code, $topBottomMargin, $printRatio, $checksum = false, $quiet_zone_left = null, $quiet_zone_right = null) { $this->init($code, $printRatio, $checksum); $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) - $this->data['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) - $this->data['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) + $this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 10); // LEFT light margin = x X-dim (spec.) + $this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 10); // RIGHT light margin = x X-dim (spec.) $this->data['lightTB'] = $topBottomMargin; // TOP/BOTTOM light margin = x X-dim (non-spec.) } @@ -70,7 +70,7 @@ private function init($code, $printRatio, $checksum) $charSpace = $code[$i + 1]; if ((!isset($chr[$charBar])) or (!isset($chr[$charSpace]))) { // invalid character - throw new \Mpdf\Barcode\BarcodeException('Invalid I25 barcode value'); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid I25 barcode value "%s"', $code)); } // create a bar-space sequence $seq = ''; diff --git a/vendor/mpdf/mpdf/src/Barcode/Msi.php b/vendor/mpdf/mpdf/src/Barcode/Msi.php index 26b57ffe..ac4d1dc9 100644 --- a/vendor/mpdf/mpdf/src/Barcode/Msi.php +++ b/vendor/mpdf/mpdf/src/Barcode/Msi.php @@ -13,14 +13,14 @@ class Msi extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\Barcode * @param int $code * @param bool $checksum */ - public function __construct($code, $checksum = false) + public function __construct($code, $checksum = false, $quiet_zone_left = null, $quiet_zone_right = null) { $this->init($code, $checksum); $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) - $this->data['lightmL'] = 12; // LEFT light margin = x X-dim (spec.) - $this->data['lightmR'] = 12; // RIGHT light margin = x X-dim (spec.) + $this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 12); // LEFT light margin = x X-dim (spec.) + $this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 12); // RIGHT light margin = x X-dim (spec.) $this->data['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) } @@ -76,7 +76,7 @@ private function init($code, $checksum) $digit = $code[$i]; if (!isset($chr[$digit])) { // invalid character - throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in MSI barcode value', $digit)); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in MSI barcode value "%s"', $digit, $code)); } $seq .= $chr[$digit]; } diff --git a/vendor/mpdf/mpdf/src/Barcode/S25.php b/vendor/mpdf/mpdf/src/Barcode/S25.php index c238687b..ed739541 100644 --- a/vendor/mpdf/mpdf/src/Barcode/S25.php +++ b/vendor/mpdf/mpdf/src/Barcode/S25.php @@ -14,14 +14,14 @@ class S25 extends \Mpdf\Barcode\AbstractBarcode implements \Mpdf\Barcode\Barcode * @param string $code * @param bool $checksum */ - public function __construct($code, $checksum = false) + public function __construct($code, $checksum = false, $quiet_zone_left = null, $quiet_zone_right = null) { $this->init($code, $checksum); $this->data['nom-X'] = 0.381; // Nominal value for X-dim (bar width) in mm (2 X min. spec.) $this->data['nom-H'] = 10; // Nominal value for Height of Full bar in mm (non-spec.) - $this->data['lightmL'] = 10; // LEFT light margin = x X-dim (spec.) - $this->data['lightmR'] = 10; // RIGHT light margin = x X-dim (spec.) + $this->data['lightmL'] = ($quiet_zone_left !== null ? $quiet_zone_left : 10); // LEFT light margin = x X-dim (spec.) + $this->data['lightmR'] = ($quiet_zone_right !== null ? $quiet_zone_right : 10); // RIGHT light margin = x X-dim (spec.) $this->data['lightTB'] = 0; // TOP/BOTTOM light margin = x X-dim (non-spec.) } @@ -63,7 +63,7 @@ private function init($code, $checksum) $digit = $code[$i]; if (!isset($chr[$digit])) { // invalid character - throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in S25 barcode value', $digit)); + throw new \Mpdf\Barcode\BarcodeException(sprintf('Invalid character "%s" in S25 barcode value "%s"', $digit, $code)); } $seq .= $chr[$digit]; } diff --git a/vendor/mpdf/mpdf/src/Cache.php b/vendor/mpdf/mpdf/src/Cache.php index bc6bc91b..5554575e 100644 --- a/vendor/mpdf/mpdf/src/Cache.php +++ b/vendor/mpdf/mpdf/src/Cache.php @@ -13,6 +13,10 @@ class Cache public function __construct($basePath, $cleanupInterval = 3600) { + if (!is_int($cleanupInterval) && false !== $cleanupInterval) { + throw new \Mpdf\MpdfException('Cache cleanup interval has to be an integer or false'); + } + if (!$this->createBasePath($basePath)) { throw new \Mpdf\MpdfException(sprintf('Temporary files directory "%s" is not writable', $basePath)); } @@ -72,6 +76,7 @@ public function write($filename, $data) { $tempFile = tempnam($this->basePath, 'cache_tmp_'); file_put_contents($tempFile, $data); + chmod($tempFile, 0664); $path = $this->getFilePath($filename); rename($tempFile, $path); @@ -106,7 +111,9 @@ private function getFilePath($filename) private function isOld(DirectoryIterator $item) { - return $item->getMTime() + $this->cleanupInterval < time(); + return $this->cleanupInterval + ? $item->getMTime() + $this->cleanupInterval < time() + : false; } public function isDotFile(DirectoryIterator $item) diff --git a/vendor/mpdf/mpdf/src/Color/ColorConverter.php b/vendor/mpdf/mpdf/src/Color/ColorConverter.php index 0eeb2bda..fe5e547d 100644 --- a/vendor/mpdf/mpdf/src/Color/ColorConverter.php +++ b/vendor/mpdf/mpdf/src/Color/ColorConverter.php @@ -53,7 +53,15 @@ public function convert($color, array &$PDFAXwarnings = []) $cstr = ''; if (is_array($c)) { $c = array_pad($c, 6, 0); - $cstr = pack('a1ccccc', $c[0], $c[1] & 0xFF, $c[2] & 0xFF, $c[3] & 0xFF, $c[4] & 0xFF, $c[5] & 0xFF); + $cstr = pack( + 'a1ccccc', + $c[0], + round($c[1]) & 0xFF, + round($c[2]) & 0xFF, + round($c[3]) & 0xFF, + round($c[4]) & 0xFF, + round($c[5]) & 0xFF + ); } $this->cache[$color] = $cstr; @@ -78,7 +86,15 @@ public function lighten($c) } $c = array_pad($ret, 6, 0); - $cstr = pack('a1ccccc', $c[0], $c[1] & 0xFF, $c[2] & 0xFF, $c[3] & 0xFF, $c[4] & 0xFF, $c[5] & 0xFF); + $cstr = pack( + 'a1ccccc', + $c[0], + round($c[1]) & 0xFF, + round($c[2]) & 0xFF, + round($c[3]) & 0xFF, + round($c[4]) & 0xFF, + round($c[5]) & 0xFF + ); return $cstr; } @@ -202,9 +218,9 @@ private function processHashColor($color) $cor = '#' . $cor[1] . $cor[1] . $cor[2] . $cor[2] . $cor[3] . $cor[3]; } - $r = hexdec(substr($cor, 1, 2)); - $g = hexdec(substr($cor, 3, 2)); - $b = hexdec(substr($cor, 5, 2)); + $r = self::safeHexDec(substr($cor, 1, 2)); + $g = self::safeHexDec(substr($cor, 3, 2)); + $b = self::safeHexDec(substr($cor, 5, 2)); return [3, $r, $g, $b]; } @@ -334,4 +350,14 @@ private function ensureBinaryColorFormat($color) } } + /** + * Converts the given hexString to its decimal representation when all digits are hexadecimal + * + * @param string $hexString The hexadecimal string to convert + * @return float|int The decimal representation of hexString or 0 if not all digits of hexString are hexadecimal + */ + private function safeHexDec($hexString) + { + return ctype_xdigit($hexString) ? hexdec($hexString) : 0; + } } diff --git a/vendor/mpdf/mpdf/src/Config/ConfigVariables.php b/vendor/mpdf/mpdf/src/Config/ConfigVariables.php index f151caac..8eef5a80 100644 --- a/vendor/mpdf/mpdf/src/Config/ConfigVariables.php +++ b/vendor/mpdf/mpdf/src/Config/ConfigVariables.php @@ -3,10 +3,8 @@ namespace Mpdf\Config; use Mpdf\Css\DefaultCss; - use Mpdf\Language\LanguageToFont; use Mpdf\Language\ScriptToLanguage; - use Mpdf\Ucdn; class ConfigVariables @@ -455,6 +453,8 @@ public function __construct() 'tempDir' => __DIR__ . '/../../tmp', + 'cacheCleanupInterval' => 3600, + 'allowAnnotationFiles' => false, 'hyphenationDictionaryFile' => __DIR__ . '/../../data/patterns/dictionary.txt', @@ -512,6 +512,7 @@ public function __construct() 'curlAllowUnsafeSslRequests' => false, 'curlCaCertificate' => '', 'curlTimeout' => 5, + 'curlExecutionTimeout' => null, 'curlProxy' => null, 'curlProxyAuth' => null, 'curlUserAgent' => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1', diff --git a/vendor/mpdf/mpdf/src/CssManager.php b/vendor/mpdf/mpdf/src/CssManager.php index 22a34bdb..1ab5c14b 100644 --- a/vendor/mpdf/mpdf/src/CssManager.php +++ b/vendor/mpdf/mpdf/src/CssManager.php @@ -47,7 +47,12 @@ class CssManager var $cell_border_dominance_T; - public function __construct(Mpdf $mpdf, Cache $cache, SizeConverter $sizeConverter, ColorConverter $colorConverter) + /** + * @var \Mpdf\RemoteContentFetcher + */ + private $remoteContentFetcher; + + public function __construct(Mpdf $mpdf, Cache $cache, SizeConverter $sizeConverter, ColorConverter $colorConverter, RemoteContentFetcher $remoteContentFetcher) { $this->mpdf = $mpdf; $this->cache = $cache; @@ -58,6 +63,7 @@ public function __construct(Mpdf $mpdf, Cache $cache, SizeConverter $sizeConvert $this->cascadeCSS = []; $this->tbCSSlvl = 0; $this->colorConverter = $colorConverter; + $this->remoteContentFetcher = $remoteContentFetcher; } function ReadCSS($html) @@ -2312,13 +2318,13 @@ private function getFileContents($path) $contents = @file_get_contents($localpath); - } elseif (!$contents && !ini_get('allow_url_fopen') && function_exists('curl_init')) { // if not use full URL + } else { // if not use full URL - $ch = curl_init($path); - curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - $contents = curl_exec($ch); - curl_close($ch); + try { + $contents = $this->remoteContentFetcher->getFileContentsByCurl($path); + } catch (\Mpdf\MpdfException $e) { + // Ignore error + } } diff --git a/vendor/mpdf/mpdf/src/Form.php b/vendor/mpdf/mpdf/src/Form.php index 0be548fe..51b88a8e 100644 --- a/vendor/mpdf/mpdf/src/Form.php +++ b/vendor/mpdf/mpdf/src/Form.php @@ -3,9 +3,7 @@ namespace Mpdf; use Mpdf\Strict; - use Mpdf\Color\ColorConverter; - use Mpdf\Writer\BaseWriter; use Mpdf\Writer\FormWriter; diff --git a/vendor/mpdf/mpdf/src/FpdiTrait.php b/vendor/mpdf/mpdf/src/FpdiTrait.php index 7bc1e540..69d0d30c 100644 --- a/vendor/mpdf/mpdf/src/FpdiTrait.php +++ b/vendor/mpdf/mpdf/src/FpdiTrait.php @@ -5,16 +5,19 @@ use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException; use setasign\Fpdi\PdfParser\Filter\AsciiHex; use setasign\Fpdi\PdfParser\Type\PdfArray; -use setasign\Fpdi\PdfParser\Type\PdfIndirectObjectReference; -use setasign\Fpdi\PdfReader\PageBoundaries; +use setasign\Fpdi\PdfParser\Type\PdfDictionary; use setasign\Fpdi\PdfParser\Type\PdfHexString; use setasign\Fpdi\PdfParser\Type\PdfIndirectObject; +use setasign\Fpdi\PdfParser\Type\PdfIndirectObjectReference; +use setasign\Fpdi\PdfParser\Type\PdfName; use setasign\Fpdi\PdfParser\Type\PdfNull; use setasign\Fpdi\PdfParser\Type\PdfNumeric; use setasign\Fpdi\PdfParser\Type\PdfStream; use setasign\Fpdi\PdfParser\Type\PdfString; use setasign\Fpdi\PdfParser\Type\PdfType; use setasign\Fpdi\PdfParser\Type\PdfTypeException; +use setasign\Fpdi\PdfReader\DataStructure\Rectangle; +use setasign\Fpdi\PdfReader\PageBoundaries; /** * @mixin Mpdf @@ -196,49 +199,35 @@ public function getImportedExternalPageLinks($pageNumber) } if ($annotations instanceof PdfArray) { - - $getAttribute = function ($array, $key) { - if (isset($array[$key]->value)) { - return $array[$key]->value; - } - - return ''; - }; + $annotations = PdfType::resolve($annotations, $parser); foreach ($annotations->value as $annotation) { - $annotation = PdfType::resolve($annotation, $parser)->value; - - /* Skip over any annotations that aren't links */ - $type = $getAttribute($annotation, 'Type'); - $subtype = $getAttribute($annotation, 'Subtype'); - if ($type !== 'Annot' || $subtype !== 'Link' || !isset($annotation['A'])) { - continue; - } - - /* Calculate the link positioning */ - $position = $getAttribute($annotation, 'Rect'); + try { + $annotation = PdfType::resolve($annotation, $parser); - if (count($position) !== 4) { - continue; - } + $type = PdfName::ensure(PdfType::resolve(PdfDictionary::get($annotation, 'Type'), $parser)); + $subtype = PdfName::ensure(PdfType::resolve(PdfDictionary::get($annotation, 'Subtype'), $parser)); + $link = PdfDictionary::ensure(PdfType::resolve(PdfDictionary::get($annotation, 'A'), $parser)); - $x1 = $getAttribute($position, 0) / Mpdf::SCALE; - $y1 = $getAttribute($position, 1) / Mpdf::SCALE; - $x2 = $getAttribute($position, 2) / Mpdf::SCALE; - $y2 = $getAttribute($position, 3) / Mpdf::SCALE; - $width = $x2 - $x1; - $height = $y2 - $y1; + /* Skip over annotations that aren't links */ + if ($type->value !== 'Annot' || $subtype->value !== 'Link') { + continue; + } - $link = $annotation['A'] instanceof PdfIndirectObjectReference ? PdfType::resolve($annotation['A'], $parser)->value : $getAttribute($annotation, 'A'); + /* Calculate the link positioning */ + $position = PdfArray::ensure(PdfType::resolve(PdfDictionary::get($annotation, 'Rect'), $parser), 4); + $rect = Rectangle::byPdfArray($position, $parser); + $uri = PdfString::ensure(PdfType::resolve(PdfDictionary::get($link, 'URI'), $parser)); - if (isset($link['URI'])) { $links[] = [ - 'x' => $x1, - 'y' => $y1, - 'width' => $width, - 'height' => $height, - 'url' => $getAttribute($link, 'URI') + 'x' => $rect->getLlx() / Mpdf::SCALE, + 'y' => $rect->getLly() / Mpdf::SCALE, + 'width' => $rect->getWidth() / Mpdf::SCALE, + 'height' => $rect->getHeight() / Mpdf::SCALE, + 'url' => $uri->value ]; + } catch (PdfTypeException $e) { + continue; } } } diff --git a/vendor/mpdf/mpdf/src/Gradient.php b/vendor/mpdf/mpdf/src/Gradient.php index 8c42f2ac..95062e3c 100644 --- a/vendor/mpdf/mpdf/src/Gradient.php +++ b/vendor/mpdf/mpdf/src/Gradient.php @@ -51,10 +51,13 @@ public function CoonsPatchMesh($x, $y, $w, $h, $patch_array = [], $x_min = 0, $x $bpcd = 65535; //16 BitsPerCoordinate $trans = false; $this->mpdf->gradients[$n]['stream'] = ''; + for ($i = 0; $i < count($patch_array); $i++) { $this->mpdf->gradients[$n]['stream'].=chr($patch_array[$i]['f']); //start with the edge flag as 8 bit + for ($j = 0; $j < count($patch_array[$i]['points']); $j++) { - //each point as 16 bit + + // each point as 16 bit if (($j % 2) == 1) { // Y coordinate (adjusted as input is From top left) $patch_array[$i]['points'][$j] = (($patch_array[$i]['points'][$j] - $y_min) / ($y_max - $y_min)) * $bpcd; $patch_array[$i]['points'][$j] = $bpcd - $patch_array[$i]['points'][$j]; @@ -67,23 +70,25 @@ public function CoonsPatchMesh($x, $y, $w, $h, $patch_array = [], $x_min = 0, $x if ($patch_array[$i]['points'][$j] > $bpcd) { $patch_array[$i]['points'][$j] = $bpcd; } - $this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j] / 256)); - $this->mpdf->gradients[$n]['stream'].=chr(floor($patch_array[$i]['points'][$j] % 256)); + + $this->mpdf->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] / 256)); + $this->mpdf->gradients[$n]['stream'] .= chr(floor(round($patch_array[$i]['points'][$j]) % 256)); } + for ($j = 0; $j < count($patch_array[$i]['colors']); $j++) { //each color component as 8 bit if ($colspace === 'RGB') { - $this->mpdf->gradients[$n]['stream'].= $patch_array[$i]['colors'][$j][1]; - $this->mpdf->gradients[$n]['stream'].= $patch_array[$i]['colors'][$j][2]; - $this->mpdf->gradients[$n]['stream'].= $patch_array[$i]['colors'][$j][3]; + $this->mpdf->gradients[$n]['stream'] .= $patch_array[$i]['colors'][$j][1]; + $this->mpdf->gradients[$n]['stream'] .= $patch_array[$i]['colors'][$j][2]; + $this->mpdf->gradients[$n]['stream'] .= $patch_array[$i]['colors'][$j][3]; if (isset($patch_array[$i]['colors'][$j][4]) && ord($patch_array[$i]['colors'][$j][4]) < 100) { $trans = true; } } elseif ($colspace === 'CMYK') { - $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][1]) * 2.55); - $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][2]) * 2.55); - $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][3]) * 2.55); - $this->mpdf->gradients[$n]['stream'].=chr(ord($patch_array[$i]['colors'][$j][4]) * 2.55); + $this->mpdf->gradients[$n]['stream'] .= chr(ord($patch_array[$i]['colors'][$j][1]) * 2.55); + $this->mpdf->gradients[$n]['stream'] .= chr(ord($patch_array[$i]['colors'][$j][2]) * 2.55); + $this->mpdf->gradients[$n]['stream'] .= chr(ord($patch_array[$i]['colors'][$j][3]) * 2.55); + $this->mpdf->gradients[$n]['stream'] .= chr(ord($patch_array[$i]['colors'][$j][4]) * 2.55); if (isset($patch_array[$i]['colors'][$j][5]) && ord($patch_array[$i]['colors'][$j][5]) < 100) { $trans = true; } @@ -95,34 +100,43 @@ public function CoonsPatchMesh($x, $y, $w, $h, $patch_array = [], $x_min = 0, $x } } } + // TRANSPARENCY if ($trans) { $this->mpdf->gradients[$n]['stream_trans'] = ''; + for ($i = 0; $i < count($patch_array); $i++) { - $this->mpdf->gradients[$n]['stream_trans'].=chr($patch_array[$i]['f']); + + $this->mpdf->gradients[$n]['stream_trans'] .= chr($patch_array[$i]['f']); + for ($j = 0; $j < count($patch_array[$i]['points']); $j++) { - //each point as 16 bit - $this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j] / 256)); - $this->mpdf->gradients[$n]['stream_trans'].=chr(floor($patch_array[$i]['points'][$j] % 256)); + // each point as 16 bit + $this->mpdf->gradients[$n]['stream_trans'] .= chr(floor($patch_array[$i]['points'][$j] / 256)); + $this->mpdf->gradients[$n]['stream_trans'] .= chr(floor(round($patch_array[$i]['points'][$j]) % 256)); } + for ($j = 0; $j < count($patch_array[$i]['colors']); $j++) { - //each color component as 8 bit // OPACITY + // each color component as 8 bit // OPACITY if ($colspace === 'RGB') { - $this->mpdf->gradients[$n]['stream_trans'].=chr((int) (ord($patch_array[$i]['colors'][$j][4]) * 2.55)); + $this->mpdf->gradients[$n]['stream_trans'] .= chr((int) (ord($patch_array[$i]['colors'][$j][4]) * 2.55)); } elseif ($colspace === 'CMYK') { - $this->mpdf->gradients[$n]['stream_trans'].=chr((int) (ord($patch_array[$i]['colors'][$j][5]) * 2.55)); + $this->mpdf->gradients[$n]['stream_trans'] .= chr((int) (ord($patch_array[$i]['colors'][$j][5]) * 2.55)); } elseif ($colspace === 'Gray') { - $this->mpdf->gradients[$n]['stream_trans'].=chr((int) (ord($patch_array[$i]['colors'][$j][3]) * 2.55)); + $this->mpdf->gradients[$n]['stream_trans'] .= chr((int) (ord($patch_array[$i]['colors'][$j][3]) * 2.55)); } } } + $this->mpdf->gradients[$n]['trans'] = true; $s .= ' /TGS' . $n . ' gs '; } - //paint the gradient + + // paint the gradient $s .= '/Sh' . $n . ' sh' . "\n"; - //restore previous Graphic State + + // restore previous Graphic State $s .= 'Q' . "\n"; + if ($return) { return $s; } @@ -140,15 +154,16 @@ public function CoonsPatchMesh($x, $y, $w, $h, $patch_array = [], $x_min = 0, $x // $stops = array('col'=>$col [, 'opacity'=>0-1] [, 'offset'=>0-1]) public function Gradient($x, $y, $w, $h, $type, $stops = [], $colorspace = 'RGB', $coords = '', $extend = '', $return = false, $is_mask = false) { - if (stripos($type, 'L') === 0) { + if ($type && stripos($type, 'L') === 0) { $type = self::TYPE_LINEAR; - } elseif (stripos($type, 'R') === 0) { + } elseif ($type && stripos($type, 'R') === 0) { $type = self::TYPE_RADIAL; } if ($colorspace !== 'CMYK' && $colorspace !== 'Gray') { $colorspace = 'RGB'; } + $bboxw = $w; $bboxh = $h; $usex = $x; @@ -159,12 +174,14 @@ public function Gradient($x, $y, $w, $h, $type, $stops = [], $colorspace = 'RGB' if ($type < 1) { $type = self::TYPE_LINEAR; } + if ($coords[0] !== false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $coords[0], $m)) { $tmp = $this->sizeConverter->convert($m[1], $this->mpdf->w, $this->mpdf->FontSize, false); if ($tmp) { $coords[0] = $tmp / $w; } } + if ($coords[1] !== false && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $coords[1], $m)) { $tmp = $this->sizeConverter->convert($m[1], $this->mpdf->w, $this->mpdf->FontSize, false); if ($tmp) { @@ -494,7 +511,7 @@ public function Gradient($x, $y, $w, $h, $type, $stops = [], $colorspace = 'RGB' for ($i = 0; $i < count($stops); $i++) { if (isset($stops[$i]['offset']) && preg_match('/([0-9.]+(px|em|ex|pc|pt|cm|mm|in))/i', $stops[$i]['offset'], $m)) { $tmp = $this->sizeConverter->convert($m[1], $this->mpdf->w, $this->mpdf->FontSize, false); - $stops[$i]['offset'] = $tmp / $axis_length; + $stops[$i]['offset'] = $axis_length ? $tmp / $axis_length : 0; } } diff --git a/vendor/mpdf/mpdf/src/Image/ImageProcessor.php b/vendor/mpdf/mpdf/src/Image/ImageProcessor.php index 60a4304d..da587c25 100644 --- a/vendor/mpdf/mpdf/src/Image/ImageProcessor.php +++ b/vendor/mpdf/mpdf/src/Image/ImageProcessor.php @@ -3,29 +3,18 @@ namespace Mpdf\Image; use Mpdf\Cache; - use Mpdf\Color\ColorConverter; use Mpdf\Color\ColorModeConverter; - use Mpdf\CssManager; - use Mpdf\File\StreamWrapperChecker; - use Mpdf\Gif\Gif; - use Mpdf\Language\LanguageToFontInterface; use Mpdf\Language\ScriptToLanguageInterface; - use Mpdf\Log\Context as LogContext; - use Mpdf\Mpdf; - use Mpdf\Otl; - use Mpdf\RemoteContentFetcher; - use Mpdf\SizeConverter; - use Psr\Log\LoggerInterface; class ImageProcessor implements \Psr\Log\LoggerAwareInterface @@ -155,11 +144,15 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s /** * Prevents insecure PHP object injection through phar:// wrapper * @see https://github.com/mpdf/mpdf/issues/949 + * @see https://github.com/mpdf/mpdf/issues/1381 */ $wrapperChecker = new StreamWrapperChecker($this->mpdf); if ($wrapperChecker->hasBlacklistedStreamWrapper($file)) { return $this->imageError($file, $firsttime, 'File contains an invalid stream. Only ' . implode(', ', $wrapperChecker->getWhitelistedStreamWrappers()) . ' streams are allowed.'); } + if ($wrapperChecker->hasBlacklistedStreamWrapper($orig_srcpath)) { + return $this->imageError($orig_srcpath, $firsttime, 'File contains an invalid stream. Only ' . implode(', ', $wrapperChecker->getWhitelistedStreamWrappers()) . ' streams are allowed.'); + } // mPDF 6 // firsttime i.e. whether to add to this->images - use false when calling iteratively @@ -176,7 +169,7 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s $file = md5($data); } - if (preg_match('/data:image\/(gif|jpe?g|png);base64,(.*)/', $file, $v)) { + if (preg_match('/data:image\/(gif|jpe?g|png|webp);base64,(.*)/', $file, $v)) { $type = $v[1]; $data = base64_decode($v[2]); $file = md5($data); @@ -231,7 +224,7 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s $type = $this->guesser->guess($data); } - if (!$data && $check = @fopen($file, 'rb')) { + if ($file && !$data && $check = @fopen($file, 'rb')) { fclose($check); $this->logger->debug(sprintf('Fetching (file_get_contents) content of file "%s" with non-local basepath', $file), ['context' => LogContext::REMOTE_CONTENT]); $data = file_get_contents($file); @@ -286,6 +279,31 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s return $info; } + if ($type === 'webp') { // Convert webp images to JPG and treat them as such + + $im = @imagecreatefromstring($data); + + if (!function_exists('imagewebp') || false === $im) { + return $this->imageError($file, $firsttime, 'Missing GD support for WEBP images.'); + } + + $tempfile = $this->cache->tempFilename('_tempImgPNG' . md5($file) . random_int(1, 10000) . '.jpg'); + $checkfile = $this->cache->tempFilename('_tempImgPNG' . md5($file) . random_int(1, 10000) . '.jpg'); + $check = @imagewebp($im, $checkfile); + + if (!$check) { + return $this->imageError($file, $firsttime, 'Error creating temporary file (' . $tempfile . ') when using GD library to parse WEBP image'); + } + + @imagejpeg($im, $tempfile); + $data = file_get_contents($tempfile); + imagedestroy($im); + unlink($tempfile); + unlink($checkfile); + $type = 'jpeg'; + + } + // JPEG if ($type === 'jpeg' || $type === 'jpg') { @@ -327,7 +345,7 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s imageinterlace($im, false); $check = @imagepng($im, $tempfile); if (!$check) { - return $this->imageError($file, $firsttime, 'Error creating temporary file (' . $tempfile . ') whilst using GD library to parse JPG(CMYK) image'); + return $this->imageError($file, $firsttime, 'Error creating temporary file (' . $tempfile . ') when using GD library to parse JPG(CMYK) image'); } $info = $this->getImage($tempfile, false); if (!$info) { @@ -844,10 +862,13 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s } else { return $this->imageError($file, $firsttime, 'Error parsing PNG image data'); } + } while ($n); + if (!$pngdata) { return $this->imageError($file, $firsttime, 'Error parsing PNG image data - no IDAT data found'); } + if ($colspace === 'Indexed' && empty($pal)) { return $this->imageError($file, $firsttime, 'Error parsing PNG image data - missing colour palette'); } @@ -877,11 +898,9 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s } elseif ($type === 'gif') { // GIF - if (function_exists('gd_info')) { - $gd = gd_info(); - } else { - $gd = []; - } + $gd = function_exists('gd_info') + ? gd_info() + : []; if (isset($gd['GIF Read Support']) && $gd['GIF Read Support']) { @@ -895,7 +914,7 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s ob_start(); $check = @imagepng($im); if (!$check) { - return $this->imageError($file, $firsttime, 'Error creating temporary image object whilst using GD library to parse GIF image'); + return $this->imageError($file, $firsttime, 'Error creating temporary image object when using GD library to parse GIF image'); } $this->mpdf->imageVars['tempImage'] = ob_get_contents(); $tempimglnk = 'var:tempImage'; @@ -908,7 +927,7 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s } else { $check = @imagepng($im, $tempfile); if (!$check) { - return $this->imageError($file, $firsttime, 'Error creating temporary file (' . $tempfile . ') whilst using GD library to parse GIF image'); + return $this->imageError($file, $firsttime, 'Error creating temporary file (' . $tempfile . ') when using GD library to parse GIF image'); } $info = $this->getImage($tempfile, false); if (!$info) { @@ -1031,11 +1050,9 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s } else { // UNKNOWN TYPE - try GD imagecreatefromstring - if (function_exists('gd_info')) { - $gd = gd_info(); - } else { - $gd = []; - } + $gd = function_exists('gd_info') + ? gd_info() + : []; if (isset($gd['PNG Support']) && $gd['PNG Support']) { @@ -1054,7 +1071,7 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s $check = @imagepng($im, $tempfile); if (!$check) { - return $this->imageError($file, $firsttime, 'Error creating temporary file (' . $tempfile . ') whilst using GD library to parse unknown image type'); + return $this->imageError($file, $firsttime, 'Error creating temporary file (' . $tempfile . ') when using GD library to parse unknown image type'); } $info = $this->getImage($tempfile, false); @@ -1082,6 +1099,10 @@ public function getImage(&$file, $firsttime = true, $allowvector = true, $orig_s private function convertImage(&$data, $colspace, $targetcs, $w, $h, $dpi, $mask, $gamma_correction = false, $pngcolortype = false) { + if (!function_exists('gd_info')) { + return $this->imageError($file, $firsttime, 'GD library needed to parse image files'); + } + if ($this->mpdf->PDFA || $this->mpdf->PDFX) { $mask = false; } diff --git a/vendor/mpdf/mpdf/src/Image/ImageTypeGuesser.php b/vendor/mpdf/mpdf/src/Image/ImageTypeGuesser.php index d2e63635..bdd3fa26 100644 --- a/vendor/mpdf/mpdf/src/Image/ImageTypeGuesser.php +++ b/vendor/mpdf/mpdf/src/Image/ImageTypeGuesser.php @@ -16,6 +16,10 @@ public function guess($data) return 'jpeg'; } + if (in_array(substr($data, 0, 4), ['RIFF'], true)) { + return 'webp'; + } + if (in_array(substr($data, 0, 6), ['GIF87a', 'GIF89a'], true)) { return 'gif'; } diff --git a/vendor/mpdf/mpdf/src/Image/Svg.php b/vendor/mpdf/mpdf/src/Image/Svg.php index dfcc6855..9bc0f607 100644 --- a/vendor/mpdf/mpdf/src/Image/Svg.php +++ b/vendor/mpdf/mpdf/src/Image/Svg.php @@ -606,17 +606,17 @@ function svgGradient($gradient_info, $attribs, $element) $y2 = 0; } // mPDF 6 - if (stristr($x1, '%') !== false) { - $x1 = ($x1 + 0) / 100; + if (strpos($x1, '%') !== false) { + $x1 = (stristr($x1, '%', true) + 0) / 100; } - if (stristr($x2, '%') !== false) { - $x2 = ($x2 + 0) / 100; + if (strpos($x2, '%') !== false) { + $x2 = (stristr($x2, '%', true) + 0) / 100; } - if (stristr($y1, '%') !== false) { - $y1 = ($y1 + 0) / 100; + if (strpos($y1, '%') !== false) { + $y1 = (stristr($y1, '%', true) + 0) / 100; } - if (stristr($y2, '%') !== false) { - $y2 = ($y2 + 0) / 100; + if (strpos($y2, '%') !== false) { + $y2 = (stristr($y2, '%', true) + 0) / 100; } // mPDF 5.0.042 @@ -861,23 +861,23 @@ function svgGradient($gradient_info, $attribs, $element) $y1 = $y0; } - if (stristr($x1, '%') !== false) { - $x1 = ($x1 + 0) / 100; + if (strpos($x1, '%') !== false) { + $x1 = (stristr($x1, '%', true) + 0) / 100; } - if (stristr($x0, '%') !== false) { - $x0 = ($x0 + 0) / 100; + if (strpos($x0, '%') !== false) { + $x0 = (stristr($x0, '%', true) + 0) / 100; } - if (stristr($y1, '%') !== false) { - $y1 = ($y1 + 0) / 100; + if (strpos($y1, '%') !== false) { + $y1 = (stristr($y1, '%', true) + 0) / 100; } - if (stristr($y0, '%') !== false) { - $y0 = ($y0 + 0) / 100; + if (strpos($y0, '%') !== false) { + $y0 = (stristr($y0, '%', true) + 0) / 100; } - if (stristr($rx, '%') !== false) { - $rx = ($rx + 0) / 100; + if (strpos($rx, '%') !== false) { + $rx = (stristr($rx, '%', true) + 0) / 100; } - if (stristr($ry, '%') !== false) { - $ry = ($ry + 0) / 100; + if (strpos($ry, '%') !== false) { + $ry = (stristr($ry, '%', true) + 0) / 100; } $bboxw = $w; @@ -1463,22 +1463,35 @@ function svgStyle($critere_style, $attribs, $element) $path_style .= sprintf('%.2F M ', $critere_style['stroke-miterlimit']); } } + if (isset($critere_style['stroke-dasharray'])) { + $off = 0; $d = preg_split('/(,\s?|\s)/', $critere_style['stroke-dasharray']); + if (count($d) == 1 && $d[0] == 0) { $path_style .= '[] 0 d '; } else { + if (count($d) % 2 == 1) { $d = array_merge($d, $d); } // 5, 3, 1 => 5,3,1,5,3,1 OR 3 => 3,3 + $arr = ''; - for ($i = 0; $i < count($d); $i+=2) { + + for ($i = 0; $i < count($d); $i += 2) { + + if ($d[$i] === 'none') { + continue; + } + $arr .= sprintf('%.3F %.3F ', $d[$i] * $this->kp, $d[$i + 1] * $this->kp); } + if (isset($critere_style['stroke-dashoffset'])) { $off = $critere_style['stroke-dashoffset'] + 0; } + $path_style .= sprintf('[%s] %.3F d ', $arr, $off * $this->kp); } } @@ -1570,36 +1583,47 @@ function svgPath($command, $arguments) } - $ile_argumentow = count($a); + $argumentCount = count($a); // each command may have different needs for arguments [1 to 8] switch (strtolower($command)) { + case 'm': // move - for ($i = 0; $i < $ile_argumentow; $i+=2) { + + for ($i = 0; $i < $argumentCount; $i += 2) { + $x = $a[$i]; $y = $a[$i + 1]; + if ($relative) { + $pdfx = ($this->xbase + $x); $pdfy = ($this->ybase - $y); $this->xbase += $x; $this->ybase += -$y; + } else { + $pdfx = $x; $pdfy = -$y; $this->xbase = $x; $this->ybase = -$y; } + $pdf_pt = $this->svg_overflow($pdfx, $pdfy); + $minl = min($minl, $pdf_pt['x']); $maxr = max($maxr, $pdf_pt['x']); $mint = min($mint, -$pdf_pt['y']); $maxb = max($maxb, -$pdf_pt['y']); + if ($i == 0) { $path_cmd .= sprintf('%.3F %.3F m ', $pdf_pt['x'] * $this->kp, $pdf_pt['y'] * $this->kp); } else { $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x'] * $this->kp, $pdf_pt['y'] * $this->kp); } + // mPDF 4.4.003 Save start points of subpath if ($this->subPathInit) { $this->spxstart = $this->xbase; @@ -1607,46 +1631,68 @@ function svgPath($command, $arguments) $this->subPathInit = false; } } + break; + case 'l': // a simple line - for ($i = 0; $i < $ile_argumentow; $i+=2) { + + for ($i = 0; $i < $argumentCount; $i+=2) { + $x = ($a[$i]); $y = ($a[$i + 1]); + if ($relative) { + $pdfx = ($this->xbase + $x); $pdfy = ($this->ybase - $y); $this->xbase += $x; $this->ybase += -$y; + } else { + $pdfx = $x; $pdfy = -$y; $this->xbase = $x; $this->ybase = -$y; + } + $pdf_pt = $this->svg_overflow($pdfx, $pdfy); + $minl = min($minl, $pdf_pt['x']); $maxr = max($maxr, $pdf_pt['x']); $mint = min($mint, -$pdf_pt['y']); $maxb = max($maxb, -$pdf_pt['y']); + $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x'] * $this->kp, $pdf_pt['y'] * $this->kp); } + break; + case 'h': // a very simple horizontal line - for ($i = 0; $i < $ile_argumentow; $i++) { + + for ($i = 0; $i < $argumentCount; $i++) { + $x = ($a[$i]); + if ($relative) { + $y = 0; $pdfx = ($this->xbase + $x); $pdfy = ($this->ybase - $y); $this->xbase += $x; $this->ybase += -$y; + } else { + $y = -$this->ybase; $pdfx = $x; $pdfy = -$y; $this->xbase = $x; $this->ybase = -$y; + } + $pdf_pt = $this->svg_overflow($pdfx, $pdfy); $minl = min($minl, $pdf_pt['x']); $maxr = max($maxr, $pdf_pt['x']); @@ -1654,44 +1700,65 @@ function svgPath($command, $arguments) $maxb = max($maxb, -$pdf_pt['y']); $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x'] * $this->kp, $pdf_pt['y'] * $this->kp); } + break; + case 'v': // the simplest line, vertical - for ($i = 0; $i < $ile_argumentow; $i++) { + + for ($i = 0; $i < $argumentCount; $i++) { + $y = ($a[$i]); + if ($relative) { + $x = 0; $pdfx = ($this->xbase + $x); $pdfy = ($this->ybase - $y); $this->xbase += $x; $this->ybase += -$y; + } else { + $x = $this->xbase; $pdfx = $x; $pdfy = -$y; $this->xbase = $x; $this->ybase = -$y; + } + $pdf_pt = $this->svg_overflow($pdfx, $pdfy); $minl = min($minl, $pdf_pt['x']); $maxr = max($maxr, $pdf_pt['x']); $mint = min($mint, -$pdf_pt['y']); $maxb = max($maxb, -$pdf_pt['y']); $path_cmd .= sprintf('%.3F %.3F l ', $pdf_pt['x'] * $this->kp, $pdf_pt['y'] * $this->kp); + } + break; + case 's': // bezier with first vertex equal first control + // mPDF 4.4.003 + if (!($this->lastcommand == 'C' || $this->lastcommand == 'c' || $this->lastcommand == 'S' || $this->lastcommand == 's')) { $this->lastcontrolpoints = [0, 0]; } - for ($i = 0; $i < $ile_argumentow; $i += 4) { + + for ($i = 0; $i < $argumentCount; $i += 4) { + $x1 = $this->lastcontrolpoints[0]; $y1 = $this->lastcontrolpoints[1]; + $x2 = ($a[$i]); $y2 = ($a[$i + 1]); + $x = ($a[$i + 2]); $y = ($a[$i + 3]); + if ($relative) { + $pdfx1 = ($this->xbase + $x1); $pdfy1 = ($this->ybase - $y1); $pdfx2 = ($this->xbase + $x2); @@ -1700,7 +1767,9 @@ function svgPath($command, $arguments) $pdfy = ($this->ybase - $y); $this->xbase += $x; $this->ybase += -$y; + } else { + $pdfx1 = $this->xbase + $x1; $pdfy1 = $this->ybase - $y1; $pdfx2 = $x2; @@ -1709,7 +1778,9 @@ function svgPath($command, $arguments) $pdfy = -$y; $this->xbase = $x; $this->ybase = -$y; + } + $this->lastcontrolpoints = [($pdfx - $pdfx2), -($pdfy - $pdfy2)]; // mPDF 4.4.003 always relative $pdf_pt = $this->svg_overflow($pdfx, $pdfy); @@ -1727,9 +1798,13 @@ function svgPath($command, $arguments) $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1 * $this->kp, $pdfy1 * $this->kp, $pdfx2 * $this->kp, $pdfy2 * $this->kp, $pdfx * $this->kp, $pdfy * $this->kp); } } + break; + case 'c': // bezier with second vertex equal second control - for ($i = 0; $i < $ile_argumentow; $i += 6) { + + for ($i = 0; $i < $argumentCount; $i += 6) { + $x1 = ($a[$i]); $y1 = ($a[$i + 1]); $x2 = ($a[$i + 2]); @@ -1737,8 +1812,8 @@ function svgPath($command, $arguments) $x = ($a[$i + 4]); $y = ($a[$i + 5]); - if ($relative) { + $pdfx1 = ($this->xbase + $x1); $pdfy1 = ($this->ybase - $y1); $pdfx2 = ($this->xbase + $x2); @@ -1747,7 +1822,9 @@ function svgPath($command, $arguments) $pdfy = ($this->ybase - $y); $this->xbase += $x; $this->ybase += -$y; + } else { + $pdfx1 = $x1; $pdfy1 = -$y1; $pdfx2 = $x2; @@ -1756,7 +1833,9 @@ function svgPath($command, $arguments) $pdfy = -$y; $this->xbase = $x; $this->ybase = -$y; + } + $this->lastcontrolpoints = [($pdfx - $pdfx2), -($pdfy - $pdfy2)]; // mPDF 4.4.003 always relative // $pdf_pt2 = $this->svg_overflow($pdfx2,$pdfy2); // $pdf_pt1 = $this->svg_overflow($pdfx1,$pdfy1); @@ -1775,15 +1854,20 @@ function svgPath($command, $arguments) $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1 * $this->kp, $pdfy1 * $this->kp, $pdfx2 * $this->kp, $pdfy2 * $this->kp, $pdfx * $this->kp, $pdfy * $this->kp); } } + break; case 'q': // bezier quadratic avec point de control - for ($i = 0; $i < $ile_argumentow; $i += 4) { + + for ($i = 0; $i < $argumentCount; $i += 4) { + $x1 = ($a[$i]); $y1 = ($a[$i + 1]); $x = ($a[$i + 2]); $y = ($a[$i + 3]); + if ($relative) { + $pdfx = ($this->xbase + $x); $pdfy = ($this->ybase - $y); @@ -1795,7 +1879,9 @@ function svgPath($command, $arguments) $this->xbase += $x; $this->ybase += -$y; + } else { + $pdfx = $x; $pdfy = -$y; @@ -1811,7 +1897,9 @@ function svgPath($command, $arguments) $this->xbase = $x; $this->ybase = -$y; + } + $this->lastcontrolpoints = [($pdfx - $pdfx2), -($pdfy - $pdfy2)]; // mPDF 4.4.003 always relative $pdf_pt = $this->svg_overflow($pdfx, $pdfy); @@ -1829,12 +1917,17 @@ function svgPath($command, $arguments) $path_cmd .= sprintf('%.3F %.3F %.3F %.3F %.3F %.3F c ', $pdfx1 * $this->kp, $pdfy1 * $this->kp, $pdfx2 * $this->kp, $pdfy2 * $this->kp, $pdfx * $this->kp, $pdfy * $this->kp); } } + break; + case 't': // bezier quadratic avec point de control simetrique a lancien point de control + if (!($this->lastcommand == 'Q' || $this->lastcommand == 'q' || $this->lastcommand == 'T' || $this->lastcommand == 't')) { $this->lastcontrolpoints = [0, 0]; } - for ($i = 0; $i < $ile_argumentow; $i += 2) { + + for ($i = 0; $i < $argumentCount; $i += 2) { + $x = ($a[$i]); $y = ($a[$i + 1]); @@ -1853,12 +1946,15 @@ function svgPath($command, $arguments) $this->xbase += $x; $this->ybase += -$y; + } else { + $pdfx = $x; $pdfy = -$y; $pdfx1 = ($this->xbase + ($x1)); $pdfy1 = ($this->ybase - ($y1)); + // mPDF 4.4.003 $pdfx2 = $pdfx1 + 1 / 3 * ($x - $this->xbase); $pdfy2 = $pdfy1 + 1 / 3 * (-$y - $this->ybase); @@ -1880,54 +1976,73 @@ function svgPath($command, $arguments) } break; + case 'a': // Elliptical arc - for ($i = 0; $i < $ile_argumentow; $i += 7) { - $rx = ($a[$i]); - $ry = ($a[$i + 1]); - $angle = ($a[$i + 2]); //x-axis-rotation - $largeArcFlag = ($a[$i + 3]); - $sweepFlag = ($a[$i + 4]); - $x2 = ($a[$i + 5]); - $y2 = ($a[$i + 6]); + + for ($i = 0; $i < $argumentCount; $i += 7) { + + $rx = isset($a[$i]) ? $a[$i] : 0; + $ry = isset($a[$i + 1]) ? $a[$i + 1] : 0; + + // x-axis-rotation + $angle = isset($a[$i + 2]) ? $a[$i + 2] : 0; + + $largeArcFlag = isset($a[$i + 3]) ? $a[$i + 3] : 0; + $sweepFlag = isset($a[$i + 4]) ? $a[$i + 4] : 0; + + $x2 = isset($a[$i + 5]) ? $a[$i + 5] : 0; + $y2 = isset($a[$i + 6]) ? $a[$i + 6] : 0; + $x1 = $this->xbase; $y1 = -$this->ybase; + if ($relative) { $x2 = $this->xbase + $x2; $y2 = -$this->ybase + $y2; - $this->xbase += ($a[$i + 5]); - $this->ybase += -($a[$i + 6]); + $this->xbase += isset($a[$i + 5]) ? $a[$i + 5] : 0; + $this->ybase += isset($a[$i + 6]) ? -$a[$i + 6] : 0; } else { $this->xbase = $x2; $this->ybase = -$y2; } + list($pcmd, $bounds) = $this->Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag); + $minl = min($minl, $x2, min($bounds[0])); $maxr = max($maxr, $x2, max($bounds[0])); $mint = min($mint, $y2, min($bounds[1])); $maxb = max($maxb, $y2, max($bounds[1])); + $path_cmd .= $pcmd; + } + break; + case 'z': + $path_cmd .= 'h '; + $this->subPathInit = true; $newsubpath = true; $this->xbase = $this->spxstart; $this->ybase = $this->spystart; - break; - default: + break; } if (!$newsubpath) { $this->subPathInit = false; } + $this->lastcommand = $command; + // mPDF 5.0.039 $this->pathBBox[0] = $minl; $this->pathBBox[1] = $mint; $this->pathBBox[2] = $maxr - $this->pathBBox[0]; $this->pathBBox[3] = $maxb - $this->pathBBox[1]; + return $path_cmd; } @@ -1935,6 +2050,7 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) { $bounds = [0 => [$x1, $x2], 1 => [$y1, $y2]]; + // 1. Treat out-of-range parameters as described in // http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes // If the endpoints (x1, y1) and (x2, y2) are identical, then this @@ -1943,8 +2059,7 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) return ['', $bounds]; // mPD 5.0.040 } - -// If rX = 0 or rY = 0 then this arc is treated as a straight line + // If rX = 0 or rY = 0 then this arc is treated as a straight line // segment (a "lineto") joining the endpoints. if ($rx == 0.0 || $ry == 0.0) { // return array(Lineto(x2, y2), $bounds); @@ -1955,6 +2070,7 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) if ($rx < 0.0) { $rx = -$rx; } + if ($ry < 0.0) { $ry = -$ry; } @@ -1967,10 +2083,10 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) $x1dash = $cosPhi * ($x1 - $x2) / 2.0 + $sinPhi * ($y1 - $y2) / 2.0; $y1dash = -$sinPhi * ($x1 - $x2) / 2.0 + $cosPhi * ($y1 - $y2) / 2.0; - $numerator = $rx * $rx * $ry * $ry - $rx * $rx * $y1dash * $y1dash - $ry * $ry * $x1dash * $x1dash; if ($numerator < 0.0) { + // If rX , rY and are such that there is no solution (basically, // the ellipse is not big enough to reach from (x1, y1) to (x2, // y2)) then the ellipse is scaled up uniformly until there is @@ -1982,6 +2098,7 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) $rx *= $s; $ry *= $s; $root = 0.0; + } else { $root = ($largeArcFlag == $sweepFlag ? -1.0 : 1.0) * sqrt($numerator / ($rx * $rx * $y1dash * $y1dash + $ry * $ry * $x1dash * $x1dash)); } @@ -1995,6 +2112,7 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) $theta1 = $this->CalcVectorAngle(1.0, 0.0, ($x1dash - $cxdash) / $rx, ($y1dash - $cydash) / $ry); $dtheta = $this->CalcVectorAngle(($x1dash - $cxdash) / $rx, ($y1dash - $cydash) / $ry, (-$x1dash - $cxdash) / $rx, (-$y1dash - $cydash) / $ry); + if (!$sweepFlag && $dtheta > 0) { $dtheta -= 2.0 * M_PI; } elseif ($sweepFlag && $dtheta < 0) { @@ -2006,10 +2124,14 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) $delta = $dtheta / $segments; $t = 8.0 / 3.0 * sin($delta / 4.0) * sin($delta / 4.0) / sin($delta / 2.0); $coords = []; + for ($i = 0; $i < $segments; $i++) { + $cosTheta1 = cos($theta1); $sinTheta1 = sin($theta1); + $theta2 = $theta1 + $delta; + $cosTheta2 = cos($theta2); $sinTheta2 = sin($theta2); @@ -2032,8 +2154,11 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) $x1 = $xe; $y1 = $ye; } + $path = ' '; + foreach ($coords as $c) { + $cpx1 = $c[0]; $cpy1 = $c[1]; $cpx2 = $c[2]; @@ -2046,16 +2171,19 @@ function Arcto($x1, $y1, $x2, $y2, $rx, $ry, $angle, $largeArcFlag, $sweepFlag) $bounds[0][] = $c[4]; $bounds[1][] = $c[5]; } - return [$path, $bounds]; // mPD 5.0.040 + + return [$path, $bounds]; // mPDF 5.0.040 } function CalcVectorAngle($ux, $uy, $vx, $vy) { $ta = atan2($uy, $ux); $tb = atan2($vy, $vx); + if ($tb >= $ta) { return ($tb - $ta); } + return (6.28318530718 - ($ta - $tb)); } @@ -2073,10 +2201,13 @@ function ConvertSVGSizePixels($size = 5, $maxsize = 'x') } elseif ($maxsize == 'x') { $maxsize = $this->svg_info['w']; } + $maxsize *= (25.4 / $this->mpdf->dpi); // convert pixels to mm $fontsize = $this->mpdf->FontSize / $this->kf; - //Return as pixels + + // Return as pixels $size = $this->sizeConverter->convert($size, $maxsize, $fontsize, false) * 1 / (25.4 / $this->mpdf->dpi); + return $size; } @@ -2087,16 +2218,15 @@ function ConvertSVGSizePts($size = 5) // For text $maxsize = Fontsize // Setting e.g. margin % will use maxsize (pagewidth) and em will use fontsize $maxsize = $this->mpdf->FontSize; - //Return as pts + + // Return as pts $size = $this->sizeConverter->convert($size, $maxsize, false, true) * 72 / 25.4; + return $size; } - // - // fonction retracant les function svgRect($arguments) { - if ($arguments['h'] == 0 || $arguments['w'] == 0) { return ''; } @@ -2108,16 +2238,20 @@ function svgRect($arguments) $rx = $this->ConvertSVGSizePixels($arguments['rx'], 'x'); // mPDF 4.4.003 $ry = $this->ConvertSVGSizePixels($arguments['ry'], 'y'); // mPDF 4.4.003 + // mPDF 4.4.003 if ($rx > $w / 2) { $rx = $w / 2; - } // mPDF 4.4.003 + } + + // mPDF 4.4.003 if ($ry > $h / 2) { $ry = $h / 2; - } // mPDF 4.4.003 + } if ($rx > 0 and $ry == 0) { $ry = $rx; } + if ($ry > 0 and $rx == 0) { $rx = $ry; } @@ -2151,10 +2285,11 @@ function svgRect($arguments) return $path_cmd; } - // - // fonction retracant les et - // le cercle est tracé grave a 4 bezier cubic, les poitn de controles - // sont deduis grace a la constante kappa * rayon + /** + * fonction retracant les et + * le cercle est tracé grave a 4 bezier cubic, les poitn de controles + * sont deduis grace a la constante kappa * rayon + */ function svgEllipse($arguments) { if ($arguments['rx'] == 0 || $arguments['ry'] == 0) { @@ -2190,8 +2325,6 @@ function svgEllipse($arguments) return $path_cmd; } - // - // fonction retracant les et les function svgPolyline($arguments, $ispolyline = true) { if ($ispolyline) { @@ -2204,7 +2337,9 @@ function svgPolyline($arguments, $ispolyline = true) $xbase = $this->ConvertSVGSizePixels($arguments[0], 'x'); $ybase = - $this->ConvertSVGSizePixels($arguments[1], 'y'); } + $path_cmd = sprintf('%.3F %.3F m ', $xbase * $this->kp, $ybase * $this->kp); + for ($i = 2; $i < count($arguments); $i += 2) { if ($ispolyline) { $tmp_x = $arguments[$i]; @@ -2220,37 +2355,38 @@ function svgPolyline($arguments, $ispolyline = true) return $path_cmd; } - // - // fonction retracant les function svgPolygon($arguments) { $xbase = $arguments[0]; $ybase = - $arguments[1]; $path_cmd = sprintf('%.3F %.3F m ', $xbase * $this->kp, $ybase * $this->kp); + for ($i = 2; $i < count($arguments); $i += 2) { $tmp_x = $arguments[$i]; $tmp_y = - $arguments[($i + 1)]; $path_cmd .= sprintf('%.3F %.3F l ', $tmp_x * $this->kp, $tmp_y * $this->kp); } + $path_cmd .= sprintf('%.3F %.3F l ', $xbase * $this->kp, $ybase * $this->kp); $path_cmd .= 'h '; + return $path_cmd; } - // - // write string to image function svgText() { - // $tmp = count($this->txt_style)-1; $current_style = $this->txt_style[count($this->txt_style) - 1]; // mPDF 5.7.4 $style = ''; $op = ''; $render = -1; + if (isset($this->txt_data[2])) { + // mPDF 6 // If using SVG Font if (isset($this->svg_font[$current_style['font-family']])) { + // select font $style = 'R'; $style .= (isset($current_style['font-weight']) && $current_style['font-weight'] == 'bold') ? 'B' : ''; @@ -2258,6 +2394,7 @@ function svgText() $style .= (isset($current_style['font-variant']) && $current_style['font-variant'] == 'small-caps') ? 'S' : ''; $fontsize = $current_style['font-size'] * $this->mpdf->dpi / 72; + if (isset($this->svg_font[$current_style['font-family']][$style])) { $svg_font = $this->svg_font[$current_style['font-family']][$style]; } elseif (isset($this->svg_font[$current_style['font-family']]['R'])) { @@ -2267,6 +2404,7 @@ function svgText() if (!isset($svg_font['units-per-em']) || $svg_font['units-per-em'] < 1) { $svg_font['units-per-em'] = 1000; } + $units_per_em = $svg_font['units-per-em']; $scale = $fontsize / $units_per_em; $stroke_width = $current_style['stroke-width']; @@ -2274,6 +2412,7 @@ function svgText() $opacitystr = ''; $fopacity = 1; + if (isset($current_style['fill-opacity'])) { if ($current_style['fill-opacity'] == 0) { $fopacity = 0; @@ -2285,6 +2424,7 @@ function svgText() $fopacity = 0; } } + $sopacity = 1; if (isset($current_style['stroke-opacity'])) { if ($current_style['stroke-opacity'] == 0) { @@ -2297,6 +2437,7 @@ function svgText() $sopacity = 0; } } + $gs = $this->mpdf->AddExtGState(['ca' => $fopacity, 'CA' => $sopacity, 'BM' => '/Normal']); $this->mpdf->extgstates[$gs]['fo'] = true; $opacitystr = sprintf(' /GS%d gs ', $gs); @@ -2308,6 +2449,7 @@ function svgText() $render = "0"; // Fill (only) $op = 'f'; } + $strokestr = ''; if ($stroke_width > 0 && $current_style['stroke'] != 'none') { $scol = $this->colorConverter->convert($current_style['stroke'], $this->mpdf->PDFAXwarnings); @@ -2326,9 +2468,11 @@ function svgText() $op .= 'S'; } } + if ($render == -1) { return ''; } + if ($op == 'fS') { $op = 'B'; } @@ -2346,9 +2490,11 @@ function svgText() if ($this->textjuststarted) { $txt = ltrim($txt); } // mPDF 5.7.4 + $this->textjuststarted = false; // mPDF 5.7.4 $txt = $this->mpdf->purify_utf8_text($txt); + if ($this->mpdf->text_input_as_HTML) { $txt = $this->mpdf->all_entities_to_utf8($txt); } @@ -2357,8 +2503,10 @@ function svgText() $i = 0; $sw = 0; $subpath_cmd = ''; + while ($i < $nb) { - //Get next character + + // Get next character $char = mb_substr($txt, $i, 1, 'UTF-8'); @@ -2373,12 +2521,15 @@ function svgText() $d = $svg_font['d']; $horiz_adv_x = $svg_font['horiz-adv-x']; // missing glyph width } + preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $d, $commands, PREG_SET_ORDER); $subpath_cmd .= sprintf('q %.4F 0 0 %.4F mPDF-AXS(%.4F) %.4F cm ', $scale, -$scale, ($x + $sw * $scale) * $this->kp, -$y * $this->kp); $this->subPathInit = true; $this->pathBBox = [999999, 999999, -999999, -999999]; + foreach ($commands as $cmd) { + if (count($cmd) == 3 || (isset($cmd[2]) && $cmd[2] == '')) { list($tmp, $command, $arguments) = $cmd; } else { @@ -2388,27 +2539,32 @@ function svgText() $subpath_cmd .= $this->svgPath($command, $arguments); } + $subpath_cmd .= $op . ' Q '; + if ($this->pathBBox[2] == -1999998) { $this->pathBBox[2] = 100; } + if ($this->pathBBox[3] == -1999998) { $this->pathBBox[3] = 100; } + if ($this->pathBBox[0] == 999999) { $this->pathBBox[0] = 0; } + if ($this->pathBBox[1] == 999999) { $this->pathBBox[1] = 0; } - $sw += $horiz_adv_x; $i++; } $sw *= $scale; // convert stringwidth to units // mPDF 5.7.4 + $this->textlength = $sw; $this->texttotallength += $this->textlength; @@ -2431,6 +2587,7 @@ function svgText() $opacitystr = ''; // mPDF 6 $fopacity = 1; + if (isset($current_style['fill-opacity'])) { if ($current_style['fill-opacity'] == 0) { $fopacity = 0; @@ -2442,7 +2599,9 @@ function svgText() $fopacity = 0; } } + $sopacity = 1; + if (isset($current_style['stroke-opacity'])) { if ($current_style['stroke-opacity'] == 0) { $sopacity = 0; @@ -2454,23 +2613,30 @@ function svgText() $sopacity = 0; } } + $gs = $this->mpdf->AddExtGState(['ca' => $fopacity, 'CA' => $sopacity, 'BM' => '/Normal']); $this->mpdf->extgstates[$gs]['fo'] = true; $opacitystr = sprintf(' /GS%d gs ', $gs); $fillstr = ''; + if (isset($current_style['fill']) && $current_style['fill'] != 'none') { $col = $this->colorConverter->convert($current_style['fill'], $this->mpdf->PDFAXwarnings); $fillstr = $this->mpdf->SetFColor($col, true); $render = "0"; // Fill (only) } + $strokestr = ''; + if (isset($current_style['stroke-width']) && $current_style['stroke-width'] > 0 && $current_style['stroke'] != 'none') { $scol = $this->colorConverter->convert($current_style['stroke'], $this->mpdf->PDFAXwarnings); + if ($scol) { $strokestr .= $this->mpdf->SetDColor($scol, true) . ' '; } + $linewidth = $this->ConvertSVGSizePixels($current_style['stroke-width']); + if ($linewidth > 0) { $strokestr .= sprintf('%.3F w 1 J 1 j ', $linewidth * $this->kp); if ($render == -1) { @@ -2481,6 +2647,7 @@ function svgText() } // fill and stroke } } + if ($render == -1) { return ''; } @@ -2498,9 +2665,11 @@ function svgText() if ($this->textjuststarted) { $txt = ltrim($txt); } // mPDF 5.7.4 + $this->textjuststarted = false; // mPDF 5.7.4 $txt = $this->mpdf->purify_utf8_text($txt); + if ($this->mpdf->text_input_as_HTML) { $txt = $this->mpdf->all_entities_to_utf8($txt); } @@ -2508,6 +2677,7 @@ function svgText() if ($this->mpdf->usingCoreFont) { $txt = mb_convert_encoding($txt, $this->mpdf->mb_enc, 'UTF-8'); } + if (preg_match("/([" . $this->mpdf->pregRTLchars . "])/u", $txt)) { $this->mpdf->biDirectional = true; } @@ -2515,13 +2685,17 @@ function svgText() $textvar = 0; $save_OTLtags = $this->mpdf->OTLtags; $this->mpdf->OTLtags = []; + if ($this->mpdf->useKerning) { + if ($this->mpdf->CurrentFont['haskernGPOS']) { + if (isset($this->mpdf->OTLtags['Plus'])) { $this->mpdf->OTLtags['Plus'] .= ' kern'; } else { $this->mpdf->OTLtags['Plus'] = ' kern'; } + } else { $textvar = ($textvar | TextVars::FC_KERNING); } @@ -2532,6 +2706,7 @@ function svgText() $txt = $this->otl->applyOTL($txt, $this->mpdf->CurrentFont['useOTL']); $OTLdata = $this->otl->OTLdata; } + $this->mpdf->OTLtags = $save_OTLtags; $this->mpdf->magic_reverse_dir($txt, $this->mpdf->directionality, $OTLdata); @@ -2539,6 +2714,7 @@ function svgText() $this->mpdf->CurrentFont['used'] = true; $sw = $this->mpdf->GetStringWidth($txt, true, $OTLdata, $textvar); // also adds characters to subset + // mPDF 5.7.4 $this->textlength = $sw * 1 / (25.4 / $this->mpdf->dpi); $this->texttotallength += $this->textlength; @@ -2557,9 +2733,11 @@ function svgText() if (isset($current_style['font-size-parent'])) { $this->mpdf->SetFontSize($current_style['font-size-parent']); } + } else { return ' '; } + // Reset font // mPDF 5.7.4 $prev_style = $this->txt_style[count($this->txt_style) - 1]; $style = ''; @@ -2576,7 +2754,9 @@ function svgDefineTxtStyle($critere_style) // get copy of current/default txt style, and modify it with supplied attributes $tmp = count($this->txt_style) - 1; $current_style = $this->txt_style[$tmp]; + if (isset($critere_style['style'])) { + if (preg_match('/fill:\s*rgb\((\d+),\s*(\d+),\s*(\d+)\)/', $critere_style['style'], $m)) { $current_style['fill'] = '#' . str_pad(dechex($m[1]), 2, "0", STR_PAD_LEFT) . str_pad(dechex($m[2]), 2, "0", STR_PAD_LEFT) . str_pad(dechex($m[3]), 2, "0", STR_PAD_LEFT); } else { @@ -2677,6 +2857,7 @@ function svgDefineTxtStyle($critere_style) $critere_style['text-anchor'] = $tmp; } } + if (isset($critere_style['font'])) { // [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]?<'font-size'> [ / <'line-height'> ]? <'font-family'> ] @@ -2687,6 +2868,7 @@ function svgDefineTxtStyle($critere_style) } $current_style['font-style'] = $tmp; } + $tmp = preg_replace("/(.*)(bold|bolder)(.*)/i", "$2", $critere_style['font']); if ($tmp != $critere_style['font']) { if ($tmp == 'bolder') { @@ -2713,20 +2895,25 @@ function svgDefineTxtStyle($critere_style) $current_style['fill-opacity'] = $critere_style['opacity']; $current_style['stroke-opacity'] = $critere_style['opacity']; } + // mPDF 6 if (isset($critere_style['stroke-opacity']) && $critere_style['stroke-opacity'] != 'inherit') { $current_style['stroke-opacity'] = $critere_style['stroke-opacity']; } + // mPDF 6 if (isset($critere_style['fill-opacity']) && $critere_style['fill-opacity'] != 'inherit') { $current_style['fill-opacity'] = $critere_style['fill-opacity']; } + if (isset($critere_style['fill']) && $critere_style['fill'] != 'inherit') { $current_style['fill'] = $critere_style['fill']; } + if (isset($critere_style['stroke']) && $critere_style['stroke'] != 'inherit') { $current_style['stroke'] = $critere_style['stroke']; } + if (isset($critere_style['stroke-width']) && $critere_style['stroke-width'] != 'inherit') { $current_style['stroke-width'] = $critere_style['stroke-width']; } @@ -2783,6 +2970,7 @@ function svgDefineTxtStyle($critere_style) break; } } + if (!$found) { foreach ($aux_fontlist as $f) { $fonttype = trim($f); @@ -2799,6 +2987,7 @@ function svgDefineTxtStyle($critere_style) } } } + if (isset($critere_style['text-anchor']) && $critere_style['text-anchor'] != 'inherit') { $current_style['text-anchor'] = $critere_style['text-anchor']; } @@ -2807,18 +2996,12 @@ function svgDefineTxtStyle($critere_style) array_push($this->txt_style, $current_style); } - // - // fonction ajoutant un gradient function svgAddGradient($id, $array_gradient) { $this->svg_gradient[$id] = $array_gradient; } - // - // Ajoute une couleur dans le gradient correspondant - // - // function ecrivant dans le svgstring function svgWriteString($content) { $this->svg_string .= $content; @@ -3259,44 +3442,53 @@ function markScriptToLang($html) function xml_svg2pdf_start($parser, $name, $attribs) { global $last_gradid, $last_svg_fontid, $last_svg_fontdefw, $last_svg_fontstyle; // mPDF 6 + // mPDF 6 if (strtolower($name) == 'font') { $last_svg_fontid = ''; + if (isset($attribs['horiz-adv-x']) && $attribs['horiz-adv-x']) { $last_svg_fontdefw = $attribs['horiz-adv-x']; } + return; - } // mPDF 6 - elseif (strtolower($name) == 'font-face') { + } elseif (strtolower($name) == 'font-face') { // mPDF 6 $last_svg_fontstyle = 'R'; $last_svg_fontstyle .= (isset($attribs['font-weight']) && $attribs['font-weight'] == 'bold') ? 'B' : ''; $last_svg_fontstyle .= (isset($attribs['font-style']) && $attribs['font-style'] == 'italic') ? 'I' : ''; $last_svg_fontstyle .= (isset($attribs['font-variant']) && $attribs['font-variant'] == 'small-caps') ? 'S' : ''; if (isset($attribs['font-family']) && $attribs['font-family']) { + $tmp_svg_font = [ 'units-per-em' => (isset($attribs['units-per-em']) ? $attribs['units-per-em'] : ''), 'd' => '', 'glyphs' => [] ]; + $last_svg_fontid = strtolower($attribs['font-family']); + if ($last_svg_fontdefw) { $tmp_svg_font['horiz-adv-x'] = $last_svg_fontdefw; } else { $tmp_svg_font['horiz-adv-x'] = 500; } + $this->svg_font[$last_svg_fontid][$last_svg_fontstyle] = $tmp_svg_font; } + return; - } // mPDF 6 - elseif (strtolower($name) == 'missing-glyph') { + } elseif (strtolower($name) == 'missing-glyph') { // mPDF 6 + if ($last_svg_fontid && isset($attribs['horiz-adv-x'])) { $this->svg_font[$last_svg_fontid][$last_svg_fontstyle]['horiz-adv-x'] = (isset($attribs['horiz-adv-x']) ? $attribs['horiz-adv-x'] : ''); $this->svg_font[$last_svg_fontid][$last_svg_fontstyle]['d'] = (isset($attribs['d']) ? $attribs['d'] : ''); } + return; - } // mPDF 6 - elseif (strtolower($name) == 'glyph') { + + } elseif (strtolower($name) == 'glyph') { // mPDF 6 + if ($last_svg_fontid && isset($attribs['unicode'])) { $this->svg_font[$last_svg_fontid][$last_svg_fontstyle]['glyphs'][$attribs['unicode']] = [ 'horiz-adv-x' => (isset($attribs['horiz-adv-x']) ? $attribs['horiz-adv-x'] : $last_svg_fontdefw), @@ -3304,8 +3496,9 @@ function xml_svg2pdf_start($parser, $name, $attribs) ]; } return; - } // mPDF 5.7.2 - elseif (strtolower($name) == 'lineargradient') { + + } elseif (strtolower($name) == 'lineargradient') { // mPDF 5.7.2 + $tmp_gradient = [ 'type' => 'linear', 'transform' => (isset($attribs['gradientTransform']) ? $attribs['gradientTransform'] : ''), @@ -3313,22 +3506,30 @@ function xml_svg2pdf_start($parser, $name, $attribs) 'spread' => (isset($attribs['spreadMethod']) ? $attribs['spreadMethod'] : ''), 'color' => [] ]; + if (isset($attribs['x1'])) { $tmp_gradient['info']['x1'] = $attribs['x1']; } + if (isset($attribs['y1'])) { $tmp_gradient['info']['y1'] = $attribs['y1']; } + if (isset($attribs['x2'])) { $tmp_gradient['info']['x2'] = $attribs['x2']; } + if (isset($attribs['y2'])) { $tmp_gradient['info']['y2'] = $attribs['y2']; } + $last_gradid = $attribs['id']; $this->svgAddGradient($attribs['id'], $tmp_gradient); + return; + } elseif (strtolower($name) == 'radialgradient') { + $tmp_gradient = [ 'type' => 'radial', 'transform' => (isset($attribs['gradientTransform']) ? $attribs['gradientTransform'] : ''), @@ -3336,38 +3537,50 @@ function xml_svg2pdf_start($parser, $name, $attribs) 'spread' => (isset($attribs['spreadMethod']) ? $attribs['spreadMethod'] : ''), 'color' => [] ]; + if (isset($attribs['cx'])) { $tmp_gradient['info']['x0'] = $attribs['cx']; } + if (isset($attribs['cy'])) { $tmp_gradient['info']['y0'] = $attribs['cy']; } + if (isset($attribs['fx'])) { $tmp_gradient['info']['x1'] = $attribs['fx']; } + if (isset($attribs['fy'])) { $tmp_gradient['info']['y1'] = $attribs['fy']; } + if (isset($attribs['r'])) { $tmp_gradient['info']['r'] = $attribs['r']; } + $last_gradid = $attribs['id']; $this->svgAddGradient($attribs['id'], $tmp_gradient); + return; + } elseif (strtolower($name) == 'stop') { + if (!$last_gradid) { return; } + $color = '#000000'; if (isset($attribs['style']) and preg_match('/stop-color:\s*([^;]*)/i', $attribs['style'], $m)) { $color = trim($m[1]); } elseif (isset($attribs['stop-color']) && $attribs['stop-color']) { $color = $attribs['stop-color']; } + $col = $this->colorConverter->convert($color, $this->mpdf->PDFAXwarnings); if (!$col) { $col = $this->colorConverter->convert('#000000', $this->mpdf->PDFAXwarnings); } // In case "transparent" or "inherit" returned + if ($col[0] == 3 || $col[0] == 5) { // RGB $color_final = sprintf('%.3F %.3F %.3F', ord($col[1]) / 255, ord($col[2]) / 255, ord($col[3]) / 255); $this->svg_gradient[$last_gradid]['colorspace'] = 'RGB'; @@ -3380,6 +3593,7 @@ function xml_svg2pdf_start($parser, $name, $attribs) } $stop_opacity = 1; + if (isset($attribs['style']) and preg_match('/stop-opacity:\s*([0-9.]*)/i', $attribs['style'], $m)) { $stop_opacity = $m[1]; } elseif (isset($attribs['stop-opacity'])) { @@ -3396,15 +3610,19 @@ function xml_svg2pdf_start($parser, $name, $attribs) 'opacity' => $stop_opacity ]; array_push($this->svg_gradient[$last_gradid]['color'], $tmp_color); + return; } + if ($this->inDefs) { return; } $this->xbase = 0; $this->ybase = 0; + switch (strtolower($name)) { + // Don't output stuff inside case 'defs': $this->inDefs = true; @@ -3415,11 +3633,13 @@ function xml_svg2pdf_start($parser, $name, $attribs) break; case 'path': + $path = Arrays::get($attribs, 'd', ''); preg_match_all('/([MZLHVCSQTAmzlhvcsqta])([eE ,\-.\d]+)*/', $path, $commands, PREG_SET_ORDER); $path_cmd = ''; $this->subPathInit = true; $this->pathBBox = [999999, 999999, -999999, -999999]; + foreach ($commands as $c) { if ((isset($c) && count($c) == 3) || (isset($c[2]) && $c[2] == '')) { list($tmp, $command, $arguments) = $c; @@ -3430,114 +3650,151 @@ function xml_svg2pdf_start($parser, $name, $attribs) $path_cmd .= $this->svgPath($command, $arguments); } + if ($this->pathBBox[2] == -1999998) { $this->pathBBox[2] = 100; } + if ($this->pathBBox[3] == -1999998) { $this->pathBBox[3] = 100; } + if ($this->pathBBox[0] == 999999) { $this->pathBBox[0] = 0; } + if ($this->pathBBox[1] == 999999) { $this->pathBBox[1] = 0; } + $critere_style = $attribs; unset($critere_style['d']); $path_style = $this->svgDefineStyle($critere_style); + break; case 'rect': if (!isset($attribs['x'])) { $attribs['x'] = 0; } + if (!isset($attribs['y'])) { $attribs['y'] = 0; } + if (!isset($attribs['rx'])) { $attribs['rx'] = 0; } + if (!isset($attribs['ry'])) { $attribs['ry'] = 0; } + $arguments = []; + if (isset($attribs['x'])) { $arguments['x'] = $attribs['x']; } + if (isset($attribs['y'])) { $arguments['y'] = $attribs['y']; } + if (isset($attribs['width'])) { $arguments['w'] = $attribs['width']; } + if (isset($attribs['height'])) { $arguments['h'] = $attribs['height']; } + if (isset($attribs['rx'])) { $arguments['rx'] = $attribs['rx']; } + if (isset($attribs['ry'])) { $arguments['ry'] = $attribs['ry']; } + $path_cmd = $this->svgRect($arguments); $critere_style = $attribs; unset($critere_style['x'], $critere_style['y'], $critere_style['rx'], $critere_style['ry'], $critere_style['height'], $critere_style['width']); $path_style = $this->svgDefineStyle($critere_style); + break; case 'circle': + if (!isset($attribs['cx'])) { $attribs['cx'] = 0; } + if (!isset($attribs['cy'])) { $attribs['cy'] = 0; } + $arguments = []; + if (isset($attribs['cx'])) { $arguments['cx'] = $attribs['cx']; } + if (isset($attribs['cy'])) { $arguments['cy'] = $attribs['cy']; } + if (isset($attribs['r'])) { $arguments['rx'] = $attribs['r']; } + if (isset($attribs['r'])) { $arguments['ry'] = $attribs['r']; } + $path_cmd = $this->svgEllipse($arguments); $critere_style = $attribs; unset($critere_style['cx'], $critere_style['cy'], $critere_style['r']); $path_style = $this->svgDefineStyle($critere_style); + break; case 'ellipse': + if (!isset($attribs['cx'])) { $attribs['cx'] = 0; } + if (!isset($attribs['cy'])) { $attribs['cy'] = 0; } + $arguments = []; + if (isset($attribs['cx'])) { $arguments['cx'] = $attribs['cx']; } + if (isset($attribs['cy'])) { $arguments['cy'] = $attribs['cy']; } + if (isset($attribs['rx'])) { $arguments['rx'] = $attribs['rx']; } + if (isset($attribs['ry'])) { $arguments['ry'] = $attribs['ry']; } + $path_cmd = $this->svgEllipse($arguments); $critere_style = $attribs; unset($critere_style['cx'], $critere_style['cy'], $critere_style['rx'], $critere_style['ry']); $path_style = $this->svgDefineStyle($critere_style); + break; case 'line': + $arguments = []; $arguments[0] = (isset($attribs['x1']) ? $attribs['x1'] : ''); $arguments[1] = (isset($attribs['y1']) ? $attribs['y1'] : ''); @@ -3547,63 +3804,79 @@ function xml_svg2pdf_start($parser, $name, $attribs) $critere_style = $attribs; unset($critere_style['x1'], $critere_style['y1'], $critere_style['x2'], $critere_style['y2']); $path_style = $this->svgDefineStyle($critere_style); + break; case 'polyline': + $path = $attribs['points']; preg_match_all('/[0-9\-\.]*/', $path, $tmp, PREG_SET_ORDER); $arguments = []; + for ($i = 0; $i < count($tmp); $i++) { if ($tmp[$i][0] != '') { array_push($arguments, $tmp[$i][0]); } } + $path_cmd = $this->svgPolyline($arguments); $critere_style = $attribs; unset($critere_style['points']); $path_style = $this->svgDefineStyle($critere_style); + break; case 'polygon': + $path = $attribs['points']; preg_match_all('/([\-]*[0-9\.]+)/', $path, $tmp); $arguments = []; + for ($i = 0; $i < count($tmp[0]); $i++) { if ($tmp[0][$i] != '') { array_push($arguments, $tmp[0][$i]); } } + $path_cmd = $this->svgPolygon($arguments); // definition du style de la forme: $critere_style = $attribs; unset($critere_style['points']); $path_style = $this->svgDefineStyle($critere_style); + break; // mPDF 5.7.4 Embedded image case 'image': + if (isset($attribs['xlink:href']) && $attribs['xlink:href']) { $this->svgImage($attribs); } - break; + break; case 'a': + if (isset($attribs['xlink:href'])) { unset($attribs['xlink:href']); // this should be a hyperlink // not handled like a xlink:href in other elements - } // then continue like a + } + + // fallthtough - then continue like a + case 'g': + $array_style = $this->svgDefineStyle($attribs); + if (!empty($array_style['transformations'])) { // If in the middle of element, add to textoutput, else WriteString if ($this->intext) { $this->textoutput .= ' q ' . $array_style['transformations']; - } // mPDF 5.7.4 - else { + } else { // mPDF 5.7.4 $this->svgWriteString(' q ' . $array_style['transformations']); } } + array_push($this->svg_style, $array_style); $this->svgDefineTxtStyle($attribs); @@ -3611,6 +3884,7 @@ function xml_svg2pdf_start($parser, $name, $attribs) break; case 'text': + $this->textlength = 0; // mPDF 5.7.4 $this->texttotallength = 0; // mPDF 5.7.4 $this->textoutput = ''; // mPDF 5.7.4 @@ -3621,6 +3895,7 @@ function xml_svg2pdf_start($parser, $name, $attribs) $this->intext = true; // mPDF 5.7.4 $styl = ''; + if ($this->mpdf->svgClasses && isset($attribs['class']) && $attribs['class']) { $classes = preg_split('/\s+/', trim($attribs['class'])); foreach ($classes as $class) { @@ -3679,6 +3954,7 @@ function xml_svg2pdf_start($parser, $name, $attribs) // mPDF 5.7.4 case 'tspan': + // OUTPUT CHUNK(s) UP To NOW (svgText updates $this->textlength) $p_cmd = $this->svgText(); $this->textoutput .= $p_cmd; @@ -3804,6 +4080,7 @@ function characterData($parser, $data) if ($this->inDefs) { return; } // mPDF 5.7.2 + if (isset($this->txt_data[2])) { $this->txt_data[2] .= $data; } else { @@ -3941,37 +4218,51 @@ private function computeBezierBoundingBox($start, $c) $bounds[1][] = $P0[1]; $bounds[0][] = $P3[0]; $bounds[1][] = $P3[1]; + for ($i = 0; $i <= 1; $i++) { $b = 6 * $P0[$i] - 12 * $P1[$i] + 6 * $P2[$i]; $a = -3 * $P0[$i] + 9 * $P1[$i] - 9 * $P2[$i] + 3 * $P3[$i]; $c = 3 * $P1[$i] - 3 * $P0[$i]; + if ($a == 0) { + if ($b == 0) { continue; } + $t = -$c / $b; + if ($t > 0 && $t < 1) { $bounds[$i][] = (pow((1 - $t), 3) * $P0[$i] + 3 * pow((1 - $t), 2) * $t * $P1[$i] + 3 * (1 - $t) * pow($t, 2) * $P2[$i] + pow($t, 3) * $P3[$i]); } + continue; } + $b2ac = pow($b, 2) - 4 * $c * $a; + if ($b2ac < 0) { continue; } + $t1 = (-$b + sqrt($b2ac)) / (2 * $a); + if ($t1 > 0 && $t1 < 1) { $bounds[$i][] = (pow((1 - $t1), 3) * $P0[$i] + 3 * pow((1 - $t1), 2) * $t1 * $P1[$i] + 3 * (1 - $t1) * pow($t1, 2) * $P2[$i] + pow($t1, 3) * $P3[$i]); } + $t2 = (-$b - sqrt($b2ac)) / (2 * $a); + if ($t2 > 0 && $t2 < 1) { $bounds[$i][] = (pow((1 - $t2), 3) * $P0[$i] + 3 * pow((1 - $t2), 2) * $t2 * $P1[$i] + 3 * (1 - $t2) * pow($t2, 2) * $P2[$i] + pow($t2, 3) * $P3[$i]); } } + $x = min($bounds[0]); $x2 = max($bounds[0]); $y = min($bounds[1]); $y2 = max($bounds[1]); + return [$x, $y, $x2, $y2]; } @@ -3982,8 +4273,7 @@ private function testIntersectCircle($cx, $cy, $cr) // If centre of circle is inside 0,0,1,1 square if ($cx >= 0 && $cx <= 1 && $cy >= 0 && $cy <= 1) { $maxd = 1.5; - } // distance to four corners - else { + } else { // distance to four corners $d1 = sqrt(pow(($cy - 0), 2) + pow(($cx - 0), 2)); $d2 = sqrt(pow(($cy - 1), 2) + pow(($cx - 0), 2)); $d3 = sqrt(pow(($cy - 0), 2) + pow(($cx - 1), 2)); @@ -4005,6 +4295,7 @@ private function testIntersect($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4) $b2 = $x3 - $x4; $c2 = $a2 * $x3 + $b2 * $y3; $det = $a1 * $b2 - $a2 * $b1; + if ($det == 0) { //Lines are parallel return false; } else { @@ -4014,6 +4305,7 @@ private function testIntersect($x1, $y1, $x2, $y2, $x3, $y3, $x4, $y4) return true; } } + return false; } diff --git a/vendor/mpdf/mpdf/src/Mpdf.php b/vendor/mpdf/mpdf/src/Mpdf.php index fd8f9cf6..a54b8290 100644 --- a/vendor/mpdf/mpdf/src/Mpdf.php +++ b/vendor/mpdf/mpdf/src/Mpdf.php @@ -4,25 +4,16 @@ use Mpdf\Config\ConfigVariables; use Mpdf\Config\FontVariables; - use Mpdf\Conversion; - use Mpdf\Css\Border; use Mpdf\Css\TextVars; - -use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor; use Mpdf\Log\Context as LogContext; - use Mpdf\Fonts\MetricsGenerator; - use Mpdf\Output\Destination; - use Mpdf\QrCode; - use Mpdf\Utils\Arrays; use Mpdf\Utils\NumericString; use Mpdf\Utils\UtfString; - use Psr\Log\LoggerInterface; use Psr\Log\NullLogger; @@ -40,7 +31,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface use Strict; use FpdiTrait; - const VERSION = '8.0.7'; + const VERSION = '8.0.17'; const SCALE = 72 / 25.4; @@ -292,6 +283,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface var $tempDir; + var $cacheCleanupInterval; + var $allowAnnotationFiles; var $fontdata; @@ -386,6 +379,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface var $pageTemplate; var $docTemplate; var $docTemplateContinue; + var $docTemplateContinue2pages; var $arabGlyphs; var $arabHex; @@ -675,6 +669,13 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface */ var $curlTimeout; + /** + * Set execution timeout for cURL + * + * @var int + */ + var $curlExecutionTimeout; + /** * Set to true to follow redirects with cURL. * @@ -827,6 +828,8 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface public $exposeVersion; + private $preambleWritten = false; + /** * @var string */ @@ -939,7 +942,7 @@ class Mpdf implements \Psr\Log\LoggerAwareInterface private $remoteContentFetcher; /** - * @var ImageProcessor + * @var \Mpdf\Image\ImageProcessor */ private $imageProcessor; @@ -1548,6 +1551,14 @@ public function cleanup() { mb_internal_encoding($this->originalMbEnc); @mb_regex_encoding($this->originalMbRegexEnc); + + // this will free up the readers, based on code from Setasign's FpdiTrait::cleanUp() + foreach ($this->createdReaders as $id) { + $this->readers[$id]->getParser()->getStreamReader()->cleanUp(); + unset($this->readers[$id]); + } + + $this->createdReaders = []; } /** @@ -1957,11 +1968,12 @@ function Open() { // Begin document if ($this->state == 0) { - // Was is function _begindoc() - // Start document $this->state = 1; - $this->writer->write('%PDF-' . $this->pdf_version); - $this->writer->write('%' . chr(226) . chr(227) . chr(207) . chr(211)); // 4 chars > 128 to show binary file + if (false === $this->preambleWritten) { + $this->writer->write('%PDF-' . $this->pdf_version); + $this->writer->write('%' . chr(226) . chr(227) . chr(207) . chr(211)); // 4 chars > 128 to show binary file + $this->preambleWritten = true; + } } } @@ -1973,15 +1985,20 @@ function Close() if ($this->state == 3) { return; } + if ($this->page == 0) { $this->AddPage($this->CurOrientation); } + if (count($this->cellBorderBuffer)) { $this->printcellbuffer(); - } // *TABLES* + } + + // *TABLES* if ($this->tablebuffer) { $this->printtablebuffer(); - } // *TABLES* + } + /* -- COLUMNS -- */ if ($this->ColActive) { @@ -1991,6 +2008,7 @@ function Close() $this->printcolumnbuffer(); } } + /* -- END COLUMNS -- */ // BODY Backgrounds @@ -2023,7 +2041,6 @@ function Close() $this->tableOfContents->insertTOC(); } - // *TOC* // Close page $this->_endpage(); @@ -3166,7 +3183,9 @@ function AddPage( } // Start new page + $pageBeforeNewPage = $this->page; $this->_beginpage($orientation, $mgl, $mgr, $mgt, $mgb, $mgh, $mgf, $ohname, $ehname, $ofname, $efname, $ohvalue, $ehvalue, $ofvalue, $efvalue, $pagesel, $newformat); + $isNewPage = $pageBeforeNewPage !== $this->page; if ($this->docTemplate) { $currentReaderId = $this->currentReaderId; @@ -3174,8 +3193,13 @@ function AddPage( $pagecount = $this->setSourceFile($this->docTemplate); if (($this->page - $this->docTemplateStart) > $pagecount) { if ($this->docTemplateContinue) { - $tplIdx = $this->importPage($pagecount); - $this->useTemplate($tplIdx); + if ($this->docTemplateContinue2pages && $pagecount >= 2 && (0 === $this->page % 2)) { + $tplIdx = $this->importPage(($pagecount - 1)); + $this->useTemplate($tplIdx); + } else { + $tplIdx = $this->importPage($pagecount); + $this->useTemplate($tplIdx); + } } } else { $tplIdx = $this->importPage(($this->page - $this->docTemplateStart)); @@ -3189,10 +3213,14 @@ function AddPage( $this->useTemplate($this->pageTemplate); } - // Tiling Patterns - $this->writer->write('___PAGE___START' . $this->uniqstr); - $this->writer->write('___BACKGROUND___PATTERNS' . $this->uniqstr); - $this->writer->write('___HEADER___MARKER' . $this->uniqstr); + // Only add the headers if it's a new page + if ($isNewPage) { + // Tiling Patterns + $this->writer->write('___PAGE___START' . $this->uniqstr); + $this->writer->write('___BACKGROUND___PATTERNS' . $this->uniqstr); + $this->writer->write('___HEADER___MARKER' . $this->uniqstr); + } + $this->pageBackgrounds = []; // Set line cap style to square @@ -4058,13 +4086,15 @@ function SetFont($family, $style = '', $size = 0, $write = true, $forcewrite = f $style = 'BI'; } } - if ($size == 0) { + + if (!$size) { $size = $this->FontSizePt; } $fontkey = $family . $style; $stylekey = $style; + if (!$stylekey) { $stylekey = "R"; } @@ -4726,7 +4756,7 @@ function Cell($w, $h = 0, $txt = '', $border = 0, $ln = 0, $align = '', $fill = || ($this->y + $h > $this->PageBreakTrigger) || ( $this->y + ($h * 2) + $bottom > $this->PageBreakTrigger - && $this->blk[$this->blklvl]['page_break_after_avoid'] + && (isset($this->blk[$this->blklvl]['page_break_after_avoid']) && $this->blk[$this->blklvl]['page_break_after_avoid']) ) ) && !$this->InFooter @@ -6558,7 +6588,7 @@ function finishFlowingBlock($endofblock = false, $next = '') $lastfontreqstyle = null; $lastfontstyle = null; } - if ($blockdir == 'ltr' && strpos($lastfontreqstyle, "I") !== false && strpos($lastfontstyle, "I") === false) { // Artificial italic + if ($blockdir == 'ltr' && $lastfontreqstyle && strpos($lastfontreqstyle, "I") !== false && strpos($lastfontstyle, "I") === false) { // Artificial italic $lastitalic = $this->FontSize * 0.15 * Mpdf::SCALE; } else { $lastitalic = 0; @@ -7449,7 +7479,6 @@ function ($col) { unset($qrcode); } else { - $this->WriteBarcode2( $objattr['code'], $objattr['INNER-X'], @@ -7460,9 +7489,10 @@ function ($col) { $col, $objattr['btype'], $objattr['pr_ratio'], - $k + $k, + $objattr['quiet_zone_left'], + $objattr['quiet_zone_right'] ); - } } @@ -8217,7 +8247,7 @@ function WriteFlowingBlock($s, $sOTLdata) // Right Trim current content - including CJK space, and for OTLdata // incl. CJK - strip CJK space at end of line   = \xe3\x80\x80 = CJK space - $currContent = rtrim($currContent); + $currContent = $currContent ? rtrim($currContent) : ''; if ($this->checkCJK) { $currContent = preg_replace("/\xe3\x80\x80$/", '', $currContent); } // *CJK-FONTS* @@ -9304,15 +9334,18 @@ function SetDash($black = false, $white = false) } else { $s = '[] 0 d'; } + if ($this->page > 0 && ((isset($this->pageoutput[$this->page]['Dash']) && $this->pageoutput[$this->page]['Dash'] != $s) || !isset($this->pageoutput[$this->page]['Dash']))) { $this->writer->write($s); } + $this->pageoutput[$this->page]['Dash'] = $s; } function SetDisplayPreferences($preferences) { // String containing any or none of /HideMenubar/HideToolbar/HideWindowUI/DisplayDocTitle/CenterWindow/FitWindow + $this->DisplayPreferences .= $preferences; } @@ -9320,14 +9353,19 @@ function Ln($h = '', $collapsible = 0) { // Added collapsible to allow collapsible top-margin on new page // Line feed; default value is last cell height - $this->x = $this->lMargin + $this->blk[$this->blklvl]['outer_left_margin']; + + $margin = isset($this->blk[$this->blklvl]['outer_left_margin']) ? $this->blk[$this->blklvl]['outer_left_margin'] : 0; + + $this->x = $this->lMargin + $margin; + if ($collapsible && ($this->y == $this->tMargin) && (!$this->ColActive)) { $h = 0; } + if (is_string($h)) { - $this->y+=$this->lasth; + $this->y += $this->lasth; } else { - $this->y+=$h; + $this->y += $h; } } @@ -9611,6 +9649,14 @@ function _dochecks() if (!function_exists('mb_substr')) { throw new \Mpdf\MpdfException('mbstring extension must be loaded in order to run mPDF'); } + + if (!function_exists('mb_regex_encoding')) { + if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { + $mamp = ' If using MAMP, there is a bug in its PHP build causing this.'; + } + + throw new \Mpdf\MpdfException('mbstring extension with mbregex support must be loaded in order to run mPDF.' . $mamp); + } } function _puthtmlheaders() @@ -9656,10 +9702,9 @@ function _puthtmlheaders() $this->pgwidth = $this->w - $this->lMargin - $this->rMargin; $this->x = $this->lMargin; $this->y = $this->margin_header; - $html = str_replace('{PAGENO}', $pnstr, $html); - $html = str_replace($this->aliasNbPgGp, $pntstr, $html); // {nbpg} - $html = str_replace($this->aliasNbPg, $nb, $html); // {nb} - $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', [$this, 'date_callback'], $html); // mPDF 5.7 + + // Replace of page number aliases and date format + $html = $this->aliasReplace($html, $pnstr, $pntstr, $nb); $this->HTMLheaderPageLinks = []; $this->HTMLheaderPageAnnots = []; @@ -9737,11 +9782,8 @@ function _puthtmlheaders() $top_y = $this->y = ($this->h + 0.01); } - $html = str_replace('{PAGENO}', $pnstr, $html); - $html = str_replace($this->aliasNbPgGp, $pntstr, $html); // {nbpg} - $html = str_replace($this->aliasNbPg, $nb, $html); // {nb} - $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', [$this, 'date_callback'], $html); // mPDF 5.7 - + // Replace of page number aliases and date format + $html = $this->aliasReplace($html, $pnstr, $pntstr, $nb); $this->HTMLheaderPageLinks = []; $this->HTMLheaderPageAnnots = []; @@ -9815,6 +9857,10 @@ function _puthtmlheaders() } /* -- END FORMS -- */ } + + // Customization for https://github.com/mpdf/mpdf/issues/172 + // Replace of page number aliases and date format + $this->pages[$n] = $this->aliasReplace($this->pages[$n], $pnstr, $pntstr, $nb); } $this->page = $nb; @@ -11452,7 +11498,7 @@ public function GetFullPath(&$path, $basepath = '') $path = $path . "/" . $filepath; // Make it an absolute path - } elseif ((strpos($path, ":/") === false || strpos($path, ":/") > 10) && !@is_file($path)) { // It is a local link + } elseif ((strpos($path, ":/") === false || strpos($path, ":/") > 10) && !@is_file($path)) { // It is a local link. Ignore potential file errors if (substr($path, 0, 1) == "/") { @@ -12354,10 +12400,13 @@ function _getHtmlHeight($html) $save_y = $this->y; $this->x = $this->lMargin; $this->y = $this->margin_header; - $html = str_replace('{PAGENO}', $this->pagenumPrefix . $this->docPageNum($this->page) . $this->pagenumSuffix, $html); - $html = str_replace($this->aliasNbPgGp, $this->nbpgPrefix . $this->docPageNumTotal($this->page) . $this->nbpgSuffix, $html); - $html = str_replace($this->aliasNbPg, $this->page, $html); - $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', [$this, 'date_callback'], $html); // mPDF 5.7 + + // Replace of page number aliases and date format + $pnstr = $this->pagenumPrefix . $this->docPageNum($this->page) . $this->pagenumSuffix; + $pntstr = $this->nbpgPrefix . $this->docPageNumTotal($this->page) . $this->nbpgSuffix; + $nb = $this->page; + $html = $this->aliasReplace($html, $pnstr, $pntstr, $nb); + $this->HTMLheaderPageLinks = []; $this->HTMLheaderPageAnnots = []; $this->HTMLheaderPageForms = []; @@ -12367,6 +12416,7 @@ function _getHtmlHeight($html) $this->writingHTMLheader = false; $h = ($this->y - $this->margin_header); $this->Reset(); + // mPDF 5.7.2 - Clear in case Float used in Header/Footer $this->blk[0]['blockContext'] = 0; $this->blk[0]['float_endpos'] = 0; @@ -12377,6 +12427,7 @@ function _getHtmlHeight($html) $this->x = $save_x; $this->y = $save_y; $this->state = $save_state; + if ($save_state == 0) { unset($this->pages[1]); $this->page = 0; @@ -13521,21 +13572,30 @@ function WriteHTML($html, $mode = HTMLParserMode::DEFAULT_MODE, $init = true, $c $this->cell[$this->row][$this->col]['s'] += (isset($this->spanborddet['L']['w']) ? $this->spanborddet['L']['w'] : 0) + (isset($this->spanborddet['R']['w']) ? $this->spanborddet['R']['w'] : 0); } } + $this->_saveCellTextBuffer($e, $this->HREF); + if (substr($this->cell[$this->row][$this->col]['a'], 0, 1) == 'D') { + $dp = $this->decimal_align[substr($this->cell[$this->row][$this->col]['a'], 0, 2)]; $s = preg_split('/' . preg_quote($dp, '/') . '/', $e, 2); // ? needs to be /u if not core $s0 = $this->GetStringWidth($s[0], false); + if (isset($s[1]) && $s[1]) { $s1 = $this->GetStringWidth(($s[1] . $dp), false); } else { $s1 = 0; } + if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'])) { + if ($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'] === false) { + $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'] = []; + } $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = $s0; } else { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0'] = max($s0, $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs0']); } + if (!isset($this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'])) { $this->table[$this->tableLevel][$this->tbctr[$this->tableLevel]]['decimal_align'][$this->col]['maxs1'] = $s1; } else { @@ -13794,7 +13854,7 @@ function WriteHTML($html, $mode = HTMLParserMode::DEFAULT_MODE, $init = true, $c $this->Reset(); $this->pageoutput[$this->page] = []; } - $this->y = (($this->blk[$this->blklvl]['float_endpos'] * 1000) % 1000000) / 1000; // mod changes operands to integers before processing + $this->y = (round($this->blk[$this->blklvl]['float_endpos'] * 1000) % 1000000) / 1000; // mod changes operands to integers before processing } /* -- END CSS-FLOAT -- */ @@ -15242,7 +15302,8 @@ function ClearFloats($clear, $blklvl = 0) } $this->ResetMargins(); $this->pageoutput[$this->page] = []; - $this->y = (($end * 1000) % 1000000) / 1000; // mod changes operands to integers before processing + + $this->y = (round($end * 1000) % 1000000) / 1000; // mod changes operands to integers before processing } // Added mPDF 3.0 Float DIV @@ -17969,10 +18030,9 @@ function Reset() $this->currentfontsize = ''; $this->currentfontstyle = ''; - /* -- TABLES -- */ if ($this->tableLevel && isset($this->table[1][1]['cellLineHeight'])) { - $this->SetLineHeight('', $this->table[1][1]['cellLineHeight']); // *TABLES* - } else { /* -- END TABLES -- */ + $this->SetLineHeight('', $this->table[1][1]['cellLineHeight']); + } else { if (isset($this->blk[$this->blklvl]['line_height']) && $this->blk[$this->blklvl]['line_height']) { $this->SetLineHeight('', $this->blk[$this->blklvl]['line_height']); // sets default line height } @@ -17994,15 +18054,19 @@ function Reset() $this->oldy = -1; $bodystyle = []; + if (isset($this->cssManager->CSS['BODY']['FONT-STYLE'])) { $bodystyle['FONT-STYLE'] = $this->cssManager->CSS['BODY']['FONT-STYLE']; } + if (isset($this->cssManager->CSS['BODY']['FONT-WEIGHT'])) { $bodystyle['FONT-WEIGHT'] = $this->cssManager->CSS['BODY']['FONT-WEIGHT']; } + if (isset($this->cssManager->CSS['BODY']['COLOR'])) { $bodystyle['COLOR'] = $this->cssManager->CSS['BODY']['COLOR']; } + if (isset($bodystyle)) { $this->setCSS($bodystyle, 'BLOCK', 'BODY'); } @@ -26413,14 +26477,14 @@ function WriteBarcode($code, $showtext = 1, $x = '', $y = '', $size = 1, $border /** * POSTAL and OTHER barcodes */ - function WriteBarcode2($code, $x = '', $y = '', $size = 1, $height = 1, $bgcol = false, $col = false, $btype = 'IMB', $print_ratio = '', $k = 1) + function WriteBarcode2($code, $x = '', $y = '', $size = 1, $height = 1, $bgcol = false, $col = false, $btype = 'IMB', $print_ratio = '', $k = 1, $quiet_zone_left = null, $quiet_zone_right = null) { if (empty($code)) { return; } $this->barcode = new Barcode(); - $arrcode = $this->barcode->getBarcodeArray($code, $btype, $print_ratio); + $arrcode = $this->barcode->getBarcodeArray($code, $btype, $print_ratio, $quiet_zone_left, $quiet_zone_right); if (empty($x)) { $x = $this->x; @@ -26887,7 +26951,15 @@ function lesser_entity_decode($html) function AdjustHTML($html, $tabSpaces = 8) { $limit = ini_get('pcre.backtrack_limit'); - if (strlen($html) > $limit) { + + if (0 >= (int) $limit) { + throw new \Mpdf\MpdfException(sprintf( + 'mPDF will not process HTML with disabled pcre.backtrack_limit to prevent unexpected behaviours, please set a positive backtrack limit.', + $limit + )); + } + + if (strlen($html) > (int) $limit) { throw new \Mpdf\MpdfException(sprintf( 'The HTML code size is larger than pcre.backtrack_limit %d. You should use WriteHTML() with smaller string lengths.', $limit @@ -27270,10 +27342,15 @@ function SetPageTemplate($tplidx = '') $this->pageTemplate = $tplidx; } - function SetDocTemplate($file = '', $continue = 0) + function SetDocTemplate($file = '', $continue = 0, $continue2pages = 0) { $this->docTemplate = $file; $this->docTemplateContinue = $continue; + $this->docTemplateContinue2pages = $continue2pages; + + if ($this->docTemplateContinue2pages) { // Enable continue when continue2pages is set + $this->docTemplateContinue = $this->docTemplateContinue2pages; + } } /* -- END IMPORTS -- */ @@ -27330,4 +27407,29 @@ public function _out($s) $this->writer->write($s); } + /** + * @param string $html + * @param string $PAGENO + * @param string $NbPgGp + * @param string $NbPg + * @return string + */ + protected function aliasReplace($html, $PAGENO, $NbPgGp, $NbPg) + { + // Replaces for header and footer + $html = str_replace('{PAGENO}', $PAGENO, $html); + $html = str_replace($this->aliasNbPgGp, $NbPgGp, $html); // {nbpg} + $html = str_replace($this->aliasNbPg, $NbPg, $html); // {nb} + + // Replaces for the body + $html = str_replace(mb_convert_encoding('{PAGENO}', 'UTF-16BE', 'UTF-8'), mb_convert_encoding($PAGENO, 'UTF-16BE', 'UTF-8'), $html); + $html = str_replace(mb_convert_encoding($this->aliasNbPgGp, 'UTF-16BE', 'UTF-8'), mb_convert_encoding($NbPgGp, 'UTF-16BE', 'UTF-8'), $html); // {nbpg} + $html = str_replace(mb_convert_encoding($this->aliasNbPg, 'UTF-16BE', 'UTF-8'), mb_convert_encoding($NbPg, 'UTF-16BE', 'UTF-8'), $html); // {nb} + + // Date replace + $html = preg_replace_callback('/\{DATE\s+(.*?)\}/', [$this, 'date_callback'], $html); // mPDF 5.7 + + return $html; + } + } diff --git a/vendor/mpdf/mpdf/src/Otl.php b/vendor/mpdf/mpdf/src/Otl.php index 46039963..f7e44355 100644 --- a/vendor/mpdf/mpdf/src/Otl.php +++ b/vendor/mpdf/mpdf/src/Otl.php @@ -4364,7 +4364,7 @@ private function _getClassDefinitionTable($offset) $this->seek($offset); $ClassFormat = $this->read_ushort(); $GlyphClass = []; - // $GlyphByClass = array(0=>array()); // NB This forces an index[0] + $GlyphByClass = []; if ($ClassFormat == 1) { $StartGlyph = $this->read_ushort(); $GlyphCount = $this->read_ushort(); @@ -6135,16 +6135,25 @@ private function _getOTLLangTag($ietf, $available) if ($available == '') { return ''; } - $tags = preg_split('/-/', $ietf); + + $tags = $ietf + ? preg_split('/-/', $ietf) + : []; + $lang = ''; $country = ''; $script = ''; - $lang = strtolower($tags[0]); + + $lang = isset($tags[0]) + ? strtolower($tags[0]) + : ''; + if (isset($tags[1]) && $tags[1]) { if (strlen($tags[1]) == 2) { $country = strtolower($tags[1]); } } + if (isset($tags[2]) && $tags[2]) { $country = strtolower($tags[2]); } @@ -6156,6 +6165,7 @@ private function _getOTLLangTag($ietf, $available) } else { $langsys = "DFLT"; } + if (strpos($available, $langsys) === false) { if (strpos($available, "DFLT") !== false) { return "DFLT"; @@ -6163,6 +6173,7 @@ private function _getOTLLangTag($ietf, $available) return ''; } } + return $langsys; } diff --git a/vendor/mpdf/mpdf/src/OtlDump.php b/vendor/mpdf/mpdf/src/OtlDump.php index 8943e3fe..30d0ecfd 100644 --- a/vendor/mpdf/mpdf/src/OtlDump.php +++ b/vendor/mpdf/mpdf/src/OtlDump.php @@ -196,7 +196,7 @@ function getMetrics($file, $fontkey, $TTCfontID = 0, $debug = false, $BMPonly = $this->panose = []; if ($version == 0x4F54544F) { - throw new \Mpdf\Exception\FontException("Postscript outlines are not supported"); + throw new \Mpdf\Exception\FontException(sprintf('Fonts with postscript outlines are not supported (%s)', $file)); } if ($version == 0x74746366 && !$TTCfontID) { @@ -543,7 +543,7 @@ function extractInfo($debug = false, $BMPonly = false, $kerninfo = false, $useOT $c = $psName[$i]; $oc = ord($c); if ($oc > 126 || strpos(' [](){}<>/%', $c) !== false) { - throw new \Mpdf\Exception\FontException("psName=" . $psName . " contains invalid character " . $c . " ie U+" . ord(c)); + throw new \Mpdf\Exception\FontException("psName=" . $psName . " contains invalid character " . $c . " ie U+" . ord($c)); } } } diff --git a/vendor/mpdf/mpdf/src/Pdf/Protection.php b/vendor/mpdf/mpdf/src/Pdf/Protection.php index 8a63da95..d39c77df 100644 --- a/vendor/mpdf/mpdf/src/Pdf/Protection.php +++ b/vendor/mpdf/mpdf/src/Pdf/Protection.php @@ -154,7 +154,7 @@ public function objectKey($n) public function rc4($key, $text) { if ($this->lastRc4Key != $key) { - $k = str_repeat($key, 256 / strlen($key) + 1); + $k = str_repeat($key, round(256 / strlen($key)) + 1); $rc4 = range(0, 255); $j = 0; for ($i = 0; $i < 256; $i++) { diff --git a/vendor/mpdf/mpdf/src/RemoteContentFetcher.php b/vendor/mpdf/mpdf/src/RemoteContentFetcher.php index c2d74a8f..5c016a49 100644 --- a/vendor/mpdf/mpdf/src/RemoteContentFetcher.php +++ b/vendor/mpdf/mpdf/src/RemoteContentFetcher.php @@ -37,6 +37,10 @@ public function getFileContentsByCurl($url) curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->mpdf->curlTimeout); + if ($this->mpdf->curlExecutionTimeout) { + curl_setopt($ch, CURLOPT_TIMEOUT, $this->mpdf->curlExecutionTimeout); + } + if ($this->mpdf->curlFollowLocation) { curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); } @@ -46,7 +50,7 @@ public function getFileContentsByCurl($url) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); } - if (is_file($this->mpdf->curlCaCertificate)) { + if ($this->mpdf->curlCaCertificate && is_file($this->mpdf->curlCaCertificate)) { curl_setopt($ch, CURLOPT_CAINFO, $this->mpdf->curlCaCertificate); } diff --git a/vendor/mpdf/mpdf/src/ServiceFactory.php b/vendor/mpdf/mpdf/src/ServiceFactory.php index 0520d3ad..0962a6c3 100644 --- a/vendor/mpdf/mpdf/src/ServiceFactory.php +++ b/vendor/mpdf/mpdf/src/ServiceFactory.php @@ -5,15 +5,11 @@ use Mpdf\Color\ColorConverter; use Mpdf\Color\ColorModeConverter; use Mpdf\Color\ColorSpaceRestrictor; - use Mpdf\Fonts\FontCache; use Mpdf\Fonts\FontFileFinder; - -use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor; - +use Mpdf\Image\ImageProcessor; use Mpdf\Pdf\Protection; use Mpdf\Pdf\Protection\UniqidGenerator; - use Mpdf\Writer\BaseWriter; use Mpdf\Writer\BackgroundWriter; use Mpdf\Writer\ColorWriter; @@ -25,7 +21,6 @@ use Mpdf\Writer\MetadataWriter; use Mpdf\Writer\OptionalContentWriter; use Mpdf\Writer\PageWriter; - use Mpdf\Writer\ResourceWriter; use Psr\Log\LoggerInterface; @@ -56,12 +51,16 @@ public function getServices( $tableOfContents = new TableOfContents($mpdf, $sizeConverter); - $cache = new Cache($config['tempDir']); - $fontCache = new FontCache(new Cache($config['tempDir'] . '/ttfontdata')); + $cacheBasePath = $config['tempDir'] . '/mpdf'; + + $cache = new Cache($cacheBasePath, $config['cacheCleanupInterval']); + $fontCache = new FontCache(new Cache($cacheBasePath . '/ttfontdata', $config['cacheCleanupInterval'])); $fontFileFinder = new FontFileFinder($config['fontDir']); - $cssManager = new CssManager($mpdf, $cache, $sizeConverter, $colorConverter); + $remoteContentFetcher = new RemoteContentFetcher($mpdf, $logger); + + $cssManager = new CssManager($mpdf, $cache, $sizeConverter, $colorConverter, $remoteContentFetcher); $otl = new Otl($mpdf, $fontCache); @@ -77,8 +76,6 @@ public function getServices( $hyphenator = new Hyphenator($mpdf); - $remoteContentFetcher = new RemoteContentFetcher($mpdf, $logger); - $imageProcessor = new ImageProcessor( $mpdf, $otl, diff --git a/vendor/mpdf/mpdf/src/Shaper/Indic.php b/vendor/mpdf/mpdf/src/Shaper/Indic.php index 28e3001a..ab1d4bbf 100644 --- a/vendor/mpdf/mpdf/src/Shaper/Indic.php +++ b/vendor/mpdf/mpdf/src/Shaper/Indic.php @@ -401,7 +401,7 @@ public static function insert_dotted_circles(&$info, $dottedcircle) // I am not sue how this code below got in here, since $idx should now be > count($info) and thus invalid. // In case I am missing something(!) I'll leave a warning here for now: if (isset($info[$idx])) { - throw new \Mpdf\MpdfException('Unexpected error occured in Indic processing'); + throw new \Mpdf\MpdfException('Unexpected error occurred in Indic processing'); } // In case of final bloken cluster... //$syllable = $info[$idx]['syllable']; diff --git a/vendor/mpdf/mpdf/src/TTFontFile.php b/vendor/mpdf/mpdf/src/TTFontFile.php index fb5ad1ef..642699b5 100644 --- a/vendor/mpdf/mpdf/src/TTFontFile.php +++ b/vendor/mpdf/mpdf/src/TTFontFile.php @@ -265,7 +265,7 @@ public function getMetrics($file, $fontkey, $TTCfontID = 0, $debug = false, $BMP $this->panose = []; if ($version === 0x4F54544F) { - throw new \Mpdf\Exception\FontException('Postscript outlines are not supported'); + throw new \Mpdf\Exception\FontException(sprintf('Fonts with postscript outlines are not supported (%s)', $file)); } if ($version === 0x74746366 && !$TTCfontID) { @@ -518,7 +518,19 @@ function get_chunk($pos, $length) return ''; } - return (fread($this->fh, $length)); + $data = (fread($this->fh, $length)); + + // fix for #1504 + // if fread is used to read from a compressed / buffered stream (e.g. phar://...) + // the $length parameter will be ignored - fread is limited in size (usually 8192 bytes) + // to fix this, the data length must be checked after reading. If the read was incomplete, + // try to read the rest of the data + $dataLen = strlen($data); + while ($dataLen < $length && !feof($this->fh)) { + $data .= fread($this->fh, $length - $dataLen); + $dataLen = strlen($data); + } + return $data; } function get_table($tag) diff --git a/vendor/mpdf/mpdf/src/TTFontFileAnalysis.php b/vendor/mpdf/mpdf/src/TTFontFileAnalysis.php index 2851ea0b..b58fc591 100644 --- a/vendor/mpdf/mpdf/src/TTFontFileAnalysis.php +++ b/vendor/mpdf/mpdf/src/TTFontFileAnalysis.php @@ -27,7 +27,7 @@ function extractCoreInfo($file, $TTCfontID = 0) $this->panose = []; // mPDF 5.0 if ($version == 0x4F54544F) { - throw new \Mpdf\MpdfException('ERROR - NOT ADDED as Postscript outlines are not supported - ' . $file); + throw new \Mpdf\Exception\FontException(sprintf('Fonts with postscript outlines are not supported (%s)', $file)); } if ($version == 0x74746366) { diff --git a/vendor/mpdf/mpdf/src/Tag.php b/vendor/mpdf/mpdf/src/Tag.php index 5c51e317..33d90b6b 100644 --- a/vendor/mpdf/mpdf/src/Tag.php +++ b/vendor/mpdf/mpdf/src/Tag.php @@ -3,11 +3,8 @@ namespace Mpdf; use Mpdf\Strict; - use Mpdf\Color\ColorConverter; - -use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor; - +use Mpdf\Image\ImageProcessor; use Mpdf\Language\LanguageToFontInterface; class Tag diff --git a/vendor/mpdf/mpdf/src/Tag/BarCode.php b/vendor/mpdf/mpdf/src/Tag/BarCode.php index 65edb2a3..44ecd951 100644 --- a/vendor/mpdf/mpdf/src/Tag/BarCode.php +++ b/vendor/mpdf/mpdf/src/Tag/BarCode.php @@ -25,6 +25,8 @@ public function open($attr, &$ahtml, &$ihtml) $objattr['padding_right'] = 0; $objattr['width'] = 0; $objattr['height'] = 0; + $objattr['quiet_l'] = 0; + $objattr['quiet_r'] = 0; $objattr['border_top']['w'] = 0; $objattr['border_bottom']['w'] = 0; $objattr['border_left']['w'] = 0; @@ -67,6 +69,17 @@ public function open($attr, &$ahtml, &$ihtml) } else { $objattr['pr_ratio'] = ''; } + if (isset($attr['QUIET_ZONE_LEFT']) && is_numeric($attr['QUIET_ZONE_LEFT'])) { + $objattr['quiet_zone_left'] = $attr['QUIET_ZONE_LEFT']; + } else { + $objattr['quiet_zone_left'] = null; + } + if (isset($attr['QUIET_ZONE_RIGHT']) && is_numeric($attr['QUIET_ZONE_RIGHT'])) { + $objattr['quiet_zone_right'] = $attr['QUIET_ZONE_RIGHT']; + } else { + $objattr['quiet_zone_right'] = null; + } + $properties = $this->cssManager->MergeCSS('', 'BARCODE', $attr); if (isset($properties ['DISPLAY']) && strtolower($properties ['DISPLAY']) === 'none') { return; @@ -169,10 +182,10 @@ public function open($attr, &$ahtml, &$ihtml) if (in_array($objattr['btype'], ['EAN13', 'ISBN', 'ISSN', 'UPCA', 'UPCE', 'EAN8'])) { $code = preg_replace('/\-/', '', $objattr['code']); - $arrcode = $this->barcode->getBarcodeArray($code, $objattr['btype']); + $arrcode = $this->barcode->getBarcodeArray($code, $objattr['btype'], '', $objattr['quiet_l'], $objattr['quiet_r']); if ($objattr['bsupp'] == 2 || $objattr['bsupp'] == 5) { // EAN-2 or -5 Supplement - $supparrcode = $this->barcode->getBarcodeArray($objattr['bsupp_code'], 'EAN' . $objattr['bsupp']); + $supparrcode = $this->barcode->getBarcodeArray($objattr['bsupp_code'], 'EAN' . $objattr['bsupp'], '', $objattr['quiet_l'], $objattr['quiet_r']); $w = ($arrcode['maxw'] + $arrcode['lightmL'] + $arrcode['lightmR'] + $supparrcode['maxw'] + $supparrcode['sepM']) * $arrcode['nom-X'] * $objattr['bsize']; } else { @@ -200,7 +213,7 @@ public function open($attr, &$ahtml, &$ihtml) } elseif (in_array($objattr['btype'], ['IMB', 'RM4SCC', 'KIX', 'POSTNET', 'PLANET'])) { - $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype']); + $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'], '', $objattr['quiet_l'], $objattr['quiet_r']); $w = ($arrcode['maxw'] * $arrcode['nom-X'] * $objattr['bsize']) + $arrcode['quietL'] + $arrcode['quietR']; $h = ($arrcode['nom-H'] * $objattr['bsize']) + (2 * $arrcode['quietTB']); @@ -209,7 +222,7 @@ public function open($attr, &$ahtml, &$ihtml) 'C39', 'C39+', 'C39E', 'C39E+', 'S25', 'S25+', 'I25', 'I25+', 'I25B', 'I25B+', 'C93', 'MSI', 'MSI+', 'CODABAR', 'CODE11'])) { - $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'], $objattr['pr_ratio']); + $arrcode = $this->barcode->getBarcodeArray($objattr['code'], $objattr['btype'], $objattr['pr_ratio'], $objattr['quiet_zone_left'], $objattr['quiet_zone_right']); $w = ($arrcode['maxw'] + $arrcode['lightmL'] + $arrcode['lightmR']) * $arrcode['nom-X'] * $objattr['bsize']; $h = ((2 * $arrcode['lightTB'] * $arrcode['nom-X']) + $arrcode['nom-H']) * $objattr['bsize'] * $objattr['bheight']; diff --git a/vendor/mpdf/mpdf/src/Tag/BlockTag.php b/vendor/mpdf/mpdf/src/Tag/BlockTag.php index 14e6a644..94a17dc1 100644 --- a/vendor/mpdf/mpdf/src/Tag/BlockTag.php +++ b/vendor/mpdf/mpdf/src/Tag/BlockTag.php @@ -4,7 +4,6 @@ use Mpdf\Conversion\DecToAlpha; use Mpdf\Conversion\DecToRoman; - use Mpdf\Utils\Arrays; use Mpdf\Utils\UtfString; @@ -1066,7 +1065,7 @@ public function close(&$ahtml, &$ihtml) $this->mpdf->pageoutput[$this->mpdf->page] = []; } // mod changes operands to integers before processing - $this->mpdf->y = (($this->mpdf->blk[$this->mpdf->blklvl]['float_endpos'] * 1000) % 1000000) / 1000; + $this->mpdf->y = (round($this->mpdf->blk[$this->mpdf->blklvl]['float_endpos'] * 1000) % 1000000) / 1000; } /* -- END CSS-FLOAT -- */ diff --git a/vendor/mpdf/mpdf/src/Tag/Img.php b/vendor/mpdf/mpdf/src/Tag/Img.php index 8b061bab..5c68099b 100644 --- a/vendor/mpdf/mpdf/src/Tag/Img.php +++ b/vendor/mpdf/mpdf/src/Tag/Img.php @@ -3,7 +3,6 @@ namespace Mpdf\Tag; use Mpdf\Mpdf; -use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor; class Img extends Tag { diff --git a/vendor/mpdf/mpdf/src/Tag/Table.php b/vendor/mpdf/mpdf/src/Tag/Table.php index 8504e515..6a7b427c 100644 --- a/vendor/mpdf/mpdf/src/Tag/Table.php +++ b/vendor/mpdf/mpdf/src/Tag/Table.php @@ -182,10 +182,19 @@ public function open($attr, &$ahtml, &$ihtml) } if (isset($properties['BACKGROUND-COLOR'])) { + if ($table['bgcolor'] === false) { // @todo cleaner initialization + $table['bgcolor'] = []; + } $table['bgcolor'][-1] = $properties['BACKGROUND-COLOR']; } elseif (isset($properties['BACKGROUND'])) { + if ($table['bgcolor'] === false) { + $table['bgcolor'] = []; + } $table['bgcolor'][-1] = $properties['BACKGROUND']; } elseif (isset($attr['BGCOLOR'])) { + if ($table['bgcolor'] === false) { + $table['bgcolor'] = []; + } $table['bgcolor'][-1] = $attr['BGCOLOR']; } diff --git a/vendor/mpdf/mpdf/src/Tag/Tag.php b/vendor/mpdf/mpdf/src/Tag/Tag.php index a75438a4..094b2a46 100644 --- a/vendor/mpdf/mpdf/src/Tag/Tag.php +++ b/vendor/mpdf/mpdf/src/Tag/Tag.php @@ -8,7 +8,7 @@ use Mpdf\Color\ColorConverter; use Mpdf\CssManager; use Mpdf\Form; -use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor; +use Mpdf\Image\ImageProcessor; use Mpdf\Language\LanguageToFontInterface; use Mpdf\Mpdf; use Mpdf\Otl; @@ -61,7 +61,7 @@ abstract class Tag protected $colorConverter; /** - * @var ImageProcessor + * @var \Mpdf\Image\ImageProcessor */ protected $imageProcessor; diff --git a/vendor/mpdf/mpdf/src/Tag/Td.php b/vendor/mpdf/mpdf/src/Tag/Td.php index 47fb978d..d74cc0b8 100644 --- a/vendor/mpdf/mpdf/src/Tag/Td.php +++ b/vendor/mpdf/mpdf/src/Tag/Td.php @@ -57,6 +57,7 @@ public function open($attr, &$ahtml, &$ihtml) $table['simple']['border_details']['T']['style'] = ''; $table['simple']['border_details']['B']['style'] = ''; } elseif (!$this->mpdf->simpleTables) { + $c['border'] = false; $c['border_details']['R']['w'] = 0; $c['border_details']['L']['w'] = 0; @@ -89,14 +90,16 @@ public function open($attr, &$ahtml, &$ihtml) $c['border_details']['cellposdom'] = 0; } - if ($table['va']) { $c['va'] = $table['va']; } + if ($table['txta']) { $c['a'] = $table['txta']; } + if ($this->mpdf->table_border_attr_set && $table['border_details']) { + if (!$this->mpdf->simpleTables) { $c['border_details']['R'] = $table['border_details']['R']; $c['border_details']['L'] = $table['border_details']['L']; @@ -115,20 +118,26 @@ public function open($attr, &$ahtml, &$ihtml) $table['simple']['border'] = $table['border']; } } + // INHERITED THEAD CSS Properties if ($this->mpdf->tablethead) { + if ($this->mpdf->thead_valign_default) { $c['va'] = $this->getAlign($this->mpdf->thead_valign_default); } + if ($this->mpdf->thead_textalign_default) { $c['a'] = $this->getAlign($this->mpdf->thead_textalign_default); } + if ($this->mpdf->thead_font_weight === 'B') { $this->mpdf->SetStyle('B', true); } + if ($this->mpdf->thead_font_style === 'I') { $this->mpdf->SetStyle('I', true); } + if ($this->mpdf->thead_font_smCaps === 'S') { $this->mpdf->textvar |= TextVars::FC_SMALLCAPS; } // mPDF 5.7.1 @@ -397,20 +406,24 @@ public function open($attr, &$ahtml, &$ihtml) $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['s'] = 0; $cs = $rs = 1; - if (isset($attr['COLSPAN']) && $attr['COLSPAN'] > 1) { + if (isset($attr['COLSPAN']) && preg_match('/^\d+$/', $attr['COLSPAN']) && $attr['COLSPAN'] > 1) { $cs = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['colspan'] = $attr['COLSPAN']; } + if ($this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nc'] < $this->mpdf->col + $cs) { $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['nc'] = $this->mpdf->col + $cs; } // following code moved outside if... + for ($l = $this->mpdf->col; $l < $this->mpdf->col + $cs; $l++) { if ($l - $this->mpdf->col) { $this->mpdf->cell[$this->mpdf->row][$l] = 0; } } + if (isset($attr['ROWSPAN']) && $attr['ROWSPAN'] > 1) { $rs = $this->mpdf->cell[$this->mpdf->row][$this->mpdf->col]['rowspan'] = $attr['ROWSPAN']; } + for ($k = $this->mpdf->row; $k < $this->mpdf->row + $rs; $k++) { for ($l = $this->mpdf->col; $l < $this->mpdf->col + $cs; $l++) { if ($k - $this->mpdf->row || $l - $this->mpdf->col) { diff --git a/vendor/mpdf/mpdf/src/Tag/Tr.php b/vendor/mpdf/mpdf/src/Tag/Tr.php index f891df99..24b7749b 100644 --- a/vendor/mpdf/mpdf/src/Tag/Tr.php +++ b/vendor/mpdf/mpdf/src/Tag/Tr.php @@ -34,8 +34,10 @@ public function open($attr, &$ahtml, &$ihtml) } if (isset($properties['BACKGROUND-COLOR'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] : []; $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][$this->mpdf->row] = $properties['BACKGROUND-COLOR']; } elseif (isset($attr['BGCOLOR'])) { + $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] = $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] ? $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'] : []; $this->mpdf->table[$this->mpdf->tableLevel][$this->mpdf->tbctr[$this->mpdf->tableLevel]]['bgcolor'][$this->mpdf->row] = $attr['BGCOLOR']; } diff --git a/vendor/mpdf/mpdf/src/Utils/Arrays.php b/vendor/mpdf/mpdf/src/Utils/Arrays.php index f27c83a4..3c9c3d5a 100644 --- a/vendor/mpdf/mpdf/src/Utils/Arrays.php +++ b/vendor/mpdf/mpdf/src/Utils/Arrays.php @@ -78,12 +78,20 @@ public static function combinations($array, $k) $combinations[] = $combination; $anotherCombination = false; + $resetFromIndex = -1; for ($i = $k - 1; $i >= 0; $i--) { if ($indexes[$i] < $maxIndexes[$i]) { $indexes[$i]++; $anotherCombination = true; break; } + $resetFromIndex = $i; + } + + if ($resetFromIndex > 0) { + for ($i = $resetFromIndex; $i < $k; $i++) { + $indexes[$i] = $indexes[$i - 1] + 1; + } } } while ($anotherCombination); diff --git a/vendor/mpdf/mpdf/src/Writer/BaseWriter.php b/vendor/mpdf/mpdf/src/Writer/BaseWriter.php index 8abff919..80463f8f 100644 --- a/vendor/mpdf/mpdf/src/Writer/BaseWriter.php +++ b/vendor/mpdf/mpdf/src/Writer/BaseWriter.php @@ -3,7 +3,6 @@ namespace Mpdf\Writer; use Mpdf\Strict; - use Mpdf\Mpdf; use Mpdf\Pdf\Protection; diff --git a/vendor/mpdf/mpdf/src/Writer/FontWriter.php b/vendor/mpdf/mpdf/src/Writer/FontWriter.php index 8d6b2cfa..ddc70232 100644 --- a/vendor/mpdf/mpdf/src/Writer/FontWriter.php +++ b/vendor/mpdf/mpdf/src/Writer/FontWriter.php @@ -3,7 +3,6 @@ namespace Mpdf\Writer; use Mpdf\Strict; - use Mpdf\Fonts\FontCache; use Mpdf\Mpdf; use Mpdf\TTFontFile; diff --git a/vendor/mpdf/mpdf/src/Writer/FormWriter.php b/vendor/mpdf/mpdf/src/Writer/FormWriter.php index 609aac5c..88c6f356 100644 --- a/vendor/mpdf/mpdf/src/Writer/FormWriter.php +++ b/vendor/mpdf/mpdf/src/Writer/FormWriter.php @@ -3,7 +3,6 @@ namespace Mpdf\Writer; use Mpdf\Strict; - use Mpdf\Mpdf; final class FormWriter diff --git a/vendor/mpdf/mpdf/src/Writer/MetadataWriter.php b/vendor/mpdf/mpdf/src/Writer/MetadataWriter.php index 01caafc5..a171c732 100644 --- a/vendor/mpdf/mpdf/src/Writer/MetadataWriter.php +++ b/vendor/mpdf/mpdf/src/Writer/MetadataWriter.php @@ -3,7 +3,6 @@ namespace Mpdf\Writer; use Mpdf\Strict; - use Mpdf\Form; use Mpdf\Mpdf; use Mpdf\Pdf\Protection; From bd07ae46b441907a31b7985c326faef05e7df09f Mon Sep 17 00:00:00 2001 From: Eduardo Mozart de Oliveira <2974895+eduardomozart@users.noreply.github.com> Date: Tue, 7 Nov 2023 11:34:17 -0300 Subject: [PATCH 2/2] Replace mPDF ImageProcessor with DW2PDF one --- vendor/mpdf/mpdf/src/ServiceFactory.php | 2 +- vendor/mpdf/mpdf/src/Tag.php | 4 ++-- vendor/mpdf/mpdf/src/Tag/Img.php | 1 + vendor/mpdf/mpdf/src/Tag/Tag.php | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/vendor/mpdf/mpdf/src/ServiceFactory.php b/vendor/mpdf/mpdf/src/ServiceFactory.php index 0962a6c3..1e776346 100644 --- a/vendor/mpdf/mpdf/src/ServiceFactory.php +++ b/vendor/mpdf/mpdf/src/ServiceFactory.php @@ -7,7 +7,7 @@ use Mpdf\Color\ColorSpaceRestrictor; use Mpdf\Fonts\FontCache; use Mpdf\Fonts\FontFileFinder; -use Mpdf\Image\ImageProcessor; +use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor; use Mpdf\Pdf\Protection; use Mpdf\Pdf\Protection\UniqidGenerator; use Mpdf\Writer\BaseWriter; diff --git a/vendor/mpdf/mpdf/src/Tag.php b/vendor/mpdf/mpdf/src/Tag.php index 33d90b6b..a9081413 100644 --- a/vendor/mpdf/mpdf/src/Tag.php +++ b/vendor/mpdf/mpdf/src/Tag.php @@ -4,7 +4,7 @@ use Mpdf\Strict; use Mpdf\Color\ColorConverter; -use Mpdf\Image\ImageProcessor; +use \dokuwiki\plugin\dw2pdf\DokuImageProcessorDecorator as ImageProcessor; use Mpdf\Language\LanguageToFontInterface; class Tag @@ -53,7 +53,7 @@ class Tag private $colorConverter; /** - * @var \Mpdf\Image\ImageProcessor + * @var ImageProcessor */ private $imageProcessor; diff --git a/vendor/mpdf/mpdf/src/Tag/Img.php b/vendor/mpdf/mpdf/src/Tag/Img.php index 5c68099b..30b357d0 100644 --- a/vendor/mpdf/mpdf/src/Tag/Img.php +++ b/vendor/mpdf/mpdf/src/Tag/Img.php @@ -1,6 +1,7 @@