Re: problem with double width floating diacritic
Alfred Reibenschuh <[email protected]> Tue, 16 Oct 2007 22:11:26 +0200
| Newsgroups | gmane.comp.lang.perl.modules.pdfapi2 |
|---|---|
| Message-ID | <[email protected]> |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 kf_oxf wrote: > Hi, > > First of all, sorry if I'm doing something obviously wrong. I've only > just started working with PDF:API2 and am struggling to find much > documentation. not at all. > I have utf8 input that includes "U+0361 Combining Double Inverted > Breve" characters. This looks like a sort of arch that goes over the > top of two base characters. My problem is that although the resulting > PDF visually has this arch over the first base character, it also > visually has whitespace following, in the middle of the word. E.g. > for "Nezhinskaia" with the arch over the "ia" it looks like > "Nezhinskai a" with the arch over "i ". > > I have tried a couple of different fonts and the same happens. I'm > particularly wanting it to work with DejaVu Sans. > > Can anyone help? i've looked up the glyph tables of DejaVu Sans and according to them the diacritical marks are supposed to work. seams like some of the undef safeguards in pdfapi2 are the cause. could you try the cvs version of BaseFont.pm ? (attached) if the fix is ok for you i'll upload a new release. C fredo - -- Schonmal davon gehoert, dass nicht jeder linux user gleich ein programmierer ist, der alles, was er selber braucht, auch selber programmiert, installiert, patched, hacked oder portiert? Urks? Das ist doch nur eine Legende..... -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFHFRrujKJMaHhpyr4RCAJVAKC7XUsVIoo2FcmwjIxhyA6d48K7DQCdE1CV jlKr3FHldrkDi7QKXfAt4qU= =ED58 -----END PGP SIGNATURE-----
BaseFont.pm
(text/plain, 21.6 KB)
#======================================================================= # ____ ____ _____ _ ____ ___ ____ # | _ \| _ \| ___| _ _ / \ | _ \_ _| |___ \ # | |_) | | | | |_ (_) (_) / _ \ | |_) | | __) | # | __/| |_| | _| _ _ / ___ \| __/| | / __/ # |_| |____/|_| (_) (_) /_/ \_\_| |___| |_____| # # A Perl Module Chain to faciliate the Creation and Modification # of High-Quality "Portable Document Format (PDF)" Files. # # Copyright 1999-2005 Alfred Reibenschuh <[email protected]>. # #======================================================================= # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # # $Id: BaseFont.pm,v 2.9 2007/10/16 20:08:19 areibens Exp $ # #======================================================================= package PDF::API2::Resource::BaseFont; BEGIN { use utf8; use Encode qw(:all); use PDF::API2::Util; use PDF::API2::Basic::PDF::Utils; use PDF::API2::Resource; use Compress::Zlib; use vars qw(@ISA $VERSION); @ISA = qw( PDF::API2::Resource ); ( $VERSION ) = sprintf '%i.%03i', split(/\./,('$Revision: 2.9 $' =~ /Revision: (\S+)\s/)[0]); # $Date: 2007/10/16 20:08:19 $ } no warnings qw[ deprecated recursion uninitialized ]; =item $font = PDF::API2::Resource::BaseFont->new $pdf, $name Returns a font resource object. =cut sub new { my ($class,$pdf,$name) = @_; my $self; $class = ref $class if ref $class; $self=$class->SUPER::new($pdf,$name); $pdf->new_obj($self) unless($self->is_obj($pdf)); $self->{Type} = PDFName('Font'); $self->{' apipdf'}=$pdf; return($self); } =item $font = PDF::API2::Resource::BaseFont->new_api $api, $name Returns a font resource object. This method is different from 'new' that it needs an PDF::API2-object rather than a Text::PDF::File-object. =cut sub new_api { my ($class,$api,@opts)=@_; my $obj=$class->new($api->{pdf},@opts); $obj->{' api'}=$api; return($obj); } sub data { return( $_[0]->{' data'} ); } =item $descriptor = $font->descrByData() Returns the fonts FontDescriptor key-structure based on the fonts data. =cut sub descrByData { my $self=shift @_; my $des=PDFDict(); $self->{' apipdf'}->new_obj($des); ### $self->{'FontDescriptor'}=$des; $des->{'Type'}=PDFName('FontDescriptor'); $des->{'FontName'}=PDFName($self->fontname); my @w = map { PDFNum($_ || 0) } $self->fontbbox; $des->{'FontBBox'}=PDFArray(@w); # unless($self->issymbol) { $des->{'Ascent'}=PDFNum($self->ascender || 0); $des->{'Descent'}=PDFNum($self->descender || 0); $des->{'ItalicAngle'}=PDFNum($self->italicangle || 0.0); $des->{'XHeight'}=PDFNum($self->xheight || (($self->fontbbox)[3]*0.5) || 500); $des->{'CapHeight'}=PDFNum($self->capheight || ($self->fontbbox)[3] || 800); $des->{'StemV'}=PDFNum($self->stemv || 0); $des->{'StemH'}=PDFNum($self->stemh || 0); $des->{'AvgWidth'}=PDFNum($self->avgwidth || 300); $des->{'MissingWidth'}=PDFNum($self->missingwidth || 300); $des->{'MaxWidth'}=PDFNum($self->maxwidth || $self->missingwidth || ($self->fontbbox)[2]); $des->{'Flags'}=PDFNum($self->flags || 0) unless($self->data->{iscore}); if(defined $self->data->{panose}) { $des->{Style}=PDFDict(); $des->{Style}->{Panose}=PDFStrHex($self->data->{panose}); } $des->{FontFamily}=PDFStr($self->data->{fontfamily}) if(defined $self->data->{fontfamily}); $des->{FontWeight}=PDFNum($self->data->{fontweight}) if(defined $self->data->{fontweight}); $des->{FontStretch}=PDFName($self->data->{fontstretch}) if(defined $self->data->{fontstretch}); # } return($des); } sub tounicodemap { my $self=shift @_; return($self) if(defined $self->{ToUnicode}); my $cmap=qq|\%\% Custom\n\%\% CMap\n\%\%\n/CIDInit /ProcSet findresource begin\n|; $cmap.=qq|12 dict begin begincmap\n|; $cmap.=qq|/CIDSystemInfo <<\n|; $cmap.=sprintf(qq| /Registry (%s)\n|,$self->name); $cmap.=qq| /Ordering (XYZ)\n|; $cmap.=qq| /Supplement 0\n|; $cmap.=qq|>> def\n|; $cmap.=sprintf(qq|/CMapName /pdfapi2-%s+0 def\n|,$self->name); if(UNIVERSAL::can($self,'uniByCId') && UNIVERSAL::can($self,'glyphNum')) { # this is a type0 font $cmap.=sprintf(qq|1 begincodespacerange <0000> <%04X> endcodespacerange\n|,$self->glyphNum-1); for(my $j=0;$j<$self->glyphNum;$j++) { my $i = $self->glyphNum - $j > 100 ? 100 : $self->glyphNum - $j; if($j==0) { $cmap.=qq|$i beginbfrange\n|; } elsif($j%100 == 0) { $cmap.=qq|endbfrange\n|; $cmap.=qq|$i beginbfrange\n|; } $cmap.=sprintf(qq|<%04x> <%04x> <%04x>\n|,$j,$j,$self->uniByCId($j)); } $cmap.="endbfrange\n"; } else { # everything else is single byte font $cmap.=qq|1 begincodespacerange\n<00> <FF>\nendcodespacerange\n|; $cmap.=qq|256 beginbfchar\n|; for(my $j=0; $j<256;$j++) { $cmap.=sprintf(qq|<%02X> <%04X>\n|,$j,$self->uniByEnc($j)); } $cmap.=qq|endbfchar\n|; } $cmap.=qq|endcmap CMapName currendict /CMap defineresource pop end end\n|; my $tuni=PDFDict(); $tuni->{Type}=PDFName('CMap'); $tuni->{CMapName}=PDFName(sprintf(qq|pdfapi2-%s+0|,$self->name)); $tuni->{CIDSystemInfo}=PDFDict(); $tuni->{CIDSystemInfo}->{Registry}=PDFStr($self->name); $tuni->{CIDSystemInfo}->{Ordering}=PDFStr('XYZ'); $tuni->{CIDSystemInfo}->{Supplement}=PDFNum(0); $self->{' apipdf'}->new_obj($tuni); $tuni->{' nofilt'}=1; $tuni->{' stream'}=Compress::Zlib::compress($cmap); $tuni->{Filter}=PDFArray(PDFName('FlateDecode')); $self->{ToUnicode}=$tuni; return($self); } =back =head1 FONT-MANAGEMENT RELATED METHODS =over 4 =item $name = $font->fontname() Returns the fonts name (aka. display-name). =cut sub fontname { return( $_[0]->data->{fontname} ); } =item $name = $font->altname() Returns the fonts alternative-name (aka. windows-name for a postscript font). =cut sub altname { return( $_[0]->data->{altname} ); } =item $name = $font->subname() Returns the fonts subname (aka. font-variant, schriftschnitt). =cut sub subname { return( $_[0]->data->{subname} ); } =item $name = $font->apiname() Returns the fonts name to be used internally (should be equal to $font->name). =cut sub apiname { return( $_[0]->data->{apiname} ); } =item $issymbol = $font->issymbol() Returns the fonts symbol flag. =cut sub issymbol { return( $_[0]->data->{issymbol} ); } =item $iscff = $font->iscff() Returns the fonts compact-font-format flag. =cut sub iscff { return( $_[0]->data->{iscff} ); } =back =head1 TYPOGRAPHY RELATED METHODS =over 4 =item ($llx, $lly, $urx, $ury) = $font->fontbbox() Returns the fonts bounding-box. =cut sub fontbbox { return( @{$_[0]->data->{fontbbox}} ); } =item $capheight = $font->capheight() Returns the fonts capheight value. =cut sub capheight { return( $_[0]->data->{capheight} ); } =item $xheight = $font->xheight() Returns the fonts xheight value. =cut sub xheight { return( $_[0]->data->{xheight} ); } =item $missingwidth = $font->missingwidth() Returns the fonts missingwidth value. =cut sub missingwidth { return( $_[0]->data->{missingwidth} ); } =item $maxwidth = $font->maxwidth() Returns the fonts maxwidth value. =cut sub maxwidth { return( $_[0]->data->{maxwidth} ); } =item $avgwidth = $font->avgwidth() Returns the fonts avgwidth value. =cut sub avgwidth { my ($self) = @_; my $aw=$self->data->{avgwidth}; $aw||=(( $self->wxByGlyph('a')*64 + $self->wxByGlyph('b')*14 + $self->wxByGlyph('c')*27 + $self->wxByGlyph('d')*35 + $self->wxByGlyph('e')*100 + $self->wxByGlyph('f')*20 + $self->wxByGlyph('g')*14 + $self->wxByGlyph('h')*42 + $self->wxByGlyph('i')*63 + $self->wxByGlyph('j')* 3 + $self->wxByGlyph('k')* 6 + $self->wxByGlyph('l')*35 + $self->wxByGlyph('m')*20 + $self->wxByGlyph('n')*56 + $self->wxByGlyph('o')*56 + $self->wxByGlyph('p')*17 + $self->wxByGlyph('q')* 4 + $self->wxByGlyph('r')*49 + $self->wxByGlyph('s')*56 + $self->wxByGlyph('t')*71 + $self->wxByGlyph('u')*31 + $self->wxByGlyph('v')*10 + $self->wxByGlyph('w')*18 + $self->wxByGlyph('x')* 3 + $self->wxByGlyph('y')*18 + $self->wxByGlyph('z')* 2 + $self->wxByGlyph('A')*64 + $self->wxByGlyph('B')*14 + $self->wxByGlyph('C')*27 + $self->wxByGlyph('D')*35 + $self->wxByGlyph('E')*100 + $self->wxByGlyph('F')*20 + $self->wxByGlyph('G')*14 + $self->wxByGlyph('H')*42 + $self->wxByGlyph('I')*63 + $self->wxByGlyph('J')* 3 + $self->wxByGlyph('K')* 6 + $self->wxByGlyph('L')*35 + $self->wxByGlyph('M')*20 + $self->wxByGlyph('N')*56 + $self->wxByGlyph('O')*56 + $self->wxByGlyph('P')*17 + $self->wxByGlyph('Q')* 4 + $self->wxByGlyph('R')*49 + $self->wxByGlyph('S')*56 + $self->wxByGlyph('T')*71 + $self->wxByGlyph('U')*31 + $self->wxByGlyph('V')*10 + $self->wxByGlyph('W')*18 + $self->wxByGlyph('X')* 3 + $self->wxByGlyph('Y')*18 + $self->wxByGlyph('Z')* 2 + $self->wxByGlyph('space')*332 ) / 2000); return( int($aw) ); } =item $flags = $font->flags() Returns the fonts flags value. =cut sub flags { return( $_[0]->data->{flags} ); } =item $stemv = $font->stemv() Returns the fonts stemv value. =cut sub stemv { return( $_[0]->data->{stemv} ); } =item $stemh = $font->stemh() Returns the fonts stemh value. =cut sub stemh { return( $_[0]->data->{stemh} ); } =item $italicangle = $font->italicangle() Returns the fonts italicangle value. =cut sub italicangle { return( $_[0]->data->{italicangle} ); } =item $isfixedpitch = $font->isfixedpitch() Returns the fonts isfixedpitch flag. =cut sub isfixedpitch { return( $_[0]->data->{isfixedpitch} ); } =item $underlineposition = $font->underlineposition() Returns the fonts underlineposition value. =cut sub underlineposition { return( $_[0]->data->{underlineposition} ); } =item $underlinethickness = $font->underlinethickness() Returns the fonts underlinethickness value. =cut sub underlinethickness { return( $_[0]->data->{underlinethickness} ); } =item $ascender = $font->ascender() Returns the fonts ascender value. =cut sub ascender { return( $_[0]->data->{ascender} ); } =item $descender = $font->descender() Returns the fonts descender value. =cut sub descender { return( $_[0]->data->{descender} ); } =back =head1 GLYPH RELATED METHODS =over 4 =item @names = $font->glyphNames() Returns the defined glyph-names of the font. =cut sub glyphNames { return ( keys %{$_[0]->data->{wx}} ); } =item $glNum = $font->glyphNum() Returns the number of defined glyph-names of the font. =cut sub glyphNum { return ( scalar keys %{$_[0]->data->{wx}} ); } =item $uni = $font->uniByGlyph $char Returns the unicode by glyph-name. =cut sub uniByGlyph { return( $_[0]->data->{n2u}->{$_[1]} ); } =item $uni = $font->uniByEnc $char Returns the unicode by the fonts encoding map. =cut sub uniByEnc { return($_[0]->data->{e2u}->[$_[1]] ); } =item $uni = $font->uniByMap $char Returns the unicode by the fonts default map. =cut sub uniByMap { return($_[0]->data->{uni}->[$_[1]]); } =item $char = $font->encByGlyph $glyph Returns the character by the given glyph-name of the fonts encoding map. =cut sub encByGlyph { return( $_[0]->data->{n2e}->{$_[1]} || 0 ); } =item $char = $font->encByUni $uni Returns the character by the given unicode of the fonts encoding map. =cut sub encByUni { return( $_[0]->data->{u2e}->{$_[1]} || $_[0]->data->{u2c}->{$_[1]} || 0 ); } =item $char = $font->mapByGlyph $glyph Returns the character by the given glyph-name of the fonts default map. =cut sub mapByGlyph { return( $_[0]->data->{n2c}->{$_[1]} || 0 ); } =item $char = $font->mapByUni $uni Returns the character by the given unicode of the fonts default map. =cut sub mapByUni { return( $_[0]->data->{u2c}->{$_[1]} || 0 ); } =item $name = $font->glyphByUni $unicode Returns the glyphs name by the fonts unicode map. B<BEWARE:> non-standard glyph-names are mapped onto the ms-symbol area (0xF000). =cut sub glyphByUni { return ( $_[0]->data->{u2n}->{$_[1]} || '.notdef' ); } =item $name = $font->glyphByEnc $char Returns the glyphs name by the fonts encoding map. =cut sub glyphByEnc { my ($self,$e)=@_; my $g=$self->data->{e2n}->[$e]; return( $g ); } =item $name = $font->glyphByMap $char Returns the glyphs name by the fonts default map. =cut sub glyphByMap { return ( $_[0]->data->{char}->[$_[1]] ); } =item $width = $font->wxByGlyph $glyph Returns the glyphs width. =cut sub wxByGlyph { my $self=shift; my $val=shift; my $ret=undef; if(ref($self->data->{wx}) eq 'HASH') { $ret=$self->data->{wx}->{$val}; if(!defined($ret)) { $ret=$self->missingwidth; } if(!defined($ret)) { $ret=300; } } else { my $cid=$self->cidByUni(uniByName($val)); $ret=$self->data->{wx}->[$cid]; if(!defined($ret)) { $ret=$self->missingwidth; } if(!defined($ret)) { $ret=300; } } return $ret; } =item $width = $font->wxByUni $uni Returns the unicodes width. =cut sub wxByUni { my $self=shift; my $val=shift; my $gid=$self->glyphByUni($val); my $ret=$self->data->{wx}->{$gid}; if(!defined($ret)) { $ret=$self->missingwidth; } if(!defined($ret)) { $ret=300; } return $ret; } =item $width = $font->wxByEnc $char Returns the characters width based on the current encoding. =cut sub wxByEnc { my ($self,$e)=@_; my $g=$self->glyphByEnc($e); my $ret=$self->data->{wx}->{$g}; if(!defined($ret)) { $ret=$self->missingwidth; } if(!defined($ret)) { $ret=300; } return $ret; } =item $width = $font->wxByMap $char Returns the characters width based on the fonts default encoding. =cut sub wxByMap { my ($self,$m)=@_; my $g=$self->glyphByMap($m); my $ret=$self->data->{wx}->{$g}; if(!defined($ret)) { $ret=$self->missingwidth; } if(!defined($ret)) { $ret=300; } return $ret; } =item $wd = $font->width $text Returns the width of $text as if it were at size 1. B<BEWARE:> works only correctly if a proper perl-string is used either in native or utf8 format (check utf8-flag). =cut sub width { my ($self,$text)=@_; my $width=0; if(is_utf8($text)) { $text=$self->strByUtf($text) } my $lastglyph=''; foreach my $n (unpack('C*',$text)) { $width+=$self->wxByEnc($n); if($self->{-dokern} && ref($self->data->{kern})) { $width+=$self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]}; $lastglyph=$self->data->{e2n}->[$n]; } } $width/=1000; return($width); } =item @widths = $font->width_array $text Returns the widths of the words in $text as if they were at size 1. =cut sub width_array { my ($self,$text)=@_; if(!is_utf8($text)) { $text=$self->utfByStr($text); } my @text=split(/\s+/,$text); my @widths=map { $self->width($_) } @text; return(@widths); } =back =head1 STRING METHODS =over 4 =item $utf8string = $font->utfByStr $string Returns the utf8-string from string based on the fonts encoding map. =cut sub utfByStr { my ($self,$s)=@_; $s=pack('U*',map { $self->uniByEnc($_) } unpack('C*',$s)); utf8::upgrade($s); return($s); } =item $string = $font->strByUtf $utf8string Returns the encoded string from utf8-string based on the fonts encoding map. =cut sub strByUtf { my ($self,$s)=@_; $s=pack('C*',map { $self->encByUni($_) & 0xFF } unpack('U*',$s)); utf8::downgrade($s); return($s); } =item $pdfstring = $font->textByStr $text Returns a properly formatted representation of $text for use in the PDF. =cut sub textByStr { my ($self,$text)=@_; my $newtext=''; if(is_utf8($text)) { $text=$self->strByUtf($text); } $newtext=$text; $newtext=~s/\\/\\\\/go; $newtext=~s/([\x00-\x1f])/sprintf('\%03lo',ord($1))/ge; $newtext=~s/([\{\}\[\]\(\)])/\\$1/g; return($newtext); } sub textByStrKern { my ($self,$text)=@_; if($self->{-dokern} && ref($self->data->{kern})) { my $newtext=' '; if(is_utf8($text)) { $text=$self->strByUtf($text); } my $lastglyph=''; my $tBefore=0; foreach my $n (unpack('C*',$text)) { if(defined $self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]}) { $newtext.=') ' if($tBefore); $newtext.=sprintf('%i ',-($self->data->{kern}->{$lastglyph.':'.$self->data->{e2n}->[$n]})); $tBefore=0; } $lastglyph=$self->data->{e2n}->[$n]; my $t=pack('C',$n); $t=~s/\\/\\\\/go; $t=~s/([\x00-\x1f])/sprintf('\%03lo',ord($1))/ge; $t=~s/([\{\}\[\]\(\)])/\\$1/g; $newtext.='(' if(!$tBefore); $newtext.="$t"; $tBefore=1; } $newtext.=') ' if($tBefore); return($newtext); } else { return('('.$self->textByStr($text).')'); } } sub text { my ($self,$text,$size,$ident)=@_; my $newtext=$self->textByStr($text); if(defined $size && $self->{-dokern}) { $newtext=$self->textByStrKern($text); if(defined($ident) && $ident!=0) { return("[ $ident $newtext ] TJ"); } else { return("[ $newtext ] TJ"); } } elsif(defined $size) { if(defined($ident) && $ident!=0) { return("[ $ident ($newtext) ] TJ"); } else { return("[ ($newtext) ] TJ"); } } else { return("($newtext)"); } } sub isvirtual { return(0); } 1; __END__ =back =head1 AUTHOR alfred reibenschuh. =head1 HISTORY $Log: BaseFont.pm,v $ Revision 2.9 2007/10/16 20:08:19 areibens changed undef safeguards for wx* methods Revision 2.8 2007/10/10 06:18:15 areibens fixed noisy undef handling of isvirtual Revision 2.7 2007/04/07 10:25:46 areibens fixed fix for wxByGlyph not honoring cidfont width arrays Revision 2.6 2007/04/07 09:51:16 areibens fix for wxByGlyph not honoring cidfont width arrays Revision 2.5 2007/01/04 16:33:20 areibens fix acro 8 fix Revision 2.4 2007/01/04 16:02:28 areibens applied untested fix for acrobat 8 "<ident> TJ" bug Revision 2.3 2006/08/14 18:11:47 areibens fixed wxByGlyph Revision 2.2 2006/06/14 16:57:52 areibens fixed ToUnicode cmap greneration to use actual encoden rather than the default Revision 2.1 2006/06/14 16:53:00 areibens fixed unicode lookup to use actual encoding rather than default Revision 2.0 2005/11/16 02:16:04 areibens revision workaround for SF cvs import not to screw up CPAN Revision 1.2 2005/11/16 01:27:48 areibens genesis2 Revision 1.1 2005/11/16 01:19:25 areibens genesis Revision 1.18 2005/10/19 19:06:27 fredo added handling of kerning Revision 1.17 2005/06/17 19:44:03 fredo fixed CPAN modulefile versioning (again) Revision 1.16 2005/06/17 18:53:34 fredo fixed CPAN modulefile versioning (dislikes cvs) Revision 1.15 2005/03/14 22:01:06 fredo upd 2005 Revision 1.14 2005/01/21 10:03:09 fredo added object saver for cmap Revision 1.13 2004/12/16 00:30:53 fredo added no warn for recursion Revision 1.12 2004/11/24 20:10:55 fredo added virtual font handling Revision 1.11 2004/11/22 02:05:32 fredo added pdf-1.5 font param specs Revision 1.10 2004/10/26 14:41:37 fredo added panose identification style entry Revision 1.9 2004/10/17 03:55:00 fredo simplified ToUnicode associated CMap for single-byte fonts Revision 1.8 2004/10/17 03:47:36 fredo fixed inclusion of ToUnicode compatible key and associated CMap Revision 1.7 2004/06/15 09:14:41 fredo removed cr+lf Revision 1.6 2004/06/07 19:44:36 fredo cleaned out cr+lf for lf Revision 1.5 2004/04/20 09:47:34 fredo fixed unicode to font-encoding-vector conversion Revision 1.4 2003/12/08 13:05:32 Administrator corrected to proper licencing statement Revision 1.3 2003/11/30 17:28:54 Administrator merged into default Revision 1.2.2.1 2003/11/30 16:56:35 Administrator merged into default Revision 1.2 2003/11/30 11:44:49 Administrator added CVS id/log =cut