diff options
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-src/t1lint/t1lint.cc')
-rw-r--r-- | Build/source/texk/lcdf-typetools/lcdf-typetools-src/t1lint/t1lint.cc | 450 |
1 files changed, 0 insertions, 450 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/t1lint/t1lint.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-src/t1lint/t1lint.cc deleted file mode 100644 index 1d5c6363f65..00000000000 --- a/Build/source/texk/lcdf-typetools/lcdf-typetools-src/t1lint/t1lint.cc +++ /dev/null @@ -1,450 +0,0 @@ -/* t1lint.cc -- driver for checking Type 1 fonts for validity - * - * Copyright (c) 1999-2019 Eddie Kohler - * - * This program 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 of the License, or (at your option) - * any later version. 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 the GNU General - * Public License for more details. - */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif -#include <efont/psres.hh> -#include <efont/t1rw.hh> -#include <efont/t1font.hh> -#include <efont/t1item.hh> -#include <efont/t1mm.hh> -#include "cscheck.hh" -#include <lcdf/clp.h> -#include <lcdf/error.hh> -#include <stdlib.h> -#include <string.h> -#include <stdio.h> -#include <stdarg.h> -#include <ctype.h> -#include <errno.h> -#ifdef HAVE_CTIME -# include <time.h> -#endif -#if defined(_MSDOS) || defined(_WIN32) -# include <fcntl.h> -# include <io.h> -#endif - -using namespace Efont; - -#define VERSION_OPT 301 -#define HELP_OPT 302 -#define QUIET_OPT 303 - -const Clp_Option options[] = { - { "help", 'h', HELP_OPT, 0, 0 }, - { "quiet", 'q', QUIET_OPT, 0, Clp_Negate }, - { "version", 0, VERSION_OPT, 0, 0 }, -}; - - -static const char *program_name; - - -void -usage_error(ErrorHandler *errh, const char *error_message, ...) -{ - va_list val; - va_start(val, error_message); - if (!error_message) - errh->message("Usage: %s [OPTION]... FONT", program_name); - else - errh->xmessage(ErrorHandler::e_error, error_message, val); - errh->message("Type %s --help for more information.", program_name); - exit(1); -} - -void -usage() -{ - FileErrorHandler uerrh(stdout); - uerrh.message("\ -%<T1lint%> checks a PostScript Type 1 font for correctness. Any errors or\n\ -divergences from the specification are reported to standard error. Nothing is\n\ -printed for correct fonts. The command exits with status 0 if there are no\n\ -errors, and status 1 otherwise.\n\ -\n\ -Usage: %s [OPTION]... FONT [...]\n\ -\n\ -Each FONT is the name of a PFA or PFB font file.\n\ -\n\ -Options:\n\ - -h, --help Print this message and exit.\n\ - -q, --quiet Do not report errors to standard error.\n\ - --version Print version number and exit.\n\ -\n\ -Report bugs to <ekohler@gmail.com>.\n", program_name); -} - - -/***** - * CHECKS - **/ - -static bool -get_num_array(Type1Font *font, int dictionary, const char *name, - Vector<double> &v, ErrorHandler *errh, bool mandatory = false) -{ - if (Type1Definition *d = font->dict(dictionary, name)) { - if (d->value_numvec(v)) - return true; - errh->error("%s not an array of numbers", name); - v.clear(); - } else if (mandatory) - errh->error("%s not defined", name); - return false; -} - -static bool -get_integer(Type1Font *font, int dictionary, const char *name, - int &v, ErrorHandler *errh, bool mandatory = false) -{ - Type1Definition *d = font->dict(dictionary, name); - double scratch; - if (d && d->value_int(v)) - return true; - else if (d && d->value_num(scratch)) { - errh->warning("%s not an integer", name); - v = (int)scratch; - return true; - } else if (d) - errh->error("%s not a number", name); - else if (mandatory) - errh->error("%s not defined", name); - return false; -} - -// BLUES - -static void -check_blue_array(Vector<double> &blues, const char *name, double BlueScale, - ErrorHandler *errh) -{ - if (blues.size() % 2 != 0) { - errh->error("%s has an odd number of entries", name); - blues.push_back(blues.back()); - } - - for (int i = 0; i < blues.size(); i++) - if (blues[i] != (double)((int)blues[i])) { - errh->warning("some %s entries are not integers", name); - break; - } - - double max_diff = 1 / BlueScale; - for (int i = 0; i < blues.size(); i += 2) { - if (blues[i] > blues[i+1]) - errh->error("%s zone %d in the wrong order", name, i/2); - else if (blues[i+1] - blues[i] >= max_diff) - errh->error("%s zone %d too large in relation to BlueScale (size %g, max %g [%g])", name, i/2, blues[i+1] - blues[i], max_diff, BlueScale); - } -} - -static void -check_blue_overlap(Vector<double> &bl1, const char *name1, - Vector<double> &bl2, const char *name2, int BlueFuzz, - ErrorHandler *errh) -{ - int min_fuzz = 2*BlueFuzz + 1; - for (int i = 2; i < bl1.size(); i += 2) { - int thresh = (&bl1 == &bl2 ? i : bl2.size()); - for (int j = 0; j < thresh; j += 2) { - if ((bl2[j] >= bl1[i] && bl2[j] <= bl1[i+1]) - || (bl2[j+1] >= bl1[i] && bl2[j+1] <= bl1[i+1])) - errh->error("%s zone %d and %s zone %d overlap", - name1, i/2, name2, j/2); - else if ((bl2[j] >= bl1[i+1] && bl2[j] < bl1[i+1]+min_fuzz) - || (bl2[j+1] <= bl1[i] && bl2[j+1]+min_fuzz > bl1[i])) - errh->error("%s zone %d and %s zone %d overlap within BlueFuzz", - name1, i/2, name2, j/2); - } - } -} - -static void -check_blues(Type1Font *font, ErrorHandler *errh) -{ - Type1Definition *d; - - // BlueScale - double BlueScale; - bool ok = false; - if ((d = font->p_dict("BlueScale"))) { - if (!d->value_num(BlueScale)) - errh->error("BlueScale not a real number"); - else if (BlueScale <= 0) - errh->error("BlueScale less than or equal to 0"); - else { - if (BlueScale > 0.5) - errh->error("suspiciously large BlueScale (%g)", BlueScale); - ok = true; - } - } - if (!ok) BlueScale = 0.039625; - - // BlueShift - int BlueShift = -1; - if (get_integer(font, Type1Font::dP, "BlueShift", BlueShift, errh) - && BlueShift < 0) - errh->error("BlueShift less than 0"); - if (BlueShift < 0) - BlueShift = 7; - - // BlueFuzz - int BlueFuzz = -1; - if (get_integer(font, Type1Font::dP, "BlueFuzz", BlueFuzz, errh) - && BlueFuzz < 0) - errh->error("BlueFuzz less than 0"); - if (BlueFuzz < 0) - BlueFuzz = 1; - else if (BlueFuzz > 10) - errh->warning("suspiciously large BlueFuzz (%d)", BlueFuzz); - - // BlueValues - Vector<double> BlueValues, OtherBlues; - get_num_array(font, Type1Font::dP, "BlueValues", BlueValues, errh, true); - get_num_array(font, Type1Font::dP, "OtherBlues", OtherBlues, errh); - - check_blue_array(BlueValues, "BlueValues", BlueScale, errh); - if (BlueValues.size() > 14) - errh->error("too many zones in BlueValues (max 7)"); - check_blue_array(OtherBlues, "OtherBlues", BlueScale, errh); - if (OtherBlues.size() > 10) - errh->error("too many zones in OtherBlues (max 5)"); - - check_blue_overlap(BlueValues, "BlueValues", BlueValues, "BlueValues", BlueFuzz, errh); - check_blue_overlap(OtherBlues, "OtherBlues", OtherBlues, "OtherBlues", BlueFuzz, errh); - check_blue_overlap(BlueValues, "BlueValues", OtherBlues, "OtherBlues", BlueFuzz, errh); - - // FamilyBlues - Vector<double> FamilyBlues, FamilyOtherBlues; - get_num_array(font, Type1Font::dP, "FamilyBlues", FamilyBlues, errh); - get_num_array(font, Type1Font::dP, "FamilyOtherBlues", FamilyOtherBlues, errh); - - check_blue_array(FamilyBlues, "FamilyBlues", BlueScale, errh); - if (FamilyBlues.size() > 14) - errh->error("too many zones in FamilyBlues (max 7)"); - check_blue_array(FamilyOtherBlues, "FamilyOtherBlues", BlueScale, errh); - if (FamilyOtherBlues.size() > 10) - errh->error("too many zones in FamilyOtherBlues (max 5)"); - - check_blue_overlap(FamilyBlues, "FamilyBlues", FamilyBlues, "FamilyBlues", BlueFuzz, errh); - check_blue_overlap(FamilyOtherBlues, "FamilyOtherBlues", FamilyOtherBlues, "FamilyOtherBlues", BlueFuzz, errh); - check_blue_overlap(FamilyBlues, "FamilyBlues", FamilyOtherBlues, "FamilyOtherBlues", BlueFuzz, errh); -} - - -// STEMS - -void -check_stem_snap(Vector<double> &stem_snap, double main, bool is_v, - ErrorHandler *errh) -{ - const char *name = (is_v ? "V" : "H"); - if (stem_snap.size() > 12) - errh->error("StemSnap%s has more than 12 entries", name); - for (int i = 0; i < stem_snap.size() - 1; i++) - if (stem_snap[i] >= stem_snap[i+1]) { - errh->error("StemSnap%s is not sorted in increasing order", name); - break; - } - for (int i = 0; i < stem_snap.size(); i++) - if (stem_snap[i] == main) - return; - if (main >= 0) - errh->warning("Std%sW not in StemSnap%s array", name, name); -} - -void -check_stems(Type1Font *font, ErrorHandler *errh) -{ - Vector<double> StdHW, StdVW, StemSnapH, StemSnapV; - if (get_num_array(font, Type1Font::dP, "StdHW", StdHW, errh)) { - if (StdHW.size() != 1) - errh->error("StdHW has %d entries (exactly one required)", StdHW.size()); - if (StdHW.size() > 0 && StdHW[0] <= 0) - errh->error("StdHW entry less than or equal to 0"); - } - if (get_num_array(font, Type1Font::dP, "StdVW", StdVW, errh)) { - if (StdVW.size() != 1) - errh->error("StdVW has %d entries (exactly one required)", StdVW.size()); - if (StdVW.size() > 0 && StdVW[0] <= 0) - errh->error("StdVW entry less than or equal to 0"); - } - - if (get_num_array(font, Type1Font::dP, "StemSnapH", StemSnapH, errh)) - check_stem_snap(StemSnapH, StdHW.size() ? StdHW[0] : -1000, false, errh); - if (get_num_array(font, Type1Font::dP, "StemSnapV", StemSnapV, errh)) - check_stem_snap(StemSnapV, StdVW.size() ? StdVW[0] : -1000, true, errh); -} - - -// MAIN - -static void -do_file(const char *filename, PsresDatabase *psres, ErrorHandler *errh, - ErrorHandler *err_errh) -{ - FILE *f; - if (strcmp(filename, "-") == 0) { - f = stdin; - filename = "<stdin>"; -#if defined(_MSDOS) || defined(_WIN32) - _setmode(_fileno(f), _O_BINARY); -#endif - } else - f = fopen(filename, "rb"); - - if (!f) { - // check for PostScript name - Filename fn = psres->filename_value("FontOutline", filename); - f = fn.open_read(); - } - - if (!f) - err_errh->fatal("%s: %s", filename, strerror(errno)); - - Type1Reader *reader; - int c = getc(f); - ungetc(c, f); - if (c == EOF) - err_errh->fatal("%s: empty file", filename); - if (c == 128) - reader = new Type1PFBReader(f); - else - reader = new Type1PFAReader(f); - - Type1Font *font = new Type1Font(*reader); - - if (font) { - LandmarkErrorHandler cerrh(errh, filename); - - // check UniqueID values - int UniqueID = -1, UniqueID2 = -1; - if (get_integer(font, Type1Font::dF, "UniqueID", UniqueID, errh) - && (UniqueID < 0 || UniqueID > 0xFFFFFF)) - cerrh.error("UniqueID not in the range 0-16777215"); - if (get_integer(font, Type1Font::dP, "UniqueID", UniqueID2, errh) - && (UniqueID2 < 0 || UniqueID2 > 0xFFFFFF)) - cerrh.error("Private UniqueID not in the range 0-16777215"); - if (UniqueID >= 0 && UniqueID2 >= 0 && UniqueID != UniqueID2) - cerrh.error("Private UniqueID does not equal font UniqueID"); - - // check XUID values - Vector<double> XUID; - if (get_num_array(font, Type1Font::dF, "XUID", XUID, errh)) { - if (XUID.size() == 0) - cerrh.error("empty XUID"); - for (int i = 0; i < XUID.size(); i++) { - if (floor(XUID[i]) != XUID[i] || XUID[i] < 0 || XUID[i] > 0xFFFFFF) { - cerrh.error("element of XUID not an integer in the range 0-16777215"); - break; - } - } - } - - check_blues(font, &cerrh); - check_stems(font, &cerrh); - - MultipleMasterSpace *mmspace = font->create_mmspace(&cerrh); - Vector<double> weight_vector; - if (mmspace) - weight_vector = mmspace->default_weight_vector(); - int gc = font->nglyphs(); - CharstringChecker cc(weight_vector); - - for (int i = 0; i < gc; i++) { - ContextErrorHandler derrh - (&cerrh, "While interpreting %<%s%>:", font->glyph_name(i).c_str()); - cc.check(font->glyph_context(i), &derrh); - } - - int ns = font->nsubrs(); - CharstringSubrChecker csc(weight_vector); - for (int i = 0; i < ns; ++i) - if (Type1Charstring *cs = font->subr(i)) { - ContextErrorHandler derrh(&cerrh, "While interpreting subr %d:", i); - CharstringContext cctx(font, cs); - csc.check(cctx, &derrh); - } - } - - delete font; - delete reader; -} - -int -main(int argc, char *argv[]) -{ - PsresDatabase *psres = new PsresDatabase; - psres->add_psres_path(getenv("PSRESOURCEPATH"), 0, false); - - Clp_Parser *clp = - Clp_NewParser(argc, (const char * const *)argv, sizeof(options) / sizeof(options[0]), options); - program_name = Clp_ProgramName(clp); - - ErrorHandler *err_errh = ErrorHandler::static_initialize(new FileErrorHandler(stderr)); - ErrorHandler *out_errh = new FileErrorHandler(stdout); - ErrorHandler *errh = out_errh; - int nfiles = 0; - - while (1) { - int opt = Clp_Next(clp); - switch (opt) { - - case QUIET_OPT: - if (clp->negated) - errh = out_errh; - else - errh = new SilentErrorHandler; - break; - - case VERSION_OPT: - printf("t1lint (LCDF typetools) %s\n", VERSION); - printf("Copyright (C) 1999-2019 Eddie Kohler\n\ -This is free software; see the source for copying conditions.\n\ -There is NO warranty, not even for merchantability or fitness for a\n\ -particular purpose.\n"); - exit(0); - break; - - case HELP_OPT: - usage(); - exit(0); - break; - - case Clp_NotOption: - do_file(clp->vstr, psres, errh, err_errh); - nfiles++; - break; - - case Clp_Done: - goto done; - - case Clp_BadOption: - usage_error(err_errh, 0); - break; - - default: - break; - - } - } - - done: - if (nfiles == 0) - do_file("-", psres, errh, err_errh); - - return (errh->nerrors() == 0 ? 0 : 1); -} |