250 |
kaklik |
1 |
<?php |
|
|
2 |
/******************************************************************************* |
|
|
3 |
* Software: UFPDF, Unicode Free PDF generator * |
|
|
4 |
* Version: 0.1 * |
|
|
5 |
* based on FPDF 1.52 by Olivier PLATHEY * |
|
|
6 |
* Date: 2004-09-01 * |
|
|
7 |
* Author: Steven Wittens <steven@acko.net> * |
|
|
8 |
* License: GPL * |
|
|
9 |
* * |
|
|
10 |
* UFPDF is a modification of FPDF to support Unicode through UTF-8. * |
|
|
11 |
* * |
|
|
12 |
*******************************************************************************/ |
|
|
13 |
|
|
|
14 |
if(!class_exists('UFPDF')) |
|
|
15 |
{ |
|
|
16 |
define('UFPDF_VERSION','0.1'); |
|
|
17 |
|
|
|
18 |
include_once './libraries/fpdf/fpdf.php'; |
|
|
19 |
|
|
|
20 |
class UFPDF extends FPDF |
|
|
21 |
{ |
|
|
22 |
|
|
|
23 |
/******************************************************************************* |
|
|
24 |
* * |
|
|
25 |
* Public methods * |
|
|
26 |
* * |
|
|
27 |
*******************************************************************************/ |
|
|
28 |
function UFPDF($orientation='P',$unit='mm',$format='A4') |
|
|
29 |
{ |
|
|
30 |
FPDF::FPDF($orientation, $unit, $format); |
|
|
31 |
} |
|
|
32 |
|
|
|
33 |
function GetStringWidth($s) |
|
|
34 |
{ |
|
|
35 |
//Get width of a string in the current font |
|
|
36 |
$s = (string)$s; |
|
|
37 |
$codepoints=$this->utf8_to_codepoints($s); |
|
|
38 |
$cw=&$this->CurrentFont['cw']; |
|
|
39 |
$w=0; |
|
|
40 |
foreach($codepoints as $cp) |
|
|
41 |
$w+=isset($cw[$cp])?$cw[$cp]:0; |
|
|
42 |
return $w*$this->FontSize/1000; |
|
|
43 |
} |
|
|
44 |
|
|
|
45 |
function AddFont($family,$style='',$file='') |
|
|
46 |
{ |
|
|
47 |
//Add a TrueType or Type1 font |
|
|
48 |
$family=strtolower($family); |
|
|
49 |
if($family=='arial') |
|
|
50 |
$family='helvetica'; |
|
|
51 |
$style=strtoupper($style); |
|
|
52 |
if($style=='IB') |
|
|
53 |
$style='BI'; |
|
|
54 |
if(isset($this->fonts[$family.$style])) |
|
|
55 |
$this->Error('Font already added: '.$family.' '.$style); |
|
|
56 |
if($file=='') |
|
|
57 |
$file=str_replace(' ','',$family).strtolower($style).'.php'; |
|
|
58 |
if(defined('FPDF_FONTPATH')) |
|
|
59 |
$file=FPDF_FONTPATH.$file; |
|
|
60 |
include($file); |
|
|
61 |
if(!isset($name)) |
|
|
62 |
$this->Error('Could not include font definition file'); |
|
|
63 |
$i=count($this->fonts)+1; |
|
|
64 |
$this->fonts[$family.$style]=array('i'=>$i,'type'=>$type,'name'=>$name,'desc'=>$desc,'up'=>$up,'ut'=>$ut,'cw'=>$cw,'file'=>$file,'ctg'=>$ctg); |
|
|
65 |
if($file) |
|
|
66 |
{ |
|
|
67 |
if($type=='TrueTypeUnicode') |
|
|
68 |
$this->FontFiles[$file]=array('length1'=>$originalsize); |
|
|
69 |
else |
|
|
70 |
$this->FontFiles[$file]=array('length1'=>$size1,'length2'=>$size2); |
|
|
71 |
} |
|
|
72 |
} |
|
|
73 |
|
|
|
74 |
function Text($x,$y,$txt) |
|
|
75 |
{ |
|
|
76 |
//Output a string |
|
|
77 |
$s=sprintf('BT %.2f %.2f Td %s Tj ET',$x*$this->k,($this->h-$y)*$this->k,$this->_escapetext($txt)); |
|
|
78 |
if($this->underline and $txt!='') |
|
|
79 |
$s.=' '.$this->_dounderline($x,$y,$this->GetStringWidth($txt),$txt); |
|
|
80 |
if($this->ColorFlag) |
|
|
81 |
$s='q '.$this->TextColor.' '.$s.' Q'; |
|
|
82 |
$this->_out($s); |
|
|
83 |
} |
|
|
84 |
|
|
|
85 |
function AcceptPageBreak() |
|
|
86 |
{ |
|
|
87 |
//Accept automatic page break or not |
|
|
88 |
return $this->AutoPageBreak; |
|
|
89 |
} |
|
|
90 |
|
|
|
91 |
function Cell($w,$h=0,$txt='',$border=0,$ln=0,$align='',$fill=0,$link='') |
|
|
92 |
{ |
|
|
93 |
//Output a cell |
|
|
94 |
$k=$this->k; |
|
|
95 |
if($this->y+$h>$this->PageBreakTrigger and !$this->InFooter and $this->AcceptPageBreak()) |
|
|
96 |
{ |
|
|
97 |
//Automatic page break |
|
|
98 |
$x=$this->x; |
|
|
99 |
$ws=$this->ws; |
|
|
100 |
if($ws>0) |
|
|
101 |
{ |
|
|
102 |
$this->ws=0; |
|
|
103 |
$this->_out('0 Tw'); |
|
|
104 |
} |
|
|
105 |
$this->AddPage($this->CurOrientation); |
|
|
106 |
$this->x=$x; |
|
|
107 |
if($ws>0) |
|
|
108 |
{ |
|
|
109 |
$this->ws=$ws; |
|
|
110 |
$this->_out(sprintf('%.3f Tw',$ws*$k)); |
|
|
111 |
} |
|
|
112 |
} |
|
|
113 |
if($w==0) |
|
|
114 |
$w=$this->w-$this->rMargin-$this->x; |
|
|
115 |
$s=''; |
|
|
116 |
if($fill==1 or $border==1) |
|
|
117 |
{ |
|
|
118 |
if($fill==1) |
|
|
119 |
$op=($border==1) ? 'B' : 'f'; |
|
|
120 |
else |
|
|
121 |
$op='S'; |
|
|
122 |
$s=sprintf('%.2f %.2f %.2f %.2f re %s ',$this->x*$k,($this->h-$this->y)*$k,$w*$k,-$h*$k,$op); |
|
|
123 |
} |
|
|
124 |
if(is_string($border)) |
|
|
125 |
{ |
|
|
126 |
$x=$this->x; |
|
|
127 |
$y=$this->y; |
|
|
128 |
if(is_int(strpos($border,'L'))) |
|
|
129 |
$s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,$x*$k,($this->h-($y+$h))*$k); |
|
|
130 |
if(is_int(strpos($border,'T'))) |
|
|
131 |
$s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-$y)*$k); |
|
|
132 |
if(is_int(strpos($border,'R'))) |
|
|
133 |
$s.=sprintf('%.2f %.2f m %.2f %.2f l S ',($x+$w)*$k,($this->h-$y)*$k,($x+$w)*$k,($this->h-($y+$h))*$k); |
|
|
134 |
if(is_int(strpos($border,'B'))) |
|
|
135 |
$s.=sprintf('%.2f %.2f m %.2f %.2f l S ',$x*$k,($this->h-($y+$h))*$k,($x+$w)*$k,($this->h-($y+$h))*$k); |
|
|
136 |
} |
|
|
137 |
if($txt!='') |
|
|
138 |
{ |
|
|
139 |
$width = $this->GetStringWidth($txt); |
|
|
140 |
if($align=='R') |
|
|
141 |
$dx=$w-$this->cMargin-$width; |
|
|
142 |
elseif($align=='C') |
|
|
143 |
$dx=($w-$width)/2; |
|
|
144 |
else |
|
|
145 |
$dx=$this->cMargin; |
|
|
146 |
if($this->ColorFlag) |
|
|
147 |
$s.='q '.$this->TextColor.' '; |
|
|
148 |
$txtstring=$this->_escapetext($txt); |
|
|
149 |
$s.=sprintf('BT %.2f %.2f Td %s Tj ET',($this->x+$dx)*$k,($this->h-($this->y+.5*$h+.3*$this->FontSize))*$k,$txtstring); |
|
|
150 |
if($this->underline) |
|
|
151 |
$s.=' '.$this->_dounderline($this->x+$dx,$this->y+.5*$h+.3*$this->FontSize,$width,$txt); |
|
|
152 |
if($this->ColorFlag) |
|
|
153 |
$s.=' Q'; |
|
|
154 |
if($link) |
|
|
155 |
$this->Link($this->x+$dx,$this->y+.5*$h-.5*$this->FontSize,$width,$this->FontSize,$link); |
|
|
156 |
} |
|
|
157 |
if($s) |
|
|
158 |
$this->_out($s); |
|
|
159 |
$this->lasth=$h; |
|
|
160 |
if($ln>0) |
|
|
161 |
{ |
|
|
162 |
//Go to next line |
|
|
163 |
$this->y+=$h; |
|
|
164 |
if($ln==1) |
|
|
165 |
$this->x=$this->lMargin; |
|
|
166 |
} |
|
|
167 |
else |
|
|
168 |
$this->x+=$w; |
|
|
169 |
} |
|
|
170 |
|
|
|
171 |
/******************************************************************************* |
|
|
172 |
* * |
|
|
173 |
* Protected methods * |
|
|
174 |
* * |
|
|
175 |
*******************************************************************************/ |
|
|
176 |
|
|
|
177 |
function _puttruetypeunicode($font) { |
|
|
178 |
//Type0 Font |
|
|
179 |
$this->_newobj(); |
|
|
180 |
$this->_out('<</Type /Font'); |
|
|
181 |
$this->_out('/Subtype /Type0'); |
|
|
182 |
$this->_out('/BaseFont /'. $font['name'] .'-UCS'); |
|
|
183 |
$this->_out('/Encoding /Identity-H'); |
|
|
184 |
$this->_out('/DescendantFonts ['. ($this->n + 1) .' 0 R]'); |
|
|
185 |
$this->_out('>>'); |
|
|
186 |
$this->_out('endobj'); |
|
|
187 |
|
|
|
188 |
//CIDFont |
|
|
189 |
$this->_newobj(); |
|
|
190 |
$this->_out('<</Type /Font'); |
|
|
191 |
$this->_out('/Subtype /CIDFontType2'); |
|
|
192 |
$this->_out('/BaseFont /'. $font['name']); |
|
|
193 |
$this->_out('/CIDSystemInfo <</Registry (Adobe) /Ordering (UCS) /Supplement 0>>'); |
|
|
194 |
$this->_out('/FontDescriptor '. ($this->n + 1) .' 0 R'); |
|
|
195 |
$c = 0; |
|
|
196 |
$widths = ''; |
|
|
197 |
foreach ($font['cw'] as $i => $w) { |
|
|
198 |
$widths .= $i .' ['. $w.'] '; |
|
|
199 |
} |
|
|
200 |
$this->_out('/W ['. $widths .']'); |
|
|
201 |
$this->_out('/CIDToGIDMap '. ($this->n + 2) .' 0 R'); |
|
|
202 |
$this->_out('>>'); |
|
|
203 |
$this->_out('endobj'); |
|
|
204 |
|
|
|
205 |
//Font descriptor |
|
|
206 |
$this->_newobj(); |
|
|
207 |
$this->_out('<</Type /FontDescriptor'); |
|
|
208 |
$this->_out('/FontName /'.$font['name']); |
|
|
209 |
$s = ''; |
|
|
210 |
foreach ($font['desc'] as $k => $v) { |
|
|
211 |
$s .= ' /'. $k .' '. $v; |
|
|
212 |
} |
|
|
213 |
if ($font['file']) { |
|
|
214 |
$s .= ' /FontFile2 '. $this->FontFiles[$font['file']]['n'] .' 0 R'; |
|
|
215 |
} |
|
|
216 |
$this->_out($s); |
|
|
217 |
$this->_out('>>'); |
|
|
218 |
$this->_out('endobj'); |
|
|
219 |
|
|
|
220 |
//Embed CIDToGIDMap |
|
|
221 |
$this->_newobj(); |
|
|
222 |
if(defined('FPDF_FONTPATH')) |
|
|
223 |
$file=FPDF_FONTPATH.$font['ctg']; |
|
|
224 |
else |
|
|
225 |
$file=$font['ctg']; |
|
|
226 |
$size=filesize($file); |
|
|
227 |
if(!$size) |
|
|
228 |
$this->Error('Font file not found'); |
|
|
229 |
$this->_out('<</Length '.$size); |
|
|
230 |
if(substr($file,-2) == '.z') |
|
|
231 |
$this->_out('/Filter /FlateDecode'); |
|
|
232 |
$this->_out('>>'); |
|
|
233 |
$f = fopen($file,'rb'); |
|
|
234 |
$this->_putstream(fread($f,$size)); |
|
|
235 |
fclose($f); |
|
|
236 |
$this->_out('endobj'); |
|
|
237 |
} |
|
|
238 |
|
|
|
239 |
function _dounderline($x,$y,$width,$txt) |
|
|
240 |
{ |
|
|
241 |
//Underline text |
|
|
242 |
$up=$this->CurrentFont['up']; |
|
|
243 |
$ut=$this->CurrentFont['ut']; |
|
|
244 |
$w=$width+$this->ws*substr_count($txt,' '); |
|
|
245 |
return sprintf('%.2f %.2f %.2f %.2f re f',$x*$this->k,($this->h-($y-$up/1000*$this->FontSize))*$this->k,$w*$this->k,-$ut/1000*$this->FontSizePt); |
|
|
246 |
} |
|
|
247 |
|
|
|
248 |
function _textstring($s) |
|
|
249 |
{ |
|
|
250 |
//Convert to UTF-16BE |
|
|
251 |
$s = $this->utf8_to_utf16be($s); |
|
|
252 |
//Escape necessary characters |
|
|
253 |
return '('. strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\')) .')'; |
|
|
254 |
} |
|
|
255 |
|
|
|
256 |
function _strreplace($what, $to, $where) { |
|
|
257 |
$to = '' . $to; |
|
|
258 |
return str_replace($this->utf8_to_utf16be($what, false), $this->utf8_to_utf16be($to, false), $where); |
|
|
259 |
} |
|
|
260 |
|
|
|
261 |
function _escapetext($s) |
|
|
262 |
{ |
|
|
263 |
//Convert to UTF-16BE |
|
|
264 |
$s = $this->utf8_to_utf16be($s, false); |
|
|
265 |
//Escape necessary characters |
|
|
266 |
return '('. strtr($s, array(')' => '\\)', '(' => '\\(', '\\' => '\\\\')) .')'; |
|
|
267 |
} |
|
|
268 |
|
|
|
269 |
function _putinfo() |
|
|
270 |
{ |
|
|
271 |
$this->_out('/Producer '.$this->_textstring('UFPDF '. UFPDF_VERSION)); |
|
|
272 |
if(!empty($this->title)) |
|
|
273 |
$this->_out('/Title '.$this->_textstring($this->title)); |
|
|
274 |
if(!empty($this->subject)) |
|
|
275 |
$this->_out('/Subject '.$this->_textstring($this->subject)); |
|
|
276 |
if(!empty($this->author)) |
|
|
277 |
$this->_out('/Author '.$this->_textstring($this->author)); |
|
|
278 |
if(!empty($this->keywords)) |
|
|
279 |
$this->_out('/Keywords '.$this->_textstring($this->keywords)); |
|
|
280 |
if(!empty($this->creator)) |
|
|
281 |
$this->_out('/Creator '.$this->_textstring($this->creator)); |
|
|
282 |
$this->_out('/CreationDate '.$this->_textstring('D:'.date('YmdHis'))); |
|
|
283 |
} |
|
|
284 |
|
|
|
285 |
// UTF-8 to UTF-16BE conversion. |
|
|
286 |
// Correctly handles all illegal UTF-8 sequences. |
|
|
287 |
function utf8_to_utf16be(&$txt, $bom = true) { |
|
|
288 |
$l = strlen($txt); |
|
|
289 |
$out = $bom ? "\xFE\xFF" : ''; |
|
|
290 |
for ($i = 0; $i < $l; ++$i) { |
|
|
291 |
$c = ord($txt{$i}); |
|
|
292 |
// ASCII |
|
|
293 |
if ($c < 0x80) { |
|
|
294 |
$out .= "\x00". $txt{$i}; |
|
|
295 |
} |
|
|
296 |
// Lost continuation byte |
|
|
297 |
else if ($c < 0xC0) { |
|
|
298 |
$out .= "\xFF\xFD"; |
|
|
299 |
continue; |
|
|
300 |
} |
|
|
301 |
// Multibyte sequence leading byte |
|
|
302 |
else { |
|
|
303 |
if ($c < 0xE0) { |
|
|
304 |
$s = 2; |
|
|
305 |
} |
|
|
306 |
else if ($c < 0xF0) { |
|
|
307 |
$s = 3; |
|
|
308 |
} |
|
|
309 |
else if ($c < 0xF8) { |
|
|
310 |
$s = 4; |
|
|
311 |
} |
|
|
312 |
// 5/6 byte sequences not possible for Unicode. |
|
|
313 |
else { |
|
|
314 |
$out .= "\xFF\xFD"; |
|
|
315 |
while (ord($txt{$i + 1}) >= 0x80 && ord($txt{$i + 1}) < 0xC0) { ++$i; } |
|
|
316 |
continue; |
|
|
317 |
} |
|
|
318 |
|
|
|
319 |
$q = array($c); |
|
|
320 |
// Fetch rest of sequence |
|
|
321 |
$l = strlen($txt); |
|
|
322 |
while ($i + 1 < $l && ord($txt{$i + 1}) >= 0x80 && ord($txt{$i + 1}) < 0xC0) { ++$i; $q[] = ord($txt{$i}); } |
|
|
323 |
|
|
|
324 |
// Check length |
|
|
325 |
if (count($q) != $s) { |
|
|
326 |
$out .= "\xFF\xFD"; |
|
|
327 |
continue; |
|
|
328 |
} |
|
|
329 |
|
|
|
330 |
switch ($s) { |
|
|
331 |
case 2: |
|
|
332 |
$cp = (($q[0] ^ 0xC0) << 6) | ($q[1] ^ 0x80); |
|
|
333 |
// Overlong sequence |
|
|
334 |
if ($cp < 0x80) { |
|
|
335 |
$out .= "\xFF\xFD"; |
|
|
336 |
} |
|
|
337 |
else { |
|
|
338 |
$out .= chr($cp >> 8); |
|
|
339 |
$out .= chr($cp & 0xFF); |
|
|
340 |
} |
|
|
341 |
continue; |
|
|
342 |
|
|
|
343 |
case 3: |
|
|
344 |
$cp = (($q[0] ^ 0xE0) << 12) | (($q[1] ^ 0x80) << 6) | ($q[2] ^ 0x80); |
|
|
345 |
// Overlong sequence |
|
|
346 |
if ($cp < 0x800) { |
|
|
347 |
$out .= "\xFF\xFD"; |
|
|
348 |
} |
|
|
349 |
// Check for UTF-8 encoded surrogates (caused by a bad UTF-8 encoder) |
|
|
350 |
else if ($c > 0xD800 && $c < 0xDFFF) { |
|
|
351 |
$out .= "\xFF\xFD"; |
|
|
352 |
} |
|
|
353 |
else { |
|
|
354 |
$out .= chr($cp >> 8); |
|
|
355 |
$out .= chr($cp & 0xFF); |
|
|
356 |
} |
|
|
357 |
continue; |
|
|
358 |
|
|
|
359 |
case 4: |
|
|
360 |
$cp = (($q[0] ^ 0xF0) << 18) | (($q[1] ^ 0x80) << 12) | (($q[2] ^ 0x80) << 6) | ($q[3] ^ 0x80); |
|
|
361 |
// Overlong sequence |
|
|
362 |
if ($cp < 0x10000) { |
|
|
363 |
$out .= "\xFF\xFD"; |
|
|
364 |
} |
|
|
365 |
// Outside of the Unicode range |
|
|
366 |
else if ($cp >= 0x10FFFF) { |
|
|
367 |
$out .= "\xFF\xFD"; |
|
|
368 |
} |
|
|
369 |
else { |
|
|
370 |
// Use surrogates |
|
|
371 |
$cp -= 0x10000; |
|
|
372 |
$s1 = 0xD800 | ($cp >> 10); |
|
|
373 |
$s2 = 0xDC00 | ($cp & 0x3FF); |
|
|
374 |
|
|
|
375 |
$out .= chr($s1 >> 8); |
|
|
376 |
$out .= chr($s1 & 0xFF); |
|
|
377 |
$out .= chr($s2 >> 8); |
|
|
378 |
$out .= chr($s2 & 0xFF); |
|
|
379 |
} |
|
|
380 |
continue; |
|
|
381 |
} |
|
|
382 |
} |
|
|
383 |
} |
|
|
384 |
return $out; |
|
|
385 |
} |
|
|
386 |
|
|
|
387 |
// UTF-8 to codepoint array conversion. |
|
|
388 |
// Correctly handles all illegal UTF-8 sequences. |
|
|
389 |
function utf8_to_codepoints(&$txt) { |
|
|
390 |
$l = strlen($txt); |
|
|
391 |
$out = array(); |
|
|
392 |
for ($i = 0; $i < $l; ++$i) { |
|
|
393 |
$c = ord($txt{$i}); |
|
|
394 |
// ASCII |
|
|
395 |
if ($c < 0x80) { |
|
|
396 |
$out[] = ord($txt{$i}); |
|
|
397 |
} |
|
|
398 |
// Lost continuation byte |
|
|
399 |
else if ($c < 0xC0) { |
|
|
400 |
$out[] = 0xFFFD; |
|
|
401 |
continue; |
|
|
402 |
} |
|
|
403 |
// Multibyte sequence leading byte |
|
|
404 |
else { |
|
|
405 |
if ($c < 0xE0) { |
|
|
406 |
$s = 2; |
|
|
407 |
} |
|
|
408 |
else if ($c < 0xF0) { |
|
|
409 |
$s = 3; |
|
|
410 |
} |
|
|
411 |
else if ($c < 0xF8) { |
|
|
412 |
$s = 4; |
|
|
413 |
} |
|
|
414 |
// 5/6 byte sequences not possible for Unicode. |
|
|
415 |
else { |
|
|
416 |
$out[] = 0xFFFD; |
|
|
417 |
while (ord($txt{$i + 1}) >= 0x80 && ord($txt{$i + 1}) < 0xC0) { ++$i; } |
|
|
418 |
continue; |
|
|
419 |
} |
|
|
420 |
|
|
|
421 |
$q = array($c); |
|
|
422 |
// Fetch rest of sequence |
|
|
423 |
$l = strlen($txt); |
|
|
424 |
while ($i + 1 < $l && ord($txt{$i + 1}) >= 0x80 && ord($txt{$i + 1}) < 0xC0) { ++$i; $q[] = ord($txt{$i}); } |
|
|
425 |
|
|
|
426 |
// Check length |
|
|
427 |
if (count($q) != $s) { |
|
|
428 |
$out[] = 0xFFFD; |
|
|
429 |
continue; |
|
|
430 |
} |
|
|
431 |
|
|
|
432 |
switch ($s) { |
|
|
433 |
case 2: |
|
|
434 |
$cp = (($q[0] ^ 0xC0) << 6) | ($q[1] ^ 0x80); |
|
|
435 |
// Overlong sequence |
|
|
436 |
if ($cp < 0x80) { |
|
|
437 |
$out[] = 0xFFFD; |
|
|
438 |
} |
|
|
439 |
else { |
|
|
440 |
$out[] = $cp; |
|
|
441 |
} |
|
|
442 |
continue; |
|
|
443 |
|
|
|
444 |
case 3: |
|
|
445 |
$cp = (($q[0] ^ 0xE0) << 12) | (($q[1] ^ 0x80) << 6) | ($q[2] ^ 0x80); |
|
|
446 |
// Overlong sequence |
|
|
447 |
if ($cp < 0x800) { |
|
|
448 |
$out[] = 0xFFFD; |
|
|
449 |
} |
|
|
450 |
// Check for UTF-8 encoded surrogates (caused by a bad UTF-8 encoder) |
|
|
451 |
else if ($c > 0xD800 && $c < 0xDFFF) { |
|
|
452 |
$out[] = 0xFFFD; |
|
|
453 |
} |
|
|
454 |
else { |
|
|
455 |
$out[] = $cp; |
|
|
456 |
} |
|
|
457 |
continue; |
|
|
458 |
|
|
|
459 |
case 4: |
|
|
460 |
$cp = (($q[0] ^ 0xF0) << 18) | (($q[1] ^ 0x80) << 12) | (($q[2] ^ 0x80) << 6) | ($q[3] ^ 0x80); |
|
|
461 |
// Overlong sequence |
|
|
462 |
if ($cp < 0x10000) { |
|
|
463 |
$out[] = 0xFFFD; |
|
|
464 |
} |
|
|
465 |
// Outside of the Unicode range |
|
|
466 |
else if ($cp >= 0x10FFFF) { |
|
|
467 |
$out[] = 0xFFFD; |
|
|
468 |
} |
|
|
469 |
else { |
|
|
470 |
$out[] = $cp; |
|
|
471 |
} |
|
|
472 |
continue; |
|
|
473 |
} |
|
|
474 |
} |
|
|
475 |
} |
|
|
476 |
return $out; |
|
|
477 |
} |
|
|
478 |
|
|
|
479 |
//End of class |
|
|
480 |
} |
|
|
481 |
|
|
|
482 |
} |
|
|
483 |
?> |