diff options
Diffstat (limited to 'Build/source/texk/lcdf-typetools/otftotfm')
16 files changed, 515 insertions, 264 deletions
diff --git a/Build/source/texk/lcdf-typetools/otftotfm/Makefile.am b/Build/source/texk/lcdf-typetools/otftotfm/Makefile.am index 0a8a66a4ef8..09af4e1376c 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/Makefile.am +++ b/Build/source/texk/lcdf-typetools/otftotfm/Makefile.am @@ -1,4 +1,6 @@ ## Process this file with automake to produce Makefile.in +AUTOMAKE_OPTIONS = foreign + bin_PROGRAMS = otftotfm man_MANS = otftotfm.1 @@ -18,6 +20,8 @@ otftotfm_DEPENDENCIES = ../libefont/libefont.a ../liblcdf/liblcdf.a INCLUDES = -I$(top_srcdir)/include CLEANFILES = @TEMPLATE_OBJS@ +EXTRA_DIST = otftotfm.1 + if have_kpathsea otftotfm_SOURCES += kpseinterface.c kpseinterface.h INCLUDES += $(KPATHSEA_INCLUDES) @@ -25,7 +29,5 @@ otftotfm_LDADD += $(KPATHSEA_LIBS) otftotfm_DEPENDENCIES += $(KPATHSEA_DEPEND) endif have_kpathsea -EXTRA_DIST = otftotfm.1 - -## Rebuild libkpathsea +## Rebuild libkpathsea in a TeX Live build @KPATHSEA_RULE@ diff --git a/Build/source/texk/lcdf-typetools/otftotfm/Makefile.in b/Build/source/texk/lcdf-typetools/otftotfm/Makefile.in index e60bfa9b130..c54586100dd 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/Makefile.in +++ b/Build/source/texk/lcdf-typetools/otftotfm/Makefile.in @@ -164,6 +164,7 @@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KPATHSEA_DEPEND = @KPATHSEA_DEPEND@ KPATHSEA_INCLUDES = @KPATHSEA_INCLUDES@ KPATHSEA_LIBS = @KPATHSEA_LIBS@ +LCDF_TYPETOOLS_VERSION = @LCDF_TYPETOOLS_VERSION@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ @@ -252,6 +253,7 @@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ +AUTOMAKE_OPTIONS = foreign man_MANS = otftotfm.1 otftotfm_SOURCES = automatic.cc automatic.hh dvipsencoding.cc \ dvipsencoding.hh glyphfilter.cc glyphfilter.hh metrics.cc \ diff --git a/Build/source/texk/lcdf-typetools/otftotfm/automatic.cc b/Build/source/texk/lcdf-typetools/otftotfm/automatic.cc index 35b3e92a081..ad303d690a2 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/automatic.cc +++ b/Build/source/texk/lcdf-typetools/otftotfm/automatic.cc @@ -1,6 +1,6 @@ /* automatic.{cc,hh} -- code for automatic mode and interfacing with kpathsea * - * Copyright (c) 2003-2009 Eddie Kohler + * Copyright (c) 2003-2010 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 @@ -339,6 +339,8 @@ set_map_file(const String &s) String installed_type1(const String &otf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh) { + (void) otf_filename, (void) allow_generate, (void) errh; + if (!ps_fontname) return String(); @@ -391,6 +393,8 @@ installed_type1(const String &otf_filename, const String &ps_fontname, bool allo String installed_type1_dotlessj(const String &otf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh) { + (void) otf_filename, (void) allow_generate, (void) errh; + if (!ps_fontname) return String(); if (verbose) @@ -451,12 +455,12 @@ installed_type1_dotlessj(const String &otf_filename, const String &ps_fontname, } String -installed_truetype(const String &otf_filename, bool allow_generate, ErrorHandler *errh) +installed_truetype(const String &ttf_filename, bool allow_generate, ErrorHandler *errh) { - String file = pathname_filename(otf_filename); + String file = pathname_filename(ttf_filename); #if HAVE_KPATHSEA - if (!(force && allow_generate && otf_filename && otf_filename != "-" && getodir(O_TRUETYPE, errh))) { + if (!(force && allow_generate && ttf_filename && ttf_filename != "-" && getodir(O_TRUETYPE, errh))) { if (String path = kpsei_string(kpsei_find_file(file.c_str(), KPSEI_FMT_TRUETYPE))) { if (path == "./" + file || path == file) { if (verbose) @@ -471,14 +475,14 @@ installed_truetype(const String &otf_filename, bool allow_generate, ErrorHandler #endif // perhaps generate type 42 in the future, for now just copy - if (allow_generate && otf_filename && otf_filename != "-" && getodir(O_TRUETYPE, errh)) { + if (allow_generate && ttf_filename && ttf_filename != "-" && getodir(O_TRUETYPE, errh)) { String ttf_filename = odir[O_TRUETYPE] + "/" + file; if (ttf_filename.find_left('\'') >= 0 || ttf_filename.find_left('\"') >= 0) return String(); int retval; - if (!same_filename(otf_filename, ttf_filename)) { - String command = "cp " + shell_quote(otf_filename) + " " + shell_quote(ttf_filename); + if (!same_filename(ttf_filename, ttf_filename)) { + String command = "cp " + shell_quote(ttf_filename) + " " + shell_quote(ttf_filename); retval = mysystem(command.c_str(), errh); if (retval == 127) errh->error("could not run %<%s%>", command.c_str()); @@ -488,7 +492,7 @@ installed_truetype(const String &otf_filename, bool allow_generate, ErrorHandler errh->error("%<%s%> failed", command.c_str()); } else { if (verbose) - errh->message("TrueType file %s already located in output directory", otf_filename.c_str()); + errh->message("TrueType file %s already located in output directory", ttf_filename.c_str()); retval = 0; } @@ -501,6 +505,59 @@ installed_truetype(const String &otf_filename, bool allow_generate, ErrorHandler return String(); } +String +installed_type42(const String &ttf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh) +{ + (void) allow_generate, (void) ttf_filename, (void) errh; + + if (!ps_fontname) + return String(); + +#if HAVE_KPATHSEA +# if HAVE_AUTO_TTFTOTYPE42 + if (!(force && allow_generate && ttf_filename && ttf_filename != "-" && getodir(O_TYPE42, errh))) { +# endif + // look for .pfb and .pfa + String file, path; + if ((file = ps_fontname + ".t42", path = kpsei_string(kpsei_find_file(file.c_str(), KPSEI_FMT_TYPE42)))) { + if (path == "./" + file || path == file) { + if (verbose) + errh->message("ignoring Type 42 file %s found with kpathsea in %<.%>", path.c_str()); + } else { + if (verbose) + errh->message("Type 42 file %s found with kpathsea at %s", file.c_str(), path.c_str()); + return path; + } + } +# if HAVE_AUTO_TTFTOTYPE42 + } +# endif +#endif + +#if HAVE_AUTO_TTFTOTYPE42 + // if not found, and can generate on the fly, run cfftot1 + if (allow_generate && ttf_filename && ttf_filename != "-" && getodir(O_TYPE42, errh)) { + String t42_filename = odir[O_TYPE42] + "/" + ps_fontname + ".t42"; + if (t42_filename.find_left('\'') >= 0 || ttf_filename.find_left('\'') >= 0) + return String(); + String command = "ttftotype42 " + shell_quote(ttf_filename) + " " + shell_quote(t42_filename); + int retval = mysystem(command.c_str(), errh); + if (retval == 127) + errh->error("could not run %<%s%>", command.c_str()); + else if (retval < 0) + errh->error("could not run %<%s%>: %s", command.c_str(), strerror(errno)); + else if (retval != 0) + errh->error("%<%s%> failed", command.c_str()); + if (retval == 0) { + update_odir(O_TYPE42, t42_filename, errh); + return t42_filename; + } + } +#endif + + return String(); +} + int update_autofont_map(const String &fontname, String mapline, ErrorHandler *errh) { diff --git a/Build/source/texk/lcdf-typetools/otftotfm/automatic.hh b/Build/source/texk/lcdf-typetools/otftotfm/automatic.hh index 5bd8d04a974..4c973347715 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/automatic.hh +++ b/Build/source/texk/lcdf-typetools/otftotfm/automatic.hh @@ -17,7 +17,8 @@ const char *odirname(int o); void update_odir(int o, String file, ErrorHandler *); String installed_type1(const String &otf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *); String installed_type1_dotlessj(const String &otf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *); -String installed_truetype(const String &otf_filename, bool allow_generate, ErrorHandler *errh); +String installed_truetype(const String &ttf_filename, bool allow_generate, ErrorHandler *errh); +String installed_type42(const String &ttf_filename, const String &ps_fontname, bool allow_generate, ErrorHandler *errh); int update_autofont_map(const String &fontname, String mapline, ErrorHandler *); String locate_encoding(String encfile, ErrorHandler *, bool literal = false); diff --git a/Build/source/texk/lcdf-typetools/otftotfm/dvipsencoding.cc b/Build/source/texk/lcdf-typetools/otftotfm/dvipsencoding.cc index 7dc8f561d31..0575c665225 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/dvipsencoding.cc +++ b/Build/source/texk/lcdf-typetools/otftotfm/dvipsencoding.cc @@ -1,6 +1,6 @@ /* dvipsencoding.{cc,hh} -- store a DVIPS encoding * - * Copyright (c) 2003-2008 Eddie Kohler + * Copyright (c) 2003-2010 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 diff --git a/Build/source/texk/lcdf-typetools/otftotfm/glyphfilter.cc b/Build/source/texk/lcdf-typetools/otftotfm/glyphfilter.cc index f7d2ec5d0ea..1e9ba03d27e 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/glyphfilter.cc +++ b/Build/source/texk/lcdf-typetools/otftotfm/glyphfilter.cc @@ -1,6 +1,6 @@ /* glyphfilter.{cc,hh} -- define subsets of characters * - * Copyright (c) 2004-2006 Eddie Kohler + * Copyright (c) 2004-2010 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 diff --git a/Build/source/texk/lcdf-typetools/otftotfm/kpseinterface.c b/Build/source/texk/lcdf-typetools/otftotfm/kpseinterface.c index 586c23e5f07..0df5c25ed00 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/kpseinterface.c +++ b/Build/source/texk/lcdf-typetools/otftotfm/kpseinterface.c @@ -1,6 +1,6 @@ /* kpseinterface.{c,h} -- interface with the kpathsea library * - * Copyright (c) 2003-2006 Eddie Kohler + * Copyright (c) 2003-2010 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 diff --git a/Build/source/texk/lcdf-typetools/otftotfm/metrics.cc b/Build/source/texk/lcdf-typetools/otftotfm/metrics.cc index 5d76691d3d3..5d2ac48fc84 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/metrics.cc +++ b/Build/source/texk/lcdf-typetools/otftotfm/metrics.cc @@ -1,6 +1,6 @@ /* metrics.{cc,hh} -- an encoding during and after OpenType features * - * Copyright (c) 2003-2008 Eddie Kohler + * Copyright (c) 2003-2010 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 @@ -121,15 +121,15 @@ Metrics::unicode_encoding(uint32_t uni) const } Metrics::Code -Metrics::hard_encoding(Glyph g) const +Metrics::hard_encoding(Glyph g, Code after) const { if (g < 0) return -1; int answer = -1, n = 0; - for (int i = _encoding.size() - 1; i >= 0; i--) + for (int i = _encoding.size() - 1; i >= after; i--) if (_encoding[i].glyph == g) answer = i, n++; - if (n < 2) { + if (n < 2 && after == 0) { if (g >= _emap.size()) _emap.resize(g + 1, -2); _emap[g] = answer; @@ -141,7 +141,7 @@ Metrics::Code Metrics::force_encoding(Glyph g, int lookup_source) { assert(g >= 0); - int e = encoding(g); + int e = encoding(g, 0); if (e >= 0) return e; else { @@ -469,8 +469,7 @@ Metrics::add_single_positioning(Code c, int pdx, int pdy, int adx) /*****************************************************************************/ /* changed_context structure */ -namespace { -class ChangedContext { public: +class Metrics::ChangedContext { public: ChangedContext(int ncodes); ~ChangedContext(); typedef Metrics::Code Code; @@ -491,12 +490,12 @@ class ChangedContext { public: inline void ensure_all(Code) const; }; -ChangedContext::ChangedContext(int ncodes) +Metrics::ChangedContext::ChangedContext(int ncodes) : _v(ncodes, 0), _initial_ncodes(ncodes), _all_sentinel(((ncodes - 1) >> 5) + 1, 0xFFFFFFFFU) { } -ChangedContext::~ChangedContext() +Metrics::ChangedContext::~ChangedContext() { for (Vector<uint32_t> **v = _v.begin(); v != _v.end(); v++) if (*v != &_all_sentinel) @@ -504,14 +503,14 @@ ChangedContext::~ChangedContext() } inline void -ChangedContext::ensure_all(Code c) const +Metrics::ChangedContext::ensure_all(Code c) const { if (c >= 0 && (c >> 5) >= _all_sentinel.size()) _all_sentinel.resize((c >> 5) + 1, 0xFFFFFFFFU); } inline bool -ChangedContext::bit(const Vector<uint32_t> &v, Code c) +Metrics::ChangedContext::bit(const Vector<uint32_t> &v, Code c) { if (c < 0 || (c >> 5) >= v.size()) return false; @@ -520,7 +519,7 @@ ChangedContext::bit(const Vector<uint32_t> &v, Code c) } bool -ChangedContext::allowed(Code c, bool left_context) const +Metrics::ChangedContext::allowed(Code c, bool left_context) const { if (c < 0) return false; @@ -531,7 +530,7 @@ ChangedContext::allowed(Code c, bool left_context) const } bool -ChangedContext::pair_allowed(Code c1, Code c2) const +Metrics::ChangedContext::pair_allowed(Code c1, Code c2) const { ensure_all(c2); if (c1 < 0 || c2 < 0) @@ -543,13 +542,13 @@ ChangedContext::pair_allowed(Code c1, Code c2) const } bool -ChangedContext::virgin(Code c) const +Metrics::ChangedContext::virgin(Code c) const { return (c >= 0 && (c >= _v.size() || _v[c] == 0)); } void -ChangedContext::disallow(Code c) +Metrics::ChangedContext::disallow(Code c) { assert(c >= 0); if (c >= _v.size()) @@ -561,7 +560,7 @@ ChangedContext::disallow(Code c) } void -ChangedContext::disallow_pair(Code c1, Code c2) +Metrics::ChangedContext::disallow_pair(Code c1, Code c2) { assert(c1 >= 0 && c2 >= 0); if (c1 >= _v.size()) @@ -575,13 +574,57 @@ ChangedContext::disallow_pair(Code c1, Code c2) } } -} - /*****************************************************************************/ /* applying GSUB substitutions */ void +Metrics::apply_single(Code cin, const Substitution *s, int lookup, + ChangedContext &ctx, const GlyphFilter &glyph_filter, + const Vector<PermString> &glyph_names) +{ + // check if encoded + if (!ctx.allowed(cin, false)) + /* not encoded before this substitution began, or completely changed; + ingore */ + return; + + // check if substitution of this code allowed + if (!glyph_filter.allow_substitution(s->in_glyph(), glyph_names, unicode(cin))) + return; + + // look for an allowed alternate + Glyph out = -1; + for (int i = 0; out < 0 && i < s->out_nglyphs(); i++) + if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, unicode(cin))) + out = s->out_glyph(i); + if (out < 0) // no allowed alternate + return; + + // apply substitution + if (ctx.virgin(cin)) { + // no one has changed this glyph yet, change it unilaterally + assign_emap(s->in_glyph(), -2); + assign_emap(out, cin); + assert(!_encoding[cin].virtual_char); + _encoding[cin].glyph = out; + } else { + // some contextual substitutions have changed this glyph, add + // contextual substitutions for the remaining possibilities + Code cout = force_encoding(out, lookup); + for (Code right = 0; right < _encoding.size(); right++) + if (_encoding[right].visible() && !_encoding[right].flag(Char::BUILT) && ctx.pair_allowed(cin, right)) { + Code pair = pair_code(cout, right, lookup); + _encoding[cout].flags &= ~Char::INTERMEDIATE; + add_ligature(cin, right, pair); + } + } + + // no more substitutions for cin + ctx.disallow(cin); +} + +void Metrics::apply_ligature(const Vector<Code> &in, const Substitution *s, int lookup) { // build up the character pair @@ -622,91 +665,77 @@ Metrics::apply_ligature(const Vector<Code> &in, const Substitution *s, int looku repoint_ligature(ch - _encoding.begin(), l, cout); } +void +Metrics::apply_simple_context_ligature(const Vector<Code> &codes, + const Substitution *s, int lookup, ChangedContext &ctx) +{ + int nleft = s->left_nglyphs(), nin = s->in_nglyphs(); + assert(codes.size() >= 2); + + // check if context allows substitutions + for (const Code *inp = codes.begin(); inp < codes.end(); ++inp) + if (!ctx.allowed(*inp, inp - codes.begin() < nleft)) + return; + + // check if any part of the combination has already changed + int ncheck = nleft + (nin > 2 ? 2 : nin); + if (ncheck == codes.size()) + --ncheck; + for (const Code *inp = codes.begin(); inp < codes.begin() + ncheck; ++inp) + if (!ctx.pair_allowed(inp[0], inp[1])) + return; + + // mark this combination as changed if appropriate + if (codes.size() == 2 && nin == 1) + ctx.disallow_pair(codes[0], codes[1]); + + // actually apply ligature + apply_ligature(codes, s, lookup); +} + +bool +Metrics::next_encoding(Vector<Code> &codes, const Vector<Glyph> &glyphs) const +{ + if (!codes.size()) { + codes.assign(glyphs.size(), 0); + for (int i = 0; i < glyphs.size(); ++i) + if ((codes[i] = encoding(glyphs[i], 0)) < 0) + return false; + return true; + } else { + for (int i = 0; i < glyphs.size(); ++i) + if ((codes[i] = encoding(glyphs[i], codes[i] + 1)) >= 0) + return true; + else + codes[i] = encoding(glyphs[i], 0); + return false; + } +} + int Metrics::apply(const Vector<Substitution>& sv, bool allow_single, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names) { + Vector<Glyph> glyphs; + Vector<Code> codes; + // keep track of what substitutions we have performed ChangedContext ctx(_encoding.size()); - // XXX does not handle multiply-encoded glyphs - // loop over substitutions int failures = 0; for (const Substitution *s = sv.begin(); s != sv.end(); s++) { bool is_single = s->is_single() || s->is_alternate(); - if (is_single && allow_single) { - // check if encoded - Code cin = encoding(s->in_glyph()); - if (!ctx.allowed(cin, false)) - /* not encoded before this substitution began, or completely - changed; ingore */ - continue; - - // check if substitution of this code allowed - if (!glyph_filter.allow_substitution(s->in_glyph(), glyph_names, unicode(cin))) - continue; - - // look for an allowed alternate - Glyph out = -1; - for (int i = 0; out < 0 && i < s->out_nglyphs(); i++) - if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, unicode(cin))) - out = s->out_glyph(i); - if (out < 0) // no allowed alternate - continue; - - // apply substitution - if (ctx.virgin(cin)) { - // no one has changed this glyph yet, change it unilaterally - assign_emap(s->in_glyph(), -2); - assign_emap(out, cin); - assert(!_encoding[cin].virtual_char); - _encoding[cin].glyph = out; - ctx.disallow(cin); - } else { - // some contextual substitutions have changed this glyph, add - // contextual substitutions for the remaining possibilities - Code cout = force_encoding(out, lookup); - for (Code right = 0; right < _encoding.size(); right++) - if (_encoding[right].visible() && !_encoding[right].flag(Char::BUILT) && ctx.pair_allowed(cin, right)) { - Code pair = pair_code(cout, right, lookup); - _encoding[cout].flags &= ~Char::INTERMEDIATE; - add_ligature(cin, right, pair); - } - ctx.disallow(cin); - } - - } else if (!is_single && !s->is_multiple() && s->is_simple_context()) { - // find a list of 'in' codes - Vector<Code> in; - s->all_in_glyphs(in); - int nleft = s->left_nglyphs(), nin = s->in_nglyphs(); - assert(in.size() >= 2); - bool ok = true; - for (Glyph *inp = in.begin(); inp < in.end(); inp++) { - *inp = encoding(*inp); - if (!ctx.allowed(*inp, inp - in.begin() < nleft)) - ok = false; + bool is_apply_single = is_single && allow_single; + bool is_apply_simple_context_ligature = !is_single && !s->is_multiple() && s->is_simple_context(); + + if (is_apply_single || is_apply_simple_context_ligature) { + s->all_in_glyphs(glyphs); + for (codes.clear(); next_encoding(codes, glyphs); ) { + if (is_apply_single) + apply_single(codes[0], s, lookup, ctx, glyph_filter, glyph_names); + else + apply_simple_context_ligature(codes, s, lookup, ctx); } - - // check if any part of the combination has already changed - int ncheck = nleft + (nin > 2 ? 2 : nin); - if (ncheck == in.size()) - ncheck--; - for (Code *inp = in.begin(); inp < in.begin() + ncheck; inp++) - if (!ctx.pair_allowed(inp[0], inp[1])) - ok = false; - - // if not ok, continue - if (!ok) - continue; - - // mark this combination as changed if appropriate - if (in.size() == 2 && nin == 1) - ctx.disallow_pair(in[0], in[1]); - - // actually apply ligature - apply_ligature(in, s, lookup); - } else failures++; } @@ -715,52 +744,65 @@ Metrics::apply(const Vector<Substitution>& sv, bool allow_single, int lookup, co } void -Metrics::apply_alternates(const Vector<Substitution>& sv, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names) +Metrics::apply_alternates_single(Code cin, const Substitution *s, int lookup, + const GlyphFilter &glyph_filter, + const Vector<PermString> &glyph_names) { - for (const Substitution *s = sv.begin(); s != sv.end(); s++) - if (s->is_single() || s->is_alternate()) { - Code e = encoding(s->in_glyph()); - if (e < 0) - continue; - for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++) - if (as->kern == 0) { - Code last = e; - for (int i = 0; i < s->out_nglyphs(); i++) - if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, unicode(e))) { - Code out = force_encoding(s->out_glyph(i), lookup); - add_ligature(last, as->in2, out); - last = out; - } - } else if (as->kern <= s->out_nglyphs()) { - Code out = force_encoding(s->out_glyph(as->kern - 1), lookup); - add_ligature(e, as->in2, out); - } - } else if (s->is_ligature()) { - // check whether the output character is allowed - bool ok = true; - if (!glyph_filter.allow_alternate(s->out_glyph(), glyph_names, 0)) - ok = false; - - // check whether the input characters are encoded - Vector<Code> in(s->in_nglyphs() + 1, 0); - if (ok && (in[0] = encoding(s->in_glyph(0))) < 0) - ok = false; - for (int i = 1; ok && i < s->in_nglyphs(); i++) - if ((in[i+1] = encoding(s->in_glyph(i))) < 0) - ok = false; - - if (!ok) - continue; - - // find alternate selector and apply ligature if appropriate - for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++) - if (as->kern == 0) { - in[1] = as->in2; - apply_ligature(in, s, lookup); + for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++) + if (as->kern == 0) { + Code last = cin; + uint32_t u = unicode(cin); + for (int i = 0; i < s->out_nglyphs(); i++) + if (glyph_filter.allow_alternate(s->out_glyph(i), glyph_names, u)) { + Code out = force_encoding(s->out_glyph(i), lookup); + add_ligature(last, as->in2, out); + last = out; } + } else if (as->kern <= s->out_nglyphs()) { + Code out = force_encoding(s->out_glyph(as->kern - 1), lookup); + add_ligature(cin, as->in2, out); } } +void +Metrics::apply_alternates_ligature(const Vector<Code> &codes, + const Substitution *s, int lookup, + const GlyphFilter &glyph_filter, + const Vector<PermString> &glyph_names) +{ + // check whether the output character is allowed + if (!glyph_filter.allow_alternate(s->out_glyph(), glyph_names, 0)) + return; + + // find alternate selector and apply ligature if appropriate + for (const Kern *as = _altselectors.begin(); as != _altselectors.end(); as++) + if (as->kern == 0) { + Vector<Code> lig(codes); + lig.insert(lig.begin() + 1, as->in2); + apply_ligature(lig, s, lookup); + } +} + +void +Metrics::apply_alternates(const Vector<Substitution>& sv, int lookup, const GlyphFilter& glyph_filter, const Vector<PermString>& glyph_names) +{ + Vector<Glyph> glyphs; + Vector<Code> codes; + + for (const Substitution *s = sv.begin(); s != sv.end(); s++) { + bool is_single = s->is_single() || s->is_alternate(); + if (is_single || s->is_ligature()) { + s->all_in_glyphs(glyphs); + for (codes.clear(); next_encoding(codes, glyphs); ) { + if (is_single) + apply_alternates_single(codes[0], s, lookup, glyph_filter, glyph_names); + else + apply_alternates_ligature(codes, s, lookup, glyph_filter, glyph_names); + } + } + } +} + /*****************************************************************************/ /* applying GPOS positionings */ @@ -786,28 +828,29 @@ Metrics::apply(const Vector<Positioning>& pv) // keep track of what substitutions we have performed int *single_changed = 0; Vector<int *> pair_changed(_encoding.size(), 0); - - // XXX does not handle multiply-encoded glyphs + Vector<Glyph> glyphs; + Vector<Code> codes; // loop over substitutions int success = 0; - for (const Positioning *p = pv.begin(); p != pv.end(); p++) - if (p->is_pairkern()) { - int code1 = encoding(p->left_glyph()); - int code2 = encoding(p->right_glyph()); - if (code1 >= 0 && code2 >= 0 - && !assign_bitvec(pair_changed[code1], code2, _encoding.size())) - add_kern(code1, code2, p->left().adx); - success++; - } else if (p->is_single()) { - int code = encoding(p->left_glyph()); - if (code >= 0 && !assign_bitvec(single_changed, code, _encoding.size())) { - _encoding[code].pdx += p->left().pdx; - _encoding[code].pdy += p->left().pdy; - _encoding[code].adx += p->left().adx; - } + for (const Positioning *p = pv.begin(); p != pv.end(); p++) { + bool is_single = p->is_single(); + if (is_single || p->is_pairkern()) { + p->all_in_glyphs(glyphs); + for (codes.clear(); next_encoding(codes, glyphs); ) + if (is_single) { + if (!assign_bitvec(single_changed, codes[0], _encoding.size())) { + _encoding[codes[0]].pdx += p->left().pdx; + _encoding[codes[0]].pdy += p->left().pdy; + _encoding[codes[0]].adx += p->left().adx; + } + } else { + if (!assign_bitvec(pair_changed[codes[0]], codes[1], _encoding.size())) + add_kern(codes[0], codes[1], p->left().adx); + } success++; } + } delete[] single_changed; for (int i = 0; i < pair_changed.size(); i++) diff --git a/Build/source/texk/lcdf-typetools/otftotfm/metrics.hh b/Build/source/texk/lcdf-typetools/otftotfm/metrics.hh index 06f6a25f291..b032e6b348f 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/metrics.hh +++ b/Build/source/texk/lcdf-typetools/otftotfm/metrics.hh @@ -54,12 +54,12 @@ class Metrics { public: PermString code_name(Code) const; inline const char *code_str(Code) const; - inline Glyph glyph(Code) const; - inline uint32_t unicode(Code) const; - inline Code encoding(Glyph) const; - Code unicode_encoding(uint32_t) const; - Code force_encoding(Glyph, int lookup_source = -1); - void encode(Code, uint32_t uni, Glyph); + inline Glyph glyph(Code code) const; + inline uint32_t unicode(Code code) const; + inline Code encoding(Glyph g, Code after) const; + Code unicode_encoding(uint32_t uni) const; + Code force_encoding(Glyph g, int lookup_source = -1); + void encode(Code code, uint32_t uni, Glyph g); void encode_virtual(Code, PermString, uint32_t uni, const Vector<Setting> &, bool base_char); void add_altselector_code(Code, int altselector_type); @@ -174,7 +174,8 @@ class Metrics { public: Metrics &operator=(const Metrics &); // does not exist inline void assign_emap(Glyph, Code); - Code hard_encoding(Glyph) const; + Code hard_encoding(Glyph, Code) const; + bool next_encoding(Vector<Code> &codes, const Vector<Glyph> &glyphs) const; Ligature *ligature_obj(Code, Code); Kern *kern_obj(Code, Code); @@ -186,7 +187,20 @@ class Metrics { public: void mark_liveness(int size, const Vector<Ligature3> * = 0); void reencode(const Vector<Code> &); + class ChangedContext; void apply_ligature(const Vector<Code> &, const Substitution *, int lookup); + void apply_single(Code cin, const Substitution *s, int lookup, + ChangedContext &ctx, const GlyphFilter &glyph_filter, + const Vector<PermString> &glyph_names); + void apply_simple_context_ligature(const Vector<Code> &codes, + const Substitution *s, int lookup, ChangedContext &ctx); + void apply_alternates_single(Code cin, const Substitution *s, int lookup, + const GlyphFilter &glyph_filter, + const Vector<PermString> &glyph_names); + void apply_alternates_ligature(const Vector<Code> &codes, + const Substitution *s, int lookup, + const GlyphFilter &glyph_filter, + const Vector<PermString> &glyph_names); void unparse(const Char *) const; @@ -242,12 +256,13 @@ Metrics::base_code(Code code) const } inline Metrics::Code -Metrics::encoding(Glyph g) const +Metrics::encoding(Glyph g, Code after) const { - if (g >= 0 && g < _emap.size() && _emap.at_u(g) >= -1) - return _emap.at_u(g); + Code c; + if (g >= 0 && g < _emap.size() && (c = _emap.at_u(g)) >= -1) + return c < 0 || c >= after ? c : -1; else - return hard_encoding(g); + return hard_encoding(g, after); } inline void diff --git a/Build/source/texk/lcdf-typetools/otftotfm/otftotfm.1 b/Build/source/texk/lcdf-typetools/otftotfm/otftotfm.1 index 1d46a440063..212f4508ba7 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/otftotfm.1 +++ b/Build/source/texk/lcdf-typetools/otftotfm/otftotfm.1 @@ -1,5 +1,5 @@ '\"t -.ds V 2.79 +.ds V 2.83 .de M .BR "\\$1" "(\\$2)\\$3" .. @@ -153,17 +153,24 @@ and options. \fISignature\fR is an opaque 6-character encoding signature. .PP .B Otftotfm -also installs a font file suitable for printing. -PostScript-flavored OpenType fonts are translated to Type 1 format and -installed as PFB fonts; TrueType-flavored fonts are installed as is (pdftex -and pdflatex can read TrueType directly). However, +also installs a font file suitable for printing. PostScript-flavored +OpenType fonts are translated to Type 1 format and installed as PFB fonts. +TrueType-flavored fonts are normally installed as is, since pdftex and +pdflatex can read TrueType directly; but if you provide the +.B \-\-type42 +option, .B otftotfm -will not install a font file if one already exists. The installation paths -are as follows, where \fIPSname\fR is the font's PostScript name. +will translate TrueType fonts to Type 42 format, which dvips understands. +.B Otftotfm +does not overwrite existing font files. +.PP +The installation paths are as follows, where \fIPSname\fR is the font's +PostScript name. .TS l l l . PFB TEXMF/fonts/type1/\fIvendor\fR/\fItypeface\fR/ \fIPSname\fR.pfb TrueType TEXMF/fonts/truetype/\fIvendor\fR/\fItypeface\fR/ \fIfontfile\fR +Type 42 TEXMF/fonts/type42/\fIvendor\fR/\fItypeface\fR/ \fIPSname\fR.t42 .TE .PP You can override these directories with environment variables and options @@ -179,6 +186,7 @@ VPL VPLDESTDIR \-\-vpl\-directory encoding ENCODINGDESTDIR \-\-encoding\-directory PFB T1DESTDIR \-\-type1\-directory TrueType TRUETYPEDESTDIR \-\-truetype\-directory +Type 42 T42DESTDIR \-\-type42\-directory font map \- \-\-map\-file .TE .PP @@ -467,6 +475,27 @@ TeX "at" a particular size effectively ignores the design size; loading a font plain or "scaled" by a given factor uses the design size.) The default is taken from the input font's optical size feature, or 10pt if it has no such feature. +' +.Sp +.TP 5 +.BI \-\-fixed\-width +Set the font to fixed-width (its space character will have no stretch or +shrink). Normally you won't need this option; the font will tell +.B otftotfm +whether it is fixed width. The opposite of +.B \-\-fixed\-width +is +.BR \-\-proportional\-width . +' +.Sp +.TP 5 +.BI \-\-italic\-angle= angle +Set the output font's default italic angle to +.IR angle , +a number of degrees. This value is used by TeX to position +accents. Normally you won't need this option; the font will tell +.B otftotfm +its italic angle. .PD ' ' @@ -725,6 +754,16 @@ dotless-j. ' .Sp .TP 5 +.BI \-\-no\-truetype +Do not install TrueType-flavored fonts. +' +.Sp +.TP 5 +.BI \-\-type42 +Install TrueType-flavored fonts in translated Type 42 format. +' +.Sp +.TP 5 .BI \-\-no\-updmap Do not run an .M updmap 1 @@ -732,11 +771,6 @@ program. This can be useful if you're installing a bunch of fonts; it is much faster to run .B updmap once, at the end, than to run it once per font. -' -.Sp -.TP 5 -.BI \-\-no\-truetype -Do not install TrueType-flavored OpenType fonts. .PD ' ' @@ -821,6 +855,8 @@ Do not generate a font map line for the font. .BI \-\-type1\-directory= dir .TP 5 .BI \-\-truetype\-directory= dir +.TP 5 +.BI \-\-type42\-directory= dir Set the directory used for various output types. Each directory may be set by an environment variable, and defaults to a TDS directory in automatic mode, or to "." otherwise. Environment variable names and default TDS @@ -1575,6 +1611,7 @@ output through .M otfinfo 1 , .M t1dotlessj 1 , .M t1testpage 1 , +.M ttftotype42 1 , .M kpsewhich 1 , .M updmap 1 .LP diff --git a/Build/source/texk/lcdf-typetools/otftotfm/otftotfm.cc b/Build/source/texk/lcdf-typetools/otftotfm/otftotfm.cc index 7c89622e9f2..49d97241fc0 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/otftotfm.cc +++ b/Build/source/texk/lcdf-typetools/otftotfm/otftotfm.cc @@ -1,6 +1,6 @@ /* otftotfm.cc -- driver for translating OpenType fonts to TeX metrics * - * Copyright (c) 2003-2009 Eddie Kohler + * Copyright (c) 2003-2010 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 @@ -99,38 +99,45 @@ using namespace Efont; #define POSITION_OPT 339 #define WARN_MISSING_OPT 340 #define BASE_ENCODINGS_OPT 341 - -#define AUTOMATIC_OPT 342 -#define FONT_NAME_OPT 343 -#define QUIET_OPT 344 -#define GLYPHLIST_OPT 345 -#define VENDOR_OPT 346 -#define TYPEFACE_OPT 347 -#define NOCREATE_OPT 348 -#define VERBOSE_OPT 349 -#define FORCE_OPT 350 - -#define VIRTUAL_OPT 351 -#define PL_OPT 352 -#define TFM_OPT 353 -#define MAP_FILE_OPT 354 -#define OUTPUT_ENCODING_OPT 355 - -#define DIR_OPTS 360 +#define FIXED_PITCH_OPT 342 +#define ITALIC_ANGLE_OPT 343 +#define PROPORTIONAL_WIDTH_OPT 344 + +#define AUTOMATIC_OPT 350 +#define FONT_NAME_OPT 351 +#define QUIET_OPT 352 +#define GLYPHLIST_OPT 353 +#define VENDOR_OPT 354 +#define TYPEFACE_OPT 355 +#define NOCREATE_OPT 356 +#define VERBOSE_OPT 357 +#define FORCE_OPT 358 + +#define VIRTUAL_OPT 360 +#define PL_OPT 361 +#define TFM_OPT 362 +#define MAP_FILE_OPT 363 +#define OUTPUT_ENCODING_OPT 364 + +#define DIR_OPTS 380 #define ENCODING_DIR_OPT (DIR_OPTS + O_ENCODING) #define TFM_DIR_OPT (DIR_OPTS + O_TFM) #define PL_DIR_OPT (DIR_OPTS + O_PL) #define VF_DIR_OPT (DIR_OPTS + O_VF) #define VPL_DIR_OPT (DIR_OPTS + O_VPL) #define TYPE1_DIR_OPT (DIR_OPTS + O_TYPE1) +#define TYPE42_DIR_OPT (DIR_OPTS + O_TYPE42) #define TRUETYPE_DIR_OPT (DIR_OPTS + O_TRUETYPE) -#define NO_OUTPUT_OPTS 380 +#define NO_OUTPUT_OPTS 400 #define NO_ENCODING_OPT (NO_OUTPUT_OPTS + G_ENCODING) #define NO_TYPE1_OPT (NO_OUTPUT_OPTS + G_TYPE1) #define NO_DOTLESSJ_OPT (NO_OUTPUT_OPTS + G_DOTLESSJ) #define NO_UPDMAP_OPT (NO_OUTPUT_OPTS + G_UPDMAP) -#define NO_TRUETYPE_OPT (NO_OUTPUT_OPTS + G_TRUETYPE) + +#define YES_OUTPUT_OPTS 2000 +#define TRUETYPE_OPT (YES_OUTPUT_OPTS + G_TRUETYPE) +#define TYPE42_OPT (YES_OUTPUT_OPTS + G_TYPE42) #define CHAR_OPTTYPE (Clp_ValFirstUser) @@ -173,14 +180,19 @@ static Clp_Option options[] = { { "alternates-filter", 0, ALTERNATES_FILTER_OPT, Clp_ValString, 0 }, { "space-factor", 0, SPACE_FACTOR_OPT, Clp_ValDouble, 0 }, { "math-spacing", 0, MATH_SPACING_OPT, CHAR_OPTTYPE, Clp_Negate | Clp_Optional }, + { "fixed-pitch", 0, FIXED_PITCH_OPT, 0, Clp_Negate }, + { "fixed-width", 0, FIXED_PITCH_OPT, 0, Clp_Negate }, + { "proportional-width", 0, PROPORTIONAL_WIDTH_OPT, 0, Clp_Negate }, + { "italic-angle", 0, ITALIC_ANGLE_OPT, Clp_ValDouble, 0 }, { "pl", 'p', PL_OPT, 0, 0 }, { "virtual", 0, VIRTUAL_OPT, 0, Clp_Negate }, { "no-encoding", 0, NO_ENCODING_OPT, 0, 0 }, { "no-type1", 0, NO_TYPE1_OPT, 0, 0 }, - { "no-truetype", 0, NO_TRUETYPE_OPT, 0, 0 }, { "no-dotlessj", 0, NO_DOTLESSJ_OPT, 0, 0 }, { "no-updmap", 0, NO_UPDMAP_OPT, 0, 0 }, + { "truetype", 0, TRUETYPE_OPT, 0, Clp_Negate }, + { "type42", 0, TYPE42_OPT, 0, Clp_Negate }, { "map-file", 0, MAP_FILE_OPT, Clp_ValString, Clp_Negate }, { "output-encoding", 0, OUTPUT_ENCODING_OPT, Clp_ValString, Clp_Optional }, @@ -195,6 +207,7 @@ static Clp_Option options[] = { { "vpl-directory", 0, VPL_DIR_OPT, Clp_ValString, 0 }, { "vf-directory", 0, VF_DIR_OPT, Clp_ValString, 0 }, { "type1-directory", 0, TYPE1_DIR_OPT, Clp_ValString, 0 }, + { "type42-directory", 0, TYPE42_DIR_OPT, Clp_ValString, 0 }, { "truetype-directory", 0, TRUETYPE_DIR_OPT, Clp_ValString, 0 }, { "quiet", 'q', QUIET_OPT, 0, Clp_Negate }, @@ -254,6 +267,10 @@ static double minimum_kern = 2.0; static double space_factor = 1.0; static bool math_spacing = false; static int skew_char = -1; +static bool override_is_fixed_pitch = false; +static bool is_fixed_pitch; +static bool override_italic_angle = false; +static double italic_angle; static String out_encoding_file; static String out_encoding_name; @@ -312,6 +329,8 @@ Font feature and transformation options:\n\ -k, --min-kern=N Omit kerns with absolute value < N [2.0].\n\ --space-factor=F Scale wordspace by a factor of F.\n\ --design-size=SIZE Set font design size to SIZE.\n\ + --fixed-width Set fixed width (no space stretch).\n\ + --italic-angle=ANGLE Set font italic angle (for positioning accents).\n\ \n"); uerrh.message("\ Encoding options:\n\ @@ -592,10 +611,10 @@ output_pl(Metrics &metrics, const String &ps_name, int boundary_char, } int xheight = font_x_height(finfo, font_xform); - if (xheight < 1000) + if (xheight * du < 1000) fprint_real(f, " (XHEIGHT", xheight, du); - fprint_real(f, " (QUAD", 1000, du); + fprint_real(f, " (QUAD", finfo.units_per_em(), du); fprintf(f, " )\n"); if (boundary_char >= 0) @@ -1271,9 +1290,15 @@ main_dvips_map(const String &ps_name, const FontInfo &finfo, ErrorHandler *errh) { if (String fn = installed_type1(otf_filename, ps_name, (output_flags & G_TYPE1) != 0, errh)) return "<" + pathname_filename(fn); - if (!finfo.cff) - if (String fn = installed_truetype(otf_filename, (output_flags & G_TRUETYPE) != 0, errh)) - return "<" + pathname_filename(fn); + if (!finfo.cff) { + String ttf_fn, t42_fn; + ttf_fn = installed_truetype(otf_filename, (output_flags & G_TRUETYPE) != 0, errh); + t42_fn = installed_type42(otf_filename, ps_name, (output_flags & G_TYPE42) != 0, errh); + if (t42_fn && (!ttf_fn || (output_flags & G_TYPE42) != 0)) + return "<" + pathname_filename(t42_fn); + else if (ttf_fn) + return "<" + pathname_filename(ttf_fn); + } return "<" + pathname_filename(otf_filename); } @@ -1339,12 +1364,53 @@ do_gsub(Metrics& metrics, const OpenType::Font& otf, DvipsEncoding& dvipsenc, bo } } +static bool +kern_feature_requested() +{ + return std::find(interesting_features.begin(), interesting_features.end(), + OpenType::Tag("kern")) != interesting_features.end(); +} + +static void +do_try_ttf_kern(Metrics& metrics, const OpenType::Font& otf, HashMap<uint32_t, int>& feature_usage, ErrorHandler* errh) +{ + // if no GPOS "kern" lookups and "kern" requested, try "kern" table + if (!kern_feature_requested()) + return; + try { + OpenType::KernTable kern(otf.table("kern"), errh); + Vector<OpenType::Positioning> poss; + bool understood = kern.unparse_automatics(poss, errh); + int nunderstood = metrics.apply(poss); + + // mark as used + int d = (understood && nunderstood == poss.size() ? F_GPOS_ALL : (nunderstood ? F_GPOS_PART : 0)) + F_GPOS_TRY; + feature_usage.find_force(OpenType::Tag("kern").value()) |= d; + } catch (OpenType::BlankTable) { + // nada + } catch (OpenType::Error e) { + errh->warning("kern %<%s%> error, continuing", e.description.c_str()); + } +} + static void do_gpos(Metrics& metrics, const OpenType::Font& otf, HashMap<uint32_t, int>& feature_usage, ErrorHandler* errh) { OpenType::Gpos gpos(otf.table("GPOS"), errh); Vector<Lookup> lookups(gpos.nlookups(), Lookup()); find_lookups(gpos.script_list(), gpos.feature_list(), lookups, errh); + + // OpenType recommends that if GPOS exists, but the "kern" feature loads + // no lookups, we use the TrueType "kern" table, if any. + if (kern_feature_requested()) { + OpenType::Tag kern_tag("kern"); + for (Lookup *l = lookups.begin(); l != lookups.end(); ++l) + if (std::find(l->features.begin(), l->features.end(), kern_tag) != l->features.end()) + goto skip_ttf_kern; + do_try_ttf_kern(metrics, otf, feature_usage, errh); + skip_ttf_kern: ; + } + Vector<OpenType::Positioning> poss; for (int i = 0; i < lookups.size(); i++) if (lookups[i].used) { @@ -1361,19 +1427,6 @@ do_gpos(Metrics& metrics, const OpenType::Font& otf, HashMap<uint32_t, int>& fea } static void -do_kern(Metrics& metrics, const OpenType::Font& otf, HashMap<uint32_t, int>& feature_usage, ErrorHandler* errh) -{ - OpenType::KernTable kern(otf.table("kern"), errh); - Vector<OpenType::Positioning> poss; - bool understood = kern.unparse_automatics(poss, errh); - int nunderstood = metrics.apply(poss); - - // mark as used - int d = (understood && nunderstood == poss.size() ? F_GPOS_ALL : (nunderstood ? F_GPOS_PART : 0)) + F_GPOS_TRY; - feature_usage.find_force(OpenType::Tag("kern").value()) |= d; -} - -static void do_math_spacing(Metrics &metrics, const FontInfo &finfo, const DvipsEncoding &dvipsenc) { @@ -1415,6 +1468,10 @@ do_file(const String &otf_filename, const OpenType::Font &otf, return; if (!finfo.cff) errh->warning("TrueType-flavored font support is experimental"); + if (override_is_fixed_pitch) + finfo.set_is_fixed_pitch(is_fixed_pitch); + if (override_italic_angle) + finfo.set_italic_angle(italic_angle); // save glyph names Vector<PermString> glyph_names; @@ -1472,17 +1529,7 @@ do_file(const String &otf_filename, const OpenType::Font &otf, try { do_gpos(metrics, otf, feature_usage, errh); } catch (OpenType::BlankTable) { - // special case: if no GPOS and "kern" requested, look in "kern" table - if (std::find(interesting_features.begin(), interesting_features.end(), - OpenType::Tag("kern")) != interesting_features.end()) { - try { - do_kern(metrics, otf, feature_usage, errh); - } catch (OpenType::BlankTable) { - // nada - } catch (OpenType::Error e) { - errh->warning("kern %<%s%> error, continuing", e.description.c_str()); - } - } + do_try_ttf_kern(metrics, otf, feature_usage, errh); } catch (OpenType::Error e) { errh->warning("GPOS %<%s%> error, continuing", e.description.c_str()); } @@ -1926,10 +1973,17 @@ main(int argc, char *argv[]) case NO_TYPE1_OPT: case NO_DOTLESSJ_OPT: case NO_UPDMAP_OPT: - case NO_TRUETYPE_OPT: output_flags &= ~(opt - NO_OUTPUT_OPTS); break; + case TRUETYPE_OPT: + case TYPE42_OPT: + if (!clp->negated) + output_flags |= (opt - YES_OUTPUT_OPTS); + else + output_flags &= ~(opt - YES_OUTPUT_OPTS); + break; + case OUTPUT_ENCODING_OPT: if (out_encoding_file) usage_error(errh, "encoding output file specified twice"); @@ -1959,13 +2013,14 @@ main(int argc, char *argv[]) output_flags = (output_flags & ~G_ASCII) | G_BINARY; break; - case ENCODING_DIR_OPT: - case TFM_DIR_OPT: - case PL_DIR_OPT: - case VF_DIR_OPT: - case VPL_DIR_OPT: - case TYPE1_DIR_OPT: - case TRUETYPE_DIR_OPT: + case ENCODING_DIR_OPT: + case TFM_DIR_OPT: + case PL_DIR_OPT: + case VF_DIR_OPT: + case VPL_DIR_OPT: + case TYPE1_DIR_OPT: + case TRUETYPE_DIR_OPT: + case TYPE42_DIR_OPT: if (!setodir(opt - DIR_OPTS, clp->vstr)) usage_error(errh, "%s directory specified twice", odirname(opt - DIR_OPTS)); break; @@ -1977,6 +2032,21 @@ main(int argc, char *argv[]) font_name = clp->vstr; break; + case FIXED_PITCH_OPT: + override_is_fixed_pitch = true; + is_fixed_pitch = !clp->negated; + break; + + case PROPORTIONAL_WIDTH_OPT: + override_is_fixed_pitch = true; + is_fixed_pitch = !!clp->negated; + break; + + case ITALIC_ANGLE_OPT: + override_italic_angle = true; + italic_angle = clp->val.d; + break; + case GLYPHLIST_OPT: glyphlist_files.push_back(clp->vstr); break; @@ -2020,7 +2090,7 @@ main(int argc, char *argv[]) case VERSION_OPT: printf("otftotfm (LCDF typetools) %s\n", VERSION); - printf("Copyright (C) 2002-2009 Eddie Kohler\n\ + printf("Copyright (C) 2002-2010 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"); @@ -2056,7 +2126,7 @@ particular purpose.\n"); done: // check for odd option combinations - if (warn_missing && !(output_flags & G_VMETRICS)) + if (warn_missing > 0 && !(output_flags & G_VMETRICS)) errh->warning("%<--warn-missing%> has no effect with %<--no-virtual%>"); // set up file names diff --git a/Build/source/texk/lcdf-typetools/otftotfm/secondary.cc b/Build/source/texk/lcdf-typetools/otftotfm/secondary.cc index 1d1c8094901..4a48f52fadb 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/secondary.cc +++ b/Build/source/texk/lcdf-typetools/otftotfm/secondary.cc @@ -1,6 +1,6 @@ /* secondary.{cc,hh} -- code for generating fake glyphs * - * Copyright (c) 2003-2006 Eddie Kohler + * Copyright (c) 2003-2010 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 @@ -82,7 +82,8 @@ enum { U_EXCLAMDOWN = 0x00A1, // U+00A1 INVERTED EXCLAMATION MARK FontInfo::FontInfo(const Efont::OpenType::Font *otf_, ErrorHandler *errh) : otf(otf_), cmap(0), cff_file(0), cff(0), post(0), name(0), _nglyphs(-1), - _got_glyph_names(false), _ttb_program(0) + _got_glyph_names(false), _ttb_program(0), _override_is_fixed_pitch(false), + _override_italic_angle(false) { cmap = new Efont::OpenType::Cmap(otf->table("cmap"), errh); assert(cmap->ok()); @@ -190,7 +191,9 @@ FontInfo::program() const bool FontInfo::is_fixed_pitch() const { - if (cff) { + if (_override_is_fixed_pitch) + return _is_fixed_pitch; + else if (cff) { double d; return (cff->dict_value(Efont::Cff::oIsFixedPitch, &d) && d); } else @@ -200,7 +203,9 @@ FontInfo::is_fixed_pitch() const double FontInfo::italic_angle() const { - if (cff) { + if (_override_italic_angle) + return _italic_angle; + else if (cff) { double d; (void) cff->dict_value(Efont::Cff::oItalicAngle, &d); return d; @@ -231,7 +236,9 @@ Secondary::encode_uni(int code, PermString name, uint32_t uni, Metrics &metrics, T1Secondary::T1Secondary(const FontInfo &finfo, const String &font_name, const String &otf_file_name) : _finfo(finfo), _font_name(font_name), _otf_file_name(otf_file_name), - _xheight(font_x_height(finfo, Transform())), _spacewidth(1000) + _units_per_em(finfo.units_per_em()), + _xheight(font_x_height(finfo, Transform())), + _spacewidth(_units_per_em) { int bounds[4], width; if (char_bounds(bounds, width, finfo, Transform(), ' ')) @@ -595,14 +602,14 @@ T1Secondary::setting(uint32_t uni, Vector<Setting> &v, Metrics &metrics, ErrorHa break; case U_RINGFITTED: { - int A_width = char_one_bound(_finfo, xform, 4, true, -1000, 'A', 0); + int A_width = char_one_bound(_finfo, xform, 4, true, -_units_per_em, 'A', 0); uint32_t ring_char = U_RINGABOVE; - int ring_width = char_one_bound(_finfo, xform, 4, true, -1000, ring_char, 0); - if (ring_width <= -1000) { + int ring_width = char_one_bound(_finfo, xform, 4, true, -_units_per_em, ring_char, 0); + if (ring_width <= -_units_per_em) { ring_char = U_COMBININGRINGABOVE; - ring_width = char_one_bound(_finfo, xform, 4, true, -1000, ring_char, 0); + ring_width = char_one_bound(_finfo, xform, 4, true, -_units_per_em, ring_char, 0); } - if (A_width > -1000 && ring_width > -1000) { + if (A_width > -_units_per_em && ring_width > -_units_per_em) { int offset = (A_width - ring_width) / 2; v.push_back(Setting(Setting::MOVE, offset, 0)); if (char_setting(v, metrics, ring_char, 0)) { @@ -663,7 +670,7 @@ font_x_height(const FontInfo &finfo, const Transform &font_xform) return os2.x_height(); } catch (Efont::OpenType::Bounds) { // XXX what if 'x', 'm', 'z' were subject to substitution? - return char_one_bound(finfo, font_xform, 3, false, 1000, + return char_one_bound(finfo, font_xform, 3, false, finfo.units_per_em(), 'x', 'm', 'z', 0); } } @@ -676,7 +683,7 @@ font_cap_height(const FontInfo &finfo, const Transform &font_xform) return os2.cap_height(); } catch (Efont::OpenType::Bounds) { // XXX what if 'H', 'O', 'B' were subject to substitution? - return char_one_bound(finfo, font_xform, 3, false, 1000, + return char_one_bound(finfo, font_xform, 3, false, finfo.units_per_em(), 'H', 'O', 'B', 0); } } diff --git a/Build/source/texk/lcdf-typetools/otftotfm/secondary.hh b/Build/source/texk/lcdf-typetools/otftotfm/secondary.hh index bfe31bf04d7..875068078ed 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/secondary.hh +++ b/Build/source/texk/lcdf-typetools/otftotfm/secondary.hh @@ -27,10 +27,22 @@ struct FontInfo { bool glyph_names(Vector<PermString> &) const; int glyphid(PermString) const; const Efont::CharstringProgram *program() const; + int units_per_em() const { + return program()->units_per_em(); + } bool is_fixed_pitch() const; double italic_angle() const; + void set_is_fixed_pitch(bool is_fixed_pitch) { + _override_is_fixed_pitch = true; + _is_fixed_pitch = is_fixed_pitch; + } + void set_italic_angle(double italic_angle) { + _override_italic_angle = true; + _italic_angle = italic_angle; + } + String family_name() const; String postscript_name() const; @@ -41,6 +53,10 @@ struct FontInfo { mutable bool _got_glyph_names; mutable Vector<uint32_t> _unicodes; mutable Efont::TrueTypeBoundsCharstringProgram *_ttb_program; + bool _override_is_fixed_pitch; + bool _override_italic_angle; + bool _is_fixed_pitch; + double _italic_angle; }; @@ -63,6 +79,7 @@ class T1Secondary : public Secondary { public: const FontInfo &_finfo; String _font_name; String _otf_file_name; + int _units_per_em; int _xheight; int _spacewidth; bool char_setting(Vector<Setting> &, Metrics &, int uni, ...); diff --git a/Build/source/texk/lcdf-typetools/otftotfm/uniprop.cc b/Build/source/texk/lcdf-typetools/otftotfm/uniprop.cc index b38b022aa3b..e37d66e6599 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/uniprop.cc +++ b/Build/source/texk/lcdf-typetools/otftotfm/uniprop.cc @@ -1,6 +1,6 @@ /* uniprop.{cc,hh} -- code for Unicode character properties * - * Copyright (c) 2004-2007 Eddie Kohler + * Copyright (c) 2004-2010 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 diff --git a/Build/source/texk/lcdf-typetools/otftotfm/util.cc b/Build/source/texk/lcdf-typetools/otftotfm/util.cc index 2aecdaa5f6a..241d2eb733c 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/util.cc +++ b/Build/source/texk/lcdf-typetools/otftotfm/util.cc @@ -1,6 +1,6 @@ /* util.{cc,hh} -- various bits * - * Copyright (c) 2003-2006 Eddie Kohler + * Copyright (c) 2003-2010 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 diff --git a/Build/source/texk/lcdf-typetools/otftotfm/util.hh b/Build/source/texk/lcdf-typetools/otftotfm/util.hh index df59f63af14..a3e42b63d9f 100644 --- a/Build/source/texk/lcdf-typetools/otftotfm/util.hh +++ b/Build/source/texk/lcdf-typetools/otftotfm/util.hh @@ -10,7 +10,7 @@ extern bool force; enum { G_ENCODING = 1, G_METRICS = 2, G_VMETRICS = 4, G_TYPE1 = 8, G_PSFONTSMAP = 16, G_BINARY = 32, G_ASCII = 64, G_DOTLESSJ = 128, - G_UPDMAP = 256, G_TRUETYPE = 512 }; + G_UPDMAP = 256, G_TRUETYPE = 512, G_TYPE42 = 1024 }; extern int output_flags; |