1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
15:
16: namespace Com\Tecnick\Pdf\Font;
17:
18: use \Com\Tecnick\Unicode\Data\Identity;
19: use \Com\Tecnick\Pdf\Encrypt\Encrypt;
20: use \Com\Tecnick\Pdf\Font\Exception as FontException;
21:
22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32:
33: abstract class OutFont extends \Com\Tecnick\Pdf\Font\OutUtil
34: {
35: 36: 37: 38: 39:
40: protected $pon;
41:
42: 43: 44: 45: 46:
47: protected $enc;
48:
49: 50: 51: 52: 53: 54: 55: 56:
57: protected function getCid0(array $font)
58: {
59: $cidoffset = 0;
60: if (!isset($font['cw'][1])) {
61: $cidoffset = 31;
62: }
63: $this->uniToCid($font, $cidoffset);
64: $name = $font['name'];
65: $longname = $name;
66: if (!empty($font['enc'])) {
67: $longname .= '-'.$font['enc'];
68: }
69:
70:
71: $out = $font['n'].' 0 obj'."\n"
72: .'<</Type /Font'
73: .' /Subtype /Type0'
74: .' /BaseFont /'.$longname
75: .' /Name /F'.$font['i'];
76: if (!empty($font['enc'])) {
77: $out .= ' /Encoding /'.$font['enc'];
78: }
79: $out .= ' /DescendantFonts ['.($this->pon + 1).' 0 R]'
80: .' >>'."\n"
81: .'endobj'."\n";
82:
83:
84: $out .= (++$this->pon).' 0 obj'."\n"
85: .'<</Type /Font'
86: .' /Subtype /CIDFontType0'
87: .' /BaseFont /'.$name;
88: $cidinfo = '/Registry '.$this->enc->escapeDataString($font['cidinfo']['Registry'], $this->pon)
89: .' /Ordering '.$this->enc->escapeDataString($font['cidinfo']['Ordering'], $this->pon)
90: .' /Supplement '.$font['cidinfo']['Supplement'];
91: $out .= ' /CIDSystemInfo <<'.$cidinfo.'>>'
92: .' /FontDescriptor '.($this->pon + 1).' 0 R'
93: .' /DW '.$font['dw']."\n"
94: .$this->getCharWidths($font, $cidoffset)
95: .' >>'."\n"
96: .'endobj'."\n";
97:
98:
99: $out .= (++$this->pon).' 0 obj'."\n"
100: .'<</Type /FontDescriptor /FontName /'.$name;
101: foreach ($font['desc'] as $key => $val) {
102: if ($key != 'Style') {
103: $out .= $this->getKeyValOut($key, $val);
104: }
105: }
106: $out .= '>>'."\n"
107: .'endobj'."\n";
108:
109: return $out;
110: }
111:
112: 113: 114: 115: 116: 117: 118: 119:
120: protected function uniToCid(array &$font, $cidoffset)
121: {
122: if (isset($font['cidinfo']['uni2cid'])) {
123:
124: $uni2cid = $font['cidinfo']['uni2cid'];
125: $chw = array();
126: foreach ($font['cw'] as $uni => $width) {
127: if (isset($uni2cid[$uni])) {
128: $chw[($uni2cid[$uni] + $cidoffset)] = $width;
129: } elseif ($uni < 256) {
130: $chw[$uni] = $width;
131: }
132: }
133: $font['cw'] = array_merge($font['cw'], $chw);
134: }
135: }
136:
137: 138: 139: 140: 141: 142: 143: 144:
145: protected function getTrueTypeUnicode(array $font)
146: {
147: $fontname = '';
148: if ($font['subset']) {
149:
150: $subtag = sprintf('%06u', $font['i']);
151: $subtag = strtr($subtag, '0123456789', 'ABCDEFGHIJ');
152: $fontname .= $subtag.'+';
153: }
154: $fontname .= $font['name'];
155:
156:
157:
158:
159:
160: $out = $font['n'].' 0 obj'."\n"
161: .'<< /Type /Font'
162: .' /Subtype /Type0'
163: .' /BaseFont /'.$fontname
164: .' /Name /F'.$font['i']
165: .' /Encoding /'.$font['enc']
166: .' /ToUnicode '.($this->pon + 1).' 0 R'
167: .' /DescendantFonts ['.($this->pon + 2).' 0 R]'
168: .' >>'."\n"
169: .'endobj'."\n";
170:
171:
172: $out .= (++$this->pon).' 0 obj'."\n";
173: $stream = $this->enc->encryptString(gzcompress(Identity::CIDHMAP), $this->pon);
174: $out .= '<</Filter /FlateDecode /Length '.strlen($stream).'>> stream'."\n"
175: .$stream."\n"
176: .'endstream'."\n"
177: .'endobj'."\n";
178:
179:
180:
181: $out .= (++$this->pon).' 0 obj'."\n"
182: .'<< /Type /Font'
183: .' /Subtype /CIDFontType2'
184: .' /BaseFont /'.$fontname;
185:
186: $cidinfo = '/Registry '.$this->enc->escapeDataString($font['cidinfo']['Registry'], $this->pon)
187: .' /Ordering '.$this->enc->escapeDataString($font['cidinfo']['Ordering'], $this->pon)
188: .' /Supplement '.$font['cidinfo']['Supplement'];
189: $out .= ' /CIDSystemInfo << '.$cidinfo.' >>'
190: .' /FontDescriptor '.($this->pon + 1).' 0 R'
191: .' /DW '.$font['dw']."\n"
192: .$this->getCharWidths($font, 0);
193: if (!empty($font['ctg'])) {
194: $out .= "\n".'/CIDToGIDMap '.($this->pon + 2).' 0 R';
195: }
196: $out .= ' >>'."\n"
197: .'endobj'."\n";
198:
199:
200:
201: $out .= (++$this->pon).' 0 obj'."\n"
202: .'<< /Type /FontDescriptor'
203: .' /FontName /'.$fontname;
204: foreach ($font['desc'] as $key => $val) {
205: $out .= $this->getKeyValOut($key, $val);
206: }
207:
208: if (!empty($font['file_n'])) {
209:
210: $out .= ' /FontFile2 '.$font['file_n'].' 0 R';
211: }
212: $out .= ' >>'."\n"
213: .'endobj'."\n";
214:
215: if (!empty($font['ctg'])) {
216: $out .= (++$this->pon).' 0 obj'."\n";
217:
218:
219:
220: $ctgfile = strtolower($font['ctg']);
221:
222: $fontfile = $this->getFontFullPath($font['dir'], $ctgfile);
223: $stream = $this->enc->encryptString(file_get_contents($fontfile), $this->pon);
224: $out .= '<< /Length '.strlen($stream).'';
225: if (substr($fontfile, -2) == '.z') {
226:
227:
228:
229: $out .= ' /Filter /FlateDecode';
230: }
231: $out .= ' >>'
232: .' stream'."\n"
233: .$stream."\n"
234: .'endstream'."\n"
235: .'endobj'."\n";
236: }
237:
238: return $out;
239: }
240:
241: 242: 243: 244: 245: 246: 247:
248: protected function getCore(array $font)
249: {
250: $out = $font['n'].' 0 obj'."\n"
251: .'<</Type /Font'
252: .' /Subtype /Type1'
253: .' /BaseFont /'.$font['name']
254: .' /Name /F'.$font['i'];
255: if (($font['family'] != 'symbol') && ($font['family'] != 'zapfdingbats')) {
256: $out .= ' /Encoding /WinAnsiEncoding';
257: }
258: $out .= ' >>'."\n"
259: .'endobj'."\n";
260: return $out;
261: }
262:
263: 264: 265: 266: 267: 268: 269:
270: protected function getTrueType(array $font)
271: {
272:
273: $out = $font['n'].' 0 obj'."\n"
274: .'<</Type /Font'
275: .' /Subtype /'.$font['type']
276: .' /BaseFont /'.$font['name']
277: .' /Name /F'.$font['i']
278: .' /FirstChar 32 /LastChar 255'
279: .' /Widths '.($this->pon + 1).' 0 R'
280: .' /FontDescriptor '.($this->pon + 2).' 0 R';
281: if (!empty($font['enc'])) {
282: if (isset($font['diff_n'])) {
283: $out .= ' /Encoding '.$font['diff_n'].' 0 R';
284: } else {
285: $out .= ' /Encoding /WinAnsiEncoding';
286: }
287: }
288: $out .= ' >>'."\n"
289: .'endobj'."\n";
290:
291:
292: $out .= (++$this->pon).' 0 obj'."\n"
293: .'[';
294: for ($idx = 32; $idx < 256; ++$idx) {
295: if (isset($font['cw'][$idx])) {
296: $out .= $font['cw'][$idx].' ';
297: } else {
298: $out .= $font['dw'].' ';
299: }
300: }
301: $out .= ']'."\n"
302: .'endobj'."\n";
303:
304:
305: $out .= (++$this->pon).' 0 obj'."\n"
306: .'<</Type /FontDescriptor /FontName /'.$font['name'];
307: foreach ($font['desc'] as $fdk => $fdv) {
308: $out .= $this->getKeyValOut($fdk, $fdv);
309: }
310: if (!empty($font['file'])) {
311: $out .= ' /FontFile'.($font['type'] == 'Type1' ? '' : '2').' '.$font['file_n'].' 0 R';
312: }
313: $out .= '>>'."\n"
314: .'endobj'."\n";
315:
316: return $out;
317: }
318:
319: 320: 321: 322: 323: 324: 325: 326:
327: protected function getKeyValOut($key, $val)
328: {
329: if (is_float($val)) {
330: $val = sprintf('%F', $val);
331: }
332: return ' /'.$key.' '.$val.'';
333: }
334: }
335: