File Coverage

blib/lib/Font/TTF/OS_2.pm
Criterion Covered Total %
statement 43 164 26.2
branch 8 98 8.1
condition 1 32 3.1
subroutine 8 13 61.5
pod 7 8 87.5
total 67 315 21.2


line stmt bran cond sub pod time code
1             package Font::TTF::OS_2;
2              
3             =head1 NAME
4              
5             Font::TTF::OS_2 - the OS/2 table in a TTF font
6              
7             =head1 DESCRIPTION
8              
9             The OS/2 table has two versions and forms, one an extension of the other. This
10             module supports both forms and the switching between them.
11              
12             =head1 INSTANCE VARIABLES
13              
14             No other variables than those in table and those in the standard:
15              
16             Version
17             xAvgCharWidth
18             usWeightClass
19             usWidthClass
20             fsType
21             ySubscriptXSize
22             ySubScriptYSize
23             ySubscriptXOffset
24             ySubscriptYOffset
25             ySuperscriptXSize
26             ySuperscriptYSize
27             ySuperscriptXOffset
28             ySuperscriptYOffset
29             yStrikeoutSize
30             yStrikeoutPosition
31             sFamilyClass
32             bFamilyType
33             bSerifStyle
34             bWeight
35             bProportion
36             bContrast
37             bStrokeVariation
38             bArmStyle
39             bLetterform
40             bMidline
41             bXheight
42             ulUnicodeRange1
43             ulUnicodeRange2
44             ulUnicodeRange3
45             ulUnicodeRange4
46             achVendID
47             fsSelection
48             usFirstCharIndex
49             usLastCharIndex
50             sTypoAscender
51             sTypoDescender
52             sTypoLineGap
53             usWinAscent
54             usWinDescent
55             ulCodePageRange1
56             ulCodePageRange2
57             xHeight
58             CapHeight
59             defaultChar
60             breakChar
61             maxLookups
62              
63             Notice that versions 0, 1, 2 & 3 of the table are supported. Notice also that the
64             Panose variable has been broken down into its elements.
65              
66             =head1 METHODS
67              
68             =cut
69              
70 1     1   7 use strict;
  1         2  
  1         60  
71 1     1   27 use vars qw(@ISA @fields @lens @field_info @weights @ranges @codepages);
  1         3  
  1         198  
72 1     1   594 use Font::TTF::Table;
  1         4  
  1         215  
73              
74             @ISA = qw(Font::TTF::Table);
75             @field_info = (
76             'xAvgCharWidth' => 's',
77             'usWeightClass' => 'S',
78             'usWidthClass' => 'S',
79             'fsType' => 's',
80             'ySubscriptXSize' => 's',
81             'ySubScriptYSize' => 's',
82             'ySubscriptXOffset' => 's',
83             'ySubscriptYOffset' => 's',
84             'ySuperscriptXSize' => 's',
85             'ySuperscriptYSize' => 's',
86             'ySuperscriptXOffset' => 's',
87             'ySuperscriptYOffset' => 's',
88             'yStrikeoutSize' => 's',
89             'yStrikeoutPosition' => 's',
90             'sFamilyClass' => 's',
91             'bFamilyType' => 'C',
92             'bSerifStyle' => 'C',
93             'bWeight' => 'C',
94             'bProportion' => 'C',
95             'bContrast' => 'C',
96             'bStrokeVariation' => 'C',
97             'bArmStyle' => 'C',
98             'bLetterform' => 'C',
99             'bMidline' => 'C',
100             'bXheight' => 'C',
101             'ulUnicodeRange1' => 'L',
102             'ulUnicodeRange2' => 'L',
103             'ulUnicodeRange3' => 'L',
104             'ulUnicodeRange4' => 'L',
105             'achVendID' => 'L',
106             'fsSelection' => 'S',
107             'usFirstCharIndex' => 'S',
108             'usLastCharIndex' => 'S',
109             'sTypoAscender' => 'S',
110             'sTypoDescender' => 's',
111             'sTypoLineGap' => 'S',
112             'usWinAscent' => 'S',
113             'usWinDescent' => 'S',
114             '' => '',
115             'ulCodePageRange1' => 'L',
116             'ulCodePageRange2' => 'L',
117             '' => '',
118             'xHeight' => 's',
119             'CapHeight' => 's',
120             'defaultChar' => 'S',
121             'breakChar' => 'S',
122             'maxLookups' => 's',
123             '' => '', # i.e. v3 is basically same as v2
124             '' => '' # i.e. v4 is structurally identical to v3
125             );
126              
127             @weights = qw(64 14 27 35 100 20 14 42 63 3 6 35 20 56 56 17 4 49 56 71 31 10 18 3 18 2 166);
128              
129 1     1   7 use Font::TTF::Utils;
  1         2  
  1         3516  
130              
131             sub init
132             {
133 1     1 0 2 my ($k, $v, $c, $n, $i, $t, $j);
134              
135 1         1 $n = 0;
136 1         3 @lens = (76, 84, 94, 94, 94);
137 1         7 for ($j = 0; $j < $#field_info; $j += 2)
138             {
139 49 100       75 if ($field_info[$j] eq '')
140             {
141 4         4 $n++;
142 4         7 next;
143             }
144 45         79 ($k, $v, $c) = TTF_Init_Fields($field_info[$j], $c, $field_info[$j+1]);
145 45 50 33     141 next unless defined $k && $k ne "";
146 45         67 for ($i = $n; $i < 5; $i++)
147 213         445 { $fields[$i]{$k} = $v; }
148             }
149             }
150              
151              
152             =head2 $t->read
153              
154             Reads in the various values from disk (see details of OS/2 table)
155              
156             =cut
157              
158             sub read
159             {
160 2     2 1 12 my ($self) = @_;
161 2         3 my ($dat, $ver);
162              
163 2 50       12 $self->SUPER::read or return $self;
164              
165 2 100       15 init unless defined $fields[2]{'xAvgCharWidth'};
166 2         10 $self->{' INFILE'}->read($dat, 2);
167 2         31 $ver = unpack("n", $dat);
168 2         5 $self->{'Version'} = $ver;
169 2 50       7 if ($ver < 5)
170             {
171 2         6 $self->{' INFILE'}->read($dat, $lens[$ver]);
172 2         18 TTF_Read_Fields($self, $dat, $fields[$ver]);
173             }
174 2         7 $self;
175             }
176              
177              
178             =head2 $t->out($fh)
179              
180             Writes the table to a file either from memory or by copying.
181              
182             =cut
183              
184             sub out
185             {
186 2     2 1 4 my ($self, $fh) = @_;
187 2         3 my ($ver);
188              
189 2 50       9 return $self->SUPER::out($fh) unless $self->{' read'};
190              
191 2         6 $ver = $self->{'Version'};
192 2         11 $fh->print(pack("n", $ver));
193 2         20 $fh->print(TTF_Out_Fields($self, $fields[$ver], $lens[$ver]));
194 2         23 $self;
195             }
196              
197              
198             =head2 $t->XML_element($context, $depth, $key, $value)
199              
200             Tidies up the hex values to output them in hex
201              
202             =cut
203              
204             sub XML_element
205             {
206 0     0 1   my ($self) = shift;
207 0           my ($context, $depth, $key, $value) = @_;
208 0           my ($fh) = $context->{'fh'};
209              
210 0 0         if ($key =~ m/^ul(?:Unicode|CodePage)Range\d$/o)
    0          
211 0           { $fh->printf("%s<%s>%08X\n", $depth, $key, $value, $key); }
212             elsif ($key eq 'achVendID')
213 0           { $fh->printf("%s<%s name='%s'/>\n", $depth, $key, pack('N', $value)); }
214             else
215 0           { return $self->SUPER::XML_element(@_); }
216 0           $self;
217             }
218              
219              
220             =head2 $t->XML_end($context, $tag, %attrs)
221              
222             Now handle them on the way back in
223              
224             =cut
225              
226             sub XML_end
227             {
228 0     0 1   my ($self) = shift;
229 0           my ($context, $tag, %attrs) = @_;
230              
231 0 0         if ($tag =~ m/^ul(?:Unicode|CodePage)Range\d$/o)
    0          
232 0           { return hex($context->{'text'}); }
233             elsif ($tag eq 'achVendID')
234 0           { return unpack('N', $attrs{'name'}); }
235             else
236 0           { return $self->SUPER::XML_end(@_); }
237             }
238              
239             =head2 $t->minsize()
240              
241             Returns the minimum size this table can be. If it is smaller than this, then the table
242             must be bad and should be deleted or whatever.
243              
244             =cut
245              
246             sub minsize
247             {
248 0     0 1   return 78;
249             }
250              
251             =head2 $t->update
252              
253             Updates the OS/2 table by getting information from other sources:
254              
255             Updates the C and C values based on the MS table in the
256             cmap.
257              
258             Updates the sTypoAscender, sTypoDescender & sTypoLineGap to be the same values
259             as Ascender, Descender and Linegap from the hhea table (assuming it is dirty)
260             and also sets usWinAscent to be the sum of Ascender+Linegap and usWinDescent to
261             be the negative of Descender.
262              
263             =cut
264              
265             sub update
266             {
267 0     0 1   my ($self) = @_;
268 0           my ($map, @keys, $table, $i, $avg, $hmtx);
269              
270 0 0         return undef unless ($self->SUPER::update);
271              
272 0           $self->{' PARENT'}{'cmap'}->update;
273 0   0       $map = $self->{' PARENT'}{'cmap'}->find_ms || return undef;
274 0           $hmtx = $self->{' PARENT'}{'hmtx'}->read;
275              
276 0           @keys = sort {$a <=> $b} grep {$_ < 0x10000} keys %{$map->{'val'}};
  0            
  0            
  0            
277              
278 0           $self->{'usFirstCharIndex'} = $keys[0];
279 0           $self->{'usLastCharIndex'} = $keys[-1];
280              
281 0           $table = $self->{' PARENT'}{'hhea'}->read;
282            
283             # try any way we can to get some real numbers passed around!
284 0 0 0       if (($self->{'fsSelection'} & 128) != 0)
    0 0        
    0 0        
    0          
285             {
286             # assume the user knows what they are doing and has sensible values already
287             }
288             elsif ($table->{'Ascender'} != 0 || $table->{'Descender'} != 0)
289             {
290 0           $self->{'sTypoAscender'} = $table->{'Ascender'};
291 0           $self->{'sTypoDescender'} = $table->{'Descender'};
292 0           $self->{'sTypoLineGap'} = $table->{'LineGap'};
293 0           $self->{'usWinAscent'} = $self->{'sTypoAscender'} + $self->{'sTypoLineGap'};
294 0           $self->{'usWinDescent'} = -$self->{'sTypoDescender'};
295             }
296             elsif ($self->{'sTypoAscender'} != 0 || $self->{'sTypoDescender'} != 0)
297             {
298 0           $table->{'Ascender'} = $self->{'sTypoAscender'};
299 0           $table->{'Descender'} = $self->{'sTypoDescender'};
300 0           $table->{'LineGap'} = $self->{'sTypoLineGap'};
301 0           $self->{'usWinAscent'} = $self->{'sTypoAscender'} + $self->{'sTypoLineGap'};
302 0           $self->{'usWinDescent'} = -$self->{'sTypoDescender'};
303             }
304             elsif ($self->{'usWinAscent'} != 0 || $self->{'usWinDescent'} != 0)
305             {
306 0           $self->{'sTypoAscender'} = $table->{'Ascender'} = $self->{'usWinAscent'};
307 0           $self->{'sTypoDescender'} = $table->{'Descender'} = -$self->{'usWinDescent'};
308 0           $self->{'sTypoLineGap'} = $table->{'LineGap'} = 0;
309             }
310              
311 0 0         if ($self->{'Version'} < 3)
    0          
312             {
313 0           for ($i = 0; $i < 26; $i++)
314 0           { $avg += $hmtx->{'advance'}[$map->{'val'}{$i + 0x0061}] * $weights[$i]; }
315 0           $avg += $hmtx->{'advance'}[$map->{'val'}{0x0020}] * $weights[-1];
316 0           $self->{'xAvgCharWidth'} = $avg / 1000;
317             }
318             elsif ($self->{'Version'} > 2)
319             {
320 0           $i = 0; $avg = 0;
  0            
321 0           foreach (@{$hmtx->{'advance'}})
  0            
322             {
323 0 0         next unless ($_);
324 0           $i++;
325 0           $avg += $_;
326             }
327 0 0         $avg /= $i if ($i);
328 0           $self->{'xAvgCharWidth'} = $avg;
329             }
330              
331 0           $self->{'ulUnicodeRange2'} &= ~0x2000000;
332 0           foreach $i (keys %{$map->{'val'}})
  0            
333             {
334 0 0         if ($i >= 0x10000)
335             {
336 0           $self->{'ulUnicodeRange2'} |= 0x2000000;
337 0           last;
338             }
339             }
340              
341 0 0 0       $self->{'Version'} = 1 if (defined $self->{'ulCodePageRange1'} && $self->{'Version'} < 1);
342 0 0 0       $self->{'Version'} = 2 if (defined $self->{'maxLookups'} && $self->{'Version'} < 2);
343            
344 0 0 0       if ((exists $self->{' PARENT'}{'GPOS'} && $self->{' PARENT'}{'GPOS'}{' read'}) ||
      0        
      0        
345             (exists $self->{' PARENT'}{'GSUB'} && $self->{' PARENT'}{'GSUB'}{' read'}))
346             {
347             # one or both of GPOS & GSUB exist and have been read or modified; so update usMaxContexts
348 0           my ($lp, $ls);
349 0 0         $lp = $self->{' PARENT'}{'GPOS'}->maxContext if exists $self->{' PARENT'}{'GPOS'};
350 0 0         $ls = $self->{' PARENT'}{'GSUB'}->maxContext if exists $self->{' PARENT'}{'GSUB'};
351 0 0         $self->{'maxLookups'} = $lp > $ls ? $lp : $ls;
352             }
353            
354 0           $self;
355             }
356              
357              
358             =head2 $t->guessRangeBits (\%map, [$cp_threshold, [%u_threshold]])
359              
360             Set the ulCodePageRange and ulUnicodeRange fields based on characters actually present in the font.
361              
362             %map is a hash keyed by USV returning non-zero for characters present (e.g. use {'val'}
363             a from Unicode cmap).
364              
365             The two optional parameters are percentage of characters within the codepage or unicode range that need
366             to be present to constitute coverage. A threshold of 0 causes corresponding range bits to
367             be set if any characters are present at all, while a negative value causes the corresponding
368             range bits to be unchanged. Defaults are 50 and 0, respectively.
369              
370             For codepage bits, the threshold is percentage of characters between 0xC0 and 0xFF that need
371             to be present to constitute coverage). For codepages other than 1252,
372             characters (e.g., punctuation) that are defined identically to cp1252 are ignored
373             for the purposes of this percentage calculation. Looks only for SBCS codepages, not DBCS.
374              
375             For Unicode range bits that represent multiple ranges, e.g., bit 29 represents:
376              
377             Latin Extended Additional 1E00-1EFF
378             Latin Extended-C 2C60-2C7F
379             Latin Extended-D A720-A7FF
380              
381             the bit will be set if any of these ranges meet the threshold requirement.
382              
383             =cut
384              
385             sub guessRangeBits
386             {
387 0     0 1   my ($self, $ucmap, $cp_threshold, $u_threshold) = @_;
388 0 0         $cp_threshold = 50 unless defined ($cp_threshold);
389 0 0         $u_threshold = 0 unless defined ($u_threshold);
390 0           my $j; # index into codepages or ranges
391             my $u; # USV
392              
393 0 0         unless (ref($codepages[0]))
394             {
395             # One-time work to convert range data
396            
397             # unpack codepages. But first make sure we have Zlib
398 0 0         eval {require Compress::Zlib} || croak("Cannot unpack codepage data Compress::Zlib not available");
  0            
399              
400 0           for ($j = 0; $j <= $#codepages; $j++)
401             {
402 0 0         next unless $codepages[$j];
403 0           $codepages[$j] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $codepages[$j])))];
404 0 0         warn ("Got nothing for codepage # $j\n") if $#{$codepages[$j]} < 128;
  0            
405             }
406            
407             # convert Unicode array data to hash
408 0           my @newRanges;
409 0           for ($j = 0; $j <= $#ranges; $j++)
410             {
411 0 0         next unless $ranges[$j][2] =~ m/^([0-9a-f]{4,6})-([0-9a-f]{4,6})$/oi;
412 0           my $s = hex ($1);
413 0           my $e = hex ($2);
414 0 0         next unless $e > $s;
415 0           push @newRanges, {start => $s, end => $e, bit => $ranges[$j][0], name => $ranges[$j][1]};
416             }
417 0           @ranges = sort {$a->{'end'} <=> $b->{'end'}} (@newRanges);
  0            
418             }
419              
420 0 0         if ($cp_threshold >= 0)
421             {
422 0           my $cpr; # codepage range vector
423 0 0         $cp_threshold = 100 if $cp_threshold > 100;
424 0           vec($cpr, 63 ,1) = 0; # Get all 64 bits into the vector
425 0           for $j (0 .. $#codepages) # For each codepage
426             {
427             # Count the number of chars from @range part of codepage that are present in the font
428 0           my $present = 0;
429 0           my $total = 0;
430 0           foreach (0x20 .. 0xFF)
431             {
432 0           $u = $codepages[$j][$_];
433 0 0         next if $u == 0xFFFD; # Ignore undefined things in codepage
434             # For codepage 1252, ignore upper ansi altogether
435             # For other codepages, ignore characters that are same as in 1252.
436 0 0         next if $j > 0 ? $u == $codepages[0][$_] : $u > 0x007F;
    0          
437 0           $total++;
438 0 0 0       $present++ if exists $ucmap->{$u} && $ucmap->{$u} > 0;
439             }
440             #printf STDERR "DBG: Got $present / $total (%0.3f%%) in codepage bit $j\n", $present * 100 / $total;
441             #print STDERR "DBG: setting bit $j\n" if $cp_threshold == 0 ? ($present > 0) : (($present * 100 / $total) >= $cp_threshold);
442 0 0         vec($cpr, $j, 1) = 1 if $cp_threshold == 0 ? ($present > 0) : (($present * 100 / $total) >= $cp_threshold);
    0          
443             #print STDERR "\n";
444             }
445 0           ($self->{'ulCodePageRange1'}, $self->{'ulCodePageRange2'}) = unpack ('V2', $cpr);
446             }
447              
448 0 0         if ($u_threshold >= 0)
449             {
450 0           my $ucr; # Unicode range vector
451             my @count; # Count of chars present in each range
452 0 0         $u_threshold = 100 if $u_threshold > 100;
453 0           vec($ucr, 127,1) = 0; # Get all 128 bits into the vector
454 0           $j = 0;
455 0           CHAR: for $u (sort {$a <=> $b} keys %{$ucmap})
  0            
  0            
456             {
457 0           while ($u > $ranges[$j]{'end'})
458             {
459 0 0         last CHAR if ++$j > $#ranges;
460             }
461 0 0         next if $u < $ranges[$j]{'start'};
462 0 0         $count[$j]++ if $ucmap->{$u};
463             }
464 0           foreach $j (0 .. $#ranges)
465             {
466 0 0         vec($ucr, $ranges[$j]{'bit'}, 1) = 1 if $u_threshold == 0 ?
    0          
467             ($count[$j] > 0) :
468             (($count[$j] * 100 / ($ranges[$j]{'end'} - $ranges[$j]{'start'} + 1)) >= $u_threshold);
469             }
470 0           ($self->{'ulUnicodeRange1'},$self->{'ulUnicodeRange2'},$self->{'ulUnicodeRange3'},$self->{'ulUnicodeRange4'}) =
471             unpack ('V4', $ucr);
472             }
473             }
474              
475             BEGIN {
476              
477 1     1   12 @codepages = (
478             <<'EOT', # Bit 0: cp1252
479             M>)P-R>-B%E```-#S+1O+O%NU;-MVRURV[7?H"3*7;2_;M6S;K=7Y>Q`1)8VT
480             MTDDO@XPRR2R+K++)+H><
481             M*J>\"BJJI+(JJJJFNAIJJJ6V.NJJI[X&&FJDL2:::J:Y%EIJI;4VVFJGO0XZ
482             MZJ2S+KKJ)EYW/?342V]]]-5/?P,,-$B"P888:ICA1AAIE-'&&&N<\2:8:)+)
483             MIIAJFNEFF&F6V>:8:Y[Y%E@8$E-30J'(HE`LQ(408J*20I5(0J@;Z9::$IF?
484             MFO)_"X2"H4@H&F)#=,@3E1P3&QD
485             MUMM@HTTVVV*K;;;;8:===MMCKWWV.^"@0PX[XJACCDMRPDFGG';&6>><=\%%
486             MEUQVQ5777'?#3;?<=D>RN^ZY[X&''GGLB:>>>>Z%EUYY[8VWWGGO@X\^^>R+
487             3K[[Y[H>??OGMCQ1_I?X#Q@N!>@``
488             EOT
489              
490             <<'EOT', # Bit 1: cp1250
491             M>)P-Q^=+U'$`Q_'WY^>LW%K=G:/OG6:VM4R[*RU'.7.EY2BW5E:.MOM?Z8%8
492             MXB#!,O"1$8A$/2G:$D40$?6D2)`.NP=O>+T!8>&'/P$$$D0P&]C()D(()8QP
493             M(H@DBFABV,P6MF+#CH-8XH@G@6T8G+A()(GM)+.#%':RB]WL82_[V$\J:1S@
494             M(.D<(H-,#N/&PQ&.DD4VQSA.#KGDD<\)3E)`(4444T(IIRBCG`HJJ>(TU=1P
495             MAK/44D<]#9SC/(TTT4P+K;313@>=7.`BE^CB,E>X2C<]]-+'-:YS@YO
496             MZ&>`08889H11,[7N-0Y?"2;9&./T*57-QJUZM6M8_;ZW&;N),_'&9:)-S+K7
497             MZ5*+\:A!'1K1`'>M)>NM1XK
498             M0$TL*,M:4;:&5,TB3V3Q5&X%LJ00EF7CF1P\YX7"%*$\%?"25ZK@-6]4JV[>
499             MJY>/K*B53ZKA,U_DQU=Y%,0WA?)==GXHEI_\4K@BE:]"?O-'E?QE577J84U]
500             +_,.K-NO=?_3I:`(`
501             EOT
502              
503             <<'EOT', # Bit 2: cp1251
504             M>)P%P=52%5``0-$-;!KISG,OW=W=#=(IV-W=_H+^@0^.CB,Z^J`^^&V.K@7$
505             M$$L<$D\"B2213`JII'&*=#+()(ML
506             M4$L=]3302!/-M-!*&^UTT$D7W?302Q_]###($,.,,,H8XTPPR133S##+'/,L
507             ML,@2RZRPRFG66&>#3;;89H==]MCG@$/.<,0Q9SG'>2YPD4M
508             M6]SF#G>YQWT>\)!'/.8)3WG&\YHVQQH5B-T)YJ`DA1,)):#,Y])MB
509             MFJEFN!X*0U$H#64A&G)"[K^_D:A[8F>V02'WS+1SX9PV?E"R=\
510             MY9N)?.>'"6[[CI_\XK=KD7PW^>.N\6ZY8Z999IMCKGGF6V"A119;8JEEEEMA
511             M,&+42JNLML9:ZZRWP4:;;+;%5MMLM\-.N^RVQU[[['?`08<<=L11QQQWPDFG
512             3G';&6>><=\%%EUQVQ=7_+3E$L0``
513             EOT
514              
515             <<'EOT', # Bit 3: cp1253
516             M>)PUB>
517             M12)-H_ZCYSR]7YS[7!^NZP8\&(48S1C&,H[Q3&`BDYB,)U/P8BK>^."+'_X$
518             M,(U`@@AF.B&$$L8,#`Z
519             M+''$D\!*5K&:-:QE'8FL9P,;V<1FMI!$,EM)81NI;&<'.]G%;O:PEWWLYP`'
520             M.<1ACG"48QSG!"
521             M;>YPESSCLBT3[%%HPDR$,<;AMF@WL;8U,A-H@DR("35.XVO\;,OA=+>XD9=R
522             M%>@>%512134UU%+GKO6X:*#1^--,"ZVT*9]V.NC4?3W00[KUB!X]UA,]U3,5
523             MJDC%>JX2O5"I7JI,K_1:;_16[U2N][:E"E6J2M6J4:WJ]$'U
524             MJC9]5+LZU*E/^JPN=>N+>O15O>K3-_7KNW[HIW[IM_YH0(,:TK#^ZI]M_0=K
525             #AH5\
526             EOT
527              
528             <<'EOT', # Bit 4: cp1254
529             M>)PER6-ST'$``.#GOVPLM]9OJY9KR\NV[99M^SOT";)MV[S,NVQ=]JWKNN?E
530             M@TB,##+*)+,LLLHFNQQRRB6W//+*)[]8!1142&%%%%5,<7%*B%=2D"!1*:65
531             MD:2L
532             M;;737@<===)9%UUUTUT//?726Q]]]=/?``,-DF:P(88:9K@11AIEM#'&&F>\
533             M"2::9+(IIIIFNAEFFF6V.>::9[X%%H;UZ7]"L6A1B`])(82$F),A.4H+J5'7
534             M]#__A2*A:(@+)4)BB`T%8NXE)$:#0]VHV[^+9EELB:6666Z%E599;8VUUEEO
535             M@XTVV6R+K;;9;H>==MEMC[WVV>^`@PXY[(BCCCGNA)-..>V,L\XY[X*++D7Q
536             M+KOBJFNNN^&F6VZ[XZY[47(TT'T///3(8T\\]
537             6Y+,OOOKFNQ]^^N5WE!(-DOX7C-.`8```
538             EOT
539              
540             <<'EOT', # Bit 5: cp1255
541             M>)Q%C]=7#@`X;L\3_X"Z)3*4E[G)9Q
542             MCFLR(MDK71'GN/K.)\[I.,_=\]X\+^"%@T$,1@QA*,/P9C@C&,DH?/!E-&,8
543             MBQ_^C&,\$P@@D""""2&4,"9B.'$QB
544             MC_DL()8XXEG((A:SA`026
545             M30Z;V,P6MK*-7+:S@YWL8C=[V,L^]G.`@QSB,$
546             MXSP7N,@E+G.%JU;N<5N0US4+LW`S6DR_B?.X![``"[00"S67^9F_H]OI
547             MZG?Q`RL%7.<&A59&$<64<)-2.KE%.;>IX`Z55%%-#;7444\#C33QFV9::*6-
548             M=E6J2M6J4:WJ5*\&-:K)XU:S6M2J-K7KKN[IOA[HNWZH3S_UZW_97_1(C]6A
549             M)WJJ9WJN3KW02W7IE;KU6F_T5N_T7A_T49_T65_T53WZIMY_OWS,U^/^`\"V
550             "EBL`
551             EOT
552              
553             <<'EOT', # Bit 6: cp1256
554             M>)P%P;=/%``8A^'W$'\J'*`"2N>[`XX.1^?.1N_UL``*=A'L8$,4-^.J$R,1
555             M&Q$%%+N2N/@'N+@:%UN"BXDA./@\@(,@5A',:L0:UK*.$$)Q$D8X$:QG`QN)
556             M)(IH-K&9&&*)(YX$$DDB&<.%FQ122<-#.AEDDD4V.>221SY>"BBDB&)***6,
557             M
558             MRS[ZZ&<_!SC((0YSA*,<8X#C##+$"4YRBM.XS"A7&.,J
559             MUQCGNLUHW.(
560             M[^@RIX7I#9-RL
561             MQWL6E:P/
562             M5:5JOJB&KZI5G>K5P#>^\X.?_%*CFECBMYK5HE:U\4?MZN"O.EE6@!7^6;A%
563             'Z--_?PY;L```
564             EOT
565              
566             <<'EOT', # Bit 7: cp1257
567             M>)P-B4=/%&``1-^L%`M86(1=FM\N106E]R)2;6`7%"P@%CI([_X5HT8E8N]1
568             M.5GBV2@22;P("6G"S?HK"""0(()9S1K6LHX00EG/!C:RB3"<
569             MA+.9"")QX2:*:&*()8XM&#QXB2>!1)+8RC:VDTP*.]A)*FFDDT$F66230RYY
570             MY%-`(4444\(N2ME-&>544$D5U>QA+_O8SP%JJ.4@ASC,$8YRC..
571             M!AHYS1G.XR"4NTTH;[73021?=]-#+%?KH9X!!AAAFA%'&&&>"
572             M2::X:F;\/A-EB3-)QAB/M71+@=_''<='7EIW&;>),;'&:YPFW._S>.U6:/\'
573             MCN\VKUFN\HSGO.`OKU3/:][PEEF6
574             M%*!4H2#>\5XNA2F$3QI5A+S*5;**U*0*5?%9-7SA*W/J4YD:U,Z"QC7)#P4J
575             M35(P/UF46TZ%LJPQ12I>>4I1L9I5J6I^J9;?K/!'_2I7HSKXIPE-.>;_`YNL
576             ";XP`
577             EOT
578              
579             <<'EOT', # Bit 8: cp1258
580             M>)PER>5.EF$`@.'KY;,[,%#1!U3L[NYNL+N[$_LR&;.=
581             M.J>S&>K<_>^Z$8D3DT=>^>170$&%%%9$4<445T))I906KXRRRBDO004559*H
582             MLBJ"),FJJJ:Z%#745$MM==153WT---1(8TTTU4QS+;342FMMM-5.>QUTU$EG
583             M773537<]]-1+;WWTU4]_`PPT2*HT@PTQU###C3#2**.-,=8XXTTPT22333'5
584             M--/-,-,LL\TQUSSS+;#0(HLML=0RZ99;8:555EMC;=B9FQ,J1.M"Y9`20DB*
585             MRPH-_TJK*#4WYW^A?$@(E4)B2`ZE0WQ<=E+R7VL=I?U[4;H,F=;;8*---MMB
586             MJVVVVV&G77;;8Z]]]CO@H$,..^*H8XX[X:133COCK'/.1W$NN"C+)9==<=6U
587             M&-?=<#,JX5:LH-ON1!GNNN>^!QYZ)#O:$XMY[(FGGD4QS[WPTBNOO?'6NUCD
588             @O0\^1B5]BE7UV9
589             EOT
590              
591             undef, # Bit 9: Reserved
592             undef, # Bit 10: Reserved
593             undef, # Bit 11: Reserved
594             undef, # Bit 12: Reserved
595             undef, # Bit 13: Reserved
596             undef, # Bit 14: Reserved
597             undef, # Bit 15: Reserved
598              
599             <<'EOT', # Bit 16: cp874
600             M>)Q=C=52&U``!1?W11(@@00N`8*[4\'=W>KN[OHK_8#^8J=]Z.0!9E_.S,Z<
601             M!;+()H=<\LBG@$****:$4LJ0JH)T&2!AH)-)&BF19:
602             M2=-&.QUTTD4W/?321S\###+$,".,,L8X$TQRB
603             MPBIKK+/!)EMLL\,N>^QSP"%'''/"*6=\X2G
604             M/.,Y+WC)*U[SAK>\XST?^,@G/O.%KWSC.S_X&7[__?.?D,ZL\X18B(=$2(94
605             MB(3H1
606             MF;+9%EM-VV:['7;:9;<]]MIGOP,..N2P(XXZYK@33F;J3CGMC+/..>^"BRZY
607             @[(JKKKGNAIMNN>V.N^ZY[X&''GGLB:>>91[^`:-3=+0`
608             EOT
609              
610             undef, # Bit 17: Reserved
611             undef, # Bit 18: Reserved
612             undef, # Bit 19: Reserved
613             undef, # Bit 20: Reserved
614             undef, # Bit 21: Reserved
615             undef, # Bit 22: Reserved
616             undef, # Bit 23: Reserved
617             undef, # Bit 24: Reserved
618             undef, # Bit 25: Reserved
619             undef, # Bit 26: Reserved
620             undef, # Bit 27: Reserved
621             undef, # Bit 28: Reserved
622             undef, # Bit 29: Reserved
623             undef, # Bit 30: Reserved
624             undef, # Bit 31: Reserved
625             undef, # Bit 32: Reserved
626             undef, # Bit 33: Reserved
627             undef, # Bit 34: Reserved
628             undef, # Bit 35: Reserved
629             undef, # Bit 36: Reserved
630             undef, # Bit 37: Reserved
631             undef, # Bit 38: Reserved
632             undef, # Bit 39: Reserved
633             undef, # Bit 40: Reserved
634             undef, # Bit 41: Reserved
635             undef, # Bit 42: Reserved
636             undef, # Bit 43: Reserved
637             undef, # Bit 44: Reserved
638             undef, # Bit 45: Reserved
639             undef, # Bit 46: Reserved
640             undef, # Bit 47: Reserved
641              
642             <<'EOT', # Bit 48: cp869
643             M>)Q%R>=7#0`
644             M3EHJ&@C)WN(_ZN0<;YSGY0,,P@LQF"$,Q9MA#&<$(_%A%*/QQ8\QC&4<_@0P
645             MG@DX"&0B000SB
646             M+&,Y*XAD):M8311K6,LZUK.!:&*()8Z-;&(S6]C*-N))8#N))+&#G22SB]VD
647             ML(>]I+*/_:1Q@(.D
648             M,E>X2OY`_W^Z/M!/-ZTT.!W.0!4Y`W1#-_58Q?_VEEIH5@F==*F5.K7IB9[J
649             MITK5I]\J4[GG5/E;308V56;F[S,I?NJTK5>F#IEF#)EJJ'JC$_
650             M\[<("[=@PR+E4:VE6))E6H:E6;QEJ4Z/5*\&-:I)S>I0I[K,83Y69`5ZIN=V
651             M32_4K9=ZI=?JT1OUZJW>Z;T^Z),^ZK,*:*-#7_15WVC4=Q723I-^Z)?:]<<\
652             '>/X"GB5Z;@``
653             EOT
654              
655             <<'EOT', # Bit 49: cp866
656             M>)P%P45#$P``AN$7_!0#<=088]381XYN&-W=#:,;N]N#!P\>C#_`P1_@S;_G
657             M\P`II'(#<9-;I'&;.]SE'NG<)X,'!,@DBVQRR"5('B'R"5-`A$****:$4J*4
658             M$<.44T$E55130YQ:ZJBG@4:::*:%5MIHIX-.NN@F00^]]-'/`(,,,
659             MS@233#'-#+/,,<\"BRRQS`JKK+'.!IMLL.<"RZY
660             MXB&/>,P3GO*,Y[S@):]XS1O>\H[W?.`CG_BL@#*5I6SE*%=!Y2FD?(55H(@*
661             M5:1BE:A4494I)JM<%:I4E:I5H[AJ5:=Z-:A136I6BUK5IG9UJ%-=ZE9"/>I5
662             MGW_ZEW\[U3'O^\"K7O&A%[SF'6][RP'GN,5Q1XP33GK7FU[VN4^\YWE?^=1G
663             M/O*Q-[SN12_YTA<..=W?_-7?_<-?U*\!#6I(PQK1J,8TK@E-:DK3FM&LYI2B
664             :!4G+2M.:,I3D;S2??]%P:9`_ON;Z/\R_26T`
665             EOT
666              
667             <<'EOT', # Bit 50: cp865
668             M>)P%P3=,%&``AN$7?FR(>BH@W>,_/A%%;-BQ*V*G]W9P1[=W:0X.#@P(BR,&
669             M([$,8B0F1J.)B'%D,0XD*K$W@AHIDNCS`#[X8O!C$I.9PE2FX<]T`IC!3&;A
670             M8#9SF$L@000SCQ!""2.<""*)8CY.HK&XB$$L():%Q+&(Q<2SA`26LHSEK&`E
671             MB:QB-6M8RSK6LX$D-K*)S6QA*]O8S@YVDLPN4MC-'O:RC_T
672             MD4T.N>213P&%%%%,":6X*:,<#UXJJ*2*:FJHI8Y#'.8(1SG&<4YPDE.
673             M.<=YZFF@D2::>^\)5/#/&#;_3RC!=\H(_?_.$G?QGC'R\9
674             M8)1.7CF[?-IXRW=^,O8N16F;*5I7*E
675             M*4=%*E2!'`I4HN(5(92D8I4H7YFJ5H5*E:HZ5:I*'GF5IURE*T.UJE&(`G1)
676             M%]6B5ETPW;PV[>:)Z31/Z3&]YKJY8FZ8>S;*])D>&V?==%NO];B
677             0;"CW;9BSF;OJH.,_G\AQ]P``
678             EOT
679              
680             <<'EOT', # Bit 51: cp864
681             M>)P=R'EHSW$
682             M:18C+<#J$<(/NK3`*,AC6A,$YKBIQG-:4$H
683             M+6E%:\)H0UO:$4X$D40137MBB"6.#GAT)-Z*Z$1GNM"5;G0G@1[TI!>]Z4-?
684             M^I%(?P8PD$$,9@A#26(8PQE!,B-)812C&<-84DEC'..9P$0F,9DI3"6=:4QG
685             M!C.9Q6SF,)=YS&
686             MZ]G`1C:QF2ULI9AM;.
687             M4L,-+XURJE6GW\%`,*`_^AL,4$J%=E'&&>WYOP=T4$=UW/PZH5,Z:QF6:5F6
688             M;3F6:WF6;P56J*<6I4I=TW6+Y;1V:*=V:Z_N:9_VZY".Z)A*=%)E.J\+*E>%
689             M+NFJJE2MF[JEV[JOQYSC(G74ZJXEZYEJ]5*O]5;O]5&?]44_5*,'>J2'>J-B
690             <2]<[?=`G?=5W/=%S_=0OO=(+?7.EP<`_%"[`E0``
691             EOT
692              
693             <<'EOT', # Bit 52: cp863
694             M>)P%P4E0#7``Q_%O_9&E>!(M4J__ZQJ_=4I;L.3@X=$A=
695             M'!N9:#+3HF+&,@W&.L/%Q3##N%3,<&#&6`X^'\`'7PS3F,X,_)C)+&8S!W\"
696             MF,L\',PGD`4$L9!%!!-"*&$L)IPE1!")DR@L+J(1,2QE&;$L)XYX5K"25220
697             MR&K6D,1:UK&>#6QD$YM)9@M;V48*V]G!3G:QFU322">#/>QE'_LYP$$RR2*;
698             M''+)(Y\""BFBF!)**:.<"BIQ4T4U'KS44$L=]3302!.'.,P1CM),"\
699             MTLHI3G.&LYSC/!=HXQG_F.(SC_C$&!-\X2N3?.>;,YAQ;O""Y[SD)Z]XPU]^
700             M"UR\$M'G"?A_1S3U?4J2[Y*EIN52E?
701             M>:I6E@I4IE*5R*$@)2E>X4+)*E>%BI6K>M6H4IEJ4JWJY)%712I4MG+4J`:%
702             MR%^7=4GMZM!%,\1'TV7&38]YS*AY8GK-5=-G1FR$>6I&;:QU,V2]UN-RNJ+X
703             39=,9M*'
704             EOT
705              
706             <<'EOT', # Bit 53: cp862
707             M>)P%P3=,U'$KHMBQ8V_8Z;T=W-'MO<+@X,"@L#BB
708             M1(UE$",QL403C;/8.V+7Q,$XF#CY/$`$D3CZ8?1G``,9Q&"&$,50AC$<'R,8
709             MR2BB&
710             MPUSF,9\%+&01Z2QF"4M9QG)6L))5K&8-:\E@'>O9P$8VL9DM9))%-CGDDD<^
711             M!1121#$EE%)&.154$J2*:D*$J:&6.NIIH)$FMK*-[>Q@)[O8S1[VLH_]'.`@
712             MASC,$8YRC&9[9#WVV)[84WMFS^V%O;17]MK>V%M[9^^MUSY8GWVT3_;9OMA7
713             M^V;?[8?]Y"R=G/-?B&BCCU_\X1^_Z>$2-[D;\'&%.]SF#)>YI5-J4[LBE:R@
714             MJI2O/%4K2P4J4ZE*Y%.TTI2J>*%TE:M"Q
715             M5(-B%*43.JY6G52+ZZ+7M;M[KM/=I]L]<.?=:7?17?<2W$/7[:5X0;J\L!<*
716             8^`-)_/4RN.K%
717             EOT
718              
719             <<'EOT', # Bit 54: cp861
720             M>)P%P4=(%7``Q_&O_FU;O4K+W?/__%6F;=NVRZRTW'L]?<_=WD/MT*&#!]-+
721             M1T,H)`\928<,C4SI$`2!1)@-VB($185F]/D`/OAB\&,2DYG"5*8QG1GX,Y-9
722             MS,;!'.8RCP`"F<\"@@@FA%#""">"A3B)Q.(B"K&(Q2PAFJ7$$,LREK."E:QB
723             M-6N(8RWK6,\&-K*)S<2SA:UL8SL[V,DN=K.'!/:2R#[V
724             M,L@DBVQRR"6/?`HHI(AB2G!32AD>O)1302555%-#+8
725             M6
726             M##+$']IXZ;SET\P[1OG!&(]XQ@M>T>-RT,%#NKG!;1[HFIK5(E]%R:U292E3
727             M94I5M@I5H'PY%*`XQ2I,*%Y%*E:>,E2E
728             MZZJNJ%%-NFPZ>6-:3*]I,X_I,GWFIKENVLT]&V'Z39>-MFXZK==Z7$Y7)+]M
729             2(G=L,/=MB+.!NVJE]3^&>7'F
730             EOT
731              
732             <<'EOT', # Bit 55: cp860
733             M>)P%P4E0#7``Q_&O_G8A*MKD]7_]4F2/0F07*NW[]NJ]=DOVO0X=.CB@BV,T
734             MPU@.931FJ"DR6:8.%0?&#.I@&0[(&,;!YP-,P`O#1"8QF2E,91K3F8$W,YG%
735             M;'R8PUQ\\<.?>
736             ML9H8UK"66.)8QWHV$,]&-I'`9K:PE6UL9P<[V44BN]G#7I)()H5]I))&.AED
737             MDD4V.>221SX%%%)$,264XJ*,
738             M3G**TYSA+.\(E!7O*5/A[SG%Z>,
739             MBK=
740             M-.6H2(4JD(_\%*-HA0C%JU@ERE>FJE6A4J6J3I6JDEL>Y2E7Z
741             MJTD7=%&-IH-WIL7TFC;31Z=Y8JZ;*^:FN6=#3;_IM%'618?U6+?3X0SCMTVD
742             1W09RWP8Y&KBK5EK_`R9#<9@`
743             EOT
744              
745             <<'EOT', # Bit 56: cp857
746             M>)P-RE-W%W```-#[7[:6E_O%Y67;7BUKM5HMVSWTT&OU!;)MVSR9YV3K9)_:
747             MZST7$5'22"N=]#+(*)/,LL@JF^QRR"F7W/*(EE<^^1504"&%Q2BBJ&***Z&D
748             M4DH+RBBKG/(JJ"A6)955454UU=40IZ9::JNCKGKJ:Z"A1AIKHJEFFFNAI59:
749             M:Z.M=MKKH*-..NNBJVZZB]=#3PEZZ:V/OOKI;X"!!AELB$1##9-DN!&2C31*
750             MBM'&&&N<\2:8:)+)IIAJFNEFF&F6V>:8Z[0_7GGLJ8>>>>&U-U[ZX'VDFA-.
751             M.NNY4[[XYI/??D:JNNF^'Y:['1D0&>B1=S[[Y:,KD:*18@[;9(.##EAJO?UA
752             M85@4%H>H4-I1QQRQ-B2&KB$A]+?,RI`S1(>X$!MB@M#`$\=#GQ`?DD-2&!2Z
753             MA!0K[+/..>>=^??719=<#@5"UK`@S+?*A3#/-0]<=]57-^Q,/;?<=<\=;_VS
754            
755             EOT
756              
757             <<'EOT', # Bit 57: cp855
758             M>)P%P<52$``40-$+7$`%*>D&>3327=)("4A(HU@H=K<+%V[5'V#AC`O'+_#G
759             M/`=(()$D))D44CG#6
760             M16H(:JFCG@8:::*9%B[12AOM=-!)%]WTT$L?_0PPR!##C##*9<889X))IIAF
761             MAEFN,,<\"RRRQ%6666&5:ZRQS@:;7&>+;7;898]]#CCD!C
762             M?1YPPD,>\9@G/.49SWG!2U[QFC>\Y1WO^
763             MFNIUS[CE6;<]YXYI[IKNOAD>F.F2EYRST3:S;#?;:6OM,M=N\YRTQDXO\(=_
764             M\3U^Q,](C!JG#/LLC*-8B
765             M'+3$(4L=MLP1RQV-PDB/;_'5"J_&%UN];*5C5CENM1->M,=\.\QQP>:J?/XZ
766             8;Y.]%CAKO8NV>,4&9ZSC=YQR^A\'$$.V
767             EOT
768              
769             <<'EOT', # Bit 58: cp852
770             M>)P%P=M/S@$%)Z.1%^BG',HG8M2#L^C)]63ZJFG(M+!N;,+
771             M%]WB'^C"QH:MBRYLKIBMF7'#*H=FS&9FN6%LIJW7"Q`.88030211+&,Y*UB)
772             MBVABB,5-'*N()X'5K&$M'A))(ID44DEC'>M)9P,;R<#8Q&8RV<)6LLAF&]O9
773             MP4YVL9L]Y+"7?>SG`+GD<9!\"BBDB&)***6,<@YQF`HJ.4(5U1SE&,
774             M)ZG!3RVGJ*.>!@(T;B[00R]]]'.12USF
775             M"E>YQG4&&&2(848898QI_O.=+WQ5KZ+XIE)^R"L?/S7`
776             M!=3(#!_5K@Z5,*MH/K/`+_XI7!$:T:@\2N2A!N52"P]X8K?LMMTQQS)XRC,E
777             MJ=E"YK,Z:]*0ALUM"99CV99B6+X
778             M9/.8R\;MIMK48S=XPR?>JDSEJE10K?+S7K7J8Y%YA9CBD3/O?'"FG3GN\9?'
779             13'+?>:=^U:O!)IA8`NR$89P`
780             EOT
781              
782             <<'EOT', # Bit 59: cp775
783             M>)P%P
784             M0P<']`\T:C*&#!J,\7#"C+,)!S,NF'$VZ.#@]0)$%`N()H98XHAG(8M8C(L$
785             MEI!($DM))H54EI%&.FX\+&<%7C+(9"4.J_"1139&#JM9PUIRR2.?=110R'HV
786             ML)%-%+&98DK8PE:V48J?[>Q@)[LHHYP**@D09#=[V$L5^ZBFAOT
787             M>@[30(A&CA"FB:,T
788             M<)5K]-)'/P,,,L2P8OG'3XEORN*[XE2N%#4HI#SU\H:WO.<'[U3#'_FXK;":
789             M^,@7YIGD,Y^8$LKEE_HUH#XG@VGN\H#[O.*ERKC'"[MIMVS
790             MM3H+6;,*%+$D2[4BRS>O87YUJ\/"5F_MUF81J[4N#2I&"?(H785J48\Z-61N
791             M<]F8C=IUNV$C?."KJE7!;^9XHDH5JT2E\BNH9`4<#S,\
792             .X1G/F>6Q33#Q'V@>75\`
793             EOT
794              
795             <<'EOT', # Bit 60: cp737
796             M>)P%P65W#@``AN';'FT8AFV&>>V1T]/3-;WN[M*=\\%QQMG!-IVOH]LFIKOK
797             M[_CJNH`.A"`ZTHG.=*$KW>A.#T+I22]Z$T8?^M*/
798             M2@S#"#"<6,P(1C**T8QA+'&,8SP3F,@D)C.%>*8RC>G,8":SF$T"
799             M@(4L8C%+6,HR$EG."E:RBM6L82U)))-"*FFDDT$F66230RYYY%-`(4444T(I
800             M991302555%-#+76L8ST;V,@F-K.%K6QC.SO8R2YVLX>][&,_]6I2LUIT0B=U
801             M2J=U1F=U3N=U01=U29<5U!5=U35=UPW=U"W=5JO:]%A/]%3/U*[G>J&7>J77
802             M>J.W>J?W^J!/^JC/^J*O^J;O;G*S6QSB6!>[Q!E.=ZF3G>E\YSG780YWO.,<
803             M;9S@`A
804             M/_50O_5'O_17A]2@PSJB1AW5,5H#Y8$RW=%=_@42>12(I#T0%5-/FX,$_P-K
805             #(&Q0
806             EOT
807              
808             undef, # Bit 61: cp708 (unknown)
809              
810             <<'EOT', # Bit 62: cp850
811             M>)P%P5-C$&```,#;UC&5[JV6WW++=0P^]5G\@V[9MV[;M.T2(E$QR
812             M*:242FIII)5.E/0RR"B3S++(*IOL
813             M5$II99153GD5Q*BHDLJJJ*J:ZFJHJ998M=515SWU-=!0(XTUT50SS;704BNM
814             MM=%6G'CMM)>@@XXZZ:R+KKKIKH>>>NFMC[X2]=/?``,-,M@00R499K@11AIE
815             MM#'&&F>\"2::9+(IIIIFNAF.^>V%AQZ[[XEG7GKEN7?>>NVP(TYXZJC/OOKH
816             MEQ_^N>JV[Q:Y[EK$7`^\\
817             MK0B)(3YT"CTLM"1D"ME"Y5`FY`M"K$<.A:XA(0P.`T+O$!>2+/;>>2>=
818             MQAEGG0NY0E28'699ZG28Z9)[+KOHBRNV^.NNFVZYX8\[UMELC0V%
819             2V6Z]Y;;989.-8;[Y_P%EF7O'
820             EOT
821              
822             <<'EOT', # Bit 63: cp437
823             M>)P%P3=,%&``AN$7?FR(>BH@(.#Q'Y^*(C;LV!LJ*+VW@SNZO1?`P<&!`6%Q
824             M1`D8RR!&8H(03$2,HXN3B4#LC5@B`4GT>0`??#'X,8G)3&$JT_!G.@',8":S
825             M<#";.
826             M:N)9PUK6L9X-;&03"6QF"UO9QG9VL)-=[&8/>TED'_LY0!+)'.00*:221CH9
827             M9))%-CGDDD<^!1121#$EN"FE#`]>RJF@DBJJJ:&6PQSA*,
828             MYSC/!2YRB3KJ:>`Y$WQBF+<,\HX/?.8+'QGA.U_IYQDO>,\`O_G#3_XRQC]>
829             M\9J;M-'NO.73S!#?^,4X/WC)';KI
830             MI2I;A2I0OAP*5+QB%2Z4H"(5*T\9JE*Y2I2B6E6H4AYYE:L
831             M55?4J"9=-IV\,2WFB6DS3^DR_:;#7#>WS4,;:09,EXVQ;CJMUWI<3E<4HS:1
832             1^S:41S;,V<`#M=+Z'T-Z<84`
833             EOT
834              
835             );
836              
837             # The following taken directly from OT Spec:
838              
839 1         175 @ranges = (
840             [ 0, "Basic Latin", "0000-007F" ],
841             [ 1, "Latin-1 Supplement", "0080-00FF" ],
842             [ 2, "Latin Extended-A", "0100-017F" ],
843             [ 3, "Latin Extended-B", "0180-024F" ],
844             [ 4, "IPA Extensions", "0250-02AF" ],
845             [ 4, "Phonetic Extensions", "1D00-1D7F" ],
846             [ 4, "Phonetic Extensions Supplement", "1D80-1DBF" ],
847             [ 5, "Spacing Modifier Letters", "02B0-02FF" ],
848             [ 5, "Modifier Tone Letters", "A700-A71F" ],
849             [ 6, "Combining Diacritical Marks", "0300-036F" ],
850             [ 6, "Combining Diacritical Marks Supplement", "1DC0-1DFF" ],
851             [ 7, "Greek and Coptic", "0370-03FF" ],
852             [ 8, "Coptic", "2C80-2CFF" ],
853             [ 9, "Cyrillic", "0400-04FF" ],
854             [ 9, "Cyrillic Supplement", "0500-052F" ],
855             [ 9, "Cyrillic Extended-A", "2DE0-2DFF" ],
856             [ 9, "Cyrillic Extended-B", "A640-A69F" ],
857             [ 10, "Armenian", "0530-058F" ],
858             [ 11, "Hebrew", "0590-05FF" ],
859             [ 12, "Vai", "A500-A63F" ],
860             [ 13, "Arabic", "0600-06FF" ],
861             [ 13, "Arabic Supplement", "0750-077F" ],
862             [ 14, "NKo", "07C0-07FF" ],
863             [ 15, "Devanagari", "0900-097F" ],
864             [ 16, "Bengali", "0980-09FF" ],
865             [ 17, "Gurmukhi", "0A00-0A7F" ],
866             [ 18, "Gujarati", "0A80-0AFF" ],
867             [ 19, "Oriya", "0B00-0B7F" ],
868             [ 20, "Tamil", "0B80-0BFF" ],
869             [ 21, "Telugu", "0C00-0C7F" ],
870             [ 22, "Kannada", "0C80-0CFF" ],
871             [ 23, "Malayalam", "0D00-0D7F" ],
872             [ 24, "Thai", "0E00-0E7F" ],
873             [ 25, "Lao", "0E80-0EFF" ],
874             [ 26, "Georgian", "10A0-10FF" ],
875             [ 26, "Georgian Supplement", "2D00-2D2F" ],
876             [ 27, "Balinese", "1B00-1B7F" ],
877             [ 28, "Hangul Jamo", "1100-11FF" ],
878             [ 29, "Latin Extended Additional", "1E00-1EFF" ],
879             [ 29, "Latin Extended-C", "2C60-2C7F" ],
880             [ 29, "Latin Extended-D", "A720-A7FF" ],
881             [ 30, "Greek Extended", "1F00-1FFF" ],
882             [ 31, "General Punctuation", "2000-206F" ],
883             [ 31, "Supplemental Punctuation", "2E00-2E7F" ],
884             [ 32, "Superscripts And Subscripts", "2070-209F" ],
885             [ 33, "Currency Symbols", "20A0-20CF" ],
886             [ 34, "Combining Diacritical Marks For Symbols", "20D0-20FF" ],
887             [ 35, "Letterlike Symbols", "2100-214F" ],
888             [ 36, "Number Forms", "2150-218F" ],
889             [ 37, "Arrows", "2190-21FF" ],
890             [ 37, "Supplemental Arrows-A", "27F0-27FF" ],
891             [ 37, "Supplemental Arrows-B", "2900-297F" ],
892             [ 37, "Miscellaneous Symbols and Arrows", "2B00-2BFF" ],
893             [ 38, "Mathematical Operators", "2200-22FF" ],
894             [ 38, "Supplemental Mathematical Operators", "2A00-2AFF" ],
895             [ 38, "Miscellaneous Mathematical Symbols-A", "27C0-27EF" ],
896             [ 38, "Miscellaneous Mathematical Symbols-B", "2980-29FF" ],
897             [ 39, "Miscellaneous Technical", "2300-23FF" ],
898             [ 40, "Control Pictures", "2400-243F" ],
899             [ 41, "Optical Character Recognition", "2440-245F" ],
900             [ 42, "Enclosed Alphanumerics", "2460-24FF" ],
901             [ 43, "Box Drawing", "2500-257F" ],
902             [ 44, "Block Elements", "2580-259F" ],
903             [ 45, "Geometric Shapes", "25A0-25FF" ],
904             [ 46, "Miscellaneous Symbols", "2600-26FF" ],
905             [ 47, "Dingbats", "2700-27BF" ],
906             [ 48, "CJK Symbols And Punctuation", "3000-303F" ],
907             [ 49, "Hiragana", "3040-309F" ],
908             [ 50, "Katakana", "30A0-30FF" ],
909             [ 50, "Katakana Phonetic Extensions", "31F0-31FF" ],
910             [ 51, "Bopomofo", "3100-312F" ],
911             [ 51, "Bopomofo Extended", "31A0-31BF" ],
912             [ 52, "Hangul Compatibility Jamo", "3130-318F" ],
913             [ 53, "Phags-pa", "A840-A87F" ],
914             [ 54, "Enclosed CJK Letters And Months", "3200-32FF" ],
915             [ 55, "CJK Compatibility", "3300-33FF" ],
916             [ 56, "Hangul Syllables", "AC00-D7AF" ],
917             [ 57, "Non-Plane 0 * ", "D800-DFFF" ],
918             [ 58, "Phoenician", "10900-1091F" ],
919             [ 59, "CJK Unified Ideographs", "4E00-9FFF" ],
920             [ 59, "CJK Radicals Supplement", "2E80-2EFF" ],
921             [ 59, "Kangxi Radicals", "2F00-2FDF" ],
922             [ 59, "Ideographic Description Characters", "2FF0-2FFF" ],
923             [ 59, "CJK Unified Ideographs Extension A", "3400-4DBF" ],
924             [ 59, "CJK Unified Ideographs Extension B", "20000-2A6DF" ],
925             [ 59, "Kanbun", "3190-319F" ],
926             [ 60, "Private Use Area (plane 0)", "E000-F8FF" ],
927             [ 61, "CJK Strokes", "31C0-31EF" ],
928             [ 61, "CJK Compatibility Ideographs", "F900-FAFF" ],
929             [ 61, "CJK Compatibility Ideographs Supplement", "2F800-2FA1F" ],
930             [ 62, "Alphabetic Presentation Forms", "FB00-FB4F" ],
931             [ 63, "Arabic Presentation Forms-A", "FB50-FDFF" ],
932             [ 64, "Combining Half Marks", "FE20-FE2F" ],
933             [ 65, "Vertical Forms", "FE10-FE1F" ],
934             [ 65, "CJK Compatibility Forms", "FE30-FE4F" ],
935             [ 66, "Small Form Variants", "FE50-FE6F" ],
936             [ 67, "Arabic Presentation Forms-B", "FE70-FEFF" ],
937             [ 68, "Halfwidth And Fullwidth Forms", "FF00-FFEF" ],
938             [ 69, "Specials", "FFF0-FFFF" ],
939             [ 70, "Tibetan", "0F00-0FFF" ],
940             [ 71, "Syriac", "0700-074F" ],
941             [ 72, "Thaana", "0780-07BF" ],
942             [ 73, "Sinhala", "0D80-0DFF" ],
943             [ 74, "Myanmar", "1000-109F" ],
944             [ 75, "Ethiopic", "1200-137F" ],
945             [ 75, "Ethiopic Supplement", "1380-139F" ],
946             [ 75, "Ethiopic Extended", "2D80-2DDF" ],
947             [ 76, "Cherokee", "13A0-13FF" ],
948             [ 77, "Unified Canadian Aboriginal Syllabics", "1400-167F" ],
949             [ 78, "Ogham", "1680-169F" ],
950             [ 79, "Runic", "16A0-16FF" ],
951             [ 80, "Khmer", "1780-17FF" ],
952             [ 80, "Khmer Symbols", "19E0-19FF" ],
953             [ 81, "Mongolian", "1800-18AF" ],
954             [ 82, "Braille Patterns", "2800-28FF" ],
955             [ 83, "Yi Syllables", "A000-A48F" ],
956             [ 83, "Yi Radicals", "A490-A4CF" ],
957             [ 84, "Tagalog", "1700-171F" ],
958             [ 85, "Hanunoo", "1720-173F" ],
959             [ 85, "Buhid", "1740-175F" ],
960             [ 85, "Tagbanwa", "1760-177F" ],
961             [ 85, "Old Italic", "10300-1032F" ],
962             [ 86, "Gothic", "10330-1034F" ],
963             [ 87, "Deseret", "10400-1044F" ],
964             [ 88, "Byzantine Musical Symbols", "1D000-1D0FF" ],
965             [ 88, "Musical Symbols", "1D100-1D1FF" ],
966             [ 88, "Ancient Greek Musical Notation", "1D200-1D24F" ],
967             [ 89, "Mathematical Alphanumeric Symbols", "1D400-1D7FF" ],
968             [ 90, "Private Use (plane 15)", "FF000-FFFFD" ],
969             [ 90, "Private Use (plane 16)", "100000-10FFFD" ],
970             [ 91, "Variation Selectors", "FE00-FE0F" ],
971             [ 91, "Variation Selectors Supplement", "E0100-E01EF" ],
972             [ 92, "Tags", "E0000-E007F" ],
973             [ 93, "Limbu", "1900-194F" ],
974             [ 94, "Tai Le", "1950-197F" ],
975             [ 95, "New Tai Lue", "1980-19DF" ],
976             [ 96, "Buginese", "1A00-1A1F" ],
977             [ 97, "Glagolitic", "2C00-2C5F" ],
978             [ 98, "Tifinagh", "2D30-2D7F" ],
979             [ 99, "Yijing Hexagram Symbols", "4DC0-4DFF" ],
980             [ 100, "Syloti Nagri", "A800-A82F" ],
981             [ 101, "Linear B Syllabary", "10000-1007F" ],
982             [ 101, "Linear B Ideograms", "10080-100FF" ],
983             [ 101, "Aegean Numbers", "10100-1013F" ],
984             [ 102, "Ancient Greek Numbers", "10140-1018F" ],
985             [ 103, "Ugaritic", "10380-1039F" ],
986             [ 104, "Old Persian", "103A0-103DF" ],
987             [ 105, "Shavian", "10450-1047F" ],
988             [ 106, "Osmanya", "10480-104AF" ],
989             [ 107, "Cypriot Syllabary", "10800-1083F" ],
990             [ 108, "Kharoshthi", "10A00-10A5F" ],
991             [ 109, "Tai Xuan Jing Symbols", "1D300-1D35F" ],
992             [ 110, "Cuneiform", "12000-123FF" ],
993             [ 110, "Cuneiform Numbers and Punctuation", "12400-1247F" ],
994             [ 111, "Counting Rod Numerals", "1D360-1D37F" ],
995             [ 112, "Sundanese", "1B80-1BBF" ],
996             [ 113, "Lepcha", "1C00-1C4F" ],
997             [ 114, "Ol Chiki", "1C50-1C7F" ],
998             [ 115, "Saurashtra", "A880-A8DF" ],
999             [ 116, "Kayah Li", "A900-A92F" ],
1000             [ 117, "Rejang", "A930-A95F" ],
1001             [ 118, "Cham", "AA00-AA5F" ],
1002             [ 119, "Ancient Symbols", "10190-101CF" ],
1003             [ 120, "Phaistos Disc", "101D0-101FF" ],
1004             [ 121, "Carian", "102A0-102DF" ],
1005             [ 121, "Lycian", "10280-1029F" ],
1006             [ 121, "Lydian", "10920-1093F" ],
1007             [ 122, "Domino Tiles", "1F030-1F09F" ],
1008             [ 122, "Mahjong Tiles", "1F000-1F02F" ],
1009             [ 123-127, "Reserved", "" ],
1010             );
1011              
1012             }
1013              
1014              
1015             1;
1016              
1017             =head1 BUGS
1018              
1019             None known
1020              
1021             =head1 AUTHOR
1022              
1023             Martin Hosken L.
1024              
1025              
1026             =head1 LICENSING
1027              
1028             Copyright (c) 1998-2014, SIL International (http://www.sil.org)
1029              
1030             This module is released under the terms of the Artistic License 2.0.
1031             For details, see the full text of the license in the file LICENSE.
1032              
1033              
1034              
1035             =cut
1036