This file is indexed.

/usr/share/perl5/PostScript/File/Metrics.pm is in libpostscript-file-perl 2.20+dfsg-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
#---------------------------------------------------------------------
package PostScript::File::Metrics;
#
# Copyright 2009 Christopher J. Madsen
#
# Author: Christopher J. Madsen <perl@cjmweb.net>
# Created: 29 Oct 2009
#
# This program is free software; you can redistribute it and/or modify
# it under the same terms as Perl itself.
#
# This program 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 either the
# GNU General Public License or the Artistic License for more details.
#
# ABSTRACT: Metrics for PostScript fonts
#---------------------------------------------------------------------

use 5.008;
our $VERSION = '2.11';          ## no critic
# This file is part of PostScript-File 2.20 (February 11, 2012)

use strict;
use warnings;
use Carp qw(carp croak);
use Encode qw(find_encoding);

use PostScript::File ':metrics_methods'; # Import some methods

our (%Info, %Metrics);

#=====================================================================
# Generate accessor methods:

BEGIN {
  my ($code, $error, $success) = '';
  foreach my $attribute (qw(
    full_name
    family
    weight
    fixed_pitch
    italic_angle
    version
  )) {
    $code .= "sub $attribute { shift->{info}{$attribute} };\n";
  }

  foreach my $attribute (qw(
    underline_position
    underline_thickness
    cap_height
    x_height
    ascender
    descender
  )) {
    $code .= <<"END SUB";
      sub $attribute {
        my \$self = shift;
        my \$v = \$self->{info}{$attribute};
        defined \$v ? \$v * \$self->{factor} : \$v;
      }
END SUB
  }

  { local $@;
    $success = eval "$code ; 'OK'"; ## no critic ProhibitStringyEval
    $error   = $@;
  } # end local $@

  unless ($success and $success eq 'OK') {
    $error ||= 'eval died with false $@';
    die "$code\n$error";
  }
} # end BEGIN

#---------------------------------------------------------------------
sub font_bbox
{
  my $self = shift;

  my $bbox = $self->{info}{font_bbox};

  if (1 != (my $f = $self->{factor})) {
    [ map { $_ * $f } @$bbox ];
  } else {
    $bbox;
  }
} # end font_bbox

#---------------------------------------------------------------------
sub auto_hyphen { shift->{auto_hyphen} }
sub size { shift->{size} }

#=====================================================================


sub new
{
  my ($class, $font, $size, $encoding) = @_;

  $encoding ||= ($font eq 'Symbol' ? 'sym' : 'std');

  # Load the metrics if necessary:
  unless ($Metrics{$font}{$encoding}) {
    # First, try to load a pre-compiled package:
    my $package = _get_package_name($font, $encoding);

    ## no critic (ProhibitStringyEval)
    unless (do { local $@; eval "require $package; 1" }
            and $Metrics{$font}{$encoding}) {
      # No pre-compiled package, we'll have to read the AFM file:
      ## use critic
      require PostScript::File::Metrics::Loader;

      PostScript::File::Metrics::Loader::load($font, [$encoding]);
    } # end unless metrics have been pre-generated
  } # end unless the metrics are loaded

  # Create the Metrics object:
  my $self = bless {
    info     => $Info{$font},
    metrics  => $Metrics{$font}{$encoding}
      || croak "Failed to load metrics for $font in encoding $encoding",
  }, $class;

  $self->{encoding} = find_encoding($encoding)
      or croak "Unknown encoding $encoding"
          unless $encoding =~ /^(?:std|sym)$/;
  $self->set_auto_hyphen(1);
  $self->set_size($size);
  $self->set_wrap_chars;
} # end new
#---------------------------------------------------------------------


sub set_size
{
  my ($self, $size) = @_;

  $self->{size} = $size || 1000;

  $self->{factor} = ($size ? $size/1000.0 : 1);

  $self;
} # end set_size
#---------------------------------------------------------------------


sub width
{
  my $self = shift; # $string

  return 0.0 unless defined $_[0] and length $_[0];

  my $wx = $self->{metrics};

  my $string = $_[1] ? $_[0] : $self->encode_text(
    $self->{auto_hyphen} ? $self->convert_hyphens($_[0]) : $_[0]
  );

  my $width = 0;
  $width += $wx->[$_] for unpack("C*", $string);

  $width * $self->{factor};
} # end width
#---------------------------------------------------------------------


