summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1dotlessj/t1dotlessj.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1dotlessj/t1dotlessj.cc')
-rw-r--r--Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1dotlessj/t1dotlessj.cc425
1 files changed, 425 insertions, 0 deletions
diff --git a/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1dotlessj/t1dotlessj.cc b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1dotlessj/t1dotlessj.cc
new file mode 100644
index 00000000000..03f56452728
--- /dev/null
+++ b/Build/source/texk/lcdf-typetools/lcdf-typetools-2.104/t1dotlessj/t1dotlessj.cc
@@ -0,0 +1,425 @@
+/* t1dotlessj.cc -- driver for creating dotlessj characters from Type 1 fonts
+ *
+ * Copyright (c) 2003-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/t1csgen.hh>
+#include <efont/t1bounds.hh>
+#include <efont/t1unparser.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
+
+// also see otftotfm/automatic.cc
+enum { EXIT_NORMAL = 0, EXIT_DOTLESSJ_EXISTS = 1, EXIT_J_NODOT = 2,
+ EXIT_NO_J = 3, EXIT_ERROR = 4 };
+
+using namespace Efont;
+
+#define VERSION_OPT 301
+#define HELP_OPT 302
+#define QUIET_OPT 303
+#define PFA_OPT 304
+#define PFB_OPT 305
+#define OUTPUT_OPT 306
+#define NAME_OPT 307
+
+const Clp_Option options[] = {
+ { "help", 'h', HELP_OPT, 0, 0 },
+ { "name", 'n', NAME_OPT, Clp_ValString, 0 },
+ { "output", 'o', OUTPUT_OPT, Clp_ValString, 0 },
+ { "pfa", 'a', PFA_OPT, 0, 0 },
+ { "pfb", 'b', PFB_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 [OPTIONS] [FONTFILE [OUTPUTFILE]]", program_name);
+ else
+ errh->vxmessage(ErrorHandler::e_error, error_message, val);
+ errh->message("Type %s --help for more information.", program_name);
+ exit(EXIT_ERROR);
+}
+
+void
+usage()
+{
+ FileErrorHandler uerrh(stdout);
+ uerrh.message("\
+%<T1dotlessj%> reads a PostScript Type 1 font, derives a new PostScript Type 1\n\
+font containing just a dotlessj character (by chopping the dot from the j),\n\
+and writes it to the standard output.\n\
+\n\
+Usage: %s [OPTIONS] [FONTFILE [OUTPUTFILE]]\n\
+\n\
+Options:\n\
+ -a, --pfa Output PFA font.\n\
+ -b, --pfb Output PFB font. This is the default.\n\
+ -o, --output=FILE Write output to FILE instead of standard output.\n\
+ -n, --name=NAME Set output font%,s PostScript name.\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);
+}
+
+
+// Sectioner
+
+class Sectioner : public Type1CharstringGenInterp { public:
+
+ Sectioner(int precision);
+
+ void act_line(int, const Point &, const Point &);
+ void act_curve(int, const Point &, const Point &, const Point &, const Point &);
+ void act_closepath(int);
+ void act_flex(int, const Point &, const Point &, const Point &, const Point &, const Point &, const Point &, const Point &, double);
+
+ void run(const CharstringContext &g);
+ void undot(PermString, ErrorHandler *);
+ Type1Charstring gen(Type1Font *);
+
+ private:
+
+ CharstringBounds _boundser;
+
+ Vector<String> _sections;
+ Vector<int> _bounds;
+
+ void append_bounds();
+
+};
+
+Sectioner::Sectioner(int precision)
+ : Type1CharstringGenInterp(precision)
+{
+ set_direct_hint_replacement(true);
+}
+
+void
+Sectioner::act_line(int cmd, const Point &p0, const Point &p1)
+{
+ Type1CharstringGenInterp::act_line(cmd, p0, p1);
+ _boundser.act_line(cmd, p0, p1);
+}
+
+void
+Sectioner::act_curve(int cmd, const Point &p0, const Point &p1, const Point &p2, const Point &p3)
+{
+ Type1CharstringGenInterp::act_curve(cmd, p0, p1, p2, p3);
+ _boundser.act_curve(cmd, p0, p1, p2, p3);
+}
+
+void
+Sectioner::act_flex(int cmd, const Point &p0, const Point &p1, const Point &p2, const Point &p3_4, const Point &p5, const Point &p6, const Point &p7, double flex_depth)
+{
+ Type1CharstringGenInterp::act_flex(cmd, p0, p1, p2, p3_4, p5, p6, p7, flex_depth);
+ _boundser.act_flex(cmd, p0, p1, p2, p3_4, p5, p6, p7, flex_depth);
+}
+
+void Sectioner::append_bounds() {
+ double bb[5];
+ _boundser.output(bb, bb[4]);
+ _bounds.push_back((int) floor(bb[0]));
+ _bounds.push_back((int) floor(bb[1]));
+ _bounds.push_back((int) ceil(bb[2]));
+ _bounds.push_back((int) ceil(bb[3]));
+}
+
+void
+Sectioner::act_closepath(int cmd)
+{
+ Type1CharstringGenInterp::act_closepath(cmd);
+ Type1Charstring result;
+ Type1CharstringGenInterp::intermediate_output(result);
+ _sections.push_back(result.data_string());
+ append_bounds();
+ _boundser.clear();
+}
+
+void
+Sectioner::run(const CharstringContext &g)
+{
+ _boundser.clear();
+ Type1Charstring last_section;
+ Type1CharstringGenInterp::run(g, last_section);
+ _sections.push_back(last_section.data_string());
+ append_bounds();
+}
+
+void
+Sectioner::undot(PermString font_name, ErrorHandler *errh)
+{
+ //for (String *s = _sections.begin(); s < _sections.end(); s++)
+ // fprintf(stderr, "%d %s\n", s - _sections.begin(), CharstringUnparser::unparse(Type1Charstring(*s)).c_str());
+
+ if (_sections.size() < 3)
+ errh->fatal("<%d>%s: %<j%> is already dotless", -EXIT_J_NODOT, font_name.c_str());
+
+ int topmost = -1;
+ for (int i = 0; i < _sections.size() - 1; i++)
+ if (topmost < 0 || _bounds[i*4 + 1] > _bounds[topmost*4 + 1])
+ topmost = i;
+
+ // check if any sections are below this
+ for (int i = 0; i < _sections.size() - 1; i++)
+ if (_bounds[i*4 + 1] < _bounds[topmost*4 + 1])
+ goto found_below;
+ errh->fatal("<%d>%s: %<j%> is already dotless", -EXIT_J_NODOT, font_name.c_str());
+
+ found_below:
+ _sections[topmost] = String();
+}
+
+Type1Charstring
+Sectioner::gen(Type1Font *font)
+{
+ StringAccum sa;
+ for (String *s = _sections.begin(); s < _sections.end(); s++)
+ sa << *s;
+ Type1Charstring in(sa.take_string()), out;
+ Type1CharstringGenInterp gen(precision());
+ gen.set_hint_replacement_storage(font);
+ gen.run(CharstringContext(program(), &in), out);
+ return out;
+}
+
+
+// MAIN
+
+static Type1Font *
+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("<%d>%s: %s", -EXIT_ERROR, filename, strerror(errno));
+
+ Type1Reader *reader;
+ int c = getc(f);
+ ungetc(c, f);
+ if (c == EOF)
+ errh->fatal("<%d>%s: empty file", -EXIT_ERROR, filename);
+ if (c == 128)
+ reader = new Type1PFBReader(f);
+ else
+ reader = new Type1PFAReader(f);
+
+ Type1Font *font = new Type1Font(*reader);
+ if (!font->ok())
+ errh->fatal("<%d>%s: no glyphs in font", -EXIT_ERROR, filename);
+
+ delete reader;
+ return font;
+}
+
+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 *input_file = 0;
+ FILE *outputf = 0;
+ const char *private_use_dotlessj = "uniF6BE";
+ bool binary = true;
+ const char *font_name = 0;
+
+ while (1) {
+ int opt = Clp_Next(clp);
+ switch (opt) {
+
+ case QUIET_OPT:
+ if (clp->negated)
+ errh = ErrorHandler::default_handler();
+ else
+ errh = new SilentErrorHandler;
+ break;
+
+ case NAME_OPT:
+ font_name = clp->vstr;
+ break;
+
+ case PFA_OPT:
+ binary = false;
+ break;
+
+ case PFB_OPT:
+ binary = true;
+ break;
+
+ case OUTPUT_OPT:
+ output_file:
+ if (outputf)
+ usage_error(errh, "output file specified twice");
+ if (strcmp(clp->vstr, "-") == 0)
+ outputf = stdout;
+ else if (!(outputf = fopen(clp->vstr, "wb")))
+ errh->fatal("<%d>%s: %s", -EXIT_ERROR, clp->vstr, strerror(errno));
+ break;
+
+ case VERSION_OPT:
+ printf("t1dotlessj (LCDF typetools) %s\n", VERSION);
+ printf("Copyright (C) 2003-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 (input_file && outputf)
+ usage_error(errh, "too many arguments");
+ else if (input_file)
+ goto output_file;
+ else
+ input_file = clp->vstr;
+ break;
+
+ case Clp_Done:
+ goto done;
+
+ case Clp_BadOption:
+ usage_error(errh, 0);
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ done:
+ Type1Font *font = do_file(input_file, psres, errh);
+ if (!input_file || strcmp(input_file, "-") == 0)
+ input_file = "<stdin>";
+
+ // check for existing dotlessj
+ if (font->glyph("dotlessj"))
+ errh->fatal("<%d>%s: already has a %<dotlessj%> glyph", -EXIT_DOTLESSJ_EXISTS, font->font_name().c_str());
+ else if (font->glyph("uni0237"))
+ errh->fatal("<%d>%s: already has a dotlessj glyph at %<uni0237%>", -EXIT_DOTLESSJ_EXISTS, font->font_name().c_str());
+ else if (font->glyph("u0237"))
+ errh->fatal("<%d>%s: already has a dotlessj glyph at %<u0237%>", -EXIT_DOTLESSJ_EXISTS, font->font_name().c_str());
+ else if (private_use_dotlessj && font->glyph(private_use_dotlessj))
+ errh->fatal("<%d>%s: already has a dotlessj glyph at %<%s%>", -EXIT_DOTLESSJ_EXISTS, font->font_name().c_str(), private_use_dotlessj);
+
+ // check for j
+ Type1Charstring *j_cs = font->glyph("j");
+ if (!j_cs)
+ j_cs = font->glyph("uni006A");
+ if (!j_cs)
+ j_cs = font->glyph("u006A");
+ if (!j_cs)
+ errh->fatal("<%d>%s: has no %<j%> glyph to make dotless", -EXIT_NO_J, font->font_name().c_str());
+
+ // make new font
+ String actual_font_name = (font_name ? String(font_name) : font->font_name() + String("LCDFJ"));
+ if (actual_font_name.length() > 29 && !font_name) {
+ errh->warning("derived font name %<%s%> longer than 29 characters", actual_font_name.c_str());
+ errh->message("(Use the %<--name%> option to supply your own name.)");
+ }
+
+ Vector<double> xuid_extension;
+ xuid_extension.push_back(0x00237237);
+ Type1Font *dotless_font = Type1Font::skeleton_make_copy(font, actual_font_name, &xuid_extension);
+ dotless_font->skeleton_common_subrs();
+
+ // copy space and .notdef
+ if (Type1Charstring *notdef = font->glyph(".notdef"))
+ dotless_font->add_glyph(Type1Subr::make_glyph(".notdef", *notdef, " |-"));
+ if (Type1Charstring *space = font->glyph("space")) {
+ dotless_font->add_glyph(Type1Subr::make_glyph("space", *space, " |-"));
+ dotless_font->type1_encoding()->put(' ', "space");
+ }
+
+ // create dotless j
+ Sectioner sec(5);
+ sec.run(CharstringContext(font, j_cs));
+ sec.undot(font->font_name(), errh);
+ Type1Subr *dotlessj = Type1Subr::make_glyph("uni0237", sec.gen(dotless_font), " |-");
+ dotless_font->add_glyph(dotlessj);
+ //fprintf(stderr, "! %s\n", CharstringUnparser::unparse(dotlessj->t1cs()).c_str());
+
+ // encode dotless j
+ dotless_font->type1_encoding()->clear();
+ dotless_font->type1_encoding()->put('j', "uni0237");
+
+ // write it to output
+ if (!outputf)
+ outputf = stdout;
+#if defined(_MSDOS) || defined(_WIN32)
+ _setmode(_fileno(outputf), _O_BINARY);
+#endif
+ if (binary) {
+ Type1PFBWriter w(outputf);
+ dotless_font->write(w);
+ } else {
+ Type1PFAWriter w(outputf);
+ dotless_font->write(w);
+ }
+
+ return (errh->nerrors() == 0 ? EXIT_NORMAL : EXIT_ERROR);
+}