Skip to content

Commit

Permalink
Merge branch 'master' into feat/pdfa
Browse files Browse the repository at this point in the history
  • Loading branch information
Starfox64 committed Apr 18, 2024
2 parents 5ccb8ea + a30da03 commit 48d97ec
Show file tree
Hide file tree
Showing 72 changed files with 3,670 additions and 1,270 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
max-parallel: 12
matrix:
php: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2']
php: ['7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3']
package-release: [dist]
extensions: ['gd']
include:
Expand All @@ -27,7 +27,7 @@ jobs:
extensions: 'imagick'
steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
Expand Down
6 changes: 4 additions & 2 deletions README.md
Expand Up @@ -57,9 +57,9 @@ Note that some required dependencies may have further dependencies

### Recommendations

* OPcache (OPcache, XCache, APC, etc.): improves performance
* GD (for image processing)
* IMagick or GMagick extension: improves image processing performance
* Additionally, the IMagick or GMagick extension improves image processing performance for certain image types
* OPcache (OPcache, XCache, APC, etc.): improves performance

Visit the wiki for more information:
https://github.com/dompdf/dompdf/wiki/Requirements
Expand Down Expand Up @@ -224,6 +224,8 @@ Files accessed through the local file system have the following requirement:
Watch https://github.com/dompdf/dompdf/issues/320 for progress
* Does not support CSS flexbox.
* Does not support CSS Grid.
* A single Dompdf instance should not be used to render more than one HTML document
because persisted parsing and rendering artifacts can impact future renders.
---

[![Donate button](https://www.paypal.com/en_US/i/btn/btn_donate_SM.gif)](http://goo.gl/DSvWf)
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Expand Up @@ -35,10 +35,10 @@
"ext-gd": "*",
"ext-json": "*",
"ext-zip": "*",
"phpunit/phpunit": "^7.5 || ^8 || ^9",
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10",
"squizlabs/php_codesniffer": "^3.5",
"mockery/mockery": "^1.3",
"symfony/process": "^4.4 || ^5.4 || ^6.2"
"symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0"
},
"suggest": {
"ext-gd": "Needed to process images",
Expand Down
23 changes: 17 additions & 6 deletions lib/Cpdf.php
Expand Up @@ -3551,7 +3551,7 @@ private function openFont($font)

$cache_name = "$metrics_name.json";
$this->addMessage("metrics: $metrics_name, cache: $cache_name");

if (file_exists($fontcache . '/' . $cache_name)) {
$this->addMessage("openFont: json metrics file exists $fontcache/$cache_name");
$cached_font_info = json_decode(file_get_contents($fontcache . '/' . $cache_name), true);
Expand Down Expand Up @@ -3921,6 +3921,8 @@ function setColor($color, $force = false)
}

/**
* sets the color for fill operations
*
* @param string $fillRule
*/
function setFillRule($fillRule)
Expand Down Expand Up @@ -5944,8 +5946,10 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte)
}
}

$imagick = new \Imagick($file);
$imagick->setFormat('png');
$imagick = new \Imagick();
$imagick->setRegistry('temporary-path', $this->tmp);
$imagick->setFormat('PNG');
$imagick->readImage($file);

// Get opacity channel (negative of alpha channel)
if ($imagick->getImageAlphaChannel()) {
Expand All @@ -5955,7 +5959,14 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte)
if (\Imagick::getVersion()['versionNumber'] < 1800) {
$alpha_channel->negateImage(true);
}
$alpha_channel->writeImage($tempfile_alpha);

try {
$alpha_channel->writeImage($tempfile_alpha);
} catch (\ImagickException $th) {
// Backwards compatible retry attempt in case the IMagick policy is still configured in lowercase
$alpha_channel->setFormat('png');
$alpha_channel->writeImage($tempfile_alpha);
}

// Cast to 8bit+palette
$imgalpha_ = @imagecreatefrompng($tempfile_alpha);
Expand All @@ -5968,6 +5979,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte)

