From f020d1e06395029b33141e35e51424e3616650d4 Mon Sep 17 00:00:00 2001 From: Andrei Bintintan Date: Thu, 4 Jun 2026 18:15:47 +0200 Subject: [PATCH] Fix Table Borders --- composer.json | 1 + composer.lock | 882 +++++++++++++++++- examples/Fpdf/example-table-4-override.pdf | Bin 21838 -> 21838 bytes examples/Fpdf/example-table-5-row-height.pdf | Bin 21950 -> 21950 bytes examples/Tcpdf/example-table-4-override.pdf | Bin 41799 -> 41799 bytes examples/Tcpdf/example-table-5-row-height.pdf | Bin 42568 -> 42568 bytes examples/Tfpdf/example-table-4-override.pdf | Bin 36282 -> 36282 bytes examples/Tfpdf/example-table-5-row-height.pdf | Bin 36394 -> 36394 bytes src/Table.php | 25 - src/Table/Cell/CellAbstract.php | 91 +- src/Table/Cell/CellInterface.php | 2 +- src/Tools.php | 6 +- tests/Unit/ToolsTest.php | 17 + .../dev/Fpdf/multi-page-draw-table-model1.png | Bin 234077 -> 234077 bytes .../dev/Fpdf/multi-page-draw-table-model2.png | Bin 199287 -> 199287 bytes .../dev/Fpdf/multi-page-draw-table-model3.png | Bin 199287 -> 199287 bytes .../_files/dev/Fpdf/test-multicell-align.png | Bin 204646 -> 204646 bytes .../dev/Fpdf/test-multicell-shrinking.png | Bin 366444 -> 366444 bytes .../dev/Fpdf/test-multicell-shrinking2.png | Bin 343803 -> 343803 bytes .../_files/dev/Fpdf/test-multicell-style.png | Bin 281374 -> 281374 bytes .../Tcpdf/multi-page-draw-table-model1.png | Bin 229427 -> 229427 bytes .../Tcpdf/multi-page-draw-table-model2.png | Bin 198155 -> 198155 bytes .../Tcpdf/multi-page-draw-table-model3.png | Bin 198155 -> 198155 bytes .../_files/dev/Tcpdf/test-multicell-align.png | Bin 201523 -> 201523 bytes .../dev/Tcpdf/test-multicell-shrinking.png | Bin 362118 -> 362118 bytes .../dev/Tcpdf/test-multicell-shrinking2.png | Bin 340957 -> 340957 bytes .../_files/dev/Tcpdf/test-multicell-style.png | Bin 278329 -> 278329 bytes .../Tfpdf/multi-page-draw-table-model1.png | Bin 234077 -> 234077 bytes .../Tfpdf/multi-page-draw-table-model2.png | Bin 199287 -> 199287 bytes .../Tfpdf/multi-page-draw-table-model3.png | Bin 169430 -> 199287 bytes .../_files/dev/Tfpdf/test-multicell-align.png | Bin 204640 -> 204640 bytes .../dev/Tfpdf/test-multicell-shrinking.png | Bin 366444 -> 366444 bytes .../dev/Tfpdf/test-multicell-shrinking2.png | Bin 343803 -> 343803 bytes .../_files/dev/Tfpdf/test-multicell-style.png | Bin 281522 -> 281522 bytes 34 files changed, 920 insertions(+), 104 deletions(-) diff --git a/composer.json b/composer.json index f103f49..6e4997c 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ }, "require-dev": { "ext-json": "*", + "illuminate/support": "^9.52", "setasign/fpdf": "^1.8.6", "tecnickcom/tcpdf": "^6.7.0", "setasign/tfpdf": "^1.33.0", diff --git a/composer.lock b/composer.lock index 343fec6..c52deae 100644 --- a/composer.lock +++ b/composer.lock @@ -4,9 +4,78 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "585c3de3abe718e3e7ef3771fc39d8b5", + "content-hash": "8eb6f9498df4d97ab691e4ec50c5d76b", "packages": [], "packages-dev": [ + { + "name": "carbonphp/carbon-doctrine-types", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon-doctrine-types.git", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon-doctrine-types/zipball/99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "reference": "99f76ffa36cce3b70a4a6abce41dba15ca2e84cb", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "conflict": { + "doctrine/dbal": "<3.7.0 || >=4.0.0" + }, + "require-dev": { + "doctrine/dbal": "^3.7.0", + "nesbot/carbon": "^2.71.0 || ^3.0.0", + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon\\Doctrine\\": "src/Carbon/Doctrine/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "KyleKatarn", + "email": "kylekatarnls@gmail.com" + } + ], + "description": "Types to use Carbon in Doctrine", + "keywords": [ + "carbon", + "date", + "datetime", + "doctrine", + "time" + ], + "support": { + "issues": "https://github.com/CarbonPHP/carbon-doctrine-types/issues", + "source": "https://github.com/CarbonPHP/carbon-doctrine-types/tree/2.1.0" + }, + "funding": [ + { + "url": "https://github.com/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon", + "type": "open_collective" + }, + { + "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "type": "tidelift" + } + ], + "time": "2023-12-11T17:09:12+00:00" + }, { "name": "composer/pcre", "version": "3.3.2", @@ -152,6 +221,96 @@ ], "time": "2024-05-06T16:37:16+00:00" }, + { + "name": "doctrine/inflector", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "reference": "6d6c96277ea252fc1304627204c3d5e6e15faa3b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^12.0 || ^13.0", + "phpstan/phpstan": "^1.12 || ^2.0", + "phpstan/phpstan-phpunit": "^1.4 || ^2.0", + "phpstan/phpstan-strict-rules": "^1.6 || ^2.0", + "phpunit/phpunit": "^8.5 || ^12.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Inflector\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", + "keywords": [ + "inflection", + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" + ], + "support": { + "issues": "https://github.com/doctrine/inflector/issues", + "source": "https://github.com/doctrine/inflector/tree/2.1.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2025-08-10T19:31:58+00:00" + }, { "name": "doctrine/instantiator", "version": "1.5.0", @@ -222,6 +381,272 @@ ], "time": "2022-12-30T00:15:36+00:00" }, + { + "name": "illuminate/collections", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/collections.git", + "reference": "d3710b0b244bfc62c288c1a87eaa62dd28352d1f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/collections/zipball/d3710b0b244bfc62c288c1a87eaa62dd28352d1f", + "reference": "d3710b0b244bfc62c288c1a87eaa62dd28352d1f", + "shasum": "" + }, + "require": { + "illuminate/conditionable": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/macroable": "^9.0", + "php": "^8.0.2" + }, + "suggest": { + "symfony/var-dumper": "Required to use the dump method (^6.0)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Collections package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-06-11T21:17:10+00:00" + }, + { + "name": "illuminate/conditionable", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/conditionable.git", + "reference": "bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/conditionable/zipball/bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364", + "reference": "bea24daa0fa84b7e7b0d5b84f62c71b7e2dc3364", + "shasum": "" + }, + "require": { + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Conditionable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-02-01T21:42:32+00:00" + }, + { + "name": "illuminate/contracts", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/contracts.git", + "reference": "44f65d723b13823baa02ff69751a5948bde60c22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/contracts/zipball/44f65d723b13823baa02ff69751a5948bde60c22", + "reference": "44f65d723b13823baa02ff69751a5948bde60c22", + "shasum": "" + }, + "require": { + "php": "^8.0.2", + "psr/container": "^1.1.1|^2.0.1", + "psr/simple-cache": "^1.0|^2.0|^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Contracts\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Contracts package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-02-08T14:36:30+00:00" + }, + { + "name": "illuminate/macroable", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/macroable.git", + "reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/macroable/zipball/e3bfaf6401742a9c6abca61b9b10e998e5b6449a", + "reference": "e3bfaf6401742a9c6abca61b9b10e998e5b6449a", + "shasum": "" + }, + "require": { + "php": "^8.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Macroable package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2022-08-09T13:29:29+00:00" + }, + { + "name": "illuminate/support", + "version": "v9.52.16", + "source": { + "type": "git", + "url": "https://github.com/illuminate/support.git", + "reference": "223c608dbca27232df6213f776bfe7bdeec24874" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/illuminate/support/zipball/223c608dbca27232df6213f776bfe7bdeec24874", + "reference": "223c608dbca27232df6213f776bfe7bdeec24874", + "shasum": "" + }, + "require": { + "doctrine/inflector": "^2.0", + "ext-ctype": "*", + "ext-filter": "*", + "ext-mbstring": "*", + "illuminate/collections": "^9.0", + "illuminate/conditionable": "^9.0", + "illuminate/contracts": "^9.0", + "illuminate/macroable": "^9.0", + "nesbot/carbon": "^2.62.1", + "php": "^8.0.2", + "voku/portable-ascii": "^2.0" + }, + "conflict": { + "tightenco/collect": "<5.5.33" + }, + "suggest": { + "illuminate/filesystem": "Required to use the composer class (^9.0).", + "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.0.2).", + "ramsey/uuid": "Required to use Str::uuid() (^4.7).", + "symfony/process": "Required to use the composer class (^6.0).", + "symfony/uid": "Required to use Str::ulid() (^6.0).", + "symfony/var-dumper": "Required to use the dd function (^6.0).", + "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.4.1)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "files": [ + "helpers.php" + ], + "psr-4": { + "Illuminate\\Support\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "The Illuminate Support package.", + "homepage": "https://laravel.com", + "support": { + "issues": "https://github.com/laravel/framework/issues", + "source": "https://github.com/laravel/framework" + }, + "time": "2023-06-11T21:11:53+00:00" + }, { "name": "myclabs/deep-copy", "version": "1.13.4", @@ -280,7 +705,114 @@ "type": "tidelift" } ], - "time": "2025-08-01T08:46:24+00:00" + "time": "2025-08-01T08:46:24+00:00" + }, + { + "name": "nesbot/carbon", + "version": "2.73.0", + "source": { + "type": "git", + "url": "https://github.com/CarbonPHP/carbon.git", + "reference": "9228ce90e1035ff2f0db84b40ec2e023ed802075" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/9228ce90e1035ff2f0db84b40ec2e023ed802075", + "reference": "9228ce90e1035ff2f0db84b40ec2e023ed802075", + "shasum": "" + }, + "require": { + "carbonphp/carbon-doctrine-types": "*", + "ext-json": "*", + "php": "^7.1.8 || ^8.0", + "psr/clock": "^1.0", + "symfony/polyfill-mbstring": "^1.0", + "symfony/polyfill-php80": "^1.16", + "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" + }, + "provide": { + "psr/clock-implementation": "1.0" + }, + "require-dev": { + "doctrine/dbal": "^2.0 || ^3.1.4 || ^4.0", + "doctrine/orm": "^2.7 || ^3.0", + "friendsofphp/php-cs-fixer": "^3.0", + "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "<6", + "phpmd/phpmd": "^2.9", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", + "squizlabs/php_codesniffer": "^3.4" + }, + "bin": [ + "bin/carbon" + ], + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Carbon\\Laravel\\ServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + }, + "branch-alias": { + "dev-2.x": "2.x-dev", + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Carbon\\": "src/Carbon/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Brian Nesbitt", + "email": "brian@nesbot.com", + "homepage": "https://markido.com" + }, + { + "name": "kylekatarnls", + "homepage": "https://github.com/kylekatarnls" + } + ], + "description": "An API extension for DateTime that supports 281 different languages.", + "homepage": "https://carbon.nesbot.com", + "keywords": [ + "date", + "datetime", + "time" + ], + "support": { + "docs": "https://carbon.nesbot.com/docs", + "issues": "https://github.com/briannesbitt/Carbon/issues", + "source": "https://github.com/briannesbitt/Carbon" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" + }, + { + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", + "type": "tidelift" + } + ], + "time": "2025-01-08T20:10:23+00:00" }, { "name": "nikic/php-parser", @@ -1232,6 +1764,54 @@ ], "time": "2026-01-27T05:45:00+00:00" }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, { "name": "psr/container", "version": "2.0.2", @@ -1335,6 +1915,57 @@ }, "time": "2024-09-11T13:17:53+00:00" }, + { + "name": "psr/simple-cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/simple-cache.git", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", + "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\SimpleCache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interfaces for simple caching", + "keywords": [ + "cache", + "caching", + "psr", + "psr-16", + "simple-cache" + ], + "support": { + "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + }, + "time": "2021-10-29T13:26:27+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.2", @@ -3301,6 +3932,179 @@ ], "time": "2022-05-30T19:17:58+00:00" }, + { + "name": "symfony/translation", + "version": "v6.0.19", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation.git", + "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation/zipball/9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "reference": "9c24b3fdbbe9fb2ef3a6afd8bbaadfd72dad681f", + "shasum": "" + }, + "require": { + "php": ">=8.0.2", + "symfony/polyfill-mbstring": "~1.0", + "symfony/translation-contracts": "^2.3|^3.0" + }, + "conflict": { + "symfony/config": "<5.4", + "symfony/console": "<5.4", + "symfony/dependency-injection": "<5.4", + "symfony/http-kernel": "<5.4", + "symfony/twig-bundle": "<5.4", + "symfony/yaml": "<5.4" + }, + "provide": { + "symfony/translation-implementation": "2.3|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/console": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/finder": "^5.4|^6.0", + "symfony/http-client-contracts": "^1.1|^2.0|^3.0", + "symfony/http-kernel": "^5.4|^6.0", + "symfony/intl": "^5.4|^6.0", + "symfony/polyfill-intl-icu": "^1.21", + "symfony/service-contracts": "^1.1.2|^2|^3", + "symfony/yaml": "^5.4|^6.0" + }, + "suggest": { + "psr/log-implementation": "To use logging capability in translator", + "symfony/config": "", + "symfony/yaml": "" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\Translation\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools to internationalize your application", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/translation/tree/v6.0.19" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-01-01T08:36:10+00:00" + }, + { + "name": "symfony/translation-contracts", + "version": "v3.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/translation-contracts.git", + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", + "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", + "shasum": "" + }, + "require": { + "php": ">=8.0.2" + }, + "suggest": { + "symfony/translation-implementation": "" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Translation\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to translation", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-06-27T17:10:44+00:00" + }, { "name": "tecnickcom/tcpdf", "version": "6.11.3", @@ -3509,6 +4313,80 @@ } ], "time": "2022-10-16T00:51:09+00:00" + }, + { + "name": "voku/portable-ascii", + "version": "2.1.1", + "source": { + "type": "git", + "url": "https://github.com/voku/portable-ascii.git", + "reference": "8e1051fe39379367aecf014f41744ce7539a856f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/voku/portable-ascii/zipball/8e1051fe39379367aecf014f41744ce7539a856f", + "reference": "8e1051fe39379367aecf014f41744ce7539a856f", + "shasum": "" + }, + "require": { + "php": ">=7.1.0" + }, + "require-dev": { + "phpunit/phpunit": "~8.5 || ~9.6 || ~10.5 || ~11.5" + }, + "suggest": { + "ext-intl": "Use Intl for transliterator_transliterate() support" + }, + "type": "library", + "autoload": { + "psr-4": { + "voku\\": "src/voku/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Lars Moelleken", + "homepage": "https://www.moelleken.org/" + } + ], + "description": "Portable ASCII library - performance optimized (ascii) string functions for php.", + "homepage": "https://github.com/voku/portable-ascii", + "keywords": [ + "ascii", + "clean", + "php" + ], + "support": { + "issues": "https://github.com/voku/portable-ascii/issues", + "source": "https://github.com/voku/portable-ascii/tree/2.1.1" + }, + "funding": [ + { + "url": "https://www.paypal.me/moelleken", + "type": "custom" + }, + { + "url": "https://github.com/voku", + "type": "github" + }, + { + "url": "https://opencollective.com/portable-ascii", + "type": "open_collective" + }, + { + "url": "https://www.patreon.com/voku", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/voku/portable-ascii", + "type": "tidelift" + } + ], + "time": "2026-04-26T05:33:54+00:00" } ], "aliases": [], diff --git a/examples/Fpdf/example-table-4-override.pdf b/examples/Fpdf/example-table-4-override.pdf index d137d13dd8562327cf6f6a9f50f0ef6334048bee..e6c1653742f289815bedb0353b460d571778594c 100644 GIT binary patch delta 37 lcmX@Nit*ek#tn(gEarL!hLcm7cR(15EX%-*&8JzK0|4zl3(Eii delta 37 lcmX@Nit*ek#tn(gEM|Jf29r~ncR(15EX%-*&8JzK0|4!73(f!l diff --git a/examples/Fpdf/example-table-5-row-height.pdf b/examples/Fpdf/example-table-5-row-height.pdf index 5b71e1d2172911a1ee7e164a2410291a32325c73..9a1de0ccf53fd7bbec3f13ef53be31408ef8f5c5 100644 GIT binary patch delta 37 mcmdnDnsMK1#tkLREarL!hLbCpcR&~>EX%-*&G%Ry1ONc;>EX%-*&G%Ry1ONc<84Otf diff --git a/examples/Tcpdf/example-table-4-override.pdf b/examples/Tcpdf/example-table-4-override.pdf index c2e59a27a531aa72d76c12d138fddb09f0bef47e..ca66ab87fd9228df96f573e4686a2ecb0e1c9b5d 100644 GIT binary patch delta 43 zcmV+`0M!4-#sbI20rVY2b`ONf;EG>-;jTMSg71FpS>x+tQ{?GlKi329S`5hlKGlKV1&~G9D DaD5XP diff --git a/examples/Tcpdf/example-table-5-row-height.pdf b/examples/Tcpdf/example-table-5-row-height.pdf index 7d4027ff92814ec785550804178a598fff7c28f7..0f383eee504ff0c8d64399f2d6556b6f152a03e6 100644 GIT binary patch delta 36 rcmX?chUvr^rVXFCC)*hEZ2rgnpJ{TvDbHq3ejuY)mS?kwkjWGPFb@u_ delta 51 ocmX?chUvr^rVXFCIn4BoEG>-;jW_?|W@bk4Sox880zwv30H*>C_y7O^ diff --git a/examples/Tfpdf/example-table-4-override.pdf b/examples/Tfpdf/example-table-4-override.pdf index b3e6d3f23628574e85f65895995d36fde9b42c59..b40771f7d4b58c957bb7cfc2f1dca960480ac93b 100644 GIT binary patch delta 37 mcmdlrn`zfEX%-*&G%S*IsxRV3%39O delta 37 lcmZ2AhiTOurVS;`EM|Jf29qn8cR&~>EX%-*&G%S*IsxR?3%URR diff --git a/src/Table.php b/src/Table.php index 3d3eb83..bef659f 100644 --- a/src/Table.php +++ b/src/Table.php @@ -1414,9 +1414,6 @@ protected function cachePrepOutputData() $count = count($dataCache); - /** @var CellInterface[] $prevRowData */ - $prevRowData = null; - for ($k = 0; $k < $count; $k++) { $val = &$dataCache[$k]; @@ -1426,7 +1423,6 @@ protected function cachePrepOutputData() if ($val['DATATYPE'] == 'new_page') { //add a new page $this->addPage(); - $prevRowData = null; // page break resets adjacent-row tracking continue; } @@ -1450,25 +1446,6 @@ protected function cachePrepOutputData() $cell->setCellDrawHeight($val['HEIGHT']); } - // Inform the cell whether an already-rendered adjacent border - // sits on its top / left edge so the fill inset can be adjusted. - if (method_exists($cell, 'setAdjacentBorderTop')) { - $cell->setAdjacentBorderTop( - $prevRowData !== null - && isset($prevRowData[$i]) - && method_exists($prevRowData[$i], 'borderIncludesSide') - && $prevRowData[$i]->borderIncludesSide('B') - ); - } - if (method_exists($cell, 'setAdjacentBorderLeft')) { - $cell->setAdjacentBorderLeft( - $i > 0 - && isset($data[$i - 1]) - && method_exists($data[$i - 1], 'borderIncludesSide') - && $data[$i - 1]->borderIncludesSide('R') - ); - } - $cell->render(); } @@ -1477,8 +1454,6 @@ protected function cachePrepOutputData() //if we have colspan, just ignore the next cells } - $prevRowData = $data; - $this->dataOnCurrentPage = true; //Go to the next line diff --git a/src/Table/Cell/CellAbstract.php b/src/Table/Cell/CellAbstract.php index 9aa20dd..aa407de 100644 --- a/src/Table/Cell/CellAbstract.php +++ b/src/Table/Cell/CellAbstract.php @@ -69,7 +69,7 @@ abstract class CellAbstract implements CellInterface */ protected $paddingLeft = 0; - protected $backgroundColor = [255, 255, 255]; + protected $backgroundColor = false; /** * @var string|int @@ -169,18 +169,6 @@ abstract class CellAbstract implements CellInterface */ protected $bSkip = false; - /** - * Whether the adjacent cell above has a bottom border (set by the table renderer). - * Used to protect that border from being covered by this cell's fill. - */ - protected bool $adjacentBorderTop = false; - - /** - * Whether the adjacent cell to the left has a right border (set by the table renderer). - * Used to protect that border from being covered by this cell's fill. - */ - protected bool $adjacentBorderLeft = false; - public function __construct($pdf) { if ($pdf instanceof PdfInterface) { @@ -406,32 +394,6 @@ public function getSkipped(): bool return $this->bSkip; } - public function setAdjacentBorderTop(bool $value): void - { - $this->adjacentBorderTop = $value; - } - - public function setAdjacentBorderLeft(bool $value): void - { - $this->adjacentBorderLeft = $value; - } - - /** - * Returns true if this cell's border type includes the given side ('T', 'B', 'L', 'R'). - */ - public function borderIncludesSide(string $side): bool - { - $bt = $this->getBorderType(); - if ($bt === 1 || $bt === '1') { - return true; - } - if ($bt === 0 || $bt === '0' || $bt === '') { - return false; - } - - return strpos((string) $bt, $side) !== false; - } - public function __get($property) { if (isset($this->properties[$property])) { @@ -486,50 +448,29 @@ public function renderCellLayout() $this->pdf->SetDrawColor($r, $g, $b); $borderType = $this->getBorderType(); - $width = $this->getCellDrawWidth(); - $height = $this->getCellDrawHeight(); - $borderSize = $this->getBorderSize(); - - // For any border type other than 0 (no border) or 1 (all borders with Cell()), - // draw manually to avoid overwriting adjacent borders - if ($borderType !== 0 && $borderType !== '0' && $borderType !== 1 && $borderType !== '1') { - $borderStr = (string) $borderType; - $hasTop = strpos($borderStr, 'T') !== false; - $hasBottom = strpos($borderStr, 'B') !== false; - $hasLeft = strpos($borderStr, 'L') !== false; - $hasRight = strpos($borderStr, 'R') !== false; - - // Inset on sides that have a border on THIS cell, or where an adjacent - // cell already drew a border on the shared edge (to avoid covering it). + + // For single-sided borders, draw manually to avoid corner artifacts and overlap issues + if ($borderType === 'B' || $borderType === 'T' || $borderType === 'L' || $borderType === 'R') { + $width = $this->getCellDrawWidth(); + $height = $this->getCellDrawHeight(); + + // Draw background using Rect to avoid overwriting adjacent borders if (! $this->isTransparent()) { - $insetLeft = ($hasLeft || $this->adjacentBorderLeft) ? $borderSize / 2 : 0; - $insetRight = $hasRight ? $borderSize / 2 : 0; - $insetTop = ($hasTop || $this->adjacentBorderTop) ? $borderSize / 2 : 0; - $insetBottom = $hasBottom ? $borderSize / 2 : 0; - $this->pdf->Rect( - $x + $insetLeft, - $y + $insetTop, - max(0, $width - $insetLeft - $insetRight), - max(0, $height - $insetTop - $insetBottom), - 'F' - ); + $this->pdf->Rect($x, $y, $width, $height, 'F'); } - // Manually draw each requested border side - if ($hasTop) { - $this->pdf->Line($x, $y, $x + $width, $y); - } - if ($hasBottom) { + // Manually draw the specific border + if ($borderType === 'B') { $this->pdf->Line($x, $y + $height, $x + $width, $y + $height); - } - if ($hasLeft) { + } elseif ($borderType === 'T') { + $this->pdf->Line($x, $y, $x + $width, $y); + } elseif ($borderType === 'L') { $this->pdf->Line($x, $y, $x, $y + $height); - } - if ($hasRight) { + } elseif ($borderType === 'R') { $this->pdf->Line($x + $width, $y, $x + $width, $y + $height); } } else { - // For 0 (no border) or 1 (all sides), use standard Cell() + // For other border types (all sides, combinations), use standard Cell() $this->pdf->Cell( $this->getCellDrawWidth(), $this->getCellDrawHeight(), diff --git a/src/Table/Cell/CellInterface.php b/src/Table/Cell/CellInterface.php index a8c7cb1..e4d3607 100644 --- a/src/Table/Cell/CellInterface.php +++ b/src/Table/Cell/CellInterface.php @@ -172,7 +172,7 @@ public function getBorderType(); /** * Sets the Border Color. - * If the value is set to FALSE, 0 or '0' then we assume transparency + * If the value is set to FALSE, 0, '0' or NULL then we assume transparency * * @param int|bool|array $r */ diff --git a/src/Tools.php b/src/Tools.php index a240c11..db736b3 100644 --- a/src/Tools.php +++ b/src/Tools.php @@ -112,7 +112,7 @@ public static function makeArray($value): array } /** - * Returns TRUE if value is FALSE(0, '0', FALSE) + * Returns TRUE if value is FALSE(0, '0', FALSE, NULL) * * @param mixed $value */ @@ -122,6 +122,10 @@ public static function isFalse($value): bool return true; } + if (null === $value) { + return true; + } + if (0 === $value) { return true; } diff --git a/tests/Unit/ToolsTest.php b/tests/Unit/ToolsTest.php index 94eaf23..2cc620d 100644 --- a/tests/Unit/ToolsTest.php +++ b/tests/Unit/ToolsTest.php @@ -48,4 +48,21 @@ public function testHex2rgb(): void $this->assertSame(null, Tools::hex2rgb('#f4')); $this->assertSame(null, Tools::hex2rgb('f489')); } + + public function testIsFalse(): void + { + // Test false values + $this->assertTrue(Tools::isFalse(false)); + $this->assertTrue(Tools::isFalse(0)); + $this->assertTrue(Tools::isFalse('0')); + $this->assertTrue(Tools::isFalse(null)); + + // Test non-false values + $this->assertFalse(Tools::isFalse(true)); + $this->assertFalse(Tools::isFalse(1)); + $this->assertFalse(Tools::isFalse('1')); + $this->assertFalse(Tools::isFalse('')); + $this->assertFalse(Tools::isFalse([])); + $this->assertFalse(Tools::isFalse([255, 255, 255])); + } } diff --git a/tests/_files/dev/Fpdf/multi-page-draw-table-model1.png b/tests/_files/dev/Fpdf/multi-page-draw-table-model1.png index 62e199c374b0213acd8807ec4a5c53f1973d1c53..c4398d4f0b580070b98fbe6c44db5b9ad5e0ea5b 100644 GIT binary patch delta 101 zcmcb+gzxSWz73l=*#&rIjx8uWxOpe%5-veAD??)|BXey711kfA<$)5llk-FrP(`ot kEI2rMzKAkZ)B>WmJn-Z9=F1}Omqi$Xm}&cE5$3L10ILEaoB#j- delta 101 zcmcb+gzxSWz73l=+48Wo&6>V5DteU}a!1BW}%;$$26QsG={K hMIt887g2_a8bj1dB-$A_UlwVXA9m)Uz diff --git a/tests/_files/dev/Fpdf/multi-page-draw-table-model3.png b/tests/_files/dev/Fpdf/multi-page-draw-table-model3.png index d6fbe14ef52066b3b02fceb89c014b4ed017f6d5..bf11188a1ab3f6fba7b72f720e7ff4af70e9890a 100644 GIT binary patch delta 97 zcmex9h3ESeo(-Eg*#&qNUY_T5+q{!=374Rmm7%efv7xqsft7&)hqms`$$26QsG^l+ fQ&T6;7g0tP)l1&8tNF4>`(+Wv?UzNEmV5;O)9fDA delta 97 zcmex9h3ESeo(-Eg+4374RWm9eFjftj{}ft7(lj$p_4$$26QsG_ny h2HunBizuUtdPNFOX}&Ddep!SOh?%xu7Ga*u1pr!V9+Ut8 diff --git a/tests/_files/dev/Fpdf/test-multicell-shrinking.png b/tests/_files/dev/Fpdf/test-multicell-shrinking.png index 0635cb34b5758a59b3cc15ff97ff6d3684fd780b..c2534541b1e49bed502e2d149561341dc277adad 100644 GIT binary patch delta 109 zcmaE}PVCJ(u??Fz*#&sj7}l&P-n^4@374Rmm7%efvAMQ^ft7(l_HT*Dlk-FrP(`Jd mEr_2yUql&I)OT}ZL-S>k_RAuSK+FWh%s|Yt{jvz_%q9S&LnE^Q delta 109 zcmaE}PVCJ(u??Fz+4DK+LlJvIwh&762nWBw+vm delta 109 zcmezUSLF9!kqw(T+41$>z%o{c!3~=@*#&qtCkStSw0S4z5-veAD??)|69a7n11kfAB{TI)Cg+JLpo(5S kGX2El`69}wqD>dKi8o&sX}>JO2*gZ4%)I@w2#dEF00I~y3jhEB delta 105 zcmbO?O>o{c!3~=@+4yt-n^4@374RWm9eFjp|Q4sft7*5r{?A7Cg+JLpo%u% klP{V)Uql&I^vY?wwau4B+AoVR0x=U1GjG2v!s2ZP03+HWfdBvi diff --git a/tests/_files/dev/Tcpdf/multi-page-draw-table-model1.png b/tests/_files/dev/Tcpdf/multi-page-draw-table-model1.png index 305122de5c3a19ce9308e18ac504c9f59c8cc928..631e4031bd5375884c01b0b720564303ecf1e84d 100644 GIT binary patch delta 99 zcmdnoz_+=9Z$bmR0IznP?3HsH+o!P!npqhdTbUSX8yHv_7#OqJ#ZJ~^S3nhYif(&2 eIi6h^RaDe(xn1*Q_V&r_j6lq^eKI@qf(ihR2^-@8 delta 99 zcmdnoz_+=9Z$bk*pQ_I4If;8WwohXdG_f)^w=yx-HZZU$vARwgFe1_o9J1_9T&(f^ViDBZ#_GxT_CRWDgRwky}1_o9J2FI(`C{Na7SAdF|K}6fn f^D#}1XIDlQy>LtaZu4aJ_Q~vw+b6R#Rr~`0A_yEv diff --git a/tests/_files/dev/Tcpdf/multi-page-draw-table-model3.png b/tests/_files/dev/Tcpdf/multi-page-draw-table-model3.png index d55b4fc148cac4acddd14ec03c926be4833f8139..298dd69ce5f962cb5683975495de6be3b15420b6 100644 GIT binary patch delta 95 zcmeC~;py(-nb5#4z^lhsuHd+_eHxpfnU$fjm5G_Qfq|8Q!EsM1zsY*+3aFynL>7IT c9M7(dD*BMIS+{vId;4T|#_f~YnJWGP0Nq*|;Q#;t delta 95 zcmeC~;py(-nb5$_r)sc&uI;Cd?bFx&a;0TF$s ieRKWfcy?t}(T#RL3YsUgw@+qg1Y)M`li8UUa03A13>~}x delta 99 zcmdnIjA!#Qo(T=?e5yu)lVk2}Y@fy^Xkuk-Ze?PrZD3$!V8C$eSomZ;b_GIAio6x{6z-#hZ^rrR3_GxT_W>$vAR;Gs91_o9J2IpK<;wI~{D?mk!AfkOA m+v+FBvn!*D-h8rrLGxtx_Q~vwK+FWh%s|YteKI@i=Q;q}A0a&e delta 107 zcmZqc6>IAio6x|{r)n1VZ^rSB?bFx({8qpkP! mtNPJRf!d delta 107 zcmccnT;%R^kqHg#e5w{3-L@Xs*glO-(8S8v+{)Bc+rYrez<~S0n!S_t*cDJkt9nHk kC&#lZql)UzFum72nZ127J0lP?0WmWWvuvNt&g!KD09{NVJOBUy diff --git a/tests/_files/dev/Tcpdf/test-multicell-style.png b/tests/_files/dev/Tcpdf/test-multicell-style.png index 3fcb807ebd0d93346b2bb9f77dbf1a3c0ce11fa1..434ee19c4f580cc1496dae80b55c828a7966219e 100644 GIT binary patch delta 103 zcmdn_PhjUife8)l0=yQ#7Ecw}*glO-(9Fuv*viyY+rYpIh`1SiC+o2*po)5j?f5u3 go?RJLRK|IxUh`!3_Q~vwK+FWh%-bikvn(?Q0Bai^*#H0l delta 103 zcmdn_PhjUife8)le5#hm99zRSwohXdG_f)^w=y-;HZZUPB8zPbll9mYprYmw(YHdZ i8k6JMl~F}^v8#MOW##~6s~ztE diff --git a/tests/_files/dev/Tfpdf/multi-page-draw-table-model1.png b/tests/_files/dev/Tfpdf/multi-page-draw-table-model1.png index 7178b28aaaad20f25882c6e422a406e9b3538021..43c59e5f692d8d52d5bead1436b3b2116884f0bf 100644 GIT binary patch delta 101 zcmcb+gzxSWz73l=*#&qldzUP2+q{!=374Rmm7%efshPHcft7&)_hYFGlk-FrprYmw k(K{zs-k3aJL>X1I`%VXY^JS6t%OZ?G%(VTo2y<600L+0Q_y7O^ delta 101 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 delta 97 zcmex9h3DF8t__muze<3 diff --git a/tests/_files/dev/Tfpdf/test-multicell-align.png b/tests/_files/dev/Tfpdf/test-multicell-align.png index 3fef0ef65428e4fd81de1cbc8ca8e1753e74e259..00b4df77b393339b0f212ac67ce0c44b8d113d6e 100644 GIT binary patch delta 101 zcmaE`kLSTYo(-Eg*#-ER#GB+3H}B+J!X;>CWoTk$V5n_iU}a#CQeo&kIZs3ZDry7~ kRXIC3Y4Us#WmM7P8=LkvUlwVqaRg>q7D5Hup=wB&qzAVyyS%eXYnYLdRVeaJu0CPqkzW@LL diff --git a/tests/_files/dev/Tfpdf/test-multicell-shrinking.png b/tests/_files/dev/Tfpdf/test-multicell-shrinking.png index 90cc0a383574df39fc15e4c9dfb7836b33b91c84..20e87789da676bbacf408d28371ec7b16843f207 100644 GIT binary patch delta 109 zcmaE}PVCJ(u??Fz*#-F61m54S*u0Z-374Rmm7$51ftj{}ft7*5!u$MZC+CSMpo(5- n+Fm$$zKAlaX#4bO>zXf%v|kos1Y#y2W(H!G?UzMZXEp%<_)H}& delta 109 zcmaE}PVCJ(u??Fz+4+POw9WQB-n^4@374RWm7%4Tv5~fcft7)Q-(I0(lk-FrP(|$@ mtg4zkUql&IG~;Xc(&oz|?UzLuftU%1nSq#P`(+WDK+LlJvIwh&762%zB^&?% delta 109 zcmezUSLF9!kqw(T+4+Q(j#}J3zj-I;5-vd#D?>{wV`FUt11kfA7pEkPCg+JLKt)X; pqA>>Z9VX8gQAQQzR^2zh`Lam+Wf4XoW&&bnAZFQqS%g(X3jiJ1BbopJ diff --git a/tests/_files/dev/Tfpdf/test-multicell-style.png b/tests/_files/dev/Tfpdf/test-multicell-style.png index 1d5b6db969c5ce7d387705caad0aec6b499c049c..d7557d92ad7de85d9cf702eaa80a356c29207c38 100644 GIT binary patch delta 105 zcmdlqU2xNM!3~=@*#-ExBqOH>Z{EqdgiFxO%Fx8hz*5`5z{qL;wH) delta 105 zcmdlqU2xNM!3~=@+4+Q3bfPPMZQjYbgiFxG%Fxov*i_rVz{