summaryrefslogtreecommitdiff
path: root/Build/source/texk/lcdf-typetools/otftotfm
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/lcdf-typetools/otftotfm')
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/Makefile.am8
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/Makefile.in2
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/automatic.cc73
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/automatic.hh3
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/dvipsencoding.cc2
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/glyphfilter.cc2
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/kpseinterface.c2
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/metrics.cc343
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/metrics.hh37
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/otftotfm.161
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/otftotfm.cc192
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/secondary.cc31
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/secondary.hh17
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/uniprop.cc2
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/util.cc2
-rw-r--r--Build/source/texk/lcdf-typetools/otftotfm/util.hh2
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;