diff --git a/tcpdf/TCPDF.php b/tcpdf/TCPDF.php index 4a227a9..eca30b8 100644 --- a/tcpdf/TCPDF.php +++ b/tcpdf/TCPDF.php @@ -777,6 +777,9 @@ class TCPDF { */ protected $lispacer = ''; + // @todo: consider to make this static and also include fontname, fontstyle, fontsize + protected array $cachedRawFontWidths = []; + /** * Default encoding. * @protected @@ -4125,7 +4128,7 @@ class TCPDF { */ public function GetArrStringWidth($sa, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) { // store current values - if (!TCPDF_STATIC::empty_string($fontname)) { + if ($fontname !== '') { $prev_FontFamily = $this->FontFamily; $prev_FontStyle = $this->FontStyle; $prev_FontSizePt = $this->FontSizePt; @@ -4144,7 +4147,7 @@ class TCPDF { $w += $cw; } // restore previous values - if (!TCPDF_STATIC::empty_string($fontname)) { + if ($fontname !== '') { $this->setFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt, '', 'default', false); } if ($getarray) { @@ -4164,7 +4167,7 @@ class TCPDF { */ public function GetCharWidth($char, $notlast=true) { // get raw width - $chw = $this->getRawCharWidth($char); + $chw = $this->cachedRawFontWidths[$char] ?? $this->getRawCharWidth($char); if (($this->font_spacing < 0) || (($this->font_spacing > 0) && $notlast)) { // increase/decrease font spacing $chw += $this->font_spacing; @@ -4200,7 +4203,10 @@ class TCPDF { } else { $w = 600; } - return $this->getAbsFontMeasure($w); + + $this->cachedRawFontWidths[$char] = $this->getAbsFontMeasure($w); + + return $this->cachedRawFontWidths[$char]; } /** @@ -4226,7 +4232,7 @@ class TCPDF { if (($fontsdir = \opendir(TCPDF_FONTS::_getfontpath())) !== false) { while (($file = \readdir($fontsdir)) !== false) { if (\substr($file, -4) === '.php') { - \array_push($this->fontlist, \strtolower(\basename($file, '.php'))); + $this->fontlist[] = \strtolower(\basename($file, '.php')); } } \closedir($fontsdir); @@ -4324,9 +4330,9 @@ class TCPDF { } // get specified font directory (if any) $fontdir = false; - if (!TCPDF_STATIC::empty_string($fontfile)) { + if (!empty($fontfile)) { $fontdir = \dirname($fontfile); - if (TCPDF_STATIC::empty_string($fontdir) || ($fontdir === '.')) { + if (empty($fontdir) || ($fontdir === '.')) { $fontdir = ''; } else { $fontdir .= '/'; @@ -4335,11 +4341,11 @@ class TCPDF { // true when the font style variation is missing $missing_style = false; // search and include font file - if (TCPDF_STATIC::empty_string($fontfile) || (!@TCPDF_STATIC::file_exists($fontfile))) { + if (empty($fontfile) || (!@TCPDF_STATIC::file_exists($fontfile))) { // build a standard filenames for specified font $tmp_fontfile = \str_replace(' ', '', $family).\strtolower($style).'.php'; $fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir); - if (TCPDF_STATIC::empty_string($fontfile)) { + if (empty($fontfile)) { $missing_style = true; // try to remove the style part $tmp_fontfile = \str_replace(' ', '', $family).'.php'; @@ -4347,7 +4353,7 @@ class TCPDF { } } // include font file - if (!TCPDF_STATIC::empty_string($fontfile) && (@TCPDF_STATIC::file_exists($fontfile))) { + if (!empty($fontfile) && (@TCPDF_STATIC::file_exists($fontfile))) { include($fontfile); } else { $this->Error('Could not include font definition file: '.$family.''); @@ -4510,6 +4516,9 @@ class TCPDF { if ($size < 0) { $size = 0; } + + $this->cachedRawFontWidths = []; + // try to add font (if not already added) $fontdata = $this->AddFont($family, $style, $fontfile, $subset); $this->FontFamily = $fontdata['family']; @@ -4536,6 +4545,7 @@ class TCPDF { $this->FontSizePt = $size; // font size in user units $this->FontSize = $size / $this->k; + $this->cachedRawFontWidths = []; // calculate some font metrics if (isset($this->CurrentFont['desc']['FontBBox'])) { $bbox = \explode(' ', \substr($this->CurrentFont['desc']['FontBBox'], 1, -1)); @@ -5413,7 +5423,7 @@ class TCPDF { } $txt2 = TCPDF_STATIC::_escape($txt2); // get current text width (considering general font stretching and spacing) - $txwidth = $this->GetStringWidth($txt); + $txwidth = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont), $txt, $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false); $width = $txwidth; // check for stretch mode if ($stretch > 0) { @@ -5467,8 +5477,7 @@ class TCPDF { $spacewidth /= ($this->font_stretching / 100); } // set word position to be used with TJ operator - $txt2 = \str_replace(\chr(0).\chr(32), ') '.\sprintf('%F', $spacewidth).' (', $txt2); - $unicode_justification = true; + $txt2 = \str_replace(\chr(0).\chr(32), ') '.\sprintf('%F', $spacewidth).' (', $txt2); } else { // get string width $width = $txwidth; @@ -6392,7 +6401,11 @@ class TCPDF { $chars = TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont); // calculate maximum width for a single character on string $chrw = $this->GetArrStringWidth($chars, '', '', 0, true); - \array_walk($chrw, [$this, 'getRawCharWidth']); + + // @todo: WHY is tcpdf doing the next step? The function getRawCharWidth doesn't modify the values in $chars!!! + //\array_walk($chars, [$this, 'getRawCharWidth']); + //\array_walk($chrw, [$this, 'getRawCharWidth']); This was the old call, which is even more stupid, since chrw contains widths + $maxchwidth = \max($chrw); // get array of chars $uchars = TCPDF_FONTS::UTF8ArrayToUniArray($chars, $this->isunicode); @@ -8887,7 +8900,7 @@ class TCPDF { foreach ($this->FontFiles as $file => $info) { // search and get font file to embedd $fontfile = TCPDF_FONTS::getFontFullPath($file, $info['fontdir']); - if (!TCPDF_STATIC::empty_string($fontfile)) { + if (!empty($fontfile)) { $font = \file_get_contents($fontfile); $compressed = (\substr($file, -2) === '.z'); if ((!$compressed) && (isset($info['length2']))) { @@ -9105,7 +9118,7 @@ class TCPDF { $ctgfile = \strtolower($font['ctg']); // search and get ctg font file to embedd $fontfile = TCPDF_FONTS::getFontFullPath($ctgfile, $fontdir); - if (TCPDF_STATIC::empty_string($fontfile)) { + if (empty($fontfile)) { $this->Error('Font file not found: '.$ctgfile); } $stream = $this->_getrawstream(\file_get_contents($fontfile)); @@ -10215,7 +10228,7 @@ class TCPDF { * @protected */ protected function _dounderline($x, $y, $txt) { - $w = $this->GetStringWidth($txt); + $w = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont), $txt, $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false); return $this->_dounderlinew($x, $y, $w); } @@ -10240,7 +10253,7 @@ class TCPDF { * @protected */ protected function _dolinethrough($x, $y, $txt) { - $w = $this->GetStringWidth($txt); + $w = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont), $txt, $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false); return $this->_dolinethroughw($x, $y, $w); } @@ -10266,7 +10279,7 @@ class TCPDF { * @since 4.9.015 (2010-04-19) */ protected function _dooverline($x, $y, $txt) { - $w = $this->GetStringWidth($txt); + $w = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont), $txt, $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false); return $this->_dooverlinew($x, $y, $w); } @@ -11476,7 +11489,7 @@ class TCPDF { if (isset($style['dash'])) { $dash_string = ''; if ($style['dash']) { - if (\preg_match('/^.+,/', $style['dash']) > 0) { + if (\preg_match('/^.+,/', (string) $style['dash']) > 0) { $tab = \explode(',', $style['dash']); } else { $tab = [$style['dash']]; @@ -17747,7 +17760,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if ($this->rMargin != $prevrMargin) { $tw += ($prevrMargin - $this->rMargin); } - $one_space_width = $this->GetStringWidth(\chr(32)); + $one_space_width = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray(\chr(32), $this->isunicode, $this->CurrentFont), \chr(32), $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false); $no = 0; // number of spaces on a line contained on a single block if ($this->isRTLTextDir()) { // RTL // remove left space if exist @@ -18695,7 +18708,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if ($this->rMargin != $prevrMargin) { $tw += ($prevrMargin - $this->rMargin); } - $one_space_width = $this->GetStringWidth(\chr(32)); + $one_space_width = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray(\chr(32), $this->isunicode, $this->CurrentFont), \chr(32), $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false); $no = 0; // number of spaces on a line contained on a single block if ($this->isRTLTextDir()) { // RTL // remove left space if exist @@ -19277,7 +19290,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: } $h = $this->getCellHeight($this->FontSize); if (isset($tag['attribute']['size']) && !TCPDF_STATIC::empty_string($tag['attribute']['size'])) { - $w = (int) ($tag['attribute']['size']) * $this->GetStringWidth(\chr(32)) * 2; + $w = (int) ($tag['attribute']['size']) * $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray(\chr(32), $this->isunicode, $this->CurrentFont), \chr(32), $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false) * 2; } else { $w = $h; } @@ -19336,7 +19349,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if (!isset($value)) { $value = 'submit'; } - $w = $this->GetStringWidth($value) * 1.5; + $w = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($value, $this->isunicode, $this->CurrentFont), $value, $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false) * 1.5; $h *= 1.6; $prop = ['lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]]; $action = []; @@ -19355,7 +19368,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if (!isset($value)) { $value = 'reset'; } - $w = $this->GetStringWidth($value) * 1.5; + $w = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($value, $this->isunicode, $this->CurrentFont), $value, $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false) * 1.5; $h *= 1.6; $prop = ['lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]]; $this->Button($name, $w, $h, $value, ['S'=>'ResetForm'], $prop, $opt, '', '', false); @@ -19367,7 +19380,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if (!isset($value)) { $value = '*'; } - $w = $this->GetStringWidth($value) * 2; + $w = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($value, $this->isunicode, $this->CurrentFont), $value, $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false) * 2; $h *= 1.2; $prop = ['lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]]; $jsaction = 'var f=this.getField(\''.$name.'\'); f.browseForFileToSubmit();'; @@ -19403,7 +19416,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: if (!isset($value)) { $value = ' '; } - $w = $this->GetStringWidth($value) * 1.5; + $w = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($value, $this->isunicode, $this->CurrentFont), $value, $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false) * 1.5; $h *= 1.6; $prop = ['lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>[196, 196, 196], 'strokeColor'=>[255, 255, 255]]; if (isset($tag['attribute']['onclick']) && !empty($tag['attribute']['onclick'])) { @@ -19432,7 +19445,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $opt['v'] = $tag['attribute']['value']; } if (isset($tag['attribute']['cols']) && !TCPDF_STATIC::empty_string($tag['attribute']['cols'])) { - $w = (int) ($tag['attribute']['cols']) * $this->GetStringWidth(\chr(32)) * 2; + $w = (int) ($tag['attribute']['cols']) * $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray(\chr(32), $this->isunicode, $this->CurrentFont), \chr(32), $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false) * 2; } else { $w = 40; } @@ -21471,7 +21484,7 @@ Putting 1 is equivalent to putting 0 and calling Ln() just after. Default value: $fontfamily = $this->FontFamily; $fontstyle = $this->FontStyle; $w = $this->w - $this->lMargin - $this->rMargin; - $spacer = $this->GetStringWidth(\chr(32)) * 4; + $spacer = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray(\chr(32), $this->isunicode, $this->CurrentFont), \chr(32), $this->tmprtl, $this->isunicode, $this->CurrentFont), '', '', 0, false) * 4; $lmargin = $this->lMargin; $rmargin = $this->rMargin; $x_start = $this->GetX(); diff --git a/tcpdf/include/TCPDF_FONTS.php b/tcpdf/include/TCPDF_FONTS.php index c09377a..80e4da5 100644 --- a/tcpdf/include/TCPDF_FONTS.php +++ b/tcpdf/include/TCPDF_FONTS.php @@ -1724,10 +1724,7 @@ class TCPDF_FONTS { * @public static */ public static function UTF8ArrayToUniArray($ta, $isunicode=true) { - if ($isunicode) { - return \array_map(['TCPDF_FONTS', 'unichrUnicode'], $ta); - } - return \array_map(['TCPDF_FONTS', 'unichrASCII'], $ta); + return \array_map(['TCPDF_FONTS', 'unichr'], $ta); } /** @@ -1786,7 +1783,7 @@ class TCPDF_FONTS { foreach ($unicode as $char) { if ($char < 256) { $outarr[] = $char; - } elseif (\array_key_exists($char, TCPDF_FONT_DATA::$uni_utf8tolatin)) { + } elseif (isset(TCPDF_FONT_DATA::$uni_utf8tolatin[$char])) { // map from UTF-8 $outarr[] = TCPDF_FONT_DATA::$uni_utf8tolatin[$char]; } elseif ($char == 0xFFFD) { @@ -1811,7 +1808,7 @@ class TCPDF_FONTS { foreach ($unicode as $char) { if ($char < 256) { $outstr .= \chr($char); - } elseif (\array_key_exists($char, TCPDF_FONT_DATA::$uni_utf8tolatin)) { + } elseif (isset(TCPDF_FONT_DATA::$uni_utf8tolatin[$char])) { // map from UTF-8 $outstr .= \chr(TCPDF_FONT_DATA::$uni_utf8tolatin[$char]); } elseif ($char == 0xFFFD) { @@ -1832,7 +1829,7 @@ class TCPDF_FONTS { */ public static function uniord($uch) { if (!isset(self::$cache_uniord[$uch])) { - self::$cache_uniord[$uch] = self::getUniord($uch); + self::$cache_uniord[$uch] = \mb_ord($uch); //self::getUniord($uch); } return self::$cache_uniord[$uch]; } @@ -1942,11 +1939,11 @@ class TCPDF_FONTS { public static function UTF8StringToArray($str, $isunicode, &$currentfont) { if ($isunicode) { // requires PCRE unicode support turned on - $chars = TCPDF_STATIC::pregSplit('//','u', $str, -1, \PREG_SPLIT_NO_EMPTY); - $carr = \array_map(['TCPDF_FONTS', 'uniord'], $chars); + $chars = \preg_split('//u', $str, -1, \PREG_SPLIT_NO_EMPTY); + $carr = \array_map('\mb_ord', $chars); // uniord } else { $chars = \str_split($str); - $carr = \array_map('ord', $chars); + $carr = \array_map('\ord', $chars); } if (\is_array($currentfont['subsetchars']) && \is_array($carr)) { $currentfont['subsetchars'] += \array_fill_keys($carr, true); diff --git a/tcpdf/include/TCPDF_STATIC.php b/tcpdf/include/TCPDF_STATIC.php index 0d3f89e..77984a7 100644 --- a/tcpdf/include/TCPDF_STATIC.php +++ b/tcpdf/include/TCPDF_STATIC.php @@ -2586,37 +2586,21 @@ class TCPDF_STATIC { switch ($layout) { case 'default': case 'single': - case 'SinglePage': { - $layout_mode = 'SinglePage'; - break; - } + case 'SinglePage': + return 'SinglePage'; case 'continuous': - case 'OneColumn': { - $layout_mode = 'OneColumn'; - break; - } + case 'OneColumn': + return 'OneColumn'; case 'two': - case 'TwoColumnLeft': { - $layout_mode = 'TwoColumnLeft'; - break; - } - case 'TwoColumnRight': { - $layout_mode = 'TwoColumnRight'; - break; - } - case 'TwoPageLeft': { - $layout_mode = 'TwoPageLeft'; - break; - } - case 'TwoPageRight': { - $layout_mode = 'TwoPageRight'; - break; - } - default: { - $layout_mode = 'SinglePage'; - } + case 'TwoColumnLeft': + return 'TwoColumnLeft'; + case 'TwoColumnRight': + case 'TwoPageLeft': + case 'TwoPageRight': + return $layout; + default: + return 'SinglePage'; } - return $layout_mode; } /** @@ -2627,35 +2611,17 @@ class TCPDF_STATIC { */ public static function getPageMode($mode='UseNone') { switch ($mode) { - case 'UseNone': { - $page_mode = 'UseNone'; - break; - } - case 'UseOutlines': { - $page_mode = 'UseOutlines'; - break; - } - case 'UseThumbs': { - $page_mode = 'UseThumbs'; - break; - } - case 'FullScreen': { - $page_mode = 'FullScreen'; - break; - } - case 'UseOC': { - $page_mode = 'UseOC'; - break; - } - case '': { - $page_mode = 'UseAttachments'; - break; - } - default: { - $page_mode = 'UseNone'; - } + case 'UseNone': + case 'UseOutlines': + case 'UseThumbs': + case 'FullScreen': + case 'UseOC': + return $mode; + case '': + return 'UseAttachments'; + default: + return 'UseNone'; } - return $page_mode; } } // END OF TCPDF_STATIC CLASS