From a3c4f3db5a9989c96566391a8f8d0182f2a3ef9e Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Sat, 4 Feb 2023 16:39:38 -0500 Subject: [PATCH 1/5] Tell XML parser when document is complete --- src/Svg/Document.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Svg/Document.php b/src/Svg/Document.php index 309875b..68a9730 100644 --- a/src/Svg/Document.php +++ b/src/Svg/Document.php @@ -133,6 +133,7 @@ function ($parser, $name) {} break; } } + xml_parse($parser, "", true); xml_parser_free($parser); From 579e7e19ef048fa3748f8f08a814e9ab601969e3 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Sat, 4 Feb 2023 16:40:51 -0500 Subject: [PATCH 2/5] Merge CPdf updated from Dompdf --- src/Svg/Surface/CPdf.php | 387 ++++++++++++++++++++------------------- 1 file changed, 194 insertions(+), 193 deletions(-) diff --git a/src/Svg/Surface/CPdf.php b/src/Svg/Surface/CPdf.php index caa28a8..e24f6f2 100644 --- a/src/Svg/Surface/CPdf.php +++ b/src/Svg/Surface/CPdf.php @@ -1044,7 +1044,7 @@ protected function getFontSubsettingTag(array $font): string } } - return 'SUB' . str_pad($base_26, 3 , 'A', STR_PAD_LEFT); + return 'SUB' . str_pad($base_26, 3, 'A', STR_PAD_LEFT); } /** @@ -1314,7 +1314,7 @@ protected function o_toUnicode($id, $action) $res = "\n$id 0 obj\n"; $res .= "<>\n"; - $res .= "stream\n" . $stream . "\nendstream" . "\nendobj";; + $res .= "stream\n" . $stream . "\nendstream" . "\nendobj"; return $res; } @@ -1724,14 +1724,14 @@ protected function o_info($id, $action, $options = '') // dates must be outputted as-is, without Unicode transformations if ($k !== 'CreationDate' && $k !== 'ModDate') { - $v = $this->filterText($v, true, false); + $v = $this->utf8toUtf16BE($v); } if ($encrypted) { $v = $this->ARC4($v); } - $res .= $v; + $res .= $this->filterText($v, false, false); $res .= ")\n"; } @@ -2356,8 +2356,7 @@ protected function o_xobject($id, $action, $options = '') $res = "\n$id 0 obj\n<< /Type /XObject\n"; foreach ($o["info"] as $k => $v) { - switch($k) - { + switch ($k) { case 'Subtype': $res .= "/Subtype /$v\n"; break; @@ -2410,7 +2409,7 @@ protected function o_xobject($id, $action, $options = '') } $res .= "/Length " . mb_strlen($tmp, '8bit') . " >>\n"; - $res .= "stream\n" . $tmp . "\nendstream" . "\nendobj";; + $res .= "stream\n" . $tmp . "\nendstream" . "\nendobj"; return $res; } @@ -2448,7 +2447,7 @@ protected function o_acroform($id, $action, $options = '') $res = "\n$id 0 obj\n<<"; foreach ($o["info"] as $k => $v) { - switch($k) { + switch ($k) { case 'Fields': $res .= " /Fields ["; foreach ($v as $i) { @@ -2552,7 +2551,7 @@ protected function o_field($id, $action, $options = '') $res .= ">>\n"; break; case 'T': - if($encrypted) { + if ($encrypted) { $v = $this->filterText($this->ARC4($v), false, false); } $res .= "/T ($v)\n"; @@ -2595,7 +2594,7 @@ protected function o_sig($id, $action, $options = '') $pos = strpos($content, sprintf("/ByteRange [ %'.010d", $id)); $len = strlen('/ByteRange [ ********** ********** ********** ********** ]'); $rangeStartPos = $pos + $len + 1 + 10; // before '<' - $content = substr_replace($content, str_pad(sprintf('/ByteRange [ 0 %u %u %u ]', $rangeStartPos, $rangeStartPos + $sign_maxlen + 2, $content_len - 2 - $sign_maxlen - $rangeStartPos ), $len, ' ', STR_PAD_RIGHT), $pos, $len); + $content = substr_replace($content, str_pad(sprintf('/ByteRange [ 0 %u %u %u ]', $rangeStartPos, $rangeStartPos + $sign_maxlen + 2, $content_len - 2 - $sign_maxlen - $rangeStartPos), $len, ' ', STR_PAD_RIGHT), $pos, $len); $fuid = uniqid(); $tmpInput = $this->tmp . "/pkcs7.tmp." . $fuid . '.in'; @@ -2659,7 +2658,7 @@ protected function o_sig($id, $action, $options = '') $o = &$this->objects[$id]; foreach ($o['info'] as $k => $v) { - switch($k) { + switch ($k) { case 'Name': case 'Location': case 'Reason': @@ -2785,7 +2784,7 @@ protected function o_indirect_references($id, $action, $options = null) case 'out': $res = "\n$id 0 obj << "; - foreach($this->objects[$id]['info'] as $referenceObjName => $referenceObjId) { + foreach ($this->objects[$id]['info'] as $referenceObjName => $referenceObjId) { $res .= "/$referenceObjName $referenceObjId 0 R "; } @@ -2851,16 +2850,18 @@ protected function o_embedded_file_dictionary($id, $action, $options = null) break; case 'out': $info = &$this->objects[$id]['info']; + $filename = $this->utf8toUtf16BE($info['filename']); + $description = $this->utf8toUtf16BE($info['description']); if ($this->encrypted) { $this->encryptInit($id); - $filename = $this->ARC4($info['filename']); - $description = $this->ARC4($info['description']); - } else { - $filename = $info['filename']; - $description = $info['description']; + $filename = $this->ARC4($filename); + $description = $this->ARC4($description); } + $filename = $this->filterText($filename, false, false); + $description = $this->filterText($description, false, false); + $res = "\n$id 0 obj <>"; $res .= " /F ($filename) /UF ($filename) /Desc ($description)"; @@ -3241,11 +3242,11 @@ private function openFont($font) { // assume that $font contains the path and file but not the extension $name = basename($font); - $dir = dirname($font) . '/'; + $dir = dirname($font); $fontcache = $this->fontcache; if ($fontcache == '') { - $fontcache = rtrim($dir, DIRECTORY_SEPARATOR."/\\"); + $fontcache = $dir; } //$name filename without folder and extension of font metrics @@ -3262,36 +3263,22 @@ private function openFont($font) $metrics_name = "$name.ufm"; } - $cache_name = "$metrics_name.php"; + $cache_name = "$metrics_name.json"; $this->addMessage("metrics: $metrics_name, cache: $cache_name"); if (file_exists($fontcache . '/' . $cache_name)) { - $this->addMessage("openFont: php file exists $fontcache/$cache_name"); - $this->fonts[$font] = require($fontcache . '/' . $cache_name); - - if (!isset($this->fonts[$font]['_version_']) || $this->fonts[$font]['_version_'] != $this->fontcacheVersion) { - // if the font file is old, then clear it out and prepare for re-creation - $this->addMessage('openFont: clear out, make way for new version.'); - $this->fonts[$font] = null; - unset($this->fonts[$font]); - } - } else { - $old_cache_name = "php_$metrics_name"; - if (file_exists($fontcache . '/' . $old_cache_name)) { - $this->addMessage( - "openFont: php file doesn't exist $fontcache/$cache_name, creating it from the old format" - ); - $old_cache = file_get_contents($fontcache . '/' . $old_cache_name); - file_put_contents($fontcache . '/' . $cache_name, 'openFont($font); - return; + $this->addMessage("openFont: json metrics file exists $fontcache/$cache_name"); + $cached_font_info = json_decode(file_get_contents($fontcache . '/' . $cache_name), true); + if (!isset($cached_font_info['_version_']) || $cached_font_info['_version_'] != $this->fontcacheVersion) { + $this->addMessage('openFont: font cache is out of date, regenerating'); + } else { + $this->fonts[$font] = $cached_font_info; } } - if (!isset($this->fonts[$font]) && file_exists($dir . $metrics_name)) { + if (!isset($this->fonts[$font]) && file_exists("$dir/$metrics_name")) { // then rebuild the php_.afm file from the .afm file - $this->addMessage("openFont: build php file from $dir$metrics_name"); + $this->addMessage("openFont: build php file from $dir/$metrics_name"); $data = []; // 20 => 'space' @@ -3306,7 +3293,7 @@ private function openFont($font) $cidtogid = str_pad('', 256 * 256 * 2, "\x00"); } - $file = file($dir . $metrics_name); + $file = file("$dir/$metrics_name"); foreach ($file as $rowA) { $row = trim($rowA); @@ -3460,7 +3447,7 @@ private function openFont($font) //Because of potential trouble with php safe mode, expect that the folder already exists. //If not existing, this will hit performance because of missing cached results. if (is_dir($fontcache) && is_writable($fontcache)) { - file_put_contents($fontcache . '/' . $cache_name, 'fonts[$font])) { $this->addMessage("openFont: no font file found for $font. Do you need to run load_font.php?"); } - - //pre_r($this->messages); } /** @@ -3479,7 +3464,7 @@ private function openFont($font) * note that encoding='none' will need to be used for symbolic fonts * and 'differences' => an array of mappings between numbers 0->255 and character names. * - * @param $fontName + * @param string $fontName * @param string $encoding * @param bool $set * @param bool $isSubsetting @@ -3627,8 +3612,8 @@ private function addContent($content) /** * sets the color for fill operations * - * @param $color - * @param bool $force + * @param array $color + * @param bool $force */ function setColor($color, $force = false) { @@ -3652,7 +3637,7 @@ function setColor($color, $force = false) /** * sets the color for fill operations * - * @param $fillRule + * @param string $fillRule */ function setFillRule($fillRule) { @@ -3666,8 +3651,8 @@ function setFillRule($fillRule) /** * sets the color for stroke operations * - * @param $color - * @param bool $force + * @param array $color + * @param bool $force */ function setStrokeColor($color, $force = false) { @@ -3818,11 +3803,11 @@ function setFillTransparency($mode, $opacity) /** * draw a line from one set of coordinates to another * - * @param $x1 - * @param $y1 - * @param $x2 - * @param $y2 - * @param bool $stroke + * @param float $x1 + * @param float $y1 + * @param float $x2 + * @param float $y2 + * @param bool $stroke */ function line($x1, $y1, $x2, $y2, $stroke = true) { @@ -3836,14 +3821,14 @@ function line($x1, $y1, $x2, $y2, $stroke = true) /** * draw a bezier curve based on 4 control points * - * @param $x0 - * @param $y0 - * @param $x1 - * @param $y1 - * @param $x2 - * @param $y2 - * @param $x3 - * @param $y3 + * @param float $x0 + * @param float $y0 + * @param float $x1 + * @param float $y1 + * @param float $x2 + * @param float $y2 + * @param float $x3 + * @param float $y3 */ function curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3) { @@ -3857,13 +3842,13 @@ function curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3) /** * draw a part of an ellipse * - * @param $x0 - * @param $y0 - * @param $astart - * @param $afinish - * @param $r1 - * @param int $r2 - * @param int $angle + * @param float $x0 + * @param float $y0 + * @param float $astart + * @param float $afinish + * @param float $r1 + * @param float $r2 + * @param float $angle * @param int $nSeg */ function partEllipse($x0, $y0, $astart, $afinish, $r1, $r2 = 0, $angle = 0, $nSeg = 8) @@ -3874,14 +3859,14 @@ function partEllipse($x0, $y0, $astart, $afinish, $r1, $r2 = 0, $angle = 0, $nSe /** * draw a filled ellipse * - * @param $x0 - * @param $y0 - * @param $r1 - * @param int $r2 - * @param int $angle + * @param float $x0 + * @param float $y0 + * @param float $r1 + * @param float $r2 + * @param float $angle * @param int $nSeg - * @param int $astart - * @param int $afinish + * @param float $astart + * @param float $afinish */ function filledEllipse($x0, $y0, $r1, $r2 = 0, $angle = 0, $nSeg = 8, $astart = 0, $afinish = 360) { @@ -3889,8 +3874,8 @@ function filledEllipse($x0, $y0, $r1, $r2 = 0, $angle = 0, $nSeg = 8, $astart = } /** - * @param $x - * @param $y + * @param float $x + * @param float $y */ function lineTo($x, $y) { @@ -3898,8 +3883,8 @@ function lineTo($x, $y) } /** - * @param $x - * @param $y + * @param float $x + * @param float $y */ function moveTo($x, $y) { @@ -3909,12 +3894,12 @@ function moveTo($x, $y) /** * draw a bezier curve based on 4 control points * - * @param $x1 - * @param $y1 - * @param $x2 - * @param $y2 - * @param $x3 - * @param $y3 + * @param float $x1 + * @param float $y1 + * @param float $x2 + * @param float $y2 + * @param float $x3 + * @param float $y3 */ function curveTo($x1, $y1, $x2, $y2, $x3, $y3) { @@ -3923,6 +3908,11 @@ function curveTo($x1, $y1, $x2, $y2, $x3, $y3) /** * draw a bezier curve based on 4 control points + * + * @param float $cpx + * @param float $cpy + * @param float $x + * @param float $y */ function quadTo($cpx, $cpy, $x, $y) { @@ -3950,18 +3940,18 @@ function endPath() * nSeg is not allowed to be less than 2, as this will simply draw a line (and will even draw a * pretty crappy shape at 2, as we are approximating with bezier curves. * - * @param $x0 - * @param $y0 - * @param $r1 - * @param int $r2 - * @param int $angle - * @param int $nSeg - * @param int $astart - * @param int $afinish - * @param bool $close - * @param bool $fill - * @param bool $stroke - * @param bool $incomplete + * @param float $x0 + * @param float $y0 + * @param float $r1 + * @param float $r2 + * @param float $angle + * @param int $nSeg + * @param float $astart + * @param float $afinish + * @param bool $close + * @param bool $fill + * @param bool $stroke + * @param bool $incomplete */ function ellipse( $x0, @@ -4075,11 +4065,11 @@ function ellipse( * (2,1) is 2 on, 1 off, 2 on, 1 off.. etc * phase is a modifier on the dash pattern which is used to shift the point at which the pattern starts. * - * @param int $width + * @param float $width * @param string $cap * @param string $join - * @param string $dash - * @param int $phase + * @param array $dash + * @param int $phase */ function setLineStyle($width = 1, $cap = '', $join = '', $dash = '', $phase = 0) { @@ -4113,19 +4103,19 @@ function setLineStyle($width = 1, $cap = '', $join = '', $dash = '', $phase = 0) /** * draw a polygon, the syntax for this is similar to the GD polygon command * - * @param $p - * @param $np - * @param bool $f + * @param float[] $p + * @param bool $fill */ - function polygon($p, $np, $f = false) + public function polygon(array $p, bool $fill = false): void { $this->addContent(sprintf("\n%.3F %.3F m ", $p[0], $p[1])); - for ($i = 2; $i < $np * 2; $i = $i + 2) { + $n = count($p); + for ($i = 2; $i < $n; $i = $i + 2) { $this->addContent(sprintf("%.3F %.3F l ", $p[$i], $p[$i + 1])); } - if ($f) { + if ($fill) { $this->addContent(' f'); } else { $this->addContent(' S'); @@ -4136,10 +4126,10 @@ function polygon($p, $np, $f = false) * a filled rectangle, note that it is the width and height of the rectangle which are the secondary parameters, not * the coordinates of the upper-right corner * - * @param $x1 - * @param $y1 - * @param $width - * @param $height + * @param float $x1 + * @param float $y1 + * @param float $width + * @param float $height */ function filledRectangle($x1, $y1, $width, $height) { @@ -4150,10 +4140,10 @@ function filledRectangle($x1, $y1, $width, $height) * draw a rectangle, note that it is the width and height of the rectangle which are the secondary parameters, not * the coordinates of the upper-right corner * - * @param $x1 - * @param $y1 - * @param $width - * @param $height + * @param float $x1 + * @param float $y1 + * @param float $width + * @param float $height */ function rectangle($x1, $y1, $width, $height) { @@ -4164,10 +4154,10 @@ function rectangle($x1, $y1, $width, $height) * draw a rectangle, note that it is the width and height of the rectangle which are the secondary parameters, not * the coordinates of the upper-right corner * - * @param $x1 - * @param $y1 - * @param $width - * @param $height + * @param float $x1 + * @param float $y1 + * @param float $width + * @param float $height */ function rect($x1, $y1, $width, $height) { @@ -4279,8 +4269,10 @@ public function addFormField($type, $name, $x0, $y0, $x1, $y1, $ff = 0, $size = $color = implode(' ', $color) . ' rg'; $currentFontNum = $this->currentFontNum; - $font = array_filter($this->objects[$this->currentNode]['info']['fonts'], - function($item) use ($currentFontNum) { return $item['fontNum'] == $currentFontNum; }); + $font = array_filter( + $this->objects[$this->currentNode]['info']['fonts'], + function ($item) use ($currentFontNum) { return $item['fontNum'] == $currentFontNum; } + ); $this->o_acroform($this->acroFormId, 'font', ['objNum' => $font[0]['objNum'], 'fontNum' => $font[0]['fontNum']]); @@ -4395,10 +4387,10 @@ function restore() /** * draw a clipping rectangle, all the elements added after this will be clipped * - * @param $x1 - * @param $y1 - * @param $width - * @param $height + * @param float $x1 + * @param float $y1 + * @param float $width + * @param float $height */ function clippingRectangle($x1, $y1, $width, $height) { @@ -4409,14 +4401,14 @@ function clippingRectangle($x1, $y1, $width, $height) /** * draw a clipping rounded rectangle, all the elements added after this will be clipped * - * @param $x1 - * @param $y1 - * @param $w - * @param $h - * @param $rTL - * @param $rTR - * @param $rBR - * @param $rBL + * @param float $x1 + * @param float $y1 + * @param float $w + * @param float $h + * @param float $rTL + * @param float $rTR + * @param float $rBR + * @param float $rBL */ function clippingRectangleRounded($x1, $y1, $w, $h, $rTL, $rTR, $rBR, $rBL) { @@ -4456,6 +4448,25 @@ function clippingRectangleRounded($x1, $y1, $w, $h, $rTL, $rTR, $rBR, $rBL) $this->addContent(" W n"); } + /** + * draw a clipping polygon, the syntax for this is similar to the GD polygon command + * + * @param float[] $p + */ + public function clippingPolygon(array $p): void + { + $this->save(); + + $this->addContent(sprintf("\n%.3F %.3F m ", $p[0], $p[1])); + + $n = count($p); + for ($i = 2; $i < $n; $i = $i + 2) { + $this->addContent(sprintf("%.3F %.3F l ", $p[$i], $p[$i + 1])); + } + + $this->addContent("W n"); + } + /** * ends the last clipping shape */ @@ -4672,10 +4683,11 @@ function stream($filename = "document.pdf", $options = []) /** * return the height in units of the current font in the given size * - * @param $size - * @return float|int + * @param float $size + * + * @return float */ - function getFontHeight($size) + public function getFontHeight(float $size): float { if (!$this->numFonts) { $this->selectFont($this->defaultFont); @@ -4707,10 +4719,11 @@ function getFontHeight($size) } /** - * @param $size - * @return float|int + * @param float $size + * + * @return float */ - function getFontXHeight($size) + public function getFontXHeight(float $size): float { if (!$this->numFonts) { $this->selectFont($this->defaultFont); @@ -4733,10 +4746,11 @@ function getFontXHeight($size) * if you add this number to the baseline, you get the level of the bottom of the font * it is in the pdf user units * - * @param $size - * @return float|int + * @param float $size + * + * @return float */ - function getFontDescender($size) + public function getFontDescender(float $size): float { // note that this will most likely return a negative value if (!$this->numFonts) { @@ -4753,8 +4767,6 @@ function getFontDescender($size) * filter the text, this is applied to all text just before being inserted into the pdf document * it escapes the various things that need to be escaped, and so on * - * @access private - * * @param $text * @param bool $bom * @param bool $convert_encoding @@ -4774,7 +4786,7 @@ function filterText($text, $bom = true, $convert_encoding = true) //$text = html_entity_decode($text, ENT_QUOTES); $text = mb_convert_encoding($text, self::$targetEncoding, 'UTF-8'); } - } else if ($bom) { + } elseif ($bom) { $text = $this->utf8toUtf16BE($text, $bom); } @@ -4789,12 +4801,7 @@ function filterText($text, $bom = true, $convert_encoding = true) * based on the excellent TCPDF code by Nicola Asuni and the * RFC for UTF-8 at http://www.faqs.org/rfcs/rfc3629.html * - * @access private - * @author Orion Richardson - * @since January 5, 2008 - * * @param string $text UTF-8 string to process - * * @return array UTF-8 codepoints array for the string */ function utf8toCodePointsArray(&$text) @@ -4864,13 +4871,8 @@ function utf8toCodePointsArray(&$text) * based on the excellent TCPDF code by Nicola Asuni and the * RFC for UTF-8 at http://www.faqs.org/rfcs/rfc3629.html * - * @access private - * @author Orion Richardson - * @since January 5, 2008 - * * @param string $text UTF-8 string to process * @param boolean $bom whether to add the byte order marker - * * @return string UTF-16 result string */ function utf8toUtf16BE(&$text, $bom = true) @@ -4945,8 +4947,8 @@ function concatMatches($matches) /** * register text for font subsetting * - * @param $font - * @param $text + * @param string $font + * @param string $text */ function registerText($font, $text) { @@ -4955,7 +4957,8 @@ function registerText($font, $text) } if (!isset($this->stringSubsets[$font])) { - $this->stringSubsets[$font] = []; + $base_subset = "\u{fffd}\u{fffe}\u{ffff}"; + $this->stringSubsets[$font] = $this->utf8toCodePointsArray($base_subset); } $this->stringSubsets[$font] = array_unique( @@ -4966,14 +4969,14 @@ function registerText($font, $text) /** * add text to the document, at a specified location, size and angle on the page * - * @param $x - * @param $y - * @param $size - * @param $text - * @param int $angle - * @param int $wordSpaceAdjust - * @param int $charSpaceAdjust - * @param bool $smallCaps + * @param float $x + * @param float $y + * @param float $size + * @param string $text + * @param float $angle + * @param float $wordSpaceAdjust + * @param float $charSpaceAdjust + * @param bool $smallCaps */ function addText($x, $y, $size, $text, $angle = 0, $wordSpaceAdjust = 0, $charSpaceAdjust = 0, $smallCaps = false) { @@ -5086,13 +5089,14 @@ function addText($x, $y, $size, $text, $angle = 0, $wordSpaceAdjust = 0, $charSp * calculate how wide a given text string will be on a page, at a given size. * this can be called externally, but is also used by the other class functions * - * @param float $size + * @param float $size * @param string $text - * @param float $word_spacing - * @param float $char_spacing + * @param float $wordSpacing + * @param float $charSpacing + * * @return float */ - function getTextWidth($size, $text, $word_spacing = 0, $char_spacing = 0) + public function getTextWidth(float $size, string $text, float $wordSpacing = 0.0, float $charSpacing = 0.0): float { static $ord_cache = []; @@ -5107,9 +5111,6 @@ function getTextWidth($size, $text, $word_spacing = 0, $char_spacing = 0) $text = str_replace(["\r", "\n"], "", $text); - // converts a number or a float to a string so it can get the width - $text = "$text"; - // hmm, this is where it all starts to get tricky - use the font information to // calculate the width of each character, add them up and convert to user units $w = 0; @@ -5136,14 +5137,14 @@ function getTextWidth($size, $text, $word_spacing = 0, $char_spacing = 0) // add additional padding for space if (isset($current_font['codeToName'][$char]) && $current_font['codeToName'][$char] === 'space') { // Space - $w += $word_spacing * $space_scale; + $w += $wordSpacing * $space_scale; } } } // add additional char spacing - if ($char_spacing != 0) { - $w += $char_spacing * $space_scale * count($unicode); + if ($charSpacing != 0) { + $w += $charSpacing * $space_scale * count($unicode); } } else { @@ -5171,14 +5172,14 @@ function getTextWidth($size, $text, $word_spacing = 0, $char_spacing = 0) // add additional padding for space if (isset($current_font['codeToName'][$char]) && $current_font['codeToName'][$char] === 'space') { // Space - $w += $word_spacing * $space_scale; + $w += $wordSpacing * $space_scale; } } } // add additional char spacing - if ($char_spacing != 0) { - $w += $char_spacing * $space_scale * $len; + if ($charSpacing != 0) { + $w += $charSpacing * $space_scale * $len; } } @@ -5418,12 +5419,12 @@ public function addEmbeddedFile(string $filepath, string $embeddedFilename, stri } /** - * add content to the documents info object + * Add content to the documents info object * - * @param $label - * @param int $value + * @param string|array $label + * @param string $value */ - function addInfo($label, $value = 0) + public function addInfo($label, string $value = ""): void { // this will only work if the label is one of the valid ones. // modify this so that arrays can be passed as well. @@ -5431,7 +5432,7 @@ function addInfo($label, $value = 0) // else assume that they are both scalar, anything else will probably error if (is_array($label)) { foreach ($label as $l => $v) { - $this->o_info($this->infoObject, $l, $v); + $this->o_info($this->infoObject, $l, (string) $v); } } else { $this->o_info($this->infoObject, $label, $value); @@ -5568,7 +5569,7 @@ function addImagePng(&$img, $file, $x, $y, $w = 0.0, $h = 0.0, $is_mask = false, protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) { // generate images - $img = imagecreatefrompng($file); + $img = @imagecreatefrompng($file); if ($img === false) { return; @@ -5617,7 +5618,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $alpha_channel->writeimage($tempfile_alpha); // Cast to 8bit+palette - $imgalpha_ = imagecreatefrompng($tempfile_alpha); + $imgalpha_ = @imagecreatefrompng($tempfile_alpha); imagecopy($imgalpha, $imgalpha_, 0, 0, 0, 0, $wpx, $hpx); imagedestroy($imgalpha_); imagepng($imgalpha, $tempfile_alpha); @@ -5630,7 +5631,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $color_channels->compositeimage($gmagick, \Gmagick::COMPOSITE_COPYBLUE, 0, 0); $color_channels->writeimage($tempfile_plain); - $imgplain = imagecreatefrompng($tempfile_plain); + $imgplain = @imagecreatefrompng($tempfile_plain); } // Use PECL imagick + ImageMagic to process transparent PNG images elseif (extension_loaded("imagick")) { @@ -5653,7 +5654,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $imagick->setFormat('png'); // Get opacity channel (negative of alpha channel) - if ($imagick->getImageAlphaChannel() !== 0) { + if ($imagick->getImageAlphaChannel()) { $alpha_channel = $imagickClonable ? clone $imagick : $imagick->clone(); $alpha_channel->separateImageChannel(\Imagick::CHANNEL_ALPHA); // Since ImageMagick7 negate invert transparency as default @@ -5663,7 +5664,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $alpha_channel->writeImage($tempfile_alpha); // Cast to 8bit+palette - $imgalpha_ = imagecreatefrompng($tempfile_alpha); + $imgalpha_ = @imagecreatefrompng($tempfile_alpha); imagecopy($imgalpha, $imgalpha_, 0, 0, 0, 0, $wpx, $hpx); imagedestroy($imgalpha_); imagepng($imgalpha, $tempfile_alpha); @@ -5679,7 +5680,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) $color_channels->compositeImage($imagick, \Imagick::COMPOSITE_COPYBLUE, 0, 0); $color_channels->writeImage($tempfile_plain); - $imgplain = imagecreatefrompng($tempfile_plain); + $imgplain = @imagecreatefrompng($tempfile_plain); } else { // allocated colors cache $allocated_colors = []; From f06e9afa4f5f49f1425fb558a3b286467e758818 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Mon, 8 Jan 2024 08:44:40 -0500 Subject: [PATCH 3/5] Update .gitignore and .gitattributes --- .gitattributes | 13 ++++++++----- .gitignore | 8 +++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.gitattributes b/.gitattributes index 9b7559f..5416ecd 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,8 +8,11 @@ *.htm text *.svg text -/.gitattributes export-ignore -/.github export-ignore -/.gitignore export-ignore -/phpunit.xml export-ignore -/tests export-ignore +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.github export-ignore +/.gitignore export-ignore +/tests export-ignore +/SECURITY.md export-ignore +/phpcs.xml export-ignore +/phpunit.xml export-ignore diff --git a/.gitignore b/.gitignore index 7181efd..b23d21a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ -excluded -gui -.idea \ No newline at end of file +composer.phar +composer.lock +phpunit.xml +vendor +.phpunit.result.cache \ No newline at end of file From a60f2828d2d12e1b9e4a504f98eb79dd85a62a6f Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Mon, 8 Jan 2024 08:52:50 -0500 Subject: [PATCH 4/5] Update README links --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2b8e6f6..ff3c921 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # SVG file parsing / rendering library -[![Build Status](https://github.com/phenx/php-svg-lib/workflows/test/badge.svg)](https://github.com/phenx/php-svg-lib/actions) - +[![Build Status](https://github.com/dompdf/php-svg-lib/actions/workflows/test.yml/badge.svg)](https://github.com/dompdf/php-svg-lib/actions/workflows/test.yml) [![Latest Stable Version](https://poser.pugx.org/phenx/php-svg-lib/v/stable)](https://packagist.org/packages/phenx/php-svg-lib) [![Total Downloads](https://poser.pugx.org/phenx/php-svg-lib/downloads)](https://packagist.org/packages/phenx/php-svg-lib) @@ -10,4 +9,4 @@ The main purpose of this lib is to rasterize SVG to a surface which can be an image or a PDF for example, through a `\Svg\Surface` PHP interface. -This project was initialized by the need to render SVG documents inside PDF files for the [DomPdf](http://dompdf.github.io) project. +This project was initialized by the need to render SVG documents inside PDF files for the [DomPdf](https://github.com/dompdf/dompdf) project. From 70a33db9c2ee7d4326950bd47c7219a8708013a4 Mon Sep 17 00:00:00 2001 From: Brian Sweeney Date: Fri, 16 Feb 2024 09:54:47 -0500 Subject: [PATCH 5/5] Update license property in composer.json fixes #104 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index a6ed9c5..910a0a1 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "A library to read, parse and export to PDF SVG files.", "homepage": "https://github.com/PhenX/php-svg-lib", - "license": "LGPL-3.0", + "license": "LGPL-3.0-or-later", "authors": [ { "name": "Fabien Ménager",