]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/fpdf/chinese.php
Reformat code
[SourceForge/phpwiki.git] / lib / fpdf / chinese.php
1 <?php // -*-php-*-
2
3 // PDF functions taken from FPDF http://www.fpdf.org
4
5 require 'lib/pdf.php';
6
7 $Big5_widths = array(' ' => 250, '!' => 250, '"' => 408, '#' => 668, '$' => 490, '%' => 875, '&' => 698, '\'' => 250,
8     '(' => 240, ')' => 240, '*' => 417, '+' => 667, ',' => 250, '-' => 313, '.' => 250, '/' => 520, '0' => 500, '1' => 500,
9     '2' => 500, '3' => 500, '4' => 500, '5' => 500, '6' => 500, '7' => 500, '8' => 500, '9' => 500, ':' => 250, ';' => 250,
10     '<' => 667, '=' => 667, '>' => 667, '?' => 396, '@' => 921, 'A' => 677, 'B' => 615, 'C' => 719, 'D' => 760, 'E' => 625,
11     'F' => 552, 'G' => 771, 'H' => 802, 'I' => 354, 'J' => 354, 'K' => 781, 'L' => 604, 'M' => 927, 'N' => 750, 'O' => 823,
12     'P' => 563, 'Q' => 823, 'R' => 729, 'S' => 542, 'T' => 698, 'U' => 771, 'V' => 729, 'W' => 948, 'X' => 771, 'Y' => 677,
13     'Z' => 635, '[' => 344, '\\' => 520, ']' => 344, '^' => 469, '_' => 500, '`' => 250, 'a' => 469, 'b' => 521, 'c' => 427,
14     'd' => 521, 'e' => 438, 'f' => 271, 'g' => 469, 'h' => 531, 'i' => 250, 'j' => 250, 'k' => 458, 'l' => 240, 'm' => 802,
15     'n' => 531, 'o' => 500, 'p' => 521, 'q' => 521, 'r' => 365, 's' => 333, 't' => 292, 'u' => 521, 'v' => 458, 'w' => 677,
16     'x' => 479, 'y' => 458, 'z' => 427, '{' => 480, '|' => 496, '}' => 480, '~' => 667);
17
18 $GB_widths = array(' ' => 207, '!' => 270, '"' => 342, '#' => 467, '$' => 462, '%' => 797, '&' => 710, '\'' => 239,
19     '(' => 374, ')' => 374, '*' => 423, '+' => 605, ',' => 238, '-' => 375, '.' => 238, '/' => 334, '0' => 462, '1' => 462,
20     '2' => 462, '3' => 462, '4' => 462, '5' => 462, '6' => 462, '7' => 462, '8' => 462, '9' => 462, ':' => 238, ';' => 238,
21     '<' => 605, '=' => 605, '>' => 605, '?' => 344, '@' => 748, 'A' => 684, 'B' => 560, 'C' => 695, 'D' => 739, 'E' => 563,
22     'F' => 511, 'G' => 729, 'H' => 793, 'I' => 318, 'J' => 312, 'K' => 666, 'L' => 526, 'M' => 896, 'N' => 758, 'O' => 772,
23     'P' => 544, 'Q' => 772, 'R' => 628, 'S' => 465, 'T' => 607, 'U' => 753, 'V' => 711, 'W' => 972, 'X' => 647, 'Y' => 620,
24     'Z' => 607, '[' => 374, '\\' => 333, ']' => 374, '^' => 606, '_' => 500, '`' => 239, 'a' => 417, 'b' => 503, 'c' => 427,
25     'd' => 529, 'e' => 415, 'f' => 264, 'g' => 444, 'h' => 518, 'i' => 241, 'j' => 230, 'k' => 495, 'l' => 228, 'm' => 793,
26     'n' => 527, 'o' => 524, 'p' => 524, 'q' => 504, 'r' => 338, 's' => 336, 't' => 277, 'u' => 517, 'v' => 450, 'w' => 652,
27     'x' => 466, 'y' => 452, 'z' => 407, '{' => 370, '|' => 258, '}' => 370, '~' => 605);
28
29 class PDF_Chinese extends PDF
30 {
31     function AddCIDFont($family, $style, $name, $cw, $CMap, $registry)
32     {
33         $fontkey = strtolower($family) . strtoupper($style);
34         if (isset($this->fonts[$fontkey]))
35             $this->Error("Font already added: $family $style");
36         $i = count($this->fonts) + 1;
37         $name = str_replace(' ', '', $name);
38         $this->fonts[$fontkey] = array('i' => $i, 'type' => 'Type0', 'name' => $name, 'up' => -130, 'ut' => 40, 'cw' => $cw, 'CMap' => $CMap, 'registry' => $registry);
39     }
40
41     function AddCIDFonts($family, $name, $cw, $CMap, $registry)
42     {
43         $this->AddCIDFont($family, '', $name, $cw, $CMap, $registry);
44         $this->AddCIDFont($family, 'B', $name . ',Bold', $cw, $CMap, $registry);
45         $this->AddCIDFont($family, 'I', $name . ',Italic', $cw, $CMap, $registry);
46         $this->AddCIDFont($family, 'BI', $name . ',BoldItalic', $cw, $CMap, $registry);
47     }
48
49     function AddBig5Font($family = 'Big5', $name = 'MSungStd-Light-Acro')
50     {
51         //Add Big5 font with proportional Latin
52         $cw = $GLOBALS['Big5_widths'];
53         $CMap = 'ETenms-B5-H';
54         $registry = array('ordering' => 'CNS1', 'supplement' => 0);
55         $this->AddCIDFonts($family, $name, $cw, $CMap, $registry);
56     }
57
58     function AddBig5hwFont($family = 'Big5-hw', $name = 'MSungStd-Light-Acro')
59     {
60         //Add Big5 font with half-witdh Latin
61         for ($i = 32; $i <= 126; $i++)
62             $cw[chr($i)] = 500;
63         $CMap = 'ETen-B5-H';
64         $registry = array('ordering' => 'CNS1', 'supplement' => 0);
65         $this->AddCIDFonts($family, $name, $cw, $CMap, $registry);
66     }
67
68     function AddGBFont($family = 'GB', $name = 'STSongStd-Light-Acro')
69     {
70         //Add GB font with proportional Latin
71         $cw = $GLOBALS['GB_widths'];
72         $CMap = 'GBKp-EUC-H';
73         $registry = array('ordering' => 'GB1', 'supplement' => 2);
74         $this->AddCIDFonts($family, $name, $cw, $CMap, $registry);
75     }
76
77     function AddGBhwFont($family = 'GB-hw', $name = 'STSongStd-Light-Acro')
78     {
79         //Add GB font with half-width Latin
80         for ($i = 32; $i <= 126; $i++)
81             $cw[chr($i)] = 500;
82         $CMap = 'GBK-EUC-H';
83         $registry = array('ordering' => 'GB1', 'supplement' => 2);
84         $this->AddCIDFonts($family, $name, $cw, $CMap, $registry);
85     }
86
87     function GetStringWidth($s)
88     {
89         if ($this->CurrentFont['type'] == 'Type0')
90             return $this->GetMBStringWidth($s);
91         else
92             return parent::GetStringWidth($s);
93     }
94
95     function GetMBStringWidth($s)
96     {
97         //Multi-byte version of GetStringWidth()
98         $l = 0;
99         $cw =& $this->CurrentFont['cw'];
100         $nb = strlen($s);
101         $i = 0;
102         while ($i < $nb) {
103             $c = $s[$i];
104             if (ord($c) < 128) {
105                 $l += $cw[$c];
106                 $i++;
107             } else {
108                 $l += 1000;
109                 $i += 2;
110             }
111         }
112         return $l * $this->FontSize / 1000;
113     }
114
115     function MultiCell($w, $h, $txt, $border = 0, $align = 'L', $fill = 0)
116     {
117         if ($this->CurrentFont['type'] == 'Type0')
118             $this->MBMultiCell($w, $h, $txt, $border, $align, $fill);
119         else
120             parent::MultiCell($w, $h, $txt, $border, $align, $fill);
121     }
122
123     function MBMultiCell($w, $h, $txt, $border = 0, $align = 'L', $fill = 0)
124     {
125         //Multi-byte version of MultiCell()
126         $cw =& $this->CurrentFont['cw'];
127         if ($w == 0)
128             $w = $this->w - $this->rMargin - $this->x;
129         $wmax = ($w - 2 * $this->cMargin) * 1000 / $this->FontSize;
130         $s = str_replace("\r", '', $txt);
131         $nb = strlen($s);
132         if ($nb > 0 and $s[$nb - 1] == "\n")
133             $nb--;
134         $b = 0;
135         if ($border) {
136             if ($border == 1) {
137                 $border = 'LTRB';
138                 $b = 'LRT';
139                 $b2 = 'LR';
140             } else {
141                 $b2 = '';
142                 if (is_int(strpos($border, 'L')))
143                     $b2 .= 'L';
144                 if (is_int(strpos($border, 'R')))
145                     $b2 .= 'R';
146                 $b = is_int(strpos($border, 'T')) ? $b2 . 'T' : $b2;
147             }
148         }
149         $sep = -1;
150         $i = 0;
151         $j = 0;
152         $l = 0;
153         $nl = 1;
154         while ($i < $nb) {
155             //Get next character
156             $c = $s[$i];
157             //Check if ASCII or MB
158             $ascii = (ord($c) < 128);
159             if ($c == "\n") {
160                 //Explicit line break
161                 $this->Cell($w, $h, substr($s, $j, $i - $j), $b, 2, $align, $fill);
162                 $i++;
163                 $sep = -1;
164                 $j = $i;
165                 $l = 0;
166                 $nl++;
167                 if ($border and $nl == 2)
168                     $b = $b2;
169                 continue;
170             }
171             if (!$ascii) {
172                 $sep = $i;
173                 $ls = $l;
174             } elseif ($c == ' ') {
175                 $sep = $i;
176                 $ls = $l;
177             }
178             $l += $ascii ? $cw[$c] : 1000;
179             if ($l > $wmax) {
180                 //Automatic line break
181                 if ($sep == -1 or $i == $j) {
182                     if ($i == $j)
183                         $i += $ascii ? 1 : 2;
184                     $this->Cell($w, $h, substr($s, $j, $i - $j), $b, 2, $align, $fill);
185                 } else {
186                     $this->Cell($w, $h, substr($s, $j, $sep - $j), $b, 2, $align, $fill);
187                     $i = ($s[$sep] == ' ') ? $sep + 1 : $sep;
188                 }
189                 $sep = -1;
190                 $j = $i;
191                 $l = 0;
192                 $nl++;
193                 if ($border and $nl == 2)
194                     $b = $b2;
195             } else
196                 $i += $ascii ? 1 : 2;
197         }
198         //Last chunk
199         if ($border and is_int(strpos($border, 'B')))
200             $b .= 'B';
201         $this->Cell($w, $h, substr($s, $j, $i - $j), $b, 2, $align, $fill);
202         $this->x = $this->lMargin;
203     }
204
205     function Write($h, $txt, $link = '')
206     {
207         if ($this->CurrentFont['type'] == 'Type0')
208             $this->MBWrite($h, $txt, $link);
209         else
210             parent::Write($h, $txt, $link);
211     }
212
213     function MBWrite($h, $txt, $link)
214     {
215         //Multi-byte version of Write()
216         $cw =& $this->CurrentFont['cw'];
217         $w = $this->w - $this->rMargin - $this->x;
218         $wmax = ($w - 2 * $this->cMargin) * 1000 / $this->FontSize;
219         $s = str_replace("\r", '', $txt);
220         $nb = strlen($s);
221         $sep = -1;
222         $i = 0;
223         $j = 0;
224         $l = 0;
225         $nl = 1;
226         while ($i < $nb) {
227             //Get next character
228             $c = $s[$i];
229             //Check if ASCII or MB
230             $ascii = (ord($c) < 128);
231             if ($c == "\n") {
232                 //Explicit line break
233                 $this->Cell($w, $h, substr($s, $j, $i - $j), 0, 2, '', 0, $link);
234                 $i++;
235                 $sep = -1;
236                 $j = $i;
237                 $l = 0;
238                 if ($nl == 1) {
239                     $this->x = $this->lMargin;
240                     $w = $this->w - $this->rMargin - $this->x;
241                     $wmax = ($w - 2 * $this->cMargin) * 1000 / $this->FontSize;
242                 }
243                 $nl++;
244                 continue;
245             }
246             if (!$ascii or $c == ' ')
247                 $sep = $i;
248             $l += $ascii ? $cw[$c] : 1000;
249             if ($l > $wmax) {
250                 //Automatic line break
251                 if ($sep == -1 or $i == $j) {
252                     if ($this->x > $this->lMargin) {
253                         //Move to next line
254                         $this->x = $this->lMargin;
255                         $this->y += $h;
256                         $w = $this->w - $this->rMargin - $this->x;
257                         $wmax = ($w - 2 * $this->cMargin) * 1000 / $this->FontSize;
258                         $i++;
259                         $nl++;
260                         continue;
261                     }
262                     if ($i == $j)
263                         $i += $ascii ? 1 : 2;
264                     $this->Cell($w, $h, substr($s, $j, $i - $j), 0, 2, '', 0, $link);
265                 } else {
266                     $this->Cell($w, $h, substr($s, $j, $sep - $j), 0, 2, '', 0, $link);
267                     $i = ($s[$sep] == ' ') ? $sep + 1 : $sep;
268                 }
269                 $sep = -1;
270                 $j = $i;
271                 $l = 0;
272                 if ($nl == 1) {
273                     $this->x = $this->lMargin;
274                     $w = $this->w - $this->rMargin - $this->x;
275                     $wmax = ($w - 2 * $this->cMargin) * 1000 / $this->FontSize;
276                 }
277                 $nl++;
278             } else
279                 $i += $ascii ? 1 : 2;
280         }
281         //Last chunk
282         if ($i != $j)
283             $this->Cell($l / 1000 * $this->FontSize, $h, substr($s, $j, $i - $j), 0, 0, '', 0, $link);
284     }
285
286     function _putfonts()
287     {
288         $nf = $this->n;
289         foreach ($this->diffs as $diff) {
290             //Encodings
291             $this->_newobj();
292             $this->_out('<</Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences [' . $diff . ']>>');
293             $this->_out('endobj');
294         }
295
296         if (!check_php_version(5, 3)) {
297             $mqr = get_magic_quotes_runtime();
298             set_magic_quotes_runtime(0);
299         }
300         foreach ($this->FontFiles as $file => $info) {
301             //Font file embedding
302             $this->_newobj();
303             $this->FontFiles[$file]['n'] = $this->n;
304             if (defined('FPDF_FONTPATH'))
305                 $file = FPDF_FONTPATH . $file;
306             $size = filesize($file);
307             if (!$size)
308                 $this->Error('Font file not found');
309             $this->_out('<</Length ' . $size);
310             if (substr($file, -2) == '.z')
311                 $this->_out('/Filter /FlateDecode');
312             $this->_out('/Length1 ' . $info['length1']);
313             if (isset($info['length2']))
314                 $this->_out('/Length2 ' . $info['length2'] . ' /Length3 0');
315             $this->_out('>>');
316             $f = fopen($file, 'rb');
317             $this->_putstream(fread($f, $size));
318             fclose($f);
319             $this->_out('endobj');
320         }
321         if (!check_php_version(5, 3)) {
322             set_magic_quotes_runtime($mqr);
323         }
324         foreach ($this->fonts as $k => $font) {
325             //Font objects
326             $this->_newobj();
327             $this->fonts[$k]['n'] = $this->n;
328             $this->_out('<</Type /Font');
329             if ($font['type'] == 'Type0')
330                 $this->_putType0($font);
331             else {
332                 $name = $font['name'];
333                 $this->_out('/BaseFont /' . $name);
334                 if ($font['type'] == 'core') {
335                     //Standard font
336                     $this->_out('/Subtype /Type1');
337                     if ($name != 'Symbol' and $name != 'ZapfDingbats')
338                         $this->_out('/Encoding /WinAnsiEncoding');
339                 } else {
340                     //Additional font
341                     $this->_out('/Subtype /' . $font['type']);
342                     $this->_out('/FirstChar 32');
343                     $this->_out('/LastChar 255');
344                     $this->_out('/Widths ' . ($this->n + 1) . ' 0 R');
345                     $this->_out('/FontDescriptor ' . ($this->n + 2) . ' 0 R');
346                     if ($font['enc']) {
347                         if (isset($font['diff']))
348                             $this->_out('/Encoding ' . ($nf + $font['diff']) . ' 0 R');
349                         else
350                             $this->_out('/Encoding /WinAnsiEncoding');
351                     }
352                 }
353                 $this->_out('>>');
354                 $this->_out('endobj');
355                 if ($font['type'] != 'core') {
356                     //Widths
357                     $this->_newobj();
358                     $cw =& $font['cw'];
359                     $s = '[';
360                     for ($i = 32; $i <= 255; $i++)
361                         $s .= $cw[chr($i)] . ' ';
362                     $this->_out($s . ']');
363                     $this->_out('endobj');
364                     //Descriptor
365                     $this->_newobj();
366                     $s = '<</Type /FontDescriptor /FontName /' . $name;
367                     foreach ($font['desc'] as $k => $v)
368                         $s .= ' /' . $k . ' ' . $v;
369                     $file = $font['file'];
370                     if ($file)
371                         $s .= ' /FontFile' . ($font['type'] == 'Type1' ? '' : '2') . ' ' . $this->FontFiles[$file]['n'] . ' 0 R';
372                     $this->_out($s . '>>');
373                     $this->_out('endobj');
374                 }
375             }
376         }
377     }
378
379     function _putType0($font)
380     {
381         //Type0
382         $this->_out('/Subtype /Type0');
383         $this->_out('/BaseFont /' . $font['name'] . '-' . $font['CMap']);
384         $this->_out('/Encoding /' . $font['CMap']);
385         $this->_out('/DescendantFonts [' . ($this->n + 1) . ' 0 R]');
386         $this->_out('>>');
387         $this->_out('endobj');
388         //CIDFont
389         $this->_newobj();
390         $this->_out('<</Type /Font');
391         $this->_out('/Subtype /CIDFontType0');
392         $this->_out('/BaseFont /' . $font['name']);
393         $this->_out('/CIDSystemInfo <</Registry ' . $this->_textstring('Adobe') . ' /Ordering ' . $this->_textstring($font['registry']['ordering']) . ' /Supplement ' . $font['registry']['supplement'] . '>>');
394         $this->_out('/FontDescriptor ' . ($this->n + 1) . ' 0 R');
395         if ($font['CMap'] == 'ETen-B5-H')
396             $W = '13648 13742 500';
397         elseif ($font['CMap'] == 'GBK-EUC-H')
398             $W = '814 907 500 7716 [500]'; else
399             $W = '1 [' . implode(' ', $font['cw']) . ']';
400         $this->_out('/W [' . $W . ']>>');
401         $this->_out('endobj');
402         //Font descriptor
403         $this->_newobj();
404         $this->_out('<</Type /FontDescriptor');
405         $this->_out('/FontName /' . $font['name']);
406         $this->_out('/Flags 6');
407         $this->_out('/FontBBox [0 -200 1000 900]');
408         $this->_out('/ItalicAngle 0');
409         $this->_out('/Ascent 800');
410         $this->_out('/Descent -200');
411         $this->_out('/CapHeight 800');
412         $this->_out('/StemV 50');
413         $this->_out('>>');
414         $this->_out('endobj');
415     }
416 }
417
418 // Local Variables:
419 // mode: php
420 // tab-width: 8
421 // c-basic-offset: 4
422 // c-hanging-comment-ender-p: nil
423 // indent-tabs-mode: nil
424 // End: