#!@PERL@
# Copyright (C) 1989-2020 Free Software Foundation, Inc.
# Written by James Clark (jjc@jclark.com)
#
# This file is part of groff.
#
# groff is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# groff 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 General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
use warnings;
use strict;
@afmtodit.tables@
my $prog = $0;
my $groff_sys_fontdir = "@FONTDIR@";
my $want_help;
my $space_width = 0;
our ($opt_a, $opt_c, $opt_d, $opt_e, $opt_f, $opt_i, $opt_k,
$opt_m, $opt_n, $opt_o, $opt_s, $opt_v, $opt_x);
use Getopt::Long qw(:config gnu_getopt);
GetOptions( "a=s", "c", "d=s", "e=s", "f=s", "i=s", "k", "m", "n",
"o=s", "s", "v", "w=i" => \$space_width, "x", "version" => \$opt_v,
"help" => \$want_help
);
my $afmtodit_version = "GNU afmtodit (groff) version @VERSION@";
if ($opt_v) {
print "$afmtodit_version\n";
exit 0;
}
sub croak {
my $msg = shift;
print STDERR "$prog: error: $msg";
exit(1);
}
sub usage {
my $stream = *STDOUT;
my $had_error = shift;
$stream = *STDERR if $had_error;
print $stream "usage: $prog [-ckmnsx] [-a slant]" .
" [-d device-description-file] [-e encoding-file]" .
" [-f internal-name] [-i italic-correction-factor]" .
" [-o output-file] [-w space-width] afm-file map-file" .
" font-description-file\n" .
"usage: $prog {-v | --version}\n" .
"usage: $prog --help\n";
unless ($had_error) {
print $stream "\n" .
"Adapt an Adobe Font Metric file, afm-file, for use with the 'ps'\n" .
"and 'pdf' output devices of groff(1). See the afmtodit(1) manual " .
"page.\n";
}
my $status = 0;
$status = 2 if ($had_error);
exit($status);
}
&usage(0) if ($want_help);
if ($#ARGV != 2) {
print STDERR "$prog: usage error: insufficient arguments\n";
&usage(1);
}
my $afm = $ARGV[0];
my $map = $ARGV[1];
my $fontfile = $ARGV[2];
my $outfile = $opt_o || $fontfile;
my $desc = $opt_d || "DESC";
my $sys_map = $groff_sys_fontdir . "/devps/generate/" . $map;
my $sys_desc = $groff_sys_fontdir . "/devps/" . $desc;
# read the afm file
my $psname;
my ($notice, $version, $fullname, $familyname, @comments);
my $italic_angle = 0;
my (@kern1, @kern2, @kernx);
my (%italic_correction, %left_italic_correction);
my %subscript_correction;
# my %ligs
my %ligatures;
my (@encoding, %in_encoding);
my (%width, %height, %depth);
my (%left_side_bearing, %right_side_bearing);
open(AFM, $afm) || croak("unable to open '$ARGV[0]': $!\n");
while () {
chomp;
s/\x0D$//;
my @field = split(' ');
next if $#field < 0;
if ($field[0] eq "FontName") {
$psname = $field[1];
if($opt_f) {
$psname = $opt_f;
}
}
elsif($field[0] eq "Notice") {
$notice = $_;
}
elsif($field[0] eq "Version") {
$version = $_;
}
elsif($field[0] eq "FullName") {
$fullname = $_;
}
elsif($field[0] eq "FamilyName") {
$familyname = $_;
}
elsif($field[0] eq "Comment") {
push(@comments, $_);
}
elsif($field[0] eq "ItalicAngle") {
$italic_angle = -$field[1];
}
elsif ($field[0] eq "KPX") {
if ($#field == 3) {
push(@kern1, $field[1]);
push(@kern2, $field[2]);
push(@kernx, $field[3]);
}
}
elsif ($field[0] eq "italicCorrection") {
$italic_correction{$field[1]} = $field[2];
}
elsif ($field[0] eq "leftItalicCorrection") {
$left_italic_correction{$field[1]} = $field[2];
}
elsif ($field[0] eq "subscriptCorrection") {
$subscript_correction{$field[1]} = $field[2];
}
elsif ($field[0] eq "StartCharMetrics") {
while () {
@field = split(' ');
next if $#field < 0;
last if ($field[0] eq "EndCharMetrics");
if ($field[0] eq "C") {
my $w;
my $wx = 0;
my $n = "";
# %ligs = ();
my $lly = 0;
my $ury = 0;
my $llx = 0;
my $urx = 0;
my $c = $field[1];
my $i = 2;
while ($i <= $#field) {
if ($field[$i] eq "WX") {
$w = $field[$i + 1];
$i += 2;
}
elsif ($field[$i] eq "N") {
$n = $field[$i + 1];
$i += 2;
}
elsif ($field[$i] eq "B") {
$llx = $field[$i + 1];
$lly = $field[$i + 2];
$urx = $field[$i + 3];
$ury = $field[$i + 4];
$i += 5;
}
# elsif ($field[$i] eq "L") {
# $ligs{$field[$i + 2]} = $field[$i + 1];
# $i += 3;
# }
else {
while ($i <= $#field && $field[$i] ne ";") {
$i++;
}
$i++;
}
}
if (!$opt_e && $c != -1) {
$encoding[$c] = $n;
$in_encoding{$n} = 1;
}
$width{$n} = $w;
$height{$n} = $ury;
$depth{$n} = -$lly;
$left_side_bearing{$n} = -$llx;
$right_side_bearing{$n} = $urx - $w;
# foreach my $lig (sort keys %ligs) {
# $ligatures{$lig} = $n . " " . $ligs{$lig};
# }
}
}
}
}
close(AFM);
# read the DESC file
my ($sizescale, $resolution, $unitwidth);
$sizescale = 1;
open(DESC, $desc) || open(DESC, $sys_desc) ||
croak("unable to open '$desc' or '$sys_desc': $!\n");
while () {
next if /^#/;
chop;
my @field = split(' ');
next if $#field < 0;
last if $field[0] eq "charset";
if ($field[0] eq "res") {
$resolution = $field[1];
}
elsif ($field[0] eq "unitwidth") {
$unitwidth = $field[1];
}
elsif ($field[0] eq "sizescale") {
$sizescale = $field[1];
}
}
close(DESC);
if ($opt_e) {
# read the encoding file
my $sys_opt_e = $groff_sys_fontdir . "/devps/" . $opt_e;
open(ENCODING, $opt_e) || open(ENCODING, $sys_opt_e) ||
croak("unable to open '$opt_e' or '$sys_opt_e': $!\n");
while () {
next if /^#/;
chop;
my @field = split(' ');
next if $#field < 0;
if ($#field == 1) {
if ($field[1] >= 0 && defined $width{$field[0]}) {
$encoding[$field[1]] = $field[0];
$in_encoding{$field[0]} = 1;
}
}
}
close(ENCODING);
}
# read the map file
my (%nmap, %map);
open(MAP, $map) || open(MAP, $sys_map) ||
croak("unable to open '$map' or '$sys_map': $!\n");
while (