summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1rawafm/t1rawafm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1rawafm/t1rawafm.cc')
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1rawafm/t1rawafm.cc366
1 files changed, 366 insertions, 0 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1rawafm/t1rawafm.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1rawafm/t1rawafm.cc
new file mode 100644
index 00000000000..84a851227ee
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1rawafm/t1rawafm.cc
@@ -0,0 +1,366 @@
+/* t1rawafm.cc -- driver for generating a raw AFM file from a font
+ *
+ * Copyright (c) 2008-2013 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 <efont/t1interp.hh>
+#include <efont/t1bounds.hh>
+#include <lcdf/clp.h>
+#include <lcdf/error.hh>
+#include <lcdf/globmatch.hh>
+#include <lcdf/transform.hh>
+#include <algorithm>
+#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 OUTPUT_OPT 303
+#define SMOKE_OPT 305
+
+const Clp_Option options[] = {
+ { "help", 'h', HELP_OPT, 0, 0 },
+ { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 },
+ { "version", 0, VERSION_OPT, 0, 0 },
+};
+
+
+static const char *program_name;
+static PermString::Initializer initializer;
+
+
+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 [OUTPUT]]", program_name);
+ else
+ errh->vxmessage(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("\
+%<T1rawafm%> generates a raw (kernless and ligatureless) AFM file corresponding\n\
+to the specified Type 1 font file and writes it to the standard output.\n\
+\n\
+Usage: %s [OPTION]... [FONT [OUTPUT]]\n\
+\n\
+FONT is the name of a PFA or PFB font file. If omitted, t1rawafm will read a\n\
+font file from the standard input.\n\
+\n\
+Options:\n\
+ -o, --output=FILE Write output to FILE instead of standard output.\n\
+ -h, --help Print this message and exit.\n\
+ --version Print version number and exit.\n\
+\n\
+Report bugs to <ekohler@gmail.com>.\n", program_name);
+}
+
+
+// MAIN
+
+static Type1Font *font;
+
+static void
+do_file(const char *filename, PsresDatabase *psres, ErrorHandler *errh)
+{
+ FILE *f;
+ if (!filename || 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)
+ errh->fatal("%s: %s", filename, strerror(errno));
+
+ Type1Reader *reader;
+ int c = getc(f);
+ ungetc(c, f);
+ if (c == EOF)
+ errh->fatal("%s: empty file", filename);
+ if (c == 128)
+ reader = new Type1PFBReader(f);
+ else
+ reader = new Type1PFAReader(f);
+
+ font = new Type1Font(*reader);
+
+ delete reader;
+}
+
+
+/*****
+ * MAIN PROGRAM
+ **/
+
+struct fontinfo_t {
+ const char *afm_name;
+ int dict;
+ const char *dict_name;
+ bool as_string;
+};
+
+static const fontinfo_t fontinfo_strings[] = {
+ { "Version", Type1Font::dFI, "version", true },
+ { "Notice", Type1Font::dFI, "Notice", true },
+ { "FullName", Type1Font::dFI, "FullName", true },
+ { "FamilyName", Type1Font::dFI, "FamilyName", true },
+ { "Weight", Type1Font::dFI, "Weight", true },
+ { "ItalicAngle", Type1Font::dFI, "ItalicAngle", false },
+ { "IsFixedPitch", Type1Font::dFI, "isFixedPitch", false },
+ { "UnderlinePosition", Type1Font::dFI, "UnderlinePosition", false },
+ { "UnderlineThickness", Type1Font::dFI, "UnderlineThickness", false }
+};
+
+static String
+strip_newlines(const String &str)
+{
+ StringAccum sa;
+ const char *end = str.end(), *last = str.begin();
+ for (const char *s = str.begin(); s != end; ++s)
+ if (*s == '\n' || *s == '\r' || *s == '\f' || *s == '\v') {
+ sa.append(last, s);
+ last = s + 1;
+ }
+ if (last == str.begin())
+ return str;
+ else {
+ sa.append(last, end);
+ return sa.take_string();
+ }
+}
+
+static void
+write_char(FILE *outf, int c, PermString n, Type1Charstring *g, const Transform &font_transform, Type1Font *font)
+{
+ double bb[4], wx;
+ CharstringBounds::bounds(font_transform, CharstringContext(font, g), bb, wx);
+ fprintf(outf, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n",
+ c, (int) ceil(wx), n.c_str(),
+ (int) floor(bb[0]), (int) floor(bb[1]),
+ (int) ceil(bb[2]), (int) ceil(bb[3]));
+}
+
+static void
+write_afm(FILE *outf, Type1Font *font)
+{
+ fprintf(outf, "StartFontMetrics 2.0\n\
+Comment Generated by t1rawafm\n");
+
+ for (size_t i = 0; i < sizeof(fontinfo_strings) / sizeof(fontinfo_t); ++i)
+ if (Type1Definition *t1d = font->dict(fontinfo_strings[i].dict,
+ fontinfo_strings[i].dict_name)) {
+ if (!fontinfo_strings[i].as_string)
+ fprintf(outf, "%s %s\n", fontinfo_strings[i].afm_name, t1d->value().c_str());
+ else {
+ String s;
+ if (t1d->value_string(s))
+ fprintf(outf, "%s %s\n", fontinfo_strings[i].afm_name, strip_newlines(s).c_str());
+ }
+ }
+
+ Transform font_transform;
+ {
+ double font_matrix[6];
+ font->font_matrix(font_matrix);
+ font_transform = Transform(font_matrix);
+ font_transform.scale(1000);
+ }
+
+ double bb[4], wx;
+ if (Type1Charstring *t1cs = font->glyph("H")) {
+ CharstringBounds::bounds(font_transform, CharstringContext(font, t1cs), bb, wx);
+ if (bb[3])
+ fprintf(outf, "CapHeight %d\n", (int) ceil(bb[3]));
+ }
+ if (Type1Charstring *t1cs = font->glyph("x")) {
+ CharstringBounds::bounds(font_transform, CharstringContext(font, t1cs), bb, wx);
+ if (bb[3])
+ fprintf(outf, "XHeight %d\n", (int) ceil(bb[3]));
+ }
+ if (Type1Charstring *t1cs = font->glyph("d")) {
+ CharstringBounds::bounds(font_transform, CharstringContext(font, t1cs), bb, wx);
+ if (bb[3])
+ fprintf(outf, "Ascender %d\n", (int) ceil(bb[3]));
+ }
+ if (Type1Charstring *t1cs = font->glyph("p")) {
+ CharstringBounds::bounds(font_transform, CharstringContext(font, t1cs), bb, wx);
+ if (bb[1])
+ fprintf(outf, "Descender %d\n", (int) floor(bb[1]));
+ }
+
+ Vector<double> vd;
+ if (Type1Definition *t1d = font->p_dict("StdHW"))
+ if (t1d->value_numvec(vd) && vd.size() > 0)
+ fprintf(outf, "StdHW %d\n", (int) ceil(vd[0]));
+ if (Type1Definition *t1d = font->p_dict("StdVW"))
+ if (t1d->value_numvec(vd) && vd.size() > 0)
+ fprintf(outf, "StdVW %d\n", (int) ceil(vd[0]));
+
+ double fontbb[4] = { 1000000, 1000000, -1000000, -1000000 };
+ for (int i = 0; i < font->nglyphs(); ++i) {
+ CharstringBounds::bounds(font_transform, CharstringContext(font, font->glyph(i)), bb, wx);
+ fontbb[0] = std::min(fontbb[0], bb[0]);
+ fontbb[1] = std::min(fontbb[1], bb[1]);
+ fontbb[2] = std::max(fontbb[2], bb[2]);
+ fontbb[3] = std::max(fontbb[3], bb[3]);
+ }
+ fprintf(outf, "FontBBox %d %d %d %d\n",
+ (int) floor(fontbb[0]), (int) floor(fontbb[1]),
+ (int) ceil(fontbb[2]), (int) ceil(fontbb[3]));
+
+ fprintf(outf, "FontName %s\n", font->font_name().c_str());
+
+ int nglyphs = font->nglyphs();
+ PermString dot_notdef(".notdef");
+ if (font->glyph(dot_notdef))
+ --nglyphs;
+ fprintf(outf, "Characters %d\n", nglyphs);
+
+ fprintf(outf, "StartCharMetrics %d\n", nglyphs);
+ Type1Encoding *enc = font->type1_encoding();
+ HashMap<PermString, int> done_yet(0);
+ done_yet.insert(dot_notdef, 1);
+ for (int i = 0; i < 256; ++i) {
+ PermString n = enc->elt(i);
+ if (!done_yet[n])
+ if (Type1Charstring *g = font->glyph(n)) {
+ write_char(outf, i, n, g, font_transform, font);
+ done_yet.insert(n, true);
+ }
+ }
+ for (int i = 0; i < font->nglyphs(); ++i) {
+ PermString n = font->glyph_name(i);
+ if (!done_yet[n])
+ write_char(outf, -1, n, font->glyph(i), font_transform, font);
+ }
+ fprintf(outf, "EndCharMetrics\n");
+
+ fprintf(outf, "EndFontMetrics\n");
+}
+
+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 *errh = ErrorHandler::static_initialize(new FileErrorHandler(stderr));
+ const char *output_file = 0;
+ Vector<String> glyph_patterns;
+
+ while (1) {
+ int opt = Clp_Next(clp);
+ switch (opt) {
+
+ case OUTPUT_OPT:
+ output_file:
+ if (output_file)
+ errh->fatal("output file already specified");
+ output_file = clp->vstr;
+ break;
+
+ case VERSION_OPT:
+ printf("t1rawafm (LCDF typetools) %s\n", VERSION);
+ printf("Copyright (C) 2008-2013 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:
+ if (font)
+ goto output_file;
+ else
+ do_file(clp->vstr, psres, errh);
+ break;
+
+ case Clp_Done:
+ goto done;
+
+ case Clp_BadOption:
+ usage_error(errh, 0);
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ done:
+ if (!font)
+ do_file(0, psres, errh);
+
+ FILE *outf;
+ if (!output_file || strcmp(output_file, "-") == 0)
+ outf = stdout;
+ else {
+ outf = fopen(output_file, "w");
+ if (!outf)
+ errh->fatal("%s: %s", output_file, strerror(errno));
+ }
+#if defined(_MSDOS) || defined(_WIN32)
+ _setmode(_fileno(outf), _O_BINARY);
+#endif
+
+ write_afm(outf, font);
+
+ exit(0);
+}