diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b352546..967cf97 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,8 @@ name: "Run unit tests" +permissions: + contents: read + on: - push - pull_request diff --git a/composer.json b/composer.json index 4a8abe3..6f66867 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,6 @@ "sabberworm/php-css-parser": "^8.4" }, "require-dev": { - "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11" + "phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11 || ^12" } } diff --git a/src/Svg/Document.php b/src/Svg/Document.php index 24c0681..2bceb4d 100644 --- a/src/Svg/Document.php +++ b/src/Svg/Document.php @@ -357,7 +357,7 @@ private function _tagStart($parser, $name, $attributes) $this->enterDefs(); $tag = new Symbol($this, $name); break; - + case 'clippath': $tag = new ClipPath($this, $name); break; @@ -403,7 +403,7 @@ function _charData($parser, $data) function _tagEnd($parser, $name) { - /** @var AbstractTag $tag */ + /** @var AbstractTag|null $tag */ $tag = null; switch (strtolower($name)) { case 'defs': @@ -414,7 +414,7 @@ function _tagEnd($parser, $name) $this->exitDefs(); $tag = array_pop($this->stack); break; - + case 'svg': case 'path': case 'rect': @@ -437,8 +437,8 @@ function _tagEnd($parser, $name) break; } - if ((!$this->inDefs && $tag) || $tag instanceof StyleTag) { + if ((!$this->inDefs && $tag !== null) || $tag instanceof StyleTag) { $tag->handleEnd(); } } -} +} diff --git a/src/Svg/Style.php b/src/Svg/Style.php index c5f3e08..6ef8ba6 100644 --- a/src/Svg/Style.php +++ b/src/Svg/Style.php @@ -78,9 +78,9 @@ protected function getStyleMap() } /** - * @param $attributes + * @param array $attributes * - * @return Style + * @return void */ public function fromAttributes($attributes) { @@ -151,6 +151,11 @@ public function fromStyleSheets(AbstractTag $tag, $attributes) { $this->fillStyles($styles); } + /** + * @param array $styles + * + * @return void + */ protected function fillStyles($styles) { $style_map = $this->getStyleMap(); diff --git a/src/Svg/Surface/CPdf.php b/src/Svg/Surface/CPdf.php index ce807a2..6aebac5 100644 --- a/src/Svg/Surface/CPdf.php +++ b/src/Svg/Surface/CPdf.php @@ -131,13 +131,13 @@ class CPdf private $gstates = []; /** - * @var array Current color for fill operations, defaults to inactive value, + * @var array|null Current color for fill operations, defaults to inactive value, * all three components should be between 0 and 1 inclusive when active */ public $currentColor = null; /** - * @var array Current color for stroke operations (lines etc.) + * @var array|null Current color for stroke operations (lines etc.) */ public $currentStrokeColor = null; @@ -152,12 +152,12 @@ class CPdf public $currentLineStyle = ''; /** - * @var array Current line transparency (partial graphics state) + * @var array|null Current line transparency (partial graphics state) */ public $currentLineTransparency = ["mode" => "Normal", "opacity" => 1.0]; /** - * array Current fill transparency (partial graphics state) + * @var array|null Current fill transparency (partial graphics state) */ public $currentFillTransparency = ["mode" => "Normal", "opacity" => 1.0]; @@ -306,7 +306,7 @@ class CPdf public $destinations = []; /** - * @var array Store the stack for the transaction commands, each item in here is a record of the values of all the + * @var array|string Store the stack for the transaction commands, each item in here is a record of the values of all the * publiciables within the class, so that the user can rollback at will (from each 'start' command) * note that this includes the objects array, so these can be large. */ @@ -427,7 +427,7 @@ public function __destruct() * $action = a string specifying the action to be performed, though ALL must support: * 'new' - create the object with the id $id * 'out' - produce the output for the pdf object - * $options = optional, a string or array containing the various parameters for the object + * $options = optional, an array containing the various parameters for the object. Or an empty string. * * These, in conjunction with the output function are the ONLY way for output to be produced * within the pdf 'file'. @@ -436,9 +436,9 @@ public function __destruct() /** * Destination object, used to specify the location for the user to jump to, presently on opening * - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param array|string $options * @return string|null */ protected function o_destination($id, $action, $options = '') @@ -481,8 +481,8 @@ protected function o_destination($id, $action, $options = '') /** * set the viewer preferences * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string|array $options * @return string|null */ @@ -590,13 +590,15 @@ protected function o_viewerPreferences($id, $action, $options = '') /** * define the document catalog, the overall controller for the document * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string|array $options * @return string|null */ protected function o_catalog($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -669,13 +671,15 @@ protected function o_catalog($id, $action, $options = '') /** * object which is a parent to the pages in the document * - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param array|string $options * @return string|null */ protected function o_pages($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -817,13 +821,15 @@ protected function o_pages($id, $action, $options = '') /** * define the outlines in the doc, empty for now * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string $options * @return string|null */ protected function o_outlines($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -859,14 +865,16 @@ protected function o_outlines($id, $action, $options = '') /** * an object to hold the font description * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string|array $options * @return string|null - * @throws FontNotFoundException + * @throws \FontLib\Exception\FontNotFoundException */ protected function o_font($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1043,7 +1051,7 @@ protected function getFontSubsettingTag(array $font): string * @param int $fontObjId * @param array $object_info * @return array|false - * @throws FontNotFoundException + * @throws \FontLib\Exception\FontNotFoundException */ private function processFont(int $fontObjId, array $object_info) { @@ -1257,8 +1265,8 @@ private function processFont(int $fontObjId, array $object_info) /** * A toUnicode section, needed for unicode fonts * - * @param $id - * @param $action + * @param string $id + * @param string $action * @return null|string */ protected function o_toUnicode($id, $action) @@ -1317,13 +1325,15 @@ protected function o_toUnicode($id, $action) /** * a font descriptor, needed for including additional fonts * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string $options * @return null|string */ protected function o_fontDescriptor($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1382,13 +1392,15 @@ protected function o_fontDescriptor($id, $action, $options = '') /** * the font encoding * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string $options * @return null|string */ protected function o_fontEncoding($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1435,13 +1447,15 @@ protected function o_fontEncoding($id, $action, $options = '') /** * a descendent cid font, needed for unicode fonts * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string|array $options * @return null|string */ protected function o_fontDescendentCID($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1526,8 +1540,8 @@ protected function o_fontDescendentCID($id, $action, $options = '') /** * CID system info section, needed for unicode fonts * - * @param $id - * @param $action + * @param string $id + * @param string $action * @return null|string */ protected function o_cidSystemInfo($id, $action) @@ -1569,13 +1583,15 @@ protected function o_cidSystemInfo($id, $action) /** * a font glyph to character map, needed for unicode fonts * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string $options * @return null|string */ protected function o_fontGIDtoCIDMap($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1626,13 +1642,15 @@ protected function o_fontGIDtoCIDMap($id, $action, $options = '') /** * the document procset, solves some problems with printing to old PS printers * - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param string $options For the 'add' action, 'ImageB', 'ImageC' or 'ImageI' * @return null|string */ protected function o_procset($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1672,8 +1690,8 @@ protected function o_procset($id, $action, $options = '') /** * define the document information * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string $options * @return null|string */ @@ -1738,13 +1756,15 @@ protected function o_info($id, $action, $options = '') /** * an action object, used to link to URLS initially * - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param array|string $options * @return null|string */ protected function o_action($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1799,13 +1819,15 @@ protected function o_action($id, $action, $options = '') * an annotation object, this will add an annotation to the current page. * initially will support just link annotations * - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param array|string $options * @return null|string */ protected function o_annotation($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1865,13 +1887,15 @@ protected function o_annotation($id, $action, $options = '') /** * a page object, it also creates a contents object to hold its contents * - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param array|string $options * @return null|string */ protected function o_page($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -1976,13 +2000,15 @@ protected function o_page($id, $action, $options = '') /** * the contents objects hold all of the content which appears on pages * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string|array $options * @return null|string */ protected function o_contents($id, $action, $options = '') { + $o = []; + if ($action !== 'new') { $o = &$this->objects[$id]; } @@ -2042,8 +2068,8 @@ protected function o_contents($id, $action, $options = '') } /** - * @param $id - * @param $action + * @param string $id + * @param string $action * @return string|null */ protected function o_embedjs($id, $action) @@ -2073,8 +2099,8 @@ protected function o_embedjs($id, $action) } /** - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string $code * @return null|string */ @@ -2109,9 +2135,9 @@ protected function o_javascript($id, $action, $code = '') /** * an image object, will be an XObject in the document, includes description and data * - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param array|string $options * @return null|string */ protected function o_image($id, $action, $options = '') @@ -2251,8 +2277,8 @@ protected function o_image($id, $action, $options = '') /** * graphics state object * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string $options * @return null|string */ @@ -2319,7 +2345,7 @@ protected function o_extGState($id, $action, $options = "") * @param integer $id * @param string $action * @param mixed $options - * @return string + * @return null|string */ protected function o_xobject($id, $action, $options = '') { @@ -2410,9 +2436,9 @@ protected function o_xobject($id, $action, $options = '') } /** - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param array|string $options * @return null|string */ protected function o_acroform($id, $action, $options = '') @@ -2471,8 +2497,8 @@ protected function o_acroform($id, $action, $options = '') } /** - * @param $id - * @param $action + * @param string $id + * @param string $action * @param mixed $options * @return null|string */ @@ -2564,9 +2590,9 @@ protected function o_field($id, $action, $options = '') /** * - * @param $id - * @param $action - * @param string $options + * @param string $id + * @param string $action + * @param array|string $options * @return null|string */ protected function o_sig($id, $action, $options = '') @@ -2673,8 +2699,8 @@ protected function o_sig($id, $action, $options = '') /** * encryption object. * - * @param $id - * @param $action + * @param string $id + * @param string $action * @param string $options * @return string|null */ @@ -2873,12 +2899,13 @@ protected function o_embedded_file($id, $action, $options = null): ?string case 'out': $info = &$this->objects[$id]['info']; + $file_content_compressed = ''; + if ($this->compressionReady) { $filepath = $info['filepath']; $checksum = md5_file($filepath); $f = fopen($filepath, "rb"); - $file_content_compressed = ''; $deflateContext = deflate_init(ZLIB_ENCODING_DEFLATE, ['level' => 6]); while (($block = fread($f, 8192))) { $file_content_compressed .= deflate_add($deflateContext, $block, ZLIB_NO_FLUSH); @@ -2917,7 +2944,7 @@ protected function o_embedded_file($id, $action, $options = null): ?string /** * calculate the 16 byte version of the 128 bit md5 digest of the string * - * @param $string + * @param string $string * @return string */ function md5_16($string) @@ -2934,7 +2961,7 @@ function md5_16($string) /** * initialize the encryption for processing a particular object * - * @param $id + * @param string $id */ function encryptInit($id) { @@ -2990,7 +3017,7 @@ function ARC4_init($key = '') /** * ARC4 encrypt a text string * - * @param $text + * @param string $text * @return string */ function ARC4($text) @@ -3020,7 +3047,7 @@ function ARC4($text) /** * add a link in the document to an external URL * - * @param $url + * @param string $url * @param $x0 * @param $y0 * @param $x1 @@ -3036,7 +3063,7 @@ function addLink($url, $x0, $y0, $x1, $y1) /** * add a link in the document to an internal destination (ie. within the document) * - * @param $label + * @param string $label * @param $x0 * @param $y0 * @param $x1 @@ -3461,7 +3488,7 @@ private function openFont($font) * @param bool $set * @param bool $isSubsetting * @return int - * @throws FontNotFoundException + * @throws \FontLib\Exception\FontNotFoundException */ function selectFont($fontName, $encoding = '', $set = true, $isSubsetting = true) { @@ -4060,7 +4087,7 @@ function ellipse( * @param float $width * @param string $cap * @param string $join - * @param array $dash + * @param array|string $dash * @param int $phase */ function setLineStyle($width = 1, $cap = '', $join = '', $dash = '', $phase = 0) @@ -5257,7 +5284,7 @@ function openObject() /** * open an existing object for editing * - * @param $id + * @param int $id */ function reopenObject($id) { @@ -5290,7 +5317,7 @@ function closeObject() /** * stop an object from appearing on pages from this point on * - * @param $id + * @param string $id */ function stopObject($id) { @@ -5304,8 +5331,8 @@ function stopObject($id) /** * after an object has been created, it wil only show if it has been added, using this function. * - * @param $id - * @param string $options + * @param string $id + * @param string $options 'all', 'add', 'even', 'odd', 'nexteven', 'nextodd' */ function addObject($id, $options = 'add') { @@ -5362,7 +5389,7 @@ function addObject($id, $options = 'add') /** * return a storable representation of a specific object * - * @param $id + * @param string $id * @return string|null */ function serializeObject($id) @@ -5452,9 +5479,9 @@ function setPreferences($label, $value = 0) /** * extract an integer from a position in a byte stream * - * @param $data - * @param $pos - * @param $num + * @param array $data + * @param int $pos + * @param int $num * @return int */ private function getBytes(&$data, $pos, $num) @@ -5493,7 +5520,7 @@ function image_iscached($imgname) * @param float $h Height * @param bool $is_mask true if the image is a mask * @param bool $mask true if the image is masked - * @throws Exception + * @throws \Exception */ function addImagePng(&$img, $file, $x, $y, $w = 0.0, $h = 0.0, $is_mask = false, $mask = null) { @@ -5741,7 +5768,7 @@ protected function addImagePngAlpha($file, $x, $y, $w, $h, $byte) * @param $y * @param int $w * @param int $h - * @throws Exception + * @throws \Exception */ function addPngFromFile($file, $x, $y, $w = 0, $h = 0) { @@ -5836,6 +5863,8 @@ function addPngFromFile($file, $x, $y, $w = 0, $h = 0) */ function addPngFromBuf(&$data, $file, $x, $y, $w = 0.0, $h = 0.0, $is_mask = false, $mask = null) { + $info = []; + if (isset($this->imagelist[$file])) { $data = null; $info['width'] = $this->imagelist[$file]['w']; @@ -6117,9 +6146,9 @@ function addPngFromBuf(&$data, $file, $x, $y, $w = 0.0, $h = 0.0, $is_mask = fal /** * add a JPEG image into the document, from a file * - * @param $img - * @param $x - * @param $y + * @param string $img + * @param int $x + * @param int $y * @param int $w * @param int $h */ @@ -6172,8 +6201,8 @@ function addJpegFromFile($img, $x, $y, $w = 0, $h = 0) * @param $imgname * @param $imageWidth * @param $imageHeight - * @param $x - * @param $y + * @param int $x + * @param int $y * @param int $w * @param int $h * @param int $channels @@ -6303,7 +6332,7 @@ function addDestination($label, $style, $a = 0, $b = 0, $c = 0) * that be desired. * * @param $family - * @param string $options + * @param array|string $options */ function setFontFamily($family, $options = '') { diff --git a/src/Svg/Surface/SurfaceCpdf.php b/src/Svg/Surface/SurfaceCpdf.php index 7169e0e..e974135 100644 --- a/src/Svg/Surface/SurfaceCpdf.php +++ b/src/Svg/Surface/SurfaceCpdf.php @@ -217,7 +217,11 @@ function image($img, $x, $y, $w, $h, $resolution = "normal") case IMAGETYPE_GIF: case IMAGETYPE_BMP: // @todo use cache for BMP and GIF - $img = $this->_convert_gif_bmp_to_png($img, $type); + if (method_exists($this, '_convert_to_png')) { + $img = $this->_convert_to_png($img, $type); + } elseif (method_exists($this, '_convert_gif_bmp_to_png')) {// Old CPDF.php adapters + $img = $this->_convert_gif_bmp_to_png($img, $type); + } case IMAGETYPE_PNG: $this->canvas->addPngFromFile($img, $x, $y - $h, $w, $h);