1: <?php
2: /**
3: * Buffer.php
4: *
5: * @since 2011-05-23
6: * @category Library
7: * @package PdfFont
8: * @author Nicola Asuni <info@tecnick.com>
9: * @copyright 2011-2015 Nicola Asuni - Tecnick.com LTD
10: * @license http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
11: * @link https://github.com/tecnickcom/tc-lib-pdf-font
12: *
13: * This file is part of tc-lib-pdf-font software library.
14: */
15:
16: namespace Com\Tecnick\Pdf\Font;
17:
18: use \Com\Tecnick\Pdf\Font\Font;
19: use \Com\Tecnick\Pdf\Font\Exception as FontException;
20:
21: /**
22: * Com\Tecnick\Pdf\Font\Buffer
23: *
24: * @since 2011-05-23
25: * @category Library
26: * @package PdfFont
27: * @author Nicola Asuni <info@tecnick.com>
28: * @copyright 2011-2015 Nicola Asuni - Tecnick.com LTD
29: * @license http://www.gnu.org/copyleft/lesser.html GNU-LGPL v3 (see LICENSE.TXT)
30: * @link https://github.com/tecnickcom/tc-lib-pdf-font
31: */
32: abstract class Buffer
33: {
34: /**
35: * Array containing all fonts data
36: *
37: * @var array
38: */
39: protected $font = array();
40:
41: /**
42: * Font counter
43: *
44: * @var int
45: */
46: protected $numfonts = 0;
47:
48: /**
49: * Array containing encoding differences
50: *
51: * @var array
52: */
53: protected $encdiff = array();
54:
55: /**
56: * Index for Encoding differences
57: *
58: * @var int
59: */
60: protected $numdiffs = 0;
61:
62: /**
63: * Array containing font definitions grouped by file
64: *
65: * @var array
66: */
67: protected $file = array();
68:
69: /**
70: * Default subset mode
71: *
72: * @var bool
73: */
74: protected $subset = false;
75:
76: /**
77: * True if we are in Unicode mode, False otherwhise.
78: *
79: * @var bool
80: */
81: protected $unicode = true;
82:
83: /**
84: * True if we are in PDF/A mode.
85: *
86: * @var bool
87: */
88: protected $pdfa = false;
89:
90: /**
91: * Unit of measure conversion ratio
92: *
93: * @var float
94: */
95: protected $kunit = 1.0;
96:
97: /**
98: * Initialize fonts buffer
99: *
100: * @param float $kunit Unit of measure conversion ratio.
101: * @param bool $subset If true embedd only a subset of the fonts
102: * (stores only the information related to the used characters);
103: * If false embedd full font;
104: * This option is valid only for TrueTypeUnicode fonts and it is disabled for PDF/A.
105: * If you want to enable users to modify the document, set this parameter to false.
106: * If you subset the font, the person who receives your PDF would need to have
107: * your same font in order to make changes to your PDF.
108: * The file size of the PDF would also be smaller because you are embedding only a subset.
109: * NOTE: This option is computational and memory intensive.
110: * @param bool $unicode True if we are in Unicode mode, False otherwhise.
111: * @param bool $pdfa True if we are in PDF/A mode.
112: *
113: * @return string Font key
114: *
115: * @throws FontException in case of error
116: */
117: public function __construct($kunit, $subset = false, $unicode = true, $pdfa = false)
118: {
119: $this->kunit = (float) $kunit;
120: $this->subset = (bool) $subset;
121: $this->unicode = (bool) $unicode;
122: $this->pdfa = (bool) $pdfa;
123: }
124:
125: /**
126: * Get the default subset mode
127: *
128: * @return bool
129: */
130: public function isSubsetMode()
131: {
132: return $this->subset;
133: }
134:
135: /**
136: * Returns the fonts buffer
137: *
138: * @return array
139: */
140: public function getFonts()
141: {
142: return $this->font;
143: }
144:
145: /**
146: * Returns the fonts buffer
147: *
148: * @return array
149: */
150: public function getEncDiffs()
151: {
152: return $this->encdiff;
153: }
154:
155: /**
156: * Returns true if the specified font key exist on buffer
157: *
158: * @param string $key Font key
159: *
160: * @return bool
161: */
162: public function isValidKey($key)
163: {
164: return isset($this->font[$key]);
165: }
166:
167: /**
168: * Get font by key
169: *
170: * @param string $key Font key
171: *
172: * @return array|bool Returns the fonts array of palse in case of missing font.
173: *
174: * @throws FontException in case of error
175: */
176: public function getFont($key)
177: {
178: if (!isset($this->font[$key])) {
179: throw new FontException('The font '.$key.' has not been loaded');
180: }
181: return $this->font[$key];
182: }
183:
184: /**
185: * Set font sub-key value
186: *
187: * @param int $key The font key
188: * @param int $subkey Font sub-key
189: * @param mixed $data The data to set
190: */
191: public function setFontSubKey($key, $subkey, $data)
192: {
193: if (!isset($this->font[$key])) {
194: $this->font[$key] = array();
195: }
196: $this->font[$key][$subkey] = $data;
197: }
198:
199: /**
200: * Add a character to the subset list
201: *
202: * @param int $key The font key
203: * @param int $char The Unicode character value to add
204: */
205: public function addSubsetChar($key, $char)
206: {
207: $this->font[$key]['subsetchars'][$char] = true;
208: }
209:
210: /**
211: * Add a new font to the fonts buffer
212: *
213: * The definition file (and the font file itself when embedding) must be present either in the current directory
214: * or in the one indicated by K_PATH_FONTS if the constant is defined.
215: *
216: * @param int $objnum Current PDF object number
217: * @param string $font Font family.
218: * If it is a standard family name, it will override the corresponding font.
219: * @param string $style Font style.
220: * Possible values are (case insensitive):
221: * regular (default)
222: * B: bold
223: * I: italic
224: * U: underline
225: * D: strikeout (linethrough)
226: * O: overline
227: * @param string $ifile The font definition file (or empty for autodetect).
228: * By default, the name is built from the family and style, in lower case with no spaces.
229: * @param bool $subset If true embedd only a subset of the font
230: * (stores only the information related to the used characters);
231: * If false embedd full font;
232: * This option is valid only for TrueTypeUnicode fonts and it is disabled for PDF/A.
233: * If you want to enable users to modify the document, set this parameter to false.
234: * If you subset the font, the person who receives your PDF would need to have
235: * your same font in order to make changes to your PDF.
236: * The file size of the PDF would also be smaller because you are embedding only a subset.
237: * Set this to null to use the default value.
238: * NOTE: This option is computational and memory intensive.
239: *
240: * @return string Font key
241: *
242: * @throws FontException in case of error
243: */
244: public function add(&$objnum, $font, $style = '', $ifile = '', $subset = null)
245: {
246: if ($subset === null) {
247: $subset = $this->subset;
248: }
249: $fobj = new Font($font, $style, $ifile, $subset, $this->unicode, $this->pdfa);
250: $key = $fobj->getFontkey();
251:
252: if (isset($this->font[$key])) {
253: return $key;
254: }
255:
256: $fobj->load();
257: $this->font[$key] = $fobj->getFontData();
258:
259: $this->setFontFile($key);
260: $this->setFontDiff($key);
261:
262: $this->font[$key]['i'] = $this->numfonts++;
263: $this->font[$key]['n'] = ++$objnum;
264:
265: return $key;
266: }
267:
268: /**
269: * Set font file and subset
270: *
271: * @param string $key Font key
272: */
273: protected function setFontFile($key)
274: {
275: if (empty($this->font[$key]['file'])) {
276: return;
277: }
278: $file = $this->font[$key]['file'];
279: if (!isset($this->file[$file])) {
280: $this->file[$file] = array('keys' => array());
281: }
282: if (!in_array($key, $this->file[$file]['keys'])) {
283: $this->file[$file]['keys'][] = $key;
284: }
285: $this->file[$file]['dir'] = $this->font[$key]['dir'];
286: $this->file[$file]['length1'] = $this->font[$key]['length1'];
287: $this->file[$file]['length2'] = $this->font[$key]['length2'];
288:
289: if (!isset($this->file[$file]['subset'])) {
290: $this->file[$file]['subset'] = true;
291: }
292: $this->file[$file]['subset'] = ($this->file[$file]['subset'] && $this->font[$key]['subset']);
293: }
294:
295: /**
296: * Set font diff
297: *
298: * @param string $key Font key
299: */
300: protected function setFontDiff($key)
301: {
302: if (empty($this->font[$key]['diff'])) {
303: return;
304: }
305: $diffid = array_search($this->font[$key]['diff'], $this->encdiff);
306: if ($diffid === false) {
307: $diffid = ++$this->numdiffs;
308: $this->encdiff[$diffid] = $this->font[$key]['diff'];
309: }
310: $this->font[$key]['diffid'] = $diffid;
311: }
312: }
313: