1 package Font::TTF::Name;
5 Font::TTF::Name - String table for a TTF font
9 Strings are held by number, platform, encoding and language. Strings are
12 $f->{'name'}{'strings'}[$number][$platform_id][$encoding_id]{$language_id}
14 Notice that the language is held in an associative array due to its sparse
15 nature on some platforms such as Microsoft ($pid = 3). Notice also that the
16 array order is different from the stored array order (platform, encoding,
17 language, number) to allow for easy manipulation of strings by number (which is
18 what I guess most people will want to do).
20 By default, C<$Font::TTF::Name::utf8> is set to 1, and strings will be stored as UTF8 wherever
21 possible. The method C<is_utf8> can be used to find out if a string in a particular
22 platform and encoding will be returned as UTF8. Unicode strings are always
23 converted if utf8 is requested. Otherwise, strings are stored according to platform:
25 You now have to set <$Font::TTF::Name::utf8> to 0 to get the old behaviour.
29 =item Apple Unicode (platform id = 0)
31 Data is stored as network ordered UCS2. There is no encoding id for this platform
32 but there are language ids as per Mac language ids.
34 =item Mac (platform id = 1)
36 Data is stored as 8-bit binary data, leaving the interpretation to the user
37 according to encoding id.
39 =item Unicode (platform id = 2)
41 Currently stored as 16-bit network ordered UCS2. Upon release of Perl 5.005 this
42 will change to utf8 assuming current UCS2 semantics for all encoding ids.
44 =item Windows (platform id = 3)
46 As per Unicode, the data is currently stored as 16-bit network ordered UCS2. Upon
47 release of Perl 5.005 this will change to utf8 assuming current UCS2 semantics for
52 =head1 INSTANCE VARIABLES
58 An array of arrays, etc.
67 use vars qw(@ISA $VERSION @apple_encs @apple_encodings $utf8 $cp_1252 @cp_1252 %win_langs %langs_win %langs_mac @ms_langids @mac_langs);
70 @ISA = qw(Font::TTF::Table);
76 eval {require Compress::Zlib;};
79 for ($i = 0; $i <= $#apple_encs; $i++)
81 $apple_encodings[0][$i] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $apple_encs[$i])))]
82 if (defined $apple_encs[$i]);
84 { $apple_encodings[0][$i][$_] = $_; }
86 $apple_encodings[1][$i] = {map {$_ => $count++} @{$apple_encodings[0][$i]}};
88 $cp_1252[0] = [unpack("n*", Compress::Zlib::uncompress(unpack("u", $cp_1252)))];
90 $cp_1252[1] = {map({$_ => $count++} @{$cp_1252[0]})};
92 for ($i = 0; $i < $#ms_langids; $i++)
94 if (defined $ms_langids[$i][1])
97 for ($j = 0; $j < $#{$ms_langids[$i][1]}; $j++)
99 my ($v) = $ms_langids[$i][1][$j];
101 { $win_langs{(($j + 1) << 10) + $i} = $ms_langids[$i][0] . $v; }
103 { $win_langs{(($j + 1) << 10) + $i} = $v; }
107 { $win_langs{$i + 0x400} = $ms_langids[$i][0]; }
109 %langs_win = map {my ($t) = $win_langs{$_}; my (@res) = ($t => $_); push (@res, $t => $_) if ($t =~ s/-.*$//o && ($_ & 0xFC00) == 0x400); @res} keys %win_langs;
111 %langs_mac = map {$_ => $i++} @mac_langs;
115 $VERSION = 1.1; # MJPH 17-JUN-2000 Add utf8 support
116 # $VERSION = 1.001; # MJPH 10-AUG-1998 Put $number first in list
120 Reads all the names into memory
127 my ($fh) = $self->{' INFILE'};
128 my ($dat, $num, $stroff, $i, $pid, $eid, $lid, $nid, $len, $off, $here);
130 $self->SUPER::read or return $self;
132 ($num, $stroff) = unpack("x2nn", $dat);
133 for ($i = 0; $i < $num; $i++)
135 use bytes; # hack to fix bugs in 5.8.7
137 ($pid, $eid, $lid, $nid, $len, $off) = unpack("n6", $dat);
139 $fh->seek($self->{' OFFSET'} + $stroff + $off, 0);
140 $fh->read($dat, $len);
143 if ($pid == 1 && defined $apple_encodings[0][$eid])
144 { $dat = TTF_word_utf8(pack("n*", map({$apple_encodings[0][$eid][$_]} unpack("C*", $dat)))); }
145 elsif ($pid == 2 && $eid == 2 && @cp_1252)
146 { $dat = TTF_word_utf8(pack("n*", map({$cp_1252[0][$_]} unpack("C*", $dat)))); }
147 elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1))
148 { $dat = TTF_word_utf8($dat); }
150 $self->{'strings'}[$nid][$pid][$eid]{$lid} = $dat;
159 Writes out all the strings
165 my ($self, $fh) = @_;
166 my ($pid, $eid, $lid, $nid, $todo, @todo);
167 my ($len, $offset, $loc, $stroff, $endloc, $str_trans);
169 return $self->SUPER::out($fh) unless $self->{' read'};
172 $fh->print(pack("n3", 0, 0, 0));
173 foreach $nid (0 .. $#{$self->{'strings'}})
175 foreach $pid (0 .. $#{$self->{'strings'}[$nid]})
177 foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]})
179 foreach $lid (sort keys %{$self->{'strings'}[$nid][$pid][$eid]})
181 $str_trans = $self->{'strings'}[$nid][$pid][$eid]{$lid};
184 if ($pid == 1 && defined $apple_encodings[1][$eid])
185 { $str_trans = pack("C*",
186 map({$apple_encodings[1][$eid]{$_} || 0x3F} unpack("n*",
187 TTF_utf8_word($str_trans)))); }
188 elsif ($pid == 2 && $eid == 2 && @cp_1252)
189 { $str_trans = pack("C*",
190 map({$cp_1252[1][$eid]{$_} || 0x3F} unpack("n*",
191 TTF_utf8_word($str_trans)))); }
192 elsif ($pid == 2 && $eid == 0)
193 { $str_trans =~ s/[\xc0-\xff][\x80-\xbf]+/?/og; }
194 elsif ($pid == 0 || $pid == 3 || ($pid == 2 && $eid == 1))
195 { $str_trans = TTF_utf8_word($str_trans); }
197 push (@todo, [$pid, $eid, $lid, $nid, $str_trans]);
204 @todo = (sort {$a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2]
205 || $a->[3] <=> $b->[3]} @todo);
206 foreach $todo (@todo)
208 $len = length($todo->[4]);
209 $fh->print(pack("n6", @{$todo}[0..3], $len, $offset));
213 $stroff = $fh->tell() - $loc;
214 foreach $todo (@todo)
215 { $fh->print($todo->[4]); }
217 $endloc = $fh->tell();
219 $fh->print(pack("n3", 0, $#todo + 1, $stroff));
220 $fh->seek($endloc, 0);
225 =head2 $t->XML_element($context, $depth, $key, $value)
227 Outputs the string element in nice XML (which is all the table really!)
234 my ($context, $depth, $key, $value) = @_;
235 my ($fh) = $context->{'fh'};
236 my ($nid, $pid, $eid, $lid);
238 return $self->SUPER::XML_element(@_) unless ($key eq 'strings');
240 foreach $nid (0 .. $#{$self->{'strings'}})
242 next unless ref($self->{'strings'}[$nid]);
243 # $fh->print("$depth<strings id='$nid'>\n");
244 foreach $pid (0 .. $#{$self->{'strings'}[$nid]})
246 foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]})
248 foreach $lid (sort {$a <=> $b} keys %{$self->{'strings'}[$nid][$pid][$eid]})
250 my ($lang) = $self->get_lang($pid, $lid) || $lid;
251 $fh->printf("%s<string id='%s' platform='%s' encoding='%s' language='%s'>\n%s%s%s\n%s</string>\n",
252 $depth, $nid, $pid, $eid, $lang, $depth,
253 $context->{'indent'}, $self->{'strings'}[$nid][$pid][$eid]{$lid}, $depth);
257 # $fh->print("$depth</strings>\n");
263 =head2 $t->XML_end($context, $tag, %attrs)
265 Store strings in the right place
272 my ($context, $tag, %attrs) = @_;
274 if ($tag eq 'string')
276 my ($lid) = $self->find_name($attrs{'platform'}, $attrs{'language'}) || $attrs{'language'};
277 $self->{'strings'}[$attrs{'id'}][$attrs{'platform'}][$attrs{'encoding'}]{$lid}
278 = $context->{'text'};
282 { return $self->SUPER::XML_end(@_); }
285 =head2 is_utf8($pid, $eid)
287 Returns whether a string of a given platform and encoding is going to be in UTF8
293 my ($self, $pid, $eid) = @_;
295 return ($utf8 && ($pid == 0 || $pid == 3 || ($pid == 2 && ($eid != 2 || @cp_1252))
296 || ($pid == 1 && defined $apple_encodings[$eid])));
300 =head2 find_name($nid)
302 Hunts down a name in all the standard places and returns the string and for an
303 array context the pid, eid & lid as well
309 my ($self, $nid) = @_;
310 my ($res, $pid, $eid, $lid, $look, $k);
312 my (@lookup) = ([3, 1, 1033], [3, 1, -1], [3, 0, 1033], [3, 0, -1], [2, 1, -1], [2, 2, -1], [2, 0, -1],
313 [0, 0, 0], [1, 0, 0]);
314 foreach $look (@lookup)
316 ($pid, $eid, $lid) = @$look;
319 foreach $k (keys %{$self->{'strings'}[$nid][$pid][$eid]})
321 if (($res = $self->{strings}[$nid][$pid][$eid]{$k}) ne '')
328 { $res = $self->{strings}[$nid][$pid][$eid]{$lid} }
330 { return wantarray ? ($res, $pid, $eid, $lid) : $res; }
336 =head2 set_name($nid, $str[, $lang[, @cover]])
338 Sets the given name id string to $str for all platforms and encodings that
339 this module can handle. If $lang is set, it is interpretted as a language
340 tag and if the particular language of a string is found to match, then
341 that string is changed, otherwise no change occurs.
343 If supplied, @cover should be a list of references to two-element arrays
344 containing pid,eid pairs that should added to the name table if not already present.
346 This function does not add any names to the table unless @cover is supplied.
352 my ($self, $nid, $str, $lang, @cover) = @_;
353 my ($pid, $eid, $lid, $c);
355 foreach $pid (0 .. $#{$self->{'strings'}[$nid]})
358 $strNL =~ s/\n/\r\n/og if $pid == 3;
359 $strNL =~ s/\n/\r/og if $pid == 1;
360 foreach $eid (0 .. $#{$self->{'strings'}[$nid][$pid]})
362 foreach $lid (keys %{$self->{'strings'}[$nid][$pid][$eid]})
364 next unless (!defined $lang || $self->match_lang($pid, $lid, $lang));
365 $self->{'strings'}[$nid][$pid][$eid]{$lid} = $strNL;
366 foreach $c (0 .. scalar @cover)
368 next unless ($cover[$c][0] == $pid && $cover[$c][1] == $eid);
377 my ($pid, $eid) = @{$c};
378 my ($lid) = $self->find_lang($pid, $lang);
380 $strNL =~ s/\n/\r\n/og if $pid == 3;
381 $strNL =~ s/\n/\r/og if $pid == 1;
382 $self->{'strings'}[$nid][$pid][$eid]{$lid} = $strNL;
387 =head2 Font::TTF::Name->match_lang($pid, $lid, $lang)
389 Compares the language associated to the string of given platform and language
390 with the given language tag. If the language matches the tag (i.e. is equal
391 or more defined than the given language tag) returns true. This is calculated
392 by finding whether the associated language tag starts with the given language
399 my ($self, $pid, $lid, $lang) = @_;
400 my ($langid) = $self->get_lang($pid, $lid);
402 return ($lid == $lang) if ($lang != 0 || $lang eq '0');
403 return !index(lc($langid), lc($lang));
406 =head2 Font::TTF::Name->get_lang($pid, $lid)
408 Returns the language tag associated with a particular platform and language id
414 my ($self, $pid, $lid) = @_;
417 { return $win_langs{$lid}; }
419 { return $mac_langs[$lid]; }
424 =head2 Font::TTF::Name->find_lang($pid, $lang)
426 Looks up the language name and returns a lang id if one exists
432 my ($self, $pid, $lang) = @_;
435 { return $langs_win{$lang}; }
437 { return $langs_mac{$lang}; }
445 M>)RES==NCW$`@.'G_S5Q*L(!#?+K1VO4:.W6IJA-:\^BM?>L>1&NP(A0Q$BL
446 M<*!62ZV8Z1)[K]BE$MR#O,=/7OW]7T&*6"NMI4K31EOMM)>N@XXZZ2Q#IBZZ
447 MZJ:['GKJ)4NVWOKHJ]\_/\!`@PR68XBAALDUW`@CC3+:&&.-,UZ>?!-,-,ED
448 M4TPUS70SS#3+;`7FF&N>0D7F6V"A119;8JEEEEMAI5566V.M==;;H-A&FVRV
449 MQ5;;_OTONJ3<%;?<5^NQ1YYXYJGG7GKME3?>>N^=#S[ZY(O/OOKNFU]^JO<[
450 M!$?LLMO>$#OAH4-*4F+'[(L+E*F,6SH:%\9%]C@>1W&CN&%2:9QNO]-))5ZH
451 M<]9.!^/DQ/8X-V[@@#,AS0ZE+KB7R$ODA\:A26@>6H2FH9D?J17^)(I#3C@8
452 MLD)V?:(^"BE.AN30,F0XK\(Y5UUVW0TW77/'W;H_;JM6HRJ1&95%M0Y'E5%5
453 .5.U4]""JB<K_`B>`?E$`
460 M>)RES[=/%```1O$WO8G_@$'J';W70Z2WHS>5WJN%8D6%D;BZ,3*P,;#C2D(8
461 M,9&)08V)+4*(1((X2'(#[.:;7[[\*./_%D,L<<230"(!@B213`JII)%.!IED
462 MD4T.N>213P&%%%%,B!)N4LJMR[Z<"BJIHIH::JFCG@;"--)$,RVTTD8['732
463 M13>WN<-=>NBECWX&&&2(848898QQ)IADBFEFF.4>]WG`0^:89X%%'O&8)SSE
464 M&<]9X@4O><4R*Y?_.ZRSRQ[[''#(1S[PB<]NL\D7OO&5[_S@9TR`(XXYX1=O
465 M.>4W9_SAG`O^7OF=O>XW*N)WV!%''7/<"2>=<MH90D9'_-X(AHTUSG@33#1@
466 MT"2333'5--/-,-,LL\TQUSSS+;#0(HL-7?DMM\)*JZRVQEKKK+?!L(TVV6R+
467 9K;;9;H<K+KGJ>S?<\K5O(G[7?/</+>Y>'```
471 M>)RED$LSEW$`A9_-^00L,H-^(=>4Y%^2J'1Q*Y+[I2(BHA`B?!%J6EM1*28S
472 M;9II[/PI*7*_%TUN\_*VZ%W:FN9LSYEGGD,\_Q?#$?SP)X"C!!)$,"&$$L8Q
473 MPCG."2(X222GB,+%:<X0S5EB.$<LYXES]A>XR"42N,P5KG*-1))()H54KG.#
474 M--*Y20:WR"2+;'+()8]\"BBDB-O<X2[%E'"/4LJX3SD5/*"2*AY230V/>$PM
475 M==3SA`8::>(IS;3PC%;::'?X'^W#?&(0-Z-,,,,TL\PSQP)+K+#,*C]9XQ?K
476 M_.8/FVRPQ0[;[+&+S=_]_J;KX/Y6I?&U.JQ.Z[GU0@-VBNTR@;Q4G]ZI5V_U
477 MQG@83^-M?,PAXV6'VF'ZH&Z]4H_>J]]IO=:0W!K6B#[KBT;U56/ZIN\:UX1^
478 ?:%)3FM:,9C6G>2UH44M:UHI6'?<BYX,"6O\!%-%\5```
482 M>)RES5=OSG$`0.$CYR.(A(3DUS]J4WOO59O6;&F+UMY[7R&(V'N^4ETZ=*"J
483 M:M:H=>E*0D1B)7HC1KC0[R#G^LEA,/]7((Z(EK2B-?&TH2WM:$\'.M*)SG0A
484 M@:YTHSL]Z$DO>M.'OO2C/P,8R*`&/X2A#&,X(QC)*$:3R!C&,H[Q3&`BDYC,
485 M%))(9BK3F,X,9C*+%%*9S1S22">#N<QC/IEDL8"%+&(Q2UC*,I:S@I6L8C5K
486 M6,LZUK.!C6QB,UO8RC:VLZ/A7TL5Y=11P6O>N(MWO.>#.\GG(Y_YQ!>^DAT7
487 M\8WZ$%$3$OC.#W(IYC=_^!N"1SWF*<]ZP1AO*:'`;*^0%V502J6'*8LRHRQR
488 M/.)Q3WC2TY[QG+D6FF^!19ZGR(M>BA*]3"'5(9Z8.>:YVSV-DD/CT"0T#RU"
489 MT]",G^YUG_L]8+$E7O6%!WUIF>4^]9K7?6R%E59YQUM6>]L:[WK/5][WH;7>
490 4M,X'/O&1-WSF<P]9^BOV#YW%>_\`
494 M>)RERT=.%5``0-&+7K'&!B(@X/L/^/3>ZZ?SZ=*K@`KVWOL:U!68.#!&8G2@
495 M$Q?F5/=@SOB0XO\$$D2**:&4)&644T$E55130RUUU--`(TTTTT(K;;3302==
496 M=--#[[_?1S\###+$,".,DF:,<2:89(II9KC`+'/,L\`B2RRSPBIKK+/!13;9
497 M8IM+7.8*.^QRE6M<YP8WN<5M[G"7>]SG`0]YQ&.>\)1G/.<%+WG%:][PEI0G
498 M/>5IL\SVC#F>-=<\\SUG@846>=Y@PFBQ)9::M,QR*ZRTRFIKK+4N!+[[CD]\
499 M#I%?9O*-+XGH/N?BMON=CT7\B#MQUR5^^MY#ZH('7?:PJQYQS14/L!?S,S[$
500 M=,SD*[]#DH\>==UC;K@8LD)V*`B%(3?D\2<4>=Q-3[B5R#'#66>LM\%&FVRV
501 GQ5;;;+?#3KOLML=>4_;9[X"##CGLB*.F'7/<"2>=<CKL_06V`DD#
506 M>)RED-DVUG$`1;=:U*Y%0C)5O^^/SSS/F>>9#"$JE7D>"D6\3S=>Q^MPU^JF
507 M&^M<G[7//G1ROP1B1.130"%QBBBFA%+***>"2JJHIH9:ZJBG@4:::*:%M[32
508 M1CL==_TNNNFAES[Z&6"0(889890QQIE@DG=,,<T,L[QGCGD6^,`B2WSD$Y]9
509 MY@M?^<8*JZRQS@:;;+'-#KOLL<\!AQQQS'=^<,(I9_SD%^=<\)M+KN[X-U%:
510 M2`\9(2MDAWB(^,-U+/KKYYJ'_W_`!!_XT$23?.1C]8E/3?&9J2:;9KH9/O>%
511 MF;XTRVQSS#7/5[[VC<&8D?D66&C<(HLML=0RRZVPTBJ7K;;&6NNLM\%&FVRV
512 L):388:===MMCKP,..F2_(XXZYK#CMKGZS[YU-]QTRVUWW'7/?0]N`4(?0WT`
516 M>)RED,5.0U$415=(D.X!$"ANMX^VN+M#D>+N[H4"Q5W^APF_PZ\PY.9-"`-&
517 MY.3LG>-"#_\3@P^'8OP$"%)"*6644T$E55130RUUU--`(TTTTT(K;;3302==
518 M=-OZ7OH(T<\`@PP19I@11AECG`DFF6*:&6:98YX%%EEBF15666.=#3;98IL=
519 M=MECGP,.B7#$,5%...6,&.=<<,D5U]QPRQWW//#($\^\\,J;G?_II)ETXS79
520 M)L<$C<,['S[GYSY=?FWK6E>Z^?L'BK,:KP0E*DD>R?6E*-7E='DM9BA36<I6
521 MCG*5IWP5J%!%,O+)4;'\"BBH$I7:S')5J%)5JE:-M6JMUKM]FM1LL55M)EG=
522 GZE&O^A1R(V$-NSRF<8L3ZO3L_]KN4!$=Z5A1G>A49XKI_!M<9D8J
526 M>)RED,E3SW$8QU_77@<''+A]^Y5(2-F7+"%92\B^ES5ES]H,)L(8&21E*UNH
527 M&"8T8ZS3I(FS_T"$_`L^-^/D8)YY/^]Y/\L\"Y/Y/XN()T8"B0P@B8$,(IG!
528 MI#"$H0PCE>&DD<X(1C**T8QA+.,8SP0FDL&DT#^%J60RC>G,((N99#.+V<QA
529 M+O.83PZY+""/A2QB,?DL82G+6,X*5K**U:QA+>M8SP8**&0CF]C,%K:RC2*V
530 M4TP).]C)+G:SA[WLHY3]'.`@ASC,$<K"_,^QWE&?J&_4+^H?)44Q[M,<'_MS
531 M7USAOS[@48]YW')/>-(*3WG:,R%ZSDK/!K[@1<][R2HO6^T5:ZSUJM>\[@UO
532 M6F>]M[SM'>]ZSX90_\"'-MIDLX^">ASPQ*?!M_C,Y[ZP->KE*U_[QK>^\WW(
533 CM/O!ML"=?K3#3[Z,*_AKOR]V^=5O=OO='_ZTQU^_`2-%:*``
546 M>)REC]=.E&$`1(\%&W@4004%_7:!I?>.Z-+[TJL*=K"`BH`*J,_"+2'A!7PW
547 MX;\2[LG<3#*9G!F2G$V!&'$***2(!,644$H9Y5102175U%!+'?4TT$@3S;30
548 M2AN/:.<Q3Z)^!YUTT4T/O?31SP"###',""E&&6.<"2:98IH99IECG@6>\HSG
549 M+++$"U[RBM>\X2WO6&:%]WS@(Y]898W/?.$KZWQC@TVV^,X/?K+-#KO\XC=_
550 M(OX!?T/"`0<=<MB1$Q?R0KXIDB%NK?TVV&B3S:?RG)`;]?<\YWDO>-$T+WG9
551 M*U[UFNEF>%V]X4TSO666V=[VCG?-,==[WC?/?!_XT&#,N`466F3"8DLLM<QR
552 M*ZRTRFIK(GJ=]?_Y+;;:]N\HI(>LD&W2#COMLML>>^V+=IX\2<7BCCGNA)-.
553 0.>V,L\XY[P*'[!\#D^='L@``
569 M>)P-SD-B'5```,#YJ6VE>DEM&[\VD]JVF?H./4'-U+93V[9M:SV;$141(Y74
570 MTD@KG?0RR"B3S++(*IOL<L@IE]SRR"N?_`J(55`AA1515!`G7C'%E5!2*:65
571 M458YY550426555%5-=754%,MM=515SWU-=!05".--=%4,\VUT%(KK;715COM
572 M==!1)YTE2-1%5]UTUT-/O?361U_]]#?`0(,,-L10PPPWPDBCC#;&6..,-\%$
573 MDTPVQ5333)=DAIEFF6V.N>:%9-$0&YD?BH22(82XF)10.3(@U(DDB$;F_/]%
574 M0_Y0(!0*A4-\R!5RQ]R*BX\,#'4CB?]];B3)`@LMLM@22RVSW`HKK;):LC76
575 M6F>]#3;:9+,MMMIFNQUVVF6W/?;:9[\##CKDL"-2''7,<2><=,II9YQUSGD7
576 M7'3)95=<=<UU-]QTRVUWW'7/?0\\],AC3SSUS',OO/3*:V^\]<Y['WSTR6=?
577 1?/7-=S_\],MO?_S]!Y==>0@`
582 @ms_langids = ( [""],
583 ['ar', ["-SA", "-IQ", "-EG", "-LY", "-DZ", "-MA", "-TN",
584 "-OM", "-YE", "-SY", "-JO", "-LB", "-KW", "-AE",
588 ['zh', ['-TW', 'CN', '-HK', '-SG', '-MO']],
591 ["de", ["-DE", "-CH", "-AT", "-LU", "-LI"]],
593 ["en", ["-US", "-UK", "-AU", "-CA", "-NZ", "-IE", "-ZA",
594 "-JM", "029", "-BZ", "-TT", "-ZW", "-PH", "-ID",
595 "-HK", "-IN", "-MY", "-SG"]],
596 ["es", ["-ES", "-MX", "-ES", "-GT", "-CR", "-PA", "-DO",
597 "-VE", "-CO", "-PE", "-AR", "-EC", "-CL", "-UY",
598 "-PY", "-BO", "-SV", "-HN", "-NI", "-PR", "-US"]],
600 ["fr", ["-FR", "-BE", "-CA", "-CH", "-LU", "-MC", "",
601 "-RE", "-CG", "-SN", "-CM", "-CI", "-ML", "-MA",
607 ["it", ["-IT", "-CH"]],
610 ["nl", ["-NL", "-BE"]],
611 ["no", ["-bok-NO", "-nyn-NO"]],
613 ["pt", ["-BR", "-PT"]],
615 ["ro", ["-RO", "_MD"]],
617 ["hr", ["-HR", "-Latn-CS", "Cyrl-CS", "-BA", "", "-Latn-BA", "-Cyrl-BA"]],
620 ["sv", ["-SE", "-FI"]],
624 ["ur", ["-PK", "tr-IN"]],
636 ["az", ["-Latn-AZ", "-Cyrl-AZ"]],
638 ["wen". ["wen-DE", "dsb-DE"]],
652 ["se", ["-NO", "-SE", "-FI", "smj-NO", "smj-SE", "sma-NO", "sma-SE",
656 ["ms", ["-MY", "-BN"]],
662 ["uz", ["-Latn-UZ", "-Cyrl-UZ"]],
664 ["bn", ["-IN", "-BD"]],
665 ["pa", ["-IN", "-Arab-PK"]],
676 ["mn", ["-Cyrl-MN", "-Mong-CN"]],
677 ["bo", ["-CN", "-BT"]],
685 ["sd", ["-IN", "-PK"]],
689 ["iu", ["-Cans-CA", "-Latn-CA"]],
691 ["tmz", ["-Arab", "tmz-Latn-DZ"]],
694 ["ne", ["-NP", "-IN"]],
704 ["quz", ["-BO", "-EC", "-PE"]],
713 ["ti", ["-ET". "-ER"]],
743 'en', 'fr', 'de', 'it', 'nl', 'sv', 'es', 'da', 'pt', 'no',
744 'he', 'ja', 'ar', 'fi', 'el', 'is', 'mt', 'tr', 'hr', 'zh-Hant',
745 'ur', 'hi', 'th', 'ko', 'lt', 'pl', 'hu', 'et', 'lv', 'se',
746 'fo', 'ru' ,'zh-Hans', 'nl', 'ga', 'sq', 'ro', 'cs', 'sk',
747 'sl', 'yi', 'sr', 'mk', 'bg', 'uk', 'be', 'uz', 'kk', 'az-Cyrl',
748 'az-Latn', 'hy', 'ka', 'mo', 'ky', 'abh', 'tuk', 'mn-Mong', 'mn-Cyrl', 'pst',
749 'ku', 'ks', 'sd', 'bo', 'ne', 'sa', 'mr', 'bn', 'as', 'gu',
750 'pa', 'or', 'ml', 'kn', 'ta', 'te', 'si', 'my', 'km', 'lo',
751 'vi', 'id', 'tl', 'ms-Latn', 'ms-Arab', 'am', 'ti', 'tga', 'so', 'sw',
752 'rw', 'rn', 'ny', 'mg', 'eo', '', '', '', '', '',
753 '', '', '', '', '', '', '', '', '', '',
754 '', '', '', '', '', '', '', '', '', '',
755 '', '', '', '', '', '', '', '', 'cy', 'eu',
756 'la', 'qu', 'gn', 'ay', 'tt', 'ug', 'dz', 'jv-Latn', 'su-Latn',
757 'gl', 'af', 'br', 'iu', 'gd', 'gv', 'gd-IR-x-dotabove', 'to', 'el-polyton', 'kl',
771 Unicode type strings will be stored in utf8 for all known platforms,
772 once Perl 5.6 has been released and I can find all the mapping tables, etc.
778 Martin Hosken Martin_Hosken@sil.org. See L<Font::TTF::Font> for copyright and