// Make opaque image
$color_channels = new \Imagick();
$color_channels->setRegistry('temporary-path', $this->tmp);
$color_channels->newImage($wpx, $hpx, "#FFFFFF", "png");
$color_channels->compositeImage($imagick, \Imagick::COMPOSITE_COPYRED, 0, 0);
$color_channels->compositeImage($imagick, \Imagick::COMPOSITE_COPYGREEN, 0, 0);
Expand Down Expand Up @@ -6125,8 +6137,7 @@ function addPngFromFile($file, $x, $y, $w = 0, $h = 0)
}

/**
* add a PNG image into the document, from a file
* this should work with remote files
* add an SVG image into the document from a file
*
* @param $file
* @param $x
Expand Down
83 changes: 53 additions & 30 deletions src/Adapter/CPDF.php
Expand Up @@ -602,11 +602,10 @@ protected function _convert_to_png($image_url, $type)

set_error_handler([Helpers::class, "record_warnings"]);

if (!function_exists($func_name)) {
if (!method_exists(Helpers::class, $func_name)) {
throw new Exception("Function $func_name() not found. Cannot convert $type image: $image_url. Please install the image PHP extension.");
}
if (method_exists(Helpers::class, $func_name)) {
$func_name = [Helpers::class, $func_name];
} elseif (!function_exists($func_name)) {
throw new Exception("Function $func_name() not found. Cannot convert $type image: $image_url. Please install the image PHP extension.");
}

try {
Expand Down Expand Up @@ -688,7 +687,6 @@ public function select($x, $y, $w, $h, $font, $size, $color = [0, 0, 0], $opts =
{
$pdf = $this->_pdf;

$font .= ".afm";
$pdf->selectFont($font);

if (!isset($pdf->acroFormId)) {
Expand All @@ -706,7 +704,6 @@ public function textarea($x, $y, $w, $h, $font, $size, $color = [0, 0, 0])
{
$pdf = $this->_pdf;

$font .= ".afm";
$pdf->selectFont($font);

if (!isset($pdf->acroFormId)) {
Expand All @@ -723,7 +720,6 @@ public function input($x, $y, $w, $h, $type, $font, $size, $color = [0, 0, 0])
{
$pdf = $this->_pdf;

$font .= ".afm";
$pdf->selectFont($font);

if (!isset($pdf->acroFormId)) {
Expand Down Expand Up @@ -756,7 +752,7 @@ public function text($x, $y, $text, $font, $size, $color = [0, 0, 0], $word_spac
$this->_set_fill_color($color);

$is_font_subsetting = $this->_dompdf->getOptions()->getIsFontSubsettingEnabled();
$pdf->selectFont($font . '.afm', '', true, $is_font_subsetting);
$pdf->selectFont($font, '', true, $is_font_subsetting);

$pdf->addText($x, $this->y($y) - $pdf->getFontHeight($size), $size, $text, $angle, $word_space, $char_space);

Expand Down Expand Up @@ -790,37 +786,64 @@ public function add_link($url, $x, $y, $width, $height)
}
}

public function font_supports_text(string $font, string $text): bool
public function font_supports_char(string $font, string $char): bool
{
if ($text === "") {
if ($char === "") {
return true;
}

$is_font_subsetting = $this->_dompdf->getOptions()->getIsFontSubsettingEnabled();
$this->_pdf->selectFont($font, '', false, $is_font_subsetting);
if (!array_key_exists($font, $this->_pdf->fonts)) {
$subsetting = $this->_dompdf->getOptions()->getIsFontSubsettingEnabled();
$this->_pdf->selectFont($font, '', false, $subsetting);
if (!\array_key_exists($font, $this->_pdf->fonts)) {
return false;
}
$font_info = $this->_pdf->fonts[$font];

if (function_exists("mb_str_split")) {
$chars = array_unique(mb_str_split($text, 1, "UTF-8"), SORT_STRING);
} else {
$chars = array_unique(preg_split("//u", $text, -1, PREG_SPLIT_NO_EMPTY), SORT_STRING);
}
$char_codes = array_map(
function($char) {
return Helpers::uniord($char, "UTF-8");
},
$chars
);

foreach ($char_codes as $char_code) {
if (!array_key_exists($char_code, $font_info['C'])) {
$fontInfo = $this->_pdf->fonts[$font];
$charCode = Helpers::uniord($char, "UTF-8");

if (!$fontInfo["isUnicode"]) {
// The core fonts use Windows ANSI encoding. The char map uses the
// position of the character in the encoding's mapping table in this
// case, not the Unicode code point, which is different for the
// characters outside ISO-8859-1 (positions 0x80-0x9F)
// https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
$mapping = [
0x20AC => 0x80,
0x201A => 0x82,
0x0192 => 0x83,
0x201E => 0x84,
0x2026 => 0x85,
0x2020 => 0x86,
0x2021 => 0x87,
0x02C6 => 0x88,
0x2030 => 0x89,
0x0160 => 0x8A,
0x2039 => 0x8B,
0x0152 => 0x8C,
0x017D => 0x8E,
0x2018 => 0x91,
0x2019 => 0x92,
0x201C => 0x93,
0x201D => 0x94,
0x2022 => 0x95,
0x2013 => 0x96,
0x2014 => 0x97,
0x02DC => 0x98,
0x2122 => 0x99,
0x0161 => 0x9A,
0x203A => 0x9B,
0x0153 => 0x9C,
0x017E => 0x9E,
0x0178 => 0x9F
];

$charCode = $mapping[$charCode] ?? $charCode;

if ($charCode > 0xFF) {
return false;
}
}
return true;

return \array_key_exists($charCode, $fontInfo["C"]);
}

/**
Expand Down
36 changes: 10 additions & 26 deletions src/Adapter/GD.php
Expand Up @@ -617,11 +617,10 @@ public function image($img, $x, $y, $w, $h, $resolution = "normal")
}

$func_name = "imagecreatefrom$img_type";
if (!function_exists($func_name)) {
if (!method_exists(Helpers::class, $func_name)) {
throw new \Exception("Function $func_name() not found. Cannot convert $img_type image: $img. Please install the image PHP extension.");
}
if (method_exists(Helpers::class, $func_name)) {
$func_name = [Helpers::class, $func_name];
} elseif (!function_exists($func_name)) {
throw new \Exception("Function $func_name() not found. Cannot convert $img_type image: $img. Please install the image PHP extension.");
}
$src = @call_user_func($func_name, $img);

Expand Down Expand Up @@ -799,32 +798,17 @@ private function getCharMap(string $font)
return $unicodeCharMapTables[$font] = $char_map;
}

public function font_supports_text(string $font, string $text): bool
public function font_supports_char(string $font, string $char): bool
{
if ($text === "") {
if ($char === "") {
return true;
}

if (function_exists("mb_str_split")) {
$chars = array_unique(mb_str_split($text, 1, "UTF-8"), SORT_STRING);
} else {
$chars = array_unique(preg_split("//u", $text, -1, PREG_SPLIT_NO_EMPTY), SORT_STRING);
}
$char_codes = array_map(
function($char) {
return Helpers::uniord($char, "UTF-8");
},
$chars
);

$char_map = $this->getCharMap($font);

foreach ($char_codes as $char_code) {
if (!array_key_exists($char_code, $char_map)) {
return false;
}
}
return true;
$font = $this->get_ttf_file($font);
$charMap = $this->getCharMap($font);
$charCode = Helpers::uniord($char, "UTF-8");

return \array_key_exists($charCode, $charMap);
}

public function get_text_width($text, $font, $size, $word_spacing = 0.0, $char_spacing = 0.0)
Expand Down

0 comments on commit 48d97ec

Please sign in to comment.