sub wrap
{
  my $self  = shift;
  my $width = shift;
  my $text  = shift;
  my %param = @_ ? %{+shift} : ();

  my $maxlines = delete $param{maxlines};
  my $quiet    = delete $param{quiet};
  my $warnings = delete $param{warnings};
  my $re       = (exists($param{chars})
                  ? $self->_build_wrap_re(delete $param{chars})
                  : $self->{wrap_re});

  carp "Unknown wrap parameter(s) @{[ keys %param ]}" if %param;

  # Remove CRs; convert ZWSP to CR:
  $text =~ s/\r//g;
  $text =~ s/\x{200B}/\r/g if Encode::is_utf8($text);

  $text  = $self->encode_text(
    $self->{auto_hyphen} ? $self->convert_hyphens($text) : $text
  );

  # Do word wrapping:
  my @lines = '';

  for ($text) {
    if (m/\G[ \t\r]*\n/gc) {
      push @lines, '';
    } else {
      m/\G($re)/g or last;
      my $word = $1;
    check_word:
      if ($self->width($lines[-1] . $word, 1) <= $width) {
        $lines[-1] .= $word;
      } elsif ($lines[-1] eq '') {
        $lines[-1] = $word;
        my $w = sprintf("%s is too wide (%g) for field width %g",
                        $word, $self->width($word, 1), $width);
        push @$warnings, $w if $warnings;
        carp $w unless $quiet;
      } else {
        push @lines, '';
        $word =~ s/^[ \t\r]+//;
        goto check_word;
      }
    } # end else not at LF

    if (defined $maxlines and @lines >= $maxlines) {
      $lines[-1] .= $1 if m/\G(.*[^ \t\r\n])/sg;
      if (($warnings or not $quiet) and
          (my $linewidth = $self->width($lines[-1], 1)) > $width) {
        my $w = sprintf("'%s' is too wide (%g) for field width %g",
                        $lines[-1], $linewidth, $width);
        push @$warnings, $w if $warnings;
        carp $w unless $quiet;
      } # end if issuing warning about last line
      last;
    } # end if reached maximum number of lines

    redo;                   # Only the "last" statement above can exit
  } # end for $text

  # Remove any remaining CR (ZWSP) chars:
  s/\r//g for @lines;

  # Remove the last line if it's blank ($text ended with newline):
  pop @lines unless @lines == 1 or length $lines[-1];

  if ($self->{auto_hyphen}) {
    # At this point, any hyphen-minus characters are unambiguously
    # MINUS SIGN.  Protect them from further processing:
    map { $self->decode_text($_, 1) } @lines;
  } else {
    @lines;
  }
} # end wrap
#---------------------------------------------------------------------


sub set_wrap_chars
{
  my $self = shift;

  $self->{wrap_re} = $self->_build_wrap_re(@_);

  $self;
} # end set_wrap_chars

#---------------------------------------------------------------------
our %_wrap_re_cache;

sub _build_wrap_re
{
  my ($self, $chars) = @_;

  if (not defined $chars) {
    $chars = '-/';
    if ($self->{encoding}) {
      $chars .= "\xAD";
      # Only cp1252 has en dash & em dash:
      $chars .= "\x{2013}\x{2014}" if $self->{encoding}->name eq 'cp1252';
    }
  } # end if $chars not supplied (use default)

  $chars = $self->encode_text($chars);

  return $_wrap_re_cache{$chars} ||= do {
    if (length $chars) {
      $chars =~ s/(.)/ sprintf '\x%02X', ord $1 /seg;

      qr(
        [ \t\r]*
        (?: [^$chars \t\r\n]+ |
            [$chars]+ [^$chars \t\r\n]* )
        [$chars]*
      )x;
    } else {
      qr( [ \t\r]*  [^ \t\r\n]+ )x;
    }
  };
} # end _build_wrap_re

#---------------------------------------------------------------------
# Return the package in which the font's metrics are stored:

sub _get_package_name
{
  my ($font, $encoding) = @_;

  my $package = $encoding;
  $package =~ s/-/_/g;
  $package .= " $font";
  $package =~ s/\W+/::/g;

  "PostScript::File::Metrics::$package";
} # end _get_package_name

#=====================================================================
# Package Return Value:

1;

__END__

