diff options
Diffstat (limited to 'contrib/groff/hpftodit/hpftodit.cc')
-rw-r--r-- | contrib/groff/hpftodit/hpftodit.cc | 812 |
1 files changed, 0 insertions, 812 deletions
diff --git a/contrib/groff/hpftodit/hpftodit.cc b/contrib/groff/hpftodit/hpftodit.cc deleted file mode 100644 index 2e5978c..0000000 --- a/contrib/groff/hpftodit/hpftodit.cc +++ /dev/null @@ -1,812 +0,0 @@ -// -*- C++ -*- -/* Copyright (C) 1994 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 2, 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 groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - -/* -TODO -put human readable font name in device file -devise new names for useful characters -use --- for unnamed characters -option to specify symbol sets to look in -make it work with TrueType fonts -put filename in error messages (or fix lib) -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <math.h> -#include <string.h> -#include <errno.h> -#include "assert.h" -#include "lib.h" -#include "posix.h" -#include "errarg.h" -#include "error.h" -#include "cset.h" -#include "nonposix.h" - -#define SIZEOF(v) (sizeof(v)/sizeof(v[0])) - -const int MULTIPLIER = 3; - -inline -int scale(int n) -{ - return n * MULTIPLIER; -} - -// tags in TFM file - -enum tag_type { - min_tag = 400, - type_tag = 400, - symbol_set_tag = 404, - msl_tag = 403, - inches_per_point_tag = 406, - design_units_per_em_tag = 408, - posture_tag = 409, - stroke_weight_tag = 411, - spacing_tag = 412, - slant_tag = 413, - appearance_width_tag = 414, - word_spacing_tag = 421, - x_height_tag = 424, - lower_ascent_tag = 427, - lower_descent_tag = 428, - width_tag = 433, - left_extent_tag = 435, - right_extent_tag = 436, - ascent_tag = 437, - descent_tag = 438, - pair_kern_tag = 439, - typeface_tag = 442, - max_tag = 443 - }; - -// types in TFM file - -enum { - ENUM_TYPE = 1, - BYTE_TYPE = 2, - USHORT_TYPE = 3, - FLOAT_TYPE = 5, - SIGNED_SHORT_TYPE = 17 - }; - - -typedef unsigned char byte; -typedef unsigned short uint16; -typedef short int16; -typedef unsigned int uint32; - -class File { -public: - File(const char *); - void skip(int n); - byte get_byte(); - uint16 get_uint16(); - uint32 get_uint32(); - void seek(uint32 n); -private: - unsigned char *buf_; - const unsigned char *ptr_; - const unsigned char *end_; -}; - -struct entry { - char present; - uint16 type; - uint32 count; - uint32 value; - entry() : present(0) { } -}; - -struct char_info { - uint16 msl; - uint16 width; - uint16 ascent; - int16 descent; - int16 left_extent; - uint16 right_extent; - uint16 symbol_set; - unsigned char code; -}; - -const uint16 NO_SYMBOL_SET = 0; - -struct name_list { - char *name; - name_list *next; - name_list(const char *s, name_list *p) : name(strsave(s)), next(p) { } - ~name_list() { a_delete name; } -}; - -struct symbol_set { - uint16 select; - uint16 index[256]; -}; - -#define SYMBOL_SET(n, c) ((n) * 32 + ((c) - 64)) - -uint16 text_symbol_sets[] = { - SYMBOL_SET(0, 'N'), // Latin 1 - SYMBOL_SET(6, 'J'), // Microsoft Publishing - SYMBOL_SET(2, 'N'), // Latin 2 - 0 - }; - -uint16 special_symbol_sets[] = { - SYMBOL_SET(8, 'M'), - SYMBOL_SET(5, 'M'), - SYMBOL_SET(15, 'U'), - 0 - }; - -entry tags[max_tag + 1 - min_tag]; - -char_info *char_table; -uint32 nchars; - -int msl_name_table_size = 0; -name_list **msl_name_table = 0; - -int n_symbol_sets; -symbol_set *symbol_set_table; - -static int special_flag = 0; -static int italic_flag = 0; -static int italic_sep; - -static void usage(); -static const char *xbasename(const char *); -static void read_tags(File &); -static void check_type(); -static void check_units(File &); -static int read_map(const char *); -static void require_tag(tag_type); -static void dump_tags(File &f); -static void output_spacewidth(); -static void output_pclweight(); -static void output_pclproportional(); -static void read_and_output_pcltypeface(File &); -static void output_pclstyle(); -static void output_slant(); -static void output_ligatures(); -static void read_symbol_sets(File &); -static void read_and_output_kernpairs(File &); -static void output_charset(); -static void read_char_table(File &f); - -inline -entry &tag_info(tag_type t) -{ - return tags[t - min_tag]; -} - -int main(int argc, char **argv) -{ - program_name = argv[0]; - - int opt; - int debug_flag = 0; - - while ((opt = getopt(argc, argv, "dsvi:")) != EOF) { - switch (opt) { - case 'd': - debug_flag = 1; - break; - case 's': - special_flag = 1; - break; - case 'i': - italic_flag = 1; - italic_sep = atoi(optarg); - break; - case 'v': - { - extern const char *Version_string; - fprintf(stderr, "hpftodit version %s\n", Version_string); - fflush(stderr); - break; - } - break; - case '?': - usage(); - default: - assert(0); - } - } - if (argc - optind != 3) - usage(); - File f(argv[optind]); - if (!read_map(argv[optind + 1])) - exit(1); - current_filename = 0; - current_lineno = -1; // no line numbers - if (freopen(argv[optind + 2], "w", stdout) == 0) - fatal("cannot open `%1': %2", argv[optind + 2], strerror(errno)); - current_filename = argv[optind]; - printf("name %s\n", xbasename(argv[optind + 2])); - if (special_flag) - printf("special\n"); - read_tags(f); - check_type(); - check_units(f); - if (debug_flag) - dump_tags(f); - read_char_table(f); - output_spacewidth(); - output_slant(); - read_and_output_pcltypeface(f); - output_pclproportional(); - output_pclweight(); - output_pclstyle(); - read_symbol_sets(f); - output_ligatures(); - read_and_output_kernpairs(f); - output_charset(); - return 0; -} - -static -void usage() -{ - fprintf(stderr, "usage: %s [-s] [-i n] tfm_file map_file output_font\n", - program_name); - exit(1); -} - -File::File(const char *s) -{ - // We need to read the file in binary mode because hpftodit relies - // on byte counts. - int fd = open(s, O_RDONLY | O_BINARY); - if (fd < 0) - fatal("cannot open `%1': %2", s, strerror(errno)); - current_filename = s; - struct stat sb; - if (fstat(fd, &sb) < 0) - fatal("cannot stat: %1", strerror(errno)); - if (!S_ISREG(sb.st_mode)) - fatal("not a regular file"); - buf_ = new unsigned char[sb.st_size]; - long nread = read(fd, buf_, sb.st_size); - if (nread < 0) - fatal("read error: %1", strerror(errno)); - if (nread != sb.st_size) - fatal("read unexpected number of bytes"); - ptr_ = buf_; - end_ = buf_ + sb.st_size; - // These are actually text files, so we must get rid of the `\r' - // characters. This is also enabled for Posix systems, in case the - // input came from Windows... - unsigned char *p = buf_, *q = buf_; - while (q < end_) - { - if (*q == '\r') - { - if (*++q != '\n') - *p++ = '\r'; - } -#if defined(__MSDOS__) || defined(_MSC_VER) - if (*q == '\032') // ^Z means ``software EOF'' - break; -#endif - *p++ = *q++; - } - end_ = p; -} - -void File::skip(int n) -{ - if (end_ - ptr_ < n) - fatal("unexpected end of file"); - ptr_ += n; -} - -void File::seek(uint32 n) -{ - if (end_ - buf_ < n) - fatal("unexpected end of file"); - ptr_ = buf_ + n; -} - -byte File::get_byte() -{ - if (ptr_ >= end_) - fatal("unexpected end of file"); - return *ptr_++; -} - -uint16 File::get_uint16() -{ - if (end_ - ptr_ < 2) - fatal("unexpected end of file"); - uint16 n = *ptr_++; - return n + (*ptr_++ << 8); -} - -uint32 File::get_uint32() -{ - if (end_ - ptr_ < 4) - fatal("unexpected end of file"); - uint32 n = *ptr_++; - for (int i = 0; i < 3; i++) - n += *ptr_++ << (i + 1)*8; - return n; -} - -static -void read_tags(File &f) -{ - if (f.get_byte() != 'I' || f.get_byte() != 'I') - fatal("not an Intel format TFM file"); - f.skip(6); - uint16 ntags = f.get_uint16(); - entry dummy; - for (uint16 i = 0; i < ntags; i++) { - uint16 tag = f.get_uint16(); - entry *p; - if (min_tag <= tag && tag <= max_tag) - p = tags + (tag - min_tag); - else - p = &dummy; - p->present = 1; - p->type = f.get_uint16(); - p->count = f.get_uint32(); - p->value = f.get_uint32(); - } -} - -static -void check_type() -{ - require_tag(type_tag); - if (tag_info(type_tag).value != 0) { - if (tag_info(type_tag).value == 2) - fatal("cannot handle TrueType tfm files"); - fatal("unknown type tag %1", int(tag_info(type_tag).value)); - } -} - -static -void check_units(File &f) -{ - require_tag(design_units_per_em_tag); - f.seek(tag_info(design_units_per_em_tag).value); - uint32 num = f.get_uint32(); - uint32 den = f.get_uint32(); - if (num != 8782 || den != 1) - fatal("design units per em != 8782/1"); - require_tag(inches_per_point_tag); - f.seek(tag_info(inches_per_point_tag).value); - num = f.get_uint32(); - den = f.get_uint32(); - if (num != 100 || den != 7231) - fatal("inches per point not 100/7231"); -} - -static -void require_tag(tag_type t) -{ - if (!tag_info(t).present) - fatal("tag %1 missing", int(t)); -} - -static -void output_spacewidth() -{ - require_tag(word_spacing_tag); - printf("spacewidth %d\n", scale(tag_info(word_spacing_tag).value)); -} - -static -void read_symbol_sets(File &f) -{ - uint32 symbol_set_dir_length = tag_info(symbol_set_tag).count; - n_symbol_sets = symbol_set_dir_length/14; - symbol_set_table = new symbol_set[n_symbol_sets]; - int i; - for (i = 0; i < n_symbol_sets; i++) { - f.seek(tag_info(symbol_set_tag).value + i*14); - (void)f.get_uint32(); - uint32 off1 = f.get_uint32(); - uint32 off2 = f.get_uint32(); - (void)f.get_uint16(); // what's this for? - f.seek(off1); - int j; - uint16 kind = 0; - for (j = 0; j < off2 - off1; j++) { - unsigned char c = f.get_byte(); - if ('0' <= c && c <= '9') - kind = kind*10 + (c - '0'); - else if ('A' <= c && c <= 'Z') - kind = kind*32 + (c - 64); - } - symbol_set_table[i].select = kind; - for (j = 0; j < 256; j++) - symbol_set_table[i].index[j] = f.get_uint16(); - } - for (i = 0; i < nchars; i++) - char_table[i].symbol_set = NO_SYMBOL_SET; - - uint16 *symbol_set_selectors = (special_flag - ? special_symbol_sets - : text_symbol_sets); - for (i = 0; symbol_set_selectors[i] != 0; i++) { - int j; - for (j = 0; j < n_symbol_sets; j++) - if (symbol_set_table[j].select == symbol_set_selectors[i]) - break; - if (j < n_symbol_sets) { - for (int k = 0; k < 256; k++) { - uint16 index = symbol_set_table[j].index[k]; - if (index != 0xffff - && char_table[index].symbol_set == NO_SYMBOL_SET) { - char_table[index].symbol_set = symbol_set_table[j].select; - char_table[index].code = k; - } - } - } - } -} - -static -void read_char_table(File &f) -{ - require_tag(msl_tag); - nchars = tag_info(msl_tag).count; - char_table = new char_info[nchars]; - - f.seek(tag_info(msl_tag).value); - uint32 i; - for (i = 0; i < nchars; i++) - char_table[i].msl = f.get_uint16(); - - require_tag(width_tag); - f.seek(tag_info(width_tag).value); - for (i = 0; i < nchars; i++) - char_table[i].width = f.get_uint16(); - - require_tag(ascent_tag); - f.seek(tag_info(ascent_tag).value); - for (i = 0; i < nchars; i++) { - char_table[i].ascent = f.get_uint16(); - } - - require_tag(descent_tag); - f.seek(tag_info(descent_tag).value); - for (i = 0; i < nchars; i++) { - char_table[i].descent = f.get_uint16(); - if (char_table[i].descent > 0) - char_table[i].descent = 0; - } - - require_tag(left_extent_tag); - f.seek(tag_info(left_extent_tag).value); - for (i = 0; i < nchars; i++) - char_table[i].left_extent = int16(f.get_uint16()); - - require_tag(right_extent_tag); - f.seek(tag_info(right_extent_tag).value); - for (i = 0; i < nchars; i++) - char_table[i].right_extent = f.get_uint16(); -} - -static -void output_pclweight() -{ - require_tag(stroke_weight_tag); - int stroke_weight = tag_info(stroke_weight_tag).value; - int pcl_stroke_weight; - if (stroke_weight < 128) - pcl_stroke_weight = -3; - else if (stroke_weight == 128) - pcl_stroke_weight = 0; - else if (stroke_weight <= 145) - pcl_stroke_weight = 1; - else if (stroke_weight <= 179) - pcl_stroke_weight = 3; - else - pcl_stroke_weight = 4; - printf("pclweight %d\n", pcl_stroke_weight); -} - -static -void output_pclproportional() -{ - require_tag(spacing_tag); - printf("pclproportional %d\n", tag_info(spacing_tag).value == 0); -} - -static -void read_and_output_pcltypeface(File &f) -{ - printf("pcltypeface "); - require_tag(typeface_tag); - f.seek(tag_info(typeface_tag).value); - for (uint32 i = 0; i < tag_info(typeface_tag).count; i++) { - unsigned char c = f.get_byte(); - if (c == '\0') - break; - putchar(c); - } - printf("\n"); -} - -static -void output_pclstyle() -{ - unsigned pcl_style = 0; - // older tfms don't have the posture tag - if (tag_info(posture_tag).present) { - if (tag_info(posture_tag).value) - pcl_style |= 1; - } - else { - require_tag(slant_tag); - if (tag_info(slant_tag).value != 0) - pcl_style |= 1; - } - require_tag(appearance_width_tag); - if (tag_info(appearance_width_tag).value < 100) // guess - pcl_style |= 4; - printf("pclstyle %d\n", pcl_style); -} - -static -void output_slant() -{ - require_tag(slant_tag); - int slant = int16(tag_info(slant_tag).value); - if (slant != 0) - printf("slant %f\n", slant/100.0); -} - -static -void output_ligatures() -{ - // don't use ligatures for fixed space font - require_tag(spacing_tag); - if (tag_info(spacing_tag).value != 0) - return; - static const char *ligature_names[] = { - "fi", "fl", "ff", "ffi", "ffl" - }; - - static const char *ligature_chars[] = { - "fi", "fl", "ff", "Fi", "Fl" - }; - - unsigned ligature_mask = 0; - int i; - for (i = 0; i < nchars; i++) { - uint16 msl = char_table[i].msl; - if (msl < msl_name_table_size - && char_table[i].symbol_set != NO_SYMBOL_SET) { - for (name_list *p = msl_name_table[msl]; p; p = p->next) - for (int j = 0; j < SIZEOF(ligature_chars); j++) - if (strcmp(p->name, ligature_chars[j]) == 0) { - ligature_mask |= 1 << j; - break; - } - } - } - if (ligature_mask) { - printf("ligatures"); - for (i = 0; i < SIZEOF(ligature_names); i++) - if (ligature_mask & (1 << i)) - printf(" %s", ligature_names[i]); - printf(" 0\n"); - } -} - -static -void read_and_output_kernpairs(File &f) -{ - if (tag_info(pair_kern_tag).present) { - printf("kernpairs\n"); - f.seek(tag_info(pair_kern_tag).value); - uint16 n_pairs = f.get_uint16(); - for (int i = 0; i < n_pairs; i++) { - uint16 i1 = f.get_uint16(); - uint16 i2 = f.get_uint16(); - int16 val = int16(f.get_uint16()); - if (char_table[i1].symbol_set != NO_SYMBOL_SET - && char_table[i2].symbol_set != NO_SYMBOL_SET - && char_table[i1].msl < msl_name_table_size - && char_table[i2].msl < msl_name_table_size) { - for (name_list *p = msl_name_table[char_table[i1].msl]; - p; - p = p->next) - for (name_list *q = msl_name_table[char_table[i2].msl]; - q; - q = q->next) - printf("%s %s %d\n", p->name, q->name, scale(val)); - } - } - } -} - -static -void output_charset() -{ - require_tag(slant_tag); - double slant_angle = int16(tag_info(slant_tag).value)*PI/18000.0; - double slant = sin(slant_angle)/cos(slant_angle); - - require_tag(x_height_tag); - require_tag(lower_ascent_tag); - require_tag(lower_descent_tag); - - printf("charset\n"); - int i; - for (i = 0; i < nchars; i++) { - uint16 msl = char_table[i].msl; - if (msl < msl_name_table_size - && msl_name_table[msl]) { - if (char_table[i].symbol_set != NO_SYMBOL_SET) { - printf("%s\t%d,%d", - msl_name_table[msl]->name, - scale(char_table[i].width), - scale(char_table[i].ascent)); - int depth = scale(- char_table[i].descent); - if (depth < 0) - depth = 0; - int italic_correction = 0; - int left_italic_correction = 0; - int subscript_correction = 0; - if (italic_flag) { - italic_correction = scale(char_table[i].right_extent - - char_table[i].width - + italic_sep); - if (italic_correction < 0) - italic_correction = 0; - subscript_correction = int((tag_info(x_height_tag).value - * slant * .8) + .5); - if (subscript_correction > italic_correction) - subscript_correction = italic_correction; - left_italic_correction = scale(italic_sep - - char_table[i].left_extent); - } - if (subscript_correction != 0) - printf(",%d,%d,%d,%d", - depth, italic_correction, left_italic_correction, - subscript_correction); - else if (left_italic_correction != 0) - printf(",%d,%d,%d", depth, italic_correction, left_italic_correction); - else if (italic_correction != 0) - printf(",%d,%d", depth, italic_correction); - else if (depth != 0) - printf(",%d", depth); - // This is fairly arbitrary. Fortunately it doesn't much matter. - unsigned type = 0; - if (char_table[i].ascent > (tag_info(lower_ascent_tag).value*9)/10) - type |= 2; - if (char_table[i].descent < (int16(tag_info(lower_descent_tag).value)*9)/10) - type |= 1; - printf("\t%d\t%d\n", - type, - char_table[i].symbol_set*256 + char_table[i].code); - for (name_list *p = msl_name_table[msl]->next; p; p = p->next) - printf("%s\t\"\n", p->name); - } - else - warning("MSL %1 not in any of the searched symbol sets", msl); - } - } -} - -static -void dump_tags(File &f) -{ - int i; - for (i = min_tag; i <= max_tag; i++) { - enum tag_type t = tag_type(i); - if (tag_info(t).present) { - fprintf(stderr, - "%d %d %d %d\n", i, tag_info(t).type, tag_info(t).count, - tag_info(t).value); - if (tag_info(t).type == FLOAT_TYPE - && tag_info(t).count == 1) { - f.seek(tag_info(t).value); - uint32 num = f.get_uint32(); - uint32 den = f.get_uint32(); - fprintf(stderr, "(%u/%u = %g)\n", num, den, (double)num/den); - } - } - } -} - -static -int read_map(const char *file) -{ - errno = 0; - FILE *fp = fopen(file, "r"); - if (!fp) { - error("can't open `%1': %2", file, strerror(errno)); - return 0; - } - current_filename = file; - char buf[512]; - current_lineno = 0; - while (fgets(buf, int(sizeof(buf)), fp)) { - current_lineno++; - char *ptr = buf; - while (csspace(*ptr)) - ptr++; - if (*ptr == '\0' || *ptr == '#') - continue; - ptr = strtok(ptr, " \n\t"); - if (!ptr) - continue; - int n; - if (sscanf(ptr, "%d", &n) != 1) { - error("bad map file"); - fclose(fp); - return 0; - } - if (n < 0) { - error("negative code"); - fclose(fp); - return 0; - } - if (n >= msl_name_table_size) { - size_t old_size = msl_name_table_size; - name_list **old_table = msl_name_table; - msl_name_table_size = n + 256; - msl_name_table = new name_list *[msl_name_table_size]; - if (old_table) { - memcpy(msl_name_table, old_table, old_size*sizeof(name_list *)); - a_delete old_table; - } - for (size_t i = old_size; i < msl_name_table_size; i++) - msl_name_table[i] = 0; - } - ptr = strtok(0, " \n\t"); - if (!ptr) { - error("missing names"); - fclose(fp); - return 0; - } - for (; ptr; ptr = strtok(0, " \n\t")) - msl_name_table[n] = new name_list(ptr, msl_name_table[n]); - } - fclose(fp); - return 1; -} - -static -const char *xbasename(const char *s) -{ - // DIR_SEPS[] are possible directory separator characters, see - // nonposix.h. We want the rightmost separator of all possible - // ones. Example: d:/foo\\bar. - const char *b = strrchr(s, DIR_SEPS[0]), *b1; - const char *sep = &DIR_SEPS[1]; - - while (*sep) - { - b1 = strrchr(s, *sep); - if (b1 && (!b || b1 > b)) - b = b1; - sep++; - } - return b ? b + 1 : s; -} |