Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
94.12% |
32 / 34 |
|
90.91% |
10 / 11 |
CRAP | |
0.00% |
0 / 1 |
Font | |
94.12% |
32 / 34 |
|
90.91% |
10 / 11 |
19.07 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
2 | |||
standardFonts | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setFont | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
3 | |||
getFont | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getName | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isStandard | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isEmbedded | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStandardFonts | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getParsedFont | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
getStringWidth | |
85.71% |
12 / 14 |
|
0.00% |
0 / 1 |
5.07 | |||
parser | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (http://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@nolainteractive.com> |
7 | * @copyright Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Pdf\Document; |
15 | |
16 | use Pop\Pdf\Build\Font\AbstractFont; |
17 | use Pop\Pdf\Build\Font\Parser; |
18 | |
19 | /** |
20 | * Pdf font class |
21 | * |
22 | * @category Pop |
23 | * @package Pop\Pdf |
24 | * @author Nick Sagona, III <dev@nolainteractive.com> |
25 | * @copyright Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
26 | * @license http://www.popphp.org/license New BSD License |
27 | * @version 4.2.0 |
28 | */ |
29 | class Font |
30 | { |
31 | |
32 | /** |
33 | * Standard font constants |
34 | */ |
35 | const ARIAL = 'Arial'; |
36 | const ARIAL_ITALIC = 'Arial,Italic'; |
37 | const ARIAL_BOLD = 'Arial,Bold'; |
38 | const ARIAL_BOLD_ITALIC = 'Arial,BoldItalic'; |
39 | const COURIER = 'Courier'; |
40 | const COURIER_OBLIQUE = 'Courier-Oblique'; |
41 | const COURIER_BOLD = 'Courier-Bold'; |
42 | const COURIER_BOLD_OBLIQUE = 'Courier-BoldOblique'; |
43 | const COURIER_NEW = 'CourierNew'; |
44 | const COURIER_NEW_ITALIC = 'CourierNew,Italic'; |
45 | const COURIER_NEW_BOLD = 'CourierNew,Bold'; |
46 | const COURIER_NEW_BOLD_ITALIC = 'CourierNew,BoldItalic'; |
47 | const HELVETICA = 'Helvetica'; |
48 | const HELVETICA_OBLIQUE = 'Helvetica-Oblique'; |
49 | const HELVETICA_BOLD = 'Helvetica-Bold'; |
50 | const HELVETICA_BOLD_OBLIQUE = 'Helvetica-BoldOblique'; |
51 | const SYMBOL = 'Symbol'; |
52 | const TIMES_ROMAN = 'Times-Roman'; |
53 | const TIMES_BOLD = 'Times-Bold'; |
54 | const TIMES_ITALIC = 'Times-Italic'; |
55 | const TIMES_BOLD_ITALIC = 'Times-BoldItalic'; |
56 | const TIMES_NEW_ROMAN = 'TimesNewRoman'; |
57 | const TIMES_NEW_ROMAN_ITALIC = 'TimesNewRoman,Italic'; |
58 | const TIMES_NEW_ROMAN_BOLD = 'TimesNewRoman,Bold'; |
59 | const TIMES_NEW_ROMAN_BOLDITALIC = 'TimesNewRoman,BoldItalic'; |
60 | const ZAPF_DINGBATS = 'ZapfDingbats'; |
61 | |
62 | /** |
63 | * Standard PDF fonts |
64 | * @var array |
65 | */ |
66 | protected $standardFonts = [ |
67 | 'Arial', 'Arial,Italic', 'Arial,Bold', 'Arial,BoldItalic', 'Courier', 'CourierNew', 'Courier-Oblique', |
68 | 'CourierNew,Italic', 'Courier-Bold', 'CourierNew,Bold', 'Courier-BoldOblique', 'CourierNew,BoldItalic', |
69 | 'Helvetica', 'Helvetica-Oblique', 'Helvetica-Bold', 'Helvetica-BoldOblique', 'Symbol', 'Times-Roman', |
70 | 'Times-Bold', 'Times-Italic', 'Times-BoldItalic', 'TimesNewRoman', 'TimesNewRoman,Italic', |
71 | 'TimesNewRoman,Bold', 'TimesNewRoman,BoldItalic', 'ZapfDingbats' |
72 | ]; |
73 | |
74 | /** |
75 | * Font |
76 | * @var string |
77 | */ |
78 | protected $font = null; |
79 | |
80 | /** |
81 | * Font name |
82 | * @var string |
83 | */ |
84 | protected $name = null; |
85 | |
86 | /** |
87 | * Flag for a standard font |
88 | * @var boolean |
89 | */ |
90 | protected $isStandard = false; |
91 | |
92 | /** |
93 | * Flag for an embedded font file |
94 | * @var boolean |
95 | */ |
96 | protected $isEmbedded = false; |
97 | |
98 | /** |
99 | * Font parser |
100 | * @var Parser |
101 | */ |
102 | protected $parser = null; |
103 | |
104 | /** |
105 | * Constructor |
106 | * |
107 | * Instantiate a PDF font. |
108 | * |
109 | * @param string $font |
110 | */ |
111 | public function __construct($font = null) |
112 | { |
113 | if (null !== $font) { |
114 | $this->setFont($font); |
115 | } |
116 | } |
117 | |
118 | /** |
119 | * Get standard PDF fonts in an array |
120 | * |
121 | * @return array |
122 | */ |
123 | public static function standardFonts() |
124 | { |
125 | return (new self())->getStandardFonts(); |
126 | } |
127 | |
128 | /** |
129 | * Set font |
130 | * |
131 | * @param string $font |
132 | * @throws \InvalidArgumentException |
133 | * @return Font |
134 | */ |
135 | public function setFont($font) |
136 | { |
137 | $this->font = $font; |
138 | if (in_array($font, $this->standardFonts)) { |
139 | $this->isStandard = true; |
140 | $this->name = $font; |
141 | } else if (file_exists($font)) { |
142 | $this->isEmbedded = true; |
143 | $this->parser = new Parser($this->font); |
144 | $this->name = $this->parser->getFontName(); |
145 | } else { |
146 | throw new \InvalidArgumentException( |
147 | "Error: The font '" . $font . "' is not valid. It must be a standard PDF font or a font file." |
148 | ); |
149 | } |
150 | |
151 | return $this; |
152 | } |
153 | |
154 | /** |
155 | * Get font |
156 | * |
157 | * @return string |
158 | */ |
159 | public function getFont() |
160 | { |
161 | return $this->font; |
162 | } |
163 | |
164 | /** |
165 | * Get font name |
166 | * |
167 | * @return string |
168 | */ |
169 | public function getName() |
170 | { |
171 | return $this->name; |
172 | } |
173 | |
174 | /** |
175 | * Determine if the font is a standard font |
176 | * |
177 | * @return boolean |
178 | */ |
179 | public function isStandard() |
180 | { |
181 | return $this->isStandard; |
182 | } |
183 | |
184 | /** |
185 | * Determine if the font is an embedded font |
186 | * |
187 | * @return boolean |
188 | */ |
189 | public function isEmbedded() |
190 | { |
191 | return $this->isEmbedded; |
192 | } |
193 | |
194 | /** |
195 | * Get available standard fonts |
196 | * |
197 | * @return array |
198 | */ |
199 | public function getStandardFonts() |
200 | { |
201 | return $this->standardFonts; |
202 | } |
203 | |
204 | /** |
205 | * Get the font parser |
206 | * |
207 | * @return AbstractFont |
208 | */ |
209 | public function getParsedFont() |
210 | { |
211 | return (null !== $this->parser) ? $this->parser->getFont() : null; |
212 | } |
213 | |
214 | /** |
215 | * Attempt to get string width |
216 | * |
217 | * @param string $string |
218 | * @param mixed $size |
219 | * @throws Exception |
220 | * @return mixed |
221 | */ |
222 | public function getStringWidth($string, $size) |
223 | { |
224 | if (null !== $this->parser) { |
225 | return $this->parser->getFont()->getStringWidth($string, $size); |
226 | } else { |
227 | $fontClass = '\Pop\Pdf\Build\Font\Standard\\' . str_replace([',', '-'], ['', ''], $this->name); |
228 | if (!class_exists($fontClass)) { |
229 | throw new Exception('Error: That standard font class was not found.'); |
230 | } |
231 | $font = new $fontClass(); |
232 | $widths = []; |
233 | |
234 | $drawingString = iconv('UTF-8', 'UTF-16BE//IGNORE', $string); |
235 | $characters = []; |
236 | |
237 | for ($i = 0; $i < strlen($drawingString); $i++) { |
238 | $characters[] = (ord($drawingString[$i++]) << 8 ) | ord($drawingString[$i]); |
239 | } |
240 | |
241 | foreach ($characters as $character) { |
242 | $widths[] = $font->getGlyphWidth($character); |
243 | } |
244 | |
245 | return (array_sum($widths) / $font->getUnitsPerEm()) * $size; |
246 | } |
247 | } |
248 | |
249 | /** |
250 | * Get the font parser |
251 | * |
252 | * @return Parser |
253 | */ |
254 | public function parser() |
255 | { |
256 | return $this->parser; |
257 | } |
258 | |
259 | } |