| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package PDF::Builder::Resource::BaseFont; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 9 |  |  | 9 |  | 1755 | use base 'PDF::Builder::Resource'; | 
|  | 9 |  |  |  |  | 16 |  | 
|  | 9 |  |  |  |  | 919 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 9 |  |  | 9 |  | 56 | use strict; | 
|  | 9 |  |  |  |  | 15 |  | 
|  | 9 |  |  |  |  | 187 |  | 
| 6 | 9 |  |  | 9 |  | 38 | use warnings; | 
|  | 9 |  |  |  |  | 17 |  | 
|  | 9 |  |  |  |  | 479 |  | 
| 7 |  |  |  |  |  |  |  | 
| 8 |  |  |  |  |  |  | our $VERSION = '3.024'; # VERSION | 
| 9 |  |  |  |  |  |  | our $LAST_UPDATE = '3.024'; # manually update whenever code is changed | 
| 10 |  |  |  |  |  |  |  | 
| 11 | 9 |  |  | 9 |  | 50 | use Compress::Zlib; | 
|  | 9 |  |  |  |  | 25 |  | 
|  | 9 |  |  |  |  | 2801 |  | 
| 12 |  |  |  |  |  |  | #use Encode qw(:all); | 
| 13 | 9 |  |  | 9 |  | 81 | use PDF::Builder::Basic::PDF::Utils; | 
|  | 9 |  |  |  |  | 17 |  | 
|  | 9 |  |  |  |  | 698 |  | 
| 14 | 9 |  |  | 9 |  | 64 | use PDF::Builder::Util; | 
|  | 9 |  |  |  |  | 16 |  | 
|  | 9 |  |  |  |  | 1212 |  | 
| 15 | 9 |  |  | 9 |  | 59 | use Scalar::Util qw(weaken); | 
|  | 9 |  |  |  |  | 24 |  | 
|  | 9 |  |  |  |  | 32289 |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | =head1 NAME | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | PDF::Builder::Resource::BaseFont - Base class for font resources | 
| 20 |  |  |  |  |  |  |  | 
| 21 |  |  |  |  |  |  | =head1 METHODS | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  | =over | 
| 24 |  |  |  |  |  |  |  | 
| 25 |  |  |  |  |  |  | =item $font = PDF::Builder::Resource::BaseFont->new($pdf, $name) | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | Return a font resource object. | 
| 28 |  |  |  |  |  |  |  | 
| 29 |  |  |  |  |  |  | =cut | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | sub new { | 
| 32 | 53 |  |  | 53 | 1 | 160 | my ($class, $pdf, $name) = @_; | 
| 33 |  |  |  |  |  |  |  | 
| 34 | 53 |  |  |  |  | 98 | my $self; | 
| 35 |  |  |  |  |  |  |  | 
| 36 | 53 | 50 |  |  |  | 138 | $class = ref($class) if ref($class); | 
| 37 | 53 |  |  |  |  | 251 | $self = $class->SUPER::new($pdf, $name); | 
| 38 |  |  |  |  |  |  |  | 
| 39 | 53 | 50 |  |  |  | 149 | $pdf->new_obj($self) unless $self->is_obj($pdf); | 
| 40 |  |  |  |  |  |  |  | 
| 41 | 53 |  |  |  |  | 148 | $self->{'Type'} = PDFName('Font'); | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 53 |  |  |  |  | 111 | $self->{' apipdf'} = $pdf; | 
| 44 | 53 |  |  |  |  | 141 | weaken $self->{' apipdf'}; | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 53 |  |  |  |  | 119 | return $self; | 
| 47 |  |  |  |  |  |  | } | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | sub data { | 
| 50 | 40369 |  |  | 40369 | 0 | 73133 | return $_[0]->{' data'}; | 
| 51 |  |  |  |  |  |  | } | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | =item $descriptor = $font->descrByData() | 
| 54 |  |  |  |  |  |  |  | 
| 55 |  |  |  |  |  |  | Return the font's FontDescriptor key structure based on the font's data. | 
| 56 |  |  |  |  |  |  |  | 
| 57 |  |  |  |  |  |  | =cut | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | sub descrByData { | 
| 60 | 16 |  |  | 16 | 1 | 27 | my $self = shift(); | 
| 61 |  |  |  |  |  |  |  | 
| 62 | 16 |  |  |  |  | 33 | my $descriptor = PDFDict(); | 
| 63 | 16 |  |  |  |  | 52 | $self->{' apipdf'}->new_obj($descriptor); | 
| 64 |  |  |  |  |  |  |  | 
| 65 | 16 |  |  |  |  | 37 | $descriptor->{'Type'}         = PDFName('FontDescriptor'); | 
| 66 | 16 |  |  |  |  | 46 | $descriptor->{'FontName'}     = PDFName($self->fontname()); | 
| 67 |  |  |  |  |  |  |  | 
| 68 | 16 |  | 100 |  |  | 53 | my @box = map { PDFNum($_ || 0) } $self->fontbbox(); | 
|  | 64 |  |  |  |  | 139 |  | 
| 69 | 16 |  |  |  |  | 47 | $descriptor->{'FontBBox'}     = PDFArray(@box); | 
| 70 |  |  |  |  |  |  |  | 
| 71 | 16 |  | 50 |  |  | 48 | $descriptor->{'Ascent'}       = PDFNum($self->ascender()     || 0); | 
| 72 | 16 |  | 50 |  |  | 51 | $descriptor->{'Descent'}      = PDFNum($self->descender()    || 0); | 
| 73 | 16 |  | 100 |  |  | 42 | $descriptor->{'ItalicAngle'}  = PDFNum($self->italicangle()  || 0.0); | 
| 74 | 16 |  | 50 |  |  | 47 | $descriptor->{'XHeight'}      = PDFNum($self->xheight()      || (($self->fontbbox())[3]*0.5) || 500); | 
| 75 | 16 |  | 50 |  |  | 57 | $descriptor->{'CapHeight'}    = PDFNum($self->capheight()    || ($self->fontbbox())[3] || 800); | 
| 76 | 16 |  | 50 |  |  | 45 | $descriptor->{'StemV'}        = PDFNum($self->stemv()        || 0); | 
| 77 | 16 |  | 50 |  |  | 43 | $descriptor->{'StemH'}        = PDFNum($self->stemh()        || 0); | 
| 78 | 16 |  | 50 |  |  | 47 | $descriptor->{'AvgWidth'}     = PDFNum($self->avgwidth()     || 300); | 
| 79 | 16 |  | 100 |  |  | 40 | $descriptor->{'MissingWidth'} = PDFNum($self->missingwidth() || 300); | 
| 80 | 16 |  | 66 |  |  | 40 | $descriptor->{'MaxWidth'}     = PDFNum($self->maxwidth()     || $self->missingwidth() || ($self->fontbbox())[2]); | 
| 81 | 16 | 50 | 50 |  |  | 34 | $descriptor->{'Flags'}        = PDFNum($self->flags()        || 0) unless $self->data()->{'iscore'}; | 
| 82 | 16 | 100 |  |  |  | 37 | if (defined $self->data()->{'panose'}) { | 
| 83 | 1 |  |  |  |  | 4 | $descriptor->{'Style'}             = PDFDict(); | 
| 84 | 1 |  |  |  |  | 4 | $descriptor->{'Style'}->{'Panose'} = PDFStrHex($self->data()->{'panose'}); | 
| 85 |  |  |  |  |  |  | } | 
| 86 |  |  |  |  |  |  | $descriptor->{'FontFamily'}   = PDFString($self->data()->{'fontfamily'}, 'x') | 
| 87 | 16 | 100 |  |  |  | 30 | if defined $self->data()->{'fontfamily'}; | 
| 88 |  |  |  |  |  |  | $descriptor->{'FontWeight'}   = PDFNum($self->data()->{'fontweight'}) | 
| 89 | 16 | 100 |  |  |  | 31 | if defined $self->data()->{'fontweight'}; | 
| 90 |  |  |  |  |  |  | $descriptor->{'FontStretch'}  = PDFName($self->data()->{'fontstretch'}) | 
| 91 | 16 | 100 |  |  |  | 27 | if defined $self->data()->{'fontstretch'}; | 
| 92 |  |  |  |  |  |  |  | 
| 93 | 16 |  |  |  |  | 48 | return $descriptor; | 
| 94 |  |  |  |  |  |  | } | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  | sub tounicodemap { | 
| 97 | 1 |  |  | 1 | 0 | 28 | my $self = shift(); | 
| 98 |  |  |  |  |  |  |  | 
| 99 | 1 | 50 |  |  |  | 6 | return $self if defined $self->{'ToUnicode'}; | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 1 |  |  |  |  | 3 | my $stream = qq|\%\% Custom\n\%\% CMap\n\%\%\n/CIDInit /ProcSet findresource begin\n|; | 
| 102 | 1 |  |  |  |  | 4 | $stream .= qq|12 dict begin begincmap\n|; | 
| 103 | 1 |  |  |  |  | 3 | $stream .= qq|/CIDSystemInfo <<\n|; | 
| 104 | 1 |  |  |  |  | 8 | $stream .= sprintf(qq|   /Registry (%s)\n|, $self->name()); | 
| 105 | 1 |  |  |  |  | 3 | $stream .= qq|   /Ordering (XYZ)\n|; | 
| 106 | 1 |  |  |  |  | 3 | $stream .= qq|   /Supplement 0\n|; | 
| 107 | 1 |  |  |  |  | 3 | $stream .= qq|>> def\n|; | 
| 108 | 1 |  |  |  |  | 4 | $stream .= sprintf(qq|/CMapName /pdfbldr-%s+0 def\n|, $self->name()); | 
| 109 | 1 | 50 | 33 |  |  | 19 | if ($self->can('uniByCId') and $self->can('glyphNum')) { | 
| 110 |  |  |  |  |  |  | # this is a type0 font | 
| 111 | 0 |  |  |  |  | 0 | $stream .= sprintf(qq|1 begincodespacerange <0000> <%04X> endcodespacerange\n|, $self->glyphNum() - 1); | 
| 112 | 0 |  |  |  |  | 0 | for (my $j = 0; $j < $self->glyphNum(); $j++) { | 
| 113 | 0 | 0 |  |  |  | 0 | my $i = $self->glyphNum() - $j > 100 ? 100 : $self->glyphNum() - $j; | 
| 114 | 0 | 0 |  |  |  | 0 | if      ($j == 0) { | 
|  |  | 0 |  |  |  |  |  | 
| 115 | 0 |  |  |  |  | 0 | $stream .= qq|$i beginbfrange\n|; | 
| 116 |  |  |  |  |  |  | } elsif ($j % 100 == 0) { | 
| 117 | 0 |  |  |  |  | 0 | $stream .= qq|endbfrange\n|; | 
| 118 | 0 |  |  |  |  | 0 | $stream .= qq|$i beginbfrange\n|; | 
| 119 |  |  |  |  |  |  | } | 
| 120 |  |  |  |  |  |  | # Default to 0000 if uniByCId returns undef in order to match | 
| 121 |  |  |  |  |  |  | # previous behavior minus an uninitialized value warning.  It's | 
| 122 |  |  |  |  |  |  | # worth looking into what should be happening here, since this may | 
| 123 |  |  |  |  |  |  | # not be the correct behavior. | 
| 124 | 0 |  | 0 |  |  | 0 | $stream .= sprintf(qq|<%04x> <%04x> <%04x>\n|, $j, $j, ($self->uniByCId($j) // 0)); | 
| 125 |  |  |  |  |  |  | } | 
| 126 | 0 |  |  |  |  | 0 | $stream .= "endbfrange\n"; | 
| 127 |  |  |  |  |  |  | } else { | 
| 128 |  |  |  |  |  |  | # everything else is single byte font | 
| 129 | 1 |  |  |  |  | 4 | $stream .= qq|1 begincodespacerange\n<00> \nendcodespacerange\n|; | 
| 130 | 1 |  |  |  |  | 3 | $stream .= qq|256 beginbfchar\n|; | 
| 131 | 1 |  |  |  |  | 7 | for (my $j=0; $j < 256; $j++) { | 
| 132 | 256 |  |  |  |  | 341 | $stream .= sprintf(qq|<%02X> <%04X>\n|, $j, $self->uniByEnc($j)); | 
| 133 |  |  |  |  |  |  | } | 
| 134 | 1 |  |  |  |  | 4 | $stream .= qq|endbfchar\n|; | 
| 135 |  |  |  |  |  |  | } | 
| 136 | 1 |  |  |  |  | 5 | $stream .= qq|endcmap CMapName currendict /CMap defineresource pop end end\n|; | 
| 137 |  |  |  |  |  |  |  | 
| 138 | 1 |  |  |  |  | 6 | my $cmap = PDFDict(); | 
| 139 | 1 |  |  |  |  | 13 | $cmap->{'Type'}                          = PDFName('CMap'); | 
| 140 | 1 |  |  |  |  | 5 | $cmap->{'CMapName'}                      = PDFName(sprintf(qq|pdfbldr-%s+0|, $self->name())); | 
| 141 | 1 |  |  |  |  | 3 | $cmap->{'CIDSystemInfo'}                 = PDFDict(); | 
| 142 | 1 |  |  |  |  | 3 | $cmap->{'CIDSystemInfo'}->{'Registry'}   = PDFString($self->name(), 'x'); | 
| 143 | 1 |  |  |  |  | 4 | $cmap->{'CIDSystemInfo'}->{'Ordering'}   = PDFString('XYZ', 'x'); | 
| 144 | 1 |  |  |  |  | 4 | $cmap->{'CIDSystemInfo'}->{'Supplement'} = PDFNum(0); | 
| 145 |  |  |  |  |  |  |  | 
| 146 | 1 |  |  |  |  | 8 | $self->{' apipdf'}->new_obj($cmap); | 
| 147 | 1 |  |  |  |  | 3 | $cmap->{' nofilt'}                       = 1; | 
| 148 | 1 |  |  |  |  | 10 | $cmap->{' stream'}                       = Compress::Zlib::compress($stream); | 
| 149 | 1 |  |  |  |  | 698 | $cmap->{'Filter'}                        = PDFArray(PDFName('FlateDecode')); | 
| 150 | 1 |  |  |  |  | 2 | $self->{'ToUnicode'}                     = $cmap; | 
| 151 |  |  |  |  |  |  |  | 
| 152 | 1 |  |  |  |  | 5 | return $self; | 
| 153 |  |  |  |  |  |  | } | 
| 154 |  |  |  |  |  |  |  | 
| 155 |  |  |  |  |  |  | =back | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | =head1 FONT-MANAGEMENT RELATED METHODS | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | =over | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | =item $name = $font->fontname() | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | Return the font's name (a.k.a. display name). | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  | =cut | 
| 166 |  |  |  |  |  |  |  | 
| 167 |  |  |  |  |  |  | sub fontname { | 
| 168 | 70 |  |  | 70 | 1 | 156 | return $_[0]->data()->{'fontname'}; | 
| 169 |  |  |  |  |  |  | } | 
| 170 |  |  |  |  |  |  |  | 
| 171 |  |  |  |  |  |  | =item $name = $font->altname() | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | Return the font's alternative name (a.k.a. Windows name for a PostScript font). | 
| 174 |  |  |  |  |  |  |  | 
| 175 |  |  |  |  |  |  | =cut | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | sub altname { | 
| 178 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'altname'}; | 
| 179 |  |  |  |  |  |  | } | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  | =item $name = $font->subname() | 
| 182 |  |  |  |  |  |  |  | 
| 183 |  |  |  |  |  |  | Return the font's subname (a.k.a. font variant). | 
| 184 |  |  |  |  |  |  |  | 
| 185 |  |  |  |  |  |  | =cut | 
| 186 |  |  |  |  |  |  |  | 
| 187 |  |  |  |  |  |  | sub subname { | 
| 188 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'subname'}; | 
| 189 |  |  |  |  |  |  | } | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | =item $name = $font->apiname() | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | Return the font's name to be used internally (should be equal to $font->name()). | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | =cut | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | sub apiname { | 
| 198 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'apiname'}; | 
| 199 |  |  |  |  |  |  | } | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  | =item $issymbol = $font->issymbol() | 
| 202 |  |  |  |  |  |  |  | 
| 203 |  |  |  |  |  |  | Return the font's symbol flag (i.e., is this a symbol font). | 
| 204 |  |  |  |  |  |  |  | 
| 205 |  |  |  |  |  |  | =cut | 
| 206 |  |  |  |  |  |  |  | 
| 207 |  |  |  |  |  |  | sub issymbol { | 
| 208 | 75 |  |  | 75 | 1 | 147 | return $_[0]->data()->{'issymbol'}; | 
| 209 |  |  |  |  |  |  | } | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | =item $iscff = $font->iscff() | 
| 212 |  |  |  |  |  |  |  | 
| 213 |  |  |  |  |  |  | Return the font's Compact Font Format flag. | 
| 214 |  |  |  |  |  |  |  | 
| 215 |  |  |  |  |  |  | =cut | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | sub iscff { | 
| 218 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'iscff'}; | 
| 219 |  |  |  |  |  |  | } | 
| 220 |  |  |  |  |  |  |  | 
| 221 |  |  |  |  |  |  | =back | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  | =head1 TYPOGRAPHY-RELATED METHODS | 
| 224 |  |  |  |  |  |  |  | 
| 225 |  |  |  |  |  |  | =over | 
| 226 |  |  |  |  |  |  |  | 
| 227 |  |  |  |  |  |  | =item ($llx,$lly, $urx,$ury) = $font->fontbbox() | 
| 228 |  |  |  |  |  |  |  | 
| 229 |  |  |  |  |  |  | Return the font's bounding box. | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | =cut | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | sub fontbbox { | 
| 234 | 31 |  |  | 31 | 1 | 40 | my @bbox = @{$_[0]->data()->{'fontbbox'}}; | 
|  | 31 |  |  |  |  | 52 |  | 
| 235 |  |  |  |  |  |  | # rearrange to LL UR order | 
| 236 | 31 | 50 |  |  |  | 69 | if ($bbox[0] > $bbox[2]) { | 
| 237 | 0 |  |  |  |  | 0 | @bbox = ($bbox[2], $bbox[3], $bbox[0], $bbox[1]); | 
| 238 |  |  |  |  |  |  | } | 
| 239 | 31 |  |  |  |  | 84 | return @bbox; | 
| 240 |  |  |  |  |  |  | } | 
| 241 |  |  |  |  |  |  |  | 
| 242 |  |  |  |  |  |  | =item $capheight = $font->capheight() | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | Return the font's capheight value. | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | =cut | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | sub capheight { | 
| 249 | 16 |  |  | 16 | 1 | 32 | return $_[0]->data()->{'capheight'}; | 
| 250 |  |  |  |  |  |  | } | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | =item $xheight = $font->xheight() | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | Return the font's xheight value. | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | =cut | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | sub xheight { | 
| 259 | 16 |  |  | 16 | 1 | 30 | return $_[0]->data()->{'xheight'}; | 
| 260 |  |  |  |  |  |  | } | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | =item $missingwidth = $font->missingwidth() | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  | Return the font's missingwidth value. | 
| 265 |  |  |  |  |  |  |  | 
| 266 |  |  |  |  |  |  | =cut | 
| 267 |  |  |  |  |  |  |  | 
| 268 |  |  |  |  |  |  | sub missingwidth { | 
| 269 | 276 |  |  | 276 | 1 | 415 | return $_[0]->data()->{'missingwidth'}; | 
| 270 |  |  |  |  |  |  | } | 
| 271 |  |  |  |  |  |  |  | 
| 272 |  |  |  |  |  |  | =item $maxwidth = $font->maxwidth() | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  | Return the font's maxwidth value. | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | =cut | 
| 277 |  |  |  |  |  |  |  | 
| 278 |  |  |  |  |  |  | sub maxwidth { | 
| 279 | 16 |  |  | 16 | 1 | 31 | return $_[0]->data()->{'maxwidth'}; | 
| 280 |  |  |  |  |  |  | } | 
| 281 |  |  |  |  |  |  |  | 
| 282 |  |  |  |  |  |  | =item $avgwidth = $font->avgwidth() | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  | Return the font's avgwidth (average width) value. | 
| 285 |  |  |  |  |  |  |  | 
| 286 |  |  |  |  |  |  | =cut | 
| 287 |  |  |  |  |  |  |  | 
| 288 |  |  |  |  |  |  | sub avgwidth { | 
| 289 | 16 |  |  | 16 | 1 | 30 | my ($self) = @_; | 
| 290 |  |  |  |  |  |  |  | 
| 291 | 16 |  |  |  |  | 27 | my $aw = $self->data()->{'avgwidth'}; | 
| 292 | 16 |  | 33 |  |  | 61 | $aw ||= (( | 
| 293 |  |  |  |  |  |  | # numbers are character-frequency weighting counts | 
| 294 |  |  |  |  |  |  | # presumably for English text... ? it may be a little off for | 
| 295 |  |  |  |  |  |  | # other languages | 
| 296 |  |  |  |  |  |  | $self->wxByGlyph('a')*64  + | 
| 297 |  |  |  |  |  |  | $self->wxByGlyph('b')*14  + | 
| 298 |  |  |  |  |  |  | $self->wxByGlyph('c')*27  + | 
| 299 |  |  |  |  |  |  | $self->wxByGlyph('d')*35  + | 
| 300 |  |  |  |  |  |  | $self->wxByGlyph('e')*100 + | 
| 301 |  |  |  |  |  |  | $self->wxByGlyph('f')*20  + | 
| 302 |  |  |  |  |  |  | $self->wxByGlyph('g')*14  + | 
| 303 |  |  |  |  |  |  | $self->wxByGlyph('h')*42  + | 
| 304 |  |  |  |  |  |  | $self->wxByGlyph('i')*63  + | 
| 305 |  |  |  |  |  |  | $self->wxByGlyph('j')* 3  + | 
| 306 |  |  |  |  |  |  | $self->wxByGlyph('k')* 6  + | 
| 307 |  |  |  |  |  |  | $self->wxByGlyph('l')*35  + | 
| 308 |  |  |  |  |  |  | $self->wxByGlyph('m')*20  + | 
| 309 |  |  |  |  |  |  | $self->wxByGlyph('n')*56  + | 
| 310 |  |  |  |  |  |  | $self->wxByGlyph('o')*56  + | 
| 311 |  |  |  |  |  |  | $self->wxByGlyph('p')*17  + | 
| 312 |  |  |  |  |  |  | $self->wxByGlyph('q')* 4  + | 
| 313 |  |  |  |  |  |  | $self->wxByGlyph('r')*49  + | 
| 314 |  |  |  |  |  |  | $self->wxByGlyph('s')*56  + | 
| 315 |  |  |  |  |  |  | $self->wxByGlyph('t')*71  + | 
| 316 |  |  |  |  |  |  | $self->wxByGlyph('u')*31  + | 
| 317 |  |  |  |  |  |  | $self->wxByGlyph('v')*10  + | 
| 318 |  |  |  |  |  |  | $self->wxByGlyph('w')*18  + | 
| 319 |  |  |  |  |  |  | $self->wxByGlyph('x')* 3  + | 
| 320 |  |  |  |  |  |  | $self->wxByGlyph('y')*18  + | 
| 321 |  |  |  |  |  |  | $self->wxByGlyph('z')* 2  + | 
| 322 |  |  |  |  |  |  | $self->wxByGlyph('A')*64  + | 
| 323 |  |  |  |  |  |  | $self->wxByGlyph('B')*14  + | 
| 324 |  |  |  |  |  |  | $self->wxByGlyph('C')*27  + | 
| 325 |  |  |  |  |  |  | $self->wxByGlyph('D')*35  + | 
| 326 |  |  |  |  |  |  | $self->wxByGlyph('E')*100 + | 
| 327 |  |  |  |  |  |  | $self->wxByGlyph('F')*20  + | 
| 328 |  |  |  |  |  |  | $self->wxByGlyph('G')*14  + | 
| 329 |  |  |  |  |  |  | $self->wxByGlyph('H')*42  + | 
| 330 |  |  |  |  |  |  | $self->wxByGlyph('I')*63  + | 
| 331 |  |  |  |  |  |  | $self->wxByGlyph('J')* 3  + | 
| 332 |  |  |  |  |  |  | $self->wxByGlyph('K')* 6  + | 
| 333 |  |  |  |  |  |  | $self->wxByGlyph('L')*35  + | 
| 334 |  |  |  |  |  |  | $self->wxByGlyph('M')*20  + | 
| 335 |  |  |  |  |  |  | $self->wxByGlyph('N')*56  + | 
| 336 |  |  |  |  |  |  | $self->wxByGlyph('O')*56  + | 
| 337 |  |  |  |  |  |  | $self->wxByGlyph('P')*17  + | 
| 338 |  |  |  |  |  |  | $self->wxByGlyph('Q')* 4  + | 
| 339 |  |  |  |  |  |  | $self->wxByGlyph('R')*49  + | 
| 340 |  |  |  |  |  |  | $self->wxByGlyph('S')*56  + | 
| 341 |  |  |  |  |  |  | $self->wxByGlyph('T')*71  + | 
| 342 |  |  |  |  |  |  | $self->wxByGlyph('U')*31  + | 
| 343 |  |  |  |  |  |  | $self->wxByGlyph('V')*10  + | 
| 344 |  |  |  |  |  |  | $self->wxByGlyph('W')*18  + | 
| 345 |  |  |  |  |  |  | $self->wxByGlyph('X')* 3  + | 
| 346 |  |  |  |  |  |  | $self->wxByGlyph('Y')*18  + | 
| 347 |  |  |  |  |  |  | $self->wxByGlyph('Z')* 2  + | 
| 348 |  |  |  |  |  |  | $self->wxByGlyph('space')*332 | 
| 349 |  |  |  |  |  |  | ) / 2000); | 
| 350 |  |  |  |  |  |  |  | 
| 351 | 16 |  |  |  |  | 83 | return int($aw); | 
| 352 |  |  |  |  |  |  | } | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | =item $flags = $font->flags() | 
| 355 |  |  |  |  |  |  |  | 
| 356 |  |  |  |  |  |  | Return the font's flags value. | 
| 357 |  |  |  |  |  |  |  | 
| 358 |  |  |  |  |  |  | =cut | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  | sub flags { | 
| 361 | 16 |  |  | 16 | 1 | 34 | return $_[0]->data()->{'flags'}; | 
| 362 |  |  |  |  |  |  | } | 
| 363 |  |  |  |  |  |  |  | 
| 364 |  |  |  |  |  |  | =item $stemv = $font->stemv() | 
| 365 |  |  |  |  |  |  |  | 
| 366 |  |  |  |  |  |  | Return the font's stemv value. | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | =cut | 
| 369 |  |  |  |  |  |  |  | 
| 370 |  |  |  |  |  |  | sub stemv { | 
| 371 | 16 |  |  | 16 | 1 | 32 | return $_[0]->data()->{'stemv'}; | 
| 372 |  |  |  |  |  |  | } | 
| 373 |  |  |  |  |  |  |  | 
| 374 |  |  |  |  |  |  | =item $stemh = $font->stemh() | 
| 375 |  |  |  |  |  |  |  | 
| 376 |  |  |  |  |  |  | Return the font's stemh value. | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | =cut | 
| 379 |  |  |  |  |  |  |  | 
| 380 |  |  |  |  |  |  | sub stemh { | 
| 381 | 16 |  |  | 16 | 1 | 36 | return $_[0]->data()->{'stemh'}; | 
| 382 |  |  |  |  |  |  | } | 
| 383 |  |  |  |  |  |  |  | 
| 384 |  |  |  |  |  |  | =item $italicangle = $font->italicangle() | 
| 385 |  |  |  |  |  |  |  | 
| 386 |  |  |  |  |  |  | Return the font's italicangle value. | 
| 387 |  |  |  |  |  |  |  | 
| 388 |  |  |  |  |  |  | =cut | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  | sub italicangle { | 
| 391 | 16 |  |  | 16 | 1 | 32 | return $_[0]->data()->{'italicangle'}; | 
| 392 |  |  |  |  |  |  | } | 
| 393 |  |  |  |  |  |  |  | 
| 394 |  |  |  |  |  |  | =item $isfixedpitch = $font->isfixedpitch() | 
| 395 |  |  |  |  |  |  |  | 
| 396 |  |  |  |  |  |  | Return the font's isfixedpitch flag. | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | =cut | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  | sub isfixedpitch { | 
| 401 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'isfixedpitch'}; | 
| 402 |  |  |  |  |  |  | } | 
| 403 |  |  |  |  |  |  |  | 
| 404 |  |  |  |  |  |  | =item $underlineposition = $font->underlineposition() | 
| 405 |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  | Return the font's underlineposition value. | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  | =cut | 
| 409 |  |  |  |  |  |  |  | 
| 410 |  |  |  |  |  |  | sub underlineposition { | 
| 411 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'underlineposition'}; | 
| 412 |  |  |  |  |  |  | } | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | =item $underlinethickness = $font->underlinethickness() | 
| 415 |  |  |  |  |  |  |  | 
| 416 |  |  |  |  |  |  | Return the font's underlinethickness value. | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | =cut | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | sub underlinethickness { | 
| 421 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'underlinethickness'}; | 
| 422 |  |  |  |  |  |  | } | 
| 423 |  |  |  |  |  |  |  | 
| 424 |  |  |  |  |  |  | =item $ascender = $font->ascender() | 
| 425 |  |  |  |  |  |  |  | 
| 426 |  |  |  |  |  |  | Return the font's ascender value. | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  | =cut | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | sub ascender { | 
| 431 | 16 |  |  | 16 | 1 | 31 | return $_[0]->data()->{'ascender'}; | 
| 432 |  |  |  |  |  |  | } | 
| 433 |  |  |  |  |  |  |  | 
| 434 |  |  |  |  |  |  | =item $descender = $font->descender() | 
| 435 |  |  |  |  |  |  |  | 
| 436 |  |  |  |  |  |  | Return the font's descender value. | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  | =cut | 
| 439 |  |  |  |  |  |  |  | 
| 440 |  |  |  |  |  |  | sub descender { | 
| 441 | 16 |  |  | 16 | 1 | 31 | return $_[0]->data()->{'descender'}; | 
| 442 |  |  |  |  |  |  | } | 
| 443 |  |  |  |  |  |  |  | 
| 444 |  |  |  |  |  |  | =back | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  | =head1 GLYPH-RELATED METHODS | 
| 447 |  |  |  |  |  |  |  | 
| 448 |  |  |  |  |  |  | =over 4 | 
| 449 |  |  |  |  |  |  |  | 
| 450 |  |  |  |  |  |  | =item @names = $font->glyphNames() | 
| 451 |  |  |  |  |  |  |  | 
| 452 |  |  |  |  |  |  | Return the defined glyph names of the font. | 
| 453 |  |  |  |  |  |  |  | 
| 454 |  |  |  |  |  |  | =cut | 
| 455 |  |  |  |  |  |  |  | 
| 456 |  |  |  |  |  |  | sub glyphNames { | 
| 457 | 0 |  |  | 0 | 1 | 0 | return keys %{$_[0]->data()->{'wx'}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 458 |  |  |  |  |  |  | } | 
| 459 |  |  |  |  |  |  |  | 
| 460 |  |  |  |  |  |  | =item $glNum = $font->glyphNum() | 
| 461 |  |  |  |  |  |  |  | 
| 462 |  |  |  |  |  |  | Return the number of defined glyph names of the font. | 
| 463 |  |  |  |  |  |  |  | 
| 464 |  |  |  |  |  |  | =cut | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | sub glyphNum { | 
| 467 |  |  |  |  |  |  | #my $self = shift(); | 
| 468 |  |  |  |  |  |  | #return scalar $self->glyphNames(); | 
| 469 | 0 |  |  | 0 | 1 | 0 | return scalar keys %{$_[0]->data()->{'wx'}}; | 
|  | 0 |  |  |  |  | 0 |  | 
| 470 |  |  |  |  |  |  | } | 
| 471 |  |  |  |  |  |  |  | 
| 472 |  |  |  |  |  |  | =item $uni = $font->uniByGlyph($char) | 
| 473 |  |  |  |  |  |  |  | 
| 474 |  |  |  |  |  |  | Return the unicode by glyph name. | 
| 475 |  |  |  |  |  |  |  | 
| 476 |  |  |  |  |  |  | =cut | 
| 477 |  |  |  |  |  |  |  | 
| 478 |  |  |  |  |  |  | sub uniByGlyph { | 
| 479 |  |  |  |  |  |  | #my ($self, $name) = @_; | 
| 480 |  |  |  |  |  |  | #return $self->data()->{'n2u'}->{$name}; | 
| 481 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'n2u'}->{$_[1]}; | 
| 482 |  |  |  |  |  |  | } | 
| 483 |  |  |  |  |  |  |  | 
| 484 |  |  |  |  |  |  | =item $uni = $font->uniByEnc($char) | 
| 485 |  |  |  |  |  |  |  | 
| 486 |  |  |  |  |  |  | Return the Unicode by the font's encoding map. | 
| 487 |  |  |  |  |  |  |  | 
| 488 |  |  |  |  |  |  | =cut | 
| 489 |  |  |  |  |  |  |  | 
| 490 |  |  |  |  |  |  | sub uniByEnc { | 
| 491 | 256 |  |  | 256 | 1 | 313 | my ($self, $enc) = @_; | 
| 492 | 256 |  |  |  |  | 307 | my $uni = $self->data()->{'e2u'}->[$enc]; | 
| 493 |  |  |  |  |  |  | # fallback to U+0000 if no match | 
| 494 | 256 | 50 |  |  |  | 380 | $uni = 0 unless defined $uni; | 
| 495 | 256 |  |  |  |  | 544 | return $uni; | 
| 496 |  |  |  |  |  |  | } | 
| 497 |  |  |  |  |  |  |  | 
| 498 |  |  |  |  |  |  | =item $uni = $font->uniByMap($char) | 
| 499 |  |  |  |  |  |  |  | 
| 500 |  |  |  |  |  |  | Return the Unicode by the font's default map. | 
| 501 |  |  |  |  |  |  |  | 
| 502 |  |  |  |  |  |  | =cut | 
| 503 |  |  |  |  |  |  |  | 
| 504 |  |  |  |  |  |  | sub uniByMap { | 
| 505 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'uni'}->[$_[1]]; | 
| 506 |  |  |  |  |  |  | } | 
| 507 |  |  |  |  |  |  |  | 
| 508 |  |  |  |  |  |  | =item $char = $font->encByGlyph($glyph) | 
| 509 |  |  |  |  |  |  |  | 
| 510 |  |  |  |  |  |  | Return the character by the given glyph name of the font's encoding map. | 
| 511 |  |  |  |  |  |  |  | 
| 512 |  |  |  |  |  |  | =cut | 
| 513 |  |  |  |  |  |  |  | 
| 514 |  |  |  |  |  |  | sub encByGlyph { | 
| 515 | 0 |  | 0 | 0 | 1 | 0 | return $_[0]->data()->{'n2e'}->{$_[1]} || 0; | 
| 516 |  |  |  |  |  |  | } | 
| 517 |  |  |  |  |  |  |  | 
| 518 |  |  |  |  |  |  | =item $char = $font->encByUni($uni) | 
| 519 |  |  |  |  |  |  |  | 
| 520 |  |  |  |  |  |  | Return the character by the given Unicode of the font's encoding map. | 
| 521 |  |  |  |  |  |  |  | 
| 522 |  |  |  |  |  |  | =cut | 
| 523 |  |  |  |  |  |  |  | 
| 524 |  |  |  |  |  |  | sub encByUni { | 
| 525 |  |  |  |  |  |  | return $_[0]->data()->{'u2e'}->{$_[1]} || | 
| 526 | 27 |  | 50 | 27 | 1 | 39 | $_[0]->data()->{'u2c'}->{$_[1]} || | 
| 527 |  |  |  |  |  |  | 0; | 
| 528 |  |  |  |  |  |  | } | 
| 529 |  |  |  |  |  |  |  | 
| 530 |  |  |  |  |  |  | =item $char = $font->mapByGlyph($glyph) | 
| 531 |  |  |  |  |  |  |  | 
| 532 |  |  |  |  |  |  | Return the character by the given glyph name of the font's default map. | 
| 533 |  |  |  |  |  |  |  | 
| 534 |  |  |  |  |  |  | =cut | 
| 535 |  |  |  |  |  |  |  | 
| 536 |  |  |  |  |  |  | sub mapByGlyph { | 
| 537 | 0 |  | 0 | 0 | 1 | 0 | return $_[0]->data()->{'n2c'}->{$_[1]} || 0; | 
| 538 |  |  |  |  |  |  | } | 
| 539 |  |  |  |  |  |  |  | 
| 540 |  |  |  |  |  |  | =item $char = $font->mapByUni($uni) | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  | Return the character by the given Unicode of the font's default map. | 
| 543 |  |  |  |  |  |  |  | 
| 544 |  |  |  |  |  |  | =cut | 
| 545 |  |  |  |  |  |  |  | 
| 546 |  |  |  |  |  |  | sub mapByUni { | 
| 547 | 0 |  | 0 | 0 | 1 | 0 | return $_[0]->data()->{'u2c'}->{$_[1]} || 0; | 
| 548 |  |  |  |  |  |  | } | 
| 549 |  |  |  |  |  |  |  | 
| 550 |  |  |  |  |  |  | =item $name = $font->glyphByUni($unicode) | 
| 551 |  |  |  |  |  |  |  | 
| 552 |  |  |  |  |  |  | Return the glyph's name by the font's Unicode map. | 
| 553 |  |  |  |  |  |  | B non-standard glyph-names are mapped onto | 
| 554 |  |  |  |  |  |  | the ms-symbol area (0xF000). | 
| 555 |  |  |  |  |  |  |  | 
| 556 |  |  |  |  |  |  | =cut | 
| 557 |  |  |  |  |  |  |  | 
| 558 |  |  |  |  |  |  | sub glyphByUni { | 
| 559 | 0 |  | 0 | 0 | 1 | 0 | return $_[0]->data()->{'u2n'}->{$_[1]} || '.notdef'; | 
| 560 |  |  |  |  |  |  | } | 
| 561 |  |  |  |  |  |  |  | 
| 562 |  |  |  |  |  |  | =item $name = $font->glyphByEnc($char) | 
| 563 |  |  |  |  |  |  |  | 
| 564 |  |  |  |  |  |  | Return the glyph's name by the font's encoding map. | 
| 565 |  |  |  |  |  |  |  | 
| 566 |  |  |  |  |  |  | =cut | 
| 567 |  |  |  |  |  |  |  | 
| 568 |  |  |  |  |  |  | sub glyphByEnc { | 
| 569 | 25398 |  |  | 25398 | 1 | 33302 | return $_[0]->data()->{'e2n'}->[$_[1]]; | 
| 570 |  |  |  |  |  |  | } | 
| 571 |  |  |  |  |  |  |  | 
| 572 |  |  |  |  |  |  | =item $name = $font->glyphByMap($char) | 
| 573 |  |  |  |  |  |  |  | 
| 574 |  |  |  |  |  |  | Return the glyph's name by the font's default map. | 
| 575 |  |  |  |  |  |  |  | 
| 576 |  |  |  |  |  |  | =cut | 
| 577 |  |  |  |  |  |  |  | 
| 578 |  |  |  |  |  |  | sub glyphByMap { | 
| 579 | 0 |  |  | 0 | 1 | 0 | return $_[0]->data()->{'char'}->[$_[1]]; | 
| 580 |  |  |  |  |  |  | } | 
| 581 |  |  |  |  |  |  |  | 
| 582 |  |  |  |  |  |  | =item $width = $font->wxByGlyph($glyph) | 
| 583 |  |  |  |  |  |  |  | 
| 584 |  |  |  |  |  |  | Return the glyph's width. | 
| 585 |  |  |  |  |  |  | This is a value, that when divided by 1000 and multiplied by | 
| 586 |  |  |  |  |  |  | the font size (height in points), gives the advance width to the | 
| 587 |  |  |  |  |  |  | next character's start. Typically, the width will be under 1000. | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | =cut | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  | sub wxByGlyph { | 
| 592 | 848 |  |  | 848 | 1 | 1112 | my ($self, $glyph) = @_; | 
| 593 |  |  |  |  |  |  |  | 
| 594 | 848 |  |  |  |  | 897 | my $width; | 
| 595 | 848 | 100 |  |  |  | 1025 | if (ref($self->data()->{'wx'}) eq 'HASH') { | 
| 596 | 795 | 50 |  |  |  | 1250 | $width   = $self->data()->{'wx'}->{$glyph} if defined $glyph; | 
| 597 |  |  |  |  |  |  | } else { | 
| 598 | 53 |  |  |  |  | 90 | my $cid = $self->cidByUni(uniByName($glyph)); | 
| 599 | 53 | 50 |  |  |  | 98 | $width = $self->data()->{'wx'}->[$cid] if defined $cid; | 
| 600 |  |  |  |  |  |  | } | 
| 601 | 848 |  | 66 |  |  | 1247 | $width //= $self->missingwidth(); | 
| 602 | 848 |  | 100 |  |  | 1238 | $width //= 300; | 
| 603 |  |  |  |  |  |  |  | 
| 604 | 848 |  |  |  |  | 1559 | return $width; | 
| 605 |  |  |  |  |  |  | } | 
| 606 |  |  |  |  |  |  |  | 
| 607 |  |  |  |  |  |  | =item $width = $font->wxByUni($uni) | 
| 608 |  |  |  |  |  |  |  | 
| 609 |  |  |  |  |  |  | Return the Unicode character's width. | 
| 610 |  |  |  |  |  |  | This is a value, that when divided by 1000 and multiplied by | 
| 611 |  |  |  |  |  |  | the font size (height in points), gives the advance width to the | 
| 612 |  |  |  |  |  |  | next character's start. Typically, the width will be under 1000. | 
| 613 |  |  |  |  |  |  |  | 
| 614 |  |  |  |  |  |  | =cut | 
| 615 |  |  |  |  |  |  |  | 
| 616 |  |  |  |  |  |  | sub wxByUni { | 
| 617 | 0 |  |  | 0 | 1 | 0 | my ($self, $uni) = @_; | 
| 618 | 0 |  |  |  |  | 0 | my ($gid, $width); | 
| 619 |  |  |  |  |  |  |  | 
| 620 | 0 | 0 |  |  |  | 0 | $gid = $self->glyphByUni($uni) if defined $uni; | 
| 621 | 0 | 0 |  |  |  | 0 | $width = $self->data()->{'wx'}->{$gid} if defined $gid; | 
| 622 | 0 |  | 0 |  |  | 0 | $width //= $self->missingwidth(); | 
| 623 | 0 |  | 0 |  |  | 0 | $width //= 300; | 
| 624 |  |  |  |  |  |  |  | 
| 625 | 0 |  |  |  |  | 0 | return $width; | 
| 626 |  |  |  |  |  |  | } | 
| 627 |  |  |  |  |  |  |  | 
| 628 |  |  |  |  |  |  | =item $width = $font->wxByEnc($char) | 
| 629 |  |  |  |  |  |  |  | 
| 630 |  |  |  |  |  |  | Return the character's width based on the current encoding. | 
| 631 |  |  |  |  |  |  | This is a value, that when divided by 1000 and multiplied by | 
| 632 |  |  |  |  |  |  | the font size (height in points), gives the advance width to the | 
| 633 |  |  |  |  |  |  | next character's start. Typically, the width will be under 1000. | 
| 634 |  |  |  |  |  |  |  | 
| 635 |  |  |  |  |  |  | =cut | 
| 636 |  |  |  |  |  |  |  | 
| 637 |  |  |  |  |  |  | sub wxByEnc { | 
| 638 | 12086 |  |  | 12086 | 1 | 15411 | my ($self, $char) = @_; | 
| 639 |  |  |  |  |  |  |  | 
| 640 | 12086 |  |  |  |  | 12480 | my $glyph; | 
| 641 | 12086 | 50 |  |  |  | 20956 | $glyph = $self->glyphByEnc($char) if defined $char; | 
| 642 | 12086 |  |  |  |  | 12941 | my $width; | 
| 643 | 12086 | 50 |  |  |  | 19205 | $width = $self->data()->{'wx'}->{$glyph} if defined $glyph; | 
| 644 |  |  |  |  |  |  |  | 
| 645 | 12086 |  | 100 |  |  | 17251 | $width //= $self->missingwidth(); | 
| 646 | 12086 |  | 100 |  |  | 15992 | $width //= 300; | 
| 647 |  |  |  |  |  |  |  | 
| 648 | 12086 |  |  |  |  | 21222 | return $width; | 
| 649 |  |  |  |  |  |  | } | 
| 650 |  |  |  |  |  |  |  | 
| 651 |  |  |  |  |  |  | =item $flag = $font->wxMissingByEnc($char) | 
| 652 |  |  |  |  |  |  |  | 
| 653 |  |  |  |  |  |  | Return true if the character's width (based on the current encoding) is | 
| 654 |  |  |  |  |  |  | supplied by "missing width" of font. | 
| 655 |  |  |  |  |  |  |  | 
| 656 |  |  |  |  |  |  | =cut | 
| 657 |  |  |  |  |  |  |  | 
| 658 |  |  |  |  |  |  | sub wxMissingByEnc { | 
| 659 | 0 |  |  | 0 | 1 | 0 | my ($self, $char) = @_; | 
| 660 |  |  |  |  |  |  |  | 
| 661 | 0 |  |  |  |  | 0 | my $glyph = $self->glyphByEnc($char); | 
| 662 | 0 |  |  |  |  | 0 | my $width = $self->data()->{'wx'}->{$glyph}; | 
| 663 |  |  |  |  |  |  |  | 
| 664 | 0 |  |  |  |  | 0 | return !defined($width); | 
| 665 |  |  |  |  |  |  | } | 
| 666 |  |  |  |  |  |  |  | 
| 667 |  |  |  |  |  |  | =item $width = $font->wxByMap($char) | 
| 668 |  |  |  |  |  |  |  | 
| 669 |  |  |  |  |  |  | Return the character's width based on the font's default encoding. | 
| 670 |  |  |  |  |  |  | This is a value, that when divided by 1000 and multiplied by | 
| 671 |  |  |  |  |  |  | the font size (height in points), gives the advance width to the | 
| 672 |  |  |  |  |  |  | next character's start. Typically, the width will be under 1000. | 
| 673 |  |  |  |  |  |  |  | 
| 674 |  |  |  |  |  |  | =cut | 
| 675 |  |  |  |  |  |  |  | 
| 676 |  |  |  |  |  |  | sub wxByMap { | 
| 677 | 0 |  |  | 0 | 1 | 0 | my ($self, $char) = @_; | 
| 678 |  |  |  |  |  |  |  | 
| 679 | 0 |  |  |  |  | 0 | my $glyph; | 
| 680 | 0 | 0 |  |  |  | 0 | $glyph = $self->glyphByMap($char) if defined $char; | 
| 681 | 0 |  |  |  |  | 0 | my $width; | 
| 682 | 0 | 0 |  |  |  | 0 | $width = $self->data()->{'wx'}->{$glyph} if defined $glyph; | 
| 683 | 0 |  | 0 |  |  | 0 | $width //= $self->missingwidth(); | 
| 684 | 0 |  | 0 |  |  | 0 | $width //= 300; | 
| 685 |  |  |  |  |  |  |  | 
| 686 | 0 |  |  |  |  | 0 | return $width; | 
| 687 |  |  |  |  |  |  | } | 
| 688 |  |  |  |  |  |  |  | 
| 689 |  |  |  |  |  |  | =item $wd = $font->width($text) | 
| 690 |  |  |  |  |  |  |  | 
| 691 |  |  |  |  |  |  | Return the width of $text as if it were at size 1. | 
| 692 |  |  |  |  |  |  | B works correctly only if a proper Perl string | 
| 693 |  |  |  |  |  |  | is used, either in native or UTF-8 format (check utf8-flag). | 
| 694 |  |  |  |  |  |  |  | 
| 695 |  |  |  |  |  |  | =cut | 
| 696 |  |  |  |  |  |  |  | 
| 697 |  |  |  |  |  |  | sub width { | 
| 698 | 192 |  |  | 192 | 1 | 301 | my ($self, $text) = @_; | 
| 699 |  |  |  |  |  |  |  | 
| 700 | 192 | 100 |  |  |  | 404 | $text = $self->strByUtf($text) if utf8::is_utf8($text); | 
| 701 |  |  |  |  |  |  |  | 
| 702 | 192 |  |  |  |  | 247 | my @cache; | 
| 703 | 192 |  |  |  |  | 264 | my $width = 0; | 
| 704 | 192 |  | 33 |  |  | 373 | my $kern = $self->{'-dokern'} && ref($self->data()->{'kern'}); | 
| 705 | 192 |  |  |  |  | 229 | my $last_glyph = ''; | 
| 706 | 192 |  |  |  |  | 435 | foreach my $n (unpack('C*',$text)) { | 
| 707 | 2391 |  | 66 |  |  | 3521 | $cache[$n] //= $self->wxByEnc($n); | 
| 708 | 2391 |  |  |  |  | 2472 | $width += $cache[$n]; | 
| 709 | 2391 | 50 |  |  |  | 3312 | if ($kern) { | 
| 710 | 0 |  |  |  |  | 0 | my $glyph = $self->data()->{'e2n'}->[$n]; | 
| 711 | 0 |  | 0 |  |  | 0 | $width += ($self->data()->{'kern'}->{$last_glyph . ':' . $glyph} // 0); | 
| 712 | 0 |  |  |  |  | 0 | $last_glyph = $glyph; | 
| 713 |  |  |  |  |  |  | } | 
| 714 |  |  |  |  |  |  | } | 
| 715 | 192 |  |  |  |  | 308 | $width /= 1000; | 
| 716 | 192 |  |  |  |  | 465 | return $width; | 
| 717 |  |  |  |  |  |  | } | 
| 718 |  |  |  |  |  |  |  | 
| 719 |  |  |  |  |  |  | =item @widths = $font->width_array($text) | 
| 720 |  |  |  |  |  |  |  | 
| 721 |  |  |  |  |  |  | Return (as an array) the widths of the words in $text as if they were at size 1. | 
| 722 |  |  |  |  |  |  |  | 
| 723 |  |  |  |  |  |  | =cut | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | sub width_array { | 
| 726 | 0 |  |  | 0 | 1 | 0 | my ($self, $text) = @_; | 
| 727 |  |  |  |  |  |  |  | 
| 728 | 0 | 0 |  |  |  | 0 | $text = $self->utfByStr($text) unless utf8::is_utf8($text); | 
| 729 | 0 |  |  |  |  | 0 | my @widths = map { $self->width($_) } split(/\s+/, $text); | 
|  | 0 |  |  |  |  | 0 |  | 
| 730 | 0 |  |  |  |  | 0 | return @widths; | 
| 731 |  |  |  |  |  |  | } | 
| 732 |  |  |  |  |  |  |  | 
| 733 |  |  |  |  |  |  | =back | 
| 734 |  |  |  |  |  |  |  | 
| 735 |  |  |  |  |  |  | =head1 STRING METHODS | 
| 736 |  |  |  |  |  |  |  | 
| 737 |  |  |  |  |  |  | =over | 
| 738 |  |  |  |  |  |  |  | 
| 739 |  |  |  |  |  |  | =item $utf8string = $font->utfByStr($string) | 
| 740 |  |  |  |  |  |  |  | 
| 741 |  |  |  |  |  |  | Return the utf8-string from string based on the font's encoding map. | 
| 742 |  |  |  |  |  |  |  | 
| 743 |  |  |  |  |  |  | =cut | 
| 744 |  |  |  |  |  |  |  | 
| 745 |  |  |  |  |  |  | sub utfByStr { | 
| 746 | 0 |  |  | 0 | 1 | 0 | my ($self, $string) = @_; | 
| 747 |  |  |  |  |  |  |  | 
| 748 | 0 |  |  |  |  | 0 | $string = pack('U*', map { $self->uniByEnc($_) } unpack('C*', $string)); | 
|  | 0 |  |  |  |  | 0 |  | 
| 749 | 0 |  |  |  |  | 0 | utf8::upgrade($string); | 
| 750 | 0 |  |  |  |  | 0 | return $string; | 
| 751 |  |  |  |  |  |  | } | 
| 752 |  |  |  |  |  |  |  | 
| 753 |  |  |  |  |  |  | =item $string = $font->strByUtf($utf8_string) | 
| 754 |  |  |  |  |  |  |  | 
| 755 |  |  |  |  |  |  | Return the encoded string from utf8-string based on the font's encoding map. | 
| 756 |  |  |  |  |  |  |  | 
| 757 |  |  |  |  |  |  | =cut | 
| 758 |  |  |  |  |  |  |  | 
| 759 |  |  |  |  |  |  | sub strByUtf { | 
| 760 | 9 |  |  | 9 | 1 | 16 | my ($self, $utf8_string) = @_; | 
| 761 |  |  |  |  |  |  |  | 
| 762 | 9 |  |  |  |  | 21 | $utf8_string = pack('C*', map { $self->encByUni($_) & 0xFF } unpack('U*', $utf8_string)); | 
|  | 27 |  |  |  |  | 45 |  | 
| 763 | 9 |  |  |  |  | 90 | utf8::downgrade($utf8_string); | 
| 764 | 9 |  |  |  |  | 16 | return $utf8_string; | 
| 765 |  |  |  |  |  |  | } | 
| 766 |  |  |  |  |  |  |  | 
| 767 |  |  |  |  |  |  | =item $pdf_string = $font->textByStr($string) | 
| 768 |  |  |  |  |  |  |  | 
| 769 |  |  |  |  |  |  | Return a properly formatted representation of $string for use in the PDF. | 
| 770 |  |  |  |  |  |  |  | 
| 771 |  |  |  |  |  |  | =cut | 
| 772 |  |  |  |  |  |  |  | 
| 773 |  |  |  |  |  |  | sub textByStr { | 
| 774 | 31 |  |  | 31 | 1 | 53 | my ($self, $string) = @_; | 
| 775 |  |  |  |  |  |  |  | 
| 776 | 31 | 50 |  |  |  | 65 | if (not defined $string) { $string = ''; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 777 | 31 | 100 |  |  |  | 102 | $string = $self->strByUtf($string) if utf8::is_utf8($string); | 
| 778 | 31 |  |  |  |  | 46 | my $text = $string; | 
| 779 | 31 |  |  |  |  | 72 | $text =~ s/\\/\\\\/go; | 
| 780 | 31 |  |  |  |  | 68 | $text =~ s/([\x00-\x1f])/sprintf('\%03lo',ord($1))/ge; | 
|  | 0 |  |  |  |  | 0 |  | 
| 781 | 31 |  |  |  |  | 71 | $text =~ s/([\{\}\[\]\(\)])/\\$1/g; | 
| 782 |  |  |  |  |  |  |  | 
| 783 | 31 |  |  |  |  | 59 | return $text; | 
| 784 |  |  |  |  |  |  | } | 
| 785 |  |  |  |  |  |  |  | 
| 786 |  |  |  |  |  |  | =item $pdf_string = $font->textByStrKern($string) | 
| 787 |  |  |  |  |  |  |  | 
| 788 |  |  |  |  |  |  | Return a properly formatted representation of $string, with kerning, | 
| 789 |  |  |  |  |  |  | for use in the PDF. | 
| 790 |  |  |  |  |  |  |  | 
| 791 |  |  |  |  |  |  | =cut | 
| 792 |  |  |  |  |  |  |  | 
| 793 |  |  |  |  |  |  | sub textByStrKern { | 
| 794 | 0 |  |  | 0 | 1 | 0 | my ($self, $string) = @_; | 
| 795 |  |  |  |  |  |  |  | 
| 796 | 0 | 0 | 0 |  |  | 0 | return '(' . $self->textByStr($string) . ')' unless $self->{'-dokern'} && ref($self->data()->{'kern'}); | 
| 797 | 0 | 0 |  |  |  | 0 | $string = $self->strByUtf($string) if utf8::is_utf8($string); | 
| 798 |  |  |  |  |  |  |  | 
| 799 | 0 |  |  |  |  | 0 | my $text = ' '; | 
| 800 | 0 |  |  |  |  | 0 | my $tBefore = 0; | 
| 801 | 0 |  |  |  |  | 0 | my $last_glyph = ''; | 
| 802 |  |  |  |  |  |  |  | 
| 803 | 0 |  |  |  |  | 0 | foreach my $n (unpack('C*', $string)) { | 
| 804 | 0 |  |  |  |  | 0 | my $glyph = $self->data()->{'e2n'}->[$n]; | 
| 805 | 0 | 0 |  |  |  | 0 | if (defined $self->data()->{'kern'}->{$last_glyph . ':' . $glyph}) { | 
| 806 | 0 | 0 |  |  |  | 0 | $text .= ') ' if $tBefore; | 
| 807 | 0 |  |  |  |  | 0 | $text .= sprintf('%i ', -($self->data()->{'kern'}->{$last_glyph . ':' . $glyph})); | 
| 808 | 0 |  |  |  |  | 0 | $tBefore = 0; | 
| 809 |  |  |  |  |  |  | } | 
| 810 | 0 |  |  |  |  | 0 | $last_glyph = $glyph; | 
| 811 | 0 |  |  |  |  | 0 | my $t = pack('C', $n); | 
| 812 | 0 |  |  |  |  | 0 | $t =~ s/\\/\\\\/go; | 
| 813 | 0 |  |  |  |  | 0 | $t =~ s/([\x00-\x1f])/sprintf('\%03lo',ord($1))/ge; | 
|  | 0 |  |  |  |  | 0 |  | 
| 814 | 0 |  |  |  |  | 0 | $t =~ s/([\{\}\[\]\(\)])/\\$1/g; | 
| 815 | 0 | 0 |  |  |  | 0 | $text .= '(' unless $tBefore; | 
| 816 | 0 |  |  |  |  | 0 | $text .= "$t"; | 
| 817 | 0 |  |  |  |  | 0 | $tBefore = 1; | 
| 818 |  |  |  |  |  |  | } | 
| 819 | 0 | 0 |  |  |  | 0 | $text .= ') ' if $tBefore; | 
| 820 | 0 |  |  |  |  | 0 | return $text; | 
| 821 |  |  |  |  |  |  | } | 
| 822 |  |  |  |  |  |  |  | 
| 823 |  |  |  |  |  |  | # Maintainer's note: $size here is used solely as a flag to determine whether or | 
| 824 |  |  |  |  |  |  | # not to append a text-showing operator (TJ or Tj). | 
| 825 |  |  |  |  |  |  | sub text { | 
| 826 | 31 |  |  | 31 | 0 | 83 | my ($self, $string, $size, $indent) = @_; | 
| 827 | 31 | 50 |  |  |  | 84 | if (not defined $string) { $string = ''; } | 
|  | 0 |  |  |  |  | 0 |  | 
| 828 | 31 |  |  |  |  | 88 | my $text = $self->textByStr($string); | 
| 829 |  |  |  |  |  |  |  | 
| 830 | 31 | 50 | 33 |  |  | 169 | if      (defined $size && $self->{'-dokern'}) { | 
|  |  | 50 |  |  |  |  |  | 
| 831 | 0 |  |  |  |  | 0 | $text = $self->textByStrKern($string); | 
| 832 | 0 | 0 |  |  |  | 0 | return "[ $indent $text ] TJ" if $indent; | 
| 833 | 0 |  |  |  |  | 0 | return "[ $text ] TJ"; | 
| 834 |  |  |  |  |  |  | } elsif (defined $size) { | 
| 835 | 31 | 100 |  |  |  | 130 | return "[ $indent ($text) ] TJ" if $indent; | 
| 836 | 19 |  |  |  |  | 83 | return "($text) Tj"; | 
| 837 |  |  |  |  |  |  | } else { | 
| 838 |  |  |  |  |  |  | # will need a later Tj operator to actually see this! | 
| 839 | 0 |  |  |  |  | 0 | return "($text)"; | 
| 840 |  |  |  |  |  |  | } | 
| 841 |  |  |  |  |  |  | } | 
| 842 |  |  |  |  |  |  |  | 
| 843 |  |  |  |  |  |  | sub isvirtual { | 
| 844 | 32 |  |  | 32 | 0 | 91 | return; | 
| 845 |  |  |  |  |  |  | } | 
| 846 |  |  |  |  |  |  |  | 
| 847 |  |  |  |  |  |  | =back | 
| 848 |  |  |  |  |  |  |  | 
| 849 |  |  |  |  |  |  | =cut | 
| 850 |  |  |  |  |  |  |  | 
| 851 |  |  |  |  |  |  | 1; |