=head1 NAME

PostScript::File::Metrics - Metrics for PostScript fonts

=head1 VERSION

This document describes version 2.11 of
PostScript::File::Metrics, released February 11, 2012
as part of PostScript-File version 2.20.

=head1 SYNOPSIS

  use PostScript::File;

  my $ps = PostScript::File->new(reencode => 'cp1252');

  my $metrics = $ps->get_metrics('Helvetica-iso', 9);

  my $upos = $metrics->underline_position;

  my $width = $metrics->width('Hello, World!');

  my @lines = $metrics->wrap( 72, # wrap it into 1 inch lines
    'This is a long string that will not fit on just one line of text.'
  );

=head1 DESCRIPTION

PostScript::File::Metrics provides a subset of the metrics available
from L<Font::AFM>.  Its reason for existence is that it allows you to
pre-compile the AFM files into Perl modules.  This makes loading them
more efficient, but more importantly, it means you don't have to
install (or configure) Font::AFM.  That's important because the
locations and filenames of AFM files are not very standardized, which
makes configuring Font::AFM quite difficult.

PostScript::File::Metrics includes pre-compiled metrics for the 13
standard PostScript fonts:

  Courier              Helvetica              Times-Roman
  Courier-Bold         Helvetica-Bold         Times-Bold
  Courier-BoldOblique  Helvetica-BoldOblique  Times-BoldItalic
  Courier-Oblique      Helvetica-Oblique      Times-Italic
                       Symbol

If you need metrics for a font not in that list, you'll need to have
Font::AFM installed and configured.  (You can modify
F<examples/generate_metrics.pl> to create additional pre-compiled
modules, but you'll still have to get Font::AFM working on one
system.)

=head1 ATTRIBUTES

All attributes are read-only, except for C<auto_hyphen> and C<size>,
which can be set using the corresponding C<set_> methods.



=head2 size

The current font size in points.  This is not an attribute of the
font, but of this Metrics object.  The attributes that describe the
font's dimensions are adjusted according to this value.


=head2 auto_hyphen

If true, the C<width> and C<wrap> methods will do hyphen-minus
processing as described in L<PostScript::File/"Hyphens and Minus Signs">,
but only if the encoding is C<cp1252> or C<iso-8859-1>.


=head2 full_name

Unique, human-readable name for an individual font, for instance
"Times Roman".


=head2 family

Human-readable name for a group of fonts that are stylistic variants
of a single design. All fonts that are members of such a group should
have exactly the same C<family>. Example of a family name is
"Times".


=head2 weight

Human-readable name for the weight, or "boldness", attribute of a font.
Examples are C<Roman>, C<Bold>, C<Medium>.


=head2 italic_angle

Angle in degrees counterclockwise from the vertical of the dominant
vertical strokes of the font.  (This is normally <= 0.)


=head2 fixed_pitch

1 if the font is a fixed-pitch (monospaced) font.  0 otherwise.


=head2 font_bbox

An arrayref of four numbers giving the lower-left x, lower-left y,
upper-right x, and upper-right y of the font bounding box. The font
bounding box is the smallest rectangle enclosing the shape that would
result if all the characters of the font were placed with their
origins coincident at (0,0), and then painted.  You must not modify
the returned arrayref.


=head2 cap_height

Usually the y-value of the top of the capital H.
Some fonts, like Symbol, may not define this attribute.


=head2 x_height

Typically the y-value of the top of the lowercase x.
Some fonts, like Symbol, may not define this attribute.


=head2 ascender

Typically the y-value of the top of the lowercase d.
Some fonts, like Symbol, may not define this attribute.


=head2 descender

Typically the y-value of the bottom of the lowercase p.
Some fonts, like Symbol, may not define this attribute.


=head2 underline_position

Recommended distance from the baseline for positioning underline
strokes. This number is the y coordinate of the center of the stroke.


=head2 underline_thickness

Recommended stroke width for underlining.


=head2 version

Version number of the font.

=head1 METHODS

=head2 new

  $metrics = PostScript::File::Metrics->new($font, [$size, [$encoding]])

You would normally use L<PostScript::File/get_metrics> to construct a
Metrics object (because it can get the C<$encoding> from the
document), but it is possible to construct one directly.

C<$size> is the font size in points, and defaults to 1000.

C<$encoding> is the character encoding used by L</width> and L</wrap>.
Valid choices are C<std>, C<sym>, C<cp1252>, and C<iso-8859-1>.  The
default is C<std>, meaning PostScript's StandardEncoding (unless the
C<$font> is Symbol, which uses C<sym>, meaning PostScript's
SymbolEncoding).  Neither C<std> nor C<sym> does any character set
translation.

The C<auto_hyphen> attribute is always set to true when character
translation is enabled.


=head2 set_auto_hyphen( translate )

If translate is a true value, then C<width> and C<wrap> will do
automatic hyphen-minus translation as described in
L<PostScript::File/"Hyphens and Minus Signs">.


=head2 set_size

  $metrics->set_size($new_size)

This method sets the font size (in points).  This influences the
attributes that concern dimensions and the string width calculations.
It returns the Metrics object, so you can chain to the next method.


=head2 set_wrap_chars

  $metrics->set_wrap_chars($new_chars)

This method (introduced in version 2.11) sets the characters after
which a word can be wrapped.  A line can wrap after any character in
C<$new_chars>, which I<should not> include whitespace.  Whitespace is
always a valid breakpoint.  If C<$new_chars> is omitted or C<undef>,
restores the default wrap characters, which means C<-/> and (if using
cp1252) both en and em dashes.  It returns the Metrics object, so you
can chain to the next method.


=head2 width

  $width = $metrics->width($string, [$already_encoded])

This calculates the width of C<$string> (in points) when displayed in
this font at the current size.  If C<$string> has the UTF8 flag set,
it is translated into the font's encoding.  Otherwise, the C<$string>
is expected to be in the correct character set already.  C<$string>
should not contain newlines.

If optional parameter C<$already_encoded> is true, then C<$string> is
assumed to be already encoded in the document's character set.  This
also prevents any hyphen-minus processing.


=head2 wrap

  @lines = $metrics->wrap($width, $text, [\%param])

This wraps C<$text> into lines of no more than C<$width> points.  If
C<$text> contains newlines, they will also cause line breaks.  If
C<$text> has the UTF8 flag set, it is translated into the font's
encoding.  Otherwise, the C<$text> is expected to be in the correct
character set already.

If the C<auto_hyphen> attribute is true, then any HYPHEN-MINUS
(U+002D) characters in C<$text> will be converted to either HYPHEN
(U+2010) or MINUS SIGN (U+2212) in the returned strings.

The characters after which a line can wrap (other than space and tab,
which are always valid line breaks) can be set with the
C<set_wrap_chars> method.  In addition, C<$text> may contain ZERO
WIDTH SPACE (U+200B) characters to indicate potential line breaks.
All ZWSP characters and CRs will be removed from the returned strings.
C<$text> may also contain NO-BREAK SPACE (U+00A0) characters, which
indicate whitespace without a potential line break.

The optional C<\%param> (introduced in version 2.11) allows additional
control over the wrapping.  It may contain the following keys:

=over

=item chars

This overrides the line-breaking characters normally set by the
C<set_wrap_chars> method.  The value has the same meaning as for
C<set_wrap_chars>.

=item maxlines

The maximum number of lines to return.  The final line will contain
all the remaining text, even if that exceeds C<$width> or contains
newline characters.

=item quiet

If true, do not warn about words that are too wide to fit in the
specified C<$width>.

=item warnings

If present, must be an arrayref.  Warning messages about words that
are too wide to fit in the specified C<$width> will be pushed onto the
array.  You should also pass S<C<< quiet => 1 >>> if you don't want
the warnings printed to STDERR.

=back

=head1 CONFIGURATION AND ENVIRONMENT

PostScript::File::Metrics requires no configuration files or environment variables.

=head1 INCOMPATIBILITIES

None reported.

=head1 BUGS AND LIMITATIONS

No bugs have been reported.

=head1 AUTHOR

Christopher J. Madsen  S<C<< <perl AT cjmweb.net> >>>

Please report any bugs or feature requests
to S<C<< <bug-PostScript-File AT rt.cpan.org> >>>
or through the web interface at
L<< http://rt.cpan.org/Public/Bug/Report.html?Queue=PostScript-File >>.

You can follow or contribute to PostScript-File's development at
L<< http://github.com/madsen/postscript-file >>.

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2012 by Christopher J. Madsen.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=head1 DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

=cut