summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/font
diff options
context:
space:
mode:
authorMartin Schröder <martin@oneiros.de>2008-03-24 15:47:15 +0000
committerMartin Schröder <martin@oneiros.de>2008-03-24 15:47:15 +0000
commit0b5550c241229764120d133af80a0cbab5937ddd (patch)
tree81309c18d6f0deba7407813cf15b9add2db375d1 /Build/source/texk/web2c/luatexdir/font
parent51f55df6a36ce376952a1f2b30bdb4dd0e06548d (diff)
First step of importing luatex (up to r1121)
git-svn-id: svn://tug.org/texlive/trunk@7124 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/font')
-rw-r--r--Build/source/texk/web2c/luatexdir/font/.indent.pro12
-rw-r--r--Build/source/texk/web2c/luatexdir/font/dofont.c183
-rw-r--r--Build/source/texk/web2c/luatexdir/font/luafont.c1733
-rw-r--r--Build/source/texk/web2c/luatexdir/font/macnames.c312
-rw-r--r--Build/source/texk/web2c/luatexdir/font/mapfile.c967
-rw-r--r--Build/source/texk/web2c/luatexdir/font/pkin.c439
-rw-r--r--Build/source/texk/web2c/luatexdir/font/sfnt.c647
-rw-r--r--Build/source/texk/web2c/luatexdir/font/sfnt.h197
-rw-r--r--Build/source/texk/web2c/luatexdir/font/subfont.c264
-rw-r--r--Build/source/texk/web2c/luatexdir/font/subfont.txt74
-rw-r--r--Build/source/texk/web2c/luatexdir/font/texfont.c1094
-rw-r--r--Build/source/texk/web2c/luatexdir/font/texfont.h524
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tfmofm.c1005
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tounicode.c604
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tt_glyf.c658
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tt_glyf.h60
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tt_table.c483
-rw-r--r--Build/source/texk/web2c/luatexdir/font/tt_table.h193
-rw-r--r--Build/source/texk/web2c/luatexdir/font/vfovf.c1349
-rw-r--r--Build/source/texk/web2c/luatexdir/font/vfpacket.c377
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writecff.c3381
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writecff.h349
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writeenc.c183
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writefont.c885
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writet1.c1768
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writet3.c348
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writettf.c1509
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writettf.h172
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writetype0.c124
-rw-r--r--Build/source/texk/web2c/luatexdir/font/writetype2.c422
30 files changed, 20316 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/font/.indent.pro b/Build/source/texk/web2c/luatexdir/font/.indent.pro
new file mode 100644
index 00000000000..e9e690f1ba8
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/.indent.pro
@@ -0,0 +1,12 @@
+/* $Id$ */
+--k-and-r-style
+--blank-lines-after-procedures
+--line-length 80
+--procnames-start-lines
+--no-space-after-function-call-names
+--dont-break-procedure-type
+--space-after-cast
+/* this does not work in indent 2.2.6 :-( */
+--no-tabs
+/* this is new in indent 2.2.9 */
+--preprocessor-indentation 2
diff --git a/Build/source/texk/web2c/luatexdir/font/dofont.c b/Build/source/texk/web2c/luatexdir/font/dofont.c
new file mode 100644
index 00000000000..fbe44c29ba9
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/dofont.c
@@ -0,0 +1,183 @@
+/*
+Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with LuaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: dofont.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+#include "luatex-api.h"
+
+#define TIMERS 0
+
+#if TIMERS
+#include <sys/time.h>
+#endif
+
+
+/* a bit more interfacing is needed for proper error reporting */
+
+static char *
+font_error_message (pointer u, char *nom, scaled s) {
+ char *str = xmalloc(256);
+ char *c = makecstring(zget_cs_text(u));
+ char *extra = "metric data not found or bad";
+ if (s>=0 ) {
+ snprintf(str,255,"Font \\%s=%s at %gpt not loadable: %s", c, nom, (double)s/65536, extra);
+ } else if (s!=-1000) {
+ snprintf(str,255,"Font \\%s=%s scaled %d not loadable: %s", c, nom, (int)(-s), extra);
+ } else {
+ snprintf(str,255,"Font \\%s=%s not loadable: %s", c, nom, extra);
+ }
+ return str;
+}
+
+static int
+do_define_font (integer f, char *cnom, char *caire, scaled s, integer natural_dir) {
+
+ boolean res; /* was the callback successful? */
+ integer callback_id;
+ char *cnam;
+#if TIMERS
+ struct timeval tva;
+ struct timeval tvb;
+ double tvdiff;
+#endif
+ int r;
+ res = 0;
+
+ callback_id=callback_defined(define_font_callback);
+ if (callback_id>0) {
+ if (caire == NULL || strlen(caire)==0) {
+ cnam = xstrdup(cnom);
+ } else {
+ cnam = xmalloc(strlen(cnom)+strlen(caire)+2);
+ sprintf(cnam,"%s/%s",caire,cnom);
+ }
+#if TIMERS
+ gettimeofday(&tva,NULL);
+#endif
+ callback_id = run_and_save_callback(callback_id,"Sdd->",cnam,s,f);
+#if TIMERS
+ gettimeofday(&tvb,NULL);
+ tvdiff = tvb.tv_sec*1000000.0;
+ tvdiff += (double)tvb.tv_usec;
+ tvdiff -= (tva.tv_sec*1000000.0);
+ tvdiff -= (double)tva.tv_usec;
+ tvdiff /= 1000000;
+ fprintf(stdout,"\ncallback('define_font',%s,%i): %f seconds\n", cnam,f,tvdiff);
+#endif
+ free(cnam);
+ if (callback_id>0) { /* success */
+ luaL_checkstack(Luas[0],1,"out of stack space");
+ lua_rawgeti(Luas[0],LUA_REGISTRYINDEX, callback_id);
+ if (lua_istable(Luas[0],-1)) {
+#if TIMERS
+ gettimeofday(&tva,NULL);
+#endif
+ res = font_from_lua(Luas[0],f);
+ destroy_saved_callback (callback_id);
+#if TIMERS
+ gettimeofday(&tvb,NULL);
+ tvdiff = tvb.tv_sec*1000000.0;
+ tvdiff += (double)tvb.tv_usec;
+ tvdiff -= (tva.tv_sec*1000000.0);
+ tvdiff -= (double)tva.tv_usec;
+ tvdiff /= 1000000;
+ fprintf(stdout,"font_from_lua(%s,%i): %f seconds\n", font_name(f),f,tvdiff);
+#endif
+ lua_pop(Luas[0],1);
+ } else if (lua_isnumber(Luas[0],-1)) {
+ r = lua_tonumber(Luas[0],-1);
+ destroy_saved_callback (callback_id);
+ delete_font(f);
+ lua_pop(Luas[0],1);
+ return r;
+ } else {
+ lua_pop(Luas[0],1);
+ delete_font(f);
+ return 0;
+ }
+ }
+ } else {
+ res = read_tfm_info(f,cnom,caire,s);
+ if (res) {
+ set_hyphen_char(f,get_default_hyphen_char());
+ set_skew_char(f,get_default_skew_char());
+ }
+ }
+ if (res) {
+ do_vf(f);
+ set_font_natural_dir(f,natural_dir);
+ return f;
+ } else {
+ delete_font(f);
+ return 0;
+ }
+
+}
+
+int
+read_font_info(pointer u, strnumber nom, strnumber aire, scaled s,
+ integer natural_dir) {
+ integer f;
+ char *cnom, *caire = NULL;
+ char *msg;
+ cnom = xstrdup(makecstring(nom));
+ if (aire != 0)
+ caire = xstrdup(makecstring(aire));
+
+ f = new_font();
+ if ((f = do_define_font(f, cnom,caire,s,natural_dir))) {
+ if (caire != NULL) free(caire);
+ free(cnom);
+ return f;
+ } else {
+ char *help[] = {"I wasn't able to read the size data for this font,",
+ "so I will ignore the font specification.",
+ "[Wizards can fix TFM files using TFtoPL/PLtoTF.]",
+ "You might try inserting a different font spec;",
+ "e.g., type `I\font<same font id>=<substitute font name>'.",
+ NULL } ;
+ if(!get_suppress_fontnotfound_error()) {
+ msg = font_error_message(u, cnom, s);
+ tex_error(msg,help);
+ free(msg);
+ }
+ if (caire != NULL) free(caire);
+ free(cnom);
+ return 0;
+ }
+}
+
+/* TODO This function is a placeholder. There can easily appears holes in
+ the |font_tables| array, and we could attempt to reuse those
+*/
+
+int
+find_font_id (char *nom, char *aire, scaled s) {
+ integer f;
+ f = new_font();
+ if ((f = do_define_font(f, nom, aire,s,-1))) {
+ return f;
+ } else {
+ return 0;
+ }
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/luafont.c b/Build/source/texk/web2c/luatexdir/font/luafont.c
new file mode 100644
index 00000000000..be32e39de9f
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/luafont.c
@@ -0,0 +1,1733 @@
+
+#include "luatex-api.h"
+#include <ptexlib.h>
+
+#include "nodes.h"
+
+#define noVERBOSE
+
+#define SAVE_REF 1
+
+char *font_type_strings[] = {"unknown","virtual","real", NULL};
+char *font_format_strings[] = {"unknown","type1","type3","truetype", "opentype", NULL};
+char *font_embedding_strings[] = {"unknown","no","subset", "full", NULL};
+char *ligature_type_strings[] = {"=:", "=:|", "|=:", "|=:|", "", "=:|>", "|=:>", "|=:|>", "", "", "", "|=:|>>", NULL };
+
+void
+font_char_to_lua (lua_State *L, internalfontnumber f, charinfo *co) {
+ int i;
+ liginfo *l;
+ kerninfo *ki;
+
+ lua_createtable(L,0,10);
+
+ lua_pushstring(L,"width");
+ lua_pushnumber(L,get_charinfo_width(co));
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"height");
+ lua_pushnumber(L,get_charinfo_height(co));
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"depth");
+ lua_pushnumber(L,get_charinfo_depth(co));
+ lua_rawset(L,-3);
+
+ lua_pushstring(L,"italic");
+ lua_pushnumber(L,get_charinfo_italic(co));
+ lua_rawset(L,-3);
+
+ if (get_charinfo_ef(co)!=0) {
+ lua_pushstring(L,"expansion_factor");
+ lua_pushnumber(L,get_charinfo_ef(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_lp(co)!=0) {
+ lua_pushstring(L,"left_protruding");
+ lua_pushnumber(L,get_charinfo_lp(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_lp(co)!=0) {
+ lua_pushstring(L,"right_protruding");
+ lua_pushnumber(L,get_charinfo_rp(co));
+ lua_rawset(L,-3);
+ }
+
+
+ if (font_encodingbytes(f) == 2 ) {
+ lua_pushstring(L,"index");
+ lua_pushnumber(L,get_charinfo_index(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_name(co)!=NULL) {
+ lua_pushstring(L,"name");
+ lua_pushstring(L,get_charinfo_name(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_tounicode(co)!=NULL) {
+ lua_pushstring(L,"tounicode");
+ lua_pushstring(L,get_charinfo_tounicode(co));
+ lua_rawset(L,-3);
+ }
+
+ if (get_charinfo_tag(co) == list_tag) {
+ lua_pushstring(L,"next");
+ lua_pushnumber(L,get_charinfo_remainder(co));
+ lua_rawset(L,-3);
+ }
+
+ lua_pushstring(L,"used");
+ lua_pushboolean(L,(get_charinfo_used(co) ? true : false));
+ lua_rawset(L,-3);
+
+ if (get_charinfo_tag(co) == ext_tag) {
+ lua_pushstring(L,"extensible");
+ lua_createtable(L,0,4);
+ lua_pushnumber(L,get_charinfo_extensible(co,EXT_TOP));
+ lua_setfield(L,-2,"top");
+ lua_pushnumber(L,get_charinfo_extensible(co,EXT_BOT));
+ lua_setfield(L,-2,"bot");
+ lua_pushnumber(L,get_charinfo_extensible(co,EXT_MID));
+ lua_setfield(L,-2,"mid");
+ lua_pushnumber(L,get_charinfo_extensible(co,EXT_REP));
+ lua_setfield(L,-2,"rep");
+ lua_rawset(L,-3);
+ }
+ ki = get_charinfo_kerns(co);
+ if (ki != NULL) {
+ lua_pushstring(L,"kerns");
+ lua_createtable(L,10,1);
+ for (i=0;!kern_end(ki[i]);i++) {
+ if (kern_char(ki[i]) == right_boundarychar) {
+ lua_pushstring(L,"right_boundary");
+ } else {
+ lua_pushnumber(L,kern_char(ki[i]));
+ }
+ lua_pushnumber(L,kern_kern(ki[i]));
+ lua_rawset(L,-3);
+ }
+ lua_rawset(L,-3);
+ }
+ l = get_charinfo_ligatures(co);
+ if (l!=NULL) {
+ lua_pushstring(L,"ligatures");
+ lua_createtable(L,10,1);
+ for (i=0;!lig_end(l[i]);i++) {
+ if (lig_char(l[i]) == right_boundarychar) {
+ lua_pushstring(L,"right_boundary");
+ } else {
+ lua_pushnumber(L,lig_char(l[i]));
+ }
+ lua_createtable(L,0,2);
+ lua_pushstring(L,"type");
+ lua_pushnumber(L,lig_type(l[i]));
+ lua_rawset(L,-3);
+ lua_pushstring(L,"char");
+ lua_pushnumber(L,lig_replacement(l[i]));
+ lua_rawset(L,-3);
+ lua_rawset(L,-3);
+ }
+ lua_rawset(L,-3);
+ }
+}
+
+static void
+write_lua_parameters (lua_State *L, int f) {
+ int k;
+ lua_newtable(L);
+ for (k=1;k<=font_params(f);k++) {
+ lua_pushnumber(L,font_param(f,k));
+ switch (k) {
+ case slant_code: lua_setfield(L,-2,"slant"); break;
+ case space_code: lua_setfield(L,-2,"space"); break;
+ case space_stretch_code: lua_setfield(L,-2,"space_stretch"); break;
+ case space_shrink_code: lua_setfield(L,-2,"space_shrink"); break;
+ case x_height_code: lua_setfield(L,-2,"x_height"); break;
+ case quad_code: lua_setfield(L,-2,"quad"); break;
+ case extra_space_code: lua_setfield(L,-2,"extra_space"); break;
+ default:
+ lua_rawseti(L,-2,k);
+ }
+ }
+ lua_setfield(L,-2,"parameters");
+}
+
+
+int
+font_to_lua (lua_State *L, int f) {
+ int k;
+ charinfo *co;
+ if (font_cache_id(f)) {
+ /* fetch the table from the registry if it was
+ saved there by font_from_lua() */
+ lua_rawgeti(L,LUA_REGISTRYINDEX,font_cache_id(f));
+ /* fontdimens can be changed from tex code */
+ write_lua_parameters(L,f);
+ return 1;
+ }
+
+ lua_newtable(L);
+ lua_pushstring(L,font_name(f));
+ lua_setfield(L,-2,"name");
+ if(font_area(f)!=NULL) {
+ lua_pushstring(L,font_area(f));
+ lua_setfield(L,-2,"area");
+ }
+ if(font_filename(f)!=NULL) {
+ lua_pushstring(L,font_filename(f));
+ lua_setfield(L,-2,"filename");
+ }
+ if(font_fullname(f)!=NULL) {
+ lua_pushstring(L,font_fullname(f));
+ lua_setfield(L,-2,"fullname");
+ }
+ if(font_encodingname(f)!=NULL) {
+ lua_pushstring(L,font_encodingname(f));
+ lua_setfield(L,-2,"encodingname");
+ }
+
+ lua_pushboolean(L,(font_used(f) ? true : false));
+ lua_setfield(L,-2,"used");
+
+
+ lua_pushstring(L,font_type_strings[font_type(f)]);
+ lua_setfield(L,-2,"type");
+ lua_pushstring(L,font_format_strings[font_format(f)]);
+ lua_setfield(L,-2,"format");
+ lua_pushstring(L,font_embedding_strings[font_embedding(f)]);
+ lua_setfield(L,-2,"embedding");
+
+ lua_pushnumber(L,font_size(f));
+ lua_setfield(L,-2,"size");
+ lua_pushnumber(L,font_dsize(f));
+ lua_setfield(L,-2,"designsize");
+ lua_pushnumber(L,font_checksum(f));
+ lua_setfield(L,-2,"checksum");
+ lua_pushnumber(L,font_slant(f));
+ lua_setfield(L,-2,"slant");
+ lua_pushnumber(L,font_extend(f));
+ lua_setfield(L,-2,"extend");
+ lua_pushnumber(L,font_natural_dir(f));
+ lua_setfield(L,-2,"direction");
+ lua_pushnumber(L,font_encodingbytes(f));
+ lua_setfield(L,-2,"encodingbytes");
+ lua_pushnumber(L,font_tounicode(f));
+ lua_setfield(L,-2,"tounicode");
+
+ /* pdf parameters */
+ /* skip the first four for now, that are very much interal */
+ /*
+ if (pdf_font_size(f) != 0) {
+ lua_pushnumber(L,pdf_font_size(f));
+ lua_setfield(L,-2,"pdf_size");
+ }
+ if (pdf_font_num(f) != 0) {
+ lua_pushnumber(L,pdf_font_num(f));
+ lua_setfield(L,-2,"pdf_num");
+ }
+ if (pdf_font_blink(f) != 0) {
+ lua_pushnumber(L,pdf_font_blink(f));
+ lua_setfield(L,-2,"pdf_blink");
+ }
+ if (pdf_font_elink(f) != 0) {
+ lua_pushnumber(L,pdf_font_elink(f));
+ lua_setfield(L,-2,"pdf_elink");
+ }
+ */
+ /* the next one is read only */
+ if (pdf_font_expand_ratio(f) != 0) {
+ lua_pushnumber(L,pdf_font_expand_ratio(f));
+ lua_setfield(L,-2,"expand_ratio");
+ }
+ if (pdf_font_shrink(f) != 0) {
+ lua_pushnumber(L,pdf_font_shrink(f));
+ lua_setfield(L,-2,"shrink");
+ }
+ if (pdf_font_stretch(f) != 0) {
+ lua_pushnumber(L,pdf_font_stretch(f));
+ lua_setfield(L,-2,"stretch");
+ }
+ if (pdf_font_step(f) != 0) {
+ lua_pushnumber(L,pdf_font_step(f));
+ lua_setfield(L,-2,"step");
+ }
+ if (pdf_font_auto_expand(f) != 0) {
+ lua_pushboolean(L,pdf_font_auto_expand(f));
+ lua_setfield(L,-2,"auto_expand");
+ }
+ if (pdf_font_attr(f) != 0) {
+ lua_pushstring(L,makecstring(pdf_font_attr(f)));
+ lua_setfield(L,-2,"attributes");
+ }
+
+ /* params */
+ write_lua_parameters(L,f);
+
+ /* chars */
+ lua_createtable(L,font_tables[f]->charinfo_size,0); /* all characters */
+
+ if (has_left_boundary(f)) {
+ co = get_charinfo(f,left_boundarychar);
+ font_char_to_lua(L,f,co);
+ lua_setfield(L,-2,"left_boundary");
+ }
+ if (has_right_boundary(f)) {
+ co = get_charinfo(f,right_boundarychar);
+ font_char_to_lua(L,f,co);
+ lua_setfield(L,-2,"right_boundary");
+ }
+
+ for (k=font_bc(f);k<=font_ec(f);k++) {
+ if (char_exists(f,k)) {
+ lua_pushnumber(L,k);
+ co = get_charinfo(f,k);
+ font_char_to_lua(L,f,co);
+ lua_rawset(L,-3);
+ }
+ }
+ lua_setfield(L,-2,"characters");
+ return 1;
+}
+
+static int
+count_hash_items (lua_State *L, int name_index){
+ int n = -1;
+ lua_rawgeti(L,LUA_REGISTRYINDEX,name_index);
+ lua_rawget(L,-2);
+ if (!lua_isnil(L,-1)) {
+ if (lua_istable(L,-1)) {
+ n = 0;
+ /* now find the number */
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ n++;
+ lua_pop(L,1);
+ }
+ }
+ }
+ lua_pop(L,1);
+ return n;
+}
+
+#define streq(a,b) (strcmp(a,b)==0)
+
+#define append_packet(k) { cpackets[np++] = k; }
+
+#define do_store_four(l) { \
+ append_packet((l&0xFF000000)>>24); \
+ append_packet((l&0x00FF0000)>>16); \
+ append_packet((l&0x0000FF00)>>8); \
+ append_packet((l&0x000000FF)); }
+
+/*
+*/
+
+#define lua_roundnumber(a,b) (int)floor((double)lua_tonumber(L,-1)+0.5)
+
+static int
+numeric_field (lua_State *L, char *name, int dflt) {
+ int i = dflt;
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isnumber(L,-1)) {
+ i = lua_roundnumber(L,-1);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+static int
+n_numeric_field (lua_State *L, int name_index, int dflt) {
+ register int i = dflt;
+ lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
+ lua_rawget(L,-2);
+ if (lua_type(L,-1)==LUA_TNUMBER) {
+ i = lua_roundnumber(L,-1);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+
+static int
+enum_field (lua_State *L, char *name, int dflt, char **values) {
+ int k;
+ char *s;
+ int i = dflt;
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isnumber(L,-1)) {
+ i = lua_tonumber(L,-1);
+ } else if (lua_isstring(L,-1)) {
+ s = (char *)lua_tostring(L,-1);
+ k = 0;
+ while (values[k] != NULL) {
+ if (strcmp(values[k],s) == 0) {
+ i = k;
+ break;
+ }
+ k++;
+ }
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+static int
+boolean_field (lua_State *L, char *name, int dflt) {
+ int i = dflt;
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isboolean(L,-1)) {
+ i = lua_toboolean(L,-1);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+static int
+n_boolean_field (lua_State *L, int name_index, int dflt) {
+ int i = dflt;
+ lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
+ lua_rawget(L,-2);
+ if (lua_isboolean(L,-1)) {
+ i = lua_toboolean(L,-1);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+
+static char *
+string_field (lua_State *L, char *name, char *dflt) {
+ char *i;
+ lua_pushstring(L,name);
+ lua_rawget(L,-2);
+ if (lua_isstring(L,-1)) {
+ i = xstrdup(lua_tostring(L,-1));
+ } else if (dflt==NULL) {
+ i = NULL;
+ } else {
+ i = xstrdup(dflt);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+static char *
+n_string_field (lua_State *L, int name_index, char *dflt) {
+ char *i;
+ lua_rawgeti(L,LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
+ lua_rawget(L,-2);
+ if (lua_isstring(L,-1)) {
+ i = xstrdup(lua_tostring(L,-1));
+ } else if (dflt==NULL) {
+ i = NULL;
+ } else {
+ i = xstrdup(dflt);
+ }
+ lua_pop(L,1);
+ return i;
+}
+
+#define init_luaS_index(a) do { \
+ lua_pushliteral(L,#a); \
+ luaS_##a##_ptr = (char *)lua_tostring(L,-1); \
+ luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \
+ } while (0)
+
+#define make_luaS_index(a) \
+ static int luaS_##a##_index = 0; \
+ static char * luaS_##a##_ptr = NULL
+
+#define luaS_index(a) luaS_##a##_index
+
+#define luaS_ptr_eq(a,b) (a==luaS_##b##_ptr)
+
+make_luaS_index(width);
+make_luaS_index(height);
+make_luaS_index(depth);
+make_luaS_index(italic);
+make_luaS_index(index);
+make_luaS_index(left_protruding);
+make_luaS_index(right_protruding);
+make_luaS_index(expansion_factor);
+make_luaS_index(top);
+make_luaS_index(bot);
+make_luaS_index(rep);
+make_luaS_index(mid);
+make_luaS_index(next);
+make_luaS_index(used);
+make_luaS_index(name);
+make_luaS_index(tounicode);
+make_luaS_index(font);
+make_luaS_index(char);
+make_luaS_index(slot);
+make_luaS_index(comment);
+make_luaS_index(push);
+make_luaS_index(pop);
+make_luaS_index(rule);
+make_luaS_index(right);
+make_luaS_index(node);
+make_luaS_index(down);
+make_luaS_index(special);
+make_luaS_index(slant);
+make_luaS_index(space);
+make_luaS_index(space_stretch);
+make_luaS_index(space_shrink);
+make_luaS_index(x_height);
+make_luaS_index(quad);
+make_luaS_index(extra_space);
+make_luaS_index(left_boundary);
+make_luaS_index(right_boundary);
+make_luaS_index(kerns);
+make_luaS_index(ligatures);
+make_luaS_index(fonts);
+
+void init_font_string_pointers (lua_State *L) {
+ init_luaS_index(width);
+ init_luaS_index(height);
+ init_luaS_index(depth);
+ init_luaS_index(italic);
+ init_luaS_index(index);
+ init_luaS_index(left_protruding);
+ init_luaS_index(right_protruding);
+ init_luaS_index(expansion_factor);
+ init_luaS_index(top);
+ init_luaS_index(bot);
+ init_luaS_index(rep);
+ init_luaS_index(mid);
+ init_luaS_index(next);
+ init_luaS_index(used);
+ init_luaS_index(name);
+ init_luaS_index(tounicode);
+ init_luaS_index(font);
+ init_luaS_index(char);
+ init_luaS_index(slot);
+ init_luaS_index(comment);
+ init_luaS_index(push);
+ init_luaS_index(pop);
+ init_luaS_index(rule);
+ init_luaS_index(right);
+ init_luaS_index(node);
+ init_luaS_index(down);
+ init_luaS_index(special);
+
+ init_luaS_index(slant);
+ init_luaS_index(space);
+ init_luaS_index(space_stretch);
+ init_luaS_index(space_shrink);
+ init_luaS_index(x_height);
+ init_luaS_index(quad);
+ init_luaS_index(extra_space);
+
+ init_luaS_index(left_boundary);
+ init_luaS_index(right_boundary);
+ init_luaS_index(kerns);
+ init_luaS_index(ligatures);
+ init_luaS_index(fonts);
+}
+
+static int
+count_char_packet_bytes (lua_State *L) {
+ register int i;
+ register int l = 0;
+ int ff = 0;
+ for (i=1;i<=lua_objlen(L,-1);i++) {
+ lua_rawgeti(L,-1,i);
+ if (lua_istable(L,-1)) {
+ lua_rawgeti(L,-1,1);
+ if (lua_isstring(L,-1)) {
+ char *s = (char *)lua_tostring(L,-1);
+ if (luaS_ptr_eq(s,font)) { l+= 5; ff =1; }
+ else if (luaS_ptr_eq(s,char)) { if (ff==0) { l+=5; } l += 5; ff = 1; }
+ else if (luaS_ptr_eq(s,slot)) { l += 10; ff = 1;}
+ else if (luaS_ptr_eq(s,comment)) { ; }
+ else if (luaS_ptr_eq(s,push) ||
+ luaS_ptr_eq(s,pop)) { l++; }
+ else if (luaS_ptr_eq(s,rule)) { l+=9; }
+ else if (luaS_ptr_eq(s,right) ||
+ luaS_ptr_eq(s,node) ||
+ luaS_ptr_eq(s,down)) { l+=5; }
+ else if (luaS_ptr_eq(s,special)) {
+ size_t len;
+ lua_rawgeti(L,-2,2);
+ (void)lua_tolstring(L,-1,&len);
+ lua_pop(L,1);
+ if (len>0) { l = l + 5 + len; }
+ }
+ else { fprintf(stdout,"unknown packet command %s!\n",s); }
+ } else {
+ fprintf(stdout,"no packet command!\n");
+ }
+ lua_pop(L,1); /* command name */
+ }
+ lua_pop(L,1); /* item */
+ }
+ return l;
+}
+
+
+
+scaled
+sp_to_dvi (halfword sp, halfword atsize) {
+ double result, mult;
+ mult = (double)(atsize>>16);
+ result = (sp << 4);
+ return floor (result/mult );
+}
+
+
+static void
+read_char_packets (lua_State *L, integer *l_fonts, charinfo *co, int atsize) {
+ int i, n, m;
+ size_t l;
+ int cmd;
+ char *s;
+ real_eight_bits *cpackets;
+ int ff = 0;
+ int np = 0;
+ int max_f = 0;
+ int pc = count_char_packet_bytes (L);
+ if (pc<=0)
+ return;
+ assert(l_fonts != NULL);
+ assert(l_fonts[1] != 0);
+ while (l_fonts[(max_f+1)]!=0)
+ max_f++;
+
+ cpackets = xmalloc(pc+1);
+ for (i=1;i<=lua_objlen(L,-1);i++) {
+ lua_rawgeti(L,-1,i);
+ if (lua_istable(L,-1)) {
+ /* fetch the command code */
+ lua_rawgeti(L,-1,1);
+ if (lua_isstring(L,-1)) {
+ s = (char *)lua_tostring(L,-1);
+ cmd = 0;
+ if (luaS_ptr_eq(s,font)) {
+ cmd = packet_font_code;
+ } else if (luaS_ptr_eq(s,char)) {
+ cmd = packet_char_code;
+ if (ff==0) {
+ append_packet(packet_font_code);
+ ff = l_fonts[1];
+ do_store_four(ff);
+ }
+ } else if (luaS_ptr_eq(s,slot)) {
+ cmd = packet_nop_code;
+ lua_rawgeti(L,-2,2); n = lua_tointeger(L,-1);
+ ff = (n>max_f ? l_fonts[1] : l_fonts[n]);
+ lua_rawgeti(L,-3,3); n = lua_tointeger(L,-1);
+ lua_pop(L,2);
+ append_packet(packet_font_code);
+ do_store_four(ff);
+ append_packet(packet_char_code);
+ do_store_four(n);
+ }
+ else if (luaS_ptr_eq(s,comment)) { cmd = packet_nop_code; }
+ else if (luaS_ptr_eq(s,node)) { cmd = packet_node_code; }
+ else if (luaS_ptr_eq(s,push)) { cmd = packet_push_code; }
+ else if (luaS_ptr_eq(s,pop)) { cmd = packet_pop_code; }
+ else if (luaS_ptr_eq(s,rule)) { cmd = packet_rule_code; }
+ else if (luaS_ptr_eq(s,right)) { cmd = packet_right_code; }
+ else if (luaS_ptr_eq(s,down)) { cmd = packet_down_code; }
+ else if (luaS_ptr_eq(s,special)) { cmd = packet_special_code; }
+
+ switch(cmd) {
+ case packet_push_code:
+ case packet_pop_code:
+ append_packet(cmd);
+ break;
+ case packet_font_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = lua_tointeger(L,-1);
+ ff = (n>max_f ? l_fonts[1] : l_fonts[n]);
+ do_store_four(ff);
+ lua_pop(L,1);
+ break;
+ case packet_node_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = copy_node_list(nodelist_from_lua(L));
+ do_store_four(n);
+ lua_pop(L,1);
+ break;
+ case packet_char_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = lua_tointeger(L,-1);
+ do_store_four(n);
+ lua_pop(L,1);
+ break;
+ case packet_right_code:
+ case packet_down_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = lua_tointeger(L,-1);
+ do_store_four(sp_to_dvi(n,atsize));
+ lua_pop(L,1);
+ break;
+ case packet_rule_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ n = lua_tointeger(L,-1);
+ do_store_four(sp_to_dvi(n,atsize));
+ lua_rawgeti(L,-3,3);
+ n = lua_tointeger(L,-1);
+ do_store_four(sp_to_dvi(n,atsize));
+ lua_pop(L,2);
+ break;
+ case packet_special_code:
+ append_packet(cmd);
+ lua_rawgeti(L,-2,2);
+ s = (char *)lua_tolstring(L,-1,&l);
+ if (l>0) {
+ do_store_four(l);
+ m = (int)l;
+ while(m>0) {
+ n = *s++;
+ m--;
+ append_packet(n);
+ }
+ }
+ lua_pop(L,1);
+ break;
+ case packet_nop_code:
+ break;
+ default:
+ fprintf(stdout,"Unknown char packet code %s (char %d in font %s)\n",s,(int)c,font_name(f));
+ }
+ }
+ lua_pop(L,1); /* command code */
+ } else {
+ fprintf(stdout,"Found a `commands' item that is not a table (char %d in font %s)\n",(int)c,font_name(f));
+ }
+ lua_pop(L,1); /* command table */
+ }
+ append_packet(packet_end_code);
+ set_charinfo_packets(co,cpackets);
+ return;
+}
+
+
+static void
+read_lua_cidinfo (lua_State *L, int f) {
+ int i;
+ char *s;
+ lua_getfield(L,-1,"cidinfo");
+ if (lua_istable(L,-1)) {
+ i = numeric_field(L,"version",0);
+ set_font_cidversion(f,i);
+ i = numeric_field(L,"supplement",0);
+ set_font_cidsupplement(f,i);
+ s = string_field(L,"registry","Adobe"); /* Adobe-Identity-0 */
+ set_font_cidregistry(f,s);
+ s = string_field(L,"ordering","Identity");
+ set_font_cidordering(f,s);
+ }
+ lua_pop(L,1);
+}
+
+
+static void
+read_lua_parameters (lua_State *L, int f) {
+ int i, n;
+ char *s;
+ lua_getfield(L,-1,"parameters");
+ if (lua_istable(L,-1)) {
+ /* the number of parameters is the max(IntegerKeys(L)),7) */
+ n = 7;
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ if (lua_isnumber(L,-2)) {
+ i = lua_tonumber(L,-2);
+ if (i > n) n = i;
+ }
+ lua_pop(L,1); /* pop value */
+ }
+ if (n>7) set_font_params(f,n);
+ /* sometimes it is handy to have all integer keys */
+ for (i=1;i<=7;i++) {
+ lua_rawgeti(L,-1,i);
+ if (lua_isnumber(L,-1)) {
+ n = lua_roundnumber(L,-1);
+ set_font_param(f,i, n);
+ }
+ lua_pop(L,1);
+ }
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ if (lua_isnumber(L,-2)) {
+ i = lua_tointeger(L,-2);
+ if (i>=8) {
+ n = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : 0);
+ set_font_param(f,i, n);
+ }
+ } else if (lua_isstring(L,-2)) {
+ s = (char *)lua_tostring(L,-2);
+ n = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : 0);
+ if (luaS_ptr_eq(s,slant)) { set_font_param(f,slant_code,n); }
+ else if (luaS_ptr_eq(s,space)) { set_font_param(f,space_code,n); }
+ else if (luaS_ptr_eq(s,space_stretch)) { set_font_param(f,space_stretch_code,n); }
+ else if (luaS_ptr_eq(s,space_shrink)) { set_font_param(f,space_shrink_code,n); }
+ else if (luaS_ptr_eq(s,x_height)) { set_font_param(f,x_height_code,n); }
+ else if (luaS_ptr_eq(s,quad)) { set_font_param(f,quad_code,n); }
+ else if (luaS_ptr_eq(s,extra_space)) { set_font_param(f,extra_space_code,n); }
+ }
+ lua_pop(L,1);
+ }
+ }
+ lua_pop(L,1);
+
+}
+
+void
+font_char_from_lua (lua_State *L, internal_font_number f, integer i, integer *l_fonts) {
+ int k,r,t;
+ charinfo *co;
+ kerninfo *ckerns;
+ liginfo *cligs;
+ scaled j;
+ char *s;
+ int nl = 0; /* number of ligature table items */
+ int nk = 0; /* number of kern table items */
+ int ctr = 0;
+ int atsize = font_size(f);
+ if (lua_istable(L,-1)) {
+ co = get_charinfo(f,i);
+ set_charinfo_tag (co,0);
+ j = n_numeric_field(L,luaS_width_index,0); set_charinfo_width (co,j);
+ j = n_numeric_field(L,luaS_height_index,0); set_charinfo_height (co,j);
+ j = n_numeric_field(L,luaS_depth_index,0); set_charinfo_depth (co,j);
+ j = n_numeric_field(L,luaS_italic_index,0); set_charinfo_italic (co,j);
+ j = n_numeric_field(L,luaS_index_index,0); set_charinfo_index(co,j);
+ j = n_numeric_field(L,luaS_expansion_factor_index,0); set_charinfo_ef(co,j);
+ j = n_numeric_field(L,luaS_left_protruding_index,0); set_charinfo_lp(co,j);
+ j = n_numeric_field(L,luaS_right_protruding_index,0); set_charinfo_rp(co,j);
+ k = n_boolean_field(L,luaS_used_index,0); set_charinfo_used(co,k);
+ s = n_string_field (L,luaS_name_index,NULL); set_charinfo_name(co,s);
+ s = n_string_field (L,luaS_tounicode_index,NULL); set_charinfo_tounicode(co,s);
+ k = n_numeric_field(L,luaS_next_index,-1);
+ if (k>=0) {
+ set_charinfo_tag (co,list_tag);
+ set_charinfo_remainder (co,k);
+ }
+ lua_getfield(L,-1,"extensible");
+ if (lua_istable(L,-1)){
+ int top, bot,mid, rep;
+ top = n_numeric_field(L,luaS_top_index,0);
+ bot = n_numeric_field(L,luaS_bot_index,0);
+ mid = n_numeric_field(L,luaS_mid_index,0);
+ rep = n_numeric_field(L,luaS_rep_index,0);
+ if (top != 0 || bot != 0 || mid != 0 || rep != 0) {
+ set_charinfo_tag (co,ext_tag);
+ set_charinfo_extensible (co,top,bot,mid,rep);
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid extensible field!",font_name(f),(int)i);
+ }
+ }
+ lua_pop(L,1);
+
+ nk = count_hash_items(L,luaS_index(kerns));
+ if (nk>0) {
+ ckerns = xcalloc((nk+1),sizeof(kerninfo));
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(kerns));
+ lua_rawget(L,-2);
+ if (lua_istable(L,-1)) { /* there are kerns */
+ ctr = 0;
+ lua_pushnil(L);
+ while (lua_next(L, -2) != 0) {
+ k = non_boundarychar;
+ if (lua_isnumber(L,-2)) {
+ k = lua_tonumber(L,-2); /* adjacent char */
+ if (k<0)
+ k = non_boundarychar;
+ } else if (lua_isstring(L,-2)) {
+ s = (char *)lua_tostring(L,-2);
+ if (luaS_ptr_eq(s,right_boundary)) {
+ k = right_boundarychar;
+ if (!has_right_boundary(f))
+ set_right_boundary(f,get_charinfo(f,right_boundarychar));
+ }
+ }
+ j = lua_roundnumber(L,-1); /* movement */
+ if (k!=non_boundarychar) {
+ set_kern_item(ckerns[ctr],k,j);
+ ctr++;
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid kern field!",font_name(f),(int)i);
+ }
+ lua_pop(L,1);
+ }
+ /* guard against empty tables */
+ if (ctr>0) {
+ set_kern_item(ckerns[ctr],end_kern,0);
+ set_charinfo_kerns(co,ckerns);
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid kerns field!",font_name(f),(int)i);
+ }
+ }
+ lua_pop(L,1);
+ }
+
+ /* packet commands */
+ lua_getfield(L,-1,"commands");
+ if (lua_istable(L,-1)){
+ lua_pushnil(L); /* first key */
+ if (lua_next(L, -2) != 0) {
+ lua_pop(L,2);
+ read_char_packets(L,(integer *)l_fonts,co,atsize);
+ }
+ }
+ lua_pop(L,1);
+
+ /* ligatures */
+ nl = count_hash_items(L,luaS_index(ligatures));
+
+ if (nl>0) {
+ cligs = xcalloc((nl+1),sizeof(liginfo));
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(ligatures));
+ lua_rawget(L,-2);
+ if (lua_istable(L,-1)){/* do ligs */
+ ctr = 0;
+ lua_pushnil(L);
+ while (lua_next(L, -2) != 0) {
+ k = non_boundarychar;
+ if (lua_isnumber(L,-2)) {
+ k = lua_tonumber(L,-2); /* adjacent char */
+ if (k<0) {
+ k = non_boundarychar;
+ }
+ } else if (lua_isstring(L,-2)) {
+ s = (char *)lua_tostring(L,-2);
+ if (luaS_ptr_eq(s,right_boundary)) {
+ k = right_boundarychar;
+ if (!has_right_boundary(f))
+ set_right_boundary(f,get_charinfo(f,right_boundarychar));
+ }
+ }
+ r = -1;
+ if (lua_istable(L,-1)) {
+ r = n_numeric_field(L,luaS_char_index,-1); /* ligature */
+ }
+ if (r != -1 && k != non_boundarychar) {
+ t = enum_field(L,"type",0,ligature_type_strings);
+ set_ligature_item(cligs[ctr],(t*2)+1,k,r);
+ ctr++;
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid ligature field!",font_name(f),(int)i);
+ }
+ lua_pop(L,1); /* iterator value */
+ }
+ /* guard against empty tables */
+ if (ctr>0) {
+ set_ligature_item(cligs[ctr],0,end_ligature,0);
+ set_charinfo_ligatures(co,cligs);
+ } else {
+ pdftex_warn("lua-loaded font %s char [%d] has an invalid ligatures field!",font_name(f),(int)i);
+ }
+ }
+ lua_pop(L,1); /* ligatures table */
+ }
+ }
+}
+
+
+
+/* The caller has to fix the state of the lua stack when there is an error! */
+
+
+int
+font_from_lua (lua_State *L, int f) {
+ int i,n,r,t;
+ int s_top; /* lua stack top */
+ int bc; /* first char index */
+ int ec; /* last char index */
+ char *s;
+ integer *l_fonts = NULL;
+ /* the table is at stack index -1 */
+
+ if (luaS_width_index==0)
+ init_font_string_pointers(L);
+
+ s = string_field(L,"area",""); set_font_area(f,s);
+ s = string_field(L,"filename",NULL); set_font_filename(f,s);
+ s = string_field(L,"encodingname",NULL); set_font_encodingname(f,s);
+
+ s = string_field(L,"name",NULL); set_font_name(f,s);
+ s = string_field(L,"fullname",font_name(f)); set_font_fullname(f,s);
+
+ if (s==NULL) {
+ pdftex_fail("lua-loaded font [%d] has no name!",f);
+ return false;
+ }
+
+ i = numeric_field(L,"designsize",655360); set_font_dsize(f,i);
+ i = numeric_field(L,"size",font_dsize(f)); set_font_size(f,i);
+ i = numeric_field(L,"checksum",0); set_font_checksum(f,i);
+ i = numeric_field(L,"direction",0); set_font_natural_dir(f,i);
+ i = numeric_field(L,"encodingbytes",0); set_font_encodingbytes(f,i);
+ i = numeric_field(L,"tounicode",0); set_font_tounicode(f,i);
+
+ i = numeric_field(L,"extend",0);
+ if (i<-2000) i = -2000; if (i>2000) i = 2000; if (i==1000) i = 0;
+ set_font_extend(f,i);
+ i = numeric_field(L,"slant",0);
+ if (i<-1000) i = -1000; if (i>1000) i = 1000;
+ set_font_slant(f,i);
+
+ i = numeric_field(L,"hyphenchar",get_default_hyphen_char()); set_hyphen_char(f,i);
+ i = numeric_field(L,"skewchar",get_default_skew_char()); set_skew_char(f,i);
+ i = boolean_field(L,"used",0); set_font_used(f,i);
+
+ s = string_field (L,"attributes",NULL);
+ if (s!=NULL && strlen(s)>0) {
+ i = maketexstring(s);
+ set_pdf_font_attr(f,i);
+ }
+
+ i = enum_field(L,"type", unknown_font_type,font_type_strings); set_font_type(f,i);
+ i = enum_field(L,"format", unknown_format, font_format_strings); set_font_format(f,i);
+ i = enum_field(L,"embedding",unknown_embedding,font_embedding_strings); set_font_embedding(f,i);
+ if (font_encodingbytes(f)==0 &&
+ (font_format(f)==opentype_format || font_format(f)==truetype_format)) {
+ set_font_encodingbytes(f,2);
+ }
+
+ /* now fetch the base fonts, if needed */
+ n = count_hash_items(L,luaS_index(fonts));
+ if (n>0) {
+ l_fonts = xmalloc((n+2)*sizeof(integer));
+ memset (l_fonts,0,(n+2)*sizeof(integer));
+ lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(fonts));
+ lua_rawget(L,-2);
+ for (i=1;i<=n;i++) {
+ lua_rawgeti(L,-1,i);
+ if (lua_istable(L,-1)) {
+ lua_getfield(L,-1,"id");
+ if (lua_isnumber(L,-1)) {
+ l_fonts[i] = lua_tonumber(L,-1);
+ lua_pop(L,2); /* pop id and entry */
+ continue;
+ }
+ lua_pop(L,1); /* pop id */
+ };
+ s = NULL;
+ if (lua_istable(L,-1)) {
+ lua_getfield(L,-1,"name");
+ if (lua_isstring(L,-1)) {
+ s = (char *)lua_tostring(L,-1);
+ }
+ lua_pop(L,1); /* pop name */
+ }
+ if (s!= NULL) {
+ lua_getfield(L,-1,"size");
+ t = (lua_isnumber(L,-1) ? lua_roundnumber(L,-1) : -1000);
+ lua_pop(L,1);
+
+ /* TODO: the stack is messed up, otherwise this
+ * explicit resizing would not be needed
+ */
+ s_top = lua_gettop(L);
+ l_fonts[i] = find_font_id(s,"",t);
+ lua_settop(L,s_top);
+ } else {
+ pdftex_fail("Invalid local font in font %s!\n", font_name(f));
+ }
+ lua_pop(L,1); /* pop list entry */
+ }
+ lua_pop(L,1); /* pop list entry */
+ } else {
+ if(font_type(f) == virtual_font_type) {
+ pdftex_fail("Invalid local fonts in font %s!\n", font_name(f));
+ } else {
+ l_fonts = xmalloc(3*sizeof(integer));
+ l_fonts[0] = 0;
+ l_fonts[1] = f;
+ l_fonts[2] = 0;
+ }
+ }
+
+ /* parameters */
+ read_lua_parameters(L,f);
+ read_lua_cidinfo(L,f);
+
+ /* characters */
+ lua_getfield(L,-1,"characters");
+ if (lua_istable(L,-1)) {
+ /* find the array size values */
+ ec = 0; bc = -1;
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ if (lua_isnumber(L,-2)) {
+ i = lua_tointeger(L,-2);
+ if (i>=0) {
+ if (lua_istable(L,-1)) {
+ if (i>ec) ec = i;
+ if (bc<0) bc = i;
+ if (bc>=0 && i<bc) bc = i;
+ }
+ }
+ }
+ lua_pop(L, 1);
+ }
+
+ if (bc != -1) {
+ /* fprintf(stdout,"defined a font at %d with %d-%d\n",f,bc,ec); */
+ set_font_bc(f,bc);
+ set_font_ec(f,ec);
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, -2) != 0) {
+ if (lua_isnumber(L,-2)) {
+ i = lua_tonumber(L,-2);
+ if (i>=0) {
+ font_char_from_lua(L,f, i, l_fonts);
+ }
+ } else if (lua_isstring(L,-2)) {
+ s = (char *)lua_tostring(L,-2);
+ if (luaS_ptr_eq(s,left_boundary)) {
+ font_char_from_lua(L,f, left_boundarychar, l_fonts);
+ } else if (luaS_ptr_eq(s,right_boundary)) {
+ font_char_from_lua(L,f, right_boundarychar, l_fonts);
+ }
+ }
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
+
+ /* handle font expansion last: the |copy_font| routine is called eventually,
+ and that needs to know |bc| and |ec|. */
+ if (font_type(f)!=virtual_font_type) {
+ int fstep = numeric_field(L,"step",0);
+ if (fstep<0) fstep = 0;
+ if (fstep>100) fstep = 100;
+ if (fstep!=0) {
+ int fshrink = numeric_field(L,"shrink",0);
+ int fstretch = numeric_field(L,"stretch",0);
+ int fexpand = boolean_field(L,"auto_expand",0);
+ if (fshrink<0) fshrink = 0;
+ if (fshrink>500) fshrink = 500;
+ fshrink -= (fshrink % fstep);
+ if (fshrink<0) fshrink = 0;
+ if (fstretch<0) fstretch = 0;
+ if (fstretch>1000) fstretch = 1000;
+ fstretch -= (fstretch % fstep);
+ if (fstretch<0) fstretch = 0;
+ set_expand_params(f, fexpand, fstretch, fshrink, fstep, 0);
+ }
+ }
+
+ } else { /* jikes, no characters */
+ pdftex_warn("lua-loaded font [%d] (%s) has no characters!",f, font_name(f));
+ }
+
+#if SAVE_REF
+ r = luaL_ref(Luas[0],LUA_REGISTRYINDEX); /* pops the table */
+ set_font_cache_id(f,r);
+#else
+ lua_pop(Luas[0],1);
+#endif
+ } else { /* jikes, no characters */
+ pdftex_warn("lua-loaded font [%d] (%s) has no character table!",f, font_name(f));
+ }
+
+ if (l_fonts!=NULL)
+ free(l_fonts);
+ return true;
+}
+
+/* ====================================================================
+ *
+ * L I G A T U R I N G
+ *
+ * ==================================================================== */
+
+
+#define assert_disc(a) \
+ assert(pre_break(a)!=null); /* expect head_node */ \
+ assert(type(pre_break(a))==nesting_node); \
+ assert((vlink_pre_break(a)==null && tlink_pre_break(a)==null) || tail_of_list(vlink_pre_break(a))==tlink_pre_break(a)); \
+ assert(post_break(a)!=null); /* expect head_node */ \
+ assert(type(post_break(a))==nesting_node); \
+ assert((vlink_post_break(a)==null && tlink_post_break(a)==null) || tail_of_list(vlink_post_break(a))==tlink_post_break(a)); \
+ assert(no_break(a)!=null); /* expect head_node */ \
+ assert(type(no_break(a))==nesting_node); \
+ assert((vlink_no_break(a)==null && tlink_no_break(a)==null) || tail_of_list(vlink_no_break(a))==tlink_no_break(a));
+
+static void
+nesting_append (halfword nest, halfword newn) {
+ halfword tail = tlink(nest);
+ assert(alink(nest)==null);
+ assert(vlink(newn)==null);
+ assert(alink(newn)==null);
+ if (tail==null) {
+ assert(vlink(nest)==null);
+ couple_nodes(nest,newn);
+ } else {
+ assert(vlink(tail)==null);
+ assert(tail_of_list(vlink(nest))==tail);
+ couple_nodes(tail,newn);
+ }
+ tlink(nest) = newn;
+}
+
+
+static void
+nesting_prepend (halfword nest, halfword newn) {
+ halfword head = vlink(nest);
+ assert(alink(nest)==null);
+ assert(vlink(newn)==null);
+ assert(alink(newn)==null);
+ couple_nodes(nest,newn);
+ if (head==null) {
+ assert(tlink(nest)==null);
+ tlink(nest) = newn;
+ } else {
+ assert(alink(head)==nest);
+ assert(tail_of_list(head)==tlink(nest));
+ couple_nodes(newn,head);
+ }
+}
+
+
+static int
+test_ligature( liginfo *lig, halfword left, halfword right ) {
+ if (type(left)!=glyph_node)
+ return 0;
+ assert(type(right)==glyph_node);
+ if (font(left)!=font(right)) return 0;
+ if (is_ghost(left) || is_ghost(right)) return 0;
+ *lig = get_ligature(font(left),character(left),character(right));
+ if (is_valid_ligature(*lig)) {
+ return 1;
+ }
+ return 0;
+}
+
+
+static int
+try_ligature(halfword *frst, halfword fwd) {
+ halfword cur = *frst;
+ liginfo lig;
+ if (test_ligature(&lig,cur,fwd)) {
+ int move_after = (lig_type(lig) & 0x0C)>>2;
+ int keep_right = ((lig_type(lig) & 0x01) != 0);
+ int keep_left = ((lig_type(lig) & 0x02) != 0);
+ halfword newgl = raw_glyph_node();
+ font(newgl) = font(cur);
+ character(newgl) = lig_replacement(lig);
+ set_is_ligature(newgl);
+
+ /* below might not be correct in contrived border case.
+ * but we use it only for debugging, so ... */
+ if (character(cur)<0) {
+ set_is_leftboundary(newgl);
+ }
+ if (character(fwd)<0) {
+ set_is_rightboundary(newgl);
+ }
+ if (character(cur)<0) {
+ if (character(fwd)<0) {
+ build_attribute_list(newgl);
+ } else {
+ add_node_attr_ref(node_attr(fwd));
+ node_attr(newgl) = node_attr(fwd);
+ }
+ } else {
+ add_node_attr_ref(node_attr(cur));
+ node_attr(newgl) = node_attr(cur);
+ }
+
+ /* TODO/FIXME if this ligature is consists of another ligature
+ * we should add it's lig_ptr to the new glyphs lig_ptr (and
+ * cleanup the no longer needed node) LOW PRIORITY */
+ /* left side */
+ if (keep_left) {
+ halfword new_first = copy_node(cur);
+ lig_ptr(newgl) = new_first;
+ couple_nodes(cur,newgl);
+ if (move_after) {
+ move_after--;
+ cur = newgl;
+ }
+ } else {
+ halfword prev = alink(cur);
+ uncouple_node(cur);
+ lig_ptr(newgl) = cur;
+ assert(prev!=null);
+ couple_nodes(prev,newgl);
+ cur = newgl; /* as cur has disappeared */
+ }
+ /* right side */
+ if (keep_right) {
+ halfword new_second = copy_node(fwd);
+ /* correct, because we _know_ lig_ptr points to _one_ node */
+ couple_nodes(lig_ptr(newgl),new_second);
+ couple_nodes(newgl,fwd);
+ if (move_after) {
+ move_after--;
+ cur = fwd;
+ }
+ } else {
+ halfword next = vlink(fwd);
+ uncouple_node(fwd);
+ /* correct, because we _know_ lig_ptr points to _one_ node */
+ couple_nodes(lig_ptr(newgl),fwd);
+ if (next!=null) {couple_nodes(newgl,next);}
+ }
+
+ /* check and return */
+ /* assert(move_after==0);*/
+ *frst = cur;
+ return 1;
+ }
+ return 0;
+}
+
+
+/* there shouldn't be any ligatures here - we only add them at the end of
+ * xxx_break in a DISC-1 - DISC-2 situation and we stop processing DISC-1
+ * (we continue with DISC-1's post_ and no_break */
+static halfword
+handle_lig_nest(halfword root, halfword cur) {
+ if (cur==null) return root;
+ while (vlink(cur)!=null) {
+ halfword fwd = vlink(cur);
+ if (type(cur)==glyph_node && type(fwd)==glyph_node &&
+ font(cur)==font(fwd) && try_ligature(&cur,fwd)) continue;
+ cur = vlink(cur);
+ assert(vlink(alink(cur))==cur);
+ }
+ tlink(root) = cur;
+ return root;
+}
+
+
+static halfword
+handle_lig_word(halfword cur) {
+ halfword right=null;
+
+ if (type(cur)==whatsit_node && subtype(cur)==cancel_boundary_node) {
+ halfword prev= alink(cur);
+ halfword fwd = vlink(cur);
+/* uncouple_node(cur); */ /* not needed, it is freed */
+ flush_node(cur);
+ if (fwd==null) {
+ vlink(prev) = fwd;
+ return prev;
+ }
+ couple_nodes(prev,fwd);
+ if (type(fwd)!=glyph_node) return prev;
+ cur = fwd;
+ } else if (has_left_boundary(font(cur))) {
+ halfword prev= alink(cur);
+ halfword p = new_glyph(font(cur),left_boundarychar);
+ couple_nodes(prev,p);
+ couple_nodes(p,cur);
+ cur = p;
+ }
+ if (has_right_boundary(font(cur))) {
+ right = new_glyph(font(cur),right_boundarychar);
+ }
+
+ while (1) {
+ /* A glyph followed by ... */
+ if (type(cur)==glyph_node) {
+ halfword fwd = vlink(cur);
+ if (fwd==null) { /* last character of paragraph */
+ if (right==null) break;
+ couple_nodes(cur,right);
+ right = null;
+ continue;
+ }
+ assert(alink(fwd)==cur);
+ if (type(fwd)==glyph_node) { /* GLYPH - GLYPH */
+ if (font(cur)!=font(fwd)) break;
+ if (try_ligature(&cur,fwd)) continue;
+ } else if (type(fwd)==disc_node) { /* GLYPH - DISC */
+
+ /* if a{bx}{}{y} and a+b=>B convert to {Bx}{}{ay} */
+ halfword pre = vlink_pre_break(fwd);
+ halfword nob = vlink_no_break(fwd);
+ liginfo lig;
+ assert_disc(fwd);
+ /* Check on: a{b?}{?}{?} and a+b=>B : {B?}{?}{a?}*/
+ /* Check on: a{?}{?}{b?} and a+b=>B : {a?}{?}{B?} */
+ if ( (pre!=null && type(pre)==glyph_node && test_ligature(&lig,cur,pre))
+ || (nob!=null && type(nob)==glyph_node && test_ligature(&lig,cur,nob))) {
+ /* move cur from before disc, to skipped part */
+ halfword prev = alink(cur);
+ assert(vlink(prev)==cur);
+ uncouple_node(cur);
+ couple_nodes(prev,fwd);
+ nesting_prepend(no_break(fwd),cur);
+ /* now ligature the pre_break */
+ nesting_prepend(pre_break(fwd),copy_node(cur));
+ /* As we have removed cur, we need to start again ... */
+ cur = prev;
+ }
+ /* Check on: a{?}{?}{}b and a+b=>B : {a?}{?b}{B}*/
+ halfword next = vlink(fwd);
+ if (nob==null && next != null && type(next)==glyph_node
+ && test_ligature(&lig,cur,next)) {
+ /* move cur from before disc to no_break part */
+ halfword prev = alink(cur);
+ assert(alink(next)==fwd);
+ assert(vlink(prev)==cur);
+ uncouple_node(cur);
+ couple_nodes(prev,fwd);
+ couple_nodes(no_break(fwd),cur); /* we _know_ it's empty */
+ /* now copy cur the pre_break */
+ nesting_prepend(pre_break(fwd),copy_node(cur));
+ /* move next from after disc to no_break part */
+ halfword tail = vlink(next);
+ uncouple_node(next);
+ try_couple_nodes(fwd,tail);
+ couple_nodes(cur,next); /* we _know_ this works */
+ tlink(no_break(fwd)) = next; /* and make sure the list is correct */
+ /* now copy next to the post_break */
+ nesting_append(post_break(fwd),copy_node(next));
+ /* As we have removed cur, we need to start again ... */
+ cur = prev;
+ }
+ /* we are finished with the pre_break */
+ handle_lig_nest(pre_break(fwd),vlink_pre_break(fwd));
+ } else if (type(fwd)==whatsit_node && subtype(fwd)==cancel_boundary_node) {
+ halfword next = vlink(fwd);
+ try_couple_nodes(cur,next);
+ flush_node(fwd);
+ if (right!=null) {
+ flush_node(right); /* Shame, didn't need it */
+ /* right = null; */ /* no need, we're going to leave the loop anyway */
+ }
+ break;
+ } else { /* fwd is something unknown */
+ if (right==null) break;
+ couple_nodes(cur,right);
+ couple_nodes(right,fwd);
+ right = null;
+ continue;
+ }
+ /* A discretionary followed by ... */
+ } else if (type(cur)==disc_node) {
+ assert_disc(cur);
+ /* If {?}{x}{?} or {?}{?}{y} then ... */
+ if (vlink_no_break(cur)!=null || vlink_post_break(cur)!=null) {
+ halfword fwd;
+ halfword lists[511]; /* max 8 levels */
+
+ int i, max_depth=0;
+ lists[max_depth++] = handle_lig_nest(post_break(cur),vlink_post_break(cur));
+ lists[max_depth++] = handle_lig_nest(no_break(cur),vlink_no_break(cur));
+ while (1) {
+ if ((fwd = vlink(cur))==null) return cur;
+ if ( type(fwd)==glyph_node) {
+ for (i=0; i<max_depth; i++) {
+ liginfo lig;
+ halfword tail = tlink(lists[i]);
+ if ( tail!=null && test_ligature(&lig,tail,fwd))
+ goto add_glyph_to_all;
+ }
+ /* if we get here, nothing had a ligature, so we stop */
+ break;
+add_glyph_to_all:
+ for (i=0; i<max_depth; i++) {
+ halfword copy = copy_node(fwd);
+ halfword tail = tlink(lists[i]);
+ nesting_append(lists[i],copy);
+ if (tail==null) continue; /* first character - never a ligature */
+ handle_lig_nest(lists[i],tail);
+ }
+ halfword next = vlink(fwd);
+ uncouple_node(fwd);
+ try_couple_nodes(cur,next);
+ flush_node(fwd);
+ } else if ( type(fwd)==disc_node) {
+ /* MAGIC WARNING
+ * A disc followed by a disc can have different kernings
+ * depending on which path is choosen, and it is impossible to
+ * store the possible kernings: fe {}{A}{W} {V}{}{A}
+ * So we _always_ add discs so only a simple path remains. */
+ int m=max_depth; /* as max_depth changes in this loop */
+ for (i=0; i<m; i++) {
+ halfword copy = copy_node(fwd);
+ halfword tail = tlink(lists[i]);
+ if (tail!=null) {
+ halfword prev = alink(tail);
+ assert(alink(tail)!=null);
+ uncouple_node(tail);
+ vlink(prev) = null;
+ if (prev==lists[i]) {
+ tlink(prev) = null;
+ } else {
+ tlink(lists[i]) = prev;
+ }
+ nesting_prepend(pre_break(copy),tail);
+ nesting_prepend(no_break(copy),copy_node(tail));
+ }
+ nesting_append(lists[i],copy);
+ handle_lig_nest(pre_break(copy),vlink_pre_break(copy));
+ assert(max_depth<256);
+ lists[max_depth++] = handle_lig_nest(no_break(copy),vlink_no_break(copy));
+ lists[i] = handle_lig_nest(post_break(copy),vlink_post_break(copy));
+ }
+ halfword next = vlink(fwd);
+ uncouple_node(fwd);
+ try_couple_nodes(cur,next);
+ flush_node(fwd);
+ } else {
+ return cur;
+ }
+ }
+ }
+ } else { /* NO GLYPH NOR DISC */
+ /* fprintf(stdout,"This is a %d node\n",type(cur));*/
+ /* assert(0);*/ /* TODO howcome there can be a glue here? */
+ return cur;
+ }
+ /* step-to-next-node */
+ {
+ halfword prev = cur;
+ cur = vlink(cur);
+ assert(cur!=null);
+ assert(alink(cur)==prev);
+ /* alink(cur) = prev;*/
+ }
+ }
+
+ return cur;
+}
+
+/* return = new tail, head should be a dummy */
+
+halfword
+handle_ligaturing(halfword head, halfword tail) {
+ halfword save_tail ; /* trick to allow explicit node==null tests */
+ halfword cur, prev;
+
+ if (vlink(head)==null)
+ return tail;
+ save_tail = vlink(tail);
+ vlink(tail) = null;
+
+ /* if (fix_node_lists) */
+ fix_node_list(head);
+
+ prev = head;
+ cur = vlink(prev);
+
+ while (cur!=null) {
+ if ( type(cur)==glyph_node ||
+ (type(cur)==whatsit_node && subtype(cur)==cancel_boundary_node)) {
+ cur = handle_lig_word(cur);
+ }
+ prev = cur;
+ cur = vlink(cur);
+ assert(cur==null||alink(cur) == prev);
+ }
+ if (valid_node(save_tail)) {
+ try_couple_nodes(prev,save_tail);
+ }
+ return prev;
+}
+
+
+/* ====================================================================
+ *
+ * K E R N I N G
+ *
+ * ==================================================================== */
+
+static void
+add_kern_before(halfword left, halfword right) {
+ if ((!is_rightghost(right)) &&
+ font(left)==font(right) &&
+ has_kern(font(left),character(left))) {
+ int k = get_kern(font(left),character(left),character(right));
+ if (k!=0) {
+ halfword kern = new_kern(k);
+ halfword prev = alink(right);
+ assert(vlink(prev)==right);
+ couple_nodes(prev,kern);
+ couple_nodes(kern,right);
+ }
+ }
+}
+
+
+static void
+add_kern_after(halfword left, halfword right, halfword aft) {
+ if ((!is_rightghost(right)) &&
+ font(left)==font(right) &&
+ has_kern(font(left),character(left))) {
+ int k = get_kern(font(left),character(left),character(right));
+ if (k!=0) {
+ halfword kern = new_kern(k);
+ halfword next = vlink(aft);
+ assert(next==null||alink(next)==aft);
+ couple_nodes(aft,kern);
+ try_couple_nodes(kern,next);
+ }
+ }
+}
+
+
+static void
+do_handle_kerning (halfword root, halfword init_left, halfword init_right) {
+ halfword cur = vlink(root);
+ halfword left = null;
+ assert(init_left==null || type(init_left)==glyph_node);
+ assert(init_right==null || type(init_right)==glyph_node);
+ if (cur==null) {
+ if (init_left!=null && init_right!=null) {
+ add_kern_after(init_left,init_right,root);
+ tlink(root)=vlink(root);
+ }
+ return;
+ }
+ if (type(cur)==glyph_node) {
+ set_is_glyph(cur);
+ if (init_left!=null)
+ add_kern_before(init_left,cur);
+ left = cur;
+ }
+ while ((cur=vlink(cur))!=null) {
+ if (type(cur)==glyph_node) {
+ set_is_glyph(cur);
+ if (left != null) {
+ add_kern_before(left,cur);
+ if (character(left)<0 || is_ghost(left)) {
+ halfword prev = alink(left);
+ couple_nodes(prev,cur);
+ flush_node(left);
+ }
+ }
+ left = cur;
+ } else {
+ if (type(cur)==disc_node) {
+ halfword right= type(vlink(cur))==glyph_node ? vlink(cur) : null;
+ do_handle_kerning(pre_break(cur),left,null);
+ do_handle_kerning(post_break(cur),null,right);
+ do_handle_kerning(no_break(cur),left,right);
+ }
+ if (left != null) {
+ if (character(left)<0 || is_ghost(left)) {
+ halfword prev = alink(left);
+ couple_nodes(prev,cur);
+ flush_node(left);
+ }
+ left = null;
+ }
+ }
+ }
+ if (left!=null) {
+ if (init_right!=null)
+ add_kern_after(left,init_right,left);
+ if (character(left)<0 || is_ghost(left)) {
+ halfword prev = alink(left);
+ halfword next = vlink(left);
+ if (next!=null) {
+ couple_nodes(prev,next);
+ tlink(root) = next;
+ assert(vlink(next)==null);
+ assert(type(next)==kern_node);
+ } else if (prev!=root) {
+ vlink(prev) = null;
+ tlink(root) = prev;
+ } else {
+ vlink(root) = null;
+ tlink(root) = null;
+ }
+ flush_node(left);
+ }
+ }
+}
+
+
+halfword
+handle_kerning (halfword head, halfword tail) {
+ halfword save_link;
+ save_link = vlink(tail);
+ vlink(tail) = null;
+ tlink(head) = tail;
+ do_handle_kerning(head,null,null);
+ tail = tlink(head);
+ if (valid_node(save_link)) {
+ try_couple_nodes(tail,save_link);
+ }
+ return tail;
+}
+
+/* ====================================================================
+ *
+ * L I G A T U R I N G and K E R N I N G : L U A - I N T E R F A C E
+ *
+ * ==================================================================== */
+
+static halfword
+run_lua_ligkern_callback (halfword head, halfword tail, int callback_id){
+ lua_State *L = Luas[0];
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2);
+ return tail;
+ }
+ nodelist_to_lua(L,head);
+ nodelist_to_lua(L,tail);
+ if (lua_pcall(L,2,1,0) != 0) {
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ lua_error(L);
+ return tail;
+ }
+ tail = nodelist_from_lua(L);
+ if (fix_node_lists)
+ fix_node_list(head);
+ lua_pop(L,2);
+ return tail;
+}
+
+
+halfword
+new_ligkern(halfword head, halfword tail) {
+ int callback_id = 0;
+
+ assert(head!=null);
+ if (vlink(head)==null)
+ return tail;
+
+ callback_id = callback_defined(ligaturing_callback);
+ if (callback_id>0) {
+ tail = run_lua_ligkern_callback(head,tail,callback_id);
+ if (tail==null) tail = tail_of_list(head);
+ } else {
+ tail = handle_ligaturing(head,tail);
+ }
+
+ callback_id = callback_defined(kerning_callback);
+ if (callback_id>0) {
+ tail = run_lua_ligkern_callback(head,tail,callback_id);
+ if (tail==null) tail = tail_of_list(head);
+ } else {
+ halfword nest = new_node(nesting_node,1);
+ halfword cur = vlink(head);
+ halfword aft = vlink(tail);
+ couple_nodes(nest,cur);
+ tlink(nest)=tail;
+ vlink(tail)=null;
+ do_handle_kerning(nest,null,null);
+ couple_nodes(head,vlink(nest));
+ tail = tlink(nest);
+ try_couple_nodes(tail,aft);
+ flush_node(nest);
+ }
+ return tail;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/macnames.c b/Build/source/texk/web2c/luatexdir/font/macnames.c
new file mode 100644
index 00000000000..941f087ef56
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/macnames.c
@@ -0,0 +1,312 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: macnames.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+const char notdef[] = ".notdef";
+
+const char *mac_glyph_names[] = {
+/* 0x00 */
+ notdef,
+ ".null",
+ "CR",
+ "space",
+ "exclam",
+ "quotedbl",
+ "numbersign",
+ "dollar",
+ "percent",
+ "ampersand",
+ "quotesingle",
+ "parenleft",
+ "parenright",
+ "asterisk",
+ "plus",
+ "comma",
+/* 0x10 */
+ "hyphen",
+ "period",
+ "slash",
+ "zero",
+ "one",
+ "two",
+ "three",
+ "four",
+ "five",
+ "six",
+ "seven",
+ "eight",
+ "nine",
+ "colon",
+ "semicolon",
+ "less",
+/* 0x20 */
+ "equal",
+ "greater",
+ "question",
+ "at",
+ "A",
+ "B",
+ "C",
+ "D",
+ "E",
+ "F",
+ "G",
+ "H",
+ "I",
+ "J",
+ "K",
+ "L",
+/* 0x30 */
+ "M",
+ "N",
+ "O",
+ "P",
+ "Q",
+ "R",
+ "S",
+ "T",
+ "U",
+ "V",
+ "W",
+ "X",
+ "Y",
+ "Z",
+ "bracketleft",
+ "backslash",
+/* 0x40 */
+ "bracketright",
+ "asciicircum",
+ "underscore",
+ "grave",
+ "a",
+ "b",
+ "c",
+ "d",
+ "e",
+ "f",
+ "g",
+ "h",
+ "i",
+ "j",
+ "k",
+ "l",
+/* 0x50 */
+ "m",
+ "n",
+ "o",
+ "p",
+ "q",
+ "r",
+ "s",
+ "t",
+ "u",
+ "v",
+ "w",
+ "x",
+ "y",
+ "z",
+ "braceleft",
+ "bar",
+/* 0x60 */
+ "braceright",
+ "asciitilde",
+ "Adieresis",
+ "Aring",
+ "Ccedilla",
+ "Eacute",
+ "Ntilde",
+ "Odieresis",
+ "Udieresis",
+ "aacute",
+ "agrave",
+ "acircumflex",
+ "adieresis",
+ "atilde",
+ "aring",
+ "ccedilla",
+/* 0x70 */
+ "eacute",
+ "egrave",
+ "ecircumflex",
+ "edieresis",
+ "iacute",
+ "igrave",
+ "icircumflex",
+ "idieresis",
+ "ntilde",
+ "oacute",
+ "ograve",
+ "ocircumflex",
+ "odieresis",
+ "otilde",
+ "uacute",
+ "ugrave",
+/* 0x80 */
+ "ucircumflex",
+ "udieresis",
+ "dagger",
+ "degree",
+ "cent",
+ "sterling",
+ "section",
+ "bullet",
+ "paragraph",
+ "germandbls",
+ "registered",
+ "copyright",
+ "trademark",
+ "acute",
+ "dieresis",
+ "notequal",
+/* 0x90 */
+ "AE",
+ "Oslash",
+ "infinity",
+ "plusminus",
+ "lessequal",
+ "greaterequal",
+ "yen",
+ "mu",
+ "partialdiff",
+ "Sigma",
+ "Pi",
+ "pi",
+ "integral",
+ "ordfeminine",
+ "ordmasculine",
+ "Omega",
+/* 0xa0 */
+ "ae",
+ "oslash",
+ "questiondown",
+ "exclamdown",
+ "logicalnot",
+ "radical",
+ "florin",
+ "approxequal",
+ "Delta",
+ "guillemotleft",
+ "guillemotright",
+ "ellipsis",
+ "nbspace",
+ "Agrave",
+ "Atilde",
+ "Otilde",
+/* 0xb0 */
+ "OE",
+ "oe",
+ "endash",
+ "emdash",
+ "quotedblleft",
+ "quotedblright",
+ "quoteleft",
+ "quoteright",
+ "divide",
+ "lozenge",
+ "ydieresis",
+ "Ydieresis",
+ "fraction",
+ "currency",
+ "guilsinglleft",
+ "guilsinglright",
+/* 0xc0 */
+ "fi",
+ "fl",
+ "daggerdbl",
+ "periodcentered",
+ "quotesinglbase",
+ "quotedblbase",
+ "perthousand",
+ "Acircumflex",
+ "Ecircumflex",
+ "Aacute",
+ "Edieresis",
+ "Egrave",
+ "Iacute",
+ "Icircumflex",
+ "Idieresis",
+ "Igrave",
+/* 0xd0 */
+ "Oacute",
+ "Ocircumflex",
+ "applelogo",
+ "Ograve",
+ "Uacute",
+ "Ucircumflex",
+ "Ugrave",
+ "dotlessi",
+ "circumflex",
+ "tilde",
+ "macron",
+ "breve",
+ "dotaccent",
+ "ring",
+ "cedilla",
+ "hungarumlaut",
+/* 0xe0 */
+ "ogonek",
+ "caron",
+ "Lslash",
+ "lslash",
+ "Scaron",
+ "scaron",
+ "Zcaron",
+ "zcaron",
+ "brokenbar",
+ "Eth",
+ "eth",
+ "Yacute",
+ "yacute",
+ "Thorn",
+ "thorn",
+ "minus",
+/* 0xf0 */
+ "multiply",
+ "onesuperior",
+ "twosuperior",
+ "threesuperior",
+ "onehalf",
+ "onequarter",
+ "threequarters",
+ "franc",
+ "Gbreve",
+ "gbreve",
+ "Idot",
+ "Scedilla",
+ "scedilla",
+ "Cacute",
+ "cacute",
+ "Ccaron",
+/* 0x100 */
+ "ccaron",
+ "dmacron"
+};
+
+const char *ambiguous_names[] = {
+ "Delta", /* increment */
+ "Omega", /* Ohm */
+ "Pi", /* product */
+ "Sigma", /* summation */
+ "dmacron", /* dslash */
+ "macron", /* overscore */
+ "periodcentered", /* middot */
+ NULL
+};
diff --git a/Build/source/texk/web2c/luatexdir/font/mapfile.c b/Build/source/texk/web2c/luatexdir/font/mapfile.c
new file mode 100644
index 00000000000..1c444e5c1d4
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/mapfile.c
@@ -0,0 +1,967 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: mapfile.c 1013 2008-02-14 00:09:02Z oneiros $
+
+*/
+
+#include <math.h>
+#include "ptexlib.h"
+#include <kpathsea/c-auto.h>
+#include <kpathsea/c-memstr.h>
+#include <string.h>
+#include "luatex-api.h"
+
+#define FM_BUF_SIZE 1024
+
+static FILE *fm_file;
+
+static unsigned char *fm_buffer = NULL;
+static integer fm_size = 0;
+static integer fm_curbyte = 0;
+
+#define fm_open() \
+ open_input (&fm_file, kpse_fontmap_format, FOPEN_RBIN_MODE)
+#define fm_read_file() \
+ readbinfile(fm_file,&fm_buffer,&fm_size)
+#define fm_close() xfclose(fm_file, cur_file_name)
+#define fm_getchar() fm_buffer[fm_curbyte++]
+#define fm_eof() (fm_curbyte>=fm_size)
+
+typedef enum { FM_DUPIGNORE, FM_REPLACE, FM_DELETE } updatemode;
+typedef enum { MAPFILE, MAPLINE } maptype;
+
+typedef struct mitem {
+ updatemode mode; /* FM_DUPIGNORE or FM_REPLACE or FM_DELETE */
+ maptype type; /* map file or map line */
+ char *line; /* pointer to map file name or map line */
+ int lineno; /* line number in map file */
+} mapitem;
+mapitem *mitem = NULL;
+
+static const char nontfm[] = "<nontfm>";
+
+#define read_field(r, q, buf) do { \
+ q = buf; \
+ while (*r != ' ' && *r != '<' && *r != '"' && *r != '\0') \
+ *q++ = *r++; \
+ *q = '\0'; \
+ skip (r, ' '); \
+} while (0)
+
+#define set_field(F) do { \
+ if (q > buf) \
+ fm->F = xstrdup(buf); \
+ if (*r == '\0') \
+ goto done; \
+} while (0)
+
+fm_entry *new_fm_entry(void)
+{
+ fm_entry *fm;
+ fm = xtalloc(1, fm_entry);
+ fm->tfm_name = NULL;
+ fm->sfd_name = NULL;
+ fm->ps_name = NULL;
+ fm->fd_flags = 4;
+ fm->ff_name = NULL;
+ fm->encname = NULL;
+ fm->type = 0;
+ fm->slant = 0;
+ fm->extend = 0;
+ fm->links = 0;
+ fm->pid = -1;
+ fm->eid = -1;
+ fm->subfont = NULL;
+ fm->in_use = false;
+ return fm;
+}
+
+void delete_fm_entry(fm_entry * fm)
+{
+ xfree(fm->tfm_name);
+ xfree(fm->sfd_name);
+ xfree(fm->ps_name);
+ xfree(fm->ff_name);
+ xfree(fm);
+}
+
+static ff_entry *new_ff_entry (void)
+{
+ ff_entry *ff;
+ ff = xtalloc (1, ff_entry);
+ ff->ff_name = NULL;
+ ff->ff_path = NULL;
+ return ff;
+}
+
+static void delete_ff_entry (ff_entry * ff)
+{
+ xfree (ff->ff_name);
+ xfree (ff->ff_path);
+ xfree (ff);
+}
+
+static fm_entry *dummy_fm_entry ()
+{
+ static const fm_entry const_fm_entry;
+ return (fm_entry *) & const_fm_entry;
+}
+
+/**********************************************************************/
+
+struct avl_table *tfm_tree = NULL;
+struct avl_table *ps_tree = NULL;
+struct avl_table *ff_tree = NULL;
+struct avl_table *encname_tree = NULL;
+
+/* AVL sort fm_entry into tfm_tree by tfm_name */
+
+static int comp_fm_entry_tfm (const void *pa, const void *pb, void *p)
+{
+ return strcmp (((const fm_entry *) pa)->tfm_name,
+ ((const fm_entry *) pb)->tfm_name);
+}
+
+/* AVL sort fm_entry into ps_tree by ps_name, slant, and extend */
+
+static int comp_fm_entry_ps(const void *pa, const void *pb, void *p)
+{
+ int i;
+ const fm_entry *p1 = (const fm_entry *) pa, *p2 = (const fm_entry *) pb;
+ assert(p1->ps_name != NULL && p2->ps_name != NULL);
+ if ((i = strcmp(p1->ps_name, p2->ps_name)))
+ return i;
+ cmp_return(p1->slant, p2->slant);
+ cmp_return(p1->extend, p2->extend);
+ return 0;
+}
+
+/* AVL sort ff_entry into ff_tree by ff_name */
+
+static int comp_ff_entry (const void *pa, const void *pb, void *p)
+{
+ return strcmp (((const ff_entry *) pa)->ff_name,
+ ((const ff_entry *) pb)->ff_name);
+}
+
+static void create_avl_trees ()
+{
+ assert(tfm_tree == NULL);
+ tfm_tree = avl_create(comp_fm_entry_tfm, NULL, &avl_xallocator);
+ assert(tfm_tree != NULL);
+ assert(ps_tree == NULL);
+ ps_tree = avl_create(comp_fm_entry_ps, NULL, &avl_xallocator);
+ assert(ps_tree != NULL);
+ assert(ff_tree == NULL);
+ ff_tree = avl_create(comp_ff_entry, NULL, &avl_xallocator);
+ assert(ff_tree != NULL);
+ assert(encname_tree == NULL);
+ encname_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
+ assert(encname_tree != NULL);
+}
+
+/*
+The function avl_do_entry() is not completely symmetrical with regards
+to tfm_name and ps_name handling, e. g. a duplicate tfm_name gives a
+"goto exit", and no ps_name link is tried. This is to keep it compatible
+with the original version.
+*/
+
+int avl_do_entry(fm_entry * fm, int mode)
+{
+ fm_entry *p;
+ void *a;
+ void **aa;
+
+ /* handle tfm_name link */
+
+ if (strcmp(fm->tfm_name, nontfm)) {
+ p = (fm_entry *) avl_find(tfm_tree, fm);
+ if (p != NULL) {
+ switch (mode) {
+ case FM_DUPIGNORE:
+ pdftex_warn
+ ("fontmap entry for `%s' already exists, duplicates ignored",
+ fm->tfm_name);
+ goto exit;
+ break;
+ case FM_REPLACE:
+ case FM_DELETE:
+ if (p->in_use) {
+ pdftex_warn
+ ("fontmap entry for `%s' has been used, replace/delete not allowed",
+ fm->tfm_name);
+ goto exit;
+ }
+ a = avl_delete(tfm_tree, p);
+ assert(a != NULL);
+ unset_tfmlink(p);
+ if (!has_pslink(p))
+ delete_fm_entry(p);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ if (mode != FM_DELETE) {
+ aa = avl_probe(tfm_tree, fm);
+ assert(aa != NULL);
+ set_tfmlink(fm);
+ }
+ }
+
+ /* handle ps_name link */
+
+ if (fm->ps_name != NULL) {
+ p = (fm_entry *) avl_find(ps_tree, fm);
+ if (p != NULL) {
+ switch (mode) {
+ case FM_DUPIGNORE:
+ goto exit;
+ break;
+ case FM_REPLACE:
+ case FM_DELETE:
+ if (p->in_use)
+ goto exit;
+ a = avl_delete(ps_tree, p);
+ assert(a != NULL);
+ unset_pslink(p);
+ if (!has_tfmlink(p))
+ delete_fm_entry(p);
+ break;
+ default:
+ assert(0);
+ }
+ }
+ if (mode != FM_DELETE && is_t1fontfile(fm) && is_included(fm)) {
+ aa = avl_probe(ps_tree, fm);
+ assert(aa != NULL);
+ set_pslink(fm);
+ }
+ }
+ exit:
+ if (!has_tfmlink(fm) && !has_pslink(fm)) /* e. g. after FM_DELETE */
+ return 1; /* deallocation of fm_entry structure required */
+ else
+ return 0;
+}
+
+/* add the encoding name to an AVL tree. this has nothing to do with writeenc.c */
+
+char *add_encname(char *s)
+{
+ char *p;
+ void **aa;
+ assert(s != NULL);
+ assert(encname_tree != NULL);
+ if ((p = (char *) avl_find(encname_tree, s)) == NULL) { /* encoding name not yet registered */
+ p = xstrdup(s);
+ aa = avl_probe(encname_tree, p);
+ assert(aa != NULL);
+ }
+ return p;
+}
+
+/**********************************************************************/
+/* consistency check for map entry, with warn flag */
+
+int check_fm_entry(fm_entry * fm, boolean warn)
+{
+ int a = 0;
+ assert(fm != NULL);
+
+ if (is_fontfile(fm) && !is_included(fm)) {
+ if (warn)
+ pdftex_warn
+ ("ambiguous entry for `%s': font file present but not included, "
+ "will be treated as font file not present", fm->tfm_name);
+ xfree(fm->ff_name);
+ /* do not set variable |a| as this entry will be still accepted */
+ }
+
+ /* if both ps_name and font file are missing, drop this entry */
+ if (fm->ps_name == NULL && !is_fontfile(fm)) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': both ps_name and font file missing",
+ fm->tfm_name);
+ a += 1;
+ }
+
+ /* TrueType fonts cannot be reencoded without subsetting */
+ if (is_truetype(fm) && is_reencoded(fm) && !is_subsetted(fm)) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': only subsetted TrueType font can be reencoded",
+ fm->tfm_name);
+ a += 2;
+ }
+
+ /* SlantFont and ExtendFont can be used only with Type1 fonts */
+ if ((fm->slant != 0 || fm->extend != 0)
+ && !(is_t1fontfile(fm) && is_included(fm))) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': SlantFont/ExtendFont can be used only with embedded Type1 fonts",
+ fm->tfm_name);
+ a += 4;
+ }
+
+ /* the value of SlantFont and ExtendFont must be reasonable */
+ if (abs(fm->slant) > 1000) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': too big value of SlantFont (%g)",
+ fm->tfm_name, fm->slant / 1000.0);
+ a += 8;
+ }
+ if (abs(fm->extend) > 2000) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': too big value of ExtendFont (%g)",
+ fm->tfm_name, fm->extend / 1000.0);
+ a += 16;
+ }
+
+ /* subfonts must be used with subsetted non-reencoded TrueType fonts */
+ if (fm->pid != -1 &&
+ !(is_truetype(fm) && is_subsetted(fm) && !is_reencoded(fm))) {
+ if (warn)
+ pdftex_warn
+ ("invalid entry for `%s': PidEid can be used only with subsetted non-reencoded TrueType fonts",
+ fm->tfm_name);
+ a += 32;
+ }
+
+ return a;
+}
+
+/**********************************************************************/
+/* returns true if s is one of the 14 std. font names; speed-trimmed. */
+
+boolean check_std_t1font(char *s)
+{
+ static const char *std_t1font_names[] = {
+ "Courier", /* 0:7 */
+ "Courier-Bold", /* 1:12 */
+ "Courier-Oblique", /* 2:15 */
+ "Courier-BoldOblique", /* 3:19 */
+ "Helvetica", /* 4:9 */
+ "Helvetica-Bold", /* 5:14 */
+ "Helvetica-Oblique", /* 6:17 */
+ "Helvetica-BoldOblique", /* 7:21 */
+ "Symbol", /* 8:6 */
+ "Times-Roman", /* 9:11 */
+ "Times-Bold", /* 10:10 */
+ "Times-Italic", /* 11:12 */
+ "Times-BoldItalic", /* 12:16 */
+ "ZapfDingbats" /* 13:12 */
+ };
+ static const int index[] =
+ { -1, -1, -1, -1, -1, -1, 8, 0, -1, 4, 10, 9, -1, -1, 5, 2, 12, 6, -1,
+ 3, -1, 7
+ };
+ const size_t n = strlen(s);
+ int k = -1;
+ if (n > 21)
+ return false;
+ if (n == 12) { /* three names have length 12 */
+ switch (*s) {
+ case 'C':
+ k = 1; /* Courier-Bold */
+ break;
+ case 'T':
+ k = 11; /* Times-Italic */
+ break;
+ case 'Z':
+ k = 13; /* ZapfDingbats */
+ break;
+ default:
+ return false;
+ }
+ } else
+ k = index[n];
+ if (k > -1 && !strcmp(std_t1font_names[k], s))
+ return true;
+ return false;
+};
+
+/**********************************************************************/
+
+static void fm_scan_line()
+{
+ int a, b, c, j, u = 0, v = 0;
+ float d;
+ fm_entry *fm;
+ char fm_line[FM_BUF_SIZE], buf[FM_BUF_SIZE];
+ char *p, *q, *r, *s;
+ switch (mitem->type) {
+ case MAPFILE:
+ p = fm_line;
+ do {
+ c = fm_getchar();
+ append_char_to_buf(c, p, fm_line, FM_BUF_SIZE);
+ }
+ while (c != 10 && !fm_eof());
+ *(--p) = '\0';
+ r = fm_line;
+ break;
+ case MAPLINE:
+ r = mitem->line; /* work on string from makecstring() */
+ break;
+ default:
+ assert(0);
+ }
+ if (*r == '\0' || is_cfg_comment(*r))
+ return;
+ fm = new_fm_entry();
+ read_field(r, q, buf);
+ set_field(tfm_name);
+ if (!isdigit(*r)) { /* 2nd field ps_name may not start with a digit */
+ read_field(r, q, buf);
+ set_field(ps_name);
+ }
+ if (isdigit(*r)) { /* font descriptor /Flags given? */
+ for (s = r; isdigit(*s); s++);
+ if (*s == ' ' || *s == '"' || *s == '<' || *s == '\0') { /* not e. g. 8r.enc */
+ fm->fd_flags = atoi(r);
+ while (isdigit(*r))
+ r++;
+ }
+ }
+ while (1) { /* loop through "specials", encoding, font file */
+ skip(r, ' ');
+ switch (*r) {
+ case '\0':
+ goto done;
+ case '"': /* opening quote */
+ r++;
+ u = v = 0;
+ do {
+ skip(r, ' ');
+ if (sscanf(r, "%f %n", &d, &j) > 0) {
+ s = r + j; /* jump behind number, eat also blanks, if any */
+ if (*(s - 1) == 'E' || *(s - 1) == 'e')
+ s--; /* e. g. 0.5ExtendFont: %f = 0.5E */
+ if (str_prefix(s, "SlantFont")) {
+ d *= 1000.0; /* correct rounding also for neg. numbers */
+ fm->slant = (integer) (d > 0 ? d + 0.5 : d - 0.5);
+ r = s + strlen("SlantFont");
+ } else if (str_prefix(s, "ExtendFont")) {
+ d *= 1000.0;
+ fm->extend = (integer) (d > 0 ? d + 0.5 : d - 0.5);
+ if (fm->extend == 1000)
+ fm->extend = 0;
+ r = s + strlen("ExtendFont");
+ } else { /* unknown name */
+ for (r = s; *r != ' ' && *r != '"' && *r != '\0'; r++); /* jump over name */
+ c = *r; /* remember char for temporary end of string */
+ *r = '\0';
+ pdftex_warn
+ ("invalid entry for `%s': unknown name `%s' ignored",
+ fm->tfm_name, s);
+ *r = c;
+ }
+ } else
+ for (; *r != ' ' && *r != '"' && *r != '\0'; r++);
+ }
+ while (*r == ' ');
+ if (*r == '"') /* closing quote */
+ r++;
+ else {
+ pdftex_warn
+ ("invalid entry for `%s': closing quote missing",
+ fm->tfm_name);
+ goto bad_line;
+ }
+ break;
+ case 'P': /* handle cases for subfonts like 'PidEid=3,1' */
+ if (sscanf(r, "PidEid=%i, %i %n", &a, &b, &c) >= 2) {
+ fm->pid = a;
+ fm->eid = b;
+ r += c;
+ break;
+ }
+ default: /* encoding or font file specification */
+ a = b = 0;
+ if (*r == '<') {
+ a = *r++;
+ if (*r == '<' || *r == '[')
+ b = *r++;
+ }
+ read_field(r, q, buf);
+ /* encoding, formats: '8r.enc' or '<8r.enc' or '<[8r.enc' */
+ if (strlen(buf) > 4 && strcasecmp(strend(buf) - 4, ".enc") == 0) {
+ fm->encname = add_encname(buf);
+ u = v = 0; /* u, v used if intervening blank: "<< foo" */
+ } else if (strlen(buf) > 0) { /* file name given */
+ /* font file, formats:
+ * subsetting: '<cmr10.pfa'
+ * no subsetting: '<<cmr10.pfa'
+ * no embedding: 'cmr10.pfa'
+ */
+ if (a == '<' || u == '<') {
+ set_included(fm);
+ if ((a == '<' && b == 0) || (a == 0 && v == 0))
+ set_subsetted(fm);
+ /* otherwise b == '<' (or '[') => no subsetting */
+ }
+ set_field(ff_name);
+ u = v = 0;
+ } else {
+ u = a;
+ v = b;
+ }
+ }
+ }
+ done:
+ if (fm->ps_name != NULL && check_std_t1font(fm->ps_name))
+ set_std_t1font(fm);
+ if (is_fontfile(fm)) {
+ if (strcasecmp(strend(fm_fontfile(fm)) - 4, ".ttf") == 0)
+ set_truetype(fm);
+ else if (strcasecmp(strend(fm_fontfile(fm)) - 4, ".otf") == 0)
+ set_opentype(fm);
+ else
+ set_type1(fm);
+ } else
+ set_type1(fm); /* assume a builtin font is Type1 */
+ if (check_fm_entry(fm, true) != 0)
+ goto bad_line;
+ /*
+ Until here the map line has been completely scanned without errors;
+ fm points to a valid, freshly filled-out fm_entry structure.
+ Now follows the actual work of registering/deleting.
+ */
+ if (handle_subfont_fm(fm, mitem->mode)) /* is this a subfont? */
+ return;
+ if (avl_do_entry(fm, mitem->mode) == 0) /* if success */
+ return;
+ bad_line:
+ delete_fm_entry(fm);
+}
+
+/**********************************************************************/
+
+void fm_read_info ()
+{
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ if (tfm_tree == NULL)
+ create_avl_trees ();
+ if (mitem->line == NULL) /* nothing to do */
+ return;
+ mitem->lineno = 1;
+ switch (mitem->type) {
+ case MAPFILE:
+ set_cur_file_name (mitem->line);
+ if (fm_buffer!=NULL) {
+ xfree(fm_buffer);
+ fm_buffer=NULL;
+ }
+ fm_curbyte=0;
+ fm_size=0;
+ callback_id=callback_defined(find_map_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_map_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &fm_buffer,&fm_size)) {
+ if(file_opened) {
+ if (fm_size>0) {
+ cur_file_name = (char *) nameoffile + 1;
+ if (tracefilenames)
+ tex_printf ("{%s", cur_file_name);
+ while (!fm_eof ()) {
+ fm_scan_line ();
+ mitem->lineno++;
+ }
+ if (tracefilenames)
+ tex_printf ("}");
+ fm_file = NULL;
+ }
+ } else {
+ pdftex_warn ("cannot open font map file");
+ }
+ } else {
+ pdftex_warn ("cannot open font map file");
+ }
+ } else {
+ if (!fm_open ()) {
+ pdftex_warn ("cannot open font map file");
+ } else {
+ fm_read_file();
+ cur_file_name = (char *) nameoffile + 1;
+ tex_printf ("{%s", cur_file_name);
+ while (!fm_eof ()) {
+ fm_scan_line ();
+ mitem->lineno++;
+ }
+ fm_close ();
+ tex_printf ("}");
+ fm_file = NULL;
+ }
+ }
+ break;
+ case MAPLINE:
+ cur_file_name = NULL; /* makes pdftex_warn() shorter */
+ fm_scan_line ();
+ break;
+ default:
+ assert (0);
+ }
+ mitem->line = NULL; /* done with this line */
+ cur_file_name = NULL;
+ return;
+}
+
+/**********************************************************************/
+
+static fm_entry_ptr fmlookup(internalfontnumber f)
+{
+ char *tfm;
+ fm_entry *fm;
+ fm_entry tmp;
+ if (tfm_tree == NULL)
+ fm_read_info(); /* only to read default map file */
+ tfm = font_name(f);
+ assert(strcmp(tfm, nontfm));
+
+ /* Look up for full <tfmname>[+-]<expand> */
+ tmp.tfm_name = tfm;
+ fm = (fm_entry *) avl_find(tfm_tree, &tmp);
+ if (fm != NULL) {
+ fm->in_use = true;
+ return (fm_entry_ptr) fm;
+ }
+ return (fm_entry_ptr) dummy_fm_entry();
+}
+
+boolean hasfmentry(internalfontnumber f)
+{
+ if (font_map(f) == NULL)
+ set_font_map(f, (fm_entry_ptr) fmlookup(f));
+ assert(font_map(f) != NULL);
+ return font_map(f) != (fm_entry_ptr) dummy_fm_entry();
+}
+
+/* check whether a map entry is valid for font replacement */
+
+static boolean fm_valid_for_font_replacement(fm_entry * fm)
+{
+ ff_entry *ff;
+
+ assert(fm != NULL);
+ assert(is_fontfile(fm)); /* ps_tree should contain only entries with font file */
+ assert(is_type1(fm)); /* ps_tree should contain only Type1 entries */
+
+ ff = check_ff_exist(fm->ff_name, false);
+ assert(ff != NULL);
+ if (ff->ff_path == NULL) /* ...there is no font file available */
+ return false;
+ return true; /* all tests passed */
+}
+
+/**********************************************************************/
+/*
+ * lookup fontmap by ps_name;
+ * used for Type1 font replacement when embedding of PDF files
+ */
+
+fm_entry *lookup_fontmap(char *ps_name)
+{
+ fm_entry *fm, *fm2, tmp;
+ char *a, *b, *c, *d, *e, *s;
+ int i, sl, ex;
+ struct avl_traverser t, t2;
+ if (tfm_tree == NULL)
+ fm_read_info(); /* only to read default map file */
+ assert(ps_name != NULL);
+ s = ps_name;
+ if (strlen(ps_name) > 7) { /* check for subsetted name tag */
+ for (i = 0; i < 6; i++, s++)
+ if (*s < 'A' || *s > 'Z')
+ break;
+ if (i == 6 && *s == '+')
+ s++; /* if name tag found, skip behind it */
+ else
+ s = ps_name;
+ }
+
+ /*
+ * Scan -Slant_<slant> and -Extend_<extend> font name extensions;
+ * three valid formats:
+ * <fontname>-Slant_<slant>
+ * <fontname>-Slant_<slant>-Extend_<extend>
+ * <fontname>-Extend_<extend>
+ * Slant entry must come _before_ Extend entry
+ */
+
+ tmp.slant = 0;
+ tmp.extend = 0;
+ if ((a = strstr(s, "-Slant_")) != NULL) {
+ b = a + strlen("-Slant_");
+ sl = (int) strtol(b, &e, 10);
+ if ((e != b) && (e == strend(b))) {
+ tmp.slant = sl;
+ *a = '\0'; /* ps_name string ends before "-Slant_" */
+ } else {
+ if (e != b) { /* only if <slant> is valid number */
+ if ((c = strstr(e, "-Extend_")) != NULL) {
+ d = c + strlen("-Extend_");
+ ex = (int) strtol(d, &e, 10);
+ if ((e != d) && (e == strend(d))) {
+ tmp.slant = sl;
+ tmp.extend = ex;
+ *a = '\0'; /* ps_name string ends before "-Slant_" */
+ }
+ }
+ }
+ }
+ } else {
+ if ((a = strstr(s, "-Extend_")) != NULL) {
+ b = a + strlen("-Extend_");
+ ex = (int) strtol(b, &e, 10);
+ if ((e != b) && (e == strend(b))) {
+ tmp.extend = ex;
+ *a = '\0'; /* ps_name string ends before "-Extend_" */
+ }
+ }
+ }
+ tmp.ps_name = s;
+
+ fm = (fm_entry *) avl_t_find(&t, ps_tree, &tmp);
+ if (fm == NULL)
+ return NULL; /* no entry found */
+
+ /* at this point we know there is at least one fm_entry with given ps_name;
+ * we test all such entries and return the first one that is valid for font
+ * replacement */
+
+ t2 = t;
+ fm2 = (fm_entry *) avl_t_prev(&t2);
+
+ /* search forward */
+ do {
+ if (fm_valid_for_font_replacement(fm))
+ return fm;
+ fm = (fm_entry *) avl_t_next(&t);
+ } while (fm != NULL && comp_fm_entry_ps(fm, &tmp, NULL) == 0);
+
+ /* search backward */
+ while (fm2 != NULL && comp_fm_entry_ps(fm2, &tmp, NULL) == 0) {
+ if (fm_valid_for_font_replacement(fm2))
+ return fm2;
+ fm2 = (fm_entry *) avl_t_prev(&t2);
+ }
+
+ return NULL;
+}
+
+/**********************************************************************/
+/*
+ * Process map file given by its name or map line contents. Items not
+ * beginning with [+-=] flush default map file, if it has not yet been
+ * read. Leading blanks and blanks immediately following [+-=] are
+ * ignored.
+ */
+
+void process_map_item(char *s, int type)
+{
+ char *p;
+ int mode;
+ if (*s == ' ')
+ s++; /* ignore leading blank */
+ switch (*s) {
+ case '+': /* +mapfile.map, +mapline */
+ mode = FM_DUPIGNORE; /* insert entry, if it is not duplicate */
+ s++;
+ break;
+ case '=': /* =mapfile.map, =mapline */
+ mode = FM_REPLACE; /* try to replace earlier entry */
+ s++;
+ break;
+ case '-': /* -mapfile.map, -mapline */
+ mode = FM_DELETE; /* try to delete entry */
+ s++;
+ break;
+ default:
+ mode = FM_DUPIGNORE; /* like +, but also: */
+ mitem->line = NULL; /* flush default map file name */
+ }
+ if (*s == ' ')
+ s++; /* ignore blank after [+-=] */
+ p = s; /* map item starts here */
+ switch (type) {
+ case MAPFILE: /* remove blank at end */
+ while (*p != '\0' && *p != ' ')
+ p++;
+ *p = '\0';
+ break;
+ case MAPLINE: /* blank at end allowed */
+ break;
+ default:
+ assert(0);
+ }
+ if (mitem->line != NULL) /* read default map file first */
+ fm_read_info();
+ if (*s != '\0') { /* only if real item to process */
+ mitem->mode = mode;
+ mitem->type = type;
+ mitem->line = s;
+ fm_read_info();
+ }
+}
+
+void pdfmapfile(integer t)
+{
+ process_map_item(makecstring(tokens_to_string(t)), MAPFILE);
+ flush_str(last_tokens_string);
+}
+
+void pdfmapline(integer t)
+{
+ process_map_item(makecstring(tokens_to_string(t)), MAPLINE);
+ flush_str(last_tokens_string);
+}
+
+void pdf_init_map_file(string map_name)
+{
+ assert(mitem == NULL);
+ mitem = xtalloc(1, mapitem);
+ mitem->mode = FM_DUPIGNORE;
+ mitem->type = MAPFILE;
+ mitem->line = xstrdup(map_name);
+}
+
+
+/**********************************************************************/
+/*
+ * Early check whether a font file exists. Search tree ff_tree is used
+ * in 1st instance, as it may be faster than the kpse_find_file(), and
+ * kpse_find_file() is called only once per font file name + expansion
+ * parameter. This might help keeping speed, if many PDF pages with
+ * same fonts are to be embedded.
+ *
+ * The ff_tree contains only font files, which are actually needed,
+ * so this tree typically is much smaller than the tfm_tree or ps_tree.
+ */
+
+ff_entry *check_ff_exist(char *ff_name, boolean is_tt)
+{
+ ff_entry *ff;
+ ff_entry tmp;
+ void **aa;
+ int callback_id;
+ char *filepath=NULL;
+
+ assert(ff_name != NULL);
+ tmp.ff_name = ff_name;
+ ff = (ff_entry *) avl_find(ff_tree, &tmp);
+ if (ff == NULL) { /* not yet in database */
+ ff = new_ff_entry();
+ ff->ff_name = xstrdup(ff_name);
+ if (is_tt) {
+ callback_id=callback_defined(find_truetype_file_callback);
+ if (callback_id>0) {
+ run_callback(callback_id,"S->S",ff_name,&filepath);
+ if (filepath && strlen(filepath)==0)
+ filepath=NULL;
+ ff->ff_path = filepath;
+ } else {
+ ff->ff_path = kpse_find_file (ff_name, kpse_truetype_format, 0);
+ }
+ }
+ else {
+ callback_id=callback_defined(find_type1_file_callback);
+ if (callback_id>0) {
+ run_callback(callback_id,"S->S",ff_name,&filepath);
+ if (filepath && strlen(filepath)==0)
+ filepath=NULL;
+ ff->ff_path = filepath;
+ } else {
+ ff->ff_path = kpse_find_file (ff_name, kpse_type1_format, 0);
+ }
+ }
+ aa = avl_probe(ff_tree, ff);
+ assert(aa != NULL);
+ }
+ return ff;
+}
+
+/**********************************************************************/
+/* cleaning up... */
+
+static void destroy_fm_entry_tfm(void *pa, void *pb)
+{
+ fm_entry *fm;
+ fm = (fm_entry *) pa;
+ if (!has_pslink(fm))
+ delete_fm_entry(fm);
+ else
+ unset_tfmlink(fm);
+}
+
+static void destroy_fm_entry_ps(void *pa, void *pb)
+{
+ fm_entry *fm;
+ fm = (fm_entry *) pa;
+ if (!has_tfmlink(fm))
+ delete_fm_entry(fm);
+ else
+ unset_pslink(fm);
+}
+
+static void destroy_ff_entry(void *pa, void *pb)
+{
+ ff_entry *ff;
+ ff = (ff_entry *) pa;
+ delete_ff_entry(ff);
+}
+
+void fm_free(void)
+{
+ if (tfm_tree != NULL) {
+ avl_destroy(tfm_tree, destroy_fm_entry_tfm);
+ tfm_tree = NULL;
+ }
+ if (ps_tree != NULL) {
+ avl_destroy(ps_tree, destroy_fm_entry_ps);
+ ps_tree = NULL;
+ }
+ if (ff_tree != NULL) {
+ avl_destroy(ff_tree, destroy_ff_entry);
+ ff_tree = NULL;
+ }
+}
+
+/**********************************************************************/
+/* end of mapfile.c */
diff --git a/Build/source/texk/web2c/luatexdir/font/pkin.c b/Build/source/texk/web2c/luatexdir/font/pkin.c
new file mode 100644
index 00000000000..5067d6dbd66
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/pkin.c
@@ -0,0 +1,439 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: pkin.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+/*
+ * NAME
+ * pkin.c - implementation of readchar()
+ * DESCRIPTION
+ * This implementation of readchar() uses parts of the program dvips
+ * written by Tomas Rokicki--the inventor of the pkformat--(loadfont.c,
+ * download.c and unpack.c). Dvips in turn is derived from pktype.
+ * Pktype(TeX) is described in debt in ``The PKtype processor'',
+ * which is available as pktype.weave as part of the METAFONTware.
+ * What was needed to implement readchar() is rearranged in pkfile.c to
+ * get more modularity in the style of MODULA2.
+ * BUGFIXES
+ * May 1997: Eric Delaunay <delaunay@lix.polytechnique.fr> reports a
+ * problem with huge fonts (greater than 1008 DPI). The code for
+ * handling PK characters in `extended format' was wrongly derived
+ * from dvips. Made some minor improvements regarding error handling.
+ * REDESIGN
+ * Piet Tutelaers
+ * rcpt@urc.tue.nl
+ *
+ * Modified for use with pdftex by Han The Thanh <thanh@fi.muni.cz>.
+ */
+
+#include "ptexlib.h"
+
+/*
+ * Now we have some routines to get stuff from the pk file. pkbyte returns
+ * the next byte from the pk file.
+ */
+
+
+/*
+static FILE *pkfile ;
+*/
+
+extern FILE *t3_file;
+#define pkfile t3_file
+
+static shalfword pkbyte(void)
+{
+ register shalfword i;
+
+ if ((i = xgetc(pkfile)) == EOF)
+ pdftex_fail("unexpected eof in pk file");
+ return (i);
+}
+
+static integer pkduo(void)
+{
+ register integer i;
+
+ i = pkbyte();
+ if (i > 127)
+ i -= 256;
+ i = i * 256 + pkbyte();
+ return (i);
+}
+
+static integer pktrio(void)
+{
+ register integer i;
+
+ i = pkbyte();
+ if (i > 127)
+ i -= 256;
+ i = i * 256 + pkbyte();
+ i = i * 256 + pkbyte();
+ return (i);
+}
+
+static integer pkquad(void)
+{
+ register integer i;
+
+ i = pkbyte();
+ if (i > 127)
+ i -= 256;
+ i = i * 256 + pkbyte();
+ i = i * 256 + pkbyte();
+ i = i * 256 + pkbyte();
+ return (i);
+}
+
+/*
+ * The next part is devoted to unpacking the character data.
+ */
+
+/*
+ * We need procedures to get a nybble, bit, and packed word from the
+ * packed data structure.
+ */
+
+static halfword inputbyte, flagbyte;
+static halfword bitweight;
+static halfword dynf;
+static halfword repeatcount;
+
+static shalfword getnyb(void)
+{
+ halfword temp;
+ if (bitweight == 0) {
+ bitweight = 16;
+ inputbyte = pkbyte();
+ temp = inputbyte >> 4;
+ } else {
+ bitweight = 0;
+ temp = inputbyte & 15;
+ }
+ return (temp);
+}
+
+static boolean getbit(void)
+{
+ bitweight >>= 1;
+ if (bitweight == 0) {
+ inputbyte = pkbyte();
+ bitweight = 128;
+ }
+ return (inputbyte & bitweight);
+}
+
+static halfword(*realfunc) (void);
+long pk_remainder;
+static halfword handlehuge(halfword i, halfword k);
+
+static halfword pkpackednum(void)
+{
+ register halfword i, j;
+ i = getnyb();
+ if (i == 0) {
+ do {
+ j = getnyb();
+ i++;
+ } while (!(j != 0));
+ if (i > 3) {
+/*
+ * Damn, we got a huge count! We *fake* it by giving an artificially
+ * large repeat count.
+ */
+ return (handlehuge(i, j));
+ } else {
+ while (i > 0) {
+ j = j * 16 + getnyb();
+ i--;
+ }
+ return (j - 15 + (13 - dynf) * 16 + dynf);
+ }
+ } else if (i <= dynf)
+ return (i);
+ else if (i < 14)
+ return ((i - dynf - 1) * 16 + getnyb() + dynf + 1);
+ else {
+ if (i == 14)
+ repeatcount = pkpackednum();
+ else
+ repeatcount = 1;
+#ifdef DEBUG
+ printf("[%d]", (int) repeatcount);
+#endif
+ return ((*realfunc) ());
+ }
+}
+
+static halfword rest(void)
+{
+ halfword i;
+
+ if (pk_remainder < 0) {
+ pk_remainder = -pk_remainder;
+ return (0);
+ } else if (pk_remainder > 0) {
+ if (pk_remainder > 4000) {
+ pk_remainder = 4000 - pk_remainder;
+ return (4000);
+ } else {
+ i = pk_remainder;
+ pk_remainder = 0;
+ realfunc = pkpackednum;
+ return (i);
+ }
+ } else {
+ pdftex_fail("shouldn't happen");
+ return 0;
+ /*NOTREACHED*/}
+}
+
+static halfword handlehuge(halfword i, halfword k)
+{
+ register long j = k;
+
+ while (i) {
+ j = (j << 4L) + getnyb();
+ i--;
+ }
+ pk_remainder = j - 15 + (13 - dynf) * 16 + dynf;
+ realfunc = rest;
+ return (rest());
+}
+
+/*
+ * And now we have our unpacking routine.
+ */
+
+static halfword gpower[17] = { 0, 1, 3, 7, 15, 31, 63, 127,
+ 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535
+};
+
+static void unpack(chardesc * cd)
+{
+ register integer i, j;
+ register halfword word, wordweight;
+ halfword *raster;
+ shalfword rowsleft;
+ boolean turnon;
+ shalfword hbit;
+ halfword count;
+ shalfword wordwidth;
+
+ wordwidth = (cd->cwidth + 15) / 16;
+ i = 2 * cd->cheight * (long) wordwidth;
+ if (i <= 0)
+ i = 2;
+ if (i > cd->rastersize) {
+ xfree(cd->raster);
+ cd->rastersize = i;
+ cd->raster = xtalloc(cd->rastersize, halfword);
+ }
+ raster = cd->raster;
+ realfunc = pkpackednum;
+ dynf = flagbyte / 16;
+ turnon = flagbyte & 8;
+ if (dynf == 14) {
+ bitweight = 0;
+ for (i = 1; i <= cd->cheight; i++) {
+ word = 0;
+ wordweight = 32768;
+ for (j = 1; j <= cd->cwidth; j++) {
+ if (getbit())
+ word += wordweight;
+ wordweight >>= 1;
+ if (wordweight == 0) {
+ *raster++ = word;
+ word = 0;
+ wordweight = 32768;
+ }
+ }
+ if (wordweight != 32768)
+ *raster++ = word;
+ }
+ } else {
+ rowsleft = cd->cheight;
+ hbit = cd->cwidth;
+ repeatcount = 0;
+ wordweight = 16;
+ word = 0;
+ bitweight = 0;
+ while (rowsleft > 0) {
+ count = (*realfunc) ();
+#ifdef DEBUG
+ if (turnon)
+ printf("(%d) ", (int) count);
+ else
+ printf("%d ", (int) count);
+#endif
+ while (count != 0) {
+ if ((count < wordweight) && (count < hbit)) {
+ if (turnon)
+ word += gpower[wordweight] - gpower[wordweight - count];
+ hbit -= count;
+ wordweight -= count;
+ count = 0;
+ } else if ((count >= hbit) && (hbit <= wordweight)) {
+ if (turnon)
+ word += gpower[wordweight] - gpower[wordweight - hbit];
+ *raster++ = word;
+ for (i = 1; i <= repeatcount; i++) {
+ for (j = 1; j <= wordwidth; j++) {
+ *raster = *(raster - wordwidth);
+ raster++;
+ }
+ }
+ rowsleft -= repeatcount + 1;
+ repeatcount = 0;
+ word = 0;
+ wordweight = 16;
+ count -= hbit;
+ hbit = cd->cwidth;
+ } else {
+ if (turnon)
+ word += gpower[wordweight];
+ *raster++ = word;
+ word = 0;
+ count -= wordweight;
+ hbit -= wordweight;
+ wordweight = 16;
+ }
+ }
+ turnon = !turnon;
+ }
+ if ((rowsleft != 0) || ((integer) hbit != cd->cwidth))
+ pdftex_fail("error while unpacking; more bits than required");
+ }
+}
+
+/*
+ * readchar(): the main routine
+ * Reads the character definition of character `c' into `cd' if available,
+ * return FALSE (0) otherwise.
+ */
+
+/*
+ * readchar(): the main routine
+ * check pk preamble if necessary,
+ * read the next character definition into `cd',
+ * return EOF if no character definition is available
+ */
+
+int readchar(boolean check_preamble, chardesc * cd)
+{
+ register shalfword i;
+ register integer k;
+ register integer length = 0;
+
+/*
+ * Check the preamble of the pkfile
+ */
+ if (check_preamble) {
+ if (pkbyte() != 247)
+ pdftex_fail("bad pk file, expected pre");
+ if (pkbyte() != 89)
+ pdftex_fail("bad version of pk file");
+ for (i = pkbyte(); i > 0; i--) /* creator of pkfile */
+ (void) pkbyte();
+ (void) pkquad(); /* design size */
+ k = pkquad(); /* checksum */
+ k = pkquad(); /* hppp */
+ k = pkquad(); /* vppp */
+ }
+/*
+ * Now we skip to the desired character definition
+ */
+ while ((flagbyte = pkbyte()) != 245) {
+ if (flagbyte < 240) {
+ switch (flagbyte & 7) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ length = (flagbyte & 7) * 256 + pkbyte() - 3;
+ cd->charcode = pkbyte();
+ (void) pktrio(); /* TFMwidth */
+ cd->xescape = pkbyte(); /* pixel width */
+ cd->cwidth = pkbyte();
+ cd->cheight = pkbyte();
+ cd->xoff = pkbyte();
+ cd->yoff = pkbyte();
+ if (cd->xoff > 127)
+ cd->xoff -= 256;
+ if (cd->yoff > 127)
+ cd->yoff -= 256;
+ break;
+ case 4:
+ case 5:
+ case 6:
+ length = (flagbyte & 3) * 65536L + pkbyte() * 256L;
+ length = length + pkbyte() - 4L;
+ cd->charcode = pkbyte();
+ (void) pktrio(); /* TFMwidth */
+ cd->xescape = pkduo(); /* pixelwidth */
+ cd->cwidth = pkduo();
+ cd->cheight = pkduo();
+ cd->xoff = pkduo();
+ cd->yoff = pkduo();
+ break;
+ case 7:
+ length = pkquad() - 9L;
+ cd->charcode = pkquad();
+ (void) pkquad(); /* TFMwidth */
+ cd->xescape = pkquad(); /* pixelwidth */
+ k = pkquad();
+ cd->cwidth = pkquad();
+ cd->cheight = pkquad();
+ cd->xoff = pkquad();
+ cd->yoff = pkquad();
+ }
+ if (length <= 0)
+ pdftex_fail("packet length (%i) too small", (int) length);
+ unpack(cd);
+ return 1;
+ } else {
+ k = 0;
+ switch (flagbyte) {
+ case 243:
+ k = pkbyte();
+ if (k > 127)
+ k -= 256;
+ case 242:
+ k = k * 256 + pkbyte();
+ case 241:
+ k = k * 256 + pkbyte();
+ case 240:
+ k = k * 256 + pkbyte();
+ while (k-- > 0)
+ i = pkbyte();
+ break;
+ case 244:
+ k = pkquad();
+ break;
+ case 246:
+ break;
+ default:
+ pdftex_fail("unexpected command (%i)", (int) flagbyte);
+ }
+ }
+ }
+ return 0; /* character not found */
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/sfnt.c b/Build/source/texk/web2c/luatexdir/font/sfnt.c
new file mode 100644
index 00000000000..95453a531a0
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/sfnt.c
@@ -0,0 +1,647 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/sfnt.c,v 1.12 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+/* Based on dvipdfmx-0.13.2c */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H_ */
+
+#include <string.h>
+
+#ifndef pdfTeX
+#include "system.h"
+
+#include "error.h"
+#include "mem.h"
+#include "mfileio.h"
+#else
+extern void pdftex_fail (const char *fmt, ...); /* utils.c */
+#endif
+
+#include "sfnt.h"
+
+#ifdef XETEX
+UNSIGNED_BYTE
+ft_unsigned_byte(sfnt* f)
+{
+ unsigned char byte;
+ unsigned long length = 1;
+
+ if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, &byte, &length) != 0)
+ TT_ERROR("sfnt: Freetype failure...");
+ f->loc += 1;
+
+ return byte;
+}
+
+SIGNED_BYTE
+ft_signed_byte(sfnt* f)
+{
+ int b = ft_unsigned_byte(f);
+ if (b >= 0x80)
+ b -= 0x100;
+ return (SIGNED_BYTE)b;
+}
+
+UNSIGNED_PAIR
+ft_unsigned_pair(sfnt* f)
+{
+ unsigned char buf[2];
+ unsigned long length = 2;
+
+ if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0)
+ TT_ERROR("sfnt: Freetype failure...");
+ f->loc += 2;
+
+ return (UNSIGNED_PAIR)((unsigned)buf[0] << 8) + buf[1];
+}
+
+SIGNED_PAIR
+ft_signed_pair(sfnt* f)
+{
+ int p = ft_unsigned_pair(f);
+ if (p >= 0x8000U)
+ p -= 0x10000U;
+
+ return (SIGNED_PAIR)p;
+}
+
+UNSIGNED_QUAD
+ft_unsigned_quad(sfnt* f)
+{
+ unsigned char buf[4];
+ unsigned long length = 4;
+
+ if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0)
+ TT_ERROR("sfnt: Freetype failure...");
+ f->loc += 4;
+
+ return ((unsigned long)buf[0] << 24) + ((unsigned long)buf[1] << 16)
+ + ((unsigned long)buf[2] << 8) + (unsigned long)buf[3];
+}
+
+unsigned long
+ft_read(unsigned char* buf, unsigned long len, sfnt* f)
+{
+ unsigned long length = len;
+ if (FT_Load_Sfnt_Table(f->ft_face, 0, f->loc, buf, &length) != 0)
+ TT_ERROR("sfnt: Freetype failure...");
+ f->loc += len;
+
+ return length;
+}
+#endif
+
+
+/*
+ * type:
+ * `true' (0x74727565): TrueType (Mac)
+ * `typ1' (0x74797031) (Mac): PostScript font housed in a sfnt wrapper
+ * 0x00010000: TrueType (Win)/OpenType
+ * `OTTO': PostScript CFF font with OpenType wrapper
+ * `ttcf': TrueType Collection
+*/
+#define SFNT_TRUETYPE 0x00010000UL
+#define SFNT_MAC_TRUE 0x74727565UL
+#define SFNT_OPENTYPE 0x00010000UL
+#define SFNT_POSTSCRIPT 0x4f54544fUL
+#define SFNT_TTC 0x74746366UL
+
+#ifdef XETEX
+sfnt *
+sfnt_open (FT_Face face, int accept_types)
+{
+ sfnt *sfont;
+ ULONG type;
+
+ if (!face || !FT_IS_SFNT(face))
+ return NULL;
+
+ sfont = NEW(1, sfnt);
+ sfont->ft_face = face;
+ sfont->loc = 0;
+ sfont->type = 0;
+
+ type = sfnt_get_ulong(sfont);
+
+ if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) {
+ sfont->type = SFNT_TYPE_TRUETYPE;
+ } else if (type == SFNT_OPENTYPE) {
+ sfont->type = SFNT_TYPE_OPENTYPE;
+ } else if (type == SFNT_POSTSCRIPT) {
+ sfont->type = SFNT_TYPE_POSTSCRIPT;
+ } else if (type == SFNT_TTC) {
+ sfont->type = SFNT_TYPE_TTC;
+ }
+
+ if ((sfont->type & accept_types) == 0) {
+ RELEASE(sfont);
+ return NULL;
+ }
+
+ sfont->loc = 0;
+
+ sfont->directory = NULL;
+
+ return sfont;
+}
+#else /* not XETEX */
+#ifdef pdfTeX
+sfnt *
+sfnt_open (unsigned char *buffer, integer buflen)
+{
+ sfnt *sfont;
+ ULONG type;
+
+ sfont = xmalloc(sizeof(sfnt));
+ sfont->loc = 0;
+ sfont->buffer = buffer;
+ sfont->buflen = buflen;
+
+ type = sfnt_get_ulong(sfont);
+
+ if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) {
+ sfont->type = SFNT_TYPE_TRUETYPE;
+ } else if (type == SFNT_OPENTYPE) {
+ sfont->type = SFNT_TYPE_OPENTYPE;
+ } else if (type == SFNT_POSTSCRIPT) {
+ sfont->type = SFNT_TYPE_POSTSCRIPT;
+ } else if (type == SFNT_TTC) {
+ sfont->type = SFNT_TYPE_TTC;
+ }
+
+ sfont->loc=0;
+ sfont->directory = NULL;
+ return sfont;
+}
+#else
+sfnt *
+sfnt_open (FILE *fp)
+{
+ sfnt *sfont;
+ ULONG type;
+
+ ASSERT(fp);
+
+ rewind(fp);
+
+ sfont = NEW(1, sfnt);
+
+ sfont->stream = fp;
+
+ type = sfnt_get_ulong(sfont);
+
+ if (type == SFNT_TRUETYPE || type == SFNT_MAC_TRUE) {
+ sfont->type = SFNT_TYPE_TRUETYPE;
+ } else if (type == SFNT_OPENTYPE) {
+ sfont->type = SFNT_TYPE_OPENTYPE;
+ } else if (type == SFNT_POSTSCRIPT) {
+ sfont->type = SFNT_TYPE_POSTSCRIPT;
+ } else if (type == SFNT_TTC) {
+ sfont->type = SFNT_TYPE_TTC;
+ }
+
+ rewind(sfont->stream);
+
+ sfont->directory = NULL;
+
+ return sfont;
+}
+#endif
+#endif
+
+static void
+release_directory (struct sfnt_table_directory *td)
+{
+ long i;
+
+ if (td) {
+ if (td->tables) {
+ for (i = 0; i < td->num_tables; i++) {
+ if (td->tables[i].data)
+ RELEASE(td->tables[i].data);
+ }
+ RELEASE(td->tables);
+ }
+ if (td->flags)
+ RELEASE(td->flags);
+ RELEASE(td);
+ }
+
+ return;
+}
+
+void
+sfnt_close (sfnt *sfont)
+{
+
+ if (sfont) {
+ if (sfont->directory)
+ release_directory(sfont->directory);
+ RELEASE(sfont);
+ }
+
+ return;
+}
+
+int
+put_big_endian (void *s, LONG q, int n)
+{
+ int i;
+ char *p;
+
+ p = (char *) s;
+ for (i = n - 1; i >= 0; i--) {
+ p[i] = (char) (q & 0xff);
+ q >>= 8;
+ }
+
+ return n;
+}
+
+/* Convert four-byte number to big endianess
+ * in a machine independent way.
+ */
+static void
+convert_tag (char *tag, unsigned long u_tag)
+{
+ int i;
+
+ for (i = 3; i >= 0; i--) {
+ tag[i] = (char) (u_tag % 256);
+ u_tag /= 256;
+ }
+
+ return;
+}
+
+/*
+ * Computes the max power of 2 <= n
+ */
+static unsigned
+max2floor (unsigned n)
+{
+ int val = 1;
+
+ while (n > 1) {
+ n /= 2;
+ val *= 2;
+ }
+
+ return val;
+}
+
+/*
+ * Computes the log2 of the max power of 2 <= n
+ */
+static unsigned
+log2floor (unsigned n)
+{
+ unsigned val = 0;
+
+ while (n > 1) {
+ n /= 2;
+ val++;
+ }
+
+ return val;
+}
+
+static ULONG
+sfnt_calc_checksum(void *data, ULONG length)
+{
+ ULONG chksum = 0;
+ BYTE *p, *endptr;
+ int count = 0;
+
+ p = (BYTE *) data;
+ endptr = p + length;
+ while (p < endptr) {
+ chksum += (p[0] << (8 * ( 3 - count)));
+ count = ((count + 1) & 3);
+ p++;
+ }
+
+ return chksum;
+}
+
+static int
+find_table_index (struct sfnt_table_directory *td, const char *tag)
+{
+ int idx;
+
+ if (!td)
+ return -1;
+
+ for (idx = 0; idx < td->num_tables; idx++) {
+ if (!memcmp(td->tables[idx].tag, tag, 4))
+ return idx;
+ }
+
+ return -1;
+}
+
+void
+sfnt_set_table (sfnt *sfont, const char *tag, void *data, ULONG length)
+{
+ struct sfnt_table_directory *td;
+ int idx;
+
+ ASSERT(sfont);
+
+ td = sfont->directory;
+ idx = find_table_index(td, tag);
+
+ if (idx < 0) {
+ idx = td->num_tables;
+ td->num_tables++;
+ td->tables = RENEW(td->tables, td->num_tables, struct sfnt_table);
+ memcpy(td->tables[idx].tag, tag, 4);
+ }
+
+ td->tables[idx].check_sum = sfnt_calc_checksum(data, length);
+ td->tables[idx].offset = 0L;
+ td->tables[idx].length = length;
+ td->tables[idx].data = data;
+
+ return;
+}
+
+ULONG
+sfnt_find_table_len (sfnt *sfont, const char *tag)
+{
+ ULONG length;
+ struct sfnt_table_directory *td;
+ int idx;
+
+ ASSERT(sfont && tag);
+
+ td = sfont->directory;
+ idx = find_table_index(td, tag);
+ if (idx < 0)
+ length = 0;
+ else {
+ length = td->tables[idx].length;
+ }
+
+ return length;
+}
+
+ULONG
+sfnt_find_table_pos (sfnt *sfont, const char *tag)
+{
+ ULONG offset;
+ struct sfnt_table_directory *td;
+ int idx;
+
+ ASSERT(sfont && tag);
+
+ td = sfont->directory;
+ idx = find_table_index(td, tag);
+ if (idx < 0)
+ offset = 0;
+ else {
+ offset = td->tables[idx].offset;
+ }
+
+ return offset;
+}
+
+ULONG
+sfnt_locate_table (sfnt *sfont, const char *tag)
+{
+ ULONG offset;
+
+ ASSERT(sfont && tag);
+
+ offset = sfnt_find_table_pos(sfont, tag);
+ if (offset == 0)
+ TT_ERROR("sfnt: table not found...");
+
+ sfnt_seek_set(sfont, offset);
+
+ return offset;
+}
+
+int
+sfnt_read_table_directory (sfnt *sfont, ULONG offset)
+{
+ struct sfnt_table_directory *td;
+ unsigned long i, u_tag;
+
+ ASSERT(sfont);
+
+ if (sfont->directory)
+ release_directory(sfont->directory);
+ sfont->directory = td = NEW (1, struct sfnt_table_directory);
+
+#ifdef XETEX
+ ASSERT(sfont->ft_face);
+#elif defined(pdfTeX)
+ ASSERT(sfont->buffer);
+#else
+ ASSERT(sfont->stream);
+#endif
+
+ sfnt_seek_set(sfont, offset);
+
+ td->version = sfnt_get_ulong(sfont);
+ td->num_tables = sfnt_get_ushort(sfont);
+ td->search_range = sfnt_get_ushort(sfont);
+ td->entry_selector = sfnt_get_ushort(sfont);
+ td->range_shift = sfnt_get_ushort(sfont);
+
+ td->flags = NEW(td->num_tables, char);
+ td->tables = NEW(td->num_tables, struct sfnt_table);
+
+ for (i = 0; i < td->num_tables; i++) {
+ u_tag = sfnt_get_ulong(sfont);
+
+ convert_tag(td->tables[i].tag, u_tag);
+ td->tables[i].check_sum = sfnt_get_ulong(sfont);
+ td->tables[i].offset = sfnt_get_ulong(sfont);
+ td->tables[i].length = sfnt_get_ulong(sfont);
+ td->tables[i].data = NULL;
+
+ td->flags[i] = 0;
+ }
+
+ td->num_kept_tables = 0;
+
+ return 0;
+}
+
+int
+sfnt_require_table (sfnt *sfont, const char *tag, int must_exist)
+{
+ struct sfnt_table_directory *td;
+ int idx;
+
+ ASSERT(sfont && sfont->directory);
+
+ td = sfont->directory;
+ idx = find_table_index(td, tag);
+ if (idx < 0) {
+ if (must_exist)
+ return -1;
+ } else {
+ td->flags[idx] |= SFNT_TABLE_REQUIRED;
+ td->num_kept_tables++;
+ }
+
+ return 0;
+}
+
+#ifndef pdfTeX
+#include "pdfobj.h"
+#endif
+
+/*
+ * o All tables begin on four byte boundries, and pad any remaining space
+ * between tables with zeros
+ *
+ * o Entries in the Table Directory must be sorted in ascending order by tag
+ *
+ * o The head table contains checksum of the whole font file.
+ * To compute: first set it to 0, sum the entire font as ULONG,
+ * then store 0xB1B0AFBA - sum.
+ */
+
+#ifdef pdfTeX
+extern pdf_obj *pdf_new_stream(void);
+extern void pdf_add_stream(pdf_obj *, unsigned char *, long);
+extern void pdf_release_obj(pdf_obj *);
+#undef MIN
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define STREAM_COMPRESS
+#endif
+
+static unsigned char wbuf[1024], padbytes[4] = {0, 0, 0, 0};
+
+pdf_obj *
+sfnt_create_FontFile_stream (sfnt *sfont)
+{
+ pdf_obj *stream;
+#ifndef pdfTeX
+ pdf_obj *stream_dict;
+#endif
+ struct sfnt_table_directory *td;
+ long offset, nb_read, length;
+ int i, sr;
+ char *p;
+
+ ASSERT(sfont && sfont->directory);
+
+ stream = pdf_new_stream(STREAM_COMPRESS);
+
+ td = sfont->directory;
+
+ /* Header */
+ p = (char *) wbuf;
+ p += sfnt_put_ulong (p, td->version);
+ p += sfnt_put_ushort(p, td->num_kept_tables);
+ sr = max2floor(td->num_kept_tables) * 16;
+ p += sfnt_put_ushort(p, sr);
+ p += sfnt_put_ushort(p, log2floor(td->num_kept_tables));
+ p += sfnt_put_ushort(p, td->num_kept_tables * 16 - sr);
+
+ pdf_add_stream(stream, wbuf, 12);
+
+ /*
+ * Compute start of actual tables (after headers).
+ */
+ offset = 12 + 16 * td->num_kept_tables;
+ for (i = 0; i < td->num_tables; i++) {
+ /* This table must exist in FontFile */
+ if (td->flags[i] & SFNT_TABLE_REQUIRED) {
+ if ((offset % 4) != 0) {
+ offset += 4 - (offset % 4);
+ }
+
+ p = (char *) wbuf;
+ memcpy(p, td->tables[i].tag, 4);
+ p += 4;
+ p += sfnt_put_ulong(p, td->tables[i].check_sum);
+ p += sfnt_put_ulong(p, offset);
+ p += sfnt_put_ulong(p, td->tables[i].length);
+ pdf_add_stream(stream, wbuf, 16);
+
+ offset += td->tables[i].length;
+ }
+ }
+
+ offset = 12 + 16 * td->num_kept_tables;
+ for (i = 0; i < td->num_tables; i++) {
+ if (td->flags[i] & SFNT_TABLE_REQUIRED) {
+ if ((offset % 4) != 0) {
+ length = 4 - (offset % 4);
+ pdf_add_stream(stream, padbytes, length);
+ offset += length;
+ }
+ if (!td->tables[i].data) {
+#ifdef XETEX
+ if (!sfont->ft_face)
+#elif defined(pdfTeX)
+ if (!sfont->buffer)
+#else
+ if (!sfont->stream)
+#endif
+ {
+ pdf_release_obj(stream);
+ TT_ERROR("Font file not opened or already closed...");
+ return NULL;
+ }
+
+ length = td->tables[i].length;
+ sfnt_seek_set(sfont, td->tables[i].offset);
+ while (length > 0) {
+ nb_read = sfnt_read(wbuf, MIN(length, 1024), sfont);
+ if (nb_read < 0) {
+ pdf_release_obj(stream);
+ TT_ERROR("Reading file failed...");
+ return NULL;
+ } else if (nb_read > 0) {
+ pdf_add_stream(stream, wbuf, nb_read);
+ }
+ length -= nb_read;
+ }
+ } else {
+ pdf_add_stream(stream,
+ (unsigned char *)td->tables[i].data,
+ td->tables[i].length);
+ RELEASE(td->tables[i].data);
+ td->tables[i].data = NULL;
+ }
+ /* Set offset for next table */
+ offset += td->tables[i].length;
+ }
+ }
+
+#ifndef pdfTeX
+ stream_dict = pdf_stream_dict(stream);
+ pdf_add_dict(stream_dict,
+ pdf_new_name("Length1"),
+ pdf_new_number(offset));
+#endif
+ return stream;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/sfnt.h b/Build/source/texk/web2c/luatexdir/font/sfnt.h
new file mode 100644
index 00000000000..8db54dd9c39
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/sfnt.h
@@ -0,0 +1,197 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/sfnt.h,v 1.9 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifndef _SFNT_H_
+#define _SFNT_H_
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H_ */
+
+#ifndef pdfTeX
+#include "mfileio.h"
+#include "numbers.h"
+#include "pdfobj.h"
+#endif
+
+#ifdef XETEX
+#include "ft2build.h"
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TABLES_H
+#endif
+
+/* Data Types as described in Apple's TTRefMan */
+typedef unsigned char BYTE;
+typedef signed char ICHAR;
+typedef unsigned short USHORT;
+typedef signed short SHORT;
+typedef unsigned long ULONG;
+typedef signed long LONG;
+typedef unsigned long Fixed; /* 16.16-bit signed fixed-point number */
+typedef short FWord;
+typedef unsigned short uFWord;
+typedef short F2Dot14; /* 16-bit signed fixed number with the low
+ 14 bits representing fraction. */
+
+struct sfnt_table
+{
+ /* table header */
+ char tag[4];
+ ULONG check_sum;
+ ULONG offset;
+ ULONG length;
+ char *data; /* table data */
+};
+
+#define SFNT_TABLE_REQUIRED (1 << 0)
+
+struct sfnt_table_directory
+{
+ ULONG version; /* Fixed for Win */
+ USHORT num_tables;
+ USHORT search_range;
+ USHORT entry_selector;
+ USHORT range_shift;
+ USHORT num_kept_tables; /* number of kept tables */
+ char *flags; /* keep or omit */
+ struct sfnt_table *tables;
+};
+
+/* sfnt resource */
+#define SFNT_TYPE_TRUETYPE (1 << 0)
+#define SFNT_TYPE_OPENTYPE (1 << 1)
+#define SFNT_TYPE_POSTSCRIPT (1 << 2)
+#define SFNT_TYPE_TTC (1 << 4)
+
+typedef struct
+{
+ int type;
+ struct sfnt_table_directory *directory;
+#ifdef XETEX
+ FT_Face ft_face;
+ long loc;
+#elif defined(pdfTeX)
+ BYTE *buffer;
+ long buflen;
+ long loc;
+#else
+ FILE *stream;
+#endif
+} sfnt;
+
+/* Convert sfnt "fixed" type to double */
+#define fixed(a) ((double)((a)%0x10000L)/(double)(0x10000L) + \
+ (a)/0x10000L - (((a)/0x10000L > 0x7fffL) ? 0x10000L : 0))
+
+#ifdef XETEX
+UNSIGNED_BYTE ft_unsigned_byte(sfnt* f);
+SIGNED_BYTE ft_signed_byte(sfnt* f);
+UNSIGNED_PAIR ft_unsigned_pair(sfnt* f);
+SIGNED_PAIR ft_signed_pair(sfnt* f);
+UNSIGNED_QUAD ft_unsigned_quad(sfnt* f);
+unsigned long ft_read(unsigned char* buf, unsigned long len, sfnt* f);
+
+#define sfnt_get_byte(s) ((BYTE) ft_unsigned_byte(s))
+#define sfnt_get_char(s) ((ICHAR) ft_signed_byte (s))
+#define sfnt_get_ushort(s) ((USHORT) ft_unsigned_pair(s))
+#define sfnt_get_short(s) ((SHORT) ft_signed_pair (s))
+#define sfnt_get_ulong(s) ((ULONG) ft_unsigned_quad(s))
+#define sfnt_get_long(s) ((LONG) ft_signed_quad (s))
+
+#define sfnt_seek_set(s,o) (s)->loc = (o)
+#define sfnt_read(b,l,s) ft_read((b), (l), (s))
+#elif defined(pdfTeX)
+BYTE get_unsigned_byte(sfnt* f);
+ICHAR get_signed_byte(sfnt* f);
+USHORT get_unsigned_pair(sfnt* f);
+SHORT get_signed_pair(sfnt* f);
+ULONG get_unsigned_quad(sfnt* f);
+int do_sfnt_read (unsigned char *dest, int len, sfnt *f);
+
+#define sfnt_get_byte(s) ((BYTE) get_unsigned_byte(s))
+#define sfnt_get_char(s) ((ICHAR) get_signed_byte (s))
+#define sfnt_get_ushort(s) ((USHORT) get_unsigned_pair(s))
+#define sfnt_get_short(s) ((SHORT) get_signed_pair (s))
+#define sfnt_get_ulong(s) ((ULONG) get_unsigned_quad(s))
+#define sfnt_get_long(s) ((LONG) get_signed_quad (s))
+
+#define sfnt_seek_set(s,o) (s)->loc = (o)
+#define sfnt_read(b,l,s) do_sfnt_read((b), (l), (s))
+#else
+/* get_***_*** from numbers.h */
+#define sfnt_get_byte(s) ((BYTE) get_unsigned_byte((s)->stream))
+#define sfnt_get_char(s) ((ICHAR) get_signed_byte ((s)->stream))
+#define sfnt_get_ushort(s) ((USHORT) get_unsigned_pair((s)->stream))
+#define sfnt_get_short(s) ((SHORT) get_signed_pair ((s)->stream))
+#define sfnt_get_ulong(s) ((ULONG) get_unsigned_quad((s)->stream))
+#define sfnt_get_long(s) ((LONG) get_signed_quad ((s)->stream))
+
+#define sfnt_seek_set(s,o) seek_absolute((s)->stream, (o))
+#define sfnt_read(b,l,s) fread((b), 1, (l), (s)->stream)
+#endif
+
+extern int put_big_endian (void *s, LONG q, int n);
+
+#define sfnt_put_ushort(s,v) put_big_endian((s), v, 2);
+#define sfnt_put_short(s,v) put_big_endian((s), v, 2);
+#define sfnt_put_ulong(s,v) put_big_endian((s), v, 4);
+#define sfnt_put_long(s,v) put_big_endian((s), v, 4);
+
+#ifdef XETEX
+extern sfnt *sfnt_open (FT_Face face, int accept_types);
+#elif defined(pdfTeX)
+extern sfnt *sfnt_open (unsigned char *buffer, integer buflen);
+#else
+extern sfnt *sfnt_open (FILE *fp);
+#endif
+extern void sfnt_close (sfnt *sfont);
+
+/* table directory */
+extern int sfnt_read_table_directory (sfnt *sfont, ULONG offset);
+extern ULONG sfnt_find_table_len (sfnt *sfont, const char *tag);
+extern ULONG sfnt_find_table_pos (sfnt *sfont, const char *tag);
+extern ULONG sfnt_locate_table (sfnt *sfont, const char *tag);
+
+extern void sfnt_set_table (sfnt *sfont,
+ const char *tag, void *data, ULONG length);
+extern int sfnt_require_table (sfnt *sfont, const char *tag, int must_exist);
+
+#ifdef pdfTeX
+typedef struct
+{
+ ULONG length;
+ BYTE *data;
+} pdf_obj;
+
+#define ASSERT(a) assert(a)
+#define RELEASE(a) free(a)
+#define NEW(a,b) xmalloc((a)*sizeof(b))
+#define RENEW(a,b,c) xrealloc(a, ((b)*sizeof(c)))
+#define TT_ERROR pdftex_fail
+#define WARN printf
+
+
+#endif
+
+extern pdf_obj *sfnt_create_FontFile_stream (sfnt *sfont);
+
+#endif /* _SFNT_H_ */
diff --git a/Build/source/texk/web2c/luatexdir/font/subfont.c b/Build/source/texk/web2c/luatexdir/font/subfont.c
new file mode 100644
index 00000000000..836985c10fd
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/subfont.c
@@ -0,0 +1,264 @@
+/*
+Copyright (c) 2005-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "ptexlib.h"
+#include <string.h>
+
+static struct avl_table *sfd_tree = NULL;
+
+static unsigned char *sfd_buffer = NULL;
+static integer sfd_size = 0;
+static integer sfd_curbyte = 0;
+
+#define SFD_BUF_SIZE SMALL_BUF_SIZE
+
+#define sfd_close() xfclose(sfd_file, cur_file_name)
+#define sfd_open() open_input(&sfd_file, kpse_sfd_format, FOPEN_RBIN_MODE)
+
+#define sfd_read_file() readbinfile(sfd_file,&sfd_buffer,&sfd_size)
+#define sfd_getchar() sfd_buffer[sfd_curbyte++]
+#define sfd_eof() (sfd_curbyte>sfd_size)
+
+
+static FILE *sfd_file;
+static char sfd_line[SFD_BUF_SIZE];
+
+static subfont_entry *new_subfont_entry (void)
+{
+ int i;
+ subfont_entry *subfont;
+ subfont = xtalloc (1, subfont_entry);
+ subfont->infix = NULL;
+ for (i = 0; i < 256; ++i)
+ subfont->charcodes[i] = -1; /* unassigned */
+ subfont->next = NULL;
+ return subfont;
+}
+
+static sfd_entry *new_sfd_entry (void)
+{
+ sfd_entry *sfd;
+ sfd = xtalloc (1, sfd_entry);
+ sfd->name = NULL;
+ sfd->subfont = NULL;
+ return sfd;
+}
+
+static void destroy_sfd_entry (void *pa, void *pb)
+{
+ subfont_entry *p, *q;
+ sfd_entry *sfd;
+ sfd = (sfd_entry *) pa;
+ p = sfd->subfont;
+ while (p != NULL) {
+ q = p->next;
+ xfree (p->infix);
+ xfree (p);
+ p = q;
+ }
+ xfree (sfd->name);
+}
+
+static int comp_sfd_entry (const void *pa, const void *pb, void *p)
+{
+ return strcmp (((const sfd_entry *) pa)->name,
+ ((const sfd_entry *) pb)->name);
+}
+
+void sfd_free (void)
+{
+ if (sfd_tree != NULL)
+ avl_destroy (sfd_tree, destroy_sfd_entry);
+}
+
+static void sfd_getline (boolean expect_eof)
+{
+ char *p;
+ int c;
+ restart:
+ if (sfd_eof ()) {
+ if (expect_eof)
+ return;
+ else
+ pdftex_fail ("unexpected end of file");
+ }
+ p = sfd_line;
+ do {
+ c = sfd_getchar ();
+ append_char_to_buf (c, p, sfd_line, SFD_BUF_SIZE);
+ } while (c != 10 && !sfd_eof());
+ append_eol (p, sfd_line, SFD_BUF_SIZE);
+ if (p - sfd_line < 2 || *sfd_line == '#')
+ goto restart;
+}
+
+static sfd_entry *read_sfd (char *sfd_name)
+{
+ void **aa;
+ sfd_entry *sfd, tmp_sfd;
+ subfont_entry *sf;
+ char *ftemp = NULL;
+ char buf[SMALL_BUF_SIZE], *p;
+ long int i, j, k;
+ int n;
+ int callback_id=0;
+ int file_opened=0;
+ /* check whether this sfd has been read */
+ tmp_sfd.name = sfd_name;
+ if (sfd_tree == NULL) {
+ sfd_tree = avl_create (comp_sfd_entry, NULL, &avl_xallocator);
+ assert (sfd_tree != NULL);
+ }
+ sfd = (sfd_entry *) avl_find (sfd_tree, &tmp_sfd);
+ if (sfd != NULL)
+ return sfd;
+ set_cur_file_name (sfd_name);
+ if (sfd_buffer!=NULL) {
+ xfree(sfd_buffer);
+ sfd_buffer=NULL;
+ }
+ sfd_curbyte=0;
+ sfd_size=0;
+
+ callback_id=callback_defined(find_sfd_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",cur_file_name,&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ if (cur_file_name)
+ free(cur_file_name);
+ cur_file_name = xstrdup(ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_sfd_file_callback);
+ if (callback_id>0) {
+ if(! (run_callback(callback_id,"S->bSd",cur_file_name,
+ &file_opened, &sfd_buffer,&sfd_size) &&
+ file_opened &&
+ sfd_size>0 ) ) {
+ pdftex_warn ("cannot open SFD file for reading");
+ cur_file_name = NULL;
+ return NULL;
+ }
+ sfd_read_file();
+ sfd_close();
+ }
+ tex_printf ("{");
+ tex_printf (cur_file_name);
+ sfd = new_sfd_entry ();
+ sfd->name = xstrdup (sfd_name);
+ while (!sfd_eof ()) {
+ sfd_getline (true);
+ if (*sfd_line == 10) /* empty line indicating eof */
+ break;
+ sf = new_subfont_entry ();
+ sf->next = sfd->subfont;
+ sfd->subfont = sf;
+ sscanf (sfd_line, "%s %n", buf, &n);
+ sf->infix = xstrdup (buf);
+ p = sfd_line + n; /* skip to the next word */
+ k = 0;
+ read_ranges:
+ for (;;) {
+ if (*p == '\\') { /* continue on next line */
+ sfd_getline (false);
+ p = sfd_line;
+ goto read_ranges;
+ } else if (*p == 0) /* end of subfont */
+ break;
+ if (sscanf (p, " %li %n", &i, &n) == 0)
+ pdftex_fail ("invalid token:\n%s", p);
+ p += n;
+ if (*p == ':') { /* offset */
+ k = i;
+ p++;
+ } else if (*p == '_') { /* range */
+ if (sscanf (p + 1, " %li %n", &j, &n) == 0)
+ pdftex_fail ("invalid token:\n%s", p);
+ if (i > j || k + (j - i) > 255)
+ pdftex_fail ("invalid range:\n%s", p);
+ while (i <= j)
+ sf->charcodes[k++] = i++;
+ p += n + 1;
+ } else /* codepoint */
+ sf->charcodes[k++] = i;
+ }
+ }
+ tex_printf ("}");
+ aa = avl_probe (sfd_tree, sfd);
+ assert (aa != NULL);
+ return sfd;
+}
+
+boolean handle_subfont_fm (fm_entry * fm, int mode)
+{
+ size_t l;
+ char *p, *q, *r;
+ sfd_entry *sfd;
+ subfont_entry *sf;
+ fm_entry *fm2;
+ char buf[SMALL_BUF_SIZE];
+ assert (fm->tfm_name != NULL);
+ p = fm->tfm_name;
+ q = strchr (p, '@'); /* search for the first '@' */
+ if (q == NULL)
+ return false;
+ r = strchr (q + 1, '@'); /* search for the second '@' */
+ if (r == NULL)
+ return false;
+ if (q <= p || r <= q + 1 /* prefix or sfd name is empty */
+ || r - p != strlen (p) - 1) /* or the second '@' is not the last char yet */
+ return false;
+ l = r - (q + 1); /* length of sfd name */
+ strncpy (buf, q + 1, l);
+ buf[l] = 0;
+ check_buf(strlen(buf) + 4, SMALL_BUF_SIZE);
+ strcat (buf, ".sfd");
+ sfd = read_sfd (buf);
+ if (sfd == NULL)
+ return false;
+ /* at this point we know fm is a subfont */
+ set_subfont (fm);
+ xfree (fm->ps_name);
+ fm->ps_name = NULL;
+ /* set default values for PidEid */
+ if (fm->pid == -1) {
+ fm->pid = 3;
+ fm->eid = 1;
+ }
+ l = q - p; /* length of base tfm name (prefix) */
+ for (sf = sfd->subfont; sf != NULL; sf = sf->next) {
+ strncpy (buf, p, l);
+ buf[l] = 0;
+ strcat (buf, sf->infix);
+ fm2 = new_fm_entry ();
+ fm2->tfm_name = xstrdup (buf);
+ fm2->ff_name = xstrdup (fm->ff_name);
+ fm2->type = fm->type;
+ fm2->pid = fm->pid;
+ fm2->eid = fm->eid;
+ fm2->subfont = sf;
+ if (avl_do_entry (fm2, mode) != 0) /* try to insert the entry */
+ delete_fm_entry (fm2); /* delete it if failed */
+ }
+ delete_fm_entry (fm);
+ return true;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/subfont.txt b/Build/source/texk/web2c/luatexdir/font/subfont.txt
new file mode 100644
index 00000000000..9fe053cbb9c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/subfont.txt
@@ -0,0 +1,74 @@
+map entry:
+
+cyberb@Unicode@ <cyberbit.ttf PidEid=3,1
+
+means
+
+cyberb<INFIX> => look at Unicode.sfd => find the mapping => charcode
+ => PidEid=3,1 => glyphs
+
+eg cyberb01 => subfont 01 in Unicode.sfd => charcodes
+
+Infix can be anything, thus the question: given a tfm name, how to find out
+whether this is a subfont?
+
+It is safe to limit the infix to be composed from hexadecimal digits only?
+
+If so, one possibility is:
+
+(1)
+while last-char-of-tfmname is a hexdigit do
+ remove the last char from tfmname
+ do a lookup for the tfmname
+ if found an entry with subfont flag then
+ break
+enddo
+
+(2)
+Or, when a map entry with subfont flag is scanned, let pdftex create all
+the relevant entries. Which may be a safer and faster solution (but wastes more
+memory)
+
+
+Let's do (2), as infix can be any word.
+
+
+
+Implementation:
+
+- let's have a map entry:
+
+cyberb@Unicode@ <cyberbit.ttf PidEid=3,1
+
+- actions:
+ - read Unicode.sfd
+ - create corresponding sfd mapping like ("01", "Unicode") => long[256]
+ - added those subfont to an AVL tree
+ - create map entries for cyberb01--cyberbff, each has a pointer to the
+ corresponding sfd mapping entry
+
+- extended attributes for map entry:
+ - Pid
+ - Eid
+ - sfd_map
+
+- sfd_mapping:
+ - name: sfd name, eg "Unicode"
+ - infix, eg "01"
+ - mapping: long[256]
+
+- how to find out whether a sfd has been loaded:
+ - lookup for any entry with the given sfd name
+
+- functions:
+ - load_sfd
+ - lookup_subfont
+ - extend reading map entries
+
+- when writting ttf:
+ - if re-encoded --> process like in case of type1 fonts
+ - if PidEid is being used:
+ - read cmap tables: store (ttfname, pid, eid)
+ - search for used chars
+ - use sfd to find the charcodes
+ - look into cmap to
diff --git a/Build/source/texk/web2c/luatexdir/font/texfont.c b/Build/source/texk/web2c/luatexdir/font/texfont.c
new file mode 100644
index 00000000000..150c2cba769
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/texfont.c
@@ -0,0 +1,1094 @@
+/*
+ Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+ This file is part of LuaTeX.
+
+ LuaTeX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ LuaTeX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LuaTeX; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ $Id: texfont.c 1013 2008-02-14 00:09:02Z oneiros $ */
+
+/* Main font API implementation for the pascal parts */
+
+/* stuff to watch out for:
+ *
+ * - Knuth had a 'null_character' that was used when a character could
+ * not be found by the fetch() routine, to signal an error. This has
+ * been deleted, but it may mean that the output of luatex is
+ * incompatible with TeX after fetch() has detected an error condition.
+ *
+ * - Knuth also had a font_glue() optimization. I've removed that
+ * because it was a bit of dirty programming and it also was
+ * problematic if 0 != null.
+ */
+
+#include "ptexlib.h"
+#include "luatex-api.h"
+
+#define proper_char_index(c) (c<=font_ec(f) && c>=font_bc(f))
+#define dxfree(a,b) { xfree(a); a = b ; }
+#define do_realloc(a,b,d) a = xrealloc(a,(b)*sizeof(d))
+
+texfont **font_tables = NULL;
+
+static integer font_arr_max = 0;
+static integer font_id_maxval = 0;
+
+static void grow_font_table (integer id) {
+ int j;
+ if (id>=font_arr_max) {
+ font_bytes += (font_arr_max-id+8)*sizeof(texfont *);
+ font_tables = xrealloc(font_tables,(id+8)*sizeof(texfont *));
+ j = 8;
+ while (j--) {
+ font_tables[id+j] = NULL;
+ }
+ font_arr_max = id+8;
+ }
+}
+
+integer
+new_font_id (void) {
+ int i;
+ for (i=0;i<font_arr_max;i++) {
+ if (font_tables[i]==NULL) {
+ break;
+ }
+ }
+ if (i>=font_arr_max)
+ grow_font_table (i);
+ if (i>font_id_maxval)
+ font_id_maxval = i;
+ return i;
+}
+
+integer
+max_font_id (void) {
+ return font_id_maxval;
+}
+
+void
+set_max_font_id (integer i) {
+ font_id_maxval = i;
+}
+
+integer
+new_font (void) {
+ int k;
+ int id;
+ charinfo *ci;
+ id = new_font_id();
+ font_bytes += sizeof(texfont);
+ /* most stuff is zero */
+ font_tables[id] = xcalloc(1,sizeof(texfont));
+ font_tables[id]->_font_name = NULL;
+ font_tables[id]->_font_area = NULL;
+ font_tables[id]->_font_filename = NULL;
+ font_tables[id]->_font_fullname = NULL;
+ font_tables[id]->_font_encodingname = NULL;
+ font_tables[id]->_font_cidregistry = NULL;
+ font_tables[id]->_font_cidordering = NULL;
+ font_tables[id]->_left_boundary = NULL;
+ font_tables[id]->_right_boundary = NULL;
+ font_tables[id]->_param_base = NULL;
+
+ set_font_bc(id, 1); /* ec = 0 */
+ set_hyphen_char(id,'-');
+ set_skew_char(id,-1);
+
+ /* allocate eight values including 0 */
+ set_font_params(id,7);
+ for (k=0;k<=7;k++) {
+ set_font_param(id,k,0);
+ }
+ /* character info zero is reserved for notdef */
+ font_tables[id]->characters = new_sa_tree(1, 0); /* stack size 1, default item value 0 */
+
+ ci = xcalloc(1,sizeof(charinfo));
+ set_charinfo_name(ci,xstrdup(".notdef"));
+ font_tables[id]->charinfo = ci;
+ font_tables[id]->charinfo_cache = NULL;
+
+ return id;
+}
+
+#define Charinfo_count(a) font_tables[a]->charinfo_count
+#define Charinfo_size(a) font_tables[a]->charinfo_size
+#define Characters(a) font_tables[a]->characters
+
+charinfo *
+get_charinfo (internal_font_number f, integer c) {
+ sa_tree_item glyph;
+ charinfo *ci;
+ if (proper_char_index(c)) {
+ glyph = get_sa_item(Characters(f), c);
+ if (!glyph) {
+ /* this could be optimized using controlled growth */
+ font_bytes += sizeof(charinfo);
+ glyph = ++font_tables[f]->charinfo_count;
+ do_realloc(font_tables[f]->charinfo, (glyph+1), charinfo);
+ memset (&(font_tables[f]->charinfo[glyph]),0,sizeof(charinfo));
+ font_tables[f]->charinfo[glyph].ef = 1000; /* init */
+ font_tables[f]->charinfo_size = glyph;
+ set_sa_item(font_tables[f]->characters, c, glyph, 1); /* 1= global */
+ }
+ return &(font_tables[f]->charinfo[glyph]);
+ } else if (c == left_boundarychar) {
+ if (left_boundary(f)==NULL) {
+ ci = xcalloc(1,sizeof(charinfo));
+ font_bytes += sizeof(charinfo);
+ set_left_boundary(f,ci);
+ }
+ return left_boundary(f);
+ } else if (c == right_boundarychar) {
+ if (right_boundary(f)==NULL) {
+ ci = xcalloc(1,sizeof(charinfo));
+ font_bytes += sizeof(charinfo);
+ set_right_boundary(f,ci);
+ }
+ return right_boundary(f);
+ }
+ return &(font_tables[f]->charinfo[0]);
+}
+
+void
+set_charinfo (internal_font_number f, integer c, charinfo *ci) {
+ sa_tree_item glyph;
+ if (proper_char_index(c)) {
+ glyph = get_sa_item(Characters(f), c);
+ if (glyph) {
+ font_tables[f]->charinfo[glyph] = *ci;
+ } else {
+ pdftex_fail("font: %s","character insertion failed");
+ }
+ } else if (c == left_boundarychar) {
+ set_left_boundary(f,ci);
+ } else if (c == right_boundarychar) {
+ set_right_boundary(f,ci);
+ }
+}
+
+
+
+charinfo *
+copy_charinfo (charinfo *ci) {
+ int x;
+ kerninfo *kern;
+ liginfo *lig;
+ real_eight_bits *packet;
+ charinfo *co = NULL;
+ if (ci==NULL)
+ return NULL;
+ co = xmalloc(sizeof(charinfo));
+ memcpy(co,ci,sizeof(charinfo));
+ set_charinfo_used(co,false);
+ co->name = NULL;
+ co->tounicode = NULL;
+ co->packets = NULL;
+ co->ligatures = NULL;
+ co->kerns = NULL;
+ co->extensible = NULL;
+ if (ci->name!=NULL) {
+ co->name = xstrdup(ci->name);
+ }
+ if (ci->tounicode!=NULL) {
+ co->tounicode = xstrdup(ci->tounicode);
+ }
+ /* kerns */
+ if ((kern = get_charinfo_kerns(ci)) != NULL) {
+ x = 0;
+ while (!kern_end(kern[x])) { x++; } x++;
+ co->kerns = xmalloc (x*sizeof(kerninfo));
+ memcpy(co->kerns,ci->kerns,(x*sizeof(kerninfo)));
+ }
+ /* ligs */
+ if ((lig = get_charinfo_ligatures(ci)) != NULL) {
+ x = 0;
+ while (!lig_end(lig[x])) { x++; } x++;
+ co->ligatures = xmalloc (x*sizeof(liginfo));
+ memcpy(co->ligatures,ci->ligatures,(x*sizeof(liginfo)));
+ }
+ /* packets */
+ if ((packet = get_charinfo_packets(ci)) != NULL) {
+ x = vf_packet_bytes(ci);
+ co->packets = xmalloc (x);
+ memcpy(co->packets,ci->packets,x);
+ }
+ if (get_charinfo_tag(ci)==ext_tag) {
+ int top, bot, rep, mid;
+ top = get_charinfo_extensible(ci,EXT_TOP);
+ bot = get_charinfo_extensible(ci,EXT_BOT);
+ mid = get_charinfo_extensible(ci,EXT_MID);
+ rep = get_charinfo_extensible(ci,EXT_REP);
+ set_charinfo_extensible(co,top,bot,mid,rep);
+ }
+ return co;
+}
+
+#if 0
+int
+find_charinfo_id (internal_font_number f, integer c) {
+ register int g=0;
+ if (font_tables[f]->charinfo_cache==NULL) {
+ int i = (font_ec(f)+1)*sizeof(int);
+ font_tables[f]->charinfo_cache = xmalloc(i);
+ memset(font_tables[f]->charinfo_cache,0,i);
+ } else {
+ g = font_tables[f]->charinfo_cache[c];
+ }
+ if (g==0) {
+ g = get_sa_item(font_tables[f]->characters, c);
+ font_tables[f]->charinfo_cache[c] = g;
+ }
+ return g;
+}
+#else
+#define find_charinfo_id(f,c) get_sa_item(font_tables[f]->characters,c)
+#endif
+
+
+charinfo *
+char_info (internal_font_number f, integer c) {
+ if (f>font_id_maxval)
+ return 0;
+ if (proper_char_index(c)) {
+ register int glyph = find_charinfo_id(f,c);
+ return &(font_tables[f]->charinfo[glyph]);
+ } else if (c == left_boundarychar && left_boundary(f)!=NULL) {
+ return left_boundary(f);
+ } else if (c == right_boundarychar && right_boundary(f)!=NULL) {
+ return right_boundary(f);
+ }
+ return &(font_tables[f]->charinfo[0]);
+}
+
+charinfo_short
+char_info_short (internal_font_number f, integer c) {
+ charinfo_short s;
+ charinfo *i;
+ i = char_info(f,c);
+ s.ci_wd = i->width;
+ s.ci_dp = i->depth;
+ s.ci_ht = i->height;
+ return s;
+}
+
+integer
+char_exists (internal_font_number f, integer c) {
+ if (f>font_id_maxval)
+ return 0;
+ if (proper_char_index(c)) {
+ return find_charinfo_id(f,c);
+ } else if ((c == left_boundarychar) && has_left_boundary(f)) {
+ return 1;
+ } else if ((c == right_boundarychar) && has_right_boundary(f)) {
+ return 1;
+ }
+ return 0;
+}
+
+int
+lua_char_exists_callback (internal_font_number f, integer c) {
+ integer callback_id ;
+ lua_State *L = Luas[0];
+ int ret=0;
+ callback_id = callback_defined(char_exists_callback);
+ if (callback_id!=0) {
+ lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id);
+ lua_rawgeti(L,-1, callback_id);
+ if (!lua_isfunction(L,-1)) {
+ lua_pop(L,2);
+ return 0;
+ }
+ lua_pushnumber(L,f);
+ lua_pushnumber(L,c);
+ if (lua_pcall(L,2,1,0) != 0) { /* two args, 1 result */
+ fprintf(stdout,"error: %s\n",lua_tostring(L,-1));
+ lua_pop(L,2);
+ error();
+ } else {
+ ret = lua_toboolean(L,-1);
+ }
+ }
+ return ret;
+}
+
+
+void set_charinfo_width (charinfo *ci, scaled val) { ci->width = val; }
+void set_charinfo_height (charinfo *ci, scaled val) { ci->height = val; }
+void set_charinfo_depth (charinfo *ci, scaled val) { ci->depth = val; }
+void set_charinfo_italic (charinfo *ci, scaled val) { ci->italic = val; }
+void set_charinfo_tag (charinfo *ci, scaled val) { ci->tag = val; }
+void set_charinfo_remainder (charinfo *ci, scaled val) { ci->remainder = val; }
+void set_charinfo_used (charinfo *ci, scaled val) { ci->used = val; }
+void set_charinfo_index (charinfo *ci, scaled val) { ci->index = val; }
+void set_charinfo_name (charinfo *ci, char *val) { dxfree(ci->name,val); }
+void set_charinfo_tounicode (charinfo *ci, char *val) { dxfree(ci->tounicode,val); }
+void set_charinfo_ligatures (charinfo *ci, liginfo *val) { dxfree(ci->ligatures,val); }
+void set_charinfo_kerns (charinfo *ci, kerninfo *val) { dxfree(ci->kerns,val); }
+void set_charinfo_packets (charinfo *ci, real_eight_bits *val){ dxfree(ci->packets,val); }
+void set_charinfo_ef (charinfo *ci, scaled val) { ci->ef = val; }
+void set_charinfo_lp (charinfo *ci, scaled val) { ci->lp = val; }
+void set_charinfo_rp (charinfo *ci, scaled val) { ci->rp = val; }
+
+
+
+void set_charinfo_extensible (charinfo *ci, int top, int bot, int mid, int rep) {
+ if (top == 0 && bot == 0 && mid == 0 && rep == 0) {
+ if (ci->extensible != NULL) {
+ free(ci->extensible);
+ ci->extensible = NULL;
+ }
+ } else {
+ if (ci->extensible == NULL) {
+ ci->extensible = xmalloc(4*sizeof(integer));
+ }
+ ci->extensible[EXT_TOP] = top;
+ ci->extensible[EXT_BOT] = bot;
+ ci->extensible[EXT_MID] = mid;
+ ci->extensible[EXT_REP] = rep;
+ }
+}
+
+scaled get_charinfo_width (charinfo *ci) { return ci->width; }
+scaled get_charinfo_height (charinfo *ci) { return ci->height; }
+scaled get_charinfo_depth (charinfo *ci) { return ci->depth; }
+scaled get_charinfo_italic (charinfo *ci) { return ci->italic; }
+char get_charinfo_tag (charinfo *ci) { return ci->tag; }
+integer get_charinfo_remainder (charinfo *ci) { return ci->remainder; }
+char get_charinfo_used (charinfo *ci) { return ci->used; }
+integer get_charinfo_index (charinfo *ci) { return ci->index; }
+char *get_charinfo_name (charinfo *ci) { return ci->name; }
+char *get_charinfo_tounicode (charinfo *ci) { return ci->tounicode; }
+liginfo *get_charinfo_ligatures (charinfo *ci) { return ci->ligatures; }
+kerninfo *get_charinfo_kerns (charinfo *ci) { return ci->kerns; }
+real_eight_bits *get_charinfo_packets (charinfo *ci) { return ci->packets; }
+integer get_charinfo_ef (charinfo *ci) { return ci->ef; }
+integer get_charinfo_rp (charinfo *ci) { return ci->rp; }
+integer get_charinfo_lp (charinfo *ci) { return ci->lp; }
+
+integer get_charinfo_extensible (charinfo *ci, int whch) {
+ int w = 0;
+ if (ci->extensible != NULL)
+ w = ci->extensible[whch];
+ return w;
+}
+
+integer ext_top (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ integer w = get_charinfo_extensible(ci,EXT_TOP);
+ /* fprintf(stdout,"top of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+integer ext_bot (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ integer w = get_charinfo_extensible(ci,EXT_BOT);
+ /*fprintf(stdout,"bot of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+integer ext_mid (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ integer w = get_charinfo_extensible(ci,EXT_MID);
+ /*fprintf(stdout,"mid of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+integer ext_rep (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ integer w = get_charinfo_extensible(ci,EXT_REP);
+ /*fprintf(stdout,"rep of char 0x%4x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+scaled char_width (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ scaled w = get_charinfo_width(ci);
+ /*fprintf(stdout,"width of char 0x%x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+scaled char_depth (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ scaled w = get_charinfo_depth(ci);
+ /*fprintf(stdout,"depth of char 0x%x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+scaled char_height (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ scaled w = get_charinfo_height(ci);
+ /*fprintf(stdout,"height of char 0x%x in font %s: %i\n",c,font_name(f),w);*/
+ return w;
+}
+
+scaled char_italic (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_italic(ci);
+}
+
+integer char_remainder (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_remainder(ci);
+}
+
+char char_tag (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_tag(ci);
+}
+
+char char_used (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_used(ci);
+}
+
+char *char_name (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_name(ci);
+}
+
+integer char_index (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_index(ci);
+}
+
+liginfo * char_ligatures (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_ligatures(ci);
+}
+
+kerninfo * char_kerns (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_kerns(ci);
+}
+
+real_eight_bits * char_packets (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_packets(ci);
+}
+
+
+void
+set_font_params(internal_font_number f, int b) {
+ int i;
+ i = font_params(f);
+ if (i!=b) {
+ font_bytes += (b-font_params(f))*sizeof(scaled);
+ do_realloc(param_base(f), (b+1), integer);
+ font_params(f) = b;
+ if (b>i) {
+ while (i<b) {
+ i++;
+ set_font_param(f,i,0);
+ }
+ }
+ }
+}
+
+
+integer
+copy_font (integer f) {
+ int i;
+ charinfo *ci , *co;
+ integer k = new_font();
+ memcpy(font_tables[k],font_tables[f],sizeof(texfont));
+
+ set_font_cache_id(k,0);
+ set_font_used(k,0);
+ set_font_touched(k,0);
+
+ font_tables[k]->_font_name = NULL;
+ font_tables[k]->_font_filename = NULL;
+ font_tables[k]->_font_fullname = NULL;
+ font_tables[k]->_font_encodingname = NULL;
+ font_tables[k]->_font_area = NULL;
+ font_tables[k]->_font_cidregistry = NULL;
+ font_tables[k]->_font_cidordering = NULL;
+ font_tables[k]->_left_boundary = NULL;
+ font_tables[k]->_right_boundary = NULL;
+
+ set_font_name(k,xstrdup(font_name(f)));
+ if (font_filename(f)!= NULL)
+ set_font_filename(k,xstrdup(font_filename(f)));
+ if (font_fullname(f)!= NULL)
+ set_font_fullname(k,xstrdup(font_fullname(f)));
+ if (font_encodingname(f)!= NULL)
+ set_font_encodingname(k,xstrdup(font_encodingname(f)));
+ if (font_area(f)!= NULL)
+ set_font_area(k,xstrdup(font_area(f)));
+ if (font_cidregistry(f)!= NULL)
+ set_font_cidregistry(k,xstrdup(font_cidregistry(f)));
+ if (font_cidordering(f)!= NULL)
+ set_font_cidordering(k,xstrdup(font_cidordering(f)));
+
+ i = sizeof(*param_base(f))*font_params(f);
+ font_bytes += i;
+ param_base(k) = xmalloc (i);
+ memcpy(param_base(k),param_base(f), i);
+
+ i = sizeof(charinfo)*(Charinfo_size(f)+1);
+ font_bytes += i;
+ font_tables[k]->charinfo = xmalloc(i);
+ memset(font_tables[k]->charinfo,0,i);
+ for(i=0;i<=Charinfo_size(k);i++) {
+ ci = copy_charinfo(&font_tables[f]->charinfo[i]);
+ font_tables[k]->charinfo[i] = *ci;
+ }
+
+ if (left_boundary(f)!= NULL ) {
+ ci = copy_charinfo(left_boundary(f));
+ set_charinfo(k,left_boundarychar,ci);
+ }
+
+ if (right_boundary(f)!= NULL ) {
+ ci = copy_charinfo(right_boundary(f));
+ set_charinfo(k,right_boundarychar,ci);
+ }
+ return k;
+}
+
+void delete_font (integer f) {
+ int i;
+ charinfo *co;
+ assert(f>0);
+ if (font_tables[f]!=NULL) {
+ set_font_name(f,NULL);
+ set_font_filename(f,NULL);
+ set_font_fullname(f,NULL);
+ set_font_encodingname(f,NULL);
+ set_font_area(f,NULL);
+ set_font_cidregistry(f,NULL);
+ set_font_cidordering(f,NULL);
+ set_left_boundary(f,NULL);
+ set_right_boundary(f,NULL);
+
+ for(i=font_bc(f); i<=font_ec(f); i++) {
+ if (char_exists(f,i)) {
+ co = char_info(f,i);
+ set_charinfo_name(co,NULL);
+ set_charinfo_tounicode(co,NULL);
+ set_charinfo_packets(co,NULL);
+ set_charinfo_ligatures(co,NULL);
+ set_charinfo_kerns(co,NULL);
+ set_charinfo_extensible(co,0,0,0,0);
+ }
+ }
+ /* free .notdef */
+ set_charinfo_name(font_tables[f]->charinfo+0,NULL);
+ free(font_tables[f]->charinfo);
+ destroy_sa_tree(font_tables[f]->characters);
+
+ free(param_base(f));
+ free(font_tables[f]);
+ font_tables[f] = NULL;
+
+ if (font_id_maxval==f) {
+ font_id_maxval--;
+ }
+ }
+}
+
+void
+create_null_font (void) {
+ int i = new_font();
+ assert(i==0);
+ set_font_name(i,xstrdup("nullfont"));
+ set_font_area(i,xstrdup(""));
+ set_font_touched(i,1);
+}
+
+boolean
+is_valid_font (integer id) {
+ int ret=0;
+ if (id>=0 && id<=font_id_maxval && font_tables[id]!=NULL)
+ ret=1;
+ return ret;
+}
+
+/* return 1 == identical */
+boolean
+cmp_font_name (integer id, strnumber t) {
+ char *tid , *tt;
+ if (!is_valid_font(id))
+ return 0;
+ tt = makecstring(t);
+ tid = font_name(id);
+ if (tt == NULL && tid == NULL)
+ return 1;
+ if (tt == NULL || tid == NULL || strcmp(tid,tt)!=0)
+ return 0;
+ return 1;
+}
+
+boolean
+cmp_font_area (integer id, strnumber t) {
+ char *tt = NULL;
+ char *tid = font_area(id);
+ if (t == 0) {
+ if (tid == NULL || strlen(tid)==0)
+ return 1;
+ else
+ return 0;
+ }
+ tt = makecstring(t);
+ if ((tt == NULL || strlen(tt)==0) && (tid == NULL || strlen(tid)==0))
+ return 1;
+ if (tt == NULL || strcmp(tid,tt)!=0)
+ return 0;
+ return 1;
+}
+
+
+static boolean
+same_font_name (integer id, integer t) {
+ int ret = 0;
+ if (font_name(t) == NULL ||
+ font_name(id) == NULL ||
+ strcmp(font_name(t),font_name(id))!=0) {
+ ;
+ } else {
+ ret =1 ;
+ }
+ return ret;
+}
+
+boolean
+font_shareable (internal_font_number f, internal_font_number k) {
+ int ret = 0;
+ if (font_cidregistry(f) == NULL) {
+ if ( hasfmentry ( k )
+ && ( font_map ( k ) == font_map ( f ) )
+ && ( same_font_name ( k , f )
+ ||
+ ( pdf_font_auto_expand (f)
+ && ( pdf_font_blink (f) != 0 ) /* 0 = nullfont */
+ && same_font_name ( k , pdf_font_blink (f) ) ) ) ) {
+ ret = 1;
+ }
+ } else {
+ if ((font_filename(k) != NULL && font_filename(f) != NULL &&
+ strcmp(font_filename(k),font_filename(f)) == 0)
+ ||
+ ( pdf_font_auto_expand (f)
+ && ( pdf_font_blink (f) != 0 ) /* 0 = nullfont */
+ && same_font_name ( k , pdf_font_blink (f) ) ) ) {
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
+integer
+test_no_ligatures (internal_font_number f) {
+ integer c;
+ for (c=font_bc(f);c<=font_ec(f);c++) {
+ if (has_lig(f,c)) /* char_exists(f,c) */
+ return 0;
+ }
+ return 1;
+}
+
+integer
+get_tag_code (internal_font_number f, integer c) {
+ small_number i;
+ if (char_exists(f,c)) {
+ i = char_tag(f,c);
+ if (i==lig_tag) return 1;
+ else if (i==list_tag) return 2;
+ else if (i==ext_tag) return 4;
+ else return 0;
+ }
+ return -1;
+}
+
+integer
+get_lp_code (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_lp(ci);
+}
+
+integer
+get_rp_code (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_rp(ci);
+}
+
+integer
+get_ef_code (internal_font_number f, integer c) {
+ charinfo *ci = char_info(f,c);
+ return get_charinfo_ef(ci);
+}
+
+void
+set_tag_code (internal_font_number f, integer c, integer i) {
+ integer fixedi;
+ charinfo * co;
+ if (char_exists(f,c)) {
+ /* abs(fix_int(i-7,0)) */
+ fixedi = - (i<-7 ? -7 : (i>0 ? 0 : i )) ;
+ co = char_info(f,c);
+ if (fixedi >= 4) {
+ if (char_tag(f,c) == ext_tag)
+ set_charinfo_tag(co,(char_tag(f,c)- ext_tag));
+ fixedi = fixedi - 4;
+ }
+ if (fixedi >= 2) {
+ if (char_tag(f,c) == list_tag)
+ set_charinfo_tag(co,(char_tag(f,c)- list_tag));
+ fixedi = fixedi - 2;
+ };
+ if (fixedi >= 1) {
+ if (has_lig(f,c))
+ set_charinfo_ligatures(co,NULL);
+ if (has_kern(f,c))
+ set_charinfo_kerns(co,NULL);
+ }
+ }
+}
+
+
+void
+set_lp_code(internal_font_number f, integer c, integer i) {
+ charinfo * co;
+ if (char_exists(f,c)) {
+ co = char_info(f,c);
+ set_charinfo_lp(co,i);
+ }
+}
+
+void
+set_rp_code(internal_font_number f, integer c, integer i) {
+ charinfo * co;
+ if (char_exists(f,c)) {
+ co = char_info(f,c);
+ set_charinfo_rp(co,i);
+ }
+}
+
+void
+set_ef_code(internal_font_number f, integer c, integer i) {
+ charinfo * co;
+ if (char_exists(f,c)) {
+ co = char_info(f,c);
+ set_charinfo_ef(co,i);
+ }
+}
+
+void
+set_no_ligatures (internal_font_number f) {
+ integer c;
+ charinfo * co;
+
+ if (font_tables[f]->ligatures_disabled)
+ return;
+
+ co = char_info(f,left_boundarychar);
+ set_charinfo_ligatures(co,NULL);
+ co = char_info(f,right_boundarychar); /* this is weird */
+ set_charinfo_ligatures(co,NULL);
+ for (c=0;c<font_tables[f]->charinfo_count;c++) {
+ co = font_tables[f]->charinfo+c;
+ set_charinfo_ligatures(co,NULL);
+ }
+ font_tables[f]->ligatures_disabled =1;
+}
+
+liginfo
+get_ligature (internal_font_number f, integer lc, integer rc) {
+ liginfo t, u;
+ charinfo * co;
+ t.lig = 0;
+ t.type = 0;
+ t.adj = 0;
+ if (lc == non_boundarychar || rc == non_boundarychar || (!has_lig(f,lc)) )
+ return t;
+ k = 0;
+ co = char_info(f,lc);
+ while (1) {
+ u = charinfo_ligature(co,k);
+ if (lig_end(u))
+ break;
+ if (lig_char(u) == rc) {
+ if (lig_disabled(u)) {
+ return t;
+ } else {
+ return u;
+ }
+ }
+ k++;
+ }
+ return t;
+}
+
+
+scaled
+get_kern(internal_font_number f, integer lc, integer rc)
+{
+ integer k;
+ kerninfo u;
+ charinfo * co;
+ if (lc == non_boundarychar || rc == non_boundarychar || (!has_kern(f,lc)) )
+ return 0;
+ k = 0;
+ co = char_info(f,lc);
+ while (1) {
+ u = charinfo_kern(co,k);
+ if (kern_end(u))
+ break;
+ if (kern_char(u) == rc) {
+ if (kern_disabled(u))
+ return 0;
+ else
+ return kern_kern(u);
+ }
+ k++;
+ }
+ return 0;
+}
+
+
+/* dumping and undumping fonts */
+
+#define dump_string(a) \
+ if (a!=NULL) { \
+ x = strlen(a)+1; \
+ dump_int(x); dump_things(*a, x); \
+ } else { \
+ x = 0; dump_int(x); \
+ }
+
+void
+dump_charinfo (int f , int c) {
+ charinfo *co;
+ int x;
+ liginfo *lig;
+ kerninfo *kern;
+
+ dump_int(c);
+ co = char_info(f,c);
+ set_charinfo_used(co,0);
+ dump_int(get_charinfo_width(co));
+ dump_int(get_charinfo_height(co));
+ dump_int(get_charinfo_depth(co));
+ dump_int(get_charinfo_italic(co));
+ dump_int(get_charinfo_tag(co));
+ dump_int(get_charinfo_ef(co));
+ dump_int(get_charinfo_rp(co));
+ dump_int(get_charinfo_lp(co));
+ dump_int(get_charinfo_remainder(co));
+ dump_int(get_charinfo_used(co));
+ dump_int(get_charinfo_index(co));
+ dump_string(get_charinfo_name(co));
+ dump_string(get_charinfo_tounicode(co));
+
+ /* ligatures */
+ x = 0;
+ if ((lig = get_charinfo_ligatures(co)) != NULL) {
+ while (!lig_end(lig[x])) { x++; }
+ x++;
+ dump_int(x); dump_things(*lig, x);
+ } else {
+ dump_int(x);
+ }
+ /* kerns */
+ x = 0;
+ if ((kern = get_charinfo_kerns(co)) != NULL) {
+ while (!kern_end(kern[x])) { x++; }
+ x++;
+ dump_int(x); dump_things(*kern, x);
+ } else {
+ dump_int(x);
+ }
+ /* packets */
+ x= vf_packet_bytes(co);
+ dump_int(x);
+ if (x>0) {
+ dump_things(*get_charinfo_packets(co), x);
+ }
+
+ if (get_charinfo_tag(co)==ext_tag) {
+ x = get_charinfo_extensible(co,EXT_TOP); dump_int(x);
+ x = get_charinfo_extensible(co,EXT_BOT); dump_int(x);
+ x = get_charinfo_extensible(co,EXT_MID); dump_int(x);
+ x = get_charinfo_extensible(co,EXT_REP); dump_int(x);
+ }
+}
+
+void
+dump_font (int f) {
+ int i,x;
+
+ set_font_used(f,0);
+ font_tables[f]->charinfo_cache = NULL;
+ dump_things(*(font_tables[f]), 1);
+ dump_string(font_name(f));
+ dump_string(font_area(f));
+ dump_string(font_filename(f));
+ dump_string(font_fullname(f));
+ dump_string(font_encodingname(f));
+ dump_string(font_cidregistry(f));
+ dump_string(font_cidordering(f));
+
+ dump_things(*param_base(f),(font_params(f)+1));
+
+ if (has_left_boundary(f)) {
+ dump_int(1); dump_charinfo(f,left_boundarychar);
+ } else {
+ dump_int(0);
+ }
+ if (has_right_boundary(f)) {
+ dump_int(1); dump_charinfo(f,right_boundarychar);
+ } else {
+ dump_int(0);
+ }
+
+ for(i=font_bc(f); i<=font_ec(f); i++) {
+ if (char_exists(f,i)) {
+ dump_charinfo(f,i);
+ }
+ }
+}
+
+int
+undump_charinfo (int f) {
+ charinfo *co;
+ int x,i;
+ char *s = NULL;
+ liginfo *lig = NULL;
+ kerninfo *kern = NULL;
+ real_eight_bits *packet = NULL;
+ int top = 0, bot = 0, mid = 0, rep = 0;
+
+ undump_int(i);
+ co = get_charinfo(f,i);
+ undump_int(x); set_charinfo_width(co,x);
+ undump_int(x); set_charinfo_height(co,x);
+ undump_int(x); set_charinfo_depth(co,x);
+ undump_int(x); set_charinfo_italic(co,x);
+ undump_int(x); set_charinfo_tag(co,x);
+ undump_int(x); set_charinfo_ef(co,x);
+ undump_int(x); set_charinfo_rp(co,x);
+ undump_int(x); set_charinfo_lp(co,x);
+ undump_int(x); set_charinfo_remainder(co,x);
+ undump_int(x); set_charinfo_used(co,x);
+ undump_int(x); set_charinfo_index(co,x);
+
+ /* name */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x;
+ s = xmalloc(x);
+ undump_things(*s,x);
+ }
+ set_charinfo_name(co,s);
+
+ /* tounicode */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x;
+ s = xmalloc(x);
+ undump_things(*s,x);
+ }
+ set_charinfo_tounicode(co,s);
+
+ /* ligatures */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x*sizeof(liginfo);
+ lig = xmalloc(x*sizeof(liginfo));
+ undump_things(*lig,x);
+ }
+ set_charinfo_ligatures(co,lig);
+
+ /* kerns */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x*sizeof(kerninfo);
+ kern = xmalloc(x*sizeof(kerninfo));
+ undump_things(*kern,x);
+ }
+ set_charinfo_kerns(co,kern);
+
+ /* packets */
+ undump_int (x);
+ if (x>0) {
+ font_bytes += x;
+ packet = xmalloc(x);
+ undump_things(*packet,x);
+ }
+ set_charinfo_packets(co,packet);
+
+ if (get_charinfo_tag(co)==ext_tag) {
+ undump_int(top);
+ undump_int(bot);
+ undump_int(mid);
+ undump_int(rep);
+ set_charinfo_extensible(co,top,bot,mid,rep);
+ }
+ return i;
+}
+
+#define undump_font_string(a) undump_int (x); \
+ if (x>0) { \
+ font_bytes += x; \
+ s = xmalloc(x); undump_things(*s,x); \
+ a(f,s); }
+
+
+void
+undump_font(int f)
+{
+ int x, i;
+ texfont *tt;
+ charinfo *ci;
+ char *s;
+ grow_font_table (f);
+ font_tables[f] = NULL;
+ font_bytes += sizeof(texfont);
+ tt = xmalloc(sizeof(texfont));
+ undump_things(*tt,1);
+ font_tables[f] = tt;
+
+ undump_font_string(set_font_name);
+ undump_font_string(set_font_area);
+ undump_font_string(set_font_filename);
+ undump_font_string(set_font_fullname);
+ undump_font_string(set_font_encodingname);
+ undump_font_string(set_font_cidregistry);
+ undump_font_string(set_font_cidordering);
+
+ i = sizeof(*param_base(f))*(font_params(f)+1);
+ font_bytes += i;
+ param_base(f) = xmalloc (i);
+ undump_things(*param_base(f), (font_params(f)+1));
+
+ font_tables[f]->_left_boundary = NULL;
+ undump_int(x);
+ if (x) { i = undump_charinfo(f); } /* left boundary */
+
+ font_tables[f]->_right_boundary = NULL;
+ undump_int(x);
+ if (x) { i = undump_charinfo(f); } /* right boundary */
+
+
+ font_tables[f]->characters = new_sa_tree(1, 0); /* stack size 1, default item value 0 */
+ ci = xcalloc(1,sizeof(charinfo));
+ set_charinfo_name(ci,xstrdup(".notdef"));
+ font_tables[f]->charinfo = ci;
+
+ i = font_bc(f);
+ while(i<font_ec(f)) {
+ i = undump_charinfo(f);
+ }
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/texfont.h b/Build/source/texk/web2c/luatexdir/font/texfont.h
new file mode 100644
index 00000000000..21b79f1e876
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/texfont.h
@@ -0,0 +1,524 @@
+/*
+ Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+ This file is part of LuaTeX.
+
+ LuaTeX is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ LuaTeX is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with LuaTeX; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ $Id: texfont.h 1117 2008-03-21 15:26:12Z hhenkel $ */
+
+/* Here we have the interface to LuaTeX's font system, as seen from the
+ main pascal program. There is a companion list in luatex.defines to
+ keep web2c happy */
+
+/* this file is read at the end of ptexlib.h, which is called for at
+ the end of luatexcoerce.h, as well as from the C sources
+*/
+
+#ifndef TEXFONT_H
+#define TEXFONT_H 1
+
+#include "luatexdir/managed-sa.h"
+
+#define pointer halfword
+
+typedef struct liginfo {
+ integer adj;
+ integer lig;
+ char type;
+} liginfo;
+
+typedef struct kerninfo {
+ integer adj;
+ scaled sc;
+} kerninfo;
+
+typedef struct charinfo {
+ char *name; /* postscript character name */
+ liginfo *ligatures; /* ligature items */
+ kerninfo *kerns; /* kern items */
+ real_eight_bits *packets; /* virtual commands. */
+ integer *extensible; /* extensible recipe (if any) */
+ unsigned short index; /* CID index */
+ integer remainder; /* spare value for odd items, could be union-ed with extensible */
+ scaled width; /* width */
+ scaled height; /* height */
+ scaled depth; /* depth */
+ scaled italic; /* italic correction */
+ integer ef; /* font expansion factor */
+ integer lp; /* left protruding factor */
+ integer rp; /* right protruding factor */
+ char tag ; /* list / ext taginfo */
+ char used ; /* char is typeset ? */
+ char *tounicode; /* unicode equivalent */
+} charinfo;
+
+
+/* this is for speed reasons, it is called from the web source
+ when more than two of the traditional four char values are needed
+ at the same time. the structure |charinfo_short| is defined in
+ web */
+
+#ifndef luaTeX
+typedef struct charinfo_short {
+ scaled ci_wd; /* width */
+ scaled ci_ht; /* height */
+ scaled ci_dp; /* depth */
+} charinfo_short;
+#endif
+
+
+extern charinfo_short char_info_short (internal_font_number f, integer c);
+
+
+
+typedef struct texfont {
+ integer _font_size ;
+ integer _font_dsize ;
+ char * _font_name ;
+ char * _font_area ;
+ char * _font_filename ;
+ char * _font_fullname ;
+ char * _font_encodingname ;
+ char * _font_cidregistry ;
+ char * _font_cidordering ;
+ integer _font_cidversion ;
+ integer _font_cidsupplement ;
+
+ integer _font_ec ;
+ integer _font_checksum ; /* internal information */
+ char _font_used ; /* internal information */
+ char _font_touched ; /* internal information */
+ integer _font_cache_id ; /* internal information */
+ char _font_encodingbytes ; /* 1 or 2 bytes */
+ integer _font_slant ; /* a slant in ppt */
+ integer _font_extend ; /* an extension in ppt, or 0 */
+ char _font_tounicode ; /* 1 if info is present */
+ fm_entry_ptr _font_map;
+ integer _font_type;
+ integer _font_format;
+ integer _font_embedding;
+ integer _font_bc ;
+ integer _hyphen_char ;
+ integer _skew_char ;
+ integer _font_natural_dir;
+
+ charinfo *_left_boundary;
+ charinfo *_right_boundary;
+
+ integer _font_params;
+ scaled *_param_base;
+
+ sa_tree characters;
+ integer charinfo_count;
+ integer charinfo_size;
+ charinfo *charinfo;
+ int *charinfo_cache;
+ integer ligatures_disabled;
+
+ integer _pdf_font_num; /* maps to a PDF resource ID */
+ scaled _pdf_font_size; /* maps to a PDF font size */
+ internal_font_number _pdf_font_blink; /* link to base font for expanded fonts */
+ internal_font_number _pdf_font_elink; /* link to expanded fonts for base font */
+ integer _pdf_font_expand_ratio; /* expansion ratio of a particular font */
+ internal_font_number _pdf_font_shrink; /* font at limit of shrinking */
+ internal_font_number _pdf_font_stretch; /* font at limit of stretching */
+ integer _pdf_font_step; /* amount of one step of expansion */
+ boolean _pdf_font_auto_expand; /* this font is auto-expanded? */
+ str_number _pdf_font_attr; /* pointer to additional attributes */
+} texfont;
+
+typedef enum {
+ unknown_font_type=0, /* new font (has not been used yet) */
+ virtual_font_type, /* virtual font */
+ real_font_type, /* real font */
+} font_types;
+
+typedef enum {
+ unknown_format=0,
+ type1_format,
+ type3_format,
+ truetype_format,
+ opentype_format,
+} font_formats;
+
+typedef enum {
+ unknown_embedding=0,
+ no_embedding,
+ subset_embedding,
+ full_embedding,
+} font_embedding_option;
+
+extern char *font_type_strings[];
+extern char *font_format_strings[];
+extern char *font_embedding_strings[];
+
+
+#define font_checksum(a) font_tables[a]->_font_checksum
+#define set_font_checksum(a,b) font_checksum(a) = b
+
+#define font_check_0(a) ((font_tables[a]->_font_checksum&0xFF000000)>>24)
+#define font_check_1(a) ((font_tables[a]->_font_checksum&0x00FF0000)>>16)
+#define font_check_2(a) ((font_tables[a]->_font_checksum&0x0000FF00)>>8)
+#define font_check_3(a) (font_tables[a]->_font_checksum&0x000000FF)
+
+#define font_size(a) font_tables[a]->_font_size
+#define set_font_size(a,b) font_size(a) = b
+#define font_dsize(a) font_tables[a]->_font_dsize
+#define set_font_dsize(a,b) font_dsize(a) = b
+
+#define font_name(a) font_tables[a]->_font_name
+#define get_font_name(a) (unsigned char *)font_name(a)
+#define set_font_name(f,b) font_name(f) = b
+#define tex_font_name(a) maketexstring(font_name(a))
+
+boolean cmp_font_name (integer, strnumber);
+
+#define font_area(a) font_tables[a]->_font_area
+#define get_font_area(a) (unsigned char *)font_area(a)
+#define set_font_area(f,b) font_area(f) = b
+#define tex_font_area(a) maketexstring(font_area(a))
+
+boolean cmp_font_area (integer, strnumber);
+
+#define font_reassign(a,b) { if (a!=NULL) free(a); a = b; }
+
+#define font_filename(a) font_tables[a]->_font_filename
+#define set_font_filename(f,b) font_reassign(font_filename(f),b)
+
+#define font_fullname(a) font_tables[a]->_font_fullname
+#define set_font_fullname(f,b) font_reassign(font_fullname(f),b)
+
+#define font_encodingname(a) font_tables[a]->_font_encodingname
+#define set_font_encodingname(f,b) font_reassign(font_encodingname(f),b)
+
+boolean font_shareable(internal_font_number,internal_font_number);
+
+#define cmp_font_filename(a,b) (!(font_filename(a)!=NULL || font_filename(b)!=NULL || \
+ strcmp(font_filename(a),font_filename(b))))
+#define cmp_font_fullname(a,b) (!(font_fullname(a)!=NULL || font_fullname(b)!=NULL || \
+ strcmp(font_fullname(a),font_fullname(b))))
+#define cmp_font_encodingname(a,b) (!(font_encoding(a)!=NULL || font_encodingname(b)!=NULL || \
+ strcmp(font_encodingname(a),font_encodingname(b))))
+
+#define font_bc(a) font_tables[a]->_font_bc
+#define set_font_bc(f,b) font_bc(f) = b
+
+#define font_ec(a) font_tables[a]->_font_ec
+#define set_font_ec(f,b) font_ec(f) = b
+
+#define font_used(a) (font_tables[a]!=NULL && font_tables[a]->_font_used)
+#define set_font_used(a,b) font_tables[a]->_font_used = b
+
+#define font_touched(a) font_tables[a]->_font_touched
+#define set_font_touched(a,b) font_touched(a) = b
+
+#define font_type(a) font_tables[a]->_font_type
+#define set_font_type(a,b) { /* fprintf(stdout,"set font type of %s to %i: %s\n",font_name(a),b,__FILE__); */ \
+ font_type(a) = b; }
+
+#define font_format(a) font_tables[a]->_font_format
+#define font_format_name(a) font_format_strings[font_tables[a]->_font_format]
+#define set_font_format(a,b) font_format(a) = b
+
+#define font_embedding(a) font_tables[a]->_font_embedding
+#define set_font_embedding(a,b) font_embedding(a) = b
+
+#define font_cidversion(a) font_tables[a]->_font_cidversion
+#define set_font_cidversion(a,b) font_cidversion(a) = b
+
+#define font_cidsupplement(a) font_tables[a]->_font_cidsupplement
+#define set_font_cidsupplement(a,b) font_cidsupplement(a) = b
+
+#define font_cidordering(a) font_tables[a]->_font_cidordering
+#define set_font_cidordering(f,b) font_reassign(font_cidordering(f),b)
+
+#define font_cidregistry(a) font_tables[a]->_font_cidregistry
+#define set_font_cidregistry(f,b) font_reassign(font_cidregistry(f),b)
+
+#define font_map(a) font_tables[a]->_font_map
+#define set_font_map(a,b) font_map(a) = b
+
+#define font_cache_id(a) font_tables[a]->_font_cache_id
+#define set_font_cache_id(a,b) font_cache_id(a) = b
+
+#define font_encodingbytes(a) font_tables[a]->_font_encodingbytes
+#define set_font_encodingbytes(a,b) font_encodingbytes(a) = b
+
+#define font_slant(a) font_tables[a]->_font_slant
+#define set_font_slant(a,b) font_slant(a) = b
+
+#define font_extend(a) font_tables[a]->_font_extend
+#define set_font_extend(a,b) font_extend(a) = b
+
+#define font_tounicode(a) font_tables[a]->_font_tounicode
+#define set_font_tounicode(a,b) font_tounicode(a) = b
+
+#define hyphen_char(a) font_tables[a]->_hyphen_char
+#define set_hyphen_char(a,b) hyphen_char(a) = b
+
+#define skew_char(a) font_tables[a]->_skew_char
+#define set_skew_char(a,b) skew_char(a) = b
+
+#define font_natural_dir(a) font_tables[a]->_font_natural_dir
+#define set_font_natural_dir(a,b) font_natural_dir(a) = b
+
+#define pdf_font_size(a) font_tables[a]->_pdf_font_size
+#define set_pdf_font_size(a,b) pdf_font_size(a) = b
+
+#define pdf_font_num(a) font_tables[a]->_pdf_font_num
+#define set_pdf_font_num(a,b) pdf_font_num(a) = b
+
+#define pdf_font_blink(a) font_tables[a]->_pdf_font_blink
+#define set_pdf_font_blink(a,b) pdf_font_blink(a) = b
+
+#define pdf_font_elink(a) font_tables[a]->_pdf_font_elink
+#define set_pdf_font_elink(a,b) pdf_font_elink(a) = b
+
+#define pdf_font_expand_ratio(a) font_tables[a]->_pdf_font_expand_ratio
+#define set_pdf_font_expand_ratio(a,b) pdf_font_expand_ratio(a) = b
+
+#define pdf_font_shrink(a) font_tables[a]->_pdf_font_shrink
+#define set_pdf_font_shrink(a,b) pdf_font_shrink(a) = b
+
+#define pdf_font_stretch(a) font_tables[a]->_pdf_font_stretch
+#define set_pdf_font_stretch(a,b) pdf_font_stretch(a) = b
+
+#define pdf_font_step(a) font_tables[a]->_pdf_font_step
+#define set_pdf_font_step(a,b) pdf_font_step(a) = b
+
+#define pdf_font_auto_expand(a) font_tables[a]->_pdf_font_auto_expand
+#define set_pdf_font_auto_expand(a,b) pdf_font_auto_expand(a) = b
+
+#define pdf_font_attr(a) font_tables[a]->_pdf_font_attr
+#define set_pdf_font_attr(a,b) pdf_font_attr(a) = b
+
+
+#define left_boundarychar -1
+#define right_boundarychar -2
+#define non_boundarychar -3
+
+#define left_boundary(a) font_tables[a]->_left_boundary
+#define has_left_boundary(a) (left_boundary(a)!=NULL)
+#define set_left_boundary(a,b) font_reassign(left_boundary(a),b)
+
+#define right_boundary(a) font_tables[a]->_right_boundary
+#define has_right_boundary(a) (right_boundary(a)!=NULL)
+#define set_right_boundary(a,b) font_reassign(right_boundary(a),b)
+
+#define font_bchar(a) (right_boundary(a)!=NULL ? right_boundarychar : non_boundarychar)
+
+/* font parameters */
+
+#define font_params(a) font_tables[a]->_font_params
+#define param_base(a) font_tables[a]->_param_base
+#define font_param(a,b) font_tables[a]->_param_base[b]
+
+extern void set_font_params(internal_font_number f, int b);
+
+#define set_font_param(f,n,b) \
+ { if (font_params(f)<n) set_font_params(f,n); \
+ font_param(f,n) = b; }
+
+/* Font parameters are sometimes referred to as |slant(f)|, |space(f)|, etc.*/
+
+typedef enum {
+ slant_code = 1,
+ space_code = 2,
+ space_stretch_code = 3,
+ space_shrink_code = 4,
+ x_height_code = 5,
+ quad_code = 6,
+ extra_space_code = 7 } font_parameter_codes ;
+
+#define slant(f) font_param(f,slant_code)
+#define space(f) font_param(f,space_code)
+#define space_stretch(f) font_param(f,space_stretch_code)
+#define space_shrink(f) font_param(f,space_shrink_code)
+#define x_height(f) font_param(f,x_height_code)
+#define quad(f) font_param(f,quad_code)
+#define extra_space(f) font_param(f,extra_space_code)
+
+/* now for characters */
+
+extern charinfo *get_charinfo (internal_font_number f, integer c) ;
+extern integer char_exists (internal_font_number f, integer c);
+extern charinfo *char_info (internal_font_number f, integer c);
+
+
+extern void set_charinfo_width (charinfo *ci, scaled val);
+extern void set_charinfo_height (charinfo *ci, scaled val);
+extern void set_charinfo_depth (charinfo *ci, scaled val);
+extern void set_charinfo_italic (charinfo *ci, scaled val);
+extern void set_charinfo_tag (charinfo *ci, scaled val);
+extern void set_charinfo_remainder (charinfo *ci, scaled val);
+extern void set_charinfo_used (charinfo *ci, scaled val);
+extern void set_charinfo_index (charinfo *ci, scaled val);
+extern void set_charinfo_name (charinfo *ci, char *val) ;
+extern void set_charinfo_tounicode (charinfo *ci, char *val) ;
+extern void set_charinfo_ligatures (charinfo *ci, liginfo *val);
+extern void set_charinfo_kerns (charinfo *ci, kerninfo *val);
+extern void set_charinfo_packets (charinfo *ci, real_eight_bits *val);
+extern void set_charinfo_extensible (charinfo *ci, int a, int b, int c, int d);
+
+#define set_char_used(f,a,b) set_charinfo_used(get_charinfo(f,a),b)
+
+extern scaled get_charinfo_width (charinfo *ci);
+extern scaled get_charinfo_height (charinfo *ci);
+extern scaled get_charinfo_depth (charinfo *ci);
+extern scaled get_charinfo_italic (charinfo *ci);
+extern char get_charinfo_tag (charinfo *ci);
+extern integer get_charinfo_remainder (charinfo *ci);
+extern char get_charinfo_used (charinfo *ci);
+extern integer get_charinfo_index (charinfo *ci);
+extern char * get_charinfo_name (charinfo *ci) ;
+extern char * get_charinfo_tounicode (charinfo *ci) ;
+extern liginfo * get_charinfo_ligatures (charinfo *ci);
+extern kerninfo *get_charinfo_kerns (charinfo *ci);
+extern real_eight_bits *get_charinfo_packets (charinfo *ci);
+extern integer get_charinfo_extensible (charinfo *ci, int which);
+
+extern integer ext_top (internal_font_number f, integer c);
+extern integer ext_bot (internal_font_number f, integer c);
+extern integer ext_rep (internal_font_number f, integer c);
+extern integer ext_mid (internal_font_number f, integer c);
+
+#define set_ligature_item(f,b,c,d) { f.type = b; f.adj = c; f.lig = d; }
+
+#define set_kern_item(f,b,c) { f.adj = b; f.sc = c; }
+
+
+/* character information */
+
+#define non_char 65536 /* a code that can't match a real character */
+#define non_address 0 /* a spurious |bchar_label| */
+
+
+/* character kerns and ligatures */
+
+#define end_kern 0x7FFFFF /* otherchar value meaning "stop" */
+#define ignored_kern 0x800000 /* otherchar value meaning "disabled" */
+
+#define charinfo_kern(b,c) b->kerns[c]
+
+#define kern_char(b) (b).adj
+#define kern_kern(b) (b).sc
+#define kern_end(b) ((b).adj == end_kern)
+#define kern_disabled(b) ((b).adj > end_kern)
+
+/* character ligatures */
+
+#define end_ligature 0x7FFFFF /* otherchar value meaning "stop" */
+#define ignored_ligature 0x800000 /* otherchar value meaning "disabled" */
+
+#define charinfo_ligature(b,c) b->ligatures[c]
+
+#define is_valid_ligature(a) ((a).type!=0)
+#define lig_type(a) ((a).type>>1)
+#define lig_char(a) (a).adj
+#define lig_replacement(a) (a).lig
+#define lig_end(a) (lig_char(a) == end_ligature)
+#define lig_disabled(a) (lig_char(a) > end_ligature)
+
+#define no_tag 0 /* vanilla character */
+#define lig_tag 1 /* character has a ligature/kerning program */
+#define list_tag 2 /* character has a successor in a charlist */
+#define ext_tag 3 /* character is extensible */
+
+extern scaled char_height (internal_font_number f, integer c);
+extern scaled char_width (internal_font_number f, integer c);
+extern scaled char_depth (internal_font_number f, integer c);
+extern scaled char_italic (internal_font_number f, integer c);
+
+extern liginfo * char_ligatures (internal_font_number f, integer c);
+extern kerninfo * char_kerns (internal_font_number f, integer c);
+extern real_eight_bits * char_packets (internal_font_number f, integer c);
+
+#define has_lig(f,b) (char_exists(f,b) &&( char_ligatures(f,b) != NULL))
+#define has_kern(f,b) (char_exists(f,b) && (char_kerns(f,b) != NULL))
+#define has_packet(f,b) (char_exists(f,b) && (char_packets(f,b) != NULL))
+
+extern integer char_remainder (internal_font_number f, integer c);
+extern char char_tag (internal_font_number f, integer c);
+extern char char_used (internal_font_number f, integer c);
+extern char * char_name (internal_font_number f, integer c);
+extern integer char_index (internal_font_number f, integer c);
+
+scaled get_kern(internalfontnumber f, integer lc, integer rc);
+liginfo get_ligature(internalfontnumber f, integer lc, integer rc);
+
+#define EXT_TOP 0
+#define EXT_BOT 1
+#define EXT_MID 2
+#define EXT_REP 3
+
+extern texfont **font_tables;
+
+integer new_font (void) ;
+integer copy_font (integer id) ;
+integer scale_font (integer id, integer atsize) ;
+integer max_font_id (void);
+void set_max_font_id (integer id);
+integer new_font_id (void);
+void create_null_font (void);
+void delete_font(integer id);
+boolean is_valid_font (integer id);
+
+void dump_font (int font_number);
+void undump_font (int font_number);
+
+integer test_no_ligatures (internal_font_number f) ;
+void set_no_ligatures (internal_font_number f) ;
+
+extern integer get_tag_code (internal_font_number f, integer c);
+extern integer get_lp_code (internal_font_number f, integer c);
+extern integer get_rp_code (internal_font_number f, integer c);
+extern integer get_ef_code (internal_font_number f, integer c);
+
+extern void set_tag_code (internal_font_number f, integer c, integer i) ;
+extern void set_lp_code(internal_font_number f, integer c, integer i) ;
+extern void set_rp_code(internal_font_number f, integer c, integer i) ;
+extern void set_ef_code(internal_font_number f, integer c, integer i) ;
+
+int read_tfm_info(internal_font_number f, char *nom, char *aire, scaled s);
+
+
+/* from dofont.c */
+
+extern int read_font_info (pointer u, strnumber nom, strnumber aire, scaled s, integer ndir);
+extern int find_font_id (char *nom, char *aire, scaled s);
+
+/* for and from vfpacket.c */
+
+#define scan_special 3 /* look into special text */ /* this is a hack */
+
+typedef enum { packet_char_code,
+ packet_font_code,
+ packet_pop_code,
+ packet_push_code,
+ packet_special_code,
+ packet_right_code,
+ packet_down_code,
+ packet_rule_code,
+ packet_node_code,
+ packet_nop_code,
+ packet_end_code } packet_command_codes;
+
+extern scaled sqxfw (scaled sq, integer fw);
+
+extern void do_vf_packet (internal_font_number vf_f, integer c);
+extern int vf_packet_bytes (charinfo *co);
+
+#endif
diff --git a/Build/source/texk/web2c/luatexdir/font/tfmofm.c b/Build/source/texk/web2c/luatexdir/font/tfmofm.c
new file mode 100644
index 00000000000..db82f94deba
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tfmofm.c
@@ -0,0 +1,1005 @@
+/*
+Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with LuaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: tfmofm.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+#include "luatex-api.h"
+
+/* Here are some macros that help process ligatures and kerns */
+
+#define lig_kern_start(f,c) char_remainder(f,c)
+#define stop_flag 128 /* value indicating `\.{STOP}' in a lig/kern program */
+#define kern_flag 128 /* op code for a kern step */
+
+#define skip_byte(z) lig_kerns[z].b0
+#define next_char(z) lig_kerns[z].b1
+#define op_byte(z) lig_kerns[z].b2
+#define rem_byte(z) lig_kerns[z].b3
+#define lig_kern_restart(c) (256*op_byte(c)+rem_byte(c))
+
+/*
+
+The information in a \.{TFM} file appears in a sequence of 8-bit bytes.
+Since the number of bytes is always a multiple of 4, we could
+also regard the file as a sequence of 32-bit words, but \TeX\ uses the
+byte interpretation. The format of \.{TFM} files was designed by
+Lyle Ramshaw in 1980. The intent is to convey a lot of different kinds
+@^Ramshaw, Lyle Harold@>
+of information in a compact but useful form.
+
+$\Omega$ is capable of reading not only \.{TFM} files, but also
+\.{OFM} files, which can describe fonts with up to 65536 characters
+and with huge lig/kern tables. These fonts will often be virtual
+fonts built up from real fonts with 256 characters, but $\Omega$
+is not aware of this.
+
+The documentation below describes \.{TFM} files, with slight additions
+to show where \.{OFM} files differ.
+ */
+/*
+@ The first 24 bytes (6 words) of a \.{TFM} file contain twelve 16-bit
+integers that give the lengths of the various subsequent portions
+of the file. These twelve integers are, in order:
+$$\vbox{\halign{\hfil#&$\null=\null$#\hfil\cr
+|lf|&length of the entire file, in words;\cr
+|lh|&length of the header data, in words;\cr
+|bc|&smallest character code in the font;\cr
+|ec|&largest character code in the font;\cr
+|nw|&number of words in the width table;\cr
+|nh|&number of words in the height table;\cr
+|nd|&number of words in the depth table;\cr
+|ni|&number of words in the italic correction table;\cr
+|nl|&number of words in the lig/kern table;\cr
+|nk|&number of words in the kern table;\cr
+|ne|&number of words in the extensible character table;\cr
+|np|&number of font parameter words.\cr}}$$
+They are all nonnegative and less than $2^{15}$. We must have |bc-1<=ec<=255|,
+and
+$$\hbox{|lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
+Note that a \.{TFM} font may contain as many as 256 characters
+(if |bc=0| and |ec=255|), and as few as 0 characters (if |bc=ec+1|).
+
+Incidentally, when two or more 8-bit bytes are combined to form an integer of
+16 or more bits, the most significant bytes appear first in the file.
+This is called BigEndian order.
+@!@^BigEndian order@>
+
+The first 52 bytes (13 words) of an \.{OFM} file contains thirteen
+32-bit integers that give the lengths of the various subsequent
+portions of the file. The first word is 0 (future versions of
+\.{OFM} files could have different values; what is important is that
+the first two bytes be 0 to differentiate \.{TFM} and \.{OFM} files).
+The next twelve integers are as above, all nonegative and less
+than~$2^{31}$. We must have |bc-1<=ec<=65535|, and
+$$\hbox{|lf=13+lh+2*(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np|.}$$
+Note that an \.{OFM} font may contain as many as 65536 characters
+(if |bc=0| and |ec=65535|), and as few as 0 characters (if |bc=ec+1|).
+
+@ The rest of the \.{TFM} file may be regarded as a sequence of ten data
+arrays having the informal specification
+$$\def\arr$[#1]#2${\&{array} $[#1]$ \&{of} #2}
+\vbox{\halign{\hfil\\{#}&$\,:\,$\arr#\hfil\cr
+header&|[0..lh-1]@t\\{stuff}@>|\cr
+char\_info&|[bc..ec]char_info_word|\cr
+width&|[0..nw-1]fix_word|\cr
+height&|[0..nh-1]fix_word|\cr
+depth&|[0..nd-1]fix_word|\cr
+italic&|[0..ni-1]fix_word|\cr
+lig\_kern&|[0..nl-1]lig_kern_command|\cr
+kern&|[0..nk-1]fix_word|\cr
+exten&|[0..ne-1]extensible_recipe|\cr
+param&|[1..np]fix_word|\cr}}$$
+The most important data type used here is a |@!fix_word|, which is
+a 32-bit representation of a binary fraction. A |fix_word| is a signed
+quantity, with the two's complement of the entire word used to represent
+negation. Of the 32 bits in a |fix_word|, exactly 12 are to the left of the
+binary point; thus, the largest |fix_word| value is $2048-2^{-20}$, and
+the smallest is $-2048$. We will see below, however, that all but two of
+the |fix_word| values must lie between $-16$ and $+16$.
+
+@ The first data array is a block of header information, which contains
+general facts about the font. The header must contain at least two words,
+|header[0]| and |header[1]|, whose meaning is explained below.
+Additional header information of use to other software routines might
+also be included, but \TeX82 does not need to know about such details.
+For example, 16 more words of header information are in use at the Xerox
+Palo Alto Research Center; the first ten specify the character coding
+scheme used (e.g., `\.{XEROX text}' or `\.{TeX math symbols}'), the next five
+give the font identifier (e.g., `\.{HELVETICA}' or `\.{CMSY}'), and the
+last gives the ``face byte.'' The program that converts \.{DVI} files
+to Xerox printing format gets this information by looking at the \.{TFM}
+file, which it needs to read anyway because of other information that
+is not explicitly repeated in \.{DVI}~format.
+
+\yskip\hang|header[0]| is a 32-bit check sum that \TeX\ will copy into
+the \.{DVI} output file. Later on when the \.{DVI} file is printed,
+possibly on another computer, the actual font that gets used is supposed
+to have a check sum that agrees with the one in the \.{TFM} file used by
+\TeX. In this way, users will be warned about potential incompatibilities.
+(However, if the check sum is zero in either the font file or the \.{TFM}
+file, no check is made.) The actual relation between this check sum and
+the rest of the \.{TFM} file is not important; the check sum is simply an
+identification number with the property that incompatible fonts almost
+always have distinct check sums.
+@^check sum@>
+
+\yskip\hang|header[1]| is a |fix_word| containing the design size of
+the font, in units of \TeX\ points. This number must be at least 1.0; it is
+fairly arbitrary, but usually the design size is 10.0 for a ``10 point''
+font, i.e., a font that was designed to look best at a 10-point size,
+whatever that really means. When a \TeX\ user asks for a font
+`\.{at} $\delta$ \.{pt}', the effect is to override the design size
+and replace it by $\delta$, and to multiply the $x$ and~$y$ coordinates
+of the points in the font image by a factor of $\delta$ divided by the
+design size. {\sl All other dimensions in the\/ \.{TFM} file are
+|fix_word|\kern-1pt\ numbers in design-size units}, with the exception of
+|param[1]| (which denotes the slant ratio). Thus, for example, the value
+of |param[6]|, which defines the \.{em} unit, is often the |fix_word| value
+$2^{20}=1.0$, since many fonts have a design size equal to one em.
+The other dimensions must be less than 16 design-size units in absolute
+value; thus, |header[1]| and |param[1]| are the only |fix_word|
+entries in the whole \.{TFM} file whose first byte might be something
+besides 0 or 255.
+
+@ Next comes the |char_info| array, which contains one |@!char_info_word|
+per character. Each word in this part of a \.{TFM} file contains six fields
+packed into four bytes as follows.
+
+\yskip\hang first byte: |@!width_index| (8 bits)\par
+\hang second byte: |@!height_index| (4 bits) times 16, plus |@!depth_index|
+ (4~bits)\par
+\hang third byte: |@!italic_index| (6 bits) times 4, plus |@!tag|
+ (2~bits)\par
+\hang fourth byte: |@!remainder| (8 bits)\par
+\yskip\noindent
+The actual width of a character is \\{width}|[width_index]|, in design-size
+units; this is a device for compressing information, since many characters
+have the same width. Since it is quite common for many characters
+to have the same height, depth, or italic correction, the \.{TFM} format
+imposes a limit of 16 different heights, 16 different depths, and
+64 different italic corrections.
+
+For \.{OFM} files, two words (eight bytes) are used.
+The arrangement is as follows.
+
+\yskip\hang first and second bytes: |@!width_index| (16 bits)\par
+\hang third byte: |@!height_index| (8 bits)\par
+\hang fourth byte: |@!depth_index| (8~bits)\par
+\hang fifth and sixth bytes:
+|@!italic_index| (14 bits) times 4, plus |@!tag| (2~bits)\par
+\hang seventh and eighth bytes: |@!remainder| (16 bits)\par
+\yskip\noindent
+Therefore the \.{OFM} format imposes a limit of 256 different heights,
+256 different depths, and 16384 different italic corrections.
+
+@!@^italic correction@>
+The italic correction of a character has two different uses.
+(a)~In ordinary text, the italic correction is added to the width only if
+the \TeX\ user specifies `\.{\\/}' after the character.
+(b)~In math formulas, the italic correction is always added to the width,
+except with respect to the positioning of subscripts.
+
+Incidentally, the relation $\\{width}[0]=\\{height}[0]=\\{depth}[0]=
+\\{italic}[0]=0$ should always hold, so that an index of zero implies a
+value of zero. The |width_index| should never be zero unless the
+character does not exist in the font, since a character is valid if and
+only if it lies between |bc| and |ec| and has a nonzero |width_index|.
+*/
+
+ /*
+@ \TeX\ checks the information of a \.{TFM} file for validity as the
+file is being read in, so that no further checks will be needed when
+typesetting is going on. The somewhat tedious subroutine that does this
+is called |read_font_info|. It has four parameters: the user font
+identifier~|u|, the file name and area strings |nom| and |aire|, and the
+``at'' size~|s|. If |s|~is negative, it's the negative of a scale factor
+to be applied to the design size; |s=-1000| is the normal case.
+Otherwise |s| will be substituted for the design size; in this
+case, |s| must be positive and less than $2048\rm\,pt$
+(i.e., it must be less than $2^{27}$ when considered as an integer).
+
+The subroutine opens and closes a global file variable called |tfm_file|.
+It returns the value of the internal font number that was just loaded.
+If an error is detected, an error message is issued and no font
+information is stored; |null_font| is returned in this case.
+
+@d bad_tfm=11 {label for |read_font_info|}
+@d abort==goto bad_tfm {do this when the \.{TFM} data is wrong}
+
+*/
+
+/*
+The |tag| field in a |char_info_word| has four values that explain how to
+interpret the |remainder| field.
+
+\yskip\hangg|tag=0| (|no_tag|) means that |remainder| is unused.\par
+\hangg|tag=1| (|lig_tag|) means that this character has a ligature/kerning
+program starting at position |remainder| in the |lig_kern| array.\par
+\hangg|tag=2| (|list_tag|) means that this character is part of a chain of
+characters of ascending sizes, and not the largest in the chain. The
+|remainder| field gives the character code of the next larger character.\par
+\hangg|tag=3| (|ext_tag|) means that this character code represents an
+extensible character, i.e., a character that is built up of smaller pieces
+so that it can be made arbitrarily large. The pieces are specified in
+|@!exten[remainder]|.\par
+\yskip\noindent
+Characters with |tag=2| and |tag=3| are treated as characters with |tag=0|
+unless they are used in special circumstances in math formulas. For example,
+the \.{\\sum} operation looks for a |list_tag|, and the \.{\\left}
+operation looks for both |list_tag| and |ext_tag|.
+*/
+
+/* The |lig_kern| array contains instructions in a simple programming language
+that explains what to do for special letter pairs. Each word in this array,
+in a \.{TFM} file, is a |@!lig_kern_command| of four bytes.
+
+\yskip\hang first byte: |skip_byte|, indicates that this is the final program
+ step if the byte is 128 or more, otherwise the next step is obtained by
+ skipping this number of intervening steps.\par
+\hang second byte: |next_char|, ``if |next_char| follows the current character,
+ then perform the operation and stop, otherwise continue.''\par
+\hang third byte: |op_byte|, indicates a ligature step if less than~128,
+ a kern step otherwise.\par
+\hang fourth byte: |remainder|.\par
+\yskip\noindent
+In an \.{OFM} file, eight bytes are used, two bytes for each field.
+
+In a kern step, an
+additional space equal to |kern[256*(op_byte-128)+remainder]| is inserted
+between the current character and |next_char|. This amount is
+often negative, so that the characters are brought closer together
+by kerning; but it might be positive.
+
+There are eight kinds of ligature steps, having |op_byte| codes $4a+2b+c$ where
+$0\le a\le b+c$ and $0\le b,c\le1$. The character whose code is
+|remainder| is inserted between the current character and |next_char|;
+then the current character is deleted if $b=0$, and |next_char| is
+deleted if $c=0$; then we pass over $a$~characters to reach the next
+current character (which may have a ligature/kerning program of its own).
+
+If the very first instruction of the |lig_kern| array has |skip_byte=255|,
+the |next_char| byte is the so-called right boundary character of this font;
+the value of |next_char| need not lie between |bc| and~|ec|.
+If the very last instruction of the |lig_kern| array has |skip_byte=255|,
+there is a special ligature/kerning program for a left boundary character,
+beginning at location |256*op_byte+remainder|.
+The interpretation is that \TeX\ puts implicit boundary characters
+before and after each consecutive string of characters from the same font.
+These implicit characters do not appear in the output, but they can affect
+ligatures and kerning.
+
+If the very first instruction of a character's |lig_kern| program has
+|skip_byte>128|, the program actually begins in location
+|256*op_byte+remainder|. This feature allows access to large |lig_kern|
+arrays, because the first instruction must otherwise
+appear in a location |<=255| in a \.{TFM} file, |<=65535| in an \.{OFM} file.
+
+Any instruction with |skip_byte>128| in the |lig_kern| array must satisfy
+the condition
+$$\hbox{|256*op_byte+remainder<nl|.}$$
+If such an instruction is encountered during
+normal program execution, it denotes an unconditional halt; no ligature
+or kerning command is performed.
+*/
+
+/*
+ Extensible characters are specified by an |@!extensible_recipe|, which
+consists of four bytes in a \.{TFM} file,
+called |@!top|, |@!mid|, |@!bot|, and |@!rep| (in this order).
+In an \.{OFM} file, each field takes two bytes, for eight in total.
+These bytes are the character codes of individual pieces used to
+build up a large symbol. If |top|, |mid|, or |bot| are zero, they are not
+present in the built-up result. For example, an extensible vertical line is
+like an extensible bracket, except that the top and bottom pieces are missing.
+
+Let $T$, $M$, $B$, and $R$ denote the respective pieces, or an empty box
+if the piece isn't present. Then the extensible characters have the form
+$TR^kMR^kB$ from top to bottom, for some |k>=0|, unless $M$ is absent;
+in the latter case we can have $TR^kB$ for both even and odd values of~|k|.
+The width of the extensible character is the width of $R$; and the
+height-plus-depth is the sum of the individual height-plus-depths of the
+components used, since the pieces are butted together in a vertical list.
+*/
+
+/*
+The final portion of a \.{TFM} file is the |param| array, which is another
+sequence of |fix_word| values.
+
+\yskip\hang|param[1]=slant| is the amount of italic slant, which is used
+to help position accents. For example, |slant=.25| means that when you go
+up one unit, you also go .25 units to the right. The |slant| is a pure
+number; it's the only |fix_word| other than the design size itself that is
+not scaled by the design size.
+
+\hang|param[2]=space| is the normal spacing between words in text.
+Note that character |" "| in the font need not have anything to do with
+blank spaces.
+
+\hang|param[3]=space_stretch| is the amount of glue stretching between words.
+
+\hang|param[4]=space_shrink| is the amount of glue shrinking between words.
+
+\hang|param[5]=x_height| is the size of one ex in the font; it is also
+the height of letters for which accents don't have to be raised or lowered.
+
+\hang|param[6]=quad| is the size of one em in the font.
+
+\hang|param[7]=extra_space| is the amount added to |param[2]| at the
+ends of sentences.
+
+\yskip\noindent
+If fewer than seven parameters are present, \TeX\ sets the missing parameters
+to zero. Fonts used for math symbols are required to have
+additional parameter information, which is explained later.
+*/
+
+/*
+ There are programs called \.{TFtoPL} and \.{PLtoTF} that convert
+ between the \.{TFM} format and a symbolic property-list format
+ that can be easily edited. These programs contain extensive
+ diagnostic information, so \TeX\ does not have to bother giving
+ precise details about why it rejects a particular \.{TFM} file.
+
+*/
+
+#define tfm_abort { font_tables[f]->_font_name = NULL; \
+ font_tables[f]->_font_area = NULL; \
+ xfree(tfm_buffer); xfree(kerns); \
+ xfree(widths); xfree(heights); xfree(depths); \
+ xfree(italics); xfree(extens); xfree(lig_kerns); \
+ xfree(xligs); xfree(xkerns); \
+ return 0; }
+
+#define tfm_success { xfree(tfm_buffer); xfree(kerns); \
+ xfree(widths); xfree(heights); xfree(depths); \
+ xfree(italics); xfree(extens); xfree(lig_kerns); \
+ xfree(xligs); xfree(xkerns); return 1; }
+
+
+int
+open_tfm_file(char *nom, char *aire, unsigned char **tfm_buf, integer *tfm_siz) {
+ boolean res; /* was the callback successful? */
+ boolean opened; /* was |tfm_file| successfully opened?*/
+ integer callback_id;
+ FILE *tfm_file;
+ /* packfilename(nom,aire,getnullstr()); */
+ if(nameoffile != NULL)
+ xfree(nameoffile);
+ nameoffile = malloc(strlen(nom)+2);
+ strcpy(stringcast(nameoffile+1),nom);
+ namelength = strlen(nom);
+ callback_id=callback_defined(read_font_file_callback);
+ if (callback_id>0) {
+ res = run_callback(callback_id,"S->bSd",stringcast(nameoffile+1),
+ &opened, tfm_buf, tfm_siz);
+ if (res && opened && (*tfm_siz>0)) {
+ return 1;
+ }
+ if (!opened)
+ return -1;
+ } else {
+ if (ofm_open_in(tfm_file)) {
+ res = read_tfm_file(tfm_file,tfm_buf,tfm_siz);
+ b_close(tfm_file);
+ if (res) {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ Note: A malformed \.{TFM} file might be shorter than it claims to be;
+ thus |eof(tfm_file)| might be true when |read_font_info| refers to
+ |tfm_file^| or when it says |get(tfm_file)|. If such circumstances
+ cause system error messages, you will have to defeat them somehow,
+ for example by defining |fget| to be `\ignorespaces|begin get(tfm_file);|
+ |if eof(tfm_file) then abort; end|\unskip'.
+ @^system dependencies@>
+*/
+
+#define fget tfm_byte++
+#define fbyte tfm_buffer[tfm_byte]
+
+#define read_sixteen(a) \
+ { a=tfm_buffer[tfm_byte++]; \
+ if (a>127) { tfm_abort; } \
+ a=(a*256)+tfm_buffer[tfm_byte]; }
+
+#define read_sixteen_unsigned(a) \
+ { a=tfm_buffer[tfm_byte++]; \
+ a=(a*256)+tfm_buffer[tfm_byte]; }
+
+#define read_thirtytwo(a) \
+ { a=tfm_buffer[++tfm_byte]; \
+ if (a>127) { tfm_abort; } \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; }
+
+#define store_four_bytes(z) \
+ { a=tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ a=(a*256)+tfm_buffer[++tfm_byte]; \
+ z = a; }
+
+#define store_char_info(z) \
+ { if (font_level!=-1) { \
+ fget; read_sixteen_unsigned(a); \
+ ci._width_index=a; \
+ fget; read_sixteen_unsigned(b); \
+ ci._height_index=b>>8; \
+ ci._depth_index=b%256; \
+ fget; read_sixteen_unsigned(c); \
+ ci._italic_index=c>>8; \
+ ci._tag=c%4; \
+ fget; read_sixteen_unsigned(d); \
+ ci._remainder=d; \
+ } else { \
+ a=tfm_buffer[++tfm_byte]; \
+ ci._width_index=a; \
+ b=tfm_buffer[++tfm_byte]; \
+ ci._height_index=b>>4; \
+ ci._depth_index=b%16; \
+ c=tfm_buffer[++tfm_byte]; \
+ ci._italic_index=c>>2; \
+ ci._tag=c%4; \
+ d=tfm_buffer[++tfm_byte]; \
+ ci._remainder=d; \
+ } }
+
+#define read_four_quarters(q) \
+ { if (font_level!=-1) { \
+ fget; read_sixteen_unsigned(a); q.b0=a; \
+ fget; read_sixteen_unsigned(b); q.b1=b; \
+ fget; read_sixteen_unsigned(c); q.b2=c; \
+ fget; read_sixteen_unsigned(d); q.b3=d; \
+ } else { \
+ a=tfm_buffer[++tfm_byte]; q.b0=a; \
+ b=tfm_buffer[++tfm_byte]; q.b1=b; \
+ c=tfm_buffer[++tfm_byte]; q.b2=c; \
+ d=tfm_buffer[++tfm_byte]; q.b3=d; \
+ } }
+
+#define check_byte_range(z) { if ((z<bc)||(z>ec)) tfm_abort ; }
+
+
+/* A |fix_word| whose four bytes are $(a,b,c,d)$ from left to right represents
+ the number
+ $$x=\left\{\vcenter{\halign{$#$,\hfil\qquad&if $#$\hfil\cr
+ b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=0;\cr
+ -16+b\cdot2^{-4}+c\cdot2^{-12}+d\cdot2^{-20}&a=255.\cr}}\right.$$
+ (No other choices of |a| are allowed, since the magnitude of a number in
+ design-size units must be less than 16.) We want to multiply this
+ quantity by the integer~|z|, which is known to be less than $2^{27}$.
+ If $|z|<2^{23}$, the individual multiplications $b\cdot z$,
+ $c\cdot z$, $d\cdot z$ cannot overflow; otherwise we will divide |z| by 2,
+ 4, 8, or 16, to obtain a multiplier less than $2^{23}$, and we can
+ compensate for this later. If |z| has thereby been replaced by
+ $|z|^\prime=|z|/2^e$, let $\beta=2^{4-e}$; we shall compute
+ $$\lfloor(b+c\cdot2^{-8}+d\cdot2^{-16})\,z^\prime/\beta\rfloor$$
+ if $a=0$, or the same quantity minus $\alpha=2^{4+e}z^\prime$ if $a=255$.
+ This calculation must be done exactly, in order to guarantee portability
+ of \TeX\ between computers.
+*/
+
+#define store_scaled(zz) \
+ { fget; a=fbyte; fget; b=fbyte; \
+ fget; c=fbyte; fget; d=fbyte; \
+ sw=(((((d*z)>>8)+(c*z))>>8)+(b*z)) / beta; \
+ if (a==0) { zz=sw; } else if (a==255) { zz=sw-alpha; } else tfm_abort; \
+ }
+
+#define check_existence(z) \
+ { check_byte_range(z); \
+ if (!char_exists(f,z)) tfm_abort; \
+ }
+
+typedef struct tfmcharacterinfo {
+ integer _kern_index;
+ integer _lig_index;
+ integer _width_index;
+ integer _height_index;
+ integer _depth_index;
+ integer _italic_index;
+ integer _remainder;
+ unsigned char _tag ;
+} tfmcharacterinfo;
+
+extern charinfo *copy_charinfo(charinfo *ci);
+
+int
+read_tfm_info(internalfontnumber f, char *cnom, char *caire, scaled s) {
+ integer k; /* index into |font_info| */
+ halfword lf,lh,bc,ec,nw,nh,nd,ni,nl,nk,ne,np,slh; /* sizes of subfiles */
+ scaled *widths, *heights, *depths, *italics, *kerns;
+ halfword font_dir;
+ integer a,b,c,d; /* byte variables */
+ integer i; /* counter */
+ integer font_level,header_length;
+ integer nco,ncw,npc,nlw,neew;
+ tfmcharacterinfo ci;
+ charinfo *co;
+ four_quarters qw;
+ four_quarters *lig_kerns, *extens;
+ scaled sw; /* accumulators */
+ integer bch_label; /* left boundary start location, or infinity */
+ int bchar; /* :0..too_big_char; */ /* right boundary character, or |too_big_char| */
+ integer first_two;
+ scaled z; /* the design size or the ``at'' size */
+ integer alpha;
+ char beta; /* :1..16*/
+ integer *xligs, *xkerns; /* aux. for ligkern processing */
+ liginfo *cligs;
+ kerninfo *ckerns;
+ int fligs, fkerns;
+ char *tmpnam;
+ integer tfm_byte = 0; /* index into |tfm_buffer| */
+ integer saved_tfm_byte = 0; /* saved index into |tfm_buffer| */
+ unsigned char *tfm_buffer = NULL; /* byte buffer for tfm files */
+ integer tfm_size = 0; /* total size of the tfm file */
+
+ widths=NULL;
+ heights=NULL;
+ depths = NULL;
+ italics = NULL;
+ kerns = NULL;
+ lig_kerns = NULL;
+ extens = NULL;
+ xkerns = NULL;
+ ckerns = NULL;
+ xligs = NULL;
+ cligs = NULL;
+
+ font_dir = 0;
+
+ memset(&ci,0,sizeof(tfmcharacterinfo));
+
+ if(open_tfm_file(cnom,caire,&tfm_buffer,&tfm_size)!=1)
+ tfm_abort;
+
+ /* cnom can be an absolute filename, xbasename() fixes that. */
+
+ tmpnam=strdup(xbasename(cnom));
+ if (strcmp(tmpnam+strlen(tmpnam)-4,".tfm")==0) {
+ *(tmpnam+strlen(tmpnam)-4) =0;
+ }
+ set_font_name(f,tmpnam);
+ set_font_area(f,xstrdup(caire)); /* perhaps it leaks, but it doesnt crash */
+
+ /* @<Read the {\.{TFM}} size fields@>; */
+ nco=0; ncw=0; npc=0;
+ read_sixteen(first_two);
+ if (first_two!=0) {
+ font_level=-1;
+ lf=first_two;
+ fget; read_sixteen(lh);
+ fget; read_sixteen(bc);
+ fget; read_sixteen(ec);
+ if ((bc>ec+1)||(ec>255)) tfm_abort;
+ if (bc>255) { /* |bc=256| and |ec=255| */
+ bc=1; ec=0;
+ };
+ fget; read_sixteen(nw);
+ fget; read_sixteen(nh);
+ fget; read_sixteen(nd);
+ fget; read_sixteen(ni);
+ fget; read_sixteen(nl);
+ fget; read_sixteen(nk);
+ fget; read_sixteen(ne);
+ fget; read_sixteen(np);
+ header_length=6;
+ ncw=(ec-bc+1);
+ nlw=nl;
+ neew=ne;
+ } else {
+ fget; read_sixteen(font_level);
+ if (font_level!=0) tfm_abort;
+ read_thirtytwo(lf);
+ read_thirtytwo(lh);
+ read_thirtytwo(bc);
+ read_thirtytwo(ec);
+ if ((bc>ec+1)||(ec>65535)) tfm_abort;
+ if (bc>65535) { /* |bc=65536| and |ec=65535| */
+ bc=1; ec=0;
+ };
+ read_thirtytwo(nw);
+ read_thirtytwo(nh);
+ read_thirtytwo(nd);
+ read_thirtytwo(ni);
+ read_thirtytwo(nl);
+ read_thirtytwo(nk);
+ read_thirtytwo(ne);
+ read_thirtytwo(np);
+ read_thirtytwo(font_dir); /* junk */
+ nlw=2*nl;
+ neew=2*ne;
+ header_length=14;
+ ncw=2*(ec-bc+1);
+ };
+ if (lf!=(header_length+lh+ncw+nw+nh+nd+ni+nlw+nk+neew+np)) tfm_abort;
+
+ /* @<Use size fields to allocate font information@>; */
+
+ set_font_natural_dir(f,font_dir);
+ set_font_bc(f,bc);
+ set_font_ec(f,ec);
+
+ /* read the arrays first */
+ widths = xmalloc(nw*sizeof(scaled));
+ heights = xmalloc(nh*sizeof(scaled));
+ depths = xmalloc(nd*sizeof(scaled));
+ italics = xmalloc(ni*sizeof(scaled));
+ extens = xmalloc(ne*sizeof(four_quarters));
+ lig_kerns = xmalloc(nl*sizeof(four_quarters));
+ kerns = xmalloc(nk*sizeof(scaled));
+
+ /* @<Read the {\.{TFM}} header@>; */
+
+ /* Only the first two words of the header are needed by \TeX82. */
+ slh = lh;
+ if (lh<2)
+ tfm_abort;
+ store_four_bytes(font_checksum(f));
+ fget; read_sixteen(z); /* this rejects a negative design size */
+ fget; z=z*256+fbyte; fget; z=(z*16)+(fbyte>>4);
+ if (z<unity) tfm_abort;
+ while (lh>2) {
+ fget;fget;fget;fget;
+ lh--; /* ignore the rest of the header */
+ };
+
+ /* read the arrays before the character info */
+
+ set_font_dsize(f,z);
+ if (s!=-1000) {
+ z = (s>=0 ? s : xn_over_d(z,-s,1000));
+ }
+ set_font_size(f,z);
+
+ if (np>7)
+ set_font_params(f,np);
+
+ saved_tfm_byte = tfm_byte;
+ tfm_byte = (header_length+slh+ncw)*4 - 1;
+
+ /* @<Replace |z| by $|z|^\prime$ and compute $\alpha,\beta$@>; */
+
+ alpha=16;
+ while (z>=040000000) {
+ z=z>>1; alpha=alpha+alpha;
+ };
+ beta=256/alpha; alpha=alpha*z;
+
+ /* @<Read box dimensions@>; */
+
+ for (k=0;k<nw;k++) {
+ store_scaled(sw); widths[k] = sw;
+ }
+ if (widths[0]!=0) /* \\{width}[0] must be zero */
+ tfm_abort;
+ for (k=0;k<nh;k++) {
+ store_scaled(sw); heights[k] = sw;
+ }
+ if (heights[0]!=0)
+ tfm_abort; /* \\{height}[0] must be zero */
+ for (k=0;k<nd;k++) {
+ store_scaled(sw); depths[k] = sw;
+ }
+ if (depths[0]!=0)
+ tfm_abort; /* \\{depth}[0] must be zero */
+ for (k=0;k<ni;k++) {
+ store_scaled(sw); italics[k] = sw;
+ }
+ if (italics[0]!=0)
+ tfm_abort; /* \\{italic}[0] must be zero */
+
+
+ /* @<Read ligature/kern program@>; */
+
+ bch_label=nl; /* infinity*/
+ bchar=65536;
+ if (nl>0) {
+ for (k=0;k<nl;k++) {
+ read_four_quarters(qw);
+ lig_kerns[k] = qw;
+ if (a>128) {
+ if (256*c+d>=nl) tfm_abort;
+ if (a==255 && k==0) bchar=b;
+ } else {
+ /* if (b!=bchar) check_existence(b); */
+ if (c<128) {
+ /* check_existence(d); */ /* check ligature */
+ } else if (256*(c-128)+d>=nk) {
+ tfm_abort; /* check kern */
+ }
+ if ((a<128) && (k-0+a+1>=nl)) tfm_abort;
+ };
+ };
+ if (a==255) bch_label=256*c+d;
+ };
+
+ /* the actual kerns */
+ for (k=0;k<nk;k++) {
+ store_scaled(sw); kerns[k] = sw;
+ }
+
+ /* @<Read extensible character recipes@>; */
+ for (k=0;k<ne;k++) {
+ read_four_quarters(qw); extens[k] = qw;
+ }
+
+ /* @<Read font parameters@>; */
+
+ if (np>7) {
+ set_font_params(f,np);
+ }
+ for (k=1;k<=np;k++) {
+ if (k==1) { /* the |slant| parameter is a pure number */
+ fget; sw=fbyte;
+ if (sw>127) sw=sw-256;
+ fget; sw=sw*256+fbyte;
+ fget; sw=sw*256+fbyte;
+ fget; sw=(sw*16)+(fbyte>>4);
+ set_font_param(f,k,sw);
+ } else {
+ store_scaled(font_param(f,k));
+ }
+ }
+
+ /*
+ We check to see that the \.{TFM} file doesn't end prematurely; but
+ no error message is given for files having more than |lf| words.
+ */
+
+ if (tfm_byte<tfm_size-1) tfm_abort;
+
+ tfm_byte = saved_tfm_byte ;
+
+ /* fix up the left boundary character */
+ fligs = 0;
+ fkerns = 0;
+ if (bch_label != nl ) {
+ k = bch_label;
+ /*
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ */
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if(op_byte(k) >= kern_flag) { /* kern */
+ fkerns++;
+ } else { /* lig */
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ }
+ if (fkerns >0 || fligs > 0) {
+ if (fligs>0) cligs = xcalloc((fligs+1),sizeof(liginfo));
+ if (fkerns>0) ckerns = xcalloc((fkerns+1),sizeof(kerninfo));
+ fligs = 0;
+ fkerns = 0;
+ k = bch_label;
+ /*
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ */
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if(op_byte(k) >= kern_flag) { /* kern */
+ set_kern_item(ckerns[fkerns],next_char(k),kerns[256*(op_byte(k)-128)+rem_byte(k)]);
+ fkerns++;
+ } else { /* lig */
+ set_ligature_item(cligs[fligs],(op_byte(k)*2+1),next_char(k),rem_byte(k));
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ if (fkerns>0 || fligs>0){
+ co = get_charinfo(f,left_boundarychar);
+ if (fkerns>0) {
+ set_kern_item(ckerns[fkerns],end_kern,0);
+ fkerns++;
+ set_charinfo_kerns(co,ckerns);
+ }
+ if (fligs>0){
+ set_ligature_item(cligs[fligs],0,end_ligature,0);
+ fligs++;
+ set_charinfo_ligatures(co,cligs);
+ }
+ set_charinfo_remainder(co,0);
+ }
+ }
+
+ /* @<Read character data@>; */
+ for (k=bc;k<=ec;k++) {
+ store_char_info(k);
+ if (ci._width_index==0)
+ continue;
+ if (ci._width_index>=nw||ci._height_index>=nh||
+ ci._depth_index>=nd||ci._italic_index>=ni) tfm_abort;
+ d = ci._remainder;
+ switch (ci._tag) {
+ case lig_tag: if (d>=nl) tfm_abort; break;
+ case ext_tag: if (d>=ne) tfm_abort; break;
+ case list_tag:
+ /* We want to make sure that there is no cycle of characters linked together
+ by |list_tag| entries, since such a cycle would get \TeX\ into an endless
+ loop. If such a cycle exists, the routine here detects it when processing
+ the largest character code in the cycle.
+ */
+ check_byte_range(d);
+ while (d<k) { /* current_character == k */
+ if (char_tag(f,d)!=list_tag)
+ goto NOT_FOUND; /* not a cycle */
+ d=char_remainder(f,d); /* next character on the list */
+ };
+ if (d==k) tfm_abort; /* yes, there's a cycle */
+ NOT_FOUND:
+ break;
+ }
+ /* put it in the actual font */
+ co = get_charinfo(f,k);
+ set_charinfo_index (co,k);
+ set_charinfo_tag (co,ci._tag);
+ if (ci._tag == ext_tag) {
+ set_charinfo_extensible(co,
+ extens[ci._remainder].b0, /* top */
+ extens[ci._remainder].b2, /* bot */
+ extens[ci._remainder].b1, /* mid */
+ extens[ci._remainder].b3); /* rep */
+ set_charinfo_remainder (co,0);
+ } else {
+ set_charinfo_remainder (co,ci._remainder);
+ }
+ set_charinfo_width (co,widths[ci._width_index]);
+ set_charinfo_height (co,heights[ci._height_index]);
+ set_charinfo_depth (co,depths[ci._depth_index]);
+ set_charinfo_italic (co,italics[ci._italic_index]);
+ };
+
+ /* first pass: count ligs and kerns */
+
+ xligs = xcalloc((ec+1),sizeof(integer));
+ xkerns = xcalloc((ec+1),sizeof(integer));
+
+ for (i=bc;i<=ec;i++) {
+ if (char_tag(f,i) == lig_tag) {
+ k = lig_kern_start(f,i);
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ /* now k is the start index */
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if(op_byte(k) >= kern_flag) { /* kern */
+ xkerns[i]++;
+ if (next_char(k) == bchar)
+ xkerns[i]++;
+ } else { /* lig */
+ xligs[i]++;
+ if (next_char(k) == bchar)
+ xligs[i]++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ }
+ }
+
+ cligs = NULL;
+ ckerns = NULL;
+
+ for (i=bc;i<=ec;i++) {
+ fligs = 0;
+ fkerns = 0;
+ if (char_tag(f,i) == lig_tag) {
+ k = lig_kern_start(f,i);
+ if (skip_byte(k) > stop_flag)
+ k = lig_kern_restart(k);
+ /* now k is the start index */
+ if (xligs[i]>0) cligs = xcalloc((xligs[i]+1),sizeof(liginfo));
+ if (xkerns[i]>0) ckerns = xcalloc((xkerns[i]+1),sizeof(kerninfo));
+ while (1) {
+ if (skip_byte(k) <= stop_flag) {
+ if(op_byte(k) >= kern_flag) { /* kern */
+ if (next_char(k) == bchar) {
+ set_kern_item(ckerns[fkerns],right_boundarychar,kerns[256*(op_byte(k)-128)+rem_byte(k)]);
+ fkerns++;
+ }
+ set_kern_item(ckerns[fkerns],next_char(k),kerns[256*(op_byte(k)-128)+rem_byte(k)]);
+ fkerns++;
+ } else { /* lig */
+ if (next_char(k) == bchar) {
+ set_ligature_item(cligs[fligs],(op_byte(k)*2+1),right_boundarychar,rem_byte(k));
+ fligs++;
+ }
+ set_ligature_item(cligs[fligs],(op_byte(k)*2+1),next_char(k),rem_byte(k));
+ fligs++;
+ }
+ }
+ if (skip_byte(k) == 0) {
+ k++;
+ } else {
+ if (skip_byte(k) >= stop_flag)
+ break;
+ k += skip_byte(k) + 1;
+ }
+ }
+ if (fkerns>0 || fligs>0){
+ co = get_charinfo(f,i);
+ if (fkerns>0) {
+ set_kern_item(ckerns[fkerns],end_kern,0);
+ fkerns++;
+ set_charinfo_kerns(co,ckerns);
+ }
+ if (fligs>0){
+ set_ligature_item(cligs[fligs],0,end_ligature,0);
+ fligs++;
+ set_charinfo_ligatures(co,cligs);
+ }
+ set_charinfo_remainder(co,0);
+ }
+ }
+ }
+
+
+ /* @<Make final adjustments and |goto done|@> */
+
+ /* Now to wrap it up, we have checked all the necessary things about the \.{TFM}
+ file, and all we need to do is put the finishing touches on the data for
+ the new font.
+ */
+
+ if (bchar!= 65536) {
+ co = copy_charinfo(char_info(f,bchar));
+ set_right_boundary(f,co);
+ }
+
+ tfm_success;
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/tounicode.c b/Build/source/texk/web2c/luatexdir/font/tounicode.c
new file mode 100644
index 00000000000..ff86a8512e2
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tounicode.c
@@ -0,0 +1,604 @@
+/*
+Copyright (c) 2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "ptexlib.h"
+
+#define isXdigit(c) (isdigit(c) || ('A' <= (c) && (c) <= 'F'))
+#define UNI_UNDEF -1
+#define UNI_STRING -2 /* string allocated by def_tounicode() */
+#define UNI_EXTRA_STRING -3 /* string allocated by set_glyph_unicode() */
+
+static struct avl_table *glyph_unicode_tree = NULL;
+
+static int comp_glyph_unicode_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const glyph_unicode_entry *) pa)->name,
+ ((const glyph_unicode_entry *) pb)->name);
+}
+
+static glyph_unicode_entry *new_glyph_unicode_entry(void)
+{
+ glyph_unicode_entry *e;
+ e = xtalloc(1, glyph_unicode_entry);
+ e->name = NULL;
+ e->code = UNI_UNDEF;
+ e->unicode_seq = NULL;
+ return e;
+}
+
+static void destroy_glyph_unicode_entry(void *pa, void *pb)
+{
+ glyph_unicode_entry *e = (glyph_unicode_entry *) pa;
+ xfree(e->name);
+ if (e->code == UNI_STRING) {
+ assert(e->unicode_seq != NULL);
+ xfree(e->unicode_seq);
+ }
+}
+
+void glyph_unicode_free(void)
+{
+ if (glyph_unicode_tree != NULL)
+ avl_destroy(glyph_unicode_tree, destroy_glyph_unicode_entry);
+}
+
+void def_tounicode(strnumber glyph, strnumber unistr)
+{
+ char buf[SMALL_BUF_SIZE], *p;
+ char buf2[SMALL_BUF_SIZE], *q;
+ int valid_unistr; /* 0: invalid; 1: unicode value; 2: string */
+ int i, l;
+ glyph_unicode_entry *gu, t;
+ void **aa;
+
+ p = makecstring(glyph);
+ assert(strlen(p) < SMALL_BUF_SIZE);
+ strcpy(buf, p); /* copy the result to buf before next call of makecstring() */
+ p = makecstring(unistr);
+ while (*p == ' ')
+ p++; /* ignore leading spaces */
+ l = strlen(p);
+ while (l > 0 && p[l - 1] == ' ')
+ l--; /* ignore traling spaces */
+ valid_unistr = 1; /* a unicode value is the most common case */
+ for (i = 0; i < l; i++) {
+ if (p[i] == ' ')
+ valid_unistr = 2; /* if a space occurs we treat this entry as a string */
+ else if (!isXdigit(p[i])) {
+ valid_unistr = 0;
+ break;
+ }
+ }
+ if (l == 0 || valid_unistr == 0 || strlen(buf) == 0
+ || strcmp(buf, notdef) == 0) {
+ pdftex_warn("ToUnicode: invalid parameter(s): `%s' => `%s'", buf, p);
+ return;
+ }
+ if (glyph_unicode_tree == NULL) {
+ glyph_unicode_tree =
+ avl_create(comp_glyph_unicode_entry, NULL, &avl_xallocator);
+ assert(glyph_unicode_tree != NULL);
+ }
+ t.name = buf;
+ /* allow overriding existing entries */
+ if ((gu = (glyph_unicode_entry *) avl_find(glyph_unicode_tree, &t)) != NULL) {
+ if (gu->code == UNI_STRING) {
+ assert(gu->unicode_seq != NULL);
+ xfree(gu->unicode_seq);
+ }
+ } else { /* make new entry */
+ gu = new_glyph_unicode_entry();
+ gu->name = xstrdup(buf);
+ }
+ if (valid_unistr == 2) { /* a string with space(s) */
+ /* copy p to buf2, ignoring spaces */
+ for (q = buf2; *p != 0; p++)
+ if (*p != ' ')
+ *q++ = *p;
+ *q = 0;
+ gu->code = UNI_STRING;
+ gu->unicode_seq = xstrdup(buf2);
+ } else {
+ i = sscanf(p, "%lX", &(gu->code));
+ assert(i == 1);
+ }
+ aa = avl_probe(glyph_unicode_tree, gu);
+ assert(aa != NULL);
+}
+
+
+static long check_unicode_value(char *s, boolean multiple_value)
+{
+ int l = strlen(s);
+ int i;
+ long code;
+
+ if (l == 0)
+ return UNI_UNDEF;
+ if (multiple_value && l % 4 != 0)
+ return UNI_UNDEF;
+ if (!multiple_value && !(4 <= l && l <= 6))
+ return UNI_UNDEF;
+
+ for (i = 0; i < l; i++) {
+ if (!isXdigit(s[i]))
+ return UNI_UNDEF;
+ if (multiple_value) {
+ if (i % 4 == 3) {
+ if (sscanf(s + i - 3, "%4lX", &code) != 1)
+ return UNI_UNDEF;
+ if (!((0x0000 <= code && code <= 0xD7FF) ||
+ (0xE000 <= code && code <= 0xFFFF)))
+ return UNI_UNDEF;
+ }
+ } else { /* single value */
+ if (i == l - 1) {
+ if (sscanf(s, "%lX", &code) != 1)
+ return UNI_UNDEF;
+ if (!((0x0000 <= code && code <= 0xD7FF) ||
+ (0xE000 <= code && code <= 0x10FFFF)))
+ return UNI_UNDEF;
+ }
+ }
+ }
+ return code;
+}
+
+static char *utf16be_str(long code)
+{
+ static char buf[SMALL_BUF_SIZE];
+ long v;
+ unsigned vh, vl;
+
+ assert(code >= 0);
+
+ if (code <= 0xFFFF)
+ sprintf(buf, "%04lX", code);
+ else {
+ v = code - 0x10000;
+ vh = v / 0x400 + 0xD800;
+ vl = v % 0x400 + 0xDC00;
+ sprintf(buf, "%04X%04X", vh, vl);
+ }
+ return buf;
+}
+
+
+/* this function set proper values to *gp based on s; in case it returns
+ * gp->code == UNI_EXTRA_STRING then the caller is responsible for freeing
+ * gp->unicode_seq too */
+static void set_glyph_unicode(char *s, glyph_unicode_entry * gp)
+{
+ char buf[SMALL_BUF_SIZE], buf2[SMALL_BUF_SIZE], *p;
+ long code;
+ boolean last_component;
+ glyph_unicode_entry tmp, *ptmp;
+
+ /* skip dummy entries */
+ if (s == NULL || s == notdef)
+ return;
+
+ /* strip everything after the first dot */
+ p = strchr(s, '.');
+ if (p != NULL) {
+ *buf = 0;
+ strncat(buf, s, p - s);
+ s = buf;
+ }
+
+ if (strlen(s) == 0)
+ return;
+
+ /* check for case of multiple components separated by '_' */
+ p = strchr(s, '_');
+ if (p != NULL) {
+ assert(strlen(s) < sizeof(buf));
+ if (s != buf) {
+ strcpy(buf, s);
+ p = strchr(buf, '_');
+ s = buf;
+ }
+ *buf2 = 0;
+ last_component = false;
+ for (;;) {
+ *p = 0;
+ tmp.code = UNI_UNDEF;
+ set_glyph_unicode(s, &tmp);
+ switch (tmp.code) {
+ case UNI_UNDEF: /* not found, do nothing */
+ break;
+ case UNI_STRING: /* s matched an entry with string value in the database */
+ assert(tmp.unicode_seq != NULL);
+ assert(strlen(buf2) + strlen(tmp.unicode_seq) < sizeof(buf2));
+ strcat(buf2, tmp.unicode_seq);
+ break;
+ case UNI_EXTRA_STRING: /* s is a multiple value of form "uniXXXX" */
+ assert(strlen(buf2) + strlen(tmp.unicode_seq) < sizeof(buf2));
+ strcat(buf2, tmp.unicode_seq);
+ xfree(tmp.unicode_seq);
+ break;
+ default: /* s matched an entry with numeric value in the
+ database, or a value derived from "uXXXX" */
+ assert(tmp.code >= 0);
+ strcat(buf2, utf16be_str(tmp.code));
+ }
+ if (last_component)
+ break;
+ s = p + 1;
+ p = strchr(s, '_');
+ if (p == NULL) {
+ p = strend(s);
+ last_component = true;
+ }
+ }
+ gp->code = UNI_EXTRA_STRING;
+ gp->unicode_seq = xstrdup(buf2);
+ return;
+ }
+
+ /* lookup for glyph name in the database */
+ tmp.name = s;
+ tmp.code = UNI_UNDEF;
+ ptmp = (glyph_unicode_entry *) avl_find(glyph_unicode_tree, &tmp);
+ if (ptmp != NULL) {
+ gp->code = ptmp->code;
+ gp->unicode_seq = ptmp->unicode_seq;
+ return;
+ }
+
+ /* check for case of "uniXXXX" (multiple 4-hex-digit values allowed) */
+ if (str_prefix(s, "uni")) {
+ p = s + strlen("uni");
+ code = check_unicode_value(p, true);
+ if (code != UNI_UNDEF) {
+ if (strlen(p) == 4) /* single value */
+ gp->code = code;
+ else { /* multiple value */
+ gp->code = UNI_EXTRA_STRING;
+ gp->unicode_seq = xstrdup(p);
+ }
+ }
+ return; /* since the last case cannot happen */
+ }
+
+ /* check for case of "uXXXX" (single value up to 6 hex digits) */
+ if (str_prefix(s, "u")) {
+ p = s + strlen("u");
+ code = check_unicode_value(p, false);
+ if (code != UNI_UNDEF) {
+ assert(code >= 0);
+ gp->code = code;
+ }
+ }
+}
+
+static void set_cid_glyph_unicode(long index, glyph_unicode_entry * gp,
+ internal_font_number f) {
+ char *s;
+ if (font_tounicode(f)) {
+ if ((s = get_charinfo_tounicode(char_info(f,index)))!=NULL) {
+ gp->code = UNI_EXTRA_STRING;
+ gp->unicode_seq = xstrdup(s);
+ }
+ } else {
+ gp->code = index; /* fallback */
+ }
+}
+
+
+integer write_tounicode(char **glyph_names, char *name)
+{
+ char buf[SMALL_BUF_SIZE], *p;
+ static char builtin_suffix[] = "-builtin";
+ short range_size[257];
+ glyph_unicode_entry gtab[257];
+ integer objnum;
+ int i, j;
+ int bfchar_count, bfrange_count, subrange_count;
+ assert(strlen(name) + strlen(builtin_suffix) < SMALL_BUF_SIZE);
+ if (glyph_unicode_tree == NULL) {
+ pdftex_warn("no GlyphToUnicode entry has been inserted yet!");
+ fixed_gen_tounicode = 0;
+ return 0;
+ }
+ strcpy(buf, name);
+ if ((p = strrchr(buf, '.')) != NULL && strcmp(p, ".enc") == 0)
+ *p = 0; /* strip ".enc" from encoding name */
+ else
+ strcat(buf, builtin_suffix); /* ".enc" not present, this is a builtin
+ encoding so the name is eg "cmr10-builtin" */
+ objnum = pdf_new_objnum();
+ pdf_begin_dict(objnum, 0);
+ pdf_begin_stream();
+ pdf_printf("%%!PS-Adobe-3.0 Resource-CMap\n"
+ "%%%%DocumentNeededResources: ProcSet (CIDInit)\n"
+ "%%%%IncludeResource: ProcSet (CIDInit)\n"
+ "%%%%BeginResource: CMap (TeX-%s-0)\n"
+ "%%%%Title: (TeX-%s-0 TeX %s 0)\n"
+ "%%%%Version: 1.000\n"
+ "%%%%EndComments\n"
+ "/CIDInit /ProcSet findresource begin\n"
+ "12 dict begin\n"
+ "begincmap\n"
+ "/CIDSystemInfo\n"
+ "<< /Registry (TeX)\n"
+ "/Ordering (%s)\n"
+ "/Supplement 0\n"
+ ">> def\n"
+ "/CMapName /TeX-%s-0 def\n"
+ "/CMapType 2 def\n"
+ "1 begincodespacerange\n"
+ "<00> <FF>\n" "endcodespacerange\n", buf, buf, buf, buf, buf);
+
+ /* set gtab */
+ for (i = 0; i < 256; ++i) {
+ gtab[i].code = UNI_UNDEF;
+ set_glyph_unicode(glyph_names[i], &gtab[i]);
+ }
+ gtab[256].code = UNI_UNDEF;
+
+ /* set range_size */
+ for (i = 0; i < 256;) {
+ if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) {
+ range_size[i] = 1; /* single entry */
+ i++;
+ } else if (gtab[i].code == UNI_UNDEF) {
+ range_size[i] = 0; /* no entry */
+ i++;
+ } else { /* gtab[i].code >= 0 */
+ j = i;
+ while (i < 256 && gtab[i + 1].code >= 0 &&
+ gtab[i].code + 1 == gtab[i + 1].code)
+ i++;
+ /* at this point i is the last entry of the subrange */
+ i++; /* move i to the next entry */
+ range_size[j] = i - j;
+ }
+ }
+
+ /* calculate bfrange_count and bfchar_count */
+ bfrange_count = 0;
+ bfchar_count = 0;
+ for (i = 0; i < 256;) {
+ if (range_size[i] == 1) {
+ bfchar_count++;
+ i++;
+ } else if (range_size[i] > 1) {
+ bfrange_count++;
+ i += range_size[i];
+ } else
+ i++;
+ }
+
+ /* write out bfrange */
+ i = 0;
+ write_bfrange:
+ if (bfrange_count > 100)
+ subrange_count = 100;
+ else
+ subrange_count = bfrange_count;
+ bfrange_count -= subrange_count;
+ pdf_printf("%i beginbfrange\n", subrange_count);
+ for (j = 0; j < subrange_count; j++) {
+ while (range_size[i] <= 1 && i < 256)
+ i++;
+ assert(i < 256);
+ pdf_printf("<%02X> <%02X> <%s>\n", i, i + range_size[i] - 1,
+ utf16be_str(gtab[i].code));
+ i += range_size[i];
+ }
+ pdf_printf("endbfrange\n");
+ if (bfrange_count > 0)
+ goto write_bfrange;
+
+ /* write out bfchar */
+ i = 0;
+ write_bfchar:
+ if (bfchar_count > 100)
+ subrange_count = 100;
+ else
+ subrange_count = bfchar_count;
+ bfchar_count -= subrange_count;
+ pdf_printf("%i beginbfchar\n", subrange_count);
+ for (j = 0; j < subrange_count; j++) {
+ while (i < 256) {
+ if (range_size[i] > 1)
+ i += range_size[i];
+ else if (range_size[i] == 0)
+ i++;
+ else /* range_size[i] == 1 */
+ break;
+ }
+ assert(i < 256 && gtab[i].code != UNI_UNDEF);
+ if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) {
+ assert(gtab[i].unicode_seq != NULL);
+ pdf_printf("<%02X> <%s>\n", i, gtab[i].unicode_seq);
+ } else
+ pdf_printf("<%02X> <%s>\n", i, utf16be_str(gtab[i].code));
+ i++;
+ }
+ pdf_printf("endbfchar\n");
+ if (bfchar_count > 0)
+ goto write_bfchar;
+
+ /* free strings allocated by set_glyph_unicode() */
+ for (i = 0; i < 256; ++i) {
+ if (gtab[i].code == UNI_EXTRA_STRING)
+ xfree(gtab[i].unicode_seq);
+ }
+
+ pdf_printf("endcmap\n"
+ "CMapName currentdict /CMap defineresource pop\n"
+ "end\n" "end\n" "%%%%EndResource\n" "%%%%EOF\n");
+ pdf_end_stream();
+ return objnum;
+}
+
+integer write_cid_tounicode(fo_entry * fo, internalfontnumber f) {
+
+ int range_size[65537];
+ glyph_unicode_entry gtab[65537];
+ integer objnum;
+ int i, j, k;
+ int bfchar_count, bfrange_count, subrange_count;
+ char *buf;
+
+ assert(fo->fd->fontname);
+ buf = xmalloc(strlen(fo->fd->fontname)+8);
+ sprintf(buf,"%s-%s",(fo->fd->subset_tag!=NULL ? fo->fd->subset_tag : "UCS"),
+ fo->fd->fontname);
+
+ objnum = pdf_new_objnum();
+ pdf_begin_dict(objnum, 0);
+ pdf_begin_stream();
+ pdf_printf("%%!PS-Adobe-3.0 Resource-CMap\n"
+ "%%%%DocumentNeededResources: ProcSet (CIDInit)\n"
+ "%%%%IncludeResource: ProcSet (CIDInit)\n"
+ "%%%%BeginResource: CMap (TeX-%s-0)\n"
+ "%%%%Title: (TeX-%s-0 TeX %s 0)\n"
+ "%%%%Version: 1.000\n"
+ "%%%%EndComments\n"
+ "/CIDInit /ProcSet findresource begin\n"
+ "12 dict begin\n"
+ "begincmap\n"
+ "/CIDSystemInfo\n"
+ "<< /Registry (TeX)\n"
+ "/Ordering (%s)\n"
+ "/Supplement 0\n"
+ ">> def\n"
+ "/CMapName /TeX-Identity-%s def\n"
+ "/CMapType 2 def\n"
+ "1 begincodespacerange\n"
+ "<0000> <FFFF>\n"
+ "endcodespacerange\n", buf, buf, buf, buf, buf);
+ xfree(buf);
+ /* set up gtab */
+ for (i = 0; i < 65537; ++i) {
+ gtab[i].code = UNI_UNDEF;
+ }
+ for (k = 1; k <= max_font_id(); k++) {
+ if (k == f || -f == pdf_font_num(k)) {
+ for (i = font_bc(k); i <= font_ec(k); i++) {
+ if (char_exists(k,i) && char_used(k,i)) {
+ j = char_index(k,i);
+ if (gtab[j].code == UNI_UNDEF) {
+ set_cid_glyph_unicode(i, &gtab[j], f);
+ }
+ }
+ }
+ }
+ }
+
+ /* set range_size */
+ for (i = 0; i < 65536;) {
+ if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) {
+ range_size[i] = 1; /* single entry */
+ i++;
+ } else if (gtab[i].code == UNI_UNDEF) {
+ range_size[i] = 0; /* no entry */
+ i++;
+ } else { /* gtab[i].code >= 0 */
+ j = i;
+ while (i < 65536 && gtab[i + 1].code >= 0 &&
+ gtab[i].code + 1 == gtab[i + 1].code)
+ i++;
+ /* at this point i is the last entry of the subrange */
+ i++; /* move i to the next entry */
+ range_size[j] = i - j;
+ }
+ }
+
+ /* calculate bfrange_count and bfchar_count */
+ bfrange_count = 0;
+ bfchar_count = 0;
+ for (i = 0; i < 65536;) {
+ if (range_size[i] == 1) {
+ bfchar_count++;
+ i++;
+ } else if (range_size[i] > 1) {
+ bfrange_count++;
+ i += range_size[i];
+ } else
+ i++;
+ }
+
+ /* write out bfrange */
+ i = 0;
+ write_bfrange:
+ if (bfrange_count > 100)
+ subrange_count = 100;
+ else
+ subrange_count = bfrange_count;
+ bfrange_count -= subrange_count;
+ pdf_printf("%i beginbfrange\n", subrange_count);
+ for (j = 0; j < subrange_count; j++) {
+ while (range_size[i] <= 1 && i < 65536)
+ i++;
+ assert(i < 65536);
+ pdf_printf("<%04X> <%04X> <%s>\n", i, i + range_size[i] - 1,
+ utf16be_str(gtab[i].code));
+ i += range_size[i];
+ }
+ pdf_printf("endbfrange\n");
+ if (bfrange_count > 0)
+ goto write_bfrange;
+
+ /* write out bfchar */
+ i = 0;
+ write_bfchar:
+ if (bfchar_count > 100)
+ subrange_count = 100;
+ else
+ subrange_count = bfchar_count;
+ bfchar_count -= subrange_count;
+ pdf_printf("%i beginbfchar\n", subrange_count);
+ for (j = 0; j < subrange_count; j++) {
+ while (i < 65536) {
+ if (range_size[i] > 1)
+ i += range_size[i];
+ else if (range_size[i] == 0)
+ i++;
+ else /* range_size[i] == 1 */
+ break;
+ }
+ assert(i < 65536 && gtab[i].code != UNI_UNDEF);
+ if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) {
+ assert(gtab[i].unicode_seq != NULL);
+ pdf_printf("<%04X> <%s>\n", i, gtab[i].unicode_seq);
+ } else
+ pdf_printf("<%04X> <%s>\n", i, utf16be_str(gtab[i].code));
+ i++;
+ }
+ pdf_printf("endbfchar\n");
+ if (bfchar_count > 0)
+ goto write_bfchar;
+
+ /* free strings allocated by set_glyph_unicode() */
+ for (i = 0; i < 65536; ++i) {
+ if (gtab[i].code == UNI_EXTRA_STRING)
+ xfree(gtab[i].unicode_seq);
+ }
+
+ pdf_printf("endcmap\n"
+ "CMapName currentdict /CMap defineresource pop\n"
+ "end\n" "end\n" "%%%%EndResource\n" "%%%%EOF\n");
+ pdf_end_stream();
+ return objnum;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/tt_glyf.c b/Build/source/texk/web2c/luatexdir/font/tt_glyf.c
new file mode 100644
index 00000000000..bf21e58c49a
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tt_glyf.c
@@ -0,0 +1,658 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.c,v 1.2 2005/06/09 14:31:11 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+/*
+ * Subsetting glyf, updating loca, hmtx, ...
+ *
+ */
+
+#include "ptexlib.h"
+
+#include "sfnt.h"
+#include "tt_table.h"
+#include "tt_glyf.h"
+
+#define NUM_GLYPH_LIMIT 65534
+#define TABLE_DATA_ALLOC_SIZE 40960
+#define GLYPH_ARRAY_ALLOC_SIZE 256
+
+static USHORT
+find_empty_slot (struct tt_glyphs *g)
+{
+ USHORT gid;
+
+ ASSERT(g);
+
+ for (gid = 0; gid < NUM_GLYPH_LIMIT; gid++) {
+ if (!(g->used_slot[gid/8] & (1 << (7 - (gid % 8)))))
+ break;
+ }
+ if (gid == NUM_GLYPH_LIMIT)
+ TT_ERROR("No empty glyph slot available.");
+
+ return gid;
+}
+
+USHORT
+tt_find_glyph (struct tt_glyphs *g, USHORT gid)
+{
+ USHORT idx, new_gid = 0;
+
+ ASSERT(g);
+
+ for (idx = 0; idx < g->num_glyphs; idx++) {
+ if (gid == g->gd[idx].ogid) {
+ new_gid = g->gd[idx].gid;
+ break;
+ }
+ }
+
+ return new_gid;
+}
+
+USHORT
+tt_get_index (struct tt_glyphs *g, USHORT gid)
+{
+ USHORT idx;
+
+ ASSERT(g);
+
+ for (idx = 0; idx < g->num_glyphs; idx++) {
+ if (gid == g->gd[idx].gid)
+ break;
+ }
+ if (idx == g->num_glyphs)
+ idx = 0;
+
+ return idx;
+}
+
+USHORT
+tt_add_glyph (struct tt_glyphs *g, USHORT gid, USHORT new_gid)
+{
+ ASSERT(g);
+
+ if (g->used_slot[new_gid/8] & (1 << (7 - (new_gid % 8)))) {
+ WARN("Slot %u already used.", new_gid);
+ } else {
+ if (g->num_glyphs+1 >= NUM_GLYPH_LIMIT)
+ TT_ERROR("Too many glyphs.");
+
+ if (g->num_glyphs >= g->max_glyphs) {
+ g->max_glyphs += GLYPH_ARRAY_ALLOC_SIZE;
+ g->gd = RENEW(g->gd, g->max_glyphs, struct tt_glyph_desc);
+ }
+ g->gd[g->num_glyphs].gid = new_gid;
+ g->gd[g->num_glyphs].ogid = gid;
+ g->gd[g->num_glyphs].length = 0;
+ g->gd[g->num_glyphs].data = NULL;
+ g->used_slot[new_gid/8] |= (1 << (7 - (new_gid % 8)));
+ g->num_glyphs += 1;
+ }
+
+ if (new_gid > g->last_gid) {
+ g->last_gid = new_gid;
+ }
+
+ return new_gid;
+}
+
+/*
+ * Initialization
+ */
+struct tt_glyphs *
+tt_build_init (void)
+{
+ struct tt_glyphs *g;
+
+ g = NEW(1, struct tt_glyphs);
+
+ g->num_glyphs = 0;
+ g->max_glyphs = 0;
+ g->last_gid = 0;
+ g->emsize = 1;
+ g->default_advh = 0;
+ g->default_tsb = 0;
+ g->gd = NULL;
+ g->used_slot = NEW(8192, unsigned char);
+ memset(g->used_slot, 0, 8192);
+ tt_add_glyph(g, 0, 0);
+
+ return g;
+}
+
+void
+tt_build_finish (struct tt_glyphs *g)
+{
+ if (g) {
+ if (g->gd) {
+ USHORT idx;
+ for (idx = 0; idx < g->num_glyphs; idx++) {
+ if (g->gd[idx].data)
+ RELEASE(g->gd[idx].data);
+ }
+ RELEASE(g->gd);
+ }
+ if (g->used_slot)
+ RELEASE(g->used_slot);
+ RELEASE(g);
+ }
+}
+
+static int
+glyf_cmp (const void *v1, const void *v2)
+{
+ int cmp = 0;
+ struct tt_glyph_desc *sv1, *sv2;
+
+ sv1 = (struct tt_glyph_desc *) v1;
+ sv2 = (struct tt_glyph_desc *) v2;
+
+ if (sv1->gid == sv2->gid)
+ cmp = 0;
+ else if (sv1->gid < sv2->gid)
+ cmp = -1;
+ else
+ cmp = 1;
+
+ return cmp;
+}
+
+/*
+ * TrueType outline data.
+ */
+#define ARG_1_AND_2_ARE_WORDS (1 << 0)
+#define ARGS_ARE_XY_VALUES (1 << 1)
+#define ROUND_XY_TO_GRID (1 << 2)
+#define WE_HAVE_A_SCALE (1 << 3)
+#define RESERVED (1 << 4)
+#define MORE_COMPONENT (1 << 5)
+#define WE_HAVE_AN_X_AND_Y_SCALE (1 << 6)
+#define WE_HAVE_A_TWO_BY_TWO (1 << 7)
+#define WE_HAVE_INSTRUCTIONS (1 << 8)
+#define USE_MY_METRICS (1 << 9)
+
+int
+tt_build_tables (sfnt *sfont, struct tt_glyphs *g)
+{
+ char *hmtx_table_data = NULL, *loca_table_data = NULL;
+ char *glyf_table_data = NULL;
+ ULONG hmtx_table_size, loca_table_size, glyf_table_size;
+ /* some information available from other TrueType table */
+ struct tt_head_table *head = NULL;
+ struct tt_hhea_table *hhea = NULL;
+ struct tt_maxp_table *maxp = NULL;
+ struct tt_longMetrics *hmtx, *vmtx = NULL;
+ struct tt_os2__table *os2;
+ /* temp */
+ ULONG *location, offset;
+ long i;
+ USHORT *w_stat; /* Estimate most frequently appeared width */
+
+ ASSERT(g);
+
+ if (sfont->type != SFNT_TYPE_TRUETYPE &&
+ sfont->type != SFNT_TYPE_TTC)
+ TT_ERROR("Invalid font type");
+
+ if (g->num_glyphs > NUM_GLYPH_LIMIT)
+ TT_ERROR("Too many glyphs.");
+
+ /*
+ * Read head, hhea, maxp, loca:
+ *
+ * unitsPerEm --> head
+ * numHMetrics --> hhea
+ * indexToLocFormat --> head
+ * numGlyphs --> maxp
+ */
+ head = tt_read_head_table(sfont);
+ hhea = tt_read_hhea_table(sfont);
+ maxp = tt_read_maxp_table(sfont);
+
+ if (hhea->metricDataFormat != 0)
+ TT_ERROR("Unknown metricDataFormat.");
+
+ g->emsize = head->unitsPerEm;
+
+ sfnt_locate_table(sfont, "hmtx");
+ hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
+
+ os2 = tt_read_os2__table(sfont);
+ if (os2) {
+ g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
+ g->default_tsb = g->default_advh - os2->sTypoAscender;
+ }
+
+ if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
+ struct tt_vhea_table *vhea;
+ vhea = tt_read_vhea_table(sfont);
+ sfnt_locate_table(sfont, "vmtx");
+ vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics);
+ RELEASE(vhea);
+ } else {
+ vmtx = NULL;
+ }
+
+ sfnt_locate_table(sfont, "loca");
+ location = NEW(maxp->numGlyphs + 1, ULONG);
+ if (head->indexToLocFormat == 0) {
+ for (i = 0; i <= maxp->numGlyphs; i++)
+ location[i] = 2*((ULONG) sfnt_get_ushort(sfont));
+ } else if (head->indexToLocFormat == 1) {
+ for (i = 0; i <= maxp->numGlyphs; i++)
+ location[i] = sfnt_get_ulong(sfont);
+ } else {
+ TT_ERROR("Unknown IndexToLocFormat.");
+ }
+
+ w_stat = NEW(g->emsize+2, USHORT);
+ memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2));
+ /*
+ * Read glyf table.
+ */
+ offset = sfnt_locate_table(sfont, "glyf");
+ /*
+ * The num_glyphs may grow when composite glyph is found.
+ * A component of glyph refered by a composite glyph is appended
+ * to used_glyphs if it is not already registered in used_glyphs.
+ * Glyph programs of composite glyphs are modified so that it
+ * correctly refer to new gid of their components.
+ */
+ for (i = 0; i < NUM_GLYPH_LIMIT; i++) {
+ USHORT gid; /* old gid */
+ ULONG loc, len;
+ BYTE *p, *endptr;
+ SHORT number_of_contours;
+
+ if (i >= g->num_glyphs) /* finished */
+ break;
+
+ gid = g->gd[i].ogid;
+ if (gid >= maxp->numGlyphs)
+ TT_ERROR("Invalid glyph index (gid %u)", gid);
+
+ loc = location[gid];
+ len = location[gid+1] - loc;
+ g->gd[i].advw = hmtx[gid].advance;
+ g->gd[i].lsb = hmtx[gid].sideBearing;
+ if (vmtx) {
+ g->gd[i].advh = vmtx[gid].advance;
+ g->gd[i].tsb = vmtx[gid].sideBearing;
+ } else {
+ g->gd[i].advh = g->default_advh;
+ g->gd[i].tsb = g->default_tsb;
+ }
+ g->gd[i].length = len;
+ g->gd[i].data = NULL;
+ if (g->gd[i].advw <= g->emsize) {
+ w_stat[g->gd[i].advw] += 1;
+ } else {
+ w_stat[g->emsize+1] += 1; /* larger than em */
+ }
+
+ if (len == 0) { /* Does not contains any data. */
+ continue;
+ } else if (len < 10) {
+ TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
+ }
+
+ g->gd[i].data = p = NEW(len, BYTE);
+ endptr = p + len;
+
+ sfnt_seek_set(sfont, offset+loc);
+ number_of_contours = sfnt_get_short(sfont);
+ p += sfnt_put_short(p, number_of_contours);
+
+ /* BoundingBox: FWord x 4 */
+ g->gd[i].llx = sfnt_get_short(sfont);
+ g->gd[i].lly = sfnt_get_short(sfont);
+ g->gd[i].urx = sfnt_get_short(sfont);
+ g->gd[i].ury = sfnt_get_short(sfont);
+ /* _FIXME_ */
+#if 1
+ if (!vmtx) /* vertOriginY == sTypeAscender */
+ g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
+#endif
+ p += sfnt_put_short(p, g->gd[i].llx);
+ p += sfnt_put_short(p, g->gd[i].lly);
+ p += sfnt_put_short(p, g->gd[i].urx);
+ p += sfnt_put_short(p, g->gd[i].ury);
+
+ /* Read evrything else. */
+ sfnt_read(p, len - 10, sfont);
+ /*
+ * Fix GIDs of composite glyphs.
+ */
+ if (number_of_contours < 0) {
+ USHORT flags, cgid, new_gid; /* flag, gid of a component */
+ do {
+ if (p >= endptr)
+ TT_ERROR("Invalid TrueType glyph data (gid %u): %u bytes", gid, (unsigned int)len);
+ /*
+ * Flags and gid of component glyph are both USHORT.
+ */
+ flags = ((*p) << 8)| *(p+1);
+ p += 2;
+ cgid = ((*p) << 8)| *(p+1);
+ if (cgid >= maxp->numGlyphs) {
+ TT_ERROR("Invalid gid (%u > %u) in composite glyph %u.", cgid, maxp->numGlyphs, gid);
+ }
+ new_gid = tt_find_glyph(g, cgid);
+ if (new_gid == 0) {
+ new_gid = tt_add_glyph(g, cgid, find_empty_slot(g));
+ }
+ p += sfnt_put_ushort(p, new_gid);
+ /*
+ * Just skip remaining part.
+ */
+ p += (flags & ARG_1_AND_2_ARE_WORDS) ? 4 : 2;
+ if (flags & WE_HAVE_A_SCALE) /* F2Dot14 */
+ p += 2;
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) /* F2Dot14 x 2 */
+ p += 4;
+ else if (flags & WE_HAVE_A_TWO_BY_TWO) /* F2Dot14 x 4 */
+ p += 8;
+ } while (flags & MORE_COMPONENT);
+ /*
+ * TrueType instructions comes here:
+ * length_of_instruction (ushort)
+ * instruction (byte * length_of_instruction)
+ */
+ }
+ }
+ RELEASE(location);
+ RELEASE(hmtx);
+ if (vmtx)
+ RELEASE(vmtx);
+
+ {
+ int max_count = -1;
+
+ g->dw = g->gd[0].advw;
+ for (i = 0; i < g->emsize + 1; i++) {
+ if (w_stat[i] > max_count) {
+ max_count = w_stat[i];
+ g->dw = i;
+ }
+ }
+ }
+ RELEASE(w_stat);
+
+ qsort(g->gd, g->num_glyphs, sizeof(struct tt_glyph_desc), glyf_cmp);
+ {
+ USHORT prev, last_advw;
+ char *p, *q;
+ int padlen, num_hm_known;
+
+ glyf_table_size = 0UL;
+ num_hm_known = 0;
+ last_advw = g->gd[g->num_glyphs - 1].advw;
+ for (i = g->num_glyphs - 1; i >= 0; i--) {
+ padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
+ glyf_table_size += g->gd[i].length + padlen;
+ if (!num_hm_known && last_advw != g->gd[i].advw) {
+ hhea->numberOfHMetrics = g->gd[i].gid + 2;
+ num_hm_known = 1;
+ }
+ }
+ /* All advance widths are same. */
+ if (!num_hm_known) {
+ hhea->numberOfHMetrics = 1;
+ }
+ hmtx_table_size = hhea->numberOfHMetrics * 2 + (g->last_gid + 1) * 2;
+
+ /*
+ * Choosing short format does not always give good result
+ * when compressed. Sometimes increases size.
+ */
+ if (glyf_table_size < 0x20000UL) {
+ head->indexToLocFormat = 0;
+ loca_table_size = (g->last_gid + 2)*2;
+ } else {
+ head->indexToLocFormat = 1;
+ loca_table_size = (g->last_gid + 2)*4;
+ }
+
+ hmtx_table_data = p = NEW(hmtx_table_size, char);
+ loca_table_data = q = NEW(loca_table_size, char);
+ glyf_table_data = NEW(glyf_table_size, char);
+
+ offset = 0UL; prev = 0;
+ for (i = 0; i < g->num_glyphs; i++) {
+ long gap, j;
+ gap = (long) g->gd[i].gid - prev - 1;
+ for (j = 1; j <= gap; j++) {
+ if (prev + j == hhea->numberOfHMetrics - 1) {
+ p += sfnt_put_ushort(p, last_advw);
+ } else if (prev + j < hhea->numberOfHMetrics) {
+ p += sfnt_put_ushort(p, 0);
+ }
+ p += sfnt_put_short (p, 0);
+ if (head->indexToLocFormat == 0) {
+ q += sfnt_put_ushort(q, (USHORT) (offset/2));
+ } else {
+ q += sfnt_put_ulong(q, offset);
+ }
+ }
+ padlen = (g->gd[i].length % 4) ? (4 - (g->gd[i].length % 4)) : 0;
+ if (g->gd[i].gid < hhea->numberOfHMetrics) {
+ p += sfnt_put_ushort(p, g->gd[i].advw);
+ }
+ p += sfnt_put_short (p, g->gd[i].lsb);
+ if (head->indexToLocFormat == 0) {
+ q += sfnt_put_ushort(q, (USHORT) (offset/2));
+ } else {
+ q += sfnt_put_ulong(q, offset);
+ }
+ memset(glyf_table_data + offset, 0, g->gd[i].length + padlen);
+ memcpy(glyf_table_data + offset, g->gd[i].data, g->gd[i].length);
+ offset += g->gd[i].length + padlen;
+ prev = g->gd[i].gid;
+ /* free data here since it consume much memory */
+ RELEASE(g->gd[i].data);
+ g->gd[i].length = 0; g->gd[i].data = NULL;
+ }
+ if (head->indexToLocFormat == 0) {
+ q += sfnt_put_ushort(q, (USHORT) (offset/2));
+ } else {
+ q += sfnt_put_ulong(q, offset);
+ }
+
+ sfnt_set_table(sfont, "hmtx", (char *) hmtx_table_data, hmtx_table_size);
+ sfnt_set_table(sfont, "loca", (char *) loca_table_data, loca_table_size);
+ sfnt_set_table(sfont, "glyf", (char *) glyf_table_data, glyf_table_size);
+ }
+
+ head->checkSumAdjustment = 0;
+ maxp->numGlyphs = g->last_gid + 1;
+
+ /* TODO */
+ sfnt_set_table(sfont, "maxp", tt_pack_maxp_table(maxp), TT_MAXP_TABLE_SIZE);
+ sfnt_set_table(sfont, "hhea", tt_pack_hhea_table(hhea), TT_HHEA_TABLE_SIZE);
+ sfnt_set_table(sfont, "head", tt_pack_head_table(head), TT_HEAD_TABLE_SIZE);
+ RELEASE(maxp);
+ RELEASE(hhea);
+ RELEASE(head);
+ if (os2)
+ RELEASE(os2);
+
+ return 0;
+}
+
+int
+tt_get_metrics (sfnt *sfont, struct tt_glyphs *g)
+{
+ struct tt_head_table *head = NULL;
+ struct tt_hhea_table *hhea = NULL;
+ struct tt_maxp_table *maxp = NULL;
+ struct tt_longMetrics *hmtx, *vmtx = NULL;
+ struct tt_os2__table *os2;
+ /* temp */
+ ULONG *location, offset;
+ long i;
+ USHORT *w_stat;
+
+ ASSERT(g);
+
+ if (sfont == NULL ||
+#ifdef XETEX
+ sfont->ft_face == NULL
+#elif defined(pdfTeX)
+ sfont->buffer == NULL
+#else
+ sfont->stream == NULL
+#endif
+ )
+ TT_ERROR("File not opened.");
+
+ if (sfont->type != SFNT_TYPE_TRUETYPE &&
+ sfont->type != SFNT_TYPE_TTC)
+ TT_ERROR("Invalid font type");
+
+ /*
+ * Read head, hhea, maxp, loca:
+ *
+ * unitsPerEm --> head
+ * numHMetrics --> hhea
+ * indexToLocFormat --> head
+ * numGlyphs --> maxp
+ */
+ head = tt_read_head_table(sfont);
+ hhea = tt_read_hhea_table(sfont);
+ maxp = tt_read_maxp_table(sfont);
+
+ if (hhea->metricDataFormat != 0)
+ TT_ERROR("Unknown metricDataFormat.");
+
+ g->emsize = head->unitsPerEm;
+
+ sfnt_locate_table(sfont, "hmtx");
+ hmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, hhea->numberOfHMetrics);
+
+ os2 = tt_read_os2__table(sfont);
+ g->default_advh = os2->sTypoAscender - os2->sTypoDescender;
+ g->default_tsb = g->default_advh - os2->sTypoAscender;
+
+ if (sfnt_find_table_pos(sfont, "vmtx") > 0) {
+ struct tt_vhea_table *vhea;
+ vhea = tt_read_vhea_table(sfont);
+ sfnt_locate_table(sfont, "vmtx");
+ vmtx = tt_read_longMetrics(sfont, maxp->numGlyphs, vhea->numOfLongVerMetrics);
+ RELEASE(vhea);
+ } else {
+ vmtx = NULL;
+ }
+
+ sfnt_locate_table(sfont, "loca");
+ location = NEW(maxp->numGlyphs + 1, ULONG);
+ if (head->indexToLocFormat == 0) {
+ for (i = 0; i <= maxp->numGlyphs; i++)
+ location[i] = 2*((ULONG) sfnt_get_ushort(sfont));
+ } else if (head->indexToLocFormat == 1) {
+ for (i = 0; i <= maxp->numGlyphs; i++)
+ location[i] = sfnt_get_ulong(sfont);
+ } else {
+ TT_ERROR("Unknown IndexToLocFormat.");
+ }
+
+ w_stat = NEW(g->emsize+2, USHORT);
+ memset(w_stat, 0, sizeof(USHORT)*(g->emsize+2));
+ /*
+ * Read glyf table.
+ */
+ offset = sfnt_locate_table(sfont, "glyf");
+ for (i = 0; i < g->num_glyphs; i++) {
+ USHORT gid; /* old gid */
+ ULONG loc, len;
+ SHORT number_of_contours;
+
+ gid = g->gd[i].ogid;
+ if (gid >= maxp->numGlyphs)
+ TT_ERROR("Invalid glyph index (gid %u)", gid);
+
+ loc = location[gid];
+ len = location[gid+1] - loc;
+ g->gd[i].advw = hmtx[gid].advance;
+ g->gd[i].lsb = hmtx[gid].sideBearing;
+ if (vmtx) {
+ g->gd[i].advh = vmtx[gid].advance;
+ g->gd[i].tsb = vmtx[gid].sideBearing;
+ } else {
+ g->gd[i].advh = g->default_advh;
+ g->gd[i].tsb = g->default_tsb;
+ }
+ g->gd[i].length = len;
+ g->gd[i].data = NULL;
+
+ if (g->gd[i].advw <= g->emsize) {
+ w_stat[g->gd[i].advw] += 1;
+ } else {
+ w_stat[g->emsize+1] += 1; /* larger than em */
+ }
+
+ if (len == 0) { /* Does not contains any data. */
+ continue;
+ } else if (len < 10) {
+ TT_ERROR("Invalid TrueType glyph data (gid %u).", gid);
+ }
+
+ sfnt_seek_set(sfont, offset+loc);
+ number_of_contours = sfnt_get_short(sfont);
+
+ /* BoundingBox: FWord x 4 */
+ g->gd[i].llx = sfnt_get_short(sfont);
+ g->gd[i].lly = sfnt_get_short(sfont);
+ g->gd[i].urx = sfnt_get_short(sfont);
+ g->gd[i].ury = sfnt_get_short(sfont);
+ /* _FIXME_ */
+#if 1
+ if (!vmtx) /* vertOriginY == sTypeAscender */
+ g->gd[i].tsb = g->default_advh - g->default_tsb - g->gd[i].ury;
+#endif
+ }
+ RELEASE(location);
+ RELEASE(hmtx);
+ RELEASE(maxp);
+ RELEASE(hhea);
+ RELEASE(head);
+ RELEASE(os2);
+
+ if (vmtx)
+ RELEASE(vmtx);
+
+ {
+ int max_count = -1;
+
+ g->dw = g->gd[0].advw;
+ for (i = 0; i < g->emsize + 1; i++) {
+ if (w_stat[i] > max_count) {
+ max_count = w_stat[i];
+ g->dw = i;
+ }
+ }
+ }
+ RELEASE(w_stat);
+
+
+ return 0;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/tt_glyf.h b/Build/source/texk/web2c/luatexdir/font/tt_glyf.h
new file mode 100644
index 00000000000..cf33af6733f
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tt_glyf.h
@@ -0,0 +1,60 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/tt_glyf.h,v 1.1 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifndef _TT_GLYF_H_
+#define _TT_GLYF_H_
+
+struct tt_glyph_desc
+{
+ USHORT gid;
+ USHORT ogid; /* GID in original font */
+ USHORT advw, advh;
+ SHORT lsb, tsb;
+ SHORT llx, lly, urx, ury;
+ ULONG length;
+ BYTE *data;
+};
+
+struct tt_glyphs
+{
+ USHORT num_glyphs;
+ USHORT max_glyphs;
+ USHORT last_gid;
+ USHORT emsize;
+ USHORT dw; /* optimal value for DW */
+ USHORT default_advh; /* default value */
+ SHORT default_tsb; /* default value */
+ struct tt_glyph_desc *gd;
+ unsigned char *used_slot;
+};
+
+extern struct tt_glyphs *tt_build_init (void);
+extern void tt_build_finish (struct tt_glyphs *g);
+
+extern USHORT tt_add_glyph (struct tt_glyphs *g, USHORT gid, USHORT new_gid);
+extern USHORT tt_get_index (struct tt_glyphs *g, USHORT gid);
+extern USHORT tt_find_glyph (struct tt_glyphs *g, USHORT gid);
+
+extern int tt_build_tables (sfnt *sfont, struct tt_glyphs *g);
+extern int tt_get_metrics (sfnt *sfont, struct tt_glyphs *g);
+
+#endif /* _TT_GLYF_H_ */
diff --git a/Build/source/texk/web2c/luatexdir/font/tt_table.c b/Build/source/texk/web2c/luatexdir/font/tt_table.c
new file mode 100644
index 00000000000..4f82552d9df
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tt_table.c
@@ -0,0 +1,483 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.c,v 1.7 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#include <stdio.h>
+
+#ifndef pdfTeX
+#include "system.h"
+#include "error.h"
+#include "mem.h"
+#include "mfileio.h"
+#else
+extern void pdftex_fail (const char *fmt, ...); /* utils.c */
+#endif
+
+#include "sfnt.h"
+#include "tt_table.h"
+
+/*
+ tables contains information refered by other tables
+ maxp->numGlyphs, etc --> loca, etc
+ hhea->numberOfHMetrics --> hmtx
+ head->indexToLocFormat --> loca
+ head->glyphDataFormat --> glyf
+*/
+
+char *tt_pack_head_table (struct tt_head_table *table)
+{
+ int i;
+ char *p, *data;
+
+ if (table == NULL)
+ TT_ERROR("passed NULL pointer\n");
+
+ p = data = NEW(TT_HEAD_TABLE_SIZE, char);
+ p += sfnt_put_ulong(p, table->version);
+ p += sfnt_put_ulong(p, table->fontRevision);
+ p += sfnt_put_ulong(p, table->checkSumAdjustment);
+ p += sfnt_put_ulong(p, table->magicNumber);
+ p += sfnt_put_ushort(p, table->flags);
+ p += sfnt_put_ushort(p, table->unitsPerEm);
+ for (i=0; i<8; i++) {
+ *(p++) = (table->created)[i];
+ }
+ for (i=0; i<8; i++) {
+ *(p++) = (table->modified)[i];
+ }
+ p += sfnt_put_short(p, table->xMin);
+ p += sfnt_put_short(p, table->yMin);
+ p += sfnt_put_short(p, table->xMax);
+ p += sfnt_put_short(p, table->yMax);
+ p += sfnt_put_ushort(p, table->macStyle);
+ p += sfnt_put_ushort(p, table->lowestRecPPEM);
+ p += sfnt_put_short(p, table->fontDirectionHint);
+ p += sfnt_put_short(p, table->indexToLocFormat);
+ p += sfnt_put_short(p, table->glyphDataFormat);
+
+ return data;
+}
+
+struct tt_head_table *tt_read_head_table (sfnt *sfont)
+{
+ int i;
+ struct tt_head_table *table = NULL;
+
+ table = NEW(1, struct tt_head_table);
+
+ sfnt_locate_table(sfont, "head");
+
+ table->version = sfnt_get_ulong(sfont);
+ table->fontRevision = sfnt_get_ulong(sfont);
+ table->checkSumAdjustment = sfnt_get_ulong(sfont);
+ table->magicNumber = sfnt_get_ulong(sfont);
+ table->flags = sfnt_get_ushort(sfont);
+ table->unitsPerEm = sfnt_get_ushort(sfont);
+ for (i=0; i<8; i++) {
+ (table->created)[i] = sfnt_get_byte (sfont);
+ }
+ for (i=0; i<8; i++) {
+ (table->modified)[i] = sfnt_get_byte (sfont);
+ }
+ table->xMin = sfnt_get_short(sfont);
+ table->yMin = sfnt_get_short(sfont);
+ table->xMax = sfnt_get_short(sfont);
+ table->yMax = sfnt_get_short(sfont);
+ table->macStyle = sfnt_get_short(sfont);
+ table->lowestRecPPEM = sfnt_get_short(sfont);
+ table->fontDirectionHint = sfnt_get_short(sfont);
+ table->indexToLocFormat = sfnt_get_short(sfont);
+ table->glyphDataFormat = sfnt_get_short(sfont);
+
+ return table;
+}
+
+char *tt_pack_maxp_table (struct tt_maxp_table *table)
+{
+ char *p, *data;
+
+ p = data = NEW(TT_MAXP_TABLE_SIZE, char);
+ p += sfnt_put_ulong(p, table->version);
+ p += sfnt_put_ushort(p, table->numGlyphs);
+ p += sfnt_put_ushort(p, table->maxPoints);
+ p += sfnt_put_ushort(p, table->maxContours);
+ p += sfnt_put_ushort(p, table->maxComponentPoints);
+ p += sfnt_put_ushort(p, table->maxComponentContours);
+ p += sfnt_put_ushort(p, table->maxZones);
+ p += sfnt_put_ushort(p, table->maxTwilightPoints);
+ p += sfnt_put_ushort(p, table->maxStorage);
+ p += sfnt_put_ushort(p, table->maxFunctionDefs);
+ p += sfnt_put_ushort(p, table->maxInstructionDefs);
+ p += sfnt_put_ushort(p, table->maxStackElements);
+ p += sfnt_put_ushort(p, table->maxSizeOfInstructions);
+ p += sfnt_put_ushort(p, table->maxComponentElements);
+ p += sfnt_put_ushort(p, table->maxComponentDepth);
+
+ return data;
+}
+
+struct tt_maxp_table *tt_read_maxp_table (sfnt *sfont)
+{
+ struct tt_maxp_table *table = NULL;
+
+ table = NEW(1, struct tt_maxp_table);
+
+ sfnt_locate_table(sfont, "maxp");
+ table->version = sfnt_get_ulong(sfont);
+ table->numGlyphs = sfnt_get_ushort(sfont);
+ table->maxPoints = sfnt_get_ushort(sfont);
+ table->maxContours = sfnt_get_ushort(sfont);
+ table->maxComponentPoints = sfnt_get_ushort(sfont);
+ table->maxComponentContours = sfnt_get_ushort(sfont);
+ table->maxZones = sfnt_get_ushort(sfont);
+ table->maxTwilightPoints = sfnt_get_ushort(sfont);
+ table->maxStorage = sfnt_get_ushort(sfont);
+ table->maxFunctionDefs = sfnt_get_ushort(sfont);
+ table->maxInstructionDefs = sfnt_get_ushort(sfont);
+ table->maxStackElements = sfnt_get_ushort(sfont);
+ table->maxSizeOfInstructions = sfnt_get_ushort(sfont);
+ table->maxComponentElements = sfnt_get_ushort(sfont);
+ table->maxComponentDepth = sfnt_get_ushort(sfont);
+
+ return table;
+}
+
+char *tt_pack_hhea_table (struct tt_hhea_table *table)
+{
+ int i;
+ char *p, *data;
+
+ p = data = NEW(TT_HHEA_TABLE_SIZE, char);
+ p += sfnt_put_ulong(p, table->version);
+ p += sfnt_put_short(p, table->Ascender);
+ p += sfnt_put_short(p, table->Descender);
+ p += sfnt_put_short(p, table->LineGap);
+ p += sfnt_put_ushort(p, table->advanceWidthMax);
+ p += sfnt_put_short(p, table->minLeftSideBearing);
+ p += sfnt_put_short(p, table->minRightSideBearing);
+ p += sfnt_put_short(p, table->xMaxExtent);
+ p += sfnt_put_short(p, table->caretSlopeRise);
+ p += sfnt_put_short(p, table->caretSlopeRun);
+ for (i = 0; i < 5; i++) {
+ p += sfnt_put_short(p, table->reserved[i]);
+ }
+ p += sfnt_put_short(p, table->metricDataFormat);
+ p += sfnt_put_ushort(p, table->numberOfHMetrics);
+
+ return data;
+}
+
+struct tt_hhea_table *
+tt_read_hhea_table (sfnt *sfont)
+{
+ int i;
+ struct tt_hhea_table *table = NULL;
+
+ table = NEW(1, struct tt_hhea_table);
+
+ sfnt_locate_table(sfont, "hhea");
+ table->version = sfnt_get_ulong(sfont);
+ table->Ascender = sfnt_get_short (sfont);
+ table->Descender = sfnt_get_short(sfont);
+ table->LineGap = sfnt_get_short(sfont);
+ table->advanceWidthMax = sfnt_get_ushort(sfont);
+ table->minLeftSideBearing = sfnt_get_short(sfont);
+ table->minRightSideBearing = sfnt_get_short(sfont);
+ table->xMaxExtent = sfnt_get_short(sfont);
+ table->caretSlopeRise = sfnt_get_short(sfont);
+ table->caretSlopeRun = sfnt_get_short(sfont);
+ for(i = 0; i < 5; i++) {
+ table->reserved[i] = sfnt_get_short(sfont);
+ }
+ table->metricDataFormat = sfnt_get_short(sfont);
+ if (table->metricDataFormat != 0)
+ TT_ERROR("unknown metricDaraFormat");
+ table->numberOfHMetrics = sfnt_get_ushort(sfont);
+
+ return table;
+}
+
+/* vhea */
+char *
+tt_pack_vhea_table (struct tt_vhea_table *table)
+{
+ int i;
+ char *p, *data;
+
+ p = data = NEW(TT_VHEA_TABLE_SIZE, char);
+ p += sfnt_put_ulong(p, table->version);
+ p += sfnt_put_short(p, table->vertTypoAscender);
+ p += sfnt_put_short(p, table->vertTypoDescender);
+ p += sfnt_put_short(p, table->vertTypoLineGap);
+ p += sfnt_put_short(p, table->advanceHeightMax); /* ushort ? */
+ p += sfnt_put_short(p, table->minTopSideBearing);
+ p += sfnt_put_short(p, table->minBottomSideBearing);
+ p += sfnt_put_short(p, table->yMaxExtent);
+ p += sfnt_put_short(p, table->caretSlopeRise);
+ p += sfnt_put_short(p, table->caretSlopeRun);
+ p += sfnt_put_short(p, table->caretOffset);
+ for(i = 0; i < 5; i++) {
+ p += sfnt_put_short(p, table->reserved[i]);
+ }
+ p += sfnt_put_ushort(p, table->numOfLongVerMetrics);
+
+ return data;
+}
+
+struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont)
+{
+ int i;
+ struct tt_vhea_table *table = NULL;
+
+ table = NEW(1, struct tt_vhea_table);
+
+ sfnt_locate_table(sfont, "vhea");
+ table->version = sfnt_get_ulong(sfont);
+ table->vertTypoAscender = sfnt_get_short (sfont);
+ table->vertTypoDescender = sfnt_get_short(sfont);
+ table->vertTypoLineGap = sfnt_get_short(sfont);
+ table->advanceHeightMax = sfnt_get_short(sfont); /* ushort ? */
+ table->minTopSideBearing = sfnt_get_short(sfont);
+ table->minBottomSideBearing = sfnt_get_short(sfont);
+ table->yMaxExtent = sfnt_get_short(sfont);
+ table->caretSlopeRise = sfnt_get_short(sfont);
+ table->caretSlopeRun = sfnt_get_short(sfont);
+ table->caretOffset = sfnt_get_short(sfont);
+ for(i=0;i<5;i++) {
+ (table->reserved)[i] = sfnt_get_short(sfont);
+ }
+ table->numOfLongVerMetrics = sfnt_get_ushort(sfont);
+
+ return table;
+}
+
+
+struct tt_VORG_table *
+tt_read_VORG_table (sfnt *sfont)
+{
+ struct tt_VORG_table *vorg;
+ ULONG offset;
+ USHORT i;
+
+ offset = sfnt_find_table_pos(sfont, "VORG");
+
+ if (offset > 0) {
+ vorg = NEW(1, struct tt_VORG_table);
+
+ sfnt_locate_table(sfont, "VORG");
+ if (sfnt_get_ushort(sfont) != 1 ||
+ sfnt_get_ushort(sfont) != 0)
+ TT_ERROR("Unsupported VORG version.");
+
+ vorg->defaultVertOriginY = sfnt_get_short(sfont);
+ vorg->numVertOriginYMetrics = sfnt_get_ushort(sfont);
+ vorg->vertOriginYMetrics = NEW(vorg->numVertOriginYMetrics,
+ struct tt_vertOriginYMetrics);
+ /*
+ * The vertOriginYMetrics array must be sorted in increasing
+ * glyphIndex order.
+ */
+ for (i = 0;
+ i < vorg->numVertOriginYMetrics; i++) {
+ vorg->vertOriginYMetrics[i].glyphIndex = sfnt_get_ushort(sfont);
+ vorg->vertOriginYMetrics[i].vertOriginY = sfnt_get_short(sfont);
+ }
+ } else {
+ vorg = NULL;
+ }
+
+ return vorg;
+}
+
+/*
+ * hmtx and vmtx
+ *
+ * Reading/writing hmtx and vmtx depend on other tables, maxp and hhea/vhea.
+ */
+
+struct tt_longMetrics *
+tt_read_longMetrics (sfnt *sfont, USHORT numGlyphs, USHORT numLongMetrics)
+{
+ struct tt_longMetrics *m;
+ USHORT gid, last_adv = 0;
+
+ m = NEW(numGlyphs, struct tt_longMetrics);
+ for (gid = 0; gid < numGlyphs; gid++) {
+ if (gid < numLongMetrics)
+ last_adv = sfnt_get_ushort(sfont);
+ m[gid].sideBearing = sfnt_get_short(sfont);
+ m[gid].advance = last_adv;
+ }
+
+ return m;
+}
+
+/* OS/2 table */
+/* this table may not exist */
+struct tt_os2__table *
+tt_read_os2__table (sfnt *sfont)
+{
+ struct tt_os2__table *table = NULL;
+ int i;
+
+ if (sfnt_find_table_pos(sfont, "OS/2") == 0)
+ return NULL;
+
+ sfnt_locate_table(sfont, "OS/2");
+
+ table = NEW(1, struct tt_os2__table);
+
+ table->version = sfnt_get_ushort(sfont);
+ table->xAvgCharWidth = sfnt_get_short(sfont);
+ table->usWeightClass = sfnt_get_ushort(sfont);
+ table->usWidthClass = sfnt_get_ushort(sfont);
+ table->fsType = sfnt_get_short(sfont);
+ table->ySubscriptXSize = sfnt_get_short(sfont);
+ table->ySubscriptYSize = sfnt_get_short(sfont);
+ table->ySubscriptXOffset = sfnt_get_short(sfont);
+ table->ySubscriptYOffset = sfnt_get_short(sfont);
+ table->ySuperscriptXSize = sfnt_get_short(sfont);
+ table->ySuperscriptYSize = sfnt_get_short(sfont);
+ table->ySuperscriptXOffset = sfnt_get_short(sfont);
+ table->ySuperscriptYOffset = sfnt_get_short(sfont);
+ table->yStrikeoutSize = sfnt_get_short(sfont);
+ table->yStrikeoutPosition = sfnt_get_short(sfont);
+ table->sFamilyClass = sfnt_get_short(sfont);
+ for (i = 0; i < 10; i++) {
+ table->panose[i] = sfnt_get_byte(sfont);
+ }
+ table->ulUnicodeRange1 = sfnt_get_ulong(sfont);
+ table->ulUnicodeRange2 = sfnt_get_ulong(sfont);
+ table->ulUnicodeRange3 = sfnt_get_ulong(sfont);
+ table->ulUnicodeRange4 = sfnt_get_ulong(sfont);
+ for (i = 0; i < 4; i++) {
+ table->achVendID[i] = sfnt_get_char(sfont);
+ }
+ table->fsSelection = sfnt_get_ushort(sfont);
+ table->usFirstCharIndex = sfnt_get_ushort(sfont);
+ table->usLastCharIndex = sfnt_get_ushort(sfont);
+ table->sTypoAscender = sfnt_get_short(sfont);
+ table->sTypoDescender = sfnt_get_short(sfont);
+ table->sTypoLineGap = sfnt_get_short(sfont);
+ table->usWinAscent = sfnt_get_ushort(sfont);
+ table->usWinDescent = sfnt_get_ushort(sfont);
+ table->ulCodePageRange1 = sfnt_get_ulong(sfont);
+ table->ulCodePageRange2 = sfnt_get_ulong(sfont);
+ if (table->version == 0x0002) {
+ table->sxHeight = sfnt_get_short(sfont);
+ table->sCapHeight = sfnt_get_short(sfont);
+ table->usDefaultChar = sfnt_get_ushort(sfont);
+ table->usBreakChar = sfnt_get_ushort(sfont);
+ table->usMaxContext = sfnt_get_ushort(sfont);
+ }
+
+ return table;
+}
+
+USHORT
+tt_get_name (sfnt *sfont, char *dest, USHORT destlen,
+ USHORT plat_id, USHORT enco_id,
+ USHORT lang_id, USHORT name_id)
+{
+ USHORT length = 0;
+ USHORT num_names, string_offset;
+ ULONG name_offset;
+ int i;
+
+ name_offset = sfnt_locate_table (sfont, "name");
+
+ if (sfnt_get_ushort(sfont))
+ TT_ERROR ("Expecting zero");
+
+ num_names = sfnt_get_ushort(sfont);
+ string_offset = sfnt_get_ushort(sfont);
+ for (i=0;i<num_names;i++) {
+ USHORT p_id, e_id, n_id, l_id;
+ USHORT offset;
+
+ p_id = sfnt_get_ushort(sfont);
+ e_id = sfnt_get_ushort(sfont);
+ l_id = sfnt_get_ushort(sfont);
+ n_id = sfnt_get_ushort(sfont);
+ length = sfnt_get_ushort(sfont);
+ offset = sfnt_get_ushort(sfont);
+ /* language ID value 0xffffu for `accept any language ID' */
+ if ((p_id == plat_id) && (e_id == enco_id) &&
+ (lang_id == 0xffffu || l_id == lang_id) && (n_id == name_id)) {
+ if (length > destlen - 1) {
+ fprintf(stderr, "\n** Notice: Name string too long. Truncating **\n");
+ length = destlen - 1;
+ }
+ sfnt_seek_set (sfont, name_offset+string_offset+offset);
+ sfnt_read((unsigned char*)dest, length, sfont);
+ dest[length] = '\0';
+ break;
+ }
+ }
+ if (i == num_names) {
+ length = 0;
+ }
+
+ return length;
+}
+
+USHORT
+tt_get_ps_fontname (sfnt *sfont, char *dest, USHORT destlen)
+{
+ USHORT namelen = 0;
+
+#ifdef XETEX
+
+ const char* name = FT_Get_Postscript_Name(sfont->ft_face);
+ namelen = strlen(name);
+ if (namelen > destlen - 1) {
+ strncpy(dest, name, destlen - 1);
+ dest[destlen] = 0;
+ }
+ else
+ strcpy(dest, name);
+
+#else
+
+ /* First try Mac-Roman PS name and then Win-Unicode PS name */
+ if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 6)) != 0 ||
+ (namelen = tt_get_name(sfont, dest, destlen, 3, 1, 0x409u, 6)) != 0 ||
+ (namelen = tt_get_name(sfont, dest, destlen, 3, 5, 0x412u, 6)) != 0)
+ return namelen;
+
+ fprintf(stderr, "\n** Warning: No valid PostScript name available **\n");
+ /*
+ Wrokaround for some bad TTfonts:
+ Language ID value 0xffffu for `accept any language ID'
+ */
+ if ((namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0xffffu, 6)) == 0) {
+ /*
+ Finally falling back to Mac Roman name field.
+ Warning: Some bad Japanese TTfonts using SJIS encoded string in the
+ Mac Roman name field.
+ */
+ namelen = tt_get_name(sfont, dest, destlen, 1, 0, 0, 1);
+ }
+
+#endif
+
+ return namelen;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/tt_table.h b/Build/source/texk/web2c/luatexdir/font/tt_table.h
new file mode 100644
index 00000000000..ffb2c5b8f45
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/tt_table.h
@@ -0,0 +1,193 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/tt_table.h,v 1.6 2004/09/11 14:50:29 hirata Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifndef _TT_TABLE_H_
+#define _TT_TABLE_H_
+
+#include "sfnt.h"
+
+#define TT_HEAD_TABLE_SIZE 54UL
+#define TT_MAXP_TABLE_SIZE 32UL
+#define TT_HHEA_TABLE_SIZE 36UL
+#define TT_VHEA_TABLE_SIZE 36UL
+
+struct tt_head_table
+{
+ Fixed version;
+ Fixed fontRevision;
+ ULONG checkSumAdjustment;
+ ULONG magicNumber;
+ USHORT flags;
+ USHORT unitsPerEm;
+ BYTE created[8];
+ BYTE modified[8];
+ FWord xMin, yMin, xMax, yMax;
+ USHORT macStyle;
+ USHORT lowestRecPPEM;
+ SHORT fontDirectionHint;
+ SHORT indexToLocFormat;
+ SHORT glyphDataFormat;
+};
+
+struct tt_hhea_table
+{
+ Fixed version;
+ FWord Ascender;
+ FWord Descender;
+ FWord LineGap;
+ uFWord advanceWidthMax;
+ FWord minLeftSideBearing;
+ FWord minRightSideBearing;
+ FWord xMaxExtent;
+ SHORT caretSlopeRise;
+ SHORT caretSlopeRun;
+ SHORT reserved[5]; /* set to 0 */
+ SHORT metricDataFormat;
+ USHORT numberOfHMetrics;
+};
+
+struct tt_vhea_table
+{
+ Fixed version;
+ SHORT vertTypoAscender; /* v.1.1 name */
+ SHORT vertTypoDescender; /* v.1.1 name */
+ SHORT vertTypoLineGap; /* v.1.1 name */
+ SHORT advanceHeightMax;
+ SHORT minTopSideBearing;
+ SHORT minBottomSideBearing;
+ SHORT yMaxExtent;
+ SHORT caretSlopeRise;
+ SHORT caretSlopeRun;
+ SHORT caretOffset;
+ SHORT reserved[5]; /* set to 0 */
+ USHORT numOfLongVerMetrics;
+};
+
+struct tt_maxp_table
+{
+ Fixed version;
+ USHORT numGlyphs;
+ USHORT maxPoints;
+ USHORT maxContours;
+ USHORT maxComponentPoints;
+ USHORT maxComponentContours;
+ USHORT maxZones;
+ USHORT maxTwilightPoints;
+ USHORT maxStorage;
+ USHORT maxFunctionDefs;
+ USHORT maxInstructionDefs;
+ USHORT maxStackElements;
+ USHORT maxSizeOfInstructions;
+ USHORT maxComponentElements;
+ USHORT maxComponentDepth;
+};
+
+struct tt_os2__table
+{
+ USHORT version; /* 0x0001 or 0x0002 */
+ SHORT xAvgCharWidth;
+ USHORT usWeightClass;
+ USHORT usWidthClass;
+ SHORT fsType; /* if (faType & 0x08) editable_embedding */
+ SHORT ySubscriptXSize;
+ SHORT ySubscriptYSize;
+ SHORT ySubscriptXOffset;
+ SHORT ySubscriptYOffset;
+ SHORT ySuperscriptXSize;
+ SHORT ySuperscriptYSize;
+ SHORT ySuperscriptXOffset;
+ SHORT ySuperscriptYOffset;
+ SHORT yStrikeoutSize;
+ SHORT yStrikeoutPosition;
+ SHORT sFamilyClass;
+ BYTE panose[10];
+ ULONG ulUnicodeRange1;
+ ULONG ulUnicodeRange2;
+ ULONG ulUnicodeRange3;
+ ULONG ulUnicodeRange4;
+ ICHAR achVendID[4];
+ USHORT fsSelection;
+ USHORT usFirstCharIndex;
+ USHORT usLastCharIndex;
+ SHORT sTypoAscender; /* TTF spec. from MS is wrong */
+ SHORT sTypoDescender; /* TTF spec. from MS is wrong */
+ SHORT sTypoLineGap; /* TTF spec. from MS is wrong */
+ USHORT usWinAscent;
+ USHORT usWinDescent;
+ ULONG ulCodePageRange1;
+ ULONG ulCodePageRange2;
+ /* version 0x0002 */
+ SHORT sxHeight;
+ SHORT sCapHeight;
+ USHORT usDefaultChar;
+ USHORT usBreakChar;
+ USHORT usMaxContext;
+};
+
+struct tt_vertOriginYMetrics {
+ USHORT glyphIndex;
+ SHORT vertOriginY;
+};
+
+struct tt_VORG_table {
+ SHORT defaultVertOriginY;
+ USHORT numVertOriginYMetrics;
+ struct tt_vertOriginYMetrics *vertOriginYMetrics;
+};
+
+/* hmtx and vmtx */
+struct tt_longMetrics
+{
+ USHORT advance;
+ SHORT sideBearing;
+};
+
+
+/* head, hhea, maxp */
+extern char *tt_pack_head_table (struct tt_head_table *table);
+extern struct tt_head_table *tt_read_head_table (sfnt *sfont);
+extern char *tt_pack_hhea_table (struct tt_hhea_table *table);
+extern struct tt_hhea_table *tt_read_hhea_table (sfnt *sfont);
+extern char *tt_pack_maxp_table (struct tt_maxp_table *table);
+extern struct tt_maxp_table *tt_read_maxp_table (sfnt *sfont);
+
+/* vhea */
+extern char *tt_pack_vhea_table (struct tt_vhea_table *table);
+extern struct tt_vhea_table *tt_read_vhea_table (sfnt *sfont);
+
+/* VORG */
+extern struct tt_VORG_table *tt_read_VORG_table (sfnt *sfont);
+
+/* hmtx and vmtx */
+extern struct tt_longMetrics *tt_read_longMetrics (sfnt *sfont,
+ USHORT numGlyphs, USHORT numLongMetrics);
+
+/* OS/2 table */
+extern struct tt_os2__table *tt_read_os2__table (sfnt *sfont);
+
+/* name table */
+extern USHORT tt_get_name (sfnt *sfont, char *dest, USHORT destlen,
+ USHORT plat_id, USHORT enco_id,
+ USHORT lang_id, USHORT name_id);
+extern USHORT tt_get_ps_fontname (sfnt *sfont, char *dest, USHORT destlen);
+
+#endif /* _TT_TABLE_H_ */
diff --git a/Build/source/texk/web2c/luatexdir/font/vfovf.c b/Build/source/texk/web2c/luatexdir/font/vfovf.c
new file mode 100644
index 00000000000..0f23cb07b94
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/vfovf.c
@@ -0,0 +1,1349 @@
+/*
+Copyright (c) 1996-2006 Taco Hoekwater <taco@luatex.org>
+
+This file is part of LuaTeX.
+
+LuaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+LuaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with LuaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: vfovf.c 1022 2008-02-14 11:49:30Z taco $
+*/
+
+#include "ptexlib.h"
+
+#include "luatex-api.h"
+
+/* this is a hack! */
+#define font_max 5000
+
+#define set_char_0 0 /* typeset character 0 and move right */
+#define set1 128 /* typeset a character and move right */
+#define set2 129 /* typeset a character and move right */
+#define set3 130 /* typeset a character and move right */
+#define set4 131 /* typeset a character and move right */
+#define set_rule 132 /* typeset a rule and move right */
+#define put1 133 /* typeset a character without moving */
+#define put2 134 /* typeset a character without moving */
+#define put3 135 /* typeset a character without moving */
+#define put4 136 /* typeset a character without moving */
+#define put_rule 137 /* typeset a rule */
+#define nop 138 /* no operation */
+#define bop 139 /* beginning of page */
+#define eop 140 /* ending of page */
+#define push 141 /* save the current positions */
+#define pop 142 /* restore previous positions */
+#define right1 143 /* move right */
+#define right2 144 /* move right */
+#define right3 145 /* move right */
+#define right4 146 /* move right, 4 bytes */
+#define w0 147 /* move right by |w| */
+#define w1 148 /* move right and set |w| */
+#define w2 149 /* move right and set |w| */
+#define w3 150 /* move right and set |w| */
+#define w4 151 /* move right and set |w| */
+#define x0 152 /* move right by |x| */
+#define x1 153 /* move right and set |x| */
+#define x2 154 /* move right and set |x| */
+#define x3 155 /* move right and set |x| */
+#define x4 156 /* move right and set |x| */
+#define down1 157 /* move down */
+#define down2 158 /* move down */
+#define down3 159 /* move down */
+#define down4 160 /* move down, 4 bytes */
+#define y0 161 /* move down by |y| */
+#define y1 162 /* move down and set |y| */
+#define y2 163 /* move down and set |y| */
+#define y3 164 /* move down and set |y| */
+#define y4 165 /* move down and set |y| */
+#define z0 166 /* move down by |z| */
+#define z1 167 /* move down and set |z| */
+#define z2 168 /* move down and set |z| */
+#define z3 169 /* move down and set |z| */
+#define z4 170 /* move down and set |z| */
+#define fnt_num_0 171 /* set current font to 0 */
+#define fnt1 235 /* set current font */
+#define fnt2 236 /* set current font */
+#define fnt3 237 /* set current font */
+#define fnt4 238 /* set current font */
+#define xxx1 239 /* extension to DVI primitives */
+#define xxx2 240 /* extension to DVI primitives */
+#define xxx3 241 /* extension to DVI primitives */
+#define xxx4 242 /* potentially long extension to DVI primitives */
+#define fnt_def1 243 /* define the meaning of a font number */
+#define pre 247 /* preamble */
+#define post 248 /* postamble beginning */
+#define post_post 249 /* postamble ending */
+#define yyy1 250 /* PDF literal text */
+#define yyy2 251 /* PDF literal text */
+#define yyy3 252 /* PDF literal text */
+#define yyy4 253 /* PDF literal text */
+
+#define null_font 0
+
+#define long_char 242 /* \.{VF} command for general character packet */
+#define vf_id 202 /* identifies \.{VF} files */
+
+/* go out \.{VF} processing with an error message */
+#define bad_vf(a) { xfree(vf_buffer); print_nlp(); \
+ print_string("Error in processing VF font ("); \
+ print_string(font_name(f)); \
+ print_string(".vf): "); \
+ print_string(a); \
+ print_string(", virtual font will be ignored"); \
+ print_ln(); return; }
+
+#define lua_bad_vf(a) { xfree(vf_buffer); \
+ lua_settop(L,s_top); \
+ lua_pushnil(L); \
+ lua_pushstring(L,a); \
+ return 2; }
+
+#define tmp_b0 tmp_w.qqqq.b0
+#define tmp_b1 tmp_w.qqqq.b1
+#define tmp_b2 tmp_w.qqqq.b2
+#define tmp_b3 tmp_w.qqqq.b3
+#define tmp_int tmp_w.cint
+
+#define vf_stack_size 100 /* \.{DVI} files shouldn't |push| beyond this depth */
+
+typedef unsigned char vf_stack_index ; /* an index into the stack */
+
+typedef struct vf_stack_record {
+ scaled stack_w, stack_x, stack_y, stack_z;
+} vf_stack_record;
+
+boolean auto_expand_vf(internal_font_number f); /* forward */
+
+/* get a byte from\.{VF} file */
+
+#define vf_byte(a) { real_eight_bits vf_tmp_b; \
+ if (vf_cur>=vf_size) { \
+ pdftex_fail("unexpected eof on virtual font"); \
+ } \
+ vf_tmp_b = vf_buffer[vf_cur++] ; a = vf_tmp_b; }
+
+
+#define vf_replace_z() { \
+ vf_alpha=16; \
+ while (vf_z>=040000000) { \
+ vf_z= vf_z / 2; \
+ vf_alpha += vf_alpha; \
+ } \
+ vf_beta=256 / vf_alpha; \
+ vf_alpha=vf_alpha*vf_z; }
+
+/* read |k| bytes as an integer from \.{VF} file */
+
+#define vf_read(k,l) { integer itmp = 0, dtmp = k, jtmp = 0; \
+ while (dtmp > 0) { \
+ vf_byte(jtmp); \
+ if ((dtmp==k) && jtmp>127) \
+ jtmp = jtmp - 256; \
+ itmp = itmp*256 + jtmp; \
+ decr(dtmp); \
+ } \
+ l = itmp; }
+
+#define vf_read_u(k,l) { unsigned int dtmp=k, itmp = 0, jtmp = 0; \
+ while (dtmp-- > 0) { \
+ vf_byte(jtmp); \
+ itmp = itmp*256 + jtmp; \
+ } \
+ l = itmp; }
+
+void
+pdf_check_vf_cur_val (void) {
+ internal_font_number f;
+ f = cur_val;
+ if (font_type(f) == virtual_font_type)
+ pdf_error("font", "command cannot be used with virtual font");
+}
+
+static void
+vf_local_font_warning(internal_font_number f, internal_font_number k, char *s, integer a, integer b) {
+ print_nlp();
+ print_string(s);
+ print_string(" in local font ");
+ print_string(font_name(k));
+ print_string(" (");
+ print_int(b);
+ print_string(" != ");
+ print_int(a);
+ print_string(") in virtual font ");
+ print_string(font_name(f));
+ print_string(".vf ignored.");
+}
+
+
+/* process a local font in \.{VF} file */
+
+internal_font_number
+vf_def_font(internal_font_number f,unsigned char *vf_buffer, integer *vf_cr) {
+ internal_font_number k;
+ str_number s;
+ scaled ds,fs;
+ four_quarters cs;
+ memory_word tmp_w; /* accumulator */
+ integer junk;
+ unsigned long checksum;
+ cs.b0 = vf_buffer[(*vf_cr)];
+ cs.b1 = vf_buffer[(*vf_cr)+1];
+ cs.b2 = vf_buffer[(*vf_cr)+2];
+ cs.b3 = vf_buffer[(*vf_cr)+3]; (*vf_cr)+=4;
+ checksum = cs.b0*256*256*256 + cs.b1*256*256 + cs.b2*256 + cs.b3;
+ k = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ if (k>127) k-=256;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+
+ fs = sqxfw(k, font_size(f));
+
+ k = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ if (k>127) k-=256;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ k = k*256+ vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+
+ ds = k / 16;
+
+
+ tmp_b0 = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ tmp_b1 = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ while (tmp_b0 > 0) {
+ tmp_b0--;
+ (*vf_cr)++; /* skip the font path */
+ }
+ string_room(tmp_b1);
+ while (tmp_b1 > 0) {
+ tmp_b1--;
+ junk = vf_buffer[(*vf_cr)] ; (*vf_cr)++;
+ append_pool_char(junk);
+ }
+ s = make_string();
+ k = tfm_lookup(s, fs);
+ if (k == null_font)
+ k = read_font_info(get_nullcs(), s, get_nullstr(), fs, -1);
+ if (k != null_font) {
+ if (checksum!=0 && font_checksum(k)!=0 && checksum!= font_checksum(k))
+ vf_local_font_warning(f, k, "checksum mismatch",checksum,font_checksum(k));
+ if (ds != font_dsize(k))
+ vf_local_font_warning(f, k, "design size mismatch",ds,font_dsize(k));
+ }
+ if (pdf_font_expand_ratio(f) != 0)
+ set_expand_params(k, pdf_font_auto_expand(f),
+ pdf_font_expand_ratio(pdf_font_stretch(f)),
+ -pdf_font_expand_ratio(pdf_font_shrink(f)),
+ pdf_font_step(f), pdf_font_expand_ratio(f));
+ return k;
+}
+
+
+int
+open_vf_file (char *fn, unsigned char **vbuffer, integer *vsize) {
+ boolean res; /* was the callback successful? */
+ integer callback_id;
+ boolean file_read; /* was |vf_file| successfully read? */
+ FILE *vf_file;
+ char *fnam = NULL;
+
+
+
+
+ namelength = strlen(fn);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),fn);
+
+ callback_id=callback_defined(find_vf_file_callback);
+ if (callback_id>0) {
+ res = run_callback(callback_id,"S->S",fn, &fnam);
+ if (res && (fnam!=NULL) && (strlen(fnam)>0)) {
+ /* @<Fixup |nameoffile| after callback@>; */
+ free(nameoffile);
+ namelength = strlen(fnam);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),fnam);
+ } else {
+ return 0;
+ }
+ }
+ callback_id=callback_defined(read_vf_file_callback);
+ if (callback_id>0) {
+ file_read = false;
+ res = run_callback(callback_id,"S->bSd",stringcast(nameoffile+1),
+ &file_read, vbuffer,vsize);
+ if (res && file_read && (*vsize>0)) {
+ return 1;
+ }
+ if (!file_read)
+ return 0; /* -1 */
+ } else {
+ if (ovf_b_open_in(vf_file) || vf_b_open_in(vf_file)) {
+ res = read_vf_file(vf_file,vbuffer,vsize);
+ b_close(vf_file);
+ if (res) {
+ return 1;
+ }
+ } else {
+ return 0; /* -1 */
+ }
+ }
+ return 0;
+}
+
+
+/*
+ @ The |do_vf| procedure attempts to read the \.{VF} file for a font, and sets
+ |font_type()| to |real_font_type| if the \.{VF} file could not be found
+ or loaded, otherwise sets |font_type()| to |virtual_font_type|. At this
+ time, |tmp_f| is the internal font number of the current \.{TFM} font. To
+ process font definitions in virtual font we call |vf_def_font|.
+*/
+
+#define append_packet(k) vpackets[vf_np++] = k
+
+/* life is easier if all internal font commands are fnt4 and
+ all character commands are set4 or put4 */
+
+#define append_fnt_set(k) { \
+ assert(k>0) ; \
+ append_packet(packet_font_code); \
+ append_four(k); }
+
+#define append_four(k) { \
+ append_packet((k&0xFF000000)>>24); \
+ append_packet((k&0x00FF0000)>>16); \
+ append_packet((k&0x0000FF00)>>8); \
+ append_packet((k&0x000000FF)); }
+
+/* some of these things happen twice, adding a define is simplest */
+
+#define test_checksum() { vf_byte(tmp_b0); vf_byte(tmp_b1); \
+ vf_byte(tmp_b2); vf_byte(tmp_b3); \
+ if (((tmp_b0 != 0) || (tmp_b1 != 0) || (tmp_b2 != 0) || (tmp_b3 != 0)) && \
+ ((font_check_0(f) != 0) || (font_check_1(f) != 0) || \
+ (font_check_2(f) != 0) || (font_check_3(f) != 0)) && \
+ ((tmp_b0 != font_check_0(f)) || (tmp_b1 != font_check_1(f)) || \
+ (tmp_b2 != font_check_2(f)) || (tmp_b3 != font_check_3(f)))) { \
+ print_nlp(); \
+ print_string("checksum mismatch in font "); \
+ print_string(font_name(f)); \
+ print_string(".vf ignored "); } }
+
+#define test_dsize() { int read_tmp; vf_read(4,read_tmp); \
+ if ((read_tmp / 16) != font_dsize(f)) { \
+ print_nlp(); \
+ print_string("design size mismatch in font "); \
+ print_string(font_name(f)); \
+ print_string(".vf ignored"); \
+ } }
+
+
+int count_packet_bytes (real_eight_bits *vf_buf, int cur_bute, int count) {
+ int k = 0;
+ int ff = 0;
+ int acc = 0;
+ unsigned int cmd = 0;
+ unsigned int d = 0;
+ while (k<count) {
+ cmd = vf_buf[cur_bute+k]; k++;
+ if ((cmd >= set_char_0) && (cmd < set1)) {
+ if (ff==0) { ff = 1; acc+=5; }
+ acc+=5;
+ } else if ((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) {
+ ff = 1;
+ acc+=5;
+ } else {
+ switch (cmd) {
+ case fnt1: acc+=5; k+=1; ff=1 ; break;
+ case fnt2: acc+=5; k+=2; ff=1 ; break;
+ case fnt3: acc+=5; k+=3; ff=1 ; break;
+ case fnt4: acc+=5; k+=4; ff=1 ; break;
+ case set_rule: acc+=9; k+=8; break;
+ case put_rule: acc+=11; k+=8; break;
+ case set1: acc+=5; k+=1; if (ff==0) { ff = 1; acc+=5; } break;
+ case set2: acc+=5; k+=2; if (ff==0) { ff = 1; acc+=5; } break;
+ case set3: acc+=5; k+=3; if (ff==0) { ff = 1; acc+=5; } break;
+ case set4: acc+=5; k+=4; if (ff==0) { ff = 1; acc+=5; } break;
+ case put1: acc+=7; k+=1; if (ff==0) { ff = 1; acc+=5; } break;
+ case put2: acc+=7; k+=2; if (ff==0) { ff = 1; acc+=5; } break;
+ case put3: acc+=7; k+=3; if (ff==0) { ff = 1; acc+=5; } break;
+ case put4: acc+=7; k+=4; if (ff==0) { ff = 1; acc+=5; } break;
+ case right1: acc+=5; k+=1; break;
+ case right2: acc+=5; k+=2; break;
+ case right3: acc+=5; k+=3; break;
+ case right4: acc+=5; k+=4; break;
+ case w1: acc+=5; k+=1; break;
+ case w2: acc+=5; k+=2; break;
+ case w3: acc+=5; k+=3; break;
+ case w4: acc+=5; k+=4; break;
+ case x1: acc+=5; k+=1; break;
+ case x2: acc+=5; k+=2; break;
+ case x3: acc+=5; k+=3; break;
+ case x4: acc+=5; k+=4; break;
+ case down1: acc+=5; k+=1; break;
+ case down2: acc+=5; k+=2; break;
+ case down3: acc+=5; k+=3; break;
+ case down4: acc+=5; k+=4; break;
+ case y1: acc+=5; k+=1; break;
+ case y2: acc+=5; k+=2; break;
+ case y3: acc+=5; k+=3; break;
+ case y4: acc+=5; k+=4; break;
+ case z1: acc+=5; k+=1; break;
+ case z2: acc+=5; k+=2; break;
+ case z3: acc+=5; k+=3; break;
+ case z4: acc+=5; k+=4; break;
+ case xxx1:
+ d = vf_buf[cur_bute+k]; k++;
+ k += d; acc += 5 + d;
+ break;
+ case xxx2:
+ d = vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ k += d; acc += 5 + d;
+ break;
+ case xxx3:
+ d = vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ k += d; acc += 5 + d;
+ break;
+ case xxx4:
+ d = vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ d = d*256 + vf_buf[cur_bute+k]; k++;
+ k += d; acc += 5 + d;
+ break;
+ case w0: acc+=5; break;
+ case x0: acc+=5; break;
+ case y0: acc+=5; break;
+ case z0: acc+=5; break;
+ case nop: break;
+ case push: acc+=1; break;
+ case pop: acc+=1; break;
+ }
+ }
+ }
+ return (acc+1);
+}
+
+void
+do_vf(internal_font_number f) {
+ integer k, n, i;
+ unsigned cmd;
+ scaled x,y,w,z,h,v;
+ integer cc, cmd_length, packet_length;
+ charinfo *co;
+ scaled tfm_width;
+ integer save_cur_byte;
+ vf_stack_index stack_level;
+ integer vf_z; /* multiplier */
+ integer vf_alpha; /* correction for negative values */
+ char vf_beta; /* divisor */
+ integer vf_np;
+ real_eight_bits *vpackets;
+ memory_word tmp_w; /* accumulator */
+ vf_stack_record vf_stack[256];
+ integer junk;
+ unsigned char *vf_buffer;
+ integer vf_size;
+ integer vf_cur;
+ integer *vf_local_fnts = NULL; /* external font ids */
+ integer *vf_real_fnts = NULL; /* internal font ids */
+ unsigned vf_nf = 0; /* local font counter */
+
+ if (font_type(f)!= unknown_font_type)
+ return;
+ set_font_type(f,real_font_type);
+ if (auto_expand_vf(f))
+ return; /* auto-expanded virtual font */
+ stack_level = 0;
+ /* @<Open |vf_file|, return if not found@>; */
+ vf_cur=0; vf_buffer=NULL; vf_size=0;
+ if (!open_vf_file(font_name(f), &vf_buffer, &vf_size))
+ return;
+ /* @<Process the preamble@>;@/ */
+ set_font_type(f,virtual_font_type);
+ vf_byte(k);
+ if (k != pre)
+ bad_vf("PRE command expected");
+ vf_byte(k);
+ if (k != vf_id)
+ bad_vf("wrong id byte");
+ vf_byte(cmd_length);
+ for (k = 1;k<= cmd_length;k++)
+ vf_byte(junk);
+ test_checksum();
+ test_dsize();
+ /* update_terminal;*/
+ vf_z = font_size(f);
+ vf_replace_z();
+ /* @<Process the font definitions@>;@/ */
+ /* scan forward to find the number of internal fonts */
+ vf_nf = 0;
+ save_cur_byte = vf_cur;
+ vf_byte(cmd);
+ while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) {
+ vf_read((cmd - fnt_def1 + 1),junk);
+ vf_read(4,junk);
+ vf_read(4,junk);
+ vf_read(4,junk);
+ vf_byte(k);
+ vf_byte(junk);
+ k += junk;
+ while (k-- > 0) { vf_byte(junk); }
+ incr(vf_nf);
+ vf_byte(cmd);
+ }
+ vf_cur = save_cur_byte;
+ vf_byte(cmd);
+ /* malloc and fill the local font arrays */
+ if (vf_nf>0) {
+ i = vf_nf*sizeof(integer);
+ vf_local_fnts= xmalloc(i);
+ memset(vf_local_fnts,0,i);
+ vf_real_fnts= xmalloc(i);
+ memset(vf_real_fnts,0,i);
+ vf_nf = 0;
+ while ((cmd >= fnt_def1) && (cmd <= (fnt_def1 + 3))) {
+ vf_read_u((cmd - fnt_def1 + 1),vf_local_fnts[vf_nf]);
+ vf_real_fnts[vf_nf] = vf_def_font(f, vf_buffer, &vf_cur);
+ incr(vf_nf);
+ vf_byte(cmd);
+ }
+ }
+
+
+ while (cmd <= long_char) {
+ /* @<Build a character packet@>;@/ */
+ vf_np = 0;
+ if (cmd == long_char) {
+ vf_read_u(4,packet_length);
+ vf_read_u(4,cc);
+ if (!char_exists(f,cc)) {
+ bad_vf("invalid character code");
+ }
+ vf_read(4,k);
+ tfm_width = sqxfw(k, font_size(f));
+ } else {
+ packet_length = cmd;
+ vf_byte(cc);
+ if (!char_exists(f,cc)) {
+ bad_vf("invalid character code");
+ }
+ vf_read(3,k);
+ tfm_width = sqxfw(k, font_size(f));
+ }
+ if (packet_length < 0)
+ bad_vf("negative packet length");
+ if (tfm_width != char_width(f,cc)) {
+ /* precisely 'one off' errors are rampant */
+ if (abs(tfm_width - char_width(f,cc))>1) {
+ print_nlp();
+ print_string("character width mismatch in font ");
+ print_string(font_name(f));
+ print_string(".vf ignored");
+ }
+ }
+ k = count_packet_bytes(vf_buffer,vf_cur,packet_length);
+ vpackets = xmalloc(k+1);
+ co = get_charinfo(f,cc);
+ k = 0;
+ w = 0; x = 0; y = 0; z = 0;
+ while (packet_length > 0) {
+ vf_byte(cmd);
+ decr(packet_length);
+
+ if ((cmd >= set_char_0) && (cmd < set1)) {
+ if (k == 0) {
+ k = vf_real_fnts[0];
+ append_fnt_set(k);
+ }
+ append_packet(packet_char_code);
+ append_four(cmd);
+ cmd_length = 0;
+ cmd = nop;
+
+ } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) ||
+ ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) {
+ if (cmd >= fnt1) {
+ vf_read_u((cmd - fnt1 + 1),k);
+ packet_length -= (cmd - fnt1 + 1);
+ } else {
+ k = cmd - fnt_num_0;
+ }
+
+ /* change from local to external font id */
+ n = 0;
+ while ((n < vf_nf) && (vf_local_fnts[n] != k))
+ n++;
+ if (n==vf_nf)
+ bad_vf("undefined local font");
+
+ k = vf_real_fnts[n];
+ append_fnt_set(k);
+ cmd_length = 0;
+ cmd = nop;
+ } else {
+ switch (cmd) {
+ case set_rule:
+ vf_read(4,h); vf_read(4,v);
+ append_packet(packet_rule_code);
+ append_four(h);
+ append_four(v);
+ packet_length -= 8;
+ break;
+ case put_rule:
+ vf_read(4,h); vf_read(4,v);
+ append_packet(packet_push_code);
+ append_packet(packet_rule_code);
+ append_four(h);
+ append_four(v);
+ append_packet(packet_pop_code);
+ packet_length -= 8;
+ break;
+ case set1:
+ case set2:
+ case set3:
+ case set4:
+ if (k == 0) {
+ k = vf_real_fnts[0];
+ append_fnt_set(k);
+ }
+ vf_read_u((cmd - set1 + 1),i);
+ append_packet(packet_char_code);
+ append_four(i);
+ packet_length -= (cmd - set1 + 1);
+ break;
+ case put1:
+ case put2:
+ case put3:
+ case put4:
+ if (k == 0) {
+ k = vf_real_fnts[0];
+ append_fnt_set(k);
+ }
+ vf_read_u((cmd - put1 + 1),i);
+ append_packet(packet_push_code);
+ append_packet(packet_char_code);
+ append_four(i);
+ append_packet(packet_pop_code);
+ packet_length -= (cmd - put1 + 1);
+ break;
+ case right1:
+ case right2:
+ case right3:
+ case right4:
+ vf_read((cmd - right1 + 1),i);
+ append_packet(packet_right_code);
+ append_four(i);
+ packet_length -= (cmd - right1 + 1);
+ break;
+ case w1:
+ case w2:
+ case w3:
+ case w4:
+ vf_read((cmd - w1 + 1),w);
+ append_packet(packet_right_code);
+ append_four(w);
+ packet_length -= (cmd - w1 + 1);
+ break;
+ case x1:
+ case x2:
+ case x3:
+ case x4:
+ vf_read((cmd - x1 + 1),x);
+ append_packet(packet_right_code);
+ append_four(x);
+ packet_length -= (cmd - x1 + 1);
+ break;
+ case down1:
+ case down2:
+ case down3:
+ case down4:
+ vf_read((cmd - down1 + 1),i);
+ append_packet(packet_down_code);
+ append_four(i);
+ packet_length -= (cmd - down1 + 1);
+ break;
+ case y1:
+ case y2:
+ case y3:
+ case y4:
+ vf_read((cmd - y1 + 1),y);
+ append_packet(packet_down_code);
+ append_four(y);
+ packet_length -= (cmd - y1 + 1);
+ break;
+ case z1:
+ case z2:
+ case z3:
+ case z4:
+ vf_read((cmd - z1 + 1),z);
+ append_packet(packet_down_code);
+ append_four(z);
+ packet_length -= (cmd - z1 + 1);
+ break;
+ case xxx1:
+ case xxx2:
+ case xxx3:
+ case xxx4:
+ vf_read_u((cmd - xxx1 + 1),cmd_length);
+ packet_length -= (cmd - xxx1 + 1);
+ if (cmd_length <= 0)
+ bad_vf("special of negative length");
+ packet_length -= cmd_length;
+
+ append_packet(packet_special_code);
+ append_four(cmd_length);
+ while (cmd_length > 0) {
+ cmd_length--;
+ vf_byte(i);
+ append_packet(i);
+ }
+ append_packet(0);
+ break;
+ case w0:
+ append_packet(packet_right_code);
+ append_four(w);
+ break;
+ case x0:
+ append_packet(packet_right_code);
+ append_four(x);
+ break;
+ case y0:
+ append_packet(packet_down_code);
+ append_four(y);
+ break;
+ case z0:
+ append_packet(packet_down_code);
+ append_four(z);
+ break;
+ case nop:
+ break;
+ case push:
+ if (stack_level == vf_stack_size) {
+ overflow_string("virtual font stack size", vf_stack_size);
+ } else {
+ vf_stack[stack_level].stack_w = w;
+ vf_stack[stack_level].stack_x = x;
+ vf_stack[stack_level].stack_y = y;
+ vf_stack[stack_level].stack_z = z;
+ incr(stack_level);
+ append_packet(packet_push_code);
+ }
+ break;
+ case pop:
+ if (stack_level == 0) {
+ bad_vf("more POPs than PUSHs in character");
+ } else {
+ decr(stack_level);
+ w = vf_stack[stack_level].stack_w;
+ x = vf_stack[stack_level].stack_x;
+ y = vf_stack[stack_level].stack_y;
+ z = vf_stack[stack_level].stack_z;
+ append_packet(packet_pop_code);
+ }
+ break;
+ default:
+ bad_vf("improver DVI command");
+ }
+ }
+ }
+ /* signal end of packet */
+ append_packet(packet_end_code);
+
+ if (stack_level != 0)
+ bad_vf("more PUSHs than POPs in character packet");
+ if (packet_length != 0)
+ bad_vf("invalid packet length or DVI command in packet");
+ /* @<Store the packet being built@>; */
+ set_charinfo_packets(co,vpackets);
+ vf_byte(cmd);
+ }
+ if (cmd != post)
+ bad_vf("POST command expected");
+
+ xfree(vf_buffer);
+}
+
+#define make_command0(N,K) { \
+ lua_newtable(L); \
+ lua_pushstring(L, N); \
+ lua_rawseti(L,-2, 1); \
+ lua_rawseti(L,-2, K); \
+ K++; }
+
+#define make_command1(N,V,K) { \
+ lua_newtable(L); \
+ lua_pushstring(L, N); \
+ lua_rawseti(L,-2, 1); \
+ lua_pushnumber(L, V); \
+ lua_rawseti(L,-2, 2); \
+ lua_rawseti(L,-2, K); \
+ K++; }
+
+#define make_command2(N,V,W,K) { \
+ lua_newtable(L); \
+ lua_pushstring(L, N); \
+ lua_rawseti(L,-2, 1); \
+ lua_pushnumber(L, V); \
+ lua_rawseti(L,-2, 2); \
+ lua_pushnumber(L, W); \
+ lua_rawseti(L,-2, 3); \
+ lua_rawseti(L,-2, K); \
+ K++; }
+
+#define make_commands(N,S,V,K) { \
+ lua_newtable(L); \
+ lua_pushstring(L, N); \
+ lua_rawseti(L,-2, 1); \
+ lua_pushlstring(L, S, V); \
+ lua_rawseti(L,-2, 2); \
+ lua_rawseti(L,-2, K); \
+ K++; }
+
+
+int
+make_vf_table(lua_State *L, char *cnom, scaled atsize) {
+ integer cmd, k, i;
+ integer cc, cmd_length, packet_length;
+ scaled tfm_width;
+ vf_stack_index stack_level;
+ integer vf_z; /* multiplier */
+ integer vf_alpha; /* correction for negative values */
+ char vf_beta; /* divisor */
+ char *s;
+ scaled h,v;
+ scaled w, x, y, z;
+ integer s_top; /* lua stack */
+ integer vf_nf ; /* local font counter */
+ scaled ds,fs;
+ four_quarters cs;
+ memory_word tmp_w; /* accumulator */
+ vf_stack_record vf_stack[256];
+ unsigned char *vf_buffer;
+ integer vf_size;
+ integer vf_cur;
+
+
+ stack_level = 0;
+ /* @<Open |vf_file|, return if not found@>; */
+ vf_cur=0; vf_buffer=NULL; vf_size=0;
+ if (!open_vf_file(cnom, &vf_buffer, &vf_size)) {
+ lua_pushnil(L);
+ return 1;
+ }
+
+ /* start by creating a table */
+ s_top = lua_gettop(L);
+ lua_newtable(L);
+
+ /* @<Process the preamble@>;@/ */
+ vf_byte(k);
+ if (k != pre)
+ lua_bad_vf("PRE command expected");
+ vf_byte(k);
+ if (k != vf_id)
+ lua_bad_vf("wrong id byte");
+ vf_byte(cmd_length);
+
+ s = xmalloc(cmd_length);
+ for (k = 1;k<= cmd_length;k++)
+ vf_byte(s[(k-1)]);
+
+ lua_pushlstring(L,s,cmd_length);
+ free(s);
+ lua_setfield(L,-2,"header");
+
+ vf_byte(cs.b0); vf_byte(cs.b1); vf_byte(cs.b2); vf_byte(cs.b3);
+ lua_pushnumber(L, (unsigned long)(cs.b0<<24)+(cs.b1<<16)+(cs.b2<<8)+cs.b3 );
+ lua_setfield(L,-2,"checksum");
+
+ vf_read(4,k);
+ ds = k /16;
+ lua_pushinteger(L,ds);
+ lua_setfield(L,-2,"designsize");
+
+
+ lua_pushstring(L,cnom);
+ lua_setfield(L,-2,"name");
+
+ lua_pushinteger(L,atsize);
+ lua_setfield(L,-2,"size");
+
+
+ /* update_terminal;*/
+ vf_z = atsize;
+ vf_replace_z();
+ /* @<Process the font definitions@>;@/ */
+ vf_byte(cmd);
+ lua_newtable(L);
+
+ i = 1;
+ while ((cmd >= fnt_def1) && (cmd <= fnt_def1 + 3)) {
+
+ lua_newtable(L);
+ vf_read_u((cmd - fnt_def1 + 1),vf_nf);
+ vf_nf++;
+ /* checksum */
+ vf_byte(cs.b0); vf_byte(cs.b1); vf_byte(cs.b2); vf_byte(cs.b3);
+
+ vf_read(4,k);
+ fs = sqxfw(k, atsize);
+ lua_pushstring(L,"size");
+ lua_pushnumber(L,fs);
+ lua_rawset(L,-3);
+
+ vf_read(4,k);
+ ds = k / 16; /* dsize, not used */
+
+ vf_byte(tmp_b0);
+ vf_byte(tmp_b1);
+ while (tmp_b0 > 0) { tmp_b0--; vf_byte(k); } /* skip the font path */
+
+ s = xmalloc(tmp_b1+1); k = 0;
+ while (tmp_b1-- > 0)
+ vf_byte(s[k++]);
+ s[k]=0;
+ lua_pushstring(L,"name");
+ lua_pushstring(L,xstrdup(s));
+ free(s);
+ lua_rawset(L,-3);
+
+ lua_rawseti(L,-2,vf_nf);
+ i++;
+ vf_byte(cmd);
+ }
+
+ if (i>1) {
+ lua_setfield(L,-2,"fonts");
+ } else {
+ lua_pop(L,1);
+ }
+
+ lua_newtable(L); /* 'characters' */
+ while (cmd <= long_char) {
+ /* @<Build a character packet@>;@/ */
+ if (cmd == long_char) {
+ vf_read_u(4,packet_length);
+ vf_read_u(4,cc);
+ vf_read(4,tfm_width);
+ } else {
+ packet_length = cmd;
+ vf_byte(cc);
+ vf_read(3,tfm_width);
+ }
+ if (packet_length < 0)
+ lua_bad_vf("negative packet length");
+
+ lua_newtable(L); /* for this character */
+
+ lua_pushnumber(L,tfm_width);
+ lua_setfield(L,-2,"width");
+
+ lua_newtable(L); /* for 'commands' */
+
+ k = 1; vf_nf = 0;
+ w = 0; x = 0; y = 0; z = 0;
+ while (packet_length > 0) {
+ vf_byte(cmd);
+ decr(packet_length);
+
+ if ((cmd >= set_char_0) && (cmd < set1)) {
+ if (vf_nf == 0) {
+ vf_nf = 1;
+ make_command1("font",vf_nf,k);
+ }
+ make_command1("char",cmd,k);
+
+ } else if (((fnt_num_0 <= cmd) && (cmd <= fnt_num_0 + 63)) ||
+ ((fnt1 <= cmd) && (cmd <= fnt1 + 3))) {
+ if (cmd >= fnt1) {
+ vf_read_u((cmd - fnt1 + 1),vf_nf); vf_nf++;
+ packet_length -= (cmd - fnt1 + 1);
+ } else {
+ vf_nf = cmd - fnt_num_0 + 1;
+ }
+ make_command1("font",vf_nf,k);
+ } else {
+ switch (cmd) {
+ case set_rule:
+ vf_read(4,h); vf_read(4,v);
+ make_command2("rule",sqxfw(h,atsize),sqxfw(v,atsize),k);
+ packet_length -= 8;
+ break;
+ case put_rule:
+ vf_read(4,h); vf_read(4,v);
+ make_command0("push",k);
+ make_command2("rule",sqxfw(h,atsize),sqxfw(v,atsize),k);
+ make_command0("pop",k);
+ packet_length -= 8;
+ break;
+ case set1:
+ case set2:
+ case set3:
+ case set4:
+ if (vf_nf == 0) {
+ vf_nf = 1;
+ make_command1("font",vf_nf,k);
+ }
+ vf_read_u((cmd - set1 + 1),i);
+ make_command1("char",i,k);
+ packet_length -= (cmd - set1 + 1);
+ break;
+ case put1:
+ case put2:
+ case put3:
+ case put4:
+ if (vf_nf == 0) {
+ vf_nf = 1;
+ make_command1("font",vf_nf,k);
+ }
+ vf_read_u((cmd - put1 + 1),i);
+ make_command0("push",k);
+ make_command1("char",i,k);
+ make_command0("pop",k);
+ packet_length -= (cmd - put1 + 1);
+ break;
+ case right1:
+ case right2:
+ case right3:
+ case right4:
+ vf_read((cmd - right1 + 1),i);
+ make_command1("right",sqxfw(i,atsize),k);
+ packet_length -= (cmd - right1 + 1);
+ break;
+ case w1:
+ case w2:
+ case w3:
+ case w4:
+ vf_read((cmd - w1 + 1),w);
+ make_command1("right",sqxfw(w,atsize),k);
+ packet_length -= (cmd - w1 + 1);
+ break;
+ case x1:
+ case x2:
+ case x3:
+ case x4:
+ vf_read((cmd - x1 + 1),x);
+ make_command1("right",sqxfw(x,atsize),k);
+ packet_length -= (cmd - x1 + 1);
+ break;
+ case down1:
+ case down2:
+ case down3:
+ case down4:
+ vf_read((cmd - down1 + 1),i);
+ make_command1("down",sqxfw(i,atsize),k);
+ packet_length -= (cmd - down1 + 1);
+ break;
+ case y1:
+ case y2:
+ case y3:
+ case y4:
+ vf_read((cmd - y1 + 1),y);
+ make_command1("down",sqxfw(y,atsize),k);
+ packet_length -= (cmd - y1 + 1);
+ break;
+ case z1:
+ case z2:
+ case z3:
+ case z4:
+ vf_read((cmd - z1 + 1),z);
+ make_command1("down",sqxfw(z,atsize),k);
+ packet_length -= (cmd - z1 + 1);
+ break;
+ case xxx1:
+ case xxx2:
+ case xxx3:
+ case xxx4:
+ vf_read_u((cmd - xxx1 + 1),cmd_length);
+ packet_length -= (cmd - xxx1 + 1);
+ if (cmd_length <= 0)
+ lua_bad_vf("special of negative length");
+ packet_length -= cmd_length;
+
+ s = xmalloc(cmd_length+1); i = 0;
+ while (cmd_length > 0) {
+ cmd_length--;
+ vf_byte(s[i]);
+ i++;
+ }
+ s[i]=0;
+ make_commands("special",strdup(s),i,k);
+ free(s);
+ break;
+ case w0:
+ make_command1("right",sqxfw(w,atsize),k);
+ break;
+ case x0:
+ make_command1("right",sqxfw(x,atsize),k);
+ break;
+ case y0:
+ make_command1("down",sqxfw(y,atsize),k);
+ break;
+ case z0:
+ make_command1("down",sqxfw(z,atsize),k);
+ break;
+ case nop:
+ break;
+ case push:
+ if (stack_level == vf_stack_size) {
+ overflow_string("virtual font stack size", vf_stack_size);
+ } else {
+ vf_stack[stack_level].stack_w = w;
+ vf_stack[stack_level].stack_x = x;
+ vf_stack[stack_level].stack_y = y;
+ vf_stack[stack_level].stack_z = z;
+ incr(stack_level);
+ make_command0("push",k);
+ }
+ break;
+ case pop:
+ if (stack_level == 0) {
+ lua_bad_vf("more POPs than PUSHs in character");
+ } else {
+ decr(stack_level);
+ w = vf_stack[stack_level].stack_w;
+ x = vf_stack[stack_level].stack_x;
+ y = vf_stack[stack_level].stack_y;
+ z = vf_stack[stack_level].stack_z;
+ make_command0("pop",k);
+ }
+ break;
+ default:
+ lua_bad_vf("improver DVI command");
+ }
+ }
+ }
+ /* signal end of packet */
+ lua_setfield(L,-2,"commands");
+
+ if (stack_level != 0)
+ lua_bad_vf("more PUSHs than POPs in character packet");
+ if (packet_length != 0)
+ lua_bad_vf("invalid packet length or DVI command in packet");
+
+ lua_rawseti(L,-2,cc);
+
+ vf_byte(cmd);
+ }
+ lua_setfield(L,-2,"characters");
+
+ if (cmd != post)
+ lua_bad_vf("POST command expected");
+ xfree(vf_buffer);
+ return 1;
+}
+
+
+extern void replace_packet_fonts(internal_font_number f, integer *old_fontid, integer *new_fontid, int count) ;
+extern integer *packet_local_fonts(internal_font_number f, integer *num);
+extern internal_font_number auto_expand_font (internal_font_number f, integer e) ;
+
+
+/* This function is called from |do_vf|, and fixes up the virtual data
+ inside an auto-expanded virtual font */
+
+boolean
+auto_expand_vf(internal_font_number f) {
+
+ internal_font_number bf;
+ integer e, k;
+ integer *vf_old_fonts, *vf_new_fonts;
+ integer num = 0;
+
+ if ((! pdf_font_auto_expand(f)) || (pdf_font_blink(f) == null_font))
+ return false ; /* not an auto-expanded font */
+ bf = pdf_font_blink(f);
+
+ if (font_type(bf) != virtual_font_type)
+ return false; /* not a virtual font */
+
+ e = pdf_font_expand_ratio(f);
+
+ vf_old_fonts = packet_local_fonts(bf,&num);
+ if (num>0) {
+ vf_new_fonts = xmalloc(num*sizeof(integer));
+ for (k=0;k<num;k++) {
+ vf_new_fonts[k] = auto_expand_font(vf_old_fonts[k], e);
+ copy_expand_params(vf_new_fonts[k], vf_old_fonts[k], e);
+ }
+ replace_packet_fonts(f,vf_old_fonts,vf_new_fonts,num);
+ xfree(vf_new_fonts);
+ xfree(vf_old_fonts);
+ }
+ set_font_type(f,virtual_font_type);
+ return true;
+}
+
+/* this function is not always safe, because it needs makecstring() */
+str_number
+expand_font_name (internal_font_number f, integer e) {
+ int old_setting;
+ old_setting=selector;
+ selector=new_string;
+ print_string(font_name(f));
+ if (e > 0) {
+ print_char('+');
+ }
+ print_int(e);
+ selector=old_setting;
+ return make_string();
+}
+
+
+internal_font_number
+auto_expand_font (internal_font_number f, integer e) {
+ internal_font_number k;
+ kerninfo *krn;
+ charinfo *co, *ci;
+ char *fn;
+ integer i;
+ scaled w;
+ k = copy_font(f);
+ i = strlen(font_name(f))+12;
+ fn = xmalloc(i);
+ snprintf(fn,i,"%s%s%d",font_name(f),(e>0 ? "+" : ""), (int)e);
+ set_font_name(k,fn);
+ for (i = font_bc(k);i<=font_ec(k);i++) {
+ if (char_exists(k,i)) {
+ co = get_charinfo(k,i);
+ w = round_xn_over_d(char_width(f,i), 1000 + e, 1000);
+ set_charinfo_width (co, w);
+ w = round_xn_over_d(char_italic(f,i), 1000 + e, 1000);
+ set_charinfo_italic(co, w);
+ krn = get_charinfo_kerns(co);
+ if (krn != NULL) {
+ while (!kern_end((*krn))) {
+ kern_kern(*krn) = round_xn_over_d(kern_kern(*krn), 1000 + e, 1000);
+ krn++;
+ }
+ }
+ }
+ }
+ return k;
+}
+
+void
+vf_expand_local_fonts(internal_font_number f) {
+ internal_font_number lf;
+ integer k, num;
+ integer *vf_old_fonts;
+ pdfassert(font_type(f) == virtual_font_type);
+ num = 0;
+ vf_old_fonts = packet_local_fonts(f,&num);
+ if (num>0) {
+ for (k = 0;k<num;k++) {
+ lf = vf_old_fonts[k];
+ set_expand_params(lf, pdf_font_auto_expand(f),
+ pdf_font_expand_ratio(pdf_font_stretch(f)),
+ -pdf_font_expand_ratio(pdf_font_shrink(f)),
+ pdf_font_step(f), pdf_font_expand_ratio(f));
+ if (font_type(lf) == virtual_font_type)
+ vf_expand_local_fonts(lf);
+ }
+ xfree(vf_old_fonts);
+ }
+}
+
+internal_font_number
+letter_space_font (halfword u, internal_font_number f, integer e) {
+ internal_font_number k;
+ scaled w, r;
+
+ char *new_font_name;
+ integer vf_z;
+ integer vf_alpha;
+ integer vf_beta;
+ memory_word tmp_w; /* accumulator */
+
+
+ /* read a new font and expand the character widths */
+ k = read_font_info(u, tex_font_name(f), get_nullstr(), font_size(f), font_natural_dir(f));
+ set_no_ligatures(k); /* disable ligatures for letter-spaced fonts */
+/*
+ for (i = 0;i <= font_widths(k);i++) {
+ set_font_width(k,i,font_width(f,i)+round_xn_over_d(quad(k), e, 1000));
+ }
+*/
+ /* append eg '+100ls' to font name */
+ new_font_name = xmalloc(strlen(font_name(k)) + 8); /* |abs(e) <= 1000| */
+ if (e > 0) {
+ sprintf(new_font_name,"%s+%ils",font_name(k),(int)e);
+ } else {
+ /* minus from %i */
+ sprintf(new_font_name,"%s%ils",font_name(k),(int)e);
+ }
+ set_font_name(k, new_font_name);
+
+ /* create the corresponding virtual font */
+ set_font_type(k,virtual_font_type);
+
+ vf_z = font_size(f);
+ vf_replace_z();
+ w = round_xn_over_d(quad(f), e, 2000);
+ if (w > 0) {
+ tmp_b0 = 0;
+ } else {
+ tmp_b0 = 255;
+ w = vf_alpha + w;
+ }
+ r = w*vf_beta;
+ tmp_b1 = r / vf_z;
+ r = r % vf_z;
+ if (r == 0) {
+ tmp_b2 = 0;
+ } else {
+ r = r * 256;
+ tmp_b2 = r / vf_z;
+ r = r % vf_z;
+ }
+ if (r == 0) {
+ tmp_b3 = 0;
+ } else {
+ r = r * 256;
+ tmp_b3 = r / vf_z;
+ }
+ /*
+ vf_packet_base[k] = new_vf_packet(k);
+
+ for (c=font_bc(k);c<=font_ec(k);c++) {
+ string_room(17);
+ append_fnt_set(f);
+ append_packet(right1 + 3);
+ append_packet(tmp_b0);
+ append_packet(tmp_b1);
+ append_packet(tmp_b2);
+ append_packet(tmp_b3);
+
+ append_packet(set1);
+ append_packet(c);
+
+ append_packet(right1 + 3);
+ append_packet(tmp_b0);
+ append_packet(tmp_b1);
+ append_packet(tmp_b2);
+ append_packet(tmp_b3);
+ s = make_string();
+ store_packet(k, c, s);
+ flush_str(s);
+ }
+*/
+ return k;
+}
+
+
diff --git a/Build/source/texk/web2c/luatexdir/font/vfpacket.c b/Build/source/texk/web2c/luatexdir/font/vfpacket.c
new file mode 100644
index 00000000000..4d8445f2227
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/vfpacket.c
@@ -0,0 +1,377 @@
+/*
+Copyright (c) 1996-2002 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: vfpacket.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+/*
+ The |do_vf_packet| procedure is called in order to interpret the
+ character packet for a virtual character. Such a packet may contain
+ the instruction to typeset a character from the same or an other
+ virtual font; in such cases |do_vf_packet| calls itself
+ recursively. The recursion level, i.e., the number of times this has
+ happened, is kept in the global variable |packet_cur_s| and should
+ not exceed |packet_max_recursion|.
+*/
+
+#define packet_max_recursion 100
+
+typedef unsigned char packet_stack_index ; /* an index into the stack */
+
+typedef struct packet_stack_record {
+ scaled stack_h;
+ scaled stack_v;
+} packet_stack_record;
+
+
+static packet_stack_index packet_cur_s = 0; /* current recursion level */
+static packet_stack_record packet_stack [packet_max_recursion];
+static packet_stack_index packet_stack_ptr = 0; /* pointer into |packet_stack| */
+
+
+/* Some macros for processing character packets. */
+
+#define do_packet_byte() vf_packets[cur_packet_byte++]
+
+#define packet_number(fw) { \
+ fw = do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); }
+
+#define packet_scaled(a,fs) { integer fw; \
+ fw = do_packet_byte(); \
+ if (fw>127) fw = fw - 256; \
+ fw = fw*256 + do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); \
+ fw = fw*256 + do_packet_byte(); \
+ a = sqxfw(fw, fs); }
+
+
+/* count the number of bytes in a command packet */
+int
+vf_packet_bytes (charinfo *co) {
+ real_eight_bits *vf_packets;
+ integer cur_packet_byte;
+ unsigned k;
+ int cmd;
+
+ vf_packets = get_charinfo_packets(co);
+ if (vf_packets == NULL) {
+ return 0;
+ }
+ cur_packet_byte = 0;
+ while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
+ cur_packet_byte++;
+ switch (cmd) {
+ case packet_char_code:
+ case packet_font_code:
+ case packet_right_code:
+ case packet_down_code:
+ case packet_node_code:
+ cur_packet_byte += 4;
+ break;
+ case packet_push_code:
+ case packet_pop_code:
+ break;
+ case packet_rule_code:
+ cur_packet_byte += 8;
+ break;
+ case packet_special_code:
+ packet_number(k); /* +4 */
+ cur_packet_byte += k;
+ break;
+ case packet_nop_code:
+ break;
+ default:
+ pdf_error("vf", "invalid DVI command");
+ }
+ };
+ return (cur_packet_byte +1);
+}
+
+
+/* typeset the \.{DVI} commands in the
+ character packet for character |c| in current font |f| */
+
+char *packet_command_names[] = {
+ "char", "font","pop", "push", "special",
+ "right","down","rule","node", "nop","end", NULL};
+
+
+void
+do_vf_packet (internal_font_number vf_f, integer c) {
+ internal_font_number lf;
+ charinfo *co;
+ scaled save_cur_h, save_cur_v;
+ real_eight_bits *vf_packets;
+ integer cur_packet_byte;
+ integer cmd, fs_f;
+ scaled i;
+ unsigned k;
+ str_number s;
+
+ packet_cur_s++;
+ if (packet_cur_s >= packet_max_recursion)
+ overflow_string("max level recursion of virtual fonts", packet_max_recursion);
+ save_cur_v = cur_v;
+ save_cur_h = cur_h;
+
+ lf = 0; /* for -Wall */
+ co = get_charinfo(vf_f,c);
+ vf_packets = get_charinfo_packets(co);
+ if (vf_packets == NULL) {
+ packet_cur_s--;
+ return ;
+ }
+ cur_packet_byte = 0;
+ fs_f = font_size(vf_f);
+ while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
+ cur_packet_byte++;
+ /*
+ if (cmd>packet_end_code) {
+ fprintf(stdout, "do_vf_packet(%i,%i) command code = illegal \n", vf_f,c);
+ } else {
+ fprintf(stdout, "do_vf_packet(%i,%i) command code = %s\n",vf_f, c, packet_command_names[cmd]);
+ }
+ */
+ switch (cmd) {
+ case packet_font_code:
+ packet_number(lf);
+ break;
+ case packet_push_code:
+ packet_stack[packet_stack_ptr].stack_h = cur_h;
+ packet_stack[packet_stack_ptr].stack_v = cur_v;
+ packet_stack_ptr++;
+ break;
+ case packet_pop_code:
+ packet_stack_ptr--;
+ cur_h = packet_stack[packet_stack_ptr].stack_h;
+ cur_v = packet_stack[packet_stack_ptr].stack_v;
+ break;
+ case packet_char_code:
+ packet_number(k);
+ if (!char_exists(lf,k)) {
+ char_warning(lf, k);
+ } else {
+ output_one_char(lf, k);
+ }
+ cur_h = cur_h + char_width(lf,k);
+ break;
+ case packet_rule_code:
+ packet_scaled(rule_ht,fs_f);
+ packet_scaled(rule_wd,fs_f);
+ if ((rule_wd > 0) && (rule_ht > 0)) {
+ pdf_set_rule(cur_h, cur_v, rule_wd, rule_ht);
+ cur_h = cur_h + rule_wd;
+ }
+ break;
+ case packet_right_code:
+ packet_scaled(i,fs_f);
+ cur_h = cur_h + i;
+ break;
+ case packet_down_code:
+ packet_scaled(i,fs_f);
+ cur_v = cur_v + i;
+ break;
+ case packet_special_code:
+ packet_number(k);
+ string_room(k);
+ while (k > 0) {
+ k--;
+ append_pool_char(do_packet_byte());
+ }
+ s = make_string();
+ literal(s, scan_special, false);
+ flush_str(s);
+ break;
+ case packet_node_code:
+ packet_number(k);
+ temp_ptr = k;
+ pdf_hlist_out();
+ break;
+ case packet_nop_code:
+ break;
+ default:
+ pdf_error("vf", "invalid DVI command");
+ }
+ };
+ cur_h = save_cur_h;
+ cur_v = save_cur_v;
+ packet_cur_s--;
+}
+
+
+integer *packet_local_fonts(internal_font_number f, integer *num) {
+ int c, cmd, cur_packet_byte, lf, k,l, i;
+ integer localfonts[256] = {0};
+ integer *lfs;
+ charinfo *co;
+
+ real_eight_bits *vf_packets;
+ k = 0;
+ for (c = font_bc(f);c <= font_ec(f);c++) {
+ if (char_exists(f,c)) {
+ co = get_charinfo(f,c);
+ vf_packets = get_charinfo_packets(co);
+ if (vf_packets == NULL)
+ continue;
+ cur_packet_byte = 0;
+ while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
+ cur_packet_byte++;
+ switch (cmd) {
+ case packet_font_code:
+ packet_number(lf);
+ for (l=0;l<k;l++) {
+ if (localfonts[l]==lf) {
+ break;
+ }
+ }
+ if (l==k) {
+ localfonts[k++]=lf;
+ }
+ break;
+ case packet_push_code:
+ case packet_pop_code:
+ case packet_nop_code:
+ break;
+ case packet_char_code:
+ case packet_right_code:
+ case packet_down_code:
+ case packet_node_code:
+ cur_packet_byte+=4;
+ break;
+ case packet_rule_code:
+ cur_packet_byte+=8;
+ break;
+ case packet_special_code:
+ packet_number(i);
+ while (i-- > 0)
+ (void)do_packet_byte();
+ break;
+ default:
+ pdf_error("vf", "invalid DVI command");
+ }
+ }
+ }
+ }
+ *num = k;
+ if (k>0) {
+ lfs = xmalloc (k*sizeof(integer));
+ memcpy(lfs,localfonts,k*sizeof(integer));
+ return lfs;
+ }
+ return NULL;
+}
+
+
+void
+replace_packet_fonts(internal_font_number f, integer *old_fontid, integer *new_fontid, int count) {
+ int c, cmd, cur_packet_byte, lf, k,l;
+ charinfo *co;
+ real_eight_bits *vf_packets;
+
+ k = 0;
+ for (c = font_bc(f);c <= font_ec(f);c++) {
+ if (char_exists(f,c)) {
+ co = get_charinfo(f,c);
+ vf_packets = get_charinfo_packets(co);
+ if (vf_packets == NULL)
+ continue;
+ cur_packet_byte = 0;
+ while ((cmd = vf_packets[cur_packet_byte]) != packet_end_code) {
+ cur_packet_byte++;
+ switch (cmd) {
+ case packet_font_code:
+ packet_number(lf);
+ for (l=0;l<count;l++) {
+ if (old_fontid[l]==lf) {
+ break;
+ }
+ }
+ if(l<count) {
+ k = new_fontid[l];
+ vf_packets[(cur_packet_byte-4)] = (k&0xFF000000)>>24;
+ vf_packets[(cur_packet_byte-3)] = (k&0x00FF0000)>>16;
+ vf_packets[(cur_packet_byte-2)] = (k&0x0000FF00)>>8;
+ vf_packets[(cur_packet_byte-1)] = (k&0x000000FF);
+ }
+ break;
+ case packet_push_code:
+ case packet_pop_code:
+ case packet_nop_code:
+ break;
+ case packet_char_code:
+ case packet_right_code:
+ case packet_down_code:
+ case packet_node_code:
+ cur_packet_byte+=4;
+ break;
+ case packet_rule_code:
+ cur_packet_byte+=8;
+ break;
+ case packet_special_code:
+ packet_number(k);
+ while (k-- > 0)
+ (void)do_packet_byte();
+ break;
+ default:
+ pdf_error("vf", "invalid DVI command");
+ }
+ }
+ }
+ }
+}
+
+/* this function was copied/borrowed/stolen from dvipdfm code */
+
+scaled sqxfw (scaled sq, integer fw)
+{
+ int sign = 1;
+ unsigned long a, b, c, d, ad, bd, bc, ac;
+ unsigned long e, f, g, h, i, j, k;
+ unsigned long result;
+ /* Make positive. */
+ if (sq < 0) {
+ sign = -sign;
+ sq = -sq;
+ }
+ if (fw < 0) {
+ sign = -sign;
+ fw = -fw;
+ }
+ a = ((unsigned long) sq) >> 16u;
+ b = ((unsigned long) sq) & 0xffffu;
+ c = ((unsigned long) fw) >> 16u;
+ d = ((unsigned long) fw) & 0xffffu;
+ ad = a*d; bd = b*d; bc = b*c; ac = a*c;
+ e = bd >> 16u;
+ f = ad >> 16u;
+ g = ad & 0xffffu;
+ h = bc >> 16u;
+ i = bc & 0xffffu;
+ j = ac >> 16u;
+ k = ac & 0xffffu;
+ result = (e+g+i + (1<<3)) >> 4u; /* 1<<3 is for rounding */
+ result += (f+h+k) << 12u;
+ result += j << 28u;
+ return (sign>0)?result:-result;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/writecff.c b/Build/source/texk/web2c/luatexdir/font/writecff.c
new file mode 100644
index 00000000000..69c35c6950e
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writecff.c
@@ -0,0 +1,3381 @@
+/*
+Copyright (c) 2007 Taco Hoekwater, taco@luatex.org
+
+This file is part of luaTeX.
+
+luaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writecff.c 1021 2008-02-14 10:24:34Z taco $
+*/
+
+#include "ptexlib.h"
+
+#include "writecff.h"
+
+#define get_offset(s,n) get_unsigned(s, (n))
+#define get_card8(a) a->stream[a->offset++]
+#define get_card16(a) get_unsigned(a,2)
+
+#undef b0
+#undef b1
+#undef b2
+#undef b3
+
+#define WORK_BUFFER_SIZE 1024
+
+static char work_buffer[WORK_BUFFER_SIZE];
+
+static unsigned long get_unsigned (cff_font *cff, int n)
+{
+ unsigned long v = 0;
+ while (n-- > 0)
+ v = v*256 + get_card8(cff);
+ return v;
+}
+
+#define CFF_ERROR pdftex_fail
+#define WARN pdftex_warn
+
+
+const char *const cff_stdstr[CFF_STDSTR_MAX] = {
+ ".notdef", "space", "exclam", "quotedbl", "numbersign",
+ "dollar", "percent", "ampersand", "quoteright", "parenleft",
+ "parenright", "asterisk", "plus", "comma", "hyphen",
+ "period", "slash", "zero", "one", "two",
+ "three", "four", "five", "six", "seven",
+ "eight", "nine", "colon", "semicolon", "less",
+ "equal", "greater", "question", "at", "A",
+ "B", "C", "D", "E", "F",
+ "G", "H", "I", "J", "K",
+ "L", "M", "N", "O", "P",
+ "Q", "R", "S", "T", "U",
+ "V", "W", "X", "Y", "Z",
+ "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
+ "quoteleft", "a", "b", "c", "d",
+ "e", "f", "g", "h", "i",
+ "j", "k", "l", "m", "n",
+ "o", "p", "q", "r", "s",
+ "t", "u", "v", "w", "x",
+ "y", "z", "braceleft", "bar", "braceright",
+ "asciitilde", "exclamdown", "cent", "sterling", "fraction",
+ "yen", "florin", "section", "currency", "quotesingle",
+ "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
+ "fl", "endash", "dagger", "daggerdbl", "periodcentered",
+ "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
+ "guillemotright", "ellipsis", "perthousand", "questiondown", "grave",
+ "acute", "circumflex", "tilde", "macron", "breve",
+ "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut",
+ "ogonek", "caron", "emdash", "AE", "ordfeminine",
+ "Lslash", "Oslash", "OE", "ordmasculine", "ae",
+ "dotlessi", "lslash", "oslash", "oe", "germandbls",
+ "onesuperior", "logicalnot", "mu", "trademark", "Eth",
+ "onehalf", "plusminus", "Thorn", "onequarter", "divide",
+ "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
+ "registered", "minus", "eth", "multiply", "threesuperior",
+ "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave",
+ "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
+ "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
+ "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis",
+ "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
+ "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
+ "aacute", "acircumflex", "adieresis", "agrave", "aring",
+ "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
+ "egrave", "iacute", "icircumflex", "idieresis", "igrave",
+ "ntilde", "oacute", "ocircumflex", "odieresis", "ograve",
+ "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
+ "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
+ "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall", "Acutesmall",
+ "parenleftsuperior", "parenrightsuperior", "twodotenleader", "onedotenleader", "zerooldstyle",
+ "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle", "fiveoldstyle",
+ "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle", "commasuperior",
+ "threequartersemdash", "periodsuperior", "questionsmall", "asuperior", "bsuperior",
+ "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
+ "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
+ "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
+ "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall", "Asmall",
+ "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
+ "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall",
+ "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
+ "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
+ "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
+ "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall",
+ "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall", "Dieresissmall",
+ "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
+ "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall", "questiondownsmall",
+ "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird",
+ "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
+ "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior", "oneinferior",
+ "twoinferior", "threeinferior", "fourinferior", "fiveinferior", "sixinferior",
+ "seveninferior", "eightinferior", "nineinferior", "centinferior", "dollarinferior",
+ "periodinferior", "commainferior", "Agravesmall", "Aacutesmall", "Acircumflexsmall",
+ "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
+ "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall", "Igravesmall",
+ "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall", "Ntildesmall",
+ "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall", "Odieresissmall",
+ "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall",
+ "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall",
+ "001.000", "001.001", "001.002", "001.003",
+ "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"
+};
+
+
+/* Only read header part but not body */
+cff_index *
+cff_get_index_header (cff_font *cff)
+{
+ cff_index *idx;
+ card16 i, count;
+
+ idx = xcalloc(1, sizeof(cff_index));
+
+ idx->count = count = get_card16(cff);
+ if (count > 0) {
+ idx->offsize = get_card8(cff);
+ if (idx->offsize < 1 || idx->offsize > 4)
+ CFF_ERROR("invalid offsize data");
+
+ idx->offset = xcalloc(count+1, sizeof(l_offset));
+ for (i=0;i<count+1;i++) {
+ (idx->offset)[i] = get_offset(cff, idx->offsize);
+ }
+
+ if (idx->offset[0] != 1)
+ CFF_ERROR("cff_get_index(): invalid index data");
+
+ idx->data = NULL;
+ } else {
+ idx->offsize = 0;
+ idx->offset = NULL;
+ idx->data = NULL;
+ }
+
+ return idx;
+}
+
+
+
+cff_index *
+cff_get_index (cff_font *cff)
+{
+ cff_index *idx;
+ card16 i, count;
+ long length;
+
+ idx = xcalloc(1,sizeof(cff_index));
+
+ idx->count = count = get_card16(cff);
+ if (count > 0) {
+ idx->offsize = get_card8(cff);
+ if (idx->offsize < 1 || idx->offsize > 4)
+ CFF_ERROR("invalid offsize data");
+
+ idx->offset = xcalloc((count + 1),sizeof(l_offset));
+ for (i = 0 ; i < count + 1; i++) {
+ idx->offset[i] = get_offset(cff, idx->offsize);
+ }
+
+ if (idx->offset[0] != 1)
+ CFF_ERROR("Invalid CFF Index offset data");
+
+ length = idx->offset[count] - idx->offset[0];
+
+ idx->data = xcalloc(length,sizeof(card8));
+ memcpy(idx->data,&cff->stream[cff->offset],length);
+ cff->offset += length;
+
+ } else {
+ idx->offsize = 0;
+ idx->offset = NULL;
+ idx->data = NULL;
+ }
+ return idx;
+}
+
+
+long
+cff_pack_index (cff_index *idx, card8 *dest, long destlen)
+{
+ long len = 0;
+ unsigned long datalen;
+ card16 i;
+
+ if (idx->count < 1) {
+ if (destlen < 2)
+ CFF_ERROR("Not enough space available...");
+ memset(dest, 0, 2);
+ return 2;
+ }
+
+ len = cff_index_size(idx);
+ datalen = idx->offset[idx->count] - 1;
+
+ if (destlen < len)
+ CFF_ERROR("Not enough space available...");
+
+ *(dest++) = (idx->count >> 8) & 0xff;
+ *(dest++) = idx->count & 0xff;
+
+ if (datalen < 0xffUL) {
+ idx->offsize = 1;
+ *(dest++) = 1;
+ for (i = 0; i <= idx->count; i++) {
+ *(dest++) = (card8) (idx->offset[i] & 0xff);
+ }
+ } else if (datalen < 0xffffUL) {
+ idx->offsize = 2;
+ *(dest++) = 2;
+ for (i = 0; i <= idx->count; i++) {
+ *(dest++) = (card8) ((idx->offset[i] >> 8) & 0xff);
+ *(dest++) = (card8) ( idx->offset[i] & 0xff);
+ }
+ } else if (datalen < 0xffffffUL) {
+ idx->offsize = 3;
+ *(dest++) = 3;
+ for (i = 0; i <= idx->count; i++) {
+ *(dest++) = (card8)((idx->offset[i] >> 16) & 0xff);
+ *(dest++) = (card8)((idx->offset[i] >> 8) & 0xff);
+ *(dest++) = (card8)(idx->offset[i] & 0xff);
+ }
+ } else {
+ idx->offsize = 4;
+ *(dest++) = 4;
+ for (i = 0; i <= idx->count; i++) {
+ *(dest++) = (card8)((idx->offset[i] >> 24) & 0xff);
+ *(dest++) = (card8)((idx->offset[i] >> 16) & 0xff);
+ *(dest++) = (card8)((idx->offset[i] >> 8) & 0xff);
+ *(dest++) = (card8)(idx->offset[i] & 0xff);
+ }
+ }
+
+ memmove(dest, idx->data, idx->offset[idx->count] - 1);
+
+ return len;
+}
+
+long
+cff_index_size (cff_index *idx)
+{
+ if (idx->count > 0) {
+ l_offset datalen;
+
+ datalen = idx->offset[idx->count] - 1;
+ if (datalen < 0xffUL) {
+ idx->offsize = 1;
+ } else if (datalen < 0xffffUL) {
+ idx->offsize = 2;
+ } else if (datalen < 0xffffffUL) {
+ idx->offsize = 3;
+ } else {
+ idx->offsize = 4;
+ }
+ return (3 + (idx->offsize)*(idx->count + 1) + datalen);
+ } else {
+ return 2;
+ }
+}
+
+cff_index *cff_new_index (card16 count)
+{
+ cff_index *idx;
+
+ idx = xcalloc(1, sizeof(cff_index));
+ idx->count = count;
+ idx->offsize = 0;
+
+ if (count > 0) {
+ idx->offset = xcalloc(count + 1, sizeof(l_offset));
+ (idx->offset)[0] = 1;
+ } else {
+ idx->offset = NULL;
+ }
+ idx->data = NULL;
+
+ return idx;
+}
+
+
+void cff_release_index (cff_index *idx)
+{
+ if (idx) {
+ xfree(idx->data);
+ xfree(idx->offset);
+ xfree(idx);
+ }
+}
+
+void cff_release_dict (cff_dict *dict)
+{
+ if (dict) {
+ if (dict->entries) {
+ int i;
+ for (i=0;i<dict->count;i++) {
+ xfree((dict->entries)[i].values);
+ }
+ xfree(dict->entries);
+ }
+ xfree(dict);
+ }
+}
+
+
+void cff_release_encoding (cff_encoding *encoding)
+{
+ if (encoding) {
+ switch (encoding->format & (~0x80)) {
+ case 0: xfree(encoding->data.codes); break;
+ case 1: xfree(encoding->data.range1); break;
+ default: CFF_ERROR("Unknown Encoding format.");
+ }
+ if (encoding->format & 0x80)
+ xfree(encoding->supp);
+ xfree(encoding);
+ }
+}
+
+void
+cff_release_charsets (cff_charsets *charset)
+{
+ if (charset) {
+ switch (charset->format) {
+ case 0: xfree(charset->data.glyphs); break;
+ case 1: xfree(charset->data.range1); break;
+ case 2: xfree(charset->data.range2); break;
+ default: break;
+ }
+ xfree(charset);
+ }
+}
+
+void cff_release_fdselect (cff_fdselect *fdselect)
+{
+ if (fdselect) {
+ if (fdselect->format == 0) { xfree(fdselect->data.fds); }
+ else if (fdselect->format == 3) { xfree(fdselect->data.ranges); }
+ xfree(fdselect);
+ }
+}
+
+
+void
+cff_close (cff_font *cff)
+{
+ card16 i;
+
+ if (cff) {
+ if (cff->fontname) xfree(cff->fontname);
+ if (cff->name) cff_release_index(cff->name);
+ if (cff->topdict) cff_release_dict(cff->topdict);
+ if (cff->string) cff_release_index(cff->string);
+ if (cff->gsubr) cff_release_index(cff->gsubr);
+ if (cff->encoding) cff_release_encoding(cff->encoding);
+ if (cff->charsets) cff_release_charsets(cff->charsets);
+ if (cff->fdselect) cff_release_fdselect(cff->fdselect);
+ if (cff->cstrings) cff_release_index(cff->cstrings);
+ if (cff->fdarray) {
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->fdarray[i]) cff_release_dict(cff->fdarray[i]);
+ }
+ xfree(cff->fdarray);
+ }
+ if (cff->private) {
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->private[i]) cff_release_dict(cff->private[i]);
+ }
+ xfree(cff->private);
+ }
+ if (cff->subrs) {
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->subrs[i]) cff_release_index(cff->subrs[i]);
+ }
+ xfree(cff->subrs);
+ }
+ if (cff->_string)
+ cff_release_index(cff->_string);
+ xfree(cff);
+ }
+
+ return;
+}
+
+char *
+cff_get_name (cff_font *cff)
+{
+ char *fontname;
+ l_offset len;
+ cff_index *idx;
+
+ idx = cff->name;
+ len = idx->offset[cff->index + 1] - idx->offset[cff->index];
+ fontname = xmalloc((len + 1)*sizeof(char));
+ memcpy(fontname, idx->data + idx->offset[cff->index] - 1, len);
+ fontname[len] = '\0';
+
+ return fontname;
+}
+
+
+long
+cff_set_name (cff_font *cff, char *name)
+{
+ cff_index *idx;
+
+ if (strlen(name) > 127)
+ CFF_ERROR("FontName string length too large...");
+
+ if (cff->name)
+ cff_release_index(cff->name);
+
+ cff->name = idx = xcalloc(1, sizeof(cff_index));
+ idx->count = 1;
+ idx->offsize = 1;
+ idx->offset = xmalloc(2*sizeof(l_offset));
+ (idx->offset)[0] = 1;
+ (idx->offset)[1] = strlen(name) + 1;
+ idx->data = xcalloc(strlen(name), sizeof(card8));
+ memmove(idx->data, name, strlen(name)); /* no trailing '\0' */
+
+ return 5 + strlen(name);
+}
+
+long
+cff_put_header (cff_font *cff, card8 *dest, long destlen)
+{
+ if (destlen < 4)
+ CFF_ERROR("Not enough space available...");
+
+ *(dest++) = cff->header_major;
+ *(dest++) = cff->header_minor;
+ *(dest++) = 4; /* Additional data in between header and
+ * Name INDEX ignored.
+ */
+ /* We will set all offset (0) to four-byte integer. */
+ *(dest++) = 4;
+ cff->header_offsize = 4;
+
+ return 4;
+}
+
+#define CFF_PARSE_OK 0
+#define CFF_CFF_ERROR_PARSE_CFF_ERROR -1
+#define CFF_CFF_ERROR_STACK_OVERFLOW -2
+#define CFF_CFF_ERROR_STACK_UNDERFLOW -3
+#define CFF_CFF_ERROR_STACK_RANGECHECK -4
+
+#define DICT_ENTRY_MAX 16
+
+cff_dict *cff_new_dict (void)
+{
+ cff_dict *dict;
+
+ dict = xcalloc(1, sizeof(cff_dict));
+ dict->max = DICT_ENTRY_MAX;
+ dict->count = 0;
+ dict->entries = xcalloc(dict->max, sizeof(cff_dict_entry));
+ return dict;
+}
+
+/*
+ * Operand stack:
+ * only numbers are stored (as double)
+ *
+ * Operand types:
+ *
+ * number : double (integer or real)
+ * boolean: stored as a number
+ * SID : stored as a number
+ * array : array of numbers
+ * delta : array of numbers
+ */
+
+#define CFF_DICT_STACK_LIMIT 64
+static int stack_top = 0;
+static double arg_stack[CFF_DICT_STACK_LIMIT];
+
+/*
+ * CFF DICT encoding:
+ * TODO: default values
+ */
+
+#define CFF_LAST_DICT_OP1 22
+#define CFF_LAST_DICT_OP2 39
+#define CFF_LAST_DICT_OP (CFF_LAST_DICT_OP1 + CFF_LAST_DICT_OP2)
+
+static struct {
+ const char *opname;
+ int argtype;
+} dict_operator[CFF_LAST_DICT_OP] = {
+ {"version", CFF_TYPE_SID},
+ {"Notice", CFF_TYPE_SID},
+ {"FullName", CFF_TYPE_SID},
+ {"FamilyName", CFF_TYPE_SID},
+ {"Weight", CFF_TYPE_SID},
+ {"FontBBox", CFF_TYPE_ARRAY},
+ {"BlueValues", CFF_TYPE_DELTA},
+ {"OtherBlues", CFF_TYPE_DELTA},
+ {"FamilyBlues", CFF_TYPE_DELTA},
+ {"FamilyOtherBlues", CFF_TYPE_DELTA},
+ {"StdHW", CFF_TYPE_NUMBER},
+ {"StdVW", CFF_TYPE_NUMBER},
+ {NULL, -1}, /* first byte of two-byte operator */
+ /* Top */
+ {"UniqueID", CFF_TYPE_NUMBER},
+ {"XUID", CFF_TYPE_ARRAY},
+ {"charset", CFF_TYPE_OFFSET},
+ {"Encoding", CFF_TYPE_OFFSET},
+ {"CharStrings", CFF_TYPE_OFFSET},
+ {"Private", CFF_TYPE_SZOFF}, /* two numbers (size and offset) */
+ /* Private */
+ {"Subrs", CFF_TYPE_OFFSET},
+ {"defaultWidthX", CFF_TYPE_NUMBER},
+ {"nominalWidthX", CFF_TYPE_NUMBER},
+ /* Operator 2 */
+ {"Copyright", CFF_TYPE_SID},
+ {"IsFixedPitch", CFF_TYPE_BOOLEAN},
+ {"ItalicAngle", CFF_TYPE_NUMBER},
+ {"UnderlinePosition", CFF_TYPE_NUMBER},
+ {"UnderlineThickness", CFF_TYPE_NUMBER},
+ {"PaintType", CFF_TYPE_NUMBER},
+ {"CharstringType", CFF_TYPE_NUMBER},
+ {"FontMatrix", CFF_TYPE_ARRAY},
+ {"StrokeWidth", CFF_TYPE_NUMBER},
+ {"BlueScale", CFF_TYPE_NUMBER},
+ {"BlueShift", CFF_TYPE_NUMBER},
+ {"BlueFuzz", CFF_TYPE_NUMBER},
+ {"StemSnapH", CFF_TYPE_DELTA},
+ {"StemSnapV", CFF_TYPE_DELTA},
+ {"ForceBold", CFF_TYPE_BOOLEAN},
+ {NULL, -1},
+ {NULL, -1},
+ {"LanguageGroup", CFF_TYPE_NUMBER},
+ {"ExpansionFactor", CFF_TYPE_NUMBER},
+ {"InitialRandomSeed", CFF_TYPE_NUMBER},
+ {"SyntheticBase", CFF_TYPE_NUMBER},
+ {"PostScript", CFF_TYPE_SID},
+ {"BaseFontName", CFF_TYPE_SID},
+ {"BaseFontBlend", CFF_TYPE_DELTA}, /* MMaster ? */
+ {NULL, -1},
+ {NULL, -1},
+ {NULL, -1},
+ {NULL, -1},
+ {NULL, -1},
+ {NULL, -1},
+ /* CID-Keyed font */
+ {"ROS", CFF_TYPE_ROS}, /* SID SID number */
+ {"CIDFontVersion", CFF_TYPE_NUMBER},
+ {"CIDFontRevision", CFF_TYPE_NUMBER},
+ {"CIDFontType", CFF_TYPE_NUMBER},
+ {"CIDCount", CFF_TYPE_NUMBER},
+ {"UIDBase", CFF_TYPE_NUMBER},
+ {"FDArray", CFF_TYPE_OFFSET},
+ {"FDSelect", CFF_TYPE_OFFSET},
+ {"FontName", CFF_TYPE_SID},
+};
+
+/* Parse DICT data */
+static double get_integer (card8 **data, card8 *endptr, int *status)
+{
+ long result = 0;
+ card8 b0, b1, b2;
+
+ b0 = *(*data)++;
+ if (b0 == 28 && *data < endptr - 2) { /* shortint */
+ b1 = *(*data)++;
+ b2 = *(*data)++;
+ result = b1*256+b2;
+ if (result > 0x7fffL)
+ result -= 0x10000L;
+ } else if (b0 == 29 && *data < endptr - 4) { /* longint */
+ int i;
+ result = *(*data)++;
+ if (result > 0x7f)
+ result -= 0x100;
+ for (i=0;i<3;i++) {
+ result = result*256+(**data);
+ *data += 1;
+ }
+ } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
+ result = b0 - 139;
+ } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
+ b1 = *(*data)++;
+ result = (b0-247)*256+b1+108;
+ } else if (b0 >= 251 && b0 <= 254) {
+ b1 = *(*data)++;
+ result = -(b0-251)*256-b1-108;
+ } else {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ }
+
+ return (double) result;
+}
+
+/* Simply uses strtod */
+static double get_real(card8 **data, card8 *endptr, int *status)
+{
+ double result = 0.0;
+ int nibble = 0, pos = 0;
+ int len = 0, fail = 0;
+
+ if (**data != 30 || *data >= endptr -1) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ return 0.0;
+ }
+
+ *data += 1; /* skip first byte (30) */
+
+ pos = 0;
+ while ((! fail) && len < WORK_BUFFER_SIZE - 2 && *data < endptr) {
+ /* get nibble */
+ if (pos % 2) {
+ nibble = **data & 0x0f;
+ *data += 1;
+ } else {
+ nibble = (**data >> 4) & 0x0f;
+ }
+ if (nibble >= 0x00 && nibble <= 0x09) {
+ work_buffer[len++] = nibble + '0';
+ } else if (nibble == 0x0a) { /* . */
+ work_buffer[len++] = '.';
+ } else if (nibble == 0x0b || nibble == 0x0c) { /* E, E- */
+ work_buffer[len++] = 'e';
+ if (nibble == 0x0c)
+ work_buffer[len++] = '-';
+ } else if (nibble == 0x0e) { /* `-' */
+ work_buffer[len++] = '-';
+ } else if (nibble == 0x0d) { /* skip */
+ /* do nothing */
+ } else if (nibble == 0x0f) { /* end */
+ work_buffer[len++] = '\0';
+ if (((pos % 2) == 0) && (**data != 0xff)) {
+ fail = 1;
+ }
+ break;
+ } else { /* invalid */
+ fail = 1;
+ }
+ pos++;
+ }
+
+ /* returned values */
+ if (fail || nibble != 0x0f) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ } else {
+ char *s;
+ result = strtod(work_buffer, &s);
+ if (*s != 0 || errno == ERANGE) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ }
+ }
+
+ return result;
+}
+
+/* operators */
+static void add_dict (cff_dict *dict,
+ card8 **data, card8 *endptr, int *status)
+{
+ int id, argtype;
+
+ id = **data;
+ if (id == 0x0c) {
+ *data += 1;
+ if (*data >= endptr ||
+ (id = **data + CFF_LAST_DICT_OP1) >= CFF_LAST_DICT_OP) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ return;
+ }
+ } else if (id >= CFF_LAST_DICT_OP1) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ return;
+ }
+
+ argtype = dict_operator[id].argtype;
+ if (dict_operator[id].opname == NULL || argtype < 0) {
+ *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
+ return;
+ } else if (stack_top < 1) {
+ *status = CFF_CFF_ERROR_STACK_UNDERFLOW;
+ return;
+ }
+
+ if (dict->count >= dict->max) {
+ dict->max += DICT_ENTRY_MAX;
+ /* not zeroed! */
+ dict->entries = xrealloc(dict->entries, dict->max*sizeof(cff_dict_entry));
+ }
+
+ (dict->entries)[dict->count].id = id;
+ (dict->entries)[dict->count].key = (char *) dict_operator[id].opname;
+ if (argtype == CFF_TYPE_NUMBER ||
+ argtype == CFF_TYPE_BOOLEAN ||
+ argtype == CFF_TYPE_SID ||
+ argtype == CFF_TYPE_OFFSET) {
+ stack_top--;
+ (dict->entries)[dict->count].count = 1;
+ (dict->entries)[dict->count].values = xcalloc(1, sizeof(double));
+ (dict->entries)[dict->count].values[0] = arg_stack[stack_top];
+ } else {
+ (dict->entries)[dict->count].count = stack_top;
+ (dict->entries)[dict->count].values = xcalloc(stack_top, sizeof(double));
+ while (stack_top > 0) {
+ stack_top--;
+ (dict->entries)[dict->count].values[stack_top] = arg_stack[stack_top];
+ }
+ }
+
+ dict->count += 1;
+ *data += 1;
+
+ return;
+}
+
+/*
+ * All operands are treated as number or array of numbers.
+ * Private: two numbers, size and offset
+ * ROS : three numbers, SID, SID, and a number
+ */
+cff_dict *cff_dict_unpack (card8 *data, card8 *endptr)
+{
+ cff_dict *dict;
+ int status = CFF_PARSE_OK;
+
+ stack_top = 0;
+
+ dict = cff_new_dict();
+ while (data < endptr && status == CFF_PARSE_OK) {
+ if (*data < 22) { /* operator */
+ add_dict(dict, &data, endptr, &status);
+ } else if (*data == 30) { /* real - First byte of a sequence (variable) */
+ if (stack_top < CFF_DICT_STACK_LIMIT) {
+ arg_stack[stack_top] = get_real(&data, endptr, &status);
+ stack_top++;
+ } else {
+ status = CFF_CFF_ERROR_STACK_OVERFLOW;
+ }
+ } else if (*data == 255 || (*data >= 22 && *data <= 27)) { /* reserved */
+ data++;
+ } else { /* everything else are integer */
+ if (stack_top < CFF_DICT_STACK_LIMIT) {
+ arg_stack[stack_top] = get_integer(&data, endptr, &status);
+ stack_top++;
+ } else {
+ status = CFF_CFF_ERROR_STACK_OVERFLOW;
+ }
+ }
+ }
+
+ if (status != CFF_PARSE_OK) {
+ pdftex_fail("Parsing CFF DICT failed. (error=%d)", status);
+ } else if (stack_top != 0) {
+ WARN("Garbage in CFF DICT data.");
+ stack_top = 0;
+ }
+
+ return dict;
+}
+
+
+int cff_dict_known (cff_dict *dict, const char *key)
+{
+ int i;
+
+ for (i = 0; i < dict->count; i++) {
+ if (key && strcmp(key, (dict->entries)[i].key) == 0
+ && (dict->entries)[i].count > 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+double cff_dict_get (cff_dict *dict, const char *key, int idx)
+{
+ double value = 0.0;
+ int i;
+
+ assert(key && dict);
+
+ for (i = 0; i < dict->count; i++) {
+ if (strcmp(key, (dict->entries)[i].key) == 0) {
+ if ((dict->entries)[i].count > idx)
+ value = (dict->entries)[i].values[idx];
+ else
+ pdftex_fail("Invalid index number.");
+ break;
+ }
+ }
+
+ if (i == dict->count)
+ pdftex_fail("DICT entry \"%s\" not found.", key);
+
+ return value;
+}
+
+card8 cff_fdselect_lookup (cff_font *cff, card16 gid)
+{
+ card8 fd = 0xff;
+ cff_fdselect *fdsel;
+
+ if (cff->fdselect == NULL)
+ CFF_ERROR("in cff_fdselect_lookup(): FDSelect not available");
+
+ fdsel = cff->fdselect;
+
+ if (gid >= cff->num_glyphs)
+ CFF_ERROR("in cff_fdselect_lookup(): Invalid glyph index");
+
+ switch (fdsel->format) {
+ case 0:
+ fd = fdsel->data.fds[gid];
+ break;
+ case 3:
+ {
+ if (gid == 0) {
+ fd = (fdsel->data).ranges[0].fd;
+ } else {
+ card16 i;
+ for (i=1;i<(fdsel->num_entries);i++) {
+ if (gid < (fdsel->data).ranges[i].first)
+ break;
+ }
+ fd = (fdsel->data).ranges[i-1].fd;
+ }
+ }
+ break;
+ default:
+ CFF_ERROR("in cff_fdselect_lookup(): Invalid FDSelect format");
+ break;
+ }
+
+ if (fd >= cff->num_fds)
+ CFF_ERROR("in cff_fdselect_lookup(): Invalid Font DICT index");
+
+ return fd;
+}
+
+long cff_read_subrs (cff_font *cff)
+{
+ long len = 0;
+ long offset;
+ int i;
+
+
+ if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdselect == NULL) {
+ cff_read_fdselect(cff);
+ }
+
+ if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdarray == NULL) {
+ cff_read_fdarray(cff);
+ }
+
+ if (cff->private == NULL)
+ cff_read_private(cff);
+
+ if (cff->gsubr == NULL) {
+ cff->offset = cff->gsubr_offset;
+ cff->gsubr = cff_get_index(cff);
+ }
+
+ cff->subrs = xcalloc(cff->num_fds, sizeof(cff_index *));
+ if (cff->flag & FONTTYPE_CIDFONT) {
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->private[i] == NULL ||
+ !cff_dict_known(cff->private[i], "Subrs")) {
+ (cff->subrs)[i] = NULL;
+ } else {
+ offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1);
+ offset += (long) cff_dict_get(cff->private[i], "Subrs", 0);
+ cff->offset = offset;
+ (cff->subrs)[i] = cff_get_index(cff);
+ len += cff_index_size((cff->subrs)[i]);
+ }
+ }
+ } else {
+ if (cff->private[0] == NULL ||
+ !cff_dict_known(cff->private[0], "Subrs")) {
+ (cff->subrs)[0] = NULL;
+ } else {
+ offset = (long) cff_dict_get(cff->topdict, "Private", 1);
+ offset += (long) cff_dict_get(cff->private[0], "Subrs", 0);
+ cff->offset = offset;
+ (cff->subrs)[0] = cff_get_index(cff);
+ len += cff_index_size((cff->subrs)[0]);
+ }
+ }
+
+ return len;
+}
+
+
+long cff_read_fdarray (cff_font *cff)
+{
+ long len = 0;
+ cff_index *idx;
+ long offset, size;
+ card16 i;
+
+ if (cff->topdict == NULL)
+ CFF_ERROR("in cff_read_fdarray(): Top DICT not found");
+
+ if (!(cff->flag & FONTTYPE_CIDFONT))
+ return 0;
+
+ /* must exist */
+ offset = (long) cff_dict_get(cff->topdict, "FDArray", 0);
+ cff->offset = offset;
+ idx = cff_get_index(cff);
+ cff->num_fds = (card8)idx->count;
+ cff->fdarray = xcalloc(idx->count, sizeof(cff_dict *));
+ for (i=0;i<idx->count;i++) {
+ card8 *data = idx->data + (idx->offset)[i] - 1;
+ size = (idx->offset)[i+1] - (idx->offset)[i];
+ if (size > 0) {
+ (cff->fdarray)[i] = cff_dict_unpack(data, data+size);
+ } else {
+ (cff->fdarray)[i] = NULL;
+ }
+ }
+ len = cff_index_size(idx);
+ cff_release_index(idx);
+
+ return len;
+}
+
+
+long cff_read_private (cff_font *cff)
+{
+ long len = 0;
+ card8 *data;
+ long offset, size;
+
+ if (cff->flag & FONTTYPE_CIDFONT) {
+ int i;
+
+ if (cff->fdarray == NULL)
+ cff_read_fdarray(cff);
+
+ cff->private = xcalloc(cff->num_fds, sizeof(cff_dict *));
+ for (i=0;i<cff->num_fds;i++) {
+ if (cff->fdarray[i] != NULL &&
+ cff_dict_known(cff->fdarray[i], "Private") &&
+ (size = (long) cff_dict_get(cff->fdarray[i], "Private", 0))
+ > 0) {
+ offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1);
+ cff->offset = offset;
+ data = xcalloc(size, sizeof(card8));
+ memcpy(data,&cff->stream[cff->offset],size);
+ cff->offset = size;
+ (cff->private)[i] = cff_dict_unpack(data, data+size);
+ xfree(data);
+ len += size;
+ } else {
+ (cff->private)[i] = NULL;
+ }
+ }
+ } else {
+ cff->num_fds = 1;
+ cff->private = xcalloc(1, sizeof(cff_dict *));
+ if (cff_dict_known(cff->topdict, "Private") &&
+ (size = (long) cff_dict_get(cff->topdict, "Private", 0)) > 0) {
+ offset = (long) cff_dict_get(cff->topdict, "Private", 1);
+ cff->offset = offset;
+ data = xcalloc(size, sizeof(card8));
+ memcpy(data,&cff->stream[cff->offset],size);
+ cff->offset = size;
+ cff->private[0] = cff_dict_unpack(data, data+size);
+ xfree(data);
+ len += size;
+ } else {
+ (cff->private)[0] = NULL;
+ len = 0;
+ }
+ }
+
+ return len;
+}
+
+
+cff_font *read_cff (unsigned char *buf,long buflength, int n)
+{
+ cff_font *cff;
+ cff_index *idx;
+ long offset ;
+
+
+ cff = xcalloc(1,sizeof(cff_font));
+
+ cff->stream = buf;
+ cff->stream_size = buflength;
+ cff->index = n;
+
+ cff->header_major = get_card8(cff);
+ cff->header_minor = get_card8(cff);
+ cff->header_hdr_size = get_card8(cff);
+ cff->header_offsize = get_card8(cff);
+ if (cff->header_offsize < 1 || cff->header_offsize > 4) {
+ WARN("invalid offsize data");
+ cff_close(cff);
+ return NULL;
+ }
+ if (cff->header_major > 1) {
+ pdftex_warn("CFF major version %u not supported.",cff->header_major);
+ cff_close(cff);
+ return NULL;
+ }
+ cff->offset = cff->header_hdr_size;
+
+ /* Name INDEX */
+ idx = cff_get_index(cff);
+ if (n > idx->count - 1) {
+ pdftex_warn("Invalid CFF fontset index number.");
+ cff_close(cff);
+ return NULL;
+ }
+
+ cff->name = idx;
+
+ cff->fontname = cff_get_name(cff);
+
+ /* Top DICT INDEX */
+ idx = cff_get_index(cff);
+ if (n > idx->count - 1) {
+ WARN("CFF Top DICT not exist...");
+ cff_close(cff);
+ return NULL;
+ }
+ cff->topdict = cff_dict_unpack(idx->data + idx->offset[n] - 1,
+ idx->data + idx->offset[n + 1] - 1);
+ if (!cff->topdict) {
+ WARN("Parsing CFF Top DICT data failed...");
+ cff_close(cff);
+ return NULL;
+ }
+ cff_release_index(idx);
+
+ if (cff_dict_known(cff->topdict, "CharstringType") &&
+ cff_dict_get(cff->topdict, "CharstringType", 0) != 2) {
+ WARN("Only Type 2 Charstrings supported...");
+ cff_close(cff);
+ return NULL;
+ }
+
+ if (cff_dict_known(cff->topdict, "SyntheticBase")) {
+ WARN("CFF Synthetic font not supported.");
+ cff_close(cff);
+ return NULL;
+ }
+
+ /* String INDEX */
+ cff->string = cff_get_index(cff);
+
+ /* offset to GSubr */
+ cff->gsubr_offset = cff->offset;
+
+ /* Number of glyphs */
+ offset = (long) cff_dict_get(cff->topdict, "CharStrings", 0);
+ cff->offset = offset;
+ cff->num_glyphs = get_card16(cff);
+
+ /* Check for font type */
+ if (cff_dict_known(cff->topdict, "ROS")) {
+ cff->flag |= FONTTYPE_CIDFONT;
+ } else {
+ cff->flag |= FONTTYPE_FONT;
+ }
+
+ /* Check for encoding */
+ if (cff_dict_known(cff->topdict, "Encoding")) {
+ offset = (long) cff_dict_get(cff->topdict, "Encoding", 0);
+ if (offset == 0) { /* predefined */
+ cff->flag |= ENCODING_STANDARD;
+ } else if (offset == 1) {
+ cff->flag |= ENCODING_EXPERT;
+ }
+ } else {
+ cff->flag |= ENCODING_STANDARD;
+ }
+
+ cff->offset = cff->gsubr_offset; /* seek back to GSubr */
+
+ return cff;
+}
+
+/* write a cff for opentype */
+
+
+
+/* Pack DICT data */
+static long pack_integer (card8 *dest, long destlen, long value)
+{
+ long len = 0;
+
+ if (value >= -107 && value <= 107) {
+ if (destlen < 1)
+ CFF_ERROR("Buffer overflow.");
+ dest[0] = (value + 139) & 0xff;
+ len = 1;
+ } else if (value >= 108 && value <= 1131) {
+ if (destlen < 2)
+ CFF_ERROR("Buffer overflow.");
+ value = 0xf700u + value - 108;
+ dest[0] = (value >> 8) & 0xff;
+ dest[1] = value & 0xff;
+ len = 2;
+ } else if (value >= -1131 && value <= -108) {
+ if (destlen < 2)
+ CFF_ERROR("Buffer overflow.");
+ value = 0xfb00u - value - 108;
+ dest[0] = (value >> 8) & 0xff;
+ dest[1] = value & 0xff;
+ len = 2;
+ } else if (value >= -32768 && value <= 32767) { /* shortint */
+ if (destlen < 3)
+ CFF_ERROR("Buffer overflow.");
+ dest[0] = 28;
+ dest[1] = (value >> 8) & 0xff;
+ dest[2] = value & 0xff;
+ len = 3;
+ } else { /* longint */
+ if (destlen < 5)
+ CFF_ERROR("Buffer overflow.");
+ dest[0] = 29;
+ dest[1] = (value >> 24) & 0xff;
+ dest[2] = (value >> 16) & 0xff;
+ dest[3] = (value >> 8) & 0xff;
+ dest[4] = value & 0xff;
+ len = 5;
+ }
+ return len;
+}
+
+static long pack_real (card8 *dest, long destlen, double value)
+{
+ long e;
+ int i = 0, pos = 2;
+#define CFF_REAL_MAX_LEN 17
+
+ if (destlen < 2)
+ CFF_ERROR("Buffer overflow.");
+
+ dest[0] = 30;
+
+ if (value == 0.0) {
+ dest[1] = 0x0f;
+ return 2;
+ }
+
+ if (value < 0.0) {
+ dest[1] = 0xe0;
+ value *= -1.0;
+ pos++;
+ }
+
+ e = 0;
+ if (value >= 10.0) {
+ while (value >= 10.0) {
+ value /= 10.0;
+ e++;
+ }
+ } else if (value < 1.0) {
+ while (value < 1.0) {
+ value *= 10.0;
+ e--;
+ }
+ }
+
+ sprintf(work_buffer, "%1.14g", value);
+ for (i=0;i<CFF_REAL_MAX_LEN;i++) {
+ unsigned char ch = 0;
+ if (work_buffer[i] == '\0') {
+ break;
+ } else if (work_buffer[i] == '.') {
+ ch = 0x0a;
+ } else if (work_buffer[i] >= '0' && work_buffer[i] <= '9') {
+ ch = work_buffer[i] - '0';
+ } else {
+ CFF_ERROR("Invalid character.");
+ }
+
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+
+ if (pos % 2) {
+ dest[pos/2] += ch;
+ } else {
+ dest[pos/2] = (ch << 4);
+ }
+ pos++;
+ }
+
+ if (e > 0) {
+ if (pos % 2) {
+ dest[pos/2] += 0x0b;
+ } else {
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+ dest[pos/2] = 0xb0;
+ }
+ pos++;
+ } else if (e < 0) {
+ if (pos % 2) {
+ dest[pos/2] += 0x0c;
+ } else {
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+ dest[pos/2] = 0xc0;
+ }
+ e *= -1;
+ pos++;
+ }
+
+ if (e != 0) {
+ sprintf(work_buffer, "%ld", e);
+ for (i=0;i<CFF_REAL_MAX_LEN;i++) {
+ unsigned char ch = 0;
+ if (work_buffer[i] == '\0') {
+ break;
+ } else if (work_buffer[i] == '.') {
+ ch = 0x0a;
+ } else if (work_buffer[i] >= '0' && work_buffer[i] <= '9') {
+ ch = work_buffer[i] - '0';
+ } else {
+ CFF_ERROR("Invalid character.");
+ }
+
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+
+ if (pos % 2) {
+ dest[pos/2] += ch;
+ } else {
+ dest[pos/2] = (ch << 4);
+ }
+ pos++;
+ }
+ }
+
+ if (pos % 2) {
+ dest[pos/2] += 0x0f;
+ pos++;
+ } else {
+ if (destlen < pos/2 + 1)
+ CFF_ERROR("Buffer overflow.");
+ dest[pos/2] = 0xff;
+ pos += 2;
+ }
+
+ return pos/2;
+}
+
+static long cff_dict_put_number (double value,
+ card8 *dest, long destlen,
+ int type)
+{
+ long len = 0;
+ double nearint;
+
+ nearint = floor(value+0.5);
+ /* set offset to longint */
+ if (type == CFF_TYPE_OFFSET) {
+ long lvalue;
+
+ lvalue = (long) value;
+ if (destlen < 5)
+ CFF_ERROR("Buffer overflow.");
+ dest[0] = 29;
+ dest[1] = (lvalue >> 24) & 0xff;
+ dest[2] = (lvalue >> 16) & 0xff;
+ dest[3] = (lvalue >> 8) & 0xff;
+ dest[4] = lvalue & 0xff;
+ len = 5;
+ } else if (value > CFF_INT_MAX || value < CFF_INT_MIN ||
+ (fabs(value - nearint) > 1.0e-5)) { /* real */
+ len = pack_real(dest, destlen, value);
+ } else { /* integer */
+ len = pack_integer(dest, destlen, (long) nearint);
+ }
+
+ return len;
+}
+
+static long
+put_dict_entry (cff_dict_entry *de,
+ card8 *dest, long destlen)
+{
+ long len = 0;
+ int i, type, id;
+
+ if (de->count > 0) {
+ id = de->id;
+ if (dict_operator[id].argtype == CFF_TYPE_OFFSET ||
+ dict_operator[id].argtype == CFF_TYPE_SZOFF) {
+ type = CFF_TYPE_OFFSET;
+ } else {
+ type = CFF_TYPE_NUMBER;
+ }
+ for (i = 0; i < de->count; i++) {
+ len += cff_dict_put_number(de->values[i],
+ dest+len,
+ destlen-len, type);
+ }
+ if (id >= 0 && id < CFF_LAST_DICT_OP1) {
+ if (len + 1 > destlen)
+ CFF_ERROR("Buffer overflow.");
+ dest[len++] = id;
+ } else if (id >= 0 && id < CFF_LAST_DICT_OP) {
+ if (len + 2 > destlen)
+ CFF_ERROR("in cff_dict_pack(): Buffer overflow");
+ dest[len++] = 12;
+ dest[len++] = id - CFF_LAST_DICT_OP1;
+ } else {
+ CFF_ERROR("Invalid CFF DICT operator ID.");
+ }
+ }
+
+ return len;
+}
+
+long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen)
+{
+ long len = 0;
+ int i;
+
+ for (i = 0; i < dict->count; i++) {
+ if (!strcmp(dict->entries[i].key, "ROS")) {
+ len += put_dict_entry(&dict->entries[i], dest, destlen);
+ break;
+ }
+ }
+ for (i = 0; i < dict->count; i++) {
+ if (strcmp(dict->entries[i].key, "ROS")) {
+ len += put_dict_entry(&dict->entries[i], dest+len, destlen-len);
+ }
+ }
+
+ return len;
+}
+
+
+void cff_dict_add (cff_dict *dict, const char *key, int count)
+{
+ int id, i;
+
+ for (id=0;id<CFF_LAST_DICT_OP;id++) {
+ if (key && dict_operator[id].opname &&
+ strcmp(dict_operator[id].opname, key) == 0)
+ break;
+ }
+
+ if (id == CFF_LAST_DICT_OP)
+ CFF_ERROR("Unknown CFF DICT operator.");
+
+ for (i=0;i<dict->count;i++) {
+ if ((dict->entries)[i].id == id) {
+ if ((dict->entries)[i].count != count)
+ CFF_ERROR("Inconsistent DICT argument number.");
+ return;
+ }
+ }
+
+ if (dict->count + 1 >= dict->max) {
+ dict->max += 8;
+ dict->entries = xrealloc(dict->entries, (dict->max)*sizeof(cff_dict_entry));
+ }
+
+ (dict->entries)[dict->count].id = id;
+ (dict->entries)[dict->count].key = (char *) dict_operator[id].opname;
+ (dict->entries)[dict->count].count = count;
+ if (count > 0) {
+ (dict->entries)[dict->count].values = xcalloc(count, sizeof(double));
+ memset((dict->entries)[dict->count].values,
+ 0, sizeof(double)*count);
+ } else {
+ (dict->entries)[dict->count].values = NULL;
+ }
+ dict->count += 1;
+
+ return;
+}
+
+
+void cff_dict_remove (cff_dict *dict, const char *key)
+{
+ int i;
+ for (i = 0; i < dict->count; i++) {
+ if (key && strcmp(key, (dict->entries)[i].key) == 0) {
+ (dict->entries)[i].count = 0;
+ if ((dict->entries)[i].values)
+ xfree((dict->entries)[i].values);
+ (dict->entries)[i].values = NULL;
+ }
+ }
+}
+
+void cff_dict_set (cff_dict *dict, const char *key, int idx, double value)
+{
+ int i;
+
+ assert(dict && key);
+
+ for (i = 0 ; i < dict->count; i++) {
+ if (strcmp(key, (dict->entries)[i].key) == 0) {
+ if ((dict->entries)[i].count > idx)
+ (dict->entries)[i].values[idx] = value;
+ else
+ CFF_ERROR("Invalid index number.");
+ break;
+ }
+ }
+
+ if (i == dict->count)
+ pdftex_fail("DICT entry \"%s\" not found.", key);
+}
+
+
+/* Strings */
+char *cff_get_string (cff_font *cff, s_SID id)
+{
+ char *result = NULL;
+ long len;
+
+ if (id < CFF_STDSTR_MAX) {
+ len = strlen(cff_stdstr[id]);
+ result = xcalloc(len+1, sizeof(char));
+ memcpy(result, cff_stdstr[id], len);
+ result[len] = '\0';
+ } else if (cff && cff->string) {
+ cff_index *strings = cff->string;
+ id -= CFF_STDSTR_MAX;
+ if (id < strings->count) {
+ len = (strings->offset)[id+1] - (strings->offset)[id];
+ result = xcalloc(len + 1, sizeof(char));
+ memmove(result, strings->data + (strings->offset)[id] - 1, len);
+ result[len] = '\0';
+ }
+ }
+
+ return result;
+}
+
+long cff_get_sid (cff_font *cff, char *str)
+{
+ card16 i;
+
+ if (!cff || !str)
+ return -1;
+
+ /* I search String INDEX first. */
+ if (cff && cff->string) {
+ cff_index *idx = cff->string;
+ for (i = 0; i < idx->count; i++) {
+ if (strlen(str) == (idx->offset)[i+1] - (idx->offset)[i] &&
+ !memcmp(str, (idx->data)+(idx->offset)[i]-1, strlen(str)))
+ return (i + CFF_STDSTR_MAX);
+ }
+ }
+
+ for (i = 0; i < CFF_STDSTR_MAX; i++) {
+ if (!strcmp(str, cff_stdstr[i]))
+ return i;
+ }
+
+ return -1;
+}
+
+
+void cff_update_string (cff_font *cff)
+{
+ if (cff == NULL)
+ CFF_ERROR("CFF font not opened.");
+
+ if (cff->string)
+ cff_release_index(cff->string);
+ cff->string = cff->_string;
+ cff->_string = NULL;
+}
+
+
+s_SID cff_add_string (cff_font *cff, char *str)
+{
+ card16 idx;
+ cff_index *strings;
+ l_offset offset, size;
+
+ if (cff == NULL)
+ CFF_ERROR("CFF font not opened.");
+
+ if (cff->_string == NULL)
+ cff->_string = cff_new_index(0);
+ strings = cff->_string;
+
+ for (idx = 0; idx < strings->count; idx++) {
+ size = strings->offset[idx+1] - strings->offset[idx];
+ offset = strings->offset[idx];
+ if (size == strlen(str) &&
+ !memcmp(strings->data+offset-1, str, strlen(str)))
+ return (idx + CFF_STDSTR_MAX);
+ }
+
+ for (idx = 0; idx < CFF_STDSTR_MAX; idx++) {
+ if (cff_stdstr[idx] &&
+ !strcmp(cff_stdstr[idx], str))
+ return idx;
+ }
+ offset = (strings->count > 0) ? strings->offset[strings->count] : 1;
+ strings->offset = xrealloc(strings->offset, (strings->count+2)*sizeof(l_offset));
+ if (strings->count == 0)
+ strings->offset[0] = 1;
+ idx = strings->count;
+ strings->count += 1;
+ strings->offset[strings->count] = offset + strlen(str);
+ strings->data = xrealloc(strings->data, (offset+strlen(str)-1)*sizeof(card8));
+ memcpy(strings->data+offset-1, str, strlen(str));
+
+ return (idx + CFF_STDSTR_MAX);
+}
+
+
+void cff_dict_update (cff_dict *dict, cff_font *cff)
+{
+ int i;
+
+ for (i = 0;i < dict->count; i++) {
+ if ((dict->entries)[i].count > 0) {
+ char *str;
+ int id;
+
+ id = (dict->entries)[i].id;
+
+ if (dict_operator[id].argtype == CFF_TYPE_SID) {
+ str = cff_get_string(cff, (dict->entries)[i].values[0]);
+ (dict->entries)[i].values[0] = cff_add_string(cff, str);
+ xfree(str);
+ } else if (dict_operator[id].argtype == CFF_TYPE_ROS) {
+ str = cff_get_string(cff, (dict->entries)[i].values[0]);
+ (dict->entries)[i].values[0] = cff_add_string(cff, str);
+ xfree(str);
+ str = cff_get_string(cff, (dict->entries)[i].values[1]);
+ (dict->entries)[i].values[1] = cff_add_string(cff, str);
+ xfree(str);
+ }
+
+ }
+ }
+}
+
+/* charsets */
+
+long cff_read_charsets (cff_font *cff)
+{
+ cff_charsets *charset;
+ long offset, length;
+ card16 count, i;
+
+ if (cff->topdict == NULL)
+ CFF_ERROR("Top DICT not available");
+
+ if (!cff_dict_known(cff->topdict, "charset")) {
+ cff->flag |= CHARSETS_ISOADOBE;
+ cff->charsets = NULL;
+ return 0;
+ }
+
+ offset = (long) cff_dict_get(cff->topdict, "charset", 0);
+
+ if (offset == 0) { /* predefined */
+ cff->flag |= CHARSETS_ISOADOBE;
+ cff->charsets = NULL;
+ return 0;
+ } else if (offset == 1) {
+ cff->flag |= CHARSETS_EXPERT;
+ cff->charsets = NULL;
+ return 0;
+ } else if (offset == 2) {
+ cff->flag |= CHARSETS_EXPSUB;
+ cff->charsets = NULL;
+ return 0;
+ }
+
+ cff->offset = offset;
+ cff->charsets = charset = xcalloc(1, sizeof(cff_charsets));
+ charset->format = get_card8(cff);
+ charset->num_entries = 0;
+
+ count = cff->num_glyphs - 1;
+ length = 1;
+
+ /* Not sure. Not well documented. */
+ switch (charset->format) {
+ case 0:
+ charset->num_entries = cff->num_glyphs - 1; /* no .notdef */
+ charset->data.glyphs = xcalloc(charset->num_entries, sizeof(s_SID));
+ length += (charset->num_entries) * 2;
+ for (i=0;i<(charset->num_entries);i++) {
+ charset->data.glyphs[i] = get_card16(cff);
+ }
+ count = 0;
+ break;
+ case 1:
+ {
+ cff_range1 *ranges = NULL;
+ while (count > 0 && charset->num_entries < cff->num_glyphs) {
+ ranges = xrealloc(ranges, (charset->num_entries + 1)*sizeof(cff_range1));
+ ranges[charset->num_entries].first = get_card16(cff);
+ ranges[charset->num_entries].n_left = get_card8(cff);
+ count -= ranges[charset->num_entries].n_left + 1; /* no-overrap */
+ charset->num_entries += 1;
+ charset->data.range1 = ranges;
+ }
+ length += (charset->num_entries) * 3;
+ }
+ break;
+ case 2:
+ {
+ cff_range2 *ranges = NULL;
+ while (count > 0 && charset->num_entries < cff->num_glyphs) {
+ ranges = xrealloc(ranges, (charset->num_entries + 1)*sizeof(cff_range2));
+ ranges[charset->num_entries].first = get_card16(cff);
+ ranges[charset->num_entries].n_left = get_card16(cff);
+ count -= ranges[charset->num_entries].n_left + 1; /* non-overrapping */
+ charset->num_entries += 1;
+ }
+ charset->data.range2 = ranges;
+ length += (charset->num_entries) * 4;
+ }
+ break;
+ default:
+ xfree(charset);
+ CFF_ERROR("Unknown Charset format");
+ break;
+ }
+
+ if (count > 0)
+ CFF_ERROR("Charset data possibly broken");
+
+ return length;
+}
+
+long cff_pack_charsets (cff_font *cff, card8 *dest, long destlen)
+{
+ long len = 0;
+ card16 i;
+ cff_charsets *charset;
+
+ if (cff->flag & HAVE_STANDARD_CHARSETS || cff->charsets == NULL)
+ return 0;
+
+ if (destlen < 1)
+ CFF_ERROR("in cff_pack_charsets(): Buffer overflow");
+
+ charset = cff->charsets;
+
+ dest[len++] = charset->format;
+ switch (charset->format) {
+ case 0:
+ if (destlen < len + (charset->num_entries)*2)
+ CFF_ERROR("in cff_pack_charsets(): Buffer overflow");
+ for (i=0;i<(charset->num_entries);i++) {
+ s_SID sid = (charset->data).glyphs[i]; /* or CID */
+ dest[len++] = (sid >> 8) & 0xff;
+ dest[len++] = sid & 0xff;
+ }
+ break;
+ case 1:
+ {
+ if (destlen < len + (charset->num_entries)*3)
+ CFF_ERROR("in cff_pack_charsets(): Buffer overflow");
+ for (i=0;i<(charset->num_entries);i++) {
+ dest[len++] = ((charset->data).range1[i].first >> 8) & 0xff;
+ dest[len++] = (charset->data).range1[i].first & 0xff;
+ dest[len++] = (charset->data).range1[i].n_left;
+ }
+ }
+ break;
+ case 2:
+ {
+ if (destlen < len + (charset->num_entries)*4)
+ CFF_ERROR("in cff_pack_charsets(): Buffer overflow");
+ for (i=0;i<(charset->num_entries);i++) {
+ dest[len++] = ((charset->data).range2[i].first >> 8) & 0xff;
+ dest[len++] = (charset->data).range2[i].first & 0xff;
+ dest[len++] = ((charset->data).range2[i].n_left >> 8) & 0xff;
+ dest[len++] = (charset->data).range2[i].n_left & 0xff;
+ }
+ }
+ break;
+ default:
+ CFF_ERROR("Unknown Charset format");
+ break;
+ }
+
+ return len;
+}
+
+
+
+/*
+ * Type 2 Charstring support:
+ * Decode and encode Type 2 charstring
+ *
+ * All local/global subroutine calls in a given charstring is replace by the
+ * content of subroutine charstrings. We do this because some PostScript RIP
+ * may have problems with sparse subroutine array. Workaround for this is to
+ * re-order subroutine array so that no gap appears in the subroutine array,
+ * or put dummy charstrings that contains only `return' in the gap. However,
+ * re-ordering of subroutine is rather difficult for Type 2 charstrings due
+ * to the bias which depends on the total number of subroutines. Replacing
+ * callgsubr/callsubr calls with the content of the corresponding subroutine
+ * charstring may be more efficient than putting dummy subroutines in the
+ * case of subsetted font. Adobe distiller seems doing same thing.
+ *
+ * And also note that subroutine numbers within subroutines can depend on the
+ * content of operand stack as follows:
+ *
+ * ... l m callsubr << subr #(m+bias): n add callsubr >> ...
+ *
+ * I've not implemented the `random' operator which generates a pseudo-random
+ * number in the range (0, 1] and push them into argument stack.
+ * How pseudo-random sequences are generated is not documented in the Type 2
+ * charstring spec..
+ */
+
+
+#define CS_TYPE2_DEBUG_STR "Type2 Charstring Parser"
+#define CS_TYPE2_DEBUG 5
+
+/* decoder/encoder status codes */
+#define CS_BUFFER_CFF_ERROR -3
+#define CS_STACK_CFF_ERROR -2
+#define CS_PARSE_CFF_ERROR -1
+#define CS_PARSE_OK 0
+#define CS_PARSE_END 1
+#define CS_SUBR_RETURN 2
+#define CS_CHAR_END 3
+
+static int status = CS_PARSE_CFF_ERROR;
+
+#define DST_NEED(a,b) {if ((a) < (b)) { status = CS_BUFFER_CFF_ERROR ; return ; }}
+#define SRC_NEED(a,b) {if ((a) < (b)) { status = CS_PARSE_CFF_ERROR ; return ; }}
+#define NEED(a,b) {if ((a) < (b)) { status = CS_STACK_CFF_ERROR ; return ; }}
+
+/* hintmask and cntrmask need number of stem zones */
+static int num_stems = 0;
+static int phase = 0;
+
+/* subroutine nesting */
+static int cs2_nest = 0;
+
+/* advance width */
+static int have_width = 0;
+static double width = 0.0;
+
+/*
+ * Standard Encoding Accented Characters:
+ * Optional four arguments for endchar. See, CFF spec., p.35.
+ * This is obsolete feature and is no longer supported.
+ */
+#if 0
+/* adx ady bchar achar endchar */
+static double seac[4] = {0.0, 0.0, 0.0, 0.0};
+#endif
+
+/* Operand stack and Transient array */
+static int cs2_stack_top = 0;
+static double cs2_arg_stack[CS_ARG_STACK_MAX];
+static double trn_array[CS_TRANS_ARRAY_MAX];
+
+/*
+ * Type 2 CharString encoding
+ */
+
+/*
+ * 1-byte CharString operaotrs:
+ * cs_escape is first byte of two-byte operator
+ */
+
+/* RESERVED 0 */
+#define cs_hstem 1
+/* RESERVED 2 */
+#define cs_vstem 3
+#define cs_vmoveto 4
+#define cs_rlineto 5
+#define cs_hlineto 6
+#define cs_vlineto 7
+#define cs_rrcurveto 8
+/* cs_closepath 9 : TYPE1 */
+#define cs_callsubr 10
+#define cs_return 11
+#define cs_escape 12
+/* cs_hsbw 13 : TYPE1 */
+#define cs_endchar 14
+/* RESERVED 15 */
+/* RESERVED 16 */
+/* RESERVED 17 */
+#define cs_hstemhm 18
+#define cs_hintmask 19
+#define cs_cntrmask 20
+#define cs_rmoveto 21
+#define cs_hmoveto 22
+#define cs_vstemhm 23
+#define cs_rcurveline 24
+#define cs_rlinecurve 25
+#define cs_vvcurveto 26
+#define cs_hhcurveto 27
+/* SHORTINT 28 : first byte of shortint*/
+#define cs_callgsubr 29
+#define cs_vhcurveto 30
+#define cs_hvcurveto 31
+
+/*
+ * 2-byte CharString operaotrs:
+ * "dotsection" is obsoleted in Type 2 charstring.
+ */
+
+#define cs_dotsection 0
+/* cs_vstem3 1 : TYPE1 */
+/* cs_hstem3 2 : TYPE1 */
+#define cs_and 3
+#define cs_or 4
+#define cs_not 5
+/* cs_seac 6 : TYPE1 */
+/* cs_sbw 7 : TYPE1 */
+/* RESERVED 8 */
+#define cs_abs 9
+#define cs_add 10
+#define cs_sub 11
+#define cs_div 12
+/* RESERVED 13 */
+#define cs_neg 14
+#define cs_eq 15
+/* cs_callothersubr 16 : TYPE1 */
+/* cs_pop 17 : TYPE1 */
+#define cs_drop 18
+/* RESERVED 19 */
+#define cs_put 20
+#define cs_get 21
+#define cs_ifelse 22
+#define cs_random 23
+#define cs_mul 24
+/* RESERVED 25 */
+#define cs_sqrt 26
+#define cs_dup 27
+#define cs_exch 28
+#define cs_index 29
+#define cs_roll 30
+/* cs_setcurrentpoint 31 : TYPE1 */
+/* RESERVED 32 */
+/* RESERVED 33 */
+#define cs_hflex 34
+#define cs_flex 35
+#define cs_hflex1 36
+#define cs_flex1 37
+
+/*
+ * clear_stack() put all operands sotred in operand stack to dest.
+ */
+static void
+clear_stack (card8 **dest, card8 *limit)
+{
+ int i;
+
+ for (i = 0; i < cs2_stack_top; i++) {
+ double value;
+ long ivalue;
+ value = cs2_arg_stack[i];
+ /* Nearest integer value */
+ ivalue = (long) floor(value+0.5);
+ if (value >= 0x8000L || value <= (-0x8000L - 1)) {
+ /*
+ * This number cannot be represented as a single operand.
+ * We must use `a b mul ...' or `a c div' to represent large values.
+ */
+ CFF_ERROR("Argument value too large. (This is bug)");
+ } else if (fabs(value - ivalue) > 3.0e-5) {
+ /* 16.16-bit signed fixed value */
+ DST_NEED(limit, *dest + 5);
+ *(*dest)++ = 255;
+ ivalue = (long) floor(value); /* mantissa */
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = ivalue & 0xff;
+ ivalue = (long)((value - ivalue) * 0x10000l); /* fraction */
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = ivalue & 0xff;
+ /* Everything else are integers. */
+ } else if (ivalue >= -107 && ivalue <= 107) {
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = ivalue + 139;
+ } else if (ivalue >= 108 && ivalue <= 1131) {
+ DST_NEED(limit, *dest + 2);
+ ivalue = 0xf700u + ivalue - 108;
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = ivalue & 0xff;
+ } else if (ivalue >= -1131 && ivalue <= -108) {
+ DST_NEED(limit, *dest + 2);
+ ivalue = 0xfb00u - ivalue - 108;
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = ivalue & 0xff;
+ } else if (ivalue >= -32768 && ivalue <= 32767) { /* shortint */
+ DST_NEED(limit, *dest + 3);
+ *(*dest)++ = 28;
+ *(*dest)++ = (ivalue >> 8) & 0xff;
+ *(*dest)++ = (ivalue) & 0xff;
+ } else { /* Shouldn't come here */
+ CFF_ERROR("Unexpected error.");
+ }
+ }
+
+ cs2_stack_top = 0; /* clear stack */
+
+ return;
+}
+
+/*
+ * Single byte operators:
+ * Path construction, Operator for finishing a path, Hint operators.
+ *
+ * phase:
+ * 0: inital state
+ * 1: hint declaration, first stack-clearing operator appeared
+ * 2: in path construction
+ */
+
+static void
+do_operator1 (card8 **dest, card8 *limit, card8 **data, card8 *endptr)
+{
+ card8 op = **data;
+
+ *data += 1;
+
+ switch (op) {
+ case cs_hstemhm:
+ case cs_vstemhm:
+ /* charstring may have hintmask if above operator have seen */
+ case cs_hstem:
+ case cs_vstem:
+ if (phase == 0 && (cs2_stack_top % 2)) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ }
+ num_stems += cs2_stack_top/2;
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ phase = 1;
+ break;
+ case cs_hintmask:
+ case cs_cntrmask:
+ if (phase < 2) {
+ if (phase == 0 && (cs2_stack_top % 2)) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ }
+ num_stems += cs2_stack_top/2;
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ if (num_stems > 0) {
+ int masklen = (num_stems + 7) / 8;
+ DST_NEED(limit, *dest + masklen);
+ SRC_NEED(endptr, *data + masklen);
+ memmove(*dest, *data, masklen);
+ *data += masklen;
+ *dest += masklen;
+ }
+ phase = 2;
+ break;
+ case cs_rmoveto:
+ if (phase == 0 && (cs2_stack_top % 2)) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ phase = 2;
+ break;
+ case cs_hmoveto:
+ case cs_vmoveto:
+ if (phase == 0 && (cs2_stack_top % 2) == 0) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ phase = 2;
+ break;
+ case cs_endchar:
+ if (cs2_stack_top == 1) {
+ have_width = 1;
+ width = cs2_arg_stack[0];
+ clear_stack(dest, limit);
+ } else if (cs2_stack_top == 4 || cs2_stack_top == 5) {
+ WARN("\"seac\" character deprecated in Type 2 charstring.");
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ } else if (cs2_stack_top > 0) {
+ WARN("Operand stack not empty.");
+ }
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ status = CS_CHAR_END;
+ break;
+ /* above oprators are candidate for first stack-clearing operator */
+ case cs_rlineto:
+ case cs_hlineto:
+ case cs_vlineto:
+ case cs_rrcurveto:
+ case cs_rcurveline:
+ case cs_rlinecurve:
+ case cs_vvcurveto:
+ case cs_hhcurveto:
+ case cs_vhcurveto:
+ case cs_hvcurveto:
+ if (phase < 2) {
+ WARN("Broken Type 2 charstring.");
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 1);
+ *(*dest)++ = op;
+ break;
+ /* all operotors above are stack-clearing operator */
+ /* no output */
+ case cs_return:
+ case cs_callgsubr:
+ case cs_callsubr:
+ CFF_ERROR("Unexpected call(g)subr/return");
+ break;
+ default:
+ /* no-op ? */
+ WARN("%s: Unknown charstring operator: 0x%02x", CS_TYPE2_DEBUG_STR, op);
+ status = CS_PARSE_CFF_ERROR;
+ break;
+ }
+
+ return;
+}
+
+/*
+ * Double byte operators:
+ * Flex, arithmetic, conditional, and storage operators.
+ *
+ * Following operators are not supported:
+ * random: How random ?
+ */
+static void
+do_operator2 (card8 **dest, card8 *limit, card8 **data, card8 *endptr)
+{
+ card8 op;
+
+ *data += 1;
+
+ SRC_NEED(endptr, *data + 1);
+
+ op = **data;
+ *data += 1;
+
+ switch(op) {
+ case cs_dotsection: /* deprecated */
+ WARN("Operator \"dotsection\" deprecated in Type 2 charstring.");
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ break;
+ case cs_hflex:
+ case cs_flex:
+ case cs_hflex1:
+ case cs_flex1:
+ if (phase < 2) {
+ WARN("%s: Broken Type 2 charstring.", CS_TYPE2_DEBUG_STR);
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ }
+ clear_stack(dest, limit);
+ DST_NEED(limit, *dest + 2);
+ *(*dest)++ = cs_escape;
+ *(*dest)++ = op;
+ break;
+ /* all operator above are stack-clearing */
+ /* no output */
+ case cs_and:
+ NEED(cs2_stack_top, 2);
+ cs2_stack_top--;
+ if (cs2_arg_stack[cs2_stack_top] && cs2_arg_stack[cs2_stack_top-1]) {
+ cs2_arg_stack[cs2_stack_top-1] = 1.0;
+ } else {
+ cs2_arg_stack[cs2_stack_top-1] = 0.0;
+ }
+ break;
+ case cs_or:
+ NEED(cs2_stack_top, 2);
+ cs2_stack_top--;
+ if (cs2_arg_stack[cs2_stack_top] || cs2_arg_stack[cs2_stack_top-1]) {
+ cs2_arg_stack[cs2_stack_top-1] = 1.0;
+ } else {
+ cs2_arg_stack[cs2_stack_top-1] = 0.0;
+ }
+ break;
+ case cs_not:
+ NEED(cs2_stack_top, 1);
+ if (cs2_arg_stack[cs2_stack_top-1]) {
+ cs2_arg_stack[cs2_stack_top-1] = 0.0;
+ } else {
+ cs2_arg_stack[cs2_stack_top-1] = 1.0;
+ }
+ break;
+ case cs_abs:
+ NEED(cs2_stack_top, 1);
+ cs2_arg_stack[cs2_stack_top-1] = fabs(cs2_arg_stack[cs2_stack_top-1]);
+ break;
+ case cs_add:
+ NEED(cs2_stack_top, 2);
+ cs2_arg_stack[cs2_stack_top-2] += cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top--;
+ break;
+ case cs_sub:
+ NEED(cs2_stack_top, 2);
+ cs2_arg_stack[cs2_stack_top-2] -= cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top--;
+ break;
+ case cs_div: /* doesn't check overflow */
+ NEED(cs2_stack_top, 2);
+ cs2_arg_stack[cs2_stack_top-2] /= cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top--;
+ break;
+ case cs_neg:
+ NEED(cs2_stack_top, 1);
+ cs2_arg_stack[cs2_stack_top-1] *= -1.0;
+ break;
+ case cs_eq:
+ NEED(cs2_stack_top, 2);
+ cs2_stack_top--;
+ if (cs2_arg_stack[cs2_stack_top] == cs2_arg_stack[cs2_stack_top-1]) {
+ cs2_arg_stack[cs2_stack_top-1] = 1.0;
+ } else {
+ cs2_arg_stack[cs2_stack_top-1] = 0.0;
+ }
+ break;
+ case cs_drop:
+ NEED(cs2_stack_top, 1);
+ cs2_stack_top--;
+ break;
+ case cs_put:
+ NEED(cs2_stack_top, 2);
+ {
+ int idx = (int)cs2_arg_stack[--cs2_stack_top];
+ NEED(CS_TRANS_ARRAY_MAX, idx);
+ trn_array[idx] = cs2_arg_stack[--cs2_stack_top];
+ }
+ break;
+ case cs_get:
+ NEED(cs2_stack_top, 1);
+ {
+ int idx = (int)cs2_arg_stack[cs2_stack_top-1];
+ NEED(CS_TRANS_ARRAY_MAX, idx);
+ cs2_arg_stack[cs2_stack_top-1] = trn_array[idx];
+ }
+ break;
+ case cs_ifelse:
+ NEED(cs2_stack_top, 4);
+ cs2_stack_top -= 3;
+ if (cs2_arg_stack[cs2_stack_top+1] > cs2_arg_stack[cs2_stack_top+2]) {
+ cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top];
+ }
+ break;
+ case cs_mul:
+ NEED(cs2_stack_top, 2);
+ cs2_arg_stack[cs2_stack_top-2] = cs2_arg_stack[cs2_stack_top-2] * cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top--;
+ break;
+ case cs_sqrt:
+ NEED(cs2_stack_top, 1);
+ cs2_arg_stack[cs2_stack_top-1] = sqrt(cs2_arg_stack[cs2_stack_top-1]);
+ break;
+ case cs_dup:
+ NEED(cs2_stack_top, 1);
+ NEED(CS_ARG_STACK_MAX, cs2_stack_top+1);
+ cs2_arg_stack[cs2_stack_top] = cs2_arg_stack[cs2_stack_top-1];
+ cs2_stack_top++;
+ break;
+ case cs_exch:
+ NEED(cs2_stack_top, 2);
+ {
+ double save = cs2_arg_stack[cs2_stack_top-2];
+ cs2_arg_stack[cs2_stack_top-2] = cs2_arg_stack[cs2_stack_top-1];
+ cs2_arg_stack[cs2_stack_top-1] = save;
+ }
+ break;
+ case cs_index:
+ NEED(cs2_stack_top, 2); /* need two arguments at least */
+ {
+ int idx = (int)cs2_arg_stack[cs2_stack_top-1];
+ if (idx < 0) {
+ cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top-2];
+ } else {
+ NEED(cs2_stack_top, idx+2);
+ cs2_arg_stack[cs2_stack_top-1] = cs2_arg_stack[cs2_stack_top-idx-2];
+ }
+ }
+ break;
+ case cs_roll:
+ NEED(cs2_stack_top, 2);
+ {
+ int N, J;
+ J = (int)cs2_arg_stack[--cs2_stack_top];
+ N = (int)cs2_arg_stack[--cs2_stack_top];
+ NEED(cs2_stack_top, N);
+ if (J > 0) {
+ J = J % N;
+ while (J-- > 0) {
+ double save = cs2_arg_stack[cs2_stack_top-1];
+ int i = cs2_stack_top - 1;
+ while (i > cs2_stack_top-N) {
+ cs2_arg_stack[i] = cs2_arg_stack[i-1];
+ i--;
+ }
+ cs2_arg_stack[i] = save;
+ }
+ } else {
+ J = (-J) % N;
+ while (J-- > 0) {
+ double save = cs2_arg_stack[cs2_stack_top-N];
+ int i = cs2_stack_top - N;
+ while (i < cs2_stack_top-1) {
+ cs2_arg_stack[i] = cs2_arg_stack[i+1];
+ i++;
+ }
+ cs2_arg_stack[i] = save;
+ }
+ }
+ }
+ break;
+ case cs_random:
+ WARN("%s: Charstring operator \"random\" found.", CS_TYPE2_DEBUG_STR);
+ NEED(CS_ARG_STACK_MAX, cs2_stack_top+1);
+ cs2_arg_stack[cs2_stack_top++] = 1.0;
+ break;
+ default:
+ /* no-op ? */
+ WARN("%s: Unknown charstring operator: 0x0c%02x", CS_TYPE2_DEBUG_STR, op);
+ status = CS_PARSE_CFF_ERROR;
+ break;
+ }
+
+ return;
+}
+
+/*
+ * integer:
+ * exactly the same as the DICT encoding (except 29)
+ */
+static void
+cs2_get_integer (card8 **data, card8 *endptr)
+{
+ long result = 0;
+ card8 b0 = **data, b1, b2;
+
+ *data += 1;
+
+ if (b0 == 28) { /* shortint */
+ SRC_NEED(endptr, *data + 2);
+ b1 = **data;
+ b2 = *(*data+1);
+ result = b1*256+b2;
+ if (result > 0x7fff)
+ result -= 0x10000L;
+ *data += 2;
+ } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
+ result = b0 - 139;
+ } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
+ SRC_NEED(endptr, *data + 1);
+ b1 = **data;
+ result = (b0-247)*256+b1+108;
+ *data += 1;
+ } else if (b0 >= 251 && b0 <= 254) {
+ SRC_NEED(endptr, *data + 1);
+ b1 = **data;
+ result = -(b0-251)*256-b1-108;
+ *data += 1;
+ } else {
+ status = CS_PARSE_CFF_ERROR;
+ return;
+ }
+
+ NEED(CS_ARG_STACK_MAX, cs2_stack_top+1);
+ cs2_arg_stack[cs2_stack_top++] = (double) result;
+
+ return;
+}
+
+/*
+ * Signed 16.16-bits fixed number for Type 2 charstring encoding
+ */
+static void
+get_fixed (card8 **data, card8 *endptr)
+{
+ long ivalue;
+ double rvalue;
+
+ *data += 1;
+
+ SRC_NEED(endptr, *data + 4);
+
+ ivalue = *(*data) * 0x100 + *(*data+1);
+ rvalue = (ivalue > 0x7fffL) ? (ivalue - 0x10000L) : ivalue;
+ ivalue = *(*data+2) * 0x100 + *(*data+3);
+ rvalue += ((double) ivalue) / 0x10000L;
+
+ NEED(CS_ARG_STACK_MAX, cs2_stack_top+1);
+ cs2_arg_stack[cs2_stack_top++] = rvalue;
+ *data += 4;
+
+ return;
+}
+
+/*
+ * Subroutines:
+ * The bias for subroutine number is introduced in type 2 charstrings.
+ *
+ * subr: set to a pointer to the subroutine charstring.
+ * len: set to the length of subroutine charstring.
+ * subr_idx: CFF INDEX data that contains subroutines.
+ * id: biased subroutine number.
+ */
+static void
+get_subr (card8 **subr, long *len, cff_index *subr_idx, long id)
+{
+ card16 count;
+
+ if (subr_idx == NULL)
+ CFF_ERROR("%s: Subroutine called but no subroutine found.", CS_TYPE2_DEBUG_STR);
+
+ count = subr_idx->count;
+
+ /* Adding bias number */
+ if (count < 1240) {
+ id += 107;
+ } else if (count < 33900) {
+ id += 1131;
+ } else {
+ id += 32768;
+ }
+
+ if (id > count)
+ CFF_ERROR("%s: Invalid Subr index: %ld (max=%u)", CS_TYPE2_DEBUG_STR, id, count);
+
+ *len = (subr_idx->offset)[id + 1] - (subr_idx->offset)[id];
+ *subr = subr_idx->data + (subr_idx->offset)[id] - 1;
+
+ return;
+}
+
+/*
+ * NOTE:
+ * The Type 2 interpretation of a number encoded in five-bytes (those with
+ * an initial byte value of 255) differs from how it is interpreted in the
+ * Type 1 format.
+ */
+
+static void
+do_charstring (card8 **dest, card8 *limit,
+ card8 **data, card8 *endptr,
+ cff_index *gsubr_idx, cff_index *subr_idx)
+{
+ card8 b0 = 0, *subr;
+ long len;
+
+ if (cs2_nest > CS_SUBR_NEST_MAX)
+ CFF_ERROR("%s: Subroutine nested too deeply.", CS_TYPE2_DEBUG_STR);
+
+ cs2_nest++;
+
+ while (*data < endptr && status == CS_PARSE_OK) {
+ b0 = **data;
+ if (b0 == 255) { /* 16-bit.16-bit fixed signed number */
+ get_fixed(data, endptr);
+ } else if (b0 == cs_return) {
+ status = CS_SUBR_RETURN;
+ } else if (b0 == cs_callgsubr) {
+ if (cs2_stack_top < 1) {
+ status = CS_STACK_CFF_ERROR;
+ } else {
+ cs2_stack_top--;
+ get_subr(&subr, &len, gsubr_idx, (long) cs2_arg_stack[cs2_stack_top]);
+ if (*dest + len > limit)
+ CFF_ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR);
+ do_charstring(dest, limit, &subr, subr + len,
+ gsubr_idx, subr_idx);
+ *data += 1;
+ }
+ } else if (b0 == cs_callsubr) {
+ if (cs2_stack_top < 1) {
+ status = CS_STACK_CFF_ERROR;
+ } else {
+ cs2_stack_top--;
+ get_subr(&subr, &len, subr_idx, (long) cs2_arg_stack[cs2_stack_top]);
+ if (limit < *dest + len)
+ CFF_ERROR("%s: Possible buffer overflow.", CS_TYPE2_DEBUG_STR);
+ do_charstring(dest, limit, &subr, subr + len,
+ gsubr_idx, subr_idx);
+ *data += 1;
+ }
+ } else if (b0 == cs_escape) {
+ do_operator2(dest, limit, data, endptr);
+ } else if (b0 < 32 && b0 != 28) { /* 19, 20 need mask */
+ do_operator1(dest, limit, data, endptr);
+ } else if ((b0 <= 22 && b0 >= 27) || b0 == 31) { /* reserved */
+ status = CS_PARSE_CFF_ERROR; /* not an error ? */
+ } else { /* integer */
+ cs2_get_integer(data, endptr);
+ }
+ }
+
+ if (status == CS_SUBR_RETURN) {
+ status = CS_PARSE_OK;
+ } else if (status == CS_CHAR_END && *data < endptr) {
+ WARN("%s: Garbage after endchar.", CS_TYPE2_DEBUG_STR);
+ } else if (status < CS_PARSE_OK) { /* error */
+ CFF_ERROR("%s: Parsing charstring failed: (status=%d, stack=%d)",
+ CS_TYPE2_DEBUG_STR, status, cs2_stack_top);
+ }
+
+ cs2_nest--;
+
+ return;
+}
+
+static void
+cs_parse_init (void)
+{
+ status = CS_PARSE_OK;
+ cs2_nest = 0;
+ phase = 0;
+ num_stems = 0;
+ cs2_stack_top = 0;
+}
+
+/*
+ * Not just copying...
+ */
+long
+cs_copy_charstring (card8 *dst, long dstlen,
+ card8 *src, long srclen,
+ cff_index *gsubr, cff_index *subr,
+ double default_width, double nominal_width, cs_ginfo *ginfo)
+{
+ card8 *save = dst;
+
+ cs_parse_init();
+
+ width = 0.0;
+ have_width = 0;
+
+ /* expand call(g)subrs */
+ do_charstring(&dst, dst + dstlen, &src, src + srclen, gsubr, subr);
+
+ if (ginfo) {
+ ginfo->flags = 0; /* not used */
+ if (have_width) {
+ ginfo->wx = nominal_width + width;
+ } else {
+ ginfo->wx = default_width;
+ }
+ }
+
+ return (long)(dst - save);
+}
+
+/* encodings */
+
+/*
+ * Encoding and Charset
+ *
+ * Encoding and Charset arrays always begin with GID = 1.
+ */
+long cff_read_encoding (cff_font *cff)
+{
+ cff_encoding *encoding;
+ long offset, length;
+ card8 i;
+
+ if (cff->topdict == NULL) {
+ CFF_ERROR("Top DICT data not found");
+ }
+
+ if (!cff_dict_known(cff->topdict, "Encoding")) {
+ cff->flag |= ENCODING_STANDARD;
+ cff->encoding = NULL;
+ return 0;
+ }
+
+ offset = (long) cff_dict_get(cff->topdict, "Encoding", 0);
+ if (offset == 0) { /* predefined */
+ cff->flag |= ENCODING_STANDARD;
+ cff->encoding = NULL;
+ return 0;
+ } else if (offset == 1) {
+ cff->flag |= ENCODING_EXPERT;
+ cff->encoding = NULL;
+ return 0;
+ }
+
+ cff->offset= offset;
+ cff->encoding = encoding = xcalloc(1, sizeof(cff_encoding));
+ encoding->format = get_card8(cff);
+ length = 1;
+
+ switch (encoding->format & (~0x80)) {
+ case 0:
+ encoding->num_entries = get_card8(cff);
+ (encoding->data).codes = xcalloc(encoding->num_entries, sizeof(card8));
+ for (i=0;i<(encoding->num_entries);i++) {
+ (encoding->data).codes[i] = get_card8(cff);
+ }
+ length += encoding->num_entries + 1;
+ break;
+ case 1:
+ {
+ cff_range1 *ranges;
+ encoding->num_entries = get_card8(cff);
+ encoding->data.range1 = ranges
+ = xcalloc(encoding->num_entries, sizeof(cff_range1));
+ for (i=0;i<(encoding->num_entries);i++) {
+ ranges[i].first = get_card8(cff);
+ ranges[i].n_left = get_card8(cff);
+ }
+ length += (encoding->num_entries) * 2 + 1;
+ }
+ break;
+ default:
+ xfree(encoding);
+ CFF_ERROR("Unknown Encoding format");
+ break;
+ }
+
+ /* Supplementary data */
+ if ((encoding->format) & 0x80) {
+ cff_map *map;
+ encoding->num_supps = get_card8(cff);
+ encoding->supp = map = xcalloc(encoding->num_supps, sizeof(cff_map));
+ for (i=0;i<(encoding->num_supps);i++) {
+ map[i].code = get_card8(cff);
+ map[i].glyph = get_card16(cff); /* SID */
+ }
+ length += (encoding->num_supps) * 3 + 1;
+ } else {
+ encoding->num_supps = 0;
+ encoding->supp = NULL;
+ }
+
+ return length;
+}
+
+long cff_pack_encoding (cff_font *cff, card8 *dest, long destlen)
+{
+ long len = 0;
+ cff_encoding *encoding;
+ card16 i;
+
+ if (cff->flag & HAVE_STANDARD_ENCODING || cff->encoding == NULL)
+ return 0;
+
+ if (destlen < 2)
+ CFF_ERROR("in cff_pack_encoding(): Buffer overflow");
+
+ encoding = cff->encoding;
+
+ dest[len++] = encoding->format;
+ dest[len++] = encoding->num_entries;
+ switch (encoding->format & (~0x80)) {
+ case 0:
+ if (destlen < len + encoding->num_entries)
+ CFF_ERROR("in cff_pack_encoding(): Buffer overflow");
+ for (i=0;i<(encoding->num_entries);i++) {
+ dest[len++] = (encoding->data).codes[i];
+ }
+ break;
+ case 1:
+ {
+ if (destlen < len + (encoding->num_entries)*2)
+ CFF_ERROR("in cff_pack_encoding(): Buffer overflow");
+ for (i=0;i<(encoding->num_entries);i++) {
+ dest[len++] = (encoding->data).range1[i].first & 0xff;
+ dest[len++] = (encoding->data).range1[i].n_left;
+ }
+ }
+ break;
+ default:
+ CFF_ERROR("Unknown Encoding format");
+ break;
+ }
+
+ if ((encoding->format) & 0x80) {
+ if (destlen < len + (encoding->num_supps)*3 + 1)
+ CFF_ERROR("in cff_pack_encoding(): Buffer overflow");
+ dest[len++] = encoding->num_supps;
+ for (i=0;i<(encoding->num_supps);i++) {
+ dest[len++] = (encoding->supp)[i].code;
+ dest[len++] = ((encoding->supp)[i].glyph >> 8) & 0xff;
+ dest[len++] = (encoding->supp)[i].glyph & 0xff;
+ }
+ }
+
+ return len;
+}
+
+/* CID-Keyed font specific */
+long cff_read_fdselect (cff_font *cff)
+{
+ cff_fdselect *fdsel;
+ long offset, length;
+ card16 i;
+
+ if (cff->topdict == NULL)
+ CFF_ERROR("Top DICT not available");
+
+ if (!(cff->flag & FONTTYPE_CIDFONT))
+ return 0;
+
+ offset = (long) cff_dict_get(cff->topdict, "FDSelect", 0);
+ cff->offset = offset;
+ cff->fdselect = fdsel = xcalloc(1, sizeof(cff_fdselect));
+ fdsel->format = get_card8(cff);
+
+ length = 1;
+
+ switch (fdsel->format) {
+ case 0:
+ fdsel->num_entries = cff->num_glyphs;
+ (fdsel->data).fds = xcalloc(fdsel->num_entries, sizeof(card8));
+ for (i=0;i<(fdsel->num_entries);i++) {
+ (fdsel->data).fds[i] = get_card8(cff);
+ }
+ length += fdsel->num_entries;
+ break;
+ case 3:
+ {
+ cff_range3 *ranges;
+ fdsel->num_entries = get_card16(cff);
+ fdsel->data.ranges = ranges = xcalloc(fdsel->num_entries, sizeof(cff_range3));
+ for (i=0;i<(fdsel->num_entries);i++) {
+ ranges[i].first = get_card16(cff);
+ ranges[i].fd = get_card8(cff);
+ }
+ if (ranges[0].first != 0)
+ CFF_ERROR("Range not starting with 0.");
+ if (cff->num_glyphs != get_card16(cff))
+ CFF_ERROR("Sentinel value mismatched with number of glyphs.");
+ length += (fdsel->num_entries) * 3 + 4;
+ }
+ break;
+ default:
+ xfree(fdsel);
+ CFF_ERROR("Unknown FDSelect format.");
+ break;
+ }
+
+ return length;
+}
+
+
+long cff_pack_fdselect (cff_font *cff, card8 *dest, long destlen)
+{
+ cff_fdselect *fdsel;
+ long len = 0;
+ card16 i;
+
+ if (cff->fdselect == NULL)
+ return 0;
+
+ if (destlen < 1)
+ CFF_ERROR("in cff_pack_fdselect(): Buffur overflow");
+
+ fdsel = cff->fdselect;
+
+ dest[len++] = fdsel->format;
+ switch (fdsel->format) {
+ case 0:
+ if (fdsel->num_entries != cff->num_glyphs)
+ CFF_ERROR("in cff_pack_fdselect(): Invalid data");
+ if (destlen < len + fdsel->num_entries)
+ CFF_ERROR("in cff_pack_fdselect(): Buffer overflow");
+ for (i=0;i<fdsel->num_entries;i++) {
+ dest[len++] = (fdsel->data).fds[i];
+ }
+ break;
+ case 3:
+ {
+ if (destlen < len + 2)
+ CFF_ERROR("in cff_pack_fdselect(): Buffer overflow");
+ len += 2;
+ for (i=0;i<(fdsel->num_entries);i++) {
+ if (destlen < len + 3)
+ CFF_ERROR("in cff_pack_fdselect(): Buffer overflow");
+ dest[len++] = ((fdsel->data).ranges[i].first >> 8) & 0xff;
+ dest[len++] = (fdsel->data).ranges[i].first & 0xff;
+ dest[len++] = (fdsel->data).ranges[i].fd;
+ }
+ if (destlen < len + 2)
+ CFF_ERROR("in cff_pack_fdselect(): Buffer overflow");
+ dest[len++] = (cff->num_glyphs >> 8) & 0xff;
+ dest[len++] = cff->num_glyphs & 0xff;
+ dest[1] = ((len/3 - 1) >> 8) & 0xff;
+ dest[2] = (len/3 - 1) & 0xff;
+ }
+ break;
+ default:
+ CFF_ERROR("Unknown FDSelect format.");
+ break;
+ }
+
+ return len;
+}
+
+
+
+/*
+ * Create an instance of embeddable font.
+ */
+static void
+write_fontfile (cff_font *cffont, char *fullname)
+{
+ cff_index *topdict, *fdarray, *private;
+ unsigned char *dest;
+ long destlen = 0, i, size;
+ long offset, topdict_offset, fdarray_offset;
+
+ /* DICT sizes (offset set to long int) */
+ topdict = cff_new_index(1);
+ fdarray = cff_new_index(cffont->num_fds);
+ private = cff_new_index(cffont->num_fds);
+
+ cff_dict_remove(cffont->topdict, "UniqueID");
+ cff_dict_remove(cffont->topdict, "XUID");
+ cff_dict_remove(cffont->topdict, "Private"); /* some bad font may have */
+ cff_dict_remove(cffont->topdict, "Encoding"); /* some bad font may have */
+
+ topdict->offset[1] = cff_dict_pack(cffont->topdict,
+ (card8 *) work_buffer,
+ WORK_BUFFER_SIZE) + 1;
+ for (i = 0;i < cffont->num_fds; i++) {
+ size = 0;
+ if (cffont->private && cffont->private[i]) {
+ size = cff_dict_pack(cffont->private[i],
+ (card8 *) work_buffer, WORK_BUFFER_SIZE);
+ if (size < 1) { /* Private had contained only Subr */
+ cff_dict_remove(cffont->fdarray[i], "Private");
+ }
+ }
+ (private->offset)[i+1] = (private->offset)[i] + size;
+ (fdarray->offset)[i+1] = (fdarray->offset)[i] +
+ cff_dict_pack(cffont->fdarray[i],
+ (card8 *) work_buffer, WORK_BUFFER_SIZE);
+ }
+
+ destlen = 4; /* header size */
+ destlen += cff_set_name(cffont, fullname);
+ destlen += cff_index_size(topdict);
+ destlen += cff_index_size(cffont->string);
+ destlen += cff_index_size(cffont->gsubr);
+ destlen += (cffont->charsets->num_entries) * 2 + 1; /* charset format 0 */
+ destlen += (cffont->fdselect->num_entries) * 3 + 5; /* fdselect format 3 */
+ destlen += cff_index_size(cffont->cstrings);
+ destlen += cff_index_size(fdarray);
+ destlen += private->offset[private->count] - 1; /* Private is not INDEX */
+
+ dest = xcalloc(destlen, sizeof(card8));
+
+ offset = 0;
+ /* Header */
+ offset += cff_put_header(cffont, dest + offset, destlen - offset);
+ /* Name */
+ offset += cff_pack_index(cffont->name, dest + offset, destlen - offset);
+ /* Top DICT */
+ topdict_offset = offset;
+ offset += cff_index_size(topdict);
+ /* Strings */
+ offset += cff_pack_index(cffont->string, dest + offset, destlen - offset);
+ /* Global Subrs */
+ offset += cff_pack_index(cffont->gsubr, dest + offset, destlen - offset);
+
+ /* charset */
+ cff_dict_set(cffont->topdict, "charset", 0, offset);
+ offset += cff_pack_charsets(cffont, dest + offset, destlen - offset);
+
+ /* FDSelect */
+ cff_dict_set(cffont->topdict, "FDSelect", 0, offset);
+ offset += cff_pack_fdselect(cffont, dest + offset, destlen - offset);
+
+ /* CharStrings */
+ cff_dict_set(cffont->topdict, "CharStrings", 0, offset);
+ offset += cff_pack_index(cffont->cstrings,
+ dest + offset, cff_index_size(cffont->cstrings));
+ cff_release_index(cffont->cstrings);
+ cffont->cstrings = NULL; /* Charstrings cosumes huge memory */
+
+ /* FDArray and Private */
+ cff_dict_set(cffont->topdict, "FDArray", 0, offset);
+ fdarray_offset = offset;
+ offset += cff_index_size(fdarray);
+
+ fdarray->data = xcalloc(fdarray->offset[fdarray->count] - 1, sizeof(card8));
+ for (i = 0; i < cffont->num_fds; i++) {
+ size = private->offset[i+1] - private->offset[i];
+ if (cffont->private[i] && size > 0) {
+ cff_dict_pack(cffont->private[i], dest + offset, size);
+ cff_dict_set(cffont->fdarray[i], "Private", 0, size);
+ cff_dict_set(cffont->fdarray[i], "Private", 1, offset);
+ }
+ cff_dict_pack(cffont->fdarray[i],
+ fdarray->data + (fdarray->offset)[i] - 1,
+ fdarray->offset[fdarray->count] - 1);
+ offset += size;
+ }
+
+ cff_pack_index(fdarray, dest + fdarray_offset, cff_index_size(fdarray));
+ cff_release_index(fdarray);
+ cff_release_index(private);
+
+ /* Finally Top DICT */
+ topdict->data = xcalloc(topdict->offset[topdict->count] - 1, sizeof(card8));
+ cff_dict_pack(cffont->topdict,
+ topdict->data, topdict->offset[topdict->count] - 1);
+ cff_pack_index(topdict, dest + topdict_offset, cff_index_size(topdict));
+ cff_release_index(topdict);
+
+ for (i = 0; i < offset; i++)
+ fb_putchar (dest[i]);
+
+ /*fprintf(stdout," (%i/%i)",offset,cffont->stream_size);*/
+ xfree(dest);
+ return ;
+}
+
+
+/* if the CFF data was converted from an old type1 font, then the .notdef
+ glyph may not be at id 0, so in that case |uglytype1fix| is nonzero */
+
+void write_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) {
+ cff_index *charstrings, *cs_idx;
+
+ long charstring_len, max_len;
+ long size, offset = 0;
+
+ card8 *data;
+ card16 num_glyphs, cs_count, code, gid, last_cid;
+
+ double nominal_width, default_width;
+
+ char *fullname;
+
+ glw_entry *glyph, *found;
+ struct avl_traverser t;
+
+
+
+
+ fullname = xcalloc(8+strlen(fd->fontname),1);
+ sprintf(fullname,"%s+%s",fd->subset_tag,fd->fontname);
+
+ /* finish parsing the CFF */
+ cff_read_private(cffont);
+ cff_read_subrs (cffont);
+
+ /*
+ * Widths
+ */
+ if (cffont->private[0] &&
+ cff_dict_known(cffont->private[0], "defaultWidthX")) {
+ default_width = (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0);
+ } else {
+ default_width = CFF_DEFAULTWIDTHX_DEFAULT;
+ }
+ if (cffont->private[0] &&
+ cff_dict_known(cffont->private[0], "nominalWidthX")) {
+ nominal_width = (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0);
+ } else {
+ nominal_width = CFF_NOMINALWIDTHX_DEFAULT;
+ }
+
+ num_glyphs = 0;
+ last_cid = 0;
+ glyph = xtalloc(1,glw_entry);
+
+ /* insert notdef */
+ glyph->id = uglytype1fix;
+ if (avl_find(fd->gl_tree, glyph)==NULL) {
+ /*fprintf(stderr,"seeding .notdef at %i\n",uglytype1fix);*/
+ avl_insert(fd->gl_tree, glyph);
+ glyph = xtalloc(1,glw_entry);
+ }
+
+
+ avl_t_init(&t, fd->gl_tree);
+ for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
+ found != NULL;
+ found = (glw_entry *) avl_t_next(&t)) {
+ if (found->id > last_cid)
+ last_cid = found->id;
+ num_glyphs++;
+ }
+
+ {
+ cff_fdselect *fdselect;
+
+ fdselect = xcalloc(1, sizeof(cff_fdselect));
+ fdselect->format = 3;
+ fdselect->num_entries = 1;
+ fdselect->data.ranges = xcalloc(1, sizeof(cff_range3));
+ fdselect->data.ranges[0].first = 0;
+ fdselect->data.ranges[0].fd = 0;
+ cffont->fdselect = fdselect;
+ }
+
+ {
+ cff_charsets *charset;
+
+ charset = xcalloc(1, sizeof(cff_charsets));
+ charset->format = 0;
+ charset->num_entries = num_glyphs-1;
+ charset->data.glyphs = xcalloc(num_glyphs, sizeof(s_SID));
+
+ gid = 0;
+
+ avl_t_init(&t, fd->gl_tree);
+ for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
+ found != NULL;
+ found = (glw_entry *) avl_t_next(&t)) {
+ if(found->id!=0) {
+ charset->data.glyphs[gid] = found->id;
+ gid++;
+ }
+ }
+ cffont->charsets = charset;
+ }
+
+ cff_dict_add(cffont->topdict, "CIDCount", 1);
+ cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1);
+
+ cffont->fdarray = xcalloc(1, sizeof(cff_dict *));
+ cffont->fdarray[0] = cff_new_dict();
+ cff_dict_add(cffont->fdarray[0], "FontName", 1);
+ cff_dict_set(cffont->fdarray[0], "FontName", 0,
+ (double) cff_add_string(cffont, fullname)); /* FIXME: Skip XXXXXX+ */
+ cff_dict_add(cffont->fdarray[0], "Private", 2);
+ cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0);
+ cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0);
+ /* FDArray - index offset, not known yet */
+ cff_dict_add(cffont->topdict, "FDArray", 1);
+ cff_dict_set(cffont->topdict, "FDArray", 0, 0.0);
+ /* FDSelect - offset, not known yet */
+ cff_dict_add(cffont->topdict, "FDSelect", 1);
+ cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0);
+
+ cff_dict_remove(cffont->topdict, "UniqueID");
+ cff_dict_remove(cffont->topdict, "XUID");
+ cff_dict_remove(cffont->topdict, "Private");
+ cff_dict_remove(cffont->topdict, "Encoding");
+
+ cffont->offset = cff_dict_get(cffont->topdict, "CharStrings", 0);
+ cs_idx = cff_get_index_header(cffont);
+
+ offset = cffont->offset;
+ cs_count = cs_idx->count;
+ if (cs_count < 2) {
+ CFF_ERROR("No valid charstring data found.");
+ }
+
+ /* build the new charstrings entry */
+ charstrings = cff_new_index(cs_count+1);
+ max_len = 2 * CS_STR_LEN_MAX;
+ charstrings->data = xcalloc(max_len, sizeof(card8));
+ charstring_len = 0;
+
+ gid = 0;
+ data = xcalloc(CS_STR_LEN_MAX, sizeof(card8));
+
+ for (code=0; code < cs_count; code++) {
+ glyph->id = code;
+ if ((avl_find(fd->gl_tree,glyph) != NULL)) {
+ size = cs_idx->offset[code+1] - cs_idx->offset[code];
+
+ if (size > CS_STR_LEN_MAX) {
+ pdftex_fail("Charstring too long: gid=%u, %ld bytes", code, size);
+ }
+ if (charstring_len + CS_STR_LEN_MAX >= max_len) {
+ max_len = charstring_len + 2 * CS_STR_LEN_MAX;
+ charstrings->data = xrealloc(charstrings->data, max_len*sizeof(card8));
+ }
+ (charstrings->offset)[gid] = charstring_len + 1;
+ cffont->offset= offset + (cs_idx->offset)[code] - 1;
+ memcpy(data,&cffont->stream[cffont->offset],size);
+ charstring_len += cs_copy_charstring(charstrings->data + charstring_len,
+ max_len - charstring_len,
+ data, size,
+ cffont->gsubr, (cffont->subrs)[0],
+ default_width, nominal_width, NULL);
+ gid++;
+ }
+ }
+
+ /* this happens if the internal metrics do not agree with the actual disk font */
+ if (gid < num_glyphs) {
+ WARN("embedded subset is smaller than expected: %d instead of %d glyphs.", gid, num_glyphs);
+ num_glyphs = gid;
+ }
+
+ xfree(data);
+ cff_release_index(cs_idx);
+
+ (charstrings->offset)[num_glyphs] = charstring_len + 1;
+ charstrings->count = num_glyphs;
+ cffont->num_glyphs = num_glyphs;
+ cffont->cstrings = charstrings;
+
+ /*
+ * We don't use subroutines at all.
+ */
+ if (cffont->gsubr)
+ cff_release_index(cffont->gsubr);
+ cffont->gsubr = cff_new_index(0);
+
+ if (cffont->subrs && cffont->subrs[0])
+ cff_release_index(cffont->subrs[0]);
+ cffont->subrs[0] = NULL;
+
+ if (cffont->private && (cffont->private)[0]) {
+ cff_dict_remove((cffont->private)[0], "Subrs"); /* no Subrs */
+ }
+
+ cff_add_string(cffont, (char *)"Adobe");
+ cff_add_string(cffont, (char *)"Identity");
+
+ cff_dict_update(cffont->topdict, cffont);
+ cff_dict_update(cffont->private[0], cffont);
+ cff_update_string(cffont);
+
+ /* CFF code need to be rewrote... */
+ cff_dict_add(cffont->topdict, "ROS", 3);
+ cff_dict_set(cffont->topdict, "ROS", 0,
+ (double) cff_get_sid(cffont, (char *)"Adobe"));
+ cff_dict_set(cffont->topdict, "ROS", 1,
+ (double) cff_get_sid(cffont, (char *)"Identity"));
+ cff_dict_set(cffont->topdict, "ROS", 2, 0.0);
+
+ write_fontfile(cffont,fullname);
+ xfree(fullname);
+ cff_close (cffont);
+
+}
+
+#define ERROR(a) { perror(a); return 0; }
+
+/* Input : SID or CID (16-bit unsigned int)
+ * Output: glyph index
+ */
+card16
+cff_charsets_lookup (cff_font *cff, card16 cid)
+{
+ card16 gid = 0;
+ cff_charsets *charset;
+ card16 i;
+
+ if (cff->flag & (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB)) {
+ ERROR("Predefined CFF charsets not supported yet");
+ } else if (cff->charsets == NULL) {
+ ERROR("Charsets data not available");
+ }
+
+ if (cid == 0) {
+ return 0; /* GID 0 (.notdef) */
+ }
+
+ charset = cff->charsets;
+
+ gid = 0;
+ switch (charset->format) {
+ case 0:
+ for (i = 0; i <charset->num_entries; i++) {
+ if (cid == charset->data.glyphs[i]) {
+ gid = i + 1;
+ return gid;
+ }
+ }
+ break;
+ case 1:
+ for (i = 0; i < charset->num_entries; i++) {
+ if (cid >= charset->data.range1[i].first &&
+ cid <= charset->data.range1[i].first + charset->data.range1[i].n_left) {
+ gid += cid - charset->data.range1[i].first + 1;
+ return gid;
+ }
+ gid += charset->data.range1[i].n_left + 1;
+ }
+ break;
+ case 2:
+ for (i = 0; i < charset->num_entries; i++) {
+ if (cid >= charset->data.range2[i].first &&
+ cid <= charset->data.range2[i].first + charset->data.range2[i].n_left) {
+ gid += cid - charset->data.range2[i].first + 1;
+ return gid;
+ }
+ gid += charset->data.range2[i].n_left + 1;
+ }
+ break;
+ default:
+ ERROR("Unknown Charset format");
+ }
+
+ return 0; /* not found */
+}
+
+
+#define is_cidfont(a) ((a)->flag & FONTTYPE_CIDFONT)
+#define CID_MAX 65535
+
+void write_cid_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) {
+ cff_index *charstrings, *cs_idx;
+
+ long charstring_len, max_len;
+ long size, offset = 0;
+
+ card8 *data;
+ card16 num_glyphs, cs_count, gid, last_cid;
+
+
+ int fdsel, prev_fd, cid_count, cid;
+ char *fullname;
+
+ glw_entry *glyph;
+
+ unsigned char *CIDToGIDMap = NULL;
+
+ cff_fdselect *fdselect = NULL;
+ cff_charsets *charset = NULL;
+
+
+ if (!is_cidfont(cffont)) {
+ perror("Not a CIDfont.");
+ return;
+ }
+
+ fullname = xcalloc(8+strlen(fd->fontname),1);
+ sprintf(fullname,"%s+%s",fd->subset_tag,fd->fontname);
+
+ /* finish parsing the CFF */
+
+ if (cff_dict_known(cffont->topdict, "CIDCount")) {
+ cid_count = (card16) cff_dict_get(cffont->topdict, "CIDCount", 0);
+ } else {
+ cid_count = CFF_CIDCOUNT_DEFAULT;
+ }
+ cff_read_charsets(cffont);
+ CIDToGIDMap = xmalloc((2*cid_count) * sizeof(unsigned char));
+ memset(CIDToGIDMap, 0, 2*cid_count);
+
+
+ glyph = xtalloc(1,glw_entry);
+ /* insert notdef */
+ glyph->id = uglytype1fix;
+ if (avl_find(fd->gl_tree, glyph)==NULL) {
+ avl_insert(fd->gl_tree, glyph);
+ glyph = xtalloc(1,glw_entry);
+ }
+
+ cid = 0; last_cid = 0; num_glyphs = 0;
+ for (cid = 0; cid <= CID_MAX; cid++) {
+ glyph->id = cid;
+ if (avl_find(fd->gl_tree,glyph) != NULL) {
+ gid = cff_charsets_lookup(cffont, cid);
+ CIDToGIDMap[2*cid] = (gid >> 8) & 0xff;
+ CIDToGIDMap[2*cid+1] = gid & 0xff;
+ last_cid = cid;
+ num_glyphs++;
+ }
+ }
+
+ cff_read_fdselect(cffont);
+ cff_read_fdarray(cffont);
+ cff_read_private(cffont);
+
+ cff_read_subrs (cffont);
+
+
+ cffont->offset = cff_dict_get(cffont->topdict, "CharStrings", 0);
+ cs_idx = cff_get_index_header(cffont);
+
+ offset = cffont->offset;
+ cs_count = cs_idx->count;
+ if (cs_count < 2) {
+ CFF_ERROR("No valid charstring data found.");
+ }
+
+ charset = xcalloc(1, sizeof(cff_charsets));
+ charset->format = 0;
+ charset->num_entries = 0;
+ charset->data.glyphs = xcalloc(num_glyphs, sizeof(s_SID));
+
+ fdselect = xcalloc(1, sizeof(cff_fdselect));
+ fdselect->format = 3;
+ fdselect->num_entries = 0;
+ fdselect->data.ranges = xcalloc(num_glyphs, sizeof(cff_range3));
+
+ charstrings = cff_new_index(cs_count+1);
+ max_len = 2 * CS_STR_LEN_MAX;
+ charstrings->data = xcalloc(max_len, sizeof(card8));
+ charstring_len = 0;
+
+ prev_fd = -1; gid = 0;
+ data = xcalloc(CS_STR_LEN_MAX, sizeof(card8));
+ for (cid=0; cid <= last_cid; cid++) {
+ unsigned short gid_org;
+
+ glyph->id = cid;
+ if (avl_find(fd->gl_tree,glyph) == NULL)
+ continue;
+
+ gid_org = (CIDToGIDMap[2*cid] << 8)|(CIDToGIDMap[2*cid+1]);
+ size = cs_idx->offset[gid_org+1] - cs_idx->offset[gid_org];
+ if (size > CS_STR_LEN_MAX) {
+ pdftex_fail("Charstring too long: gid=%u, %ld bytes", cid, size);
+ }
+ if (charstring_len + CS_STR_LEN_MAX >= max_len) {
+ max_len = charstring_len + 2 * CS_STR_LEN_MAX;
+ charstrings->data = xrealloc(charstrings->data, max_len*sizeof(card8));
+ }
+ (charstrings->offset)[gid] = charstring_len + 1;
+ cffont->offset= offset + (cs_idx->offset)[gid_org] - 1;
+ memcpy(data,&cffont->stream[cffont->offset],size);
+ fdsel = cff_fdselect_lookup(cffont, gid_org);
+ charstring_len += cs_copy_charstring(charstrings->data + charstring_len,
+ max_len - charstring_len,
+ data, size,
+ cffont->gsubr, (cffont->subrs)[fdsel],
+ 0, 0, NULL);
+
+ if (cid>0 && gid_org > 0) {
+ charset->data.glyphs[charset->num_entries] = cid;
+ charset->num_entries += 1;
+ }
+ if (fdsel != prev_fd) {
+ fdselect->data.ranges[fdselect->num_entries].first = gid;
+ fdselect->data.ranges[fdselect->num_entries].fd = fdsel;
+ fdselect->num_entries += 1;
+ prev_fd = fdsel;
+ }
+ gid++;
+ }
+
+ if (gid != num_glyphs)
+ CFF_ERROR("Unexpected error: %i != %i", gid, num_glyphs);
+ xfree(data);
+ cff_release_index(cs_idx);
+
+ xfree(CIDToGIDMap);
+
+ (charstrings->offset)[num_glyphs] = charstring_len + 1;
+ charstrings->count = num_glyphs;
+ cffont->num_glyphs = num_glyphs;
+ cffont->cstrings = charstrings;
+
+ cff_release_charsets(cffont->charsets);
+ cffont->charsets = charset;
+ cff_release_fdselect(cffont->fdselect);
+ cffont->fdselect = fdselect;
+
+ /*
+ * We don't use subroutines at all.
+ */
+ if (cffont->gsubr)
+ cff_release_index(cffont->gsubr);
+ cffont->gsubr = cff_new_index(0);
+
+ for (fdsel = 0; fdsel < cffont->num_fds; fdsel++) {
+ if (cffont->subrs && cffont->subrs[fdsel]) {
+ cff_release_index(cffont->subrs[fdsel]);
+ cffont->subrs[fdsel] = NULL;
+ }
+ if (cffont->private && (cffont->private)[fdsel]) {
+ cff_dict_remove((cffont->private)[fdsel], "Subrs"); /* no Subrs */
+ }
+ }
+
+ write_fontfile(cffont,fullname);
+ xfree(fullname);
+ cff_close (cffont);
+
+}
+
+
+/* here is a sneaky trick: fontforge knows how to convert Type1 to CFF, so
+ * I have defined a utility function in luafflib.c that does exactly that.
+ * If it works out ok, I will clean up this code.
+ */
+
+extern int ff_createcff (char *, unsigned char **, integer *);
+
+void writetype1w (fd_entry *fd) {
+ cff_font *cff;
+ int i;
+ FILE *fp;
+ ff_entry *ff;
+ unsigned char *tfm_buffer = NULL;
+ integer tfm_size = 0;
+ int notdefpos = 0;
+
+ ff = check_ff_exist(fd->fm->ff_name, 0);
+
+ fp = fopen (ff->ff_path, "rb");
+ cur_file_name = ff->ff_path;
+
+ if (!fp) {
+ fprintf(stderr,"Type1: Could not open Type1 font: %s", cur_file_name);
+ uexit(1);
+ }
+ fclose(fp);
+
+ if (tracefilenames) {
+ if (is_subsetted(fd->fm))
+ tex_printf ("<%s", cur_file_name);
+ else
+ tex_printf ("<<%s", cur_file_name);
+ }
+
+ notdefpos = ff_createcff(ff->ff_path,&tfm_buffer,&tfm_size);
+
+ if (tfm_size>0) {
+ cff = read_cff(tfm_buffer,tfm_size,0);
+ if (cff != NULL) {
+ write_cff(cff,fd,notdefpos);
+ } else {
+ for (i = 0; i < tfm_size ; i++)
+ fb_putchar (tfm_buffer[i]);
+ }
+ fd->ff_found = 1;
+ } else {
+ fprintf(stderr,"Type1: Could not understand Type1 font: %s", cur_file_name);
+ uexit(1);
+ }
+ if (tracefilenames) {
+ if (is_subsetted (fd->fm))
+ tex_printf (">");
+ else
+ tex_printf (">>");
+ }
+ cur_file_name = NULL;
+}
+
+
diff --git a/Build/source/texk/web2c/luatexdir/font/writecff.h b/Build/source/texk/web2c/luatexdir/font/writecff.h
new file mode 100644
index 00000000000..8cb93024f7a
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writecff.h
@@ -0,0 +1,349 @@
+/* $Header: /home/cvsroot/dvipdfmx/src/cff_limits.h,v 1.3 2002/10/30 02:27:05 chofchof Exp $
+
+ This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
+
+ Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
+ the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+*/
+
+#ifndef _CFF_LIMITS_H_
+#define _CFF_LIMITS_H_
+
+#include <limits.h>
+
+#define CFF_INT_MAX 0x7fffffff
+#define CFF_INT_MIN (-0x7fffffff - 1)
+
+#if (LONG_MAX < CFF_INT_MAX || LONG_MIN > CFF_INT_MIN)
+#error "CFF support won't work on this system."
+#endif
+
+#define CFF_SID_MAX 64999
+#define CFF_STDSTR_MAX 391
+
+/* Type 2 Charstring */
+#define CS_NUM_SUBR_MAX 65536
+#define CS_STR_LEN_MAX 65536
+#define CS_STEM_ZONE_MAX 96
+#define CS_ARG_STACK_MAX 48
+#define CS_TRANS_ARRAY_MAX 32
+#define CS_SUBR_NEST_MAX 10
+
+#endif /* _CFF_LIMITS_H_ */
+
+#ifndef _CFF_TYPES_H_
+#define _CFF_TYPES_H_
+
+/* CFF Data Types */
+
+#define CFF_TYPE_UNKNOWN 0
+#define CFF_TYPE_INTEGER (1 << 0)
+#define CFF_TYPE_REAL (1 << 1)
+#define CFF_TYPE_NUMBER (CFF_TYPE_INTEGER|CFF_TYPE_REAL)
+#define CFF_TYPE_BOOLEAN (1 << 2)
+#define CFF_TYPE_SID (1 << 3)
+#define CFF_TYPE_ARRAY (1 << 4)
+#define CFF_TYPE_DELTA (1 << 5)
+
+/* SID SID number */
+#define CFF_TYPE_ROS (1 << 6)
+/* offset(0) */
+#define CFF_TYPE_OFFSET (1 << 7)
+/* size offset(0) */
+#define CFF_TYPE_SZOFF (1 << 8)
+
+typedef unsigned char card8; /* 1-byte unsigned number */
+typedef unsigned short card16; /* 2-byte unsigned number */
+typedef unsigned char c_offsize; /* 1-byte unsigned number specifies the size
+ of an Offset field or fields, range 1-4 */
+typedef unsigned long l_offset; /* 1, 2, 3, or 4-byte offset */
+typedef unsigned short s_SID; /* 2-byte string identifier */
+
+typedef unsigned long l_size;
+
+typedef struct {
+ card16 count; /* number of objects stored in INDEX */
+ c_offsize offsize; /* Offset array element size, 1-4 */
+ l_offset *offset; /* Offset array, count + 1 offsets */
+ card8 *data; /* Object data */
+} cff_index;
+
+
+/* Dictionary */
+typedef struct {
+ int id; /* encoded data value (as card8 or card16) */
+ char *key; /* opname */
+ int count; /* number of values */
+ double *values; /* values */
+} cff_dict_entry;
+
+typedef struct {
+ int max;
+ int count;
+ cff_dict_entry *entries;
+} cff_dict;
+
+/* Encoding, Charset and FDSelect */
+typedef struct
+{
+ s_SID first; /* SID or CID, or card8 for Encoding */
+ card8 n_left; /* no. of remaining gids/codes in this range */
+} cff_range1;
+
+typedef struct
+{
+ s_SID first; /* SID or CID (card16) */
+ card16 n_left; /* card16-version of range1 */
+} cff_range2;
+
+typedef struct
+{
+ card8 code;
+ s_SID glyph;
+} cff_map;
+
+typedef struct
+{
+ card8 format; /* if (format & 0x80) then have supplement */
+ card8 num_entries; /* number of entries */
+ union {
+ card8 *codes; /* format 0 */
+ cff_range1 *range1; /* format 1 */
+ } data;
+ card8 num_supps; /* number of supplementary data */
+ cff_map *supp; /* supplement */
+} cff_encoding;
+
+typedef struct
+{
+ card8 format;
+ card16 num_entries;
+ union {
+ s_SID *glyphs; /* format 0 */
+ cff_range1 *range1; /* format 1 */
+ cff_range2 *range2; /* format 2 */
+ } data;
+} cff_charsets;
+
+/* CID-Keyed font specific */
+typedef struct
+{
+ card16 first;
+ card8 fd;
+} cff_range3;
+
+typedef struct
+{
+ card8 format;
+ card16 num_entries; /* number of glyphs/ranges */
+ union {
+ card8 *fds; /* format 0 */
+ cff_range3 *ranges; /* format 3 */
+ } data;
+ /* card16 sentinel; */ /* format 3 only, must be equals to num_glyphs */
+} cff_fdselect;
+
+#endif /* _CFF_TYPES_H_ */
+
+#ifndef _CFF_STDSTR_H_
+#define _CFF_STDSTR_H_
+
+#define CFF_STDSTR_MAX 391
+
+extern const char *const cff_stdstr[];
+#endif /* _CFF_STDSTR_H_ */
+
+#ifndef _CFF_H_
+#define _CFF_H_
+
+/*#include "mfileio.h"*/
+
+/* Flag */
+#define FONTTYPE_CIDFONT (1 << 0)
+#define FONTTYPE_FONT (1 << 1)
+#define FONTTYPE_MMASTER (1 << 2)
+
+#define ENCODING_STANDARD (1 << 3)
+#define ENCODING_EXPERT (1 << 4)
+
+#define CHARSETS_ISOADOBE (1 << 5)
+#define CHARSETS_EXPERT (1 << 6)
+#define CHARSETS_EXPSUB (1 << 7)
+
+#define HAVE_STANDARD_ENCODING (ENCODING_STANDARD|ENCODING_EXPERT)
+#define HAVE_STANDARD_CHARSETS \
+ (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB)
+
+#define CFF_STRING_NOTDEF 65535
+
+typedef struct
+{
+ char *fontname; /* FontName */
+
+ /* - CFF structure - */
+
+ card8 header_major; /* major version */
+ card8 header_minor; /* minor version */
+ card8 header_hdr_size; /* Header size (bytes) */
+ c_offsize header_offsize; /* Absolute offset (0) size */
+
+ cff_index *name; /* Name INDEX */
+ cff_dict *topdict; /* Top DICT (single) */
+ cff_index *string; /* String INDEX */
+ cff_index *gsubr; /* Global Subr INDEX */
+ cff_encoding *encoding; /* Encodings */
+ cff_charsets *charsets; /* Charsets */
+ cff_fdselect *fdselect; /* FDSelect, CIDFont only */
+ cff_index *cstrings; /* CharStrings */
+ cff_dict **fdarray; /* CIDFont only */
+ cff_dict **private; /* per-Font DICT */
+ cff_index **subrs; /* Local Subr INDEX, per-Private DICT */
+
+ /* -- extra data -- */
+ l_offset gsubr_offset;
+ card16 num_glyphs; /* number of glyphs (CharString INDEX count) */
+ card8 num_fds; /* number of Font DICT */
+
+ /* Updated String INDEX.
+ * Please fix this. We should separate input and output.
+ */
+ cff_index *_string;
+
+ unsigned char *stream;
+ l_offset offset;
+ l_offset stream_size;
+
+ int index; /* CFF fontset index */
+ int flag; /* Flag: see above */
+} cff_font;
+
+extern cff_font *cff_open(unsigned char *stream, long stream_size, int n);
+extern void cff_close (cff_font *cff);
+
+#define cff_seek_set(c, p) seek_absolute (((c)->stream), ((c)->offset) + (p));
+
+/* CFF Header */
+extern long cff_put_header (cff_font *cff, card8 *dest, long destlen);
+
+/* CFF INDEX */
+extern cff_index *cff_get_index (cff_font *cff);
+extern cff_index *cff_get_index_header (cff_font *cff);
+extern void cff_release_index (cff_index *idx);
+extern cff_index *cff_new_index (card16 count);
+extern long cff_index_size (cff_index *idx);
+extern long cff_pack_index (cff_index *idx, card8 *dest, long destlen);
+
+/* Name INDEX */
+extern char *cff_get_name (cff_font *cff);
+extern long cff_set_name (cff_font *cff, char *name);
+
+/* Global and Local Subrs INDEX */
+extern long cff_read_subrs (cff_font *cff);
+
+/* Encoding */
+extern long cff_read_encoding (cff_font *cff);
+extern long cff_pack_encoding (cff_font *cff, card8 *dest, long destlen);
+extern card16 cff_encoding_lookup (cff_font *cff, card8 code);
+extern void cff_release_encoding (cff_encoding *encoding);
+
+/* Charsets */
+extern long cff_read_charsets (cff_font *cff);
+extern long cff_pack_charsets (cff_font *cff, card8 *dest, long destlen);
+
+/* Returns GID of PS name "glyph" */
+extern card16 cff_glyph_lookup (cff_font *cff, const char *glyph);
+/* Returns GID of glyph with SID/CID "cid" */
+extern card16 cff_charsets_lookup (cff_font *cff, card16 cid);
+extern void cff_release_charsets (cff_charsets *charset);
+/* Returns SID or CID */
+extern card16 cff_charsets_lookup_inverse (cff_font *cff, card16 gid);
+
+/* FDSelect */
+extern long cff_read_fdselect (cff_font *cff);
+extern long cff_pack_fdselect (cff_font *cff, card8 *dest, long destlen);
+extern card8 cff_fdselect_lookup (cff_font *cff, card16 gid);
+extern void cff_release_fdselect (cff_fdselect *fdselect);
+
+/* Font DICT(s) */
+extern long cff_read_fdarray (cff_font *cff);
+
+/* Private DICT(s) */
+extern long cff_read_private (cff_font *cff);
+
+/* String */
+extern int cff_match_string (cff_font *cff, const char *str, s_SID sid);
+extern char *cff_get_string (cff_font *cff, s_SID id);
+extern long cff_get_sid (cff_font *cff, char *str);
+extern s_SID cff_add_string (cff_font *cff, char *str);
+extern void cff_update_string (cff_font *cff);
+
+#define cff_is_stdstr(s) (cff_get_sid(NULL, (s)) >= 0)
+
+#endif /* _CFF_H_ */
+
+#ifndef _CFF_DICT_H_
+#define _CFF_DICT_H_
+
+#define CFF_CIDCOUNT_DEFAULT 8720
+#define CFF_NOMINALWIDTHX_DEFAULT 0.0
+#define CFF_DEFAULTWIDTHX_DEFAULT 0.0
+
+extern cff_dict *cff_new_dict (void);
+extern void cff_release_dict (cff_dict *dict);
+
+extern void cff_dict_set (cff_dict *dict, const char *key, int idx, double value);
+extern double cff_dict_get (cff_dict *dict, const char *key, int idx);
+extern void cff_dict_add (cff_dict *dict, const char *key, int count);
+extern void cff_dict_remove (cff_dict *dict, const char *key);
+extern int cff_dict_known (cff_dict *dict, const char *key);
+
+/* decode/encode DICT */
+extern cff_dict *cff_dict_unpack (card8 *data, card8 *endptr);
+extern long cff_dict_pack (cff_dict *dict, card8 *dest, long destlen);
+
+extern void cff_dict_update (cff_dict *dict, cff_font *cff);
+
+#endif /* _CFF_DICT_H_ */
+
+#ifndef _CS_TYPE2_H_
+#define _CS_TYPE2_H_
+
+typedef struct {
+ int flags; /* unused in Type 2 charstring */
+ double wx, wy;
+ struct {
+ double llx, lly, urx, ury;
+ } bbox;
+ struct {
+ double asb, adx, ady;
+ card8 bchar, achar;
+ } seac; /* unused in Type 2 charstring */
+} cs_ginfo;
+
+extern long cs_copy_charstring (card8 *dest, long destlen,
+ card8 *src, long srclen,
+ cff_index *gsubr, cff_index *subr,
+ double default_width, double nominal_width, cs_ginfo *ginfo);
+#endif /* _CS_TYPE2_H_ */
+
+#define cff_is_cidfont(a) (a->flag & FONTTYPE_CIDFONT)
+#define cff_understandable(a) (a->header_major==1)
+
+extern cff_font *read_cff(unsigned char *buf,long buflength, int subf);
+
+extern void write_cff(cff_font *cff, fd_entry *fd, int hack);
+extern void write_cid_cff(cff_font *cffont, fd_entry *fd, int uglytype1fix) ;
diff --git a/Build/source/texk/web2c/luatexdir/font/writeenc.c b/Build/source/texk/web2c/luatexdir/font/writeenc.c
new file mode 100644
index 00000000000..feaf1407d1e
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writeenc.c
@@ -0,0 +1,183 @@
+/*
+Copyright (c) 1996-2005 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writeenc.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+/**********************************************************************/
+/* All encoding entries go into AVL tree for fast search by name. */
+
+struct avl_table *fe_tree = NULL;
+
+/* AVL sort fe_entry into fe_tree by name */
+
+static int comp_fe_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const fe_entry *) pa)->name, ((const fe_entry *) pb)->name);
+}
+
+fe_entry *new_fe_entry()
+{
+ fe_entry *fe;
+ fe = xtalloc(1, fe_entry);
+ fe->name = NULL;
+ fe->fe_objnum = 0;
+ fe->glyph_names = NULL; /* encoding file not yet read in */
+ fe->tx_tree = NULL;
+ return fe;
+}
+
+fe_entry *lookup_fe_entry(char *s)
+{
+ fe_entry fe;
+ assert(s != NULL);
+ fe.name = s;
+ if (fe_tree == NULL) {
+ fe_tree = avl_create(comp_fe_entry, NULL, &avl_xallocator);
+ assert(fe_tree != NULL);
+ }
+ return (fe_entry *) avl_find(fe_tree, &fe);
+}
+
+void register_fe_entry(fe_entry * fe)
+{
+ void **aa;
+ if (fe_tree == NULL) {
+ fe_tree = avl_create(comp_fe_entry, NULL, &avl_xallocator);
+ assert(fe_tree != NULL);
+ }
+ assert(fe != NULL);
+ assert(fe->name != NULL);
+ assert(lookup_fe_entry(fe->name) == NULL); /* encoding not yet registered */
+ aa = avl_probe(fe_tree, fe);
+ assert(aa != NULL);
+}
+
+fe_entry *get_fe_entry(char *s)
+{
+ fe_entry *fe;
+ char **gl;
+ if ((fe = lookup_fe_entry(s)) == NULL && (gl = load_enc_file(s)) != NULL) {
+ fe = new_fe_entry();
+ fe->name = s;
+ fe->glyph_names = gl;
+ register_fe_entry(fe);
+ }
+ return fe;
+}
+
+/**********************************************************************/
+
+void epdf_write_enc(char **glyph_names, integer fe_objnum)
+{
+ int i, i_old;
+ assert(glyph_names != NULL);
+ assert(fe_objnum != 0);
+ pdf_begin_dict(fe_objnum, 1);
+ pdf_puts("/Type /Encoding\n");
+ pdf_printf("/Differences [");
+ for (i = 0, i_old = -2; i < 256; i++)
+ if (glyph_names[i] != notdef) {
+ if (i == i_old + 1) /* no gap */
+ pdf_printf("/%s", glyph_names[i]);
+ else {
+ if (i_old == -2)
+ pdf_printf("%i/%s", i, glyph_names[i]);
+ else
+ pdf_printf(" %i/%s", i, glyph_names[i]);
+ }
+ i_old = i;
+ }
+ pdf_puts("]\n");
+ pdf_end_dict();
+}
+
+void write_enc(char **glyph_names, struct avl_table *tx_tree, integer fe_objnum)
+{
+ int i_old, *p;
+ struct avl_traverser t;
+ assert(glyph_names != NULL);
+ assert(tx_tree != NULL);
+ assert(fe_objnum != 0);
+ pdf_begin_dict(fe_objnum, 1);
+ pdf_puts("/Type /Encoding\n");
+ pdf_printf("/Differences [");
+ avl_t_init(&t, tx_tree);
+ for (i_old = -2, p = (int *) avl_t_first(&t, tx_tree); p != NULL;
+ p = (int *) avl_t_next(&t)) {
+ if (*p == i_old + 1) /* no gap */
+ pdf_printf("/%s", glyph_names[*p]);
+ else {
+ if (i_old == -2)
+ pdf_printf("%i/%s", *p, glyph_names[*p]);
+ else
+ pdf_printf(" %i/%s", *p, glyph_names[*p]);
+ }
+ i_old = *p;
+ }
+ pdf_puts("]\n");
+ pdf_end_dict();
+}
+
+void write_fontencoding(fe_entry * fe)
+{
+ assert(fe != NULL);
+ write_enc(fe->glyph_names, fe->tx_tree, fe->fe_objnum);
+}
+
+void write_fontencodings()
+{
+ fe_entry *fe;
+ struct avl_traverser t;
+ if (fe_tree == NULL)
+ return;
+ avl_t_init(&t, fe_tree);
+ for (fe = (fe_entry *) avl_t_first(&t, fe_tree); fe != NULL;
+ fe = (fe_entry *) avl_t_next(&t))
+ if (fe->fe_objnum != 0)
+ write_fontencoding(fe);
+}
+
+/**********************************************************************/
+/* cleaning up... */
+
+static void destroy_fe_entry(void *pa, void *pb)
+{
+ fe_entry *p;
+ int i;
+ p = (fe_entry *) pa;
+ xfree(p->name);
+ if (p->glyph_names != NULL)
+ for (i = 0; i < 256; i++)
+ if (p->glyph_names[i] != notdef)
+ xfree(p->glyph_names[i]);
+ xfree(p->glyph_names);
+ xfree(p);
+}
+
+void enc_free()
+{
+ if (fe_tree != NULL)
+ avl_destroy(fe_tree, destroy_fe_entry);
+ fe_tree = NULL;
+}
+
+/**********************************************************************/
diff --git a/Build/source/texk/web2c/luatexdir/font/writefont.c b/Build/source/texk/web2c/luatexdir/font/writefont.c
new file mode 100644
index 00000000000..05257746889
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writefont.c
@@ -0,0 +1,885 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writefont.c 1112 2008-03-20 14:46:32Z taco $
+*/
+
+#include "ptexlib.h"
+
+extern void writetype0 (fd_entry * fd) ;
+extern void writetype2 (fd_entry * fd) ;
+extern unsigned long cidtogid_obj;
+
+#ifdef DO_TYPE1C
+extern void writet1c(fd_entry * fd); /* in writecff.c */
+#endif
+
+extern void writet1w (fd_entry * fd); /* in writecff.c */
+extern void writetype1w (fd_entry * fd);
+extern integer write_cid_tounicode(fo_entry * fo, internalfontnumber f); /* in tounicode.c */
+
+
+void write_cid_fontdictionary(fo_entry * fo, internalfontnumber f);
+void create_cid_fontdictionary(fm_entry * fm, integer font_objnum, internalfontnumber f);
+
+/**********************************************************************/
+
+struct avl_table *fo_tree = NULL; /* tree of font dictionaries */
+struct avl_table *fd_tree = NULL; /* tree of font descriptor objects */
+
+static int comp_fo_entry(const void *pa, const void *pb, void *p)
+{
+ return strcmp(((const fo_entry *) pa)->fm->tfm_name,
+ ((const fo_entry *) pb)->fm->tfm_name);
+}
+
+static int comp_fd_entry(const void *pa, const void *pb, void *p)
+{
+ int i;
+ const fd_entry *p1 = (const fd_entry *) pa, *p2 = (const fd_entry *) pb;
+ assert(p1->fm != NULL && is_fontfile(p1->fm) &&
+ p2->fm != NULL && is_fontfile(p2->fm));
+ if ((i = strcmp(p1->fm->ff_name, p2->fm->ff_name)) != 0)
+ return i;
+ cmp_return(p1->fm->slant, p2->fm->slant);
+ cmp_return(p1->fm->extend, p2->fm->extend);
+ return 0;
+}
+
+/**********************************************************************/
+/* initialize data structure for /Type /Font */
+
+fo_entry *new_fo_entry(void)
+{
+ fo_entry *fo;
+ fo = xtalloc(1, fo_entry);
+ fo->fo_objnum = 0;
+ fo->tex_font = 0;
+ fo->fm = NULL;
+ fo->fd = NULL;
+ fo->fe = NULL;
+ fo->cw_objnum = 0;
+ fo->first_char = 1;
+ fo->last_char = 0;
+ fo->tx_tree = NULL;
+ fo->tounicode_objnum = 0;
+ return fo;
+}
+
+/* initialize data structure for /Type /FontDescriptor */
+
+fd_entry *new_fd_entry(void)
+{
+ fd_entry *fd;
+ int i;
+ fd = xtalloc(1, fd_entry);
+ fd->fd_objnum = 0;
+ fd->fontname = NULL;
+ fd->subset_tag = NULL;
+ fd->ff_found = false;
+ fd->ff_objnum = 0;
+ fd->fn_objnum = 0;
+ fd->all_glyphs = false;
+ fd->write_ttf_glyph_names = false;
+ for (i = 0; i < INT_KEYS_NUM; i++) {
+ fd->font_dim[i].val = 0;
+ fd->font_dim[i].set = false;
+ }
+ fd->fe = NULL;
+ fd->builtin_glyph_names = NULL;
+ fd->fm = NULL;
+ fd->tx_tree = NULL;
+ fd->gl_tree = NULL;
+ return fd;
+}
+
+/**********************************************************************/
+/*
+ * Only fallback values of font metrics are taken from the TFM info
+ * of f by preset_fontmetrics(). During reading of the font file,
+ * these values are replaced by metrics from the font, if available.
+ */
+
+static void preset_fontmetrics(fd_entry * fd, internalfontnumber f)
+{
+ int i;
+ fd->font_dim[ITALIC_ANGLE_CODE].val =
+ divide_scaled(-atan(get_slant(f) / 65536.0) * (180 / M_PI),
+ pdf_font_size(f), 3);
+ fd->font_dim[ASCENT_CODE].val =
+ divide_scaled(char_height(f, 'h'), pdf_font_size(f), 3);
+ fd->font_dim[CAPHEIGHT_CODE].val =
+ divide_scaled(char_height(f, 'H'), pdf_font_size(f), 3);
+ i = -divide_scaled(char_depth(f, 'y'), pdf_font_size(f), 3);
+ fd->font_dim[DESCENT_CODE].val = i < 0 ? i : 0;
+ fd->font_dim[STEMV_CODE].val =
+ divide_scaled(char_width(f, '.') / 3, pdf_font_size(f), 3);
+ fd->font_dim[XHEIGHT_CODE].val =
+ divide_scaled(get_x_height(f), pdf_font_size(f), 3);
+ fd->font_dim[FONTBBOX1_CODE].val = 0;
+ fd->font_dim[FONTBBOX2_CODE].val = fd->font_dim[DESCENT_CODE].val;
+ fd->font_dim[FONTBBOX3_CODE].val =
+ divide_scaled(get_quad(f), pdf_font_size(f), 3);
+ fd->font_dim[FONTBBOX4_CODE].val =
+ fd->font_dim[CAPHEIGHT_CODE].val > fd->font_dim[ASCENT_CODE].val ?
+ fd->font_dim[CAPHEIGHT_CODE].val : fd->font_dim[ASCENT_CODE].val;
+ for (i = 0; i < INT_KEYS_NUM; i++)
+ fd->font_dim[i].set = true;
+}
+
+static void write_fontmetrics(fd_entry * fd)
+{
+ int i;
+ if (fd->font_dim[FONTBBOX1_CODE].set && fd->font_dim[FONTBBOX2_CODE].set
+ && fd->font_dim[FONTBBOX3_CODE].set && fd->font_dim[FONTBBOX4_CODE].set)
+ pdf_printf("/%s [%i %i %i %i]\n", font_key[FONTBBOX1_CODE].pdfname,
+ (int) fd->font_dim[FONTBBOX1_CODE].val,
+ (int) fd->font_dim[FONTBBOX2_CODE].val,
+ (int) fd->font_dim[FONTBBOX3_CODE].val,
+ (int) fd->font_dim[FONTBBOX4_CODE].val);
+ for (i = 0; i < GEN_KEY_NUM; i++)
+ if (fd->font_dim[i].set)
+ pdf_printf("/%s %i\n", font_key[i].pdfname, fd->font_dim[i].val);
+}
+
+/**********************************************************************/
+
+static void preset_fontname(fo_entry * fo)
+{
+ if (fo->fm->ps_name != NULL)
+ fo->fd->fontname = xstrdup(fo->fm->ps_name); /* just fallback */
+ else
+ fo->fd->fontname = xstrdup(fo->fm->tfm_name);
+}
+
+static void write_fontname(fd_entry * fd, char *key)
+{
+ assert(fd->fontname != NULL);
+ pdf_puts("/");
+ if (key != NULL)
+ pdf_printf("%s /", key);
+ if (fd->subset_tag != NULL)
+ pdf_printf("%s+", fd->subset_tag);
+ pdf_printf("%s\n", fd->fontname);
+}
+
+static void write_fontname_object(fd_entry * fd)
+{
+ assert(fd->fn_objnum != 0);
+ pdf_begin_obj(fd->fn_objnum, 1);
+ write_fontname(fd, NULL);
+ pdf_end_obj();
+}
+
+/**********************************************************************/
+
+fd_entry *lookup_fd_entry(char *s, integer slant, integer extend)
+{
+ fd_entry fd;
+ fm_entry fm;
+ assert(s != NULL);
+ fm.ff_name = s;
+ fm.slant = slant;
+ fm.extend = extend;
+ fd.fm = &fm;
+ if (fd_tree == NULL) {
+ fd_tree = avl_create(comp_fd_entry, NULL, &avl_xallocator);
+ assert(fd_tree != NULL);
+ }
+ return (fd_entry *) avl_find(fd_tree, &fd);
+}
+
+fd_entry *lookup_fontdescriptor(fo_entry * fo)
+{
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(is_fontfile(fo->fm));
+ return lookup_fd_entry(fo->fm->ff_name, fo->fm->slant, fo->fm->extend);
+}
+
+void register_fd_entry(fd_entry * fd)
+{
+ void **aa;
+ if (fd_tree == NULL) {
+ fd_tree = avl_create(comp_fd_entry, NULL, &avl_xallocator);
+ assert(fd_tree != NULL);
+ }
+ assert(fd != NULL && fd->fm != NULL && is_fontfile(fd->fm));
+ assert(lookup_fd_entry(fd->fm->ff_name, fd->fm->slant, fd->fm->extend) == NULL); /* font descriptor not yet registered */
+ aa = avl_probe(fd_tree, fd);
+ assert(aa != NULL);
+}
+
+void create_fontdescriptor(fo_entry * fo, internalfontnumber f)
+{
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(fo->fd == NULL);
+ fo->fd = new_fd_entry();
+ preset_fontname(fo);
+ preset_fontmetrics(fo->fd, f);
+ fo->fd->fe = fo->fe; /* encoding needed by TrueType writing */
+ fo->fd->fm = fo->fm; /* map entry needed by TrueType writing */
+ fo->fd->gl_tree = avl_create(comp_string_entry, NULL, &avl_xallocator);
+ assert(fo->fd->gl_tree != NULL);
+}
+
+/**********************************************************************/
+/*
+ * For all used characters of TeX font f, get corresponding glyph names
+ * from external reencoding (.enc) file and collect these in the glyph
+ * tree gl_tree of font descriptor fd referenced by font dictionary fo.
+ */
+
+void mark_reenc_glyphs(fo_entry * fo, internalfontnumber f)
+{
+ int i;
+ char **g;
+ void **aa;
+ assert(fo->fe != NULL);
+ if (is_subsetted(fo->fm)) {
+ assert(is_included(fo->fm));
+ /* mark glyphs from TeX (externally reencoded characters) */
+ g = fo->fe->glyph_names;
+ for (i = fo->first_char; i <= fo->last_char; i++) {
+ if (pdf_char_marked(f, i) && g[i] != notdef
+ && (char *) avl_find(fo->fd->gl_tree, g[i]) == NULL) {
+ aa = avl_probe(fo->fd->gl_tree, xstrdup(g[i]));
+ assert(aa != NULL);
+ }
+ }
+ }
+}
+
+/*
+ * Function mark_chars() has 2 uses:
+ * 1. Mark characters as chars on TeX level.
+ * 2. Mark encoding pairs used by TeX to optimize encoding vector.
+ */
+
+struct avl_table *mark_chars(fo_entry * fo, struct avl_table *tx_tree,
+ internalfontnumber f)
+{
+ int i, *j;
+ void **aa;
+ if (tx_tree == NULL) {
+ tx_tree = avl_create(comp_int_entry, NULL, &avl_xallocator);
+ assert(tx_tree != NULL);
+ }
+ for (i = fo->first_char; i <= fo->last_char; i++) {
+ if (pdf_char_marked(f, i) && (int *) avl_find(tx_tree, &i) == NULL) {
+ j = xtalloc(1, int);
+ *j = i;
+ aa = avl_probe(tx_tree, j);
+ assert(aa != NULL);
+ }
+ }
+ return tx_tree;
+}
+
+/**********************************************************************/
+
+void get_char_range(fo_entry * fo, internalfontnumber f)
+{
+ int i;
+ assert(fo != NULL);
+ for (i = font_bc(f); i <= font_ec(f); i++) /* search for first_char and last_char */
+ if (pdf_char_marked(f, i))
+ break;
+ fo->first_char = i;
+ for (i = font_ec(f); i >= font_bc(f); i--)
+ if (pdf_char_marked(f, i))
+ break;
+ fo->last_char = i;
+ if ((fo->first_char > fo->last_char)
+ || !pdf_char_marked(f, fo->first_char)) { /* no character used from this font */
+ fo->last_char = 0;
+ fo->first_char = fo->last_char + 1;
+ }
+}
+
+static void write_charwidth_array(fo_entry * fo, internalfontnumber f)
+{
+ int i, j, *ip, *fip, width;
+ struct avl_traverser t;
+ assert(fo->tx_tree != NULL);
+ assert(fo->cw_objnum == 0);
+ fo->cw_objnum = pdf_new_objnum();
+ pdf_begin_obj(fo->cw_objnum, 1);
+ avl_t_init(&t, fo->tx_tree);
+ fip = (int *) avl_t_first(&t, fo->tx_tree);
+ assert(fip != NULL);
+ pdf_puts("[");
+ for (ip = fip, j = *ip; ip != NULL; ip = (int *) avl_t_next(&t)) {
+ if (ip != fip)
+ pdf_puts(" ");
+ i = *ip;
+ while (j < i - 1) {
+ pdf_puts("0 ");
+ j++;
+ }
+ j = i;
+ width = divide_scaled(char_width(f, i), pdf_font_size(f), 4);
+ pdf_printf("%i", (int) width / 10); /* see adv_char_width() in pdftex.web */
+ if ((width = width % 10) != 0)
+ pdf_printf(".%i", width);
+ }
+ pdf_puts("]\n");
+ pdf_end_obj();
+}
+
+/**********************************************************************/
+/*
+ * Remark: Font objects from embedded PDF files are never registered
+ * into fo_tree; they are individually written out.
+ */
+
+fo_entry *lookup_fo_entry(char *s)
+{
+ fo_entry fo;
+ fm_entry fm;
+ assert(s != NULL);
+ fm.tfm_name = s;
+ fo.fm = &fm;
+ if (fo_tree == NULL) {
+ fo_tree = avl_create(comp_fo_entry, NULL, &avl_xallocator);
+ assert(fo_tree != NULL);
+ }
+ return (fo_entry *) avl_find(fo_tree, &fo);
+}
+
+void register_fo_entry(fo_entry * fo)
+{
+ void **aa;
+ if (fo_tree == NULL) {
+ fo_tree = avl_create(comp_fo_entry, NULL, &avl_xallocator);
+ assert(fo_tree != NULL);
+ }
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(fo->fm->tfm_name != NULL);
+ assert (lookup_fo_entry(fo->fm->tfm_name) == NULL) ;
+ aa = avl_probe(fo_tree, fo);
+ assert(aa != NULL);
+}
+
+/**********************************************************************/
+
+static void write_fontfile(fd_entry * fd)
+{
+ assert(is_included(fd->fm));
+ if (is_cidkeyed(fd->fm)) {
+ if (is_opentype(fd->fm))
+ writetype0(fd);
+ else if (is_truetype(fd->fm))
+ writetype2(fd);
+ else if (is_type1(fd->fm))
+ writetype1w(fd);
+ else
+ assert(0);
+ } else {
+ if (is_type1(fd->fm))
+#ifdef DO_TYPE1C
+ writet1c(fd);
+#else
+ writet1(fd);
+#endif
+ else if (is_truetype(fd->fm))
+ writettf(fd);
+ else if (is_opentype(fd->fm))
+ writeotf(fd);
+ else
+ assert(0);
+ }
+ if (!fd->ff_found)
+ return;
+ assert(fd->ff_objnum == 0);
+ fd->ff_objnum = pdf_new_objnum();
+ pdf_begin_dict(fd->ff_objnum, 0); /* font file stream */
+ if (is_cidkeyed(fd->fm)) {
+ /* No subtype is used for TrueType-based OpenType fonts */
+ if (is_opentype(fd->fm) || is_type1(fd->fm))
+ pdf_puts("/Subtype /CIDFontType0C\n");
+ /* else
+ pdf_puts("/Subtype /OpenType\n");*/
+ } else {
+ if (is_type1(fd->fm))
+ pdf_printf("/Length1 %i\n/Length2 %i\n/Length3 %i\n",
+ (int) t1_length1, (int) t1_length2, (int) t1_length3);
+ else if (is_truetype(fd->fm))
+ pdf_printf("/Length1 %i\n", (int) ttf_length);
+ else if (is_opentype(fd->fm))
+ pdf_puts("/Subtype /Type1C\n");
+ else
+ assert(0);
+ }
+ pdf_begin_stream();
+ fb_flush();
+ pdf_end_stream();
+}
+
+/**********************************************************************/
+
+static void write_fontdescriptor(fd_entry * fd)
+{
+ char *glyph;
+ struct avl_traverser t;
+ assert(fd != NULL && fd->fm != NULL);
+
+ if (is_fontfile(fd->fm))
+ write_fontfile(fd); /* this will set fd->ff_found if font file is found */
+ if (fd->fn_objnum != 0)
+ write_fontname_object(fd);
+ if (fd->fd_objnum == 0)
+ fd->fd_objnum = pdf_new_objnum();
+ pdf_begin_dict(fd->fd_objnum, 1);
+ pdf_puts("/Type /FontDescriptor\n");
+ write_fontname(fd, "FontName");
+ if (!fd->ff_found && fd->fm->fd_flags == 4)
+ pdf_puts("/Flags 34\n"); /* assumes a roman sans serif font */
+ else
+ pdf_printf("/Flags %i\n", (int) fd->fm->fd_flags);
+ write_fontmetrics(fd);
+ if (is_cidkeyed(fd->fm)) {
+ if (is_type1(fd->fm))
+ pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum);
+ else if (is_truetype(fd->fm))
+ pdf_printf("/FontFile2 %i 0 R\n", (int) fd->ff_objnum);
+ else if (is_opentype(fd->fm))
+ pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum);
+ else
+ assert(0);
+ } else {
+ if (fd->ff_found) {
+ if (is_subsetted(fd->fm) && is_type1(fd->fm)) {
+ /* /CharSet is optional; names may appear in any order */
+ assert(fd->gl_tree != NULL);
+ avl_t_init(&t, fd->gl_tree);
+ pdf_puts("/CharSet (");
+ for (glyph = (char *) avl_t_first(&t, fd->gl_tree); glyph != NULL;
+ glyph = (char *) avl_t_next(&t))
+ pdf_printf("/%s", glyph);
+ pdf_puts(")\n");
+ }
+ if (is_type1(fd->fm))
+ pdf_printf("/FontFile %i 0 R\n", (int) fd->ff_objnum);
+ else if (is_truetype(fd->fm))
+ pdf_printf("/FontFile2 %i 0 R\n", (int) fd->ff_objnum);
+ else if (is_opentype(fd->fm))
+ pdf_printf("/FontFile3 %i 0 R\n", (int) fd->ff_objnum);
+ else
+ assert(0);
+ }
+ }
+ /* TODO: Optional keys for CID fonts.
+
+ The most interesting ones are
+ /Style << /Panose <12-byte string>>>
+ and
+ /CIDSET <stream>
+ the latter can be used in subsets, to give the included CIDs
+ as a bitmap on the whole list.
+ */
+ pdf_end_dict();
+}
+
+void write_fontdescriptors()
+{
+ fd_entry *fd;
+ struct avl_traverser t;
+ if (fd_tree == NULL)
+ return;
+ avl_t_init(&t, fd_tree);
+ for (fd = (fd_entry *) avl_t_first(&t, fd_tree); fd != NULL;
+ fd = (fd_entry *) avl_t_next(&t))
+ write_fontdescriptor(fd);
+}
+
+/**********************************************************************/
+
+void write_fontdictionary(fo_entry * fo)
+{
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(fo->fo_objnum != 0); /* reserved as pdf_font_num(f) in pdftex.web */
+
+ /* write ToUnicode entry if needed */
+ if (fixed_gen_tounicode > 0 && fo->fd != NULL) {
+ if (fo->fe != NULL) {
+ fo->tounicode_objnum =
+ write_tounicode(fo->fe->glyph_names, fo->fe->name);
+ } else if (is_type1(fo->fm)) {
+ assert(fo->fd->builtin_glyph_names != NULL);
+ fo->tounicode_objnum =
+ write_tounicode(fo->fd->builtin_glyph_names, fo->fm->tfm_name);
+ }
+ }
+
+ pdf_begin_dict(fo->fo_objnum, 1);
+ pdf_puts("/Type /Font\n");
+ pdf_puts("/Subtype /");
+ if (is_type1(fo->fm))
+#ifdef DO_TYPE1C
+ pdf_printf("%s\n", "Type1C");
+#else
+ pdf_printf("%s\n", "Type1");
+#endif
+ else if (is_truetype(fo->fm))
+ pdf_printf("%s\n", "TrueType");
+ else if (is_opentype(fo->fm))
+ pdf_printf("%s\n", "Type1");
+ else
+ assert(0);
+ assert(fo->fd != NULL && fo->fd->fd_objnum != 0);
+ write_fontname(fo->fd, "BaseFont");
+ pdf_printf("/FontDescriptor %i 0 R\n", (int) fo->fd->fd_objnum);
+ assert(fo->cw_objnum != 0);
+ pdf_printf("/FirstChar %i\n/LastChar %i\n/Widths %i 0 R\n",
+ (int) fo->first_char, (int) fo->last_char,
+ (int) fo->cw_objnum);
+ if ((is_type1(fo->fm) || is_opentype(fo->fm)) && fo->fe != NULL && fo->fe->fe_objnum != 0)
+ pdf_printf("/Encoding %i 0 R\n", (int) fo->fe->fe_objnum);
+ if (fo->tounicode_objnum != 0)
+ pdf_printf("/ToUnicode %i 0 R\n", (int) fo->tounicode_objnum);
+ if (pdf_font_attr(fo->tex_font) != get_nullstr()) {
+ pdf_print(pdf_font_attr(fo->tex_font));
+ pdf_puts("\n");
+ }
+ pdf_end_dict();
+}
+
+void write_fontdictionaries()
+{
+ fo_entry *fo;
+ struct avl_traverser t;
+ if (fo_tree == NULL)
+ return;
+ avl_t_init(&t, fo_tree);
+ for (fo = (fo_entry *) avl_t_first(&t, fo_tree); fo != NULL;
+ fo = (fo_entry *) avl_t_next(&t))
+ write_fontdictionary(fo);
+}
+
+/**********************************************************************/
+/*
+ * Final flush of all font related stuff by call from
+ * @<Output fonts definition@>= in pdftex.web.
+ */
+
+void write_fontstuff()
+{
+ write_fontdescriptors();
+ write_fontencodings(); /* see writeenc.c */
+ write_fontdictionaries();
+}
+
+/**********************************************************************/
+
+void create_fontdictionary(fm_entry * fm, integer font_objnum,
+ internalfontnumber f)
+{
+ fo_entry *fo = new_fo_entry();
+ get_char_range(fo, f); /* set fo->first_char and fo->last_char from f */
+ assert(fo->last_char >= fo->first_char);
+ fo->fm = fm;
+ fo->fo_objnum = font_objnum;
+ fo->tex_font = f;
+ if (is_reencoded(fo->fm)) { /* at least the map entry tells so */
+ fo->fe = get_fe_entry(fo->fm->encname); /* returns NULL if .enc file couldn't be opened */
+ if (fo->fe != NULL && (is_type1(fo->fm) || is_opentype(fo->fm))) {
+ if (fo->fe->fe_objnum == 0)
+ fo->fe->fe_objnum = pdf_new_objnum(); /* then it will be written out */
+ /* mark encoding pairs used by TeX to optimize encoding vector */
+ fo->fe->tx_tree = mark_chars(fo, fo->fe->tx_tree, f);
+ }
+ }
+ fo->tx_tree = mark_chars(fo, fo->tx_tree, f); /* for write_charwidth_array() */
+ write_charwidth_array(fo, f);
+ if (!is_builtin(fo->fm)) {
+ if (is_type1(fo->fm)) {
+ if ((fo->fd = lookup_fontdescriptor(fo)) == NULL) {
+ create_fontdescriptor(fo, f);
+ register_fd_entry(fo->fd);
+ }
+ } else
+ create_fontdescriptor(fo, f);
+ if (fo->fe != NULL) {
+ mark_reenc_glyphs(fo, f);
+ if (!is_type1(fo->fm)) {
+ /* mark reencoded characters as chars on TeX level */
+ assert(fo->fd->tx_tree == NULL);
+ fo->fd->tx_tree = mark_chars(fo, fo->fd->tx_tree, f);
+ if (is_truetype(fo->fm))
+ fo->fd->write_ttf_glyph_names = true;
+ }
+ } else
+ /* mark non-reencoded characters as chars on TeX level */
+ fo->fd->tx_tree = mark_chars(fo, fo->fd->tx_tree, f);
+ if (!is_type1(fo->fm))
+ write_fontdescriptor(fo->fd);
+ } else {
+ /* builtin fonts still need the /Widths array and /FontDescriptor
+ * (to avoid error 'font FOO contains bad /BBox')
+ */
+ create_fontdescriptor(fo, f);
+ write_fontdescriptor(fo->fd);
+ if (!is_std_t1font(fo->fm))
+ pdftex_warn("font `%s' is not a standard font; "
+ "I suppose it is available to your PDF viewer then",
+ fo->fm->ps_name);
+ }
+ if (is_type1(fo->fm))
+ register_fo_entry(fo);
+ else
+ write_fontdictionary(fo);
+}
+
+/**********************************************************************/
+
+
+void do_pdf_font(integer font_objnum, internalfontnumber f)
+{
+ fm_entry *fm;
+ /* This is not 100% true: CID is actually needed whenever (and
+ * only) there are more than 256 separate glyphs used. But for
+ * now, just assume the user knows what he is doing;
+ */
+ if (font_encodingbytes(f)==2) {
+ /* Create a virtual font map entry, as this is needed by the
+ * rest of the font inclusion mechanism.
+ */
+ fm = new_fm_entry();
+ fm->tfm_name = font_name(f); /* or whatever, not a real tfm */
+ fm->ff_name = font_filename(f); /* the actual file */
+ fm->encname = font_encodingname(f); /* for the CIDSystemInfo */
+ fm->ps_name = font_fullname(f); /* the true name */
+ fm->slant = font_slant(f); /* slant factor */
+ fm->extend = font_extend(f); /* extension factor */
+ fm->fd_flags = 4; /* can perhaps be done better */
+ fm->in_use = true;
+
+ switch (font_format(f)) {
+ case opentype_format: set_opentype(fm); break;
+ case truetype_format: set_truetype(fm); break;
+ case type1_format: set_type1(fm); break;
+ default:
+ pdftex_fail("writefont.c: The file format (%s) for font `%s' is incompatible with wide characters\n",
+ font_format_name(f),font_name(f));
+ }
+ /* This makes "unknown" default to subsetted inclusion */
+ if (font_embedding(f)!=no_embedding) {
+ set_included(fm);
+ if (font_embedding(f)!=full_embedding) {
+ set_subsetted(fm);
+ }
+ }
+ set_cidkeyed(fm);
+ create_cid_fontdictionary(fm, font_objnum, f);
+
+ } else {
+ fm = hasfmentry(f) ? (fm_entry *) font_map(f) : NULL;
+ if (fm == NULL || (fm->ps_name == NULL && fm->ff_name == NULL))
+ writet3(font_objnum, f);
+ else
+ create_fontdictionary(fm, font_objnum, f);
+ }
+}
+
+/**********************************************************************/
+
+
+/*
+ The glyph width is included in |glw_entry|, because that width
+ depends on the value it has in the font where it is actually
+ typeset from, not the font that is the 'owner' of the fd entry.
+
+ TODO: It is possible that the user messes with the metric width,
+ but handling that properly would require access to the 'hmtx' table
+ at this point in the program.
+*/
+
+int comp_glw_entry(const void *pa, const void *pb, void *p)
+{
+ unsigned short i, j;
+ i = (*(glw_entry *)pa).id;
+ j = (*(glw_entry *)pb).id;
+ cmp_return(i,j);
+ return 0;
+}
+
+void create_cid_fontdescriptor(fo_entry * fo, internalfontnumber f)
+{
+ assert(fo != NULL);
+ assert(fo->fm != NULL);
+ assert(fo->fd == NULL);
+ fo->fd = new_fd_entry();
+ preset_fontname(fo);
+ preset_fontmetrics(fo->fd, f);
+ fo->fd->fe = fo->fe; /* encoding needed by TrueType writing */
+ fo->fd->fm = fo->fm; /* map entry needed by TrueType writing */
+ fo->fd->gl_tree = avl_create(comp_glw_entry, NULL, &avl_xallocator);
+ assert(fo->fd->gl_tree != NULL);
+}
+
+/*
+ The values |font_bc()| and |font_ec()| are potentially large
+ character ids, but the strings that are written out use CID
+ indexes, and those are limited to 16-bit values.
+*/
+
+static void mark_cid_subset_glyphs(fo_entry *fo, internal_font_number f)
+{
+ int i, k;
+ glw_entry *j;
+ void *aa;
+ for (k = 1; k <= max_font_id(); k++) {
+ if ( k == f || -f == pdf_font_num(k)) {
+ for (i = font_bc(k); i <= font_ec(k); i++) {
+ if (char_exists(k,i) && char_used(k,i)) {
+ j = xtalloc(1,glw_entry);
+ j->id = char_index(k,i);
+ j->wd = divide_scaled_n(char_width(k, i), pdf_font_size(k), 10000.0);
+ if ((glw_entry *)avl_find(fo->fd->gl_tree,j) == NULL) {
+ aa = avl_probe(fo->fd->gl_tree, j);
+ assert(aa != NULL);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*
+ It is possible to compress the widths array even better, by using the
+ alternate 'range' syntax and possibly even using /DW to set
+ a default value.
+
+ There is a some optimization here already: glyphs that are
+ not used do not appear in the widths array at all.
+
+ We have to make sure that we do not output an (incorrect!)
+ width for a character that exists in the font, but is not used
+ in typesetting. An enormous negative width is used as sentinel value
+*/
+
+
+static void write_cid_charwidth_array(fo_entry * fo)
+{
+ int i, j;
+ glw_entry *glyph;
+ struct avl_traverser t;
+
+ assert(fo->cw_objnum == 0);
+ fo->cw_objnum = pdf_new_objnum();
+ pdf_begin_obj(fo->cw_objnum, 1);
+ avl_t_init(&t, fo->fd->gl_tree);
+ glyph = (glw_entry *) avl_t_first(&t, fo->fd->gl_tree);
+ assert(glyph != NULL);
+ i = glyph->id;
+ pdf_printf("[ %i [", i);
+ for (; glyph != NULL; glyph = (glw_entry *) avl_t_next(&t)) {
+ j = glyph->wd;
+ if (glyph->id>(i+1)) {
+ pdf_printf("] %i [", glyph->id);
+ j = glyph->wd;
+ }
+ if (glyph->id==(i+1))
+ pdf_puts(" ");
+ pdf_printf("%i", (j/10));
+ if ((j % 10) != 0)
+ pdf_printf(".%i", (j % 10));
+ i = glyph->id;
+ }
+ pdf_puts("]]\n");
+ pdf_end_obj();
+}
+
+
+void create_cid_fontdictionary(fm_entry * fm, integer font_objnum,
+ internalfontnumber f)
+{
+ fo_entry *fo = new_fo_entry();
+ get_char_range(fo, f); /* set fo->first_char and fo->last_char from f */
+ assert(fo->last_char >= fo->first_char);
+ fo->fm = fm;
+ fo->fo_objnum = font_objnum;
+ fo->tex_font = f;
+ create_cid_fontdescriptor (fo, f);
+ mark_cid_subset_glyphs (fo,f);
+ if (is_subsetted(fo->fm)) {
+ /*
+ this is a bit sneaky. |make_subset_tag()| actually expects the glyph tree
+ to contain strings instead of |glw_entry| items. However, all calculations
+ are done using explicit typecasts, so it works out ok.
+ */
+ make_subset_tag(fo->fd);
+ }
+ write_cid_charwidth_array(fo);
+ write_fontdescriptor(fo->fd);
+
+ write_cid_fontdictionary(fo,f);
+}
+
+void write_cid_fontdictionary(fo_entry * fo, internalfontnumber f)
+{
+ int i;
+
+ fo->tounicode_objnum = write_cid_tounicode(fo,f);
+
+ pdf_begin_dict(fo->fo_objnum, 1);
+ pdf_puts("/Type /Font\n");
+ pdf_puts("/Subtype /Type0\n");
+ pdf_puts("/Encoding /Identity-H\n");
+ write_fontname(fo->fd, "BaseFont");
+ i = pdf_new_objnum();
+ pdf_printf("/DescendantFonts [%i 0 R]\n", i);
+ /* todo: the ToUnicode CMap */
+ if (fo->tounicode_objnum != 0)
+ pdf_printf("/ToUnicode %i 0 R\n", (int) fo->tounicode_objnum);
+
+ pdf_end_dict();
+
+ pdf_begin_dict(i, 1);
+ pdf_puts("/Type /Font\n");
+ if (is_opentype(fo->fm) || is_type1(fo->fm)) {
+ pdf_puts("/Subtype /CIDFontType0\n");
+ } else {
+ pdf_puts("/Subtype /CIDFontType2\n");
+ pdf_printf("/CIDToGIDMap /Identity\n");
+ }
+ write_fontname(fo->fd, "BaseFont");
+ pdf_printf("/FontDescriptor %i 0 R\n", (int) fo->fd->fd_objnum);
+ pdf_printf("/W %i 0 R\n",(int) fo->cw_objnum);
+ pdf_printf("/CIDSystemInfo <<\n");
+ pdf_printf("/Registry (%s)\n", (font_cidregistry(f)? font_cidregistry(f): "Adobe"));
+ pdf_printf("/Ordering (%s)\n",(font_cidordering(f)? font_cidordering(f) : "Identity")) ;
+ pdf_printf("/Supplement %u\n",(unsigned int)font_cidsupplement(f));
+ pdf_printf(">>\n");
+
+ /* I doubt there is anything useful that could be written here */
+ /*
+ if (pdf_font_attr(fo->tex_font) != get_nullstr()) {
+ pdf_print(pdf_font_attr(fo->tex_font));
+ pdf_puts("\n");
+ }
+ */
+ pdf_end_dict();
+
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/writet1.c b/Build/source/texk/web2c/luatexdir/font/writet1.c
new file mode 100644
index 00000000000..376135dc8be
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writet1.c
@@ -0,0 +1,1768 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id $
+
+*/
+
+# include "ptexlib.h"
+# include <kpathsea/c-vararg.h>
+# include <kpathsea/c-proto.h>
+# include <string.h>
+# include "luatex-api.h"
+
+# define t1_log(s) if(tracefilenames) tex_printf(s)
+# define get_length1() t1_length1 = t1_offset() - t1_save_offset
+# define get_length2() t1_length2 = t1_offset() - t1_save_offset
+# define get_length3() t1_length3 = fixedcontent? t1_offset() - t1_save_offset : 0
+# define save_offset() t1_save_offset = t1_offset()
+
+# define t1_putchar fb_putchar
+# define t1_offset fb_offset
+# define out_eexec_char t1_putchar
+
+# define end_last_eexec_line() \
+ t1_eexec_encrypt = false
+# define t1_char(c) c
+# define embed_all_glyphs(tex_font) fm_cur->all_glyphs
+# define extra_charset() fm_cur->charset
+# define update_subset_tag() \
+ strncpy(fb_array + t1_fontname_offset, fm_cur->subset_tag, 6)
+# define fixedcontent false
+
+integer t1_length1, t1_length2, t1_length3;
+static integer t1_save_offset;
+static integer t1_fontname_offset;
+extern char *fb_array;
+
+static unsigned char *t1_buffer = NULL;
+static integer t1_size = 0;
+static integer t1_curbyte = 0;
+
+#define t1_read_file() \
+ readbinfile(t1_file,&t1_buffer,&t1_size)
+#define t1_close() xfclose(t1_file,cur_file_name)
+#define t1_getchar() t1_buffer[t1_curbyte++]
+#define t1_ungetchar(c) t1_curbyte--
+#define t1_eof() (t1_curbyte>t1_size)
+
+#define t1_prefix(s) str_prefix(t1_line_array, s)
+#define t1_buf_prefix(s) str_prefix(t1_buf_array, s)
+#define t1_suffix(s) str_suffix(t1_line_array, t1_line_ptr, s)
+#define t1_buf_suffix(s) str_suffix(t1_buf_array, t1_buf_ptr, s)
+#define t1_charstrings() strstr(t1_line_array, charstringname)
+#define t1_subrs() t1_prefix("/Subrs")
+#define t1_end_eexec() t1_suffix("mark currentfile closefile")
+#define t1_cleartomark() t1_prefix("cleartomark")
+
+static unsigned char *enc_buffer = NULL;
+static integer enc_size = 0;
+static integer enc_curbyte = 0;
+
+#define enc_open() \
+ open_input(&enc_file, kpse_enc_format, FOPEN_RBIN_MODE)
+#define enc_read_file() \
+ readbinfile(enc_file,&enc_buffer,&enc_size)
+#define enc_close() xfclose(enc_file,cur_file_name)
+#define enc_getchar() enc_buffer[enc_curbyte++]
+#define enc_eof() (enc_curbyte>enc_size)
+
+#define valid_code(c) (c >= 0 && c < 256)
+#define fixedcontent false
+
+static const char *standard_glyph_names[256] = {
+ /* 0x00 */
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0x10 */
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0x20 */
+ "space", "exclam", "quotedbl", "numbersign", "dollar", "percent",
+ "ampersand", "quoteright", "parenleft", "parenright", "asterisk",
+ "plus", "comma", "hyphen", "period", "slash",
+ /* 0x30 */
+ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight",
+ "nine", "colon", "semicolon", "less", "equal", "greater", "question",
+ /* 0x40 */
+ "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
+ "O",
+ /* 0x50 */
+ "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bracketleft",
+ "backslash", "bracketright", "asciicircum", "underscore",
+ /* 0x60 */
+ "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
+ "m", "n", "o",
+ /* 0x70 */
+ "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "braceleft", "bar",
+ "braceright", "asciitilde", notdef,
+ /* 0x80 */
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0x90 */
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0xa0 */
+ notdef, "exclamdown", "cent", "sterling", "fraction", "yen", "florin",
+ "section", "currency", "quotesingle", "quotedblleft", "guillemotleft",
+ "guilsinglleft", "guilsinglright", "fi", "fl",
+ /* 0xb0 */
+ notdef, "endash", "dagger", "daggerdbl", "periodcentered", notdef,
+ "paragraph", "bullet", "quotesinglbase", "quotedblbase",
+ "quotedblright", "guillemotright", "ellipsis", "perthousand", notdef,
+ "questiondown",
+ /* 0xc0 */
+ notdef, "grave", "acute", "circumflex", "tilde", "macron", "breve",
+ "dotaccent", "dieresis", notdef,
+ "ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron",
+ /* 0xd0 */
+ "emdash", notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ notdef, notdef, notdef, notdef, notdef, notdef, notdef,
+ /* 0xe0 */
+ notdef, "AE", notdef, "ordfeminine", notdef, notdef, notdef, notdef,
+ "Lslash", "Oslash", "OE", "ordmasculine", notdef, notdef, notdef,
+ notdef,
+ /* 0xf0 */
+ notdef, "ae", notdef, notdef, notdef, "dotlessi", notdef, notdef, "lslash",
+ "oslash", "oe", "germandbls", notdef, notdef, notdef, notdef
+};
+
+
+integer t1_length1, t1_length2, t1_length3;
+static integer t1_save_offset;
+static integer t1_fontname_offset;
+extern char *fb_array;
+static fd_entry *fd_cur;
+
+static char charstringname[] = "/CharStrings";
+
+enum { ENC_STANDARD, ENC_BUILTIN } t1_encoding;
+
+#define T1_BUF_SIZE 0x10
+#define ENC_BUF_SIZE 0x1000
+
+#define CS_HSTEM 1
+#define CS_VSTEM 3
+#define CS_VMOVETO 4
+#define CS_RLINETO 5
+#define CS_HLINETO 6
+#define CS_VLINETO 7
+#define CS_RRCURVETO 8
+#define CS_CLOSEPATH 9
+#define CS_CALLSUBR 10
+#define CS_RETURN 11
+#define CS_ESCAPE 12
+#define CS_HSBW 13
+#define CS_ENDCHAR 14
+#define CS_RMOVETO 21
+#define CS_HMOVETO 22
+#define CS_VHCURVETO 30
+#define CS_HVCURVETO 31
+#define CS_1BYTE_MAX (CS_HVCURVETO + 1)
+
+#define CS_DOTSECTION CS_1BYTE_MAX + 0
+#define CS_VSTEM3 CS_1BYTE_MAX + 1
+#define CS_HSTEM3 CS_1BYTE_MAX + 2
+#define CS_SEAC CS_1BYTE_MAX + 6
+#define CS_SBW CS_1BYTE_MAX + 7
+#define CS_DIV CS_1BYTE_MAX + 12
+#define CS_CALLOTHERSUBR CS_1BYTE_MAX + 16
+#define CS_POP CS_1BYTE_MAX + 17
+#define CS_SETCURRENTPOINT CS_1BYTE_MAX + 33
+#define CS_2BYTE_MAX (CS_SETCURRENTPOINT + 1)
+#define CS_MAX CS_2BYTE_MAX
+
+typedef unsigned char byte;
+
+typedef struct {
+ byte nargs; /* number of arguments */
+ boolean bottom; /* take arguments from bottom of stack? */
+ boolean clear; /* clear stack? */
+ boolean valid;
+} cc_entry; /* CharString Command */
+
+typedef struct {
+ char *name; /* glyph name (or notdef for Subrs entry) */
+ byte *data;
+ unsigned short len; /* length of the whole string */
+ unsigned short cslen; /* length of the encoded part of the string */
+ boolean used;
+ boolean valid;
+} cs_entry;
+
+static unsigned short t1_dr, t1_er;
+static const unsigned short t1_c1 = 52845, t1_c2 = 22719;
+static unsigned short t1_cslen;
+static short t1_lenIV;
+static char enc_line[ENC_BUF_SIZE];
+
+/* define t1_line_ptr, t1_line_array & t1_line_limit */
+typedef char t1_line_entry;
+define_array (t1_line);
+
+/* define t1_buf_ptr, t1_buf_array & t1_buf_limit */
+typedef char t1_buf_entry;
+define_array (t1_buf);
+
+static int cs_start;
+
+static cs_entry *cs_tab, *cs_ptr, *cs_notdef;
+static char *cs_dict_start, *cs_dict_end;
+static int cs_counter, cs_size, cs_size_pos;
+
+static cs_entry *subr_tab;
+static char *subr_array_start, *subr_array_end;
+static int subr_max, subr_size, subr_size_pos;
+
+/* This list contains the begin/end tokens commonly used in the */
+/* /Subrs array of a Type 1 font. */
+
+static const char *cs_token_pairs_list[][2] = {
+ {" RD", "NP"},
+ {" -|", "|"},
+ {" RD", "noaccess put"},
+ {" -|", "noaccess put"},
+ {NULL, NULL}
+};
+static const char **cs_token_pair;
+
+static boolean t1_pfa, t1_cs, t1_scan, t1_eexec_encrypt, t1_synthetic;
+static int t1_in_eexec; /* 0 before eexec-encrypted, 1 during, 2 after */
+static long t1_block_length;
+static int last_hexbyte;
+static FILE *t1_file;
+static FILE *enc_file;
+
+static void enc_getline (void)
+{
+ char *p;
+ int c;
+ restart:
+ if (enc_eof ())
+ pdftex_fail ("unexpected end of file");
+ p = enc_line;
+ do {
+ c = enc_getchar ();
+ append_char_to_buf (c, p, enc_line, ENC_BUF_SIZE);
+ }
+ while (c != 10 && !enc_eof());
+ append_eol (p, enc_line, ENC_BUF_SIZE);
+ if (p - enc_line < 2 || *enc_line == '%')
+ goto restart;
+}
+
+/* read encoding from .enc file, return glyph_names array, or pdffail() */
+
+char **load_enc_file(char *enc_name)
+{
+ int callback_id = 0;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ char buf[ENC_BUF_SIZE], *p, *r;
+ int i, names_count;
+ char **glyph_names;
+ char *tempname ;
+ set_cur_file_name (enc_name);
+ callback_id=callback_defined(find_enc_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ } else {
+ return NULL;
+ }
+ }
+ }
+ callback_id=callback_defined(read_enc_file_callback);
+ enc_curbyte=0;
+ enc_size=0;
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &enc_buffer,&enc_size)) {
+ if((!file_opened) || enc_size==0) {
+ pdftex_warn ("cannot open encoding file for reading");
+ cur_file_name = NULL;
+ return NULL;
+ }
+ }
+ } else {
+ if (!enc_open ()) {
+ pdftex_warn ("cannot open encoding file for reading");
+ cur_file_name = NULL;
+ return NULL;
+ }
+ enc_read_file();
+ enc_close();
+ }
+ glyph_names = xtalloc(256, char *);
+ for (i = 0; i < 256; i++)
+ glyph_names[i] = (char *) notdef;
+ t1_log ("{");
+
+ tempname = xmalloc(namelength+2);
+ strcpy(tempname,(char *)(nameoffile+1));
+ set_cur_file_name (tempname);
+ t1_log (cur_file_name);
+ enc_getline ();
+ if (*enc_line != '/' || (r = strchr (enc_line, '[')) == NULL) {
+ remove_eol (r, enc_line);
+ pdftex_fail
+ ("invalid encoding vector (a name or `[' missing): `%s'", enc_line);
+ }
+ names_count = 0;
+ r++; /* skip '[' */
+ skip (r, ' ');
+ for (;;) {
+ while (*r == '/') {
+ for (p = buf, r++;
+ *r != ' ' && *r != 10 && *r != ']' && *r != '/'; *p++ = *r++);
+ *p = 0;
+ skip (r, ' ');
+ if (names_count > 256)
+ pdftex_fail ("encoding vector contains more than 256 names");
+ if (strcmp (buf, notdef) != 0)
+ glyph_names[names_count] = xstrdup (buf);
+ names_count++;
+ }
+ if (*r != 10 && *r != '%') {
+ if (strncmp (r, "] def", strlen ("] def")) == 0)
+ goto done;
+ else {
+ remove_eol (r, enc_line);
+ pdftex_fail
+ ("invalid encoding vector: a name or `] def' expected: `%s'",
+ enc_line);
+ }
+ }
+ enc_getline ();
+ r = enc_line;
+ }
+ done:
+ t1_log ("}");
+ cur_file_name = NULL;
+ return glyph_names;
+}
+
+void free_glyph_names(char **glyph_names)
+{
+ int i;
+ assert(glyph_names != NULL);
+ for (i = 0; i < 256; i++)
+ if (glyph_names[i] != notdef)
+ xfree(glyph_names[i]);
+ xfree(glyph_names);
+}
+
+
+static void t1_check_pfa (void)
+{
+ const int c = t1_getchar ();
+ t1_pfa = (c != 128) ? true : false;
+ t1_ungetchar (c);
+}
+
+static int t1_getbyte (void)
+{
+ int c = t1_getchar ();
+ if (t1_pfa)
+ return c;
+ if (t1_block_length == 0) {
+ if (c != 128)
+ pdftex_fail ("invalid marker");
+ c = t1_getchar ();
+ if (c == 3) {
+ while (!t1_eof ())
+ (void)t1_getchar ();
+ return EOF;
+ }
+ t1_block_length = t1_getchar () & 0xff;
+ t1_block_length |= (t1_getchar () & 0xff) << 8;
+ t1_block_length |= (t1_getchar () & 0xff) << 16;
+ t1_block_length |= (t1_getchar () & 0xff) << 24;
+ c = t1_getchar ();
+ }
+ t1_block_length--;
+ return c;
+}
+
+static int hexval (int c)
+{
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ else if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if (c >= '0' && c <= '9')
+ return c - '0';
+ else
+ return -1;
+}
+
+static byte edecrypt (byte cipher)
+{
+ byte plain;
+ if (t1_pfa) {
+ while (cipher == 10 || cipher == 13)
+ cipher = t1_getbyte ();
+ last_hexbyte = cipher = (hexval (cipher) << 4) + hexval (t1_getbyte ());
+ }
+ plain = (cipher ^ (t1_dr >> 8));
+ t1_dr = (cipher + t1_dr) * t1_c1 + t1_c2;
+ return plain;
+}
+
+static byte cdecrypt (byte cipher, unsigned short *cr)
+{
+ const byte plain = (cipher ^ (*cr >> 8));
+ *cr = (cipher + *cr) * t1_c1 + t1_c2;
+ return plain;
+}
+
+static byte eencrypt (byte plain)
+{
+ const byte cipher = (plain ^ (t1_er >> 8));
+ t1_er = (cipher + t1_er) * t1_c1 + t1_c2;
+ return cipher;
+}
+
+static byte cencrypt (byte plain, unsigned short *cr)
+{
+ const byte cipher = (plain ^ (*cr >> 8));
+ *cr = (cipher + *cr) * t1_c1 + t1_c2;
+ return cipher;
+}
+
+static char *eol (char *s)
+{
+ char *p = strend (s);
+ if (p - s > 1 && p[-1] != 10) {
+ *p++ = 10;
+ *p = 0;
+ }
+ return p;
+}
+
+static float t1_scan_num (char *p, char **r)
+{
+ float f;
+ skip (p, ' ');
+ if (sscanf (p, "%g", &f) != 1) {
+ remove_eol (p, t1_line_array);
+ pdftex_fail ("a number expected: `%s'", t1_line_array);
+ }
+ if (r != NULL) {
+ for (; isdigit (*p) || *p == '.' ||
+ *p == 'e' || *p == 'E' || *p == '+' || *p == '-'; p++);
+ *r = p;
+ }
+ return f;
+}
+
+static boolean str_suffix (const char *begin_buf, const char *end_buf,
+ const char *s)
+{
+ const char *s1 = end_buf - 1, *s2 = strend (s) - 1;
+ if (*s1 == 10)
+ s1--;
+ while (s1 >= begin_buf && s2 >= s) {
+ if (*s1-- != *s2--)
+ return false;
+ }
+ return s2 < s;
+}
+
+static void t1_getline (void)
+{
+ int c, l, eexec_scan;
+ char *p;
+ static const char eexec_str[] = "currentfile eexec";
+ static int eexec_len = 17; /* strlen(eexec_str) */
+ restart:
+ if (t1_eof ())
+ pdftex_fail ("unexpected end of file");
+ t1_line_ptr = t1_line_array;
+ alloc_array (t1_line, 1, T1_BUF_SIZE);
+ t1_cslen = 0;
+ eexec_scan = 0;
+ c = t1_getbyte ();
+ if (c == EOF)
+ goto exit;
+ while (!t1_eof ()) {
+ if (t1_in_eexec == 1)
+ c = edecrypt (c);
+ alloc_array (t1_line, 1, T1_BUF_SIZE);
+ append_char_to_buf (c, t1_line_ptr, t1_line_array, t1_line_limit);
+ if (t1_in_eexec == 0 && eexec_scan >= 0 && eexec_scan < eexec_len) {
+ if (t1_line_array[eexec_scan] == eexec_str[eexec_scan])
+ eexec_scan++;
+ else
+ eexec_scan = -1;
+ }
+ if (c == 10 || (t1_pfa && eexec_scan == eexec_len && c == 32))
+ break;
+ if (t1_cs && t1_cslen == 0 && (t1_line_ptr - t1_line_array > 4) &&
+ (t1_suffix (" RD ") || t1_suffix (" -| "))) {
+ p = t1_line_ptr - 5;
+ while (*p != ' ')
+ p--;
+ t1_cslen = l = t1_scan_num (p + 1, 0);
+ cs_start = t1_line_ptr - t1_line_array; /* cs_start is an index now */
+ alloc_array (t1_line, l, T1_BUF_SIZE);
+ while (l-- > 0)
+ *t1_line_ptr++ = edecrypt (t1_getbyte ());
+ }
+ c = t1_getbyte ();
+ }
+ alloc_array (t1_line, 2, T1_BUF_SIZE); /* append_eol can append 2 chars */
+ append_eol (t1_line_ptr, t1_line_array, t1_line_limit);
+ if (t1_line_ptr - t1_line_array < 2)
+ goto restart;
+ if (eexec_scan == eexec_len)
+ t1_in_eexec = 1;
+ exit:
+ /* ensure that t1_buf_array has as much room as t1_line_array */
+ t1_buf_ptr = t1_buf_array;
+ alloc_array (t1_buf, t1_line_limit, t1_line_limit);
+}
+
+static void t1_putline (void)
+{
+ char *p = t1_line_array;
+ if (t1_line_ptr - t1_line_array <= 1)
+ return;
+ if (t1_eexec_encrypt) {
+ while (p < t1_line_ptr)
+ t1_putchar (eencrypt (*p++));
+ } else
+ while (p < t1_line_ptr)
+ t1_putchar (*p++);
+}
+
+static void t1_puts (const char *s)
+{
+ if (s != t1_line_array)
+ strcpy (t1_line_array, s);
+ t1_line_ptr = strend (t1_line_array);
+ t1_putline ();
+}
+
+__attribute__ ((format (printf, 1, 2)))
+static void t1_printf (const char *fmt, ...)
+{
+ va_list args;
+ va_start (args, fmt);
+ vsprintf (t1_line_array, fmt, args);
+ t1_puts (t1_line_array);
+ va_end (args);
+}
+
+static void t1_init_params (const char *open_name_prefix)
+{
+ t1_log (open_name_prefix);
+ t1_log (cur_file_name);
+ t1_lenIV = 4;
+ t1_dr = 55665;
+ t1_er = 55665;
+ t1_in_eexec = 0;
+ t1_cs = false;
+ t1_scan = true;
+ t1_synthetic = false;
+ t1_eexec_encrypt = false;
+ t1_block_length = 0;
+ t1_check_pfa ();
+}
+
+static void t1_close_font_file (const char *close_name_suffix)
+{
+ t1_log (close_name_suffix);
+ cur_file_name = NULL;
+}
+
+static void t1_check_block_len (boolean decrypt)
+{
+ int l, c;
+ if (t1_block_length == 0)
+ return;
+ c = t1_getbyte ();
+ if (decrypt)
+ c = edecrypt (c);
+ l = t1_block_length;
+ if (!(l == 0 && (c == 10 || c == 13))) {
+ pdftex_warn ("%i bytes more than expected were ignored", l + 1);
+ while (l-- > 0)
+ t1_getbyte ();
+ }
+}
+
+static void t1_start_eexec (void)
+{
+ int i;
+ assert(is_included(fd_cur->fm));
+ get_length1 ();
+ save_offset ();
+
+ if (!t1_pfa)
+ t1_check_block_len (false);
+ for (t1_line_ptr = t1_line_array, i = 0; i < 4; i++) {
+ edecrypt (t1_getbyte ());
+ *t1_line_ptr++ = 0;
+ }
+ t1_eexec_encrypt = true;
+ t1_putline (); /* to put the first four bytes */
+}
+
+static void t1_stop_eexec (void)
+{
+ int c;
+ assert(is_included(fd_cur->fm));
+ get_length2 ();
+ save_offset ();
+ t1_eexec_encrypt = false;
+ if (!t1_pfa)
+ t1_check_block_len (true);
+ else {
+ c = edecrypt (t1_getbyte ());
+ if (!(c == 10 || c == 13)) {
+ if (last_hexbyte == 0)
+ t1_puts ("00");
+ else
+ pdftex_warn ("unexpected data after eexec");
+ }
+ }
+ t1_cs = false;
+ t1_in_eexec = 2;
+}
+
+/* macros for various transforms; currently only slant and extend are used */
+
+# define do_xshift(x,a) {x[4]+=a;}
+# define do_yshift(x,a) {x[5]+=a;}
+# define do_xscale(x,a) {x[0]*=a; x[2]*=a; x[4]*=a;}
+# define do_yscale(x,a) {x[1]*=a; x[3]*=a; x[5]*=a;}
+# define do_extend(x,a) {do_xscale(x,a);}
+# define do_scale(x,a) {do_xscale(x,a); do_yscale(x,a);}
+# define do_slant(x,a) {x[0]+=x[1]*(a); x[2]+=x[3]*(a); x[4]+=x[5]*(a);}
+# define do_shear(x,a) {x[1]+=x[0]*(a); x[3]+=x[2]*(a); x[5]+=x[4]*(a);}
+# define do_rotate(x,a) \
+ {float t, u=cos(a), v=sin(a); \
+ t =x[0]*u+x[1]*-v; \
+ x[1] =x[0]*v+x[1]* u; x[0]=t; \
+ t =x[2]*u+x[3]*-v; \
+ x[3] =x[2]*v+x[3]* u; x[2]=t; \
+ t =x[4]*u+x[5]*-v; \
+ x[5] =x[4]*v+x[5]* u; x[4]=t;}
+
+static void t1_modify_fm (void)
+{
+ /*
+ * font matrix is given as six numbers a0..a5, which stands for the matrix
+ *
+ * a0 a1 0
+ * M = a2 a3 0
+ * a4 a5 1
+ *
+ * ExtendFont is given as
+ *
+ * e 0 0
+ * E = 0 1 0
+ * 0 0 1
+ *
+ * SlantFont is given as
+ *
+ * 1 0 0
+ * S = s 1 0
+ * 0 0 1
+ *
+ * The slant transform must be done _before_ the extend transform
+ * for compatibility!
+ */
+ float a[6];
+ int i, c;
+ char *p, *q, *r;
+ if ((p = strchr (t1_line_array, '[')) == 0)
+ if ((p = strchr (t1_line_array, '{')) == 0) {
+ remove_eol (p, t1_line_array);
+ pdftex_fail ("FontMatrix: an array expected: `%s'", t1_line_array);
+ }
+ c = *p++; /* save the character '[' resp. '{' */
+ strncpy (t1_buf_array, t1_line_array, (size_t) (p - t1_line_array));
+ r = t1_buf_array + (p - t1_line_array);
+ for (i = 0; i < 6; i++) {
+ a[i] = t1_scan_num (p, &q);
+ p = q;
+ }
+ if (fm_slant(fd_cur->fm) != 0)
+ do_slant(a, fm_slant(fd_cur->fm) * 1E-3);
+ if (fm_extend(fd_cur->fm) != 0)
+ do_extend(a, fm_extend(fd_cur->fm) * 1E-3);
+ for (i = 0; i < 6; i++) {
+ sprintf (r, "%g ", a[i]);
+ r = strend (r);
+ }
+ if (c == '[') {
+ while (*p != ']' && *p != 0)
+ p++;
+ } else {
+ while (*p != '}' && *p != 0)
+ p++;
+ }
+ if (*p == 0) {
+ remove_eol (p, t1_line_array);
+ pdftex_fail
+ ("FontMatrix: cannot find the corresponding character to '%c': `%s'",
+ c, t1_line_array);
+ }
+ strcpy (r, p);
+ strcpy (t1_line_array, t1_buf_array);
+ t1_line_ptr = eol (t1_line_array);
+}
+
+static void t1_modify_italic (void)
+{
+ float a;
+ char *p, *r;
+ if (fm_slant(fd_cur->fm) == 0)
+ return;
+ p = strchr (t1_line_array, ' ');
+ strncpy (t1_buf_array, t1_line_array, (size_t) (p - t1_line_array + 1));
+ a = t1_scan_num (p + 1, &r);
+ a -= atan (fm_slant(fd_cur->fm) * 1E-3) * (180 / M_PI);
+ sprintf (t1_buf_array + (p - t1_line_array + 1), "%g", a);
+ strcpy (strend (t1_buf_array), r);
+ strcpy (t1_line_array, t1_buf_array);
+ t1_line_ptr = eol (t1_line_array);
+ fd_cur->font_dim[ITALIC_ANGLE_CODE].val = round(a);
+ fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true;
+}
+
+static void t1_scan_keys (void)
+{
+ int i, k;
+ char *p, *q, *r;
+ key_entry *key;
+ if (fm_extend(fd_cur->fm) != 0 || fm_slant(fd_cur->fm) != 0) {
+ if (t1_prefix ("/FontMatrix")) {
+ t1_modify_fm ();
+ return;
+ }
+ if (t1_prefix ("/ItalicAngle")) {
+ t1_modify_italic ();
+ return;
+ }
+ }
+ if (t1_prefix ("/FontType")) {
+ p = t1_line_array + strlen ("FontType") + 1;
+ if ((i = t1_scan_num (p, 0)) != 1)
+ pdftex_fail ("Type%d fonts unsupported by pdfTeX", i);
+ return;
+ }
+ for (key = (key_entry *) font_key; key - font_key < FONT_KEYS_NUM; key++) {
+ if (key->t1name[0] != '\0' &&
+ str_prefix(t1_line_array + 1, key->t1name))
+ break;
+ }
+ if (key - font_key == FONT_KEYS_NUM)
+ return;
+ p = t1_line_array + strlen (key->t1name) + 1;
+ skip (p, ' ');
+ if ((k = key - font_key) == FONTNAME_CODE) {
+ if (*p != '/') {
+ remove_eol (p, t1_line_array);
+ pdftex_fail ("a name expected: `%s'", t1_line_array);
+ }
+ r = ++p; /* skip the slash */
+ for (q = t1_buf_array; *p != ' ' && *p != 10; *q++ = *p++);
+ *q = 0;
+ if (fm_slant(fd_cur->fm) != 0) {
+ sprintf(q, "-Slant_%i", (int) fm_slant(fd_cur->fm));
+ q = strend (q);
+ }
+ if (fm_extend(fd_cur->fm) != 0) {
+ sprintf(q, "-Extend_%i", (int) fm_extend(fd_cur->fm));
+ }
+ xfree(fd_cur->fontname);
+ fd_cur->fontname = xstrdup(t1_buf_array);
+ /* at this moment we cannot call make_subset_tag() yet, as the encoding
+ * is not read; thus we mark the offset of the subset tag and write it
+ * later */
+ if (is_subsetted(fd_cur->fm)) {
+ assert(is_included(fd_cur->fm));
+ t1_fontname_offset = t1_offset () + (r - t1_line_array);
+ strcpy (t1_buf_array, p);
+ sprintf(r, "ABCDEF+%s%s", fd_cur->fontname, t1_buf_array);
+ t1_line_ptr = eol (r);
+ }
+ return;
+ }
+ if ((k == STEMV_CODE || k == FONTBBOX1_CODE)
+ && (*p == '[' || *p == '{'))
+ p++;
+ if (k == FONTBBOX1_CODE) {
+ for (i = 0; i < 4; i++, k++) {
+ fd_cur->font_dim[k].val = t1_scan_num(p, &r);
+ fd_cur->font_dim[k].set = true;
+ p = r;
+ }
+ return;
+ }
+ fd_cur->font_dim[k].val = t1_scan_num(p, 0);
+ fd_cur->font_dim[k].set = true;
+}
+
+static void t1_scan_param (void)
+{
+ static const char *lenIV = "/lenIV";
+ if (!t1_scan || *t1_line_array != '/')
+ return;
+ if (t1_prefix (lenIV)) {
+ t1_lenIV = t1_scan_num (t1_line_array + strlen (lenIV), 0);
+ return;
+ }
+ t1_scan_keys ();
+}
+
+static void copy_glyph_names (char **glyph_names, int a, int b)
+{
+ if (glyph_names[b] != notdef) {
+ xfree (glyph_names[b]);
+ glyph_names[b] = (char *) notdef;
+ }
+ if (glyph_names[a] != notdef) {
+ glyph_names[b] = xstrdup (glyph_names[a]);
+ }
+}
+
+/* read encoding from Type1 font file, return glyph_names array, or pdffail() */
+
+char **t1_builtin_enc(void)
+{
+ int i, a, b, c, counter = 0;
+ char *r, *p, **glyph_names;
+ /* At this moment "/Encoding" is the prefix of t1_line_array */
+ glyph_names = xtalloc(256, char *);
+ for (i = 0; i < 256; i++)
+ glyph_names[i] = (char *) notdef;
+ if (t1_suffix("def")) { /* predefined encoding */
+ sscanf(t1_line_array + strlen("/Encoding"), "%256s", t1_buf_array);
+ if (strcmp(t1_buf_array, "StandardEncoding") == 0) {
+ t1_encoding = ENC_STANDARD;
+ for (i = 0; i < 256; i++) {
+ if (standard_glyph_names[i] != notdef)
+ glyph_names[i] = xstrdup(standard_glyph_names[i]);
+ }
+ return glyph_names;
+ } else
+ pdftex_fail
+ ("cannot subset font (unknown predefined encoding `%s')",
+ t1_buf_array);
+ }
+ /* At this moment "/Encoding" is the prefix of t1_line_array, and the encoding is
+ * not a predefined encoding.
+ *
+ * We have two possible forms of Encoding vector. The first case is
+ *
+ * /Encoding [/a /b /c...] readonly def
+ *
+ * and the second case can look like
+ *
+ * /Encoding 256 array 0 1 255 {1 index exch /.notdef put} for
+ * dup 0 /x put
+ * dup 1 /y put
+ * ...
+ * readonly def
+ */
+ t1_encoding = ENC_BUILTIN;
+ if (t1_prefix("/Encoding [") || t1_prefix("/Encoding[")) { /* the first case */
+ r = strchr(t1_line_array, '[') + 1;
+ skip(r, ' ');
+ for (;;) {
+ while (*r == '/') {
+ for (p = t1_buf_array, r++;
+ *r != 32 && *r != 10 && *r != ']' && *r != '/';
+ *p++ = *r++);
+ *p = 0;
+ skip(r, ' ');
+ if (counter > 255)
+ pdftex_fail("encoding vector contains more than 256 names");
+ if (strcmp(t1_buf_array, notdef) != 0)
+ glyph_names[counter] = xstrdup(t1_buf_array);
+ counter++;
+ }
+ if (*r != 10 && *r != '%') {
+ if (str_prefix(r, "] def")
+ || str_prefix(r, "] readonly def"))
+ break;
+ else {
+ remove_eol(r, t1_line_array);
+ pdftex_fail
+ ("a name or `] def' or `] readonly def' expected: `%s'",
+ t1_line_array);
+ }
+ }
+ t1_getline();
+ r = t1_line_array;
+ }
+ } else { /* the second case */
+ p = strchr(t1_line_array, 10);
+ for (;;) {
+ if (*p == 10) {
+ t1_getline();
+ p = t1_line_array;
+ }
+ /*
+ check for `dup <index> <glyph> put'
+ */
+ if (sscanf(p, "dup %i%256s put", &i, t1_buf_array) == 2 &&
+ *t1_buf_array == '/' && valid_code(i)) {
+ if (strcmp(t1_buf_array + 1, notdef) != 0)
+ glyph_names[i] = xstrdup(t1_buf_array + 1);
+ p = strstr(p, " put") + strlen(" put");
+ skip(p, ' ');
+ }
+ /*
+ check for `dup dup <to> exch <from> get put'
+ */
+ else if (sscanf(p, "dup dup %i exch %i get put", &b, &a) == 2
+ && valid_code(a) && valid_code(b)) {
+ copy_glyph_names(glyph_names, a, b);
+ p = strstr(p, " get put") + strlen(" get put");
+ skip(p, ' ');
+ }
+ /*
+ check for `dup dup <from> <size> getinterval <to> exch putinterval'
+ */
+ else if (sscanf
+ (p, "dup dup %i %i getinterval %i exch putinterval",
+ &a, &c, &b) == 3 && valid_code(a) && valid_code(b)
+ && valid_code(c)) {
+ for (i = 0; i < c; i++)
+ copy_glyph_names(glyph_names, a + i, b + i);
+ p = strstr(p, " putinterval") + strlen(" putinterval");
+ skip(p, ' ');
+ }
+ /*
+ check for `def' or `readonly def'
+ */
+ else if ((p == t1_line_array || (p > t1_line_array && p[-1] == ' '))
+ && strcmp(p, "def\n") == 0)
+ return glyph_names;
+ /*
+ skip an unrecognizable word
+ */
+ else {
+ while (*p != ' ' && *p != 10)
+ p++;
+ skip(p, ' ');
+ }
+ }
+ }
+ return glyph_names;
+}
+
+
+static void t1_check_end (void)
+{
+ if (t1_eof ())
+ return;
+ t1_getline ();
+ if (t1_prefix ("{restore}"))
+ t1_putline ();
+}
+
+static boolean t1_open_fontfile (const char *open_name_prefix)
+{
+ int callback_id = 0;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ ff_entry *ff;
+ ff = check_ff_exist(fd_cur->fm->ff_name, is_truetype(fd_cur->fm));
+ t1_curbyte = 0;
+ t1_size = 0;
+ if (ff->ff_path != NULL) {
+ callback_id=callback_defined(find_type1_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",ff->ff_path,&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ strcpy(ff->ff_path,ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_type1_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",ff->ff_path,
+ &file_opened, &t1_buffer,&t1_size)
+ && file_opened && t1_size>0) {
+ cur_file_name = ff->ff_path;
+ } else {
+ set_cur_file_name (fd_cur->fm->ff_name);
+ pdftex_warn ("cannot open Type 1 font file for reading");
+ return false;
+ }
+ } else {
+ t1_file = xfopen (cur_file_name = ff->ff_path, FOPEN_RBIN_MODE);
+ t1_read_file();
+ t1_close();
+ }
+ }
+ else {
+ set_cur_file_name (fd_cur->fm->ff_name);
+ pdftex_warn ("cannot open Type 1 font file for reading");
+ return false;
+ }
+ t1_init_params (open_name_prefix);
+ return true;
+}
+
+static void t1_include (void)
+{
+ do {
+ t1_getline ();
+ t1_scan_param ();
+ t1_putline ();
+ }
+ while (t1_in_eexec == 0);
+ t1_start_eexec ();
+ do {
+ t1_getline ();
+ t1_scan_param ();
+ t1_putline ();
+ }
+ while (!(t1_charstrings () || t1_subrs ()));
+ t1_cs = true;
+ do {
+ t1_getline ();
+ t1_putline ();
+ }
+ while (!t1_end_eexec ());
+ t1_stop_eexec ();
+ if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */
+ do {
+ t1_getline ();
+ t1_putline ();
+ }
+ while (!t1_cleartomark ());
+ t1_check_end (); /* write "{restore}if" if found */
+ }
+ get_length3 ();
+}
+
+#define check_subr(subr) \
+ if (subr >= subr_size || subr < 0) \
+ pdftex_fail("Subrs array: entry index out of range (%i)", subr);
+
+static const char **check_cs_token_pair ()
+{
+ const char **p = (const char **) cs_token_pairs_list;
+ for (; p[0] != NULL; ++p)
+ if (t1_buf_prefix (p[0]) && t1_buf_suffix (p[1]))
+ return p;
+ return NULL;
+}
+
+static void cs_store (boolean is_subr)
+{
+ char *p;
+ cs_entry *ptr;
+ int subr;
+ for (p = t1_line_array, t1_buf_ptr = t1_buf_array; *p != ' ';
+ *t1_buf_ptr++ = *p++);
+ *t1_buf_ptr = 0;
+ if (is_subr) {
+ subr = t1_scan_num (p + 1, 0);
+ check_subr (subr);
+ ptr = subr_tab + subr;
+ } else {
+ ptr = cs_ptr++;
+ if (cs_ptr - cs_tab > cs_size)
+ pdftex_fail
+ ("CharStrings dict: more entries than dict size (%i)", cs_size);
+ if (strcmp (t1_buf_array + 1, notdef) == 0) /* skip the slash */
+ ptr->name = (char *) notdef;
+ else
+ ptr->name = xstrdup (t1_buf_array + 1);
+ }
+ /* copy " RD " + cs data to t1_buf_array */
+ memcpy (t1_buf_array, t1_line_array + cs_start - 4,
+ (unsigned) (t1_cslen + 4));
+ /* copy the end of cs data to t1_buf_array */
+ for (p = t1_line_array + cs_start + t1_cslen, t1_buf_ptr =
+ t1_buf_array + t1_cslen + 4; *p != 10; *t1_buf_ptr++ = *p++);
+ *t1_buf_ptr++ = 10;
+ if (is_subr && cs_token_pair == NULL)
+ cs_token_pair = check_cs_token_pair ();
+ ptr->len = t1_buf_ptr - t1_buf_array;
+ ptr->cslen = t1_cslen;
+ ptr->data = xtalloc (ptr->len, byte);
+ memcpy (ptr->data, t1_buf_array, ptr->len);
+ ptr->valid = true;
+}
+
+#define store_subr() cs_store(true)
+#define store_cs() cs_store(false)
+
+#define CC_STACK_SIZE 24
+
+static integer cc_stack[CC_STACK_SIZE], *stack_ptr = cc_stack;
+static cc_entry cc_tab[CS_MAX];
+static boolean is_cc_init = false;
+
+
+#define cc_pop(N) \
+ if (stack_ptr - cc_stack < (N)) \
+ stack_error(N); \
+ stack_ptr -= N
+
+#define stack_error(N) { \
+ pdftex_warn("CharString: invalid access (%i) to stack (%i entries)", \
+ (int) N, (int)(stack_ptr - cc_stack)); \
+ goto cs_error; \
+}
+
+/*
+static integer cc_get(integer index)
+{
+ if (index < 0) {
+ if (stack_ptr + index < cc_stack )
+ stack_error(stack_ptr - cc_stack + index);
+ return *(stack_ptr + index);
+ }
+ else {
+ if (cc_stack + index >= stack_ptr)
+ stack_error(index);
+ return cc_stack[index];
+ }
+}
+*/
+
+#define cc_get(N) ((N) < 0 ? *(stack_ptr + (N)) : *(cc_stack + (N)))
+
+#define cc_push(V) *stack_ptr++ = V
+#define cc_clear() stack_ptr = cc_stack
+
+#define set_cc(N, B, A, C) \
+ cc_tab[N].nargs = A; \
+ cc_tab[N].bottom = B; \
+ cc_tab[N].clear = C; \
+ cc_tab[N].valid = true
+
+static void cc_init (void)
+{
+ int i;
+ if (is_cc_init)
+ return;
+ for (i = 0; i < CS_MAX; i++)
+ cc_tab[i].valid = false;
+ set_cc (CS_HSTEM, true, 2, true);
+ set_cc (CS_VSTEM, true, 2, true);
+ set_cc (CS_VMOVETO, true, 1, true);
+ set_cc (CS_RLINETO, true, 2, true);
+ set_cc (CS_HLINETO, true, 1, true);
+ set_cc (CS_VLINETO, true, 1, true);
+ set_cc (CS_RRCURVETO, true, 6, true);
+ set_cc (CS_CLOSEPATH, false, 0, true);
+ set_cc (CS_CALLSUBR, false, 1, false);
+ set_cc (CS_RETURN, false, 0, false);
+ /*
+ set_cc(CS_ESCAPE, false, 0, false);
+ */
+ set_cc (CS_HSBW, true, 2, true);
+ set_cc (CS_ENDCHAR, false, 0, true);
+ set_cc (CS_RMOVETO, true, 2, true);
+ set_cc (CS_HMOVETO, true, 1, true);
+ set_cc (CS_VHCURVETO, true, 4, true);
+ set_cc (CS_HVCURVETO, true, 4, true);
+ set_cc (CS_DOTSECTION, false, 0, true);
+ set_cc (CS_VSTEM3, true, 6, true);
+ set_cc (CS_HSTEM3, true, 6, true);
+ set_cc (CS_SEAC, true, 5, true);
+ set_cc (CS_SBW, true, 4, true);
+ set_cc (CS_DIV, false, 2, false);
+ set_cc (CS_CALLOTHERSUBR, false, 0, false);
+ set_cc (CS_POP, false, 0, false);
+ set_cc (CS_SETCURRENTPOINT, true, 2, true);
+ is_cc_init = true;
+}
+
+#define cs_getchar() cdecrypt(*data++, &cr)
+
+#define mark_subr(n) cs_mark(0, n)
+#define mark_cs(s) cs_mark(s, 0)
+
+__attribute__ ((format (printf, 3, 4)))
+static void cs_warn (const char *cs_name, int subr, const char *fmt, ...)
+{
+ char buf[SMALL_BUF_SIZE];
+ va_list args;
+ va_start (args, fmt);
+ vsprintf (buf, fmt, args);
+ va_end (args);
+ if (cs_name == NULL)
+ pdftex_warn ("Subr (%i): %s", (int) subr, buf);
+ else
+ pdftex_warn ("CharString (/%s): %s", cs_name, buf);
+}
+
+static void cs_mark (const char *cs_name, int subr)
+{
+ byte *data;
+ int i, b, cs_len;
+ integer a, a1, a2;
+ unsigned short cr;
+ static integer lastargOtherSubr3 = 3; /* the argument of last call to
+ OtherSubrs[3] */
+ cs_entry *ptr;
+ cc_entry *cc;
+ if (cs_name == NULL) {
+ check_subr (subr);
+ ptr = subr_tab + subr;
+ if (!ptr->valid)
+ return;
+ } else {
+ if (cs_notdef != NULL &&
+ (cs_name == notdef || strcmp (cs_name, notdef) == 0))
+ ptr = cs_notdef;
+ else {
+ for (ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (strcmp (ptr->name, cs_name) == 0)
+ break;
+ if (ptr == cs_ptr) {
+ pdftex_warn ("glyph `%s' undefined", cs_name);
+ return;
+ }
+ if (ptr->name == notdef)
+ cs_notdef = ptr;
+ }
+ }
+ /* only marked CharString entries and invalid entries can be skipped;
+ valid marked subrs must be parsed to keep the stack in sync */
+ if (!ptr->valid || (ptr->used && cs_name != NULL))
+ return;
+ ptr->used = true;
+ cr = 4330;
+ cs_len = ptr->cslen;
+ data = ptr->data + 4;
+ for (i = 0; i < t1_lenIV; i++, cs_len--)
+ cs_getchar ();
+ while (cs_len > 0) {
+ --cs_len;
+ b = cs_getchar ();
+ if (b >= 32) {
+ if (b <= 246)
+ a = b - 139;
+ else if (b <= 250) {
+ --cs_len;
+ a = ((b - 247) << 8) + 108 + cs_getchar ();
+ } else if (b <= 254) {
+ --cs_len;
+ a = -((b - 251) << 8) - 108 - cs_getchar ();
+ } else {
+ cs_len -= 4;
+ a = (cs_getchar () & 0xff) << 24;
+ a |= (cs_getchar () & 0xff) << 16;
+ a |= (cs_getchar () & 0xff) << 8;
+ a |= (cs_getchar () & 0xff) << 0;
+ if (sizeof (integer) > 4 && (a & 0x80000000))
+ a |= ~0x7FFFFFFF;
+ }
+ cc_push (a);
+ } else {
+ if (b == CS_ESCAPE) {
+ b = cs_getchar () + CS_1BYTE_MAX;
+ cs_len--;
+ }
+ if (b >= CS_MAX) {
+ cs_warn (cs_name, subr, "command value out of range: %i",
+ (int) b);
+ goto cs_error;
+ }
+ cc = cc_tab + b;
+ if (!cc->valid) {
+ cs_warn (cs_name, subr, "command not valid: %i", (int) b);
+ goto cs_error;
+ }
+ if (cc->bottom) {
+ if (stack_ptr - cc_stack < cc->nargs)
+ cs_warn (cs_name, subr,
+ "less arguments on stack (%i) than required (%i)",
+ (int) (stack_ptr - cc_stack), (int) cc->nargs);
+ else if (stack_ptr - cc_stack > cc->nargs)
+ cs_warn (cs_name, subr,
+ "more arguments on stack (%i) than required (%i)",
+ (int) (stack_ptr - cc_stack), (int) cc->nargs);
+ }
+ switch (cc - cc_tab) {
+ case CS_CALLSUBR:
+ a1 = cc_get (-1);
+ cc_pop (1);
+ mark_subr (a1);
+ if (!subr_tab[a1].valid) {
+ cs_warn (cs_name, subr, "cannot call subr (%i)", (int) a1);
+ goto cs_error;
+ }
+ break;
+ case CS_DIV:
+ cc_pop (2);
+ cc_push (0);
+ break;
+ case CS_CALLOTHERSUBR:
+ if (cc_get (-1) == 3)
+ lastargOtherSubr3 = cc_get (-3);
+ a1 = cc_get (-2) + 2;
+ cc_pop (a1);
+ break;
+ case CS_POP:
+ cc_push (lastargOtherSubr3);
+ /* the only case when we care about the value being pushed onto
+ stack is when POP follows CALLOTHERSUBR (changing hints by
+ OtherSubrs[3])
+ */
+ break;
+ case CS_SEAC:
+ a1 = cc_get (3);
+ a2 = cc_get (4);
+ cc_clear ();
+ mark_cs (standard_glyph_names[a1]);
+ mark_cs (standard_glyph_names[a2]);
+ break;
+ default:
+ if (cc->clear)
+ cc_clear ();
+ }
+ }
+ }
+ return;
+ cs_error: /* an error occured during parsing */
+ cc_clear ();
+ ptr->valid = false;
+ ptr->used = false;
+}
+
+/**********************************************************************/
+/* AVL search tree for glyph code by glyph name */
+
+static int comp_t1_glyphs(const void *pa, const void *pb, void *p)
+{
+ return strcmp(*((const char **) pa), *((const char **) pb));
+}
+
+struct avl_table *create_t1_glyph_tree(char **glyph_names)
+{
+ int i;
+ void **aa;
+ static struct avl_table *gl_tree;
+ gl_tree = avl_create(comp_t1_glyphs, NULL, &avl_xallocator);
+ assert(gl_tree != NULL);
+ for (i = 0; i < 256; i++) {
+ if (glyph_names[i] != notdef &&
+ (char **) avl_find(gl_tree, &glyph_names[i]) == NULL) {
+ /* no strdup here, just point to the glyph_names array members */
+ aa = avl_probe(gl_tree, &glyph_names[i]);
+ assert(aa != NULL);
+ }
+ }
+ return gl_tree;
+}
+
+void destroy_t1_glyph_tree(struct avl_table *gl_tree)
+{
+ assert(gl_tree != NULL);
+ avl_destroy(gl_tree, NULL);
+}
+
+/**********************************************************************/
+
+static void t1_subset_ascii_part(void)
+{
+ int j, *p;
+ char *glyph, **gg, **glyph_names;
+ struct avl_table *gl_tree;
+ struct avl_traverser t;
+ void **aa;
+ assert(fd_cur != NULL);
+ assert(fd_cur->gl_tree != NULL);
+ t1_getline();
+ while (!t1_prefix("/Encoding")) {
+ t1_scan_param();
+ t1_putline();
+ t1_getline();
+ }
+ glyph_names = t1_builtin_enc();
+ fd_cur->builtin_glyph_names = glyph_names;
+ if (is_subsetted(fd_cur->fm)) {
+ assert(is_included(fd_cur->fm));
+ if (fd_cur->tx_tree != NULL) {
+ /* take over collected non-reencoded characters from TeX */
+ avl_t_init(&t, fd_cur->tx_tree);
+ for (p = (int *) avl_t_first(&t, fd_cur->tx_tree); p != NULL;
+ p = (int *) avl_t_next(&t)) {
+ if ((char *) avl_find(fd_cur->gl_tree, glyph_names[*p]) == NULL) {
+ glyph = xstrdup(glyph_names[*p]);
+ aa = avl_probe(fd_cur->gl_tree, glyph);
+ assert(aa != NULL);
+ }
+ }
+ }
+ make_subset_tag(fd_cur);
+ assert(t1_fontname_offset != 0);
+ strncpy(fb_array + t1_fontname_offset, fd_cur->subset_tag, 6);
+ }
+ /* now really all glyphs needed from this font are in the fd_cur->gl_tree */
+ if (t1_encoding == ENC_STANDARD)
+ t1_puts("/Encoding StandardEncoding def\n");
+ else {
+ t1_puts
+ ("/Encoding 256 array\n0 1 255 {1 index exch /.notdef put} for\n");
+ gl_tree = create_t1_glyph_tree(glyph_names);
+ avl_t_init(&t, fd_cur->gl_tree);
+ j = 0;
+ for (glyph = (char *) avl_t_first(&t, fd_cur->gl_tree); glyph != NULL;
+ glyph = (char *) avl_t_next(&t)) {
+ if ((gg = (char **) avl_find(gl_tree, &glyph)) != NULL) {
+ t1_printf("dup %i /%s put\n", (int) (gg - glyph_names), *gg);
+ j++;
+ }
+ }
+ destroy_t1_glyph_tree(gl_tree);
+ if (j == 0)
+ /* We didn't mark anything for the Encoding array. */
+ /* We add "dup 0 /.notdef put" for compatibility */
+ /* with Acrobat 5.0. */
+ t1_puts("dup 0 /.notdef put\n");
+ t1_puts("readonly def\n");
+ }
+ do {
+ t1_getline();
+ t1_scan_param();
+ if (!t1_prefix("/UniqueID")) /* ignore UniqueID for subsetted fonts */
+ t1_putline();
+ }
+ while (t1_in_eexec == 0);
+}
+
+
+static void cs_init (void)
+{
+ cs_ptr = cs_tab = NULL;
+ cs_dict_start = cs_dict_end = NULL;
+ cs_counter = cs_size = cs_size_pos = 0;
+ cs_token_pair = NULL;
+ subr_tab = NULL;
+ subr_array_start = subr_array_end = NULL;
+ subr_max = subr_size = subr_size_pos = 0;
+}
+
+static void init_cs_entry (cs_entry * cs)
+{
+ cs->data = NULL;
+ cs->name = NULL;
+ cs->len = 0;
+ cs->cslen = 0;
+ cs->used = false;
+ cs->valid = false;
+}
+
+static void t1_read_subrs (void)
+{
+ int i, s;
+ cs_entry *ptr;
+ t1_getline ();
+ while (!(t1_charstrings () || t1_subrs ())) {
+ t1_scan_param ();
+ t1_putline ();
+ t1_getline ();
+ }
+ found:
+ t1_cs = true;
+ t1_scan = false;
+ if (!t1_subrs ())
+ return;
+ subr_size_pos = strlen ("/Subrs") + 1;
+ /* subr_size_pos points to the number indicating dict size after "/Subrs" */
+ subr_size = t1_scan_num (t1_line_array + subr_size_pos, 0);
+ if (subr_size == 0) {
+ while (!t1_charstrings ())
+ t1_getline ();
+ return;
+ }
+ subr_tab = xtalloc (subr_size, cs_entry);
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ init_cs_entry (ptr);
+ subr_array_start = xstrdup (t1_line_array);
+ t1_getline ();
+ while (t1_cslen) {
+ store_subr ();
+ t1_getline ();
+ }
+ /* mark the first four entries without parsing */
+ for (i = 0; i < subr_size && i < 4; i++)
+ subr_tab[i].used = true;
+ /* the end of the Subrs array might have more than one line so we need to
+ concatnate them to subr_array_end. Unfortunately some fonts don't have
+ the Subrs array followed by the CharStrings dict immediately (synthetic
+ fonts). If we cannot find CharStrings in next POST_SUBRS_SCAN lines then
+ we will treat the font as synthetic and ignore everything until next
+ Subrs is found
+ */
+#define POST_SUBRS_SCAN 5
+ s = 0;
+ *t1_buf_array = 0;
+ for (i = 0; i < POST_SUBRS_SCAN; i++) {
+ if (t1_charstrings ())
+ break;
+ s += t1_line_ptr - t1_line_array;
+ alloc_array (t1_buf, s, T1_BUF_SIZE);
+ strcat (t1_buf_array, t1_line_array);
+ t1_getline ();
+ }
+ subr_array_end = xstrdup (t1_buf_array);
+ if (i == POST_SUBRS_SCAN) { /* CharStrings not found;
+ suppose synthetic font */
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->valid)
+ xfree (ptr->data);
+ xfree (subr_tab);
+ xfree (subr_array_start);
+ xfree (subr_array_end);
+ cs_init ();
+ t1_cs = false;
+ t1_synthetic = true;
+ while (!(t1_charstrings () || t1_subrs ()))
+ t1_getline ();
+ goto found;
+ }
+}
+
+#define t1_subr_flush() t1_flush_cs(true)
+#define t1_cs_flush() t1_flush_cs(false)
+
+static void t1_flush_cs (boolean is_subr)
+{
+ char *p;
+ byte *r, *return_cs = NULL;
+ cs_entry *tab, *end_tab, *ptr;
+ char *start_line, *line_end;
+ int count, size_pos;
+ unsigned short cr, cs_len;
+ if (is_subr) {
+ start_line = subr_array_start;
+ line_end = subr_array_end;
+ size_pos = subr_size_pos;
+ tab = subr_tab;
+ count = subr_max + 1;
+ end_tab = subr_tab + count;
+ } else {
+ start_line = cs_dict_start;
+ line_end = cs_dict_end;
+ size_pos = cs_size_pos;
+ tab = cs_tab;
+ end_tab = cs_ptr;
+ count = cs_counter;
+ }
+ t1_line_ptr = t1_line_array;
+ for (p = start_line; p - start_line < size_pos;)
+ *t1_line_ptr++ = *p++;
+ while (isdigit (*p))
+ p++;
+ sprintf (t1_line_ptr, "%u", count);
+ strcat (t1_line_ptr, p);
+ t1_line_ptr = eol (t1_line_array);
+ t1_putline ();
+
+ cs_len = 0; /* for -Wall */
+ /* create return_cs to replace unsused subr's */
+ if (is_subr) {
+ cr = 4330;
+ cs_len = 0;
+ return_cs = xtalloc (t1_lenIV + 1, byte);
+ if (t1_lenIV > 0) {
+ for (cs_len = 0, r = return_cs; cs_len < t1_lenIV; cs_len++, r++)
+ *r = cencrypt (0x00, &cr);
+ *r = cencrypt (CS_RETURN, &cr);
+ } else {
+ *return_cs = CS_RETURN;
+ }
+ cs_len++;
+ }
+
+ for (ptr = tab; ptr < end_tab; ptr++) {
+ if (ptr->used) {
+ if (is_subr)
+ sprintf (t1_line_array, "dup %li %u", (long int)(ptr - tab), ptr->cslen);
+ else
+ sprintf (t1_line_array, "/%s %u", ptr->name, ptr->cslen);
+ p = strend (t1_line_array);
+ memcpy (p, ptr->data, ptr->len);
+ t1_line_ptr = p + ptr->len;
+ t1_putline ();
+ } else {
+ /* replace unsused subr's by return_cs */
+ if (is_subr) {
+ sprintf (t1_line_array, "dup %li %u%s ", (long int)(ptr - tab), cs_len,
+ cs_token_pair[0]);
+ p = strend (t1_line_array);
+ memcpy (p, return_cs, cs_len);
+ t1_line_ptr = p + cs_len;
+ t1_putline ();
+ sprintf (t1_line_array, " %s", cs_token_pair[1]);
+ t1_line_ptr = eol (t1_line_array);
+ t1_putline ();
+ }
+ }
+ xfree (ptr->data);
+ if (ptr->name != notdef)
+ xfree (ptr->name);
+ }
+ sprintf (t1_line_array, "%s", line_end);
+ t1_line_ptr = eol (t1_line_array);
+ t1_putline ();
+ if (is_subr)
+ xfree (return_cs);
+ xfree (tab);
+ xfree (start_line);
+ xfree (line_end);
+}
+
+static void t1_mark_glyphs(void)
+{
+ char *glyph;
+ struct avl_traverser t;
+ cs_entry *ptr;
+ if (t1_synthetic || fd_cur->all_glyphs) { /* mark everything */
+ if (cs_tab != NULL)
+ for (ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (ptr->valid)
+ ptr->used = true;
+ if (subr_tab != NULL) {
+ for (ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->valid)
+ ptr->used = true;
+ subr_max = subr_size - 1;
+ }
+ return;
+ }
+ mark_cs(notdef);
+ avl_t_init(&t, fd_cur->gl_tree);
+ for (glyph = (char *) avl_t_first(&t, fd_cur->gl_tree); glyph != NULL;
+ glyph = (char *) avl_t_next(&t)) {
+ mark_cs(glyph);
+ }
+ if (subr_tab != NULL)
+ for (subr_max = -1, ptr = subr_tab; ptr - subr_tab < subr_size; ptr++)
+ if (ptr->used && ptr - subr_tab > subr_max)
+ subr_max = ptr - subr_tab;
+}
+
+
+static void t1_subset_charstrings (void)
+{
+ cs_entry *ptr;
+ cs_size_pos =
+ strstr (t1_line_array, charstringname) + strlen (charstringname)
+ - t1_line_array + 1;
+ /* cs_size_pos points to the number indicating
+ dict size after "/CharStrings" */
+ cs_size = t1_scan_num (t1_line_array + cs_size_pos, 0);
+ cs_ptr = cs_tab = xtalloc (cs_size, cs_entry);
+ for (ptr = cs_tab; ptr - cs_tab < cs_size; ptr++)
+ init_cs_entry (ptr);
+ cs_notdef = NULL;
+ cs_dict_start = xstrdup (t1_line_array);
+ t1_getline ();
+ while (t1_cslen) {
+ store_cs ();
+ t1_getline ();
+ }
+ cs_dict_end = xstrdup (t1_line_array);
+ t1_mark_glyphs ();
+ if (subr_tab != NULL) {
+ if (cs_token_pair == NULL)
+ pdftex_fail
+ ("This Type 1 font uses mismatched subroutine begin/end token pairs.");
+ t1_subr_flush ();
+ }
+ for (cs_counter = 0, ptr = cs_tab; ptr < cs_ptr; ptr++)
+ if (ptr->used)
+ cs_counter++;
+ t1_cs_flush ();
+}
+
+static void t1_subset_end (void)
+{
+ if (t1_synthetic) { /* copy to "dup /FontName get exch definefont pop" */
+ while (!strstr (t1_line_array, "definefont")) {
+ t1_getline ();
+ t1_putline ();
+ }
+ while (!t1_end_eexec ())
+ t1_getline (); /* ignore the rest */
+ t1_putline (); /* write "mark currentfile closefile" */
+ } else
+ while (!t1_end_eexec ()) { /* copy to "mark currentfile closefile" */
+ t1_getline ();
+ t1_putline ();
+ }
+ t1_stop_eexec ();
+ if (fixedcontent) { /* copy 512 zeros (not needed for PDF) */
+ while (!t1_cleartomark ()) {
+ t1_getline ();
+ t1_putline ();
+ }
+ if (!t1_synthetic) /* don't check "{restore}if" for synthetic fonts */
+ t1_check_end (); /* write "{restore}if" if found */
+ }
+ get_length3 ();
+}
+
+void writet1(fd_entry * fd)
+{
+ fd_cur = fd; /* fd_cur is global inside writet1.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_type1(fd->fm));
+ assert(is_included(fd->fm));
+
+ t1_save_offset = 0;
+ if (!is_subsetted(fd_cur->fm)) { /* include entire font */
+ if (!(fd->ff_found = t1_open_fontfile("<<")))
+ return;
+ t1_include ();
+ t1_close_font_file (">>");
+ return;
+ }
+ /* partial downloading */
+ if (!(fd->ff_found = t1_open_fontfile("<")))
+ return;
+ t1_subset_ascii_part ();
+ t1_start_eexec ();
+ cc_init ();
+ cs_init ();
+ t1_read_subrs ();
+ t1_subset_charstrings ();
+ t1_subset_end ();
+ t1_close_font_file (">");
+}
+
+void t1_free ()
+{
+ xfree (t1_line_array);
+ xfree (t1_buf_array);
+}
+
diff --git a/Build/source/texk/web2c/luatexdir/font/writet3.c b/Build/source/texk/web2c/luatexdir/font/writet3.c
new file mode 100644
index 00000000000..42827d1b124
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writet3.c
@@ -0,0 +1,348 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writet3.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+#include <kpathsea/tex-glyph.h>
+#include <kpathsea/magstep.h>
+#include <string.h>
+
+#define T3_BUF_SIZE 1024
+
+typedef char t3_line_entry;
+define_array (t3_line);
+
+FILE *t3_file;
+static boolean t3_image_used;
+
+static integer t3_char_procs[256];
+static float t3_char_widths[256];
+static int t3_glyph_num;
+static float t3_font_scale;
+static integer t3_b0, t3_b1, t3_b2, t3_b3;
+static boolean is_pk_font;
+
+static unsigned char *t3_buffer = NULL;
+static integer t3_size = 0;
+static integer t3_curbyte = 0;
+
+
+#define t3_open() \
+ open_input(&t3_file, kpse_miscfonts_format, FOPEN_RBIN_MODE)
+#define t3_read_file() readbinfile(t3_file,&t3_buffer,&t3_size)
+#define t3_close() xfclose(t3_file, cur_file_name)
+#define t3_getchar() t3_buffer[t3_curbyte++]
+#define t3_eof() (t3_curbyte>t3_size)
+
+#define t3_prefix(s) (!strncmp(t3_line_array, s, strlen(s)))
+#define t3_putchar(c) pdfout(c)
+
+
+
+#define t3_check_eof() \
+ if (t3_eof()) \
+ pdftex_fail("unexpected end of file");
+
+
+static void update_bbox (integer llx, integer lly, integer urx, integer ury,
+ boolean is_first_glyph)
+{
+ if (is_first_glyph) {
+ t3_b0 = llx;
+ t3_b1 = lly;
+ t3_b2 = urx;
+ t3_b3 = ury;
+ } else {
+ if (llx < t3_b0)
+ t3_b0 = llx;
+ if (lly < t3_b1)
+ t3_b1 = lly;
+ if (urx > t3_b2)
+ t3_b2 = urx;
+ if (ury > t3_b3)
+ t3_b3 = ury;
+ }
+}
+
+static integer get_pk_font_scale (internalfontnumber f)
+{
+ return
+ divide_scaled (pk_scale_factor,
+ divide_scaled (pdf_font_size(f), one_hundred_bp,
+ fixed_decimal_digits + 2), 0);
+}
+
+static integer pk_char_width (internalfontnumber f, scaled w)
+{
+ return
+ divide_scaled (divide_scaled (w, pdf_font_size(f), 7),
+ get_pk_font_scale (f), 0);
+}
+
+scaled get_pk_char_width (internalfontnumber f, scaled w)
+{
+ return (get_pk_font_scale (f) / 100000.0) *
+ (pk_char_width (f, w) / 100.0) * pdf_font_size(f);
+}
+
+static boolean writepk (internalfontnumber f)
+{
+ kpse_glyph_file_type font_ret;
+ integer llx, lly, urx, ury;
+ integer cw, rw, i, j;
+ halfword *row;
+ char *name;
+ char *ftemp = NULL;
+ chardesc cd;
+ boolean is_null_glyph, check_preamble;
+ integer dpi;
+ int callback_id=0;
+ int file_opened=0;
+ int mallocsize=0;
+ if (t3_buffer!=NULL) {
+ xfree(t3_buffer);
+ t3_buffer=NULL;
+ }
+ t3_curbyte=0;
+ t3_size=0;
+
+ callback_id=callback_defined(find_pk_file_callback);
+
+ if (callback_id>0) {
+ dpi = round (fixed_pk_resolution *
+ (((float) pdf_font_size(f)) / font_dsize(f)));
+ /* <base>.dpi/<fontname>.<tdpi>pk */
+ cur_file_name = font_name(f);
+ mallocsize = strlen(cur_file_name)+24+9;
+ name = xmalloc(mallocsize);
+ snprintf(name,mallocsize,"%ddpi/%s.%dpk",(int)fixed_pk_resolution,cur_file_name,(int)dpi);
+ if(run_callback(callback_id,"S->S",name,&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(name);
+ name = xstrdup(ftemp);
+ free(ftemp);
+ }
+ }
+ } else {
+ dpi =
+ kpse_magstep_fix (round
+ (fixed_pk_resolution *
+ (((float) pdf_font_size(f)) / font_dsize(f))),
+ fixed_pk_resolution, NULL);
+ cur_file_name = font_name(f);
+ name = kpse_find_pk (cur_file_name, (unsigned) dpi, &font_ret);
+ if (name == NULL ||
+ !FILESTRCASEEQ (cur_file_name, font_ret.name) ||
+ !kpse_bitmap_tolerance ((float) font_ret.dpi, (float) dpi)) {
+ pdftex_warn ("Font %s at %i not found", cur_file_name, (int) dpi);
+ cur_file_name = NULL;
+ return false;
+ }
+ }
+ callback_id=callback_defined(read_pk_file_callback);
+ if (callback_id>0) {
+ if(! ( run_callback(callback_id,"S->bSd",name, &file_opened, &t3_buffer,&t3_size) &&
+ file_opened &&
+ t3_size>0 ) ) {
+ pdftex_warn ("Font %s at %i not found", cur_file_name, (int)dpi);
+ cur_file_name = NULL;
+ return false;
+ }
+ } else {
+ t3_file = xfopen (name, FOPEN_RBIN_MODE);
+ t3_read_file();
+ t3_close();
+ }
+ t3_image_used = true;
+ is_pk_font = true;
+ if (tracefilenames)
+ tex_printf (" <%s", (char *) name);
+ cd.rastersize = 256;
+ cd.raster = xtalloc (cd.rastersize, halfword);
+ check_preamble = true;
+ while (readchar (check_preamble, &cd) != 0) {
+ check_preamble = false;
+ if (!pdf_char_marked (f, cd.charcode))
+ continue;
+ t3_char_widths[cd.charcode] =
+ pk_char_width (f, get_charwidth (f, cd.charcode));
+ if (cd.cwidth < 1 || cd.cheight < 1) {
+ cd.xescape = cd.cwidth =
+ round (t3_char_widths[cd.charcode] / 100.0);
+ cd.cheight = 1;
+ cd.xoff = 0;
+ cd.yoff = 0;
+ is_null_glyph = true;
+ } else
+ is_null_glyph = false;
+ llx = -cd.xoff;
+ lly = cd.yoff - cd.cheight + 1;
+ urx = cd.cwidth + llx + 1;
+ ury = cd.cheight + lly;
+ update_bbox (llx, lly, urx, ury, t3_glyph_num == 0);
+ t3_glyph_num++;
+ pdf_new_dict (0, 0, 0);
+ t3_char_procs[cd.charcode] = obj_ptr;
+ pdf_begin_stream ();
+ pdf_print_real (t3_char_widths[cd.charcode], 2);
+ pdf_printf (" 0 %i %i %i %i d1\n",
+ (int) llx, (int) lly, (int) urx, (int) ury);
+ if (is_null_glyph)
+ goto end_stream;
+ pdf_printf ("q\n%i 0 0 %i %i %i cm\nBI\n", (int) cd.cwidth,
+ (int) cd.cheight, (int) llx, (int) lly);
+ pdf_printf ("/W %i\n/H %i\n", (int) cd.cwidth, (int) cd.cheight);
+ pdf_puts ("/IM true\n/BPC 1\n/D [1 0]\nID ");
+ cw = (cd.cwidth + 7) / 8;
+ rw = (cd.cwidth + 15) / 16;
+ row = cd.raster;
+ for (i = 0; i < cd.cheight; i++) {
+ for (j = 0; j < rw - 1; j++) {
+ pdfout (*row / 256);
+ pdfout (*row % 256);
+ row++;
+ }
+ pdfout (*row / 256);
+ if (2 * rw == cw)
+ pdfout (*row % 256);
+ row++;
+ }
+ pdf_puts ("\nEI\nQ\n");
+ end_stream:
+ pdf_end_stream ();
+ }
+ xfree (cd.raster);
+ cur_file_name = NULL;
+ return true;
+}
+
+void writet3 (int objnum, internalfontnumber f)
+{
+
+ int i;
+ integer wptr, eptr, cptr;
+ int first_char, last_char;
+ integer pk_font_scale;
+ boolean is_notdef;
+
+
+ t3_glyph_num = 0;
+ t3_image_used = false;
+ for (i = 0; i < 256; i++) {
+ t3_char_procs[i] = 0;
+ t3_char_widths[i] = 0;
+ }
+ pack_file_name (tex_font_name(f), get_nullstr (), maketexlstring (".pgc",4));
+ cur_file_name = makecstring (make_name_string ());
+ is_pk_font = false;
+
+ if (t3_buffer!=NULL) {
+ xfree(t3_buffer);
+ t3_buffer=NULL;
+ }
+ t3_curbyte=0;
+ t3_size=0;
+ if (!writepk (f)) {
+ cur_file_name = NULL;
+ return;
+ }
+ for (i = font_bc(f); i <= font_ec(f); i++)
+ if (pdf_char_marked (f, i))
+ break;
+ first_char = i;
+ for (i = font_ec(f); i > first_char; i--)
+ if (pdf_char_marked (f, i))
+ break;
+ last_char = i;
+ pdf_begin_dict (objnum, 1); /* Type 3 font dictionary */
+ pdf_puts ("/Type /Font\n/Subtype /Type3\n");
+ pdf_printf ("/Name /F%i\n", (int) f);
+ if (pdf_font_attr(f) != get_nullstr ()) {
+ pdf_print (pdf_font_attr(f));
+ pdf_puts ("\n");
+ }
+ if (is_pk_font) {
+ pk_font_scale = get_pk_font_scale (f);
+ pdf_puts ("/FontMatrix [");
+ pdf_print_real (pk_font_scale, 5);
+ pdf_puts (" 0 0 ");
+ pdf_print_real (pk_font_scale, 5);
+ pdf_puts (" 0 0]\n");
+ } else
+ pdf_printf ("/FontMatrix [%g 0 0 %g 0 0]\n",
+ (double) t3_font_scale, (double) t3_font_scale);
+ pdf_printf ("/%s [ %i %i %i %i ]\n",
+ font_key[FONTBBOX1_CODE].pdfname,
+ (int) t3_b0, (int) t3_b1, (int) t3_b2, (int) t3_b3);
+ pdf_printf ("/Resources << /ProcSet [ /PDF %s] >>\n",
+ t3_image_used ? "/ImageB " : "");
+ pdf_printf ("/FirstChar %i\n/LastChar %i\n", first_char, last_char);
+ wptr = pdf_new_objnum ();
+ eptr = pdf_new_objnum ();
+ cptr = pdf_new_objnum ();
+ pdf_printf ("/Widths %i 0 R\n/Encoding %i 0 R\n/CharProcs %i 0 R\n",
+ (int)wptr, (int)eptr, (int)cptr);
+ pdf_end_dict ();
+ pdf_begin_obj (wptr, 1); /* chars width array */
+ pdf_puts ("[");
+ if (is_pk_font)
+ for (i = first_char; i <= last_char; i++) {
+ pdf_print_real (t3_char_widths[i], 2);
+ pdf_puts (" ");
+ } else
+ for (i = first_char; i <= last_char; i++)
+ pdf_printf ("%i ", (int) t3_char_widths[i]);
+ pdf_puts ("]\n");
+ pdf_end_obj ();
+ pdf_begin_dict (eptr, 1); /* encoding dictionary */
+ pdf_printf ("/Type /Encoding\n/Differences [%i", first_char);
+ if (t3_char_procs[first_char] == 0) {
+ pdf_printf ("/%s", notdef);
+ is_notdef = true;
+ } else {
+ pdf_printf ("/a%i", first_char);
+ is_notdef = false;
+ }
+ for (i = first_char + 1; i <= last_char; i++) {
+ if (t3_char_procs[i] == 0) {
+ if (!is_notdef) {
+ pdf_printf (" %i/%s", i, notdef);
+ is_notdef = true;
+ }
+ } else {
+ if (is_notdef) {
+ pdf_printf (" %i", i);
+ is_notdef = false;
+ }
+ pdf_printf ("/a%i", i);
+ }
+ }
+ pdf_puts ("]\n");
+ pdf_end_dict ();
+ pdf_begin_dict (cptr, 1); /* CharProcs dictionary */
+ for (i = first_char; i <= last_char; i++)
+ if (t3_char_procs[i] != 0)
+ pdf_printf ("/a%i %i 0 R\n", (int) i, (int) t3_char_procs[i]);
+ pdf_end_dict ();
+ if (tracefilenames)
+ tex_printf (">");
+ cur_file_name = NULL;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/writettf.c b/Build/source/texk/web2c/luatexdir/font/writettf.c
new file mode 100644
index 00000000000..2a92706a0de
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writettf.c
@@ -0,0 +1,1509 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writettf.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+#include "writettf.h"
+#include <string.h>
+
+#define DEFAULT_NTABS 14
+#define NEW_CMAP_SIZE 2
+
+#define ttf_putchar fb_putchar
+#define ttf_offset fb_offset
+#define ttf_seek_outbuf fb_seek
+
+ /* #define INFILE ttf_file*/
+
+unsigned char *ttf_buffer = NULL;
+integer ttf_size = 0;
+integer ttf_curbyte = 0;
+
+typedef struct {
+ char *name; /* name of glyph */
+ long code; /* charcode in case of subfonts */
+ short newindex; /* new index of glyph in output file */
+
+} ttfenc_entry;
+
+typedef struct {
+ TTF_USHORT platform_id;
+ TTF_USHORT encoding_id;
+ TTF_USHORT language_id;
+ TTF_USHORT name_id;
+ TTF_USHORT length;
+ TTF_USHORT offset;
+ TTF_USHORT new_offset;
+ TTF_USHORT new_length;
+} name_record;
+
+typedef struct {
+ char *ttf_name;
+ TTF_USHORT pid;
+ TTF_USHORT eid;
+ short *table;
+} ttf_cmap_entry;
+
+static TTF_USHORT ntabs;
+static TTF_USHORT upem;
+static TTF_FIXED post_format;
+static TTF_SHORT loca_format;
+static TTF_ULONG last_glyf_offset;
+static TTF_USHORT glyphs_count;
+static TTF_USHORT new_glyphs_count;
+static TTF_USHORT nhmtxs;
+static TTF_USHORT new_ntabs;
+
+glyph_entry *glyph_tab;
+dirtab_entry *dir_tab;
+
+static long *glyph_index;
+static cmap_entry *cmap_tab, new_cmap_tab[NEW_CMAP_SIZE];
+static name_record *name_tab;
+static int name_record_num;
+static char *name_buf;
+static int name_buf_size;
+static char *glyph_name_buf;
+static TTF_ULONG checksum;
+static TTF_ULONG tab_length;
+static TTF_ULONG tmp_ulong;
+static TTF_ULONG checkSumAdjustment_offset;
+FILE *ttf_file;
+static ttfenc_entry ttfenc_tab[256];
+
+fd_entry *fd_cur; /* pointer to the current font descriptor */
+
+static struct avl_table *ttf_cmap_tree = NULL;
+
+integer ttf_length;
+
+#include "macnames.c"
+
+extern char *fb_array;
+extern char charsetstr[];
+
+static const char *newtabnames[] = {
+ "OS/2",
+ "PCLT",
+ "cmap",
+ "cvt ",
+ "fpgm",
+ "glyf",
+ "head",
+ "hhea",
+ "hmtx",
+ "loca",
+ "maxp",
+ "name",
+ "post",
+ "prep"
+};
+
+ttf_cmap_entry *new_ttf_cmap_entry (void)
+{
+ ttf_cmap_entry *e;
+ e = xtalloc (1, ttf_cmap_entry);
+ e->ttf_name = NULL;
+ e->table = NULL;
+ return e;
+}
+
+static void destroy_ttf_cmap_entry (void *pa, void *pb)
+{
+ ttf_cmap_entry *p;
+ p = (ttf_cmap_entry *) pa;
+ xfree (p->ttf_name);
+ xfree (p->table);
+ xfree (p);
+}
+
+void ttf_free (void)
+{
+ if (ttf_cmap_tree != NULL)
+ avl_destroy (ttf_cmap_tree, destroy_ttf_cmap_entry);
+}
+
+static int comp_ttf_cmap_entry (const void *pa, const void *pb, void *p)
+{
+ const ttf_cmap_entry *p1 = (const ttf_cmap_entry *) pa,
+ *p2 = (const ttf_cmap_entry *) pb;
+ int i;
+ assert (p1->ttf_name != NULL && p2->ttf_name != NULL);
+ if ((i = strcmp (p1->ttf_name, p2->ttf_name)) != 0)
+ return i;
+ cmp_return (p1->pid, p2->pid);
+ cmp_return (p1->eid, p2->eid);
+ return 0;
+}
+
+static unsigned char ttf_addchksm (unsigned char b)
+{
+ tmp_ulong = (tmp_ulong << 8) + b;
+ tab_length++;
+ if (tab_length % 4 == 0) {
+ checksum += tmp_ulong;
+ tmp_ulong = 0;
+ }
+ return b;
+}
+
+static TTF_ULONG ttf_getchksm (void)
+{
+ while (tab_length % 4 != 0)
+ ttf_putchar (ttf_addchksm (0)); /* ttf_addchksm updates tab_length */
+ return checksum;
+}
+
+long ttf_putnum (int s, long n)
+{
+ long i = n;
+ char buf[TTF_LONG_SIZE + 1], *p = buf;
+ while (s-- > 0) {
+ *p++ = i & 0xFF;
+ i >>= 8;
+ }
+ p--;
+ while (p >= buf)
+ ttf_putchar (ttf_addchksm (*p--));
+ return n;
+}
+
+long ttf_getnum (int s)
+{
+ long i = 0;
+ int c;
+ while (s > 0) {
+ if (ttf_eof())
+ pdftex_fail ("unexpected EOF");
+ c = ttf_getchar ();
+ i = (i << 8) + c;
+ s--;
+ }
+ return i;
+}
+
+static long ttf_funit (long n)
+{
+ if (n < 0)
+ return -((-n / upem) * 1000 + ((-n % upem) * 1000) / upem);
+ else
+ return (n / upem) * 1000 + ((n % upem) * 1000) / upem;
+}
+
+static void ttf_ncopy (int n)
+{
+ while (n-- > 0)
+ copy_byte ();
+}
+
+dirtab_entry *ttf_name_lookup (const char *s, boolean required)
+{
+ dirtab_entry *tab;
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++)
+ if (strncmp (tab->tag, s, 4) == 0)
+ break;
+ if (tab - dir_tab == ntabs) {
+ if (required)
+ pdftex_fail ("can't find table `%s'", s);
+ else
+ tab = NULL;
+ }
+ return tab;
+}
+
+dirtab_entry *ttf_seek_tab (const char *name, TTF_LONG offset)
+{
+ dirtab_entry *tab = ttf_name_lookup (name, true);
+ /*xfseek (INFILE, tab->offset + offset, SEEK_SET, cur_file_name);*/
+ ttf_curbyte = tab->offset + offset;
+ return tab;
+}
+
+static void ttf_seek_off (TTF_LONG offset)
+{
+ ttf_curbyte = offset;
+ //xfseek (INFILE, offset, SEEK_SET, cur_file_name);
+}
+
+static void ttf_copy_encoding(void)
+{
+ int i, *q;
+ void **aa;
+ char **glyph_names;
+ long *charcodes;
+ static char buf[SMALL_BUF_SIZE];
+ struct avl_traverser t;
+ ttfenc_entry *e = ttfenc_tab;
+
+ assert(fd_cur->tx_tree != NULL); /* this must be set in create_fontdictionary */
+
+ if (fd_cur->fe != NULL) {
+ glyph_names = fd_cur->fe->glyph_names;
+ assert(glyph_names != NULL);
+
+ for (i = 0; i < 256; i++)
+ ttfenc_tab[i].name = (char *) notdef;
+
+ /* a workaround for a bug of AcroReader 4.0 */
+ if (strcmp(glyph_names[97], "a") == 0) {
+ q = xtalloc(1, int);
+ *q = 'a';
+ aa = avl_probe(fd_cur->tx_tree, q);
+ assert(aa != NULL);
+ }
+ /* end of workaround */
+
+ /* take over collected characters from TeX, reencode them */
+ avl_t_init(&t, fd_cur->tx_tree);
+ for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
+ q = (int *) avl_t_next(&t)) {
+ assert(*q >= 0 && *q < 256);
+ ttfenc_tab[*q].name = glyph_names[*q];
+ }
+ make_subset_tag(fd_cur);
+ } else if (is_subfont(fd_cur->fm)) {
+ charcodes = fd_cur->fm->subfont->charcodes;
+ assert(charcodes != NULL);
+
+ for (i = 0; i < 256; i++)
+ ttfenc_tab[i].code = -1;
+
+ /* take over collected characters from TeX */
+ avl_t_init(&t, fd_cur->tx_tree);
+ for (q = (int *) avl_t_first(&t, fd_cur->tx_tree); q != NULL;
+ q = (int *) avl_t_next(&t)) {
+ assert(*q >= 0 && *q < 256);
+ e = ttfenc_tab + *q;
+ e->code = charcodes[*q];
+ if (e->code == -1)
+ pdftex_warn("character %i is not mapped to any charcode", *q);
+ else {
+ assert(e->code < 0x10000);
+ sprintf(buf, "/c%4.4X", (int) e->code);
+ aa = avl_probe(fd_cur->gl_tree, xstrdup(buf));
+ assert(aa != NULL);
+ }
+ }
+ make_subset_tag(fd_cur);
+ } else
+ assert(0);
+}
+
+#define ttf_append_byte(B)\
+do {\
+ if (name_tab[i].platform_id == 3)\
+ *q++ = 0;\
+ *q++ = B;\
+} while (0)
+
+static char *strip_spaces_and_delims(char *s, int l)
+{
+ static char buf[SMALL_BUF_SIZE];
+ char *p = buf;
+ int i;
+
+ assert(l >= 0 && l < (int) sizeof(buf));
+
+ for (i = 0; i < l; s++, i++) {
+ if (*s == '(' || *s == ')' || *s == '<' || *s == '>' ||
+ *s == '[' || *s == ']' || *s == '{' || *s == '}' ||
+ *s == '/' || *s == '%' || isspace(*s))
+ continue;
+ *p++ = *s;
+ }
+ *p = 0;
+ return buf;
+}
+
+static void ttf_read_name (void)
+{
+ int i, j;
+ dirtab_entry *tab = ttf_seek_tab ("name", TTF_USHORT_SIZE);
+ char *p;
+ name_record_num = get_ushort ();
+ name_tab = xtalloc (name_record_num, name_record);
+ name_buf_size = tab->length -
+ (3 * TTF_USHORT_SIZE + name_record_num * 6 * TTF_USHORT_SIZE);
+ name_buf = xtalloc (name_buf_size, char);
+ ttf_skip (TTF_USHORT_SIZE);
+ for (i = 0; i < name_record_num; i++) {
+ name_tab[i].platform_id = get_ushort ();
+ name_tab[i].encoding_id = get_ushort ();
+ name_tab[i].language_id = get_ushort ();
+ name_tab[i].name_id = get_ushort ();
+ name_tab[i].length = get_ushort ();
+ name_tab[i].offset = get_ushort ();
+ }
+ for (p = name_buf; p - name_buf < name_buf_size; p++)
+ *p = get_char ();
+ /* look for PS font name */
+ for (i = 0; i < name_record_num; i++) {
+ if (name_tab[i].platform_id == 1 &&
+ name_tab[i].encoding_id == 0 && name_tab[i].name_id == 6) {
+ xfree(fd_cur->fontname);
+ fd_cur->fontname =
+ xstrdup(strip_spaces_and_delims(name_buf + name_tab[i].offset,
+ name_tab[i].length));
+ fd_cur->font_dim[FONTNAME_CODE].set = true;
+ break;
+ }
+ }
+ if (!fd_cur->font_dim[FONTNAME_CODE].set) {
+ for (i = 0; i < name_record_num; i++) {
+ if (name_tab[i].platform_id == 3 &&
+ (name_tab[i].encoding_id == 0 ||
+ name_tab[i].encoding_id == 1) && name_tab[i].name_id == 6) {
+ for (j = 0, p = fd_cur->fontname; j < name_tab[i].length;
+ j += 2)
+ *p++ = name_buf[name_tab[i].offset + j + 1];
+ *p = 0;
+ fd_cur->font_dim[FONTNAME_CODE].set = true;
+ break;
+ }
+ }
+ }
+}
+
+static void ttf_read_mapx (void)
+{
+ glyph_entry *glyph;
+ ttf_seek_tab ("maxp", TTF_FIXED_SIZE);
+ glyph_tab = xtalloc (1 + (glyphs_count = get_ushort ()), glyph_entry);
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++) {
+ glyph->newindex = -1;
+ glyph->newoffset = 0;
+ glyph->name_index = 0;
+ glyph->name = (char *) notdef;
+ }
+ glyph_index = xtalloc (glyphs_count, long);
+ glyph_index[0] = 0; /* index of ".notdef" glyph */
+ glyph_index[1] = 1; /* index of ".null" glyph */
+}
+
+void ttf_read_head (void)
+{
+ ttf_seek_tab ("head",
+ 2 * TTF_FIXED_SIZE + 2 * TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ upem = get_ushort ();
+ ttf_skip (16);
+ fd_cur->font_dim[FONTBBOX1_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[FONTBBOX2_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[FONTBBOX3_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[FONTBBOX4_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[FONTBBOX1_CODE].set = true;
+ fd_cur->font_dim[FONTBBOX2_CODE].set = true;
+ fd_cur->font_dim[FONTBBOX3_CODE].set = true;
+ fd_cur->font_dim[FONTBBOX4_CODE].set = true;
+ ttf_skip (2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ loca_format = get_short ();
+}
+
+void ttf_read_hhea (void)
+{
+ ttf_seek_tab ("hhea", TTF_FIXED_SIZE);
+ fd_cur->font_dim[ASCENT_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[DESCENT_CODE].val = ttf_funit(get_fword());
+ fd_cur->font_dim[ASCENT_CODE].set = true;
+ fd_cur->font_dim[DESCENT_CODE].set = true;
+ ttf_skip (TTF_FWORD_SIZE + TTF_UFWORD_SIZE + 3 * TTF_FWORD_SIZE +
+ 8 * TTF_SHORT_SIZE);
+ nhmtxs = get_ushort ();
+}
+
+void ttf_read_pclt (void)
+{
+ if (ttf_name_lookup ("PCLT", false) == NULL)
+ return;
+ ttf_seek_tab ("PCLT", TTF_FIXED_SIZE + TTF_ULONG_SIZE + TTF_USHORT_SIZE);
+ fd_cur->font_dim[XHEIGHT_CODE].val = ttf_funit(get_ushort());
+ ttf_skip(2 * TTF_USHORT_SIZE);
+ fd_cur->font_dim[CAPHEIGHT_CODE].val = ttf_funit(get_ushort());
+ fd_cur->font_dim[XHEIGHT_CODE].set = true;
+ fd_cur->font_dim[CAPHEIGHT_CODE].set = true;
+}
+
+static void ttf_read_hmtx (void)
+{
+ glyph_entry *glyph;
+ TTF_UFWORD last_advWidth;
+ ttf_seek_tab ("hmtx", 0);
+ for (glyph = glyph_tab; glyph - glyph_tab < nhmtxs; glyph++) {
+ glyph->advWidth = get_ufword ();
+ glyph->lsb = get_ufword ();
+ }
+ if (nhmtxs < glyphs_count) {
+ last_advWidth = glyph[-1].advWidth;
+ for (; glyph - glyph_tab < glyphs_count; glyph++) {
+ glyph->advWidth = last_advWidth;
+ glyph->lsb = get_ufword ();
+ }
+ }
+}
+
+void ttf_read_post (void)
+{
+ int k, nnames;
+ long length;
+ long int_part, frac_part;
+ int sign = 1;
+ TTF_FIXED italic_angle;
+ char *p;
+ glyph_entry *glyph;
+ const dirtab_entry *tab = ttf_seek_tab ("post", 0);
+ post_format = get_fixed ();
+ italic_angle = get_fixed ();
+ int_part = italic_angle >> 16;
+ if (int_part > 0x7FFF) { /* a negative number */
+ int_part = 0x10000 - int_part;
+ sign = -1;
+ }
+ frac_part = italic_angle % 0x10000;
+ fd_cur->font_dim[ITALIC_ANGLE_CODE].val =
+ sign * (int_part + frac_part * 1.0 / 0x10000);
+ fd_cur->font_dim[ITALIC_ANGLE_CODE].set = true;
+ if (glyph_tab == NULL)
+ return; /* being called from writeotf() */
+ ttf_skip (2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
+ switch (post_format) {
+ case 0x10000:
+ for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
+ glyph->name = (char *) mac_glyph_names[glyph - glyph_tab];
+ glyph->name_index = glyph - glyph_tab;
+ }
+ break;
+ case 0x20000:
+ nnames = get_ushort (); /* some fonts have this value different from nglyphs */
+ for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++)
+ glyph->name_index = get_ushort ();
+ /*length = tab->length - (xftell (INFILE, cur_file_name) - tab->offset);*/
+ length = tab->length - (ttf_curbyte - tab->offset);
+ glyph_name_buf = xtalloc (length, char);
+ for (p = glyph_name_buf; p - glyph_name_buf < length;) {
+ for (k = get_byte (); k > 0; k--)
+ *p++ = get_char ();
+ *p++ = 0;
+ }
+ for (glyph = glyph_tab; glyph - glyph_tab < nnames; glyph++) {
+ if (glyph->name_index < NMACGLYPHS)
+ glyph->name = (char *) mac_glyph_names[glyph->name_index];
+ else {
+ p = glyph_name_buf;
+ k = glyph->name_index - NMACGLYPHS;
+ for (; k > 0; k--)
+ p = strend (p) + 1;
+ glyph->name = p;
+ }
+ }
+ break;
+ case 0x00030000:
+ for (glyph = glyph_tab; glyph - glyph_tab < NMACGLYPHS; glyph++) {
+ glyph->name_index = glyph - glyph_tab;
+ }
+ break;
+ default:
+ pdftex_fail ("unsupported format (%.8X) of `post' table",
+ (unsigned int) post_format);
+ }
+}
+
+static void ttf_read_loca (void)
+{
+ glyph_entry *glyph;
+ ttf_seek_tab ("loca", 0);
+ if (loca_format != 0)
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
+ glyph->offset = get_ulong ();
+ else
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count + 1; glyph++)
+ glyph->offset = get_ushort () << 1;
+}
+
+void ttf_read_tabdir (void)
+{
+ int i;
+ dirtab_entry *tab;
+ ttf_skip (TTF_FIXED_SIZE); /* ignore the sfnt number */
+ dir_tab = xtalloc (ntabs = get_ushort (), dirtab_entry);
+ ttf_skip (3 * TTF_USHORT_SIZE);
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ for (i = 0; i < 4; i++)
+ tab->tag[i] = get_char ();
+ tab->checksum = get_ulong ();
+ tab->offset = get_ulong ();
+ tab->length = get_ulong ();
+ }
+}
+
+static ttf_cmap_entry *ttf_read_cmap (char *ttf_name, int pid, int eid,
+ boolean warn)
+{
+ seg_entry *seg_tab, *s;
+ TTF_USHORT *glyphId, format, segCount;
+ TTF_USHORT ncmapsubtabs, tmp_pid, tmp_eid;
+ TTF_ULONG cmap_offset, tmp_offset;
+ long n, i, k, length, index;
+ ttf_cmap_entry tmp_e, *p;
+ void **aa;
+
+ /* loop up in ttf_cmap_tree first, return if found */
+ tmp_e.ttf_name = ttf_name;
+ tmp_e.pid = pid;
+ tmp_e.eid = eid;
+ if (ttf_cmap_tree == NULL) {
+ ttf_cmap_tree = avl_create (comp_ttf_cmap_entry, NULL, &avl_xallocator);
+ assert (ttf_cmap_tree != NULL);
+ }
+ p = (ttf_cmap_entry *) avl_find (ttf_cmap_tree, &tmp_e);
+ if (p != NULL)
+ return p;
+
+ /* not found, have to read it */
+ ttf_seek_tab ("cmap", TTF_USHORT_SIZE); /* skip the table vesrion number (=0) */
+ ncmapsubtabs = get_ushort ();
+ /* cmap_offset = xftell (INFILE, cur_file_name) - 2 * TTF_USHORT_SIZE;*/
+ cmap_offset = ttf_curbyte - 2 * TTF_USHORT_SIZE;
+ cmap_tab = xtalloc (ncmapsubtabs, cmap_entry);
+ for (i = 0; i < ncmapsubtabs; ++i) {
+ tmp_pid = get_ushort ();
+ tmp_eid = get_ushort ();
+ tmp_offset = get_ulong ();
+ if (tmp_pid == pid && tmp_eid == eid) {
+ ttf_seek_off (cmap_offset + tmp_offset);
+ format = get_ushort ();
+ if (format == 4)
+ goto read_cmap_format_4;
+ else {
+ if (warn)
+ pdftex_warn ("cmap format %i unsupported", format);
+ return NULL;
+ }
+ }
+ }
+ if (warn)
+ pdftex_warn ("cannot find cmap subtable for (pid,eid) = (%i, %i)",
+ pid, eid);
+ return NULL;
+ read_cmap_format_4:
+ /* initialize the new entry */
+ p = new_ttf_cmap_entry ();
+ p->ttf_name = xstrdup (ttf_name);
+ p->pid = pid;
+ p->eid = eid;
+ p->table = xtalloc (0x10000, short);
+ for (i = 0; i < 0x10000; ++i)
+ p->table[i] = -1; /* unassigned yet */
+
+ /* read the subtable */
+ length = get_ushort (); /* length of subtable */
+ (void) get_ushort (); /* skip the version number */
+ segCount = get_ushort () / 2;
+ (void) get_ushort (); /* skip searchRange */
+ (void) get_ushort (); /* skip entrySelector */
+ (void) get_ushort (); /* skip rangeShift */
+ seg_tab = xtalloc (segCount, seg_entry);
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->endCode = get_ushort ();
+ (void) get_ushort (); /* skip reversedPad */
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->startCode = get_ushort ();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idDelta = get_ushort ();
+ for (s = seg_tab; s - seg_tab < segCount; s++)
+ s->idRangeOffset = get_ushort ();
+ length -= 8 * TTF_USHORT_SIZE + 4 * segCount * TTF_USHORT_SIZE;
+ n = length / TTF_USHORT_SIZE; /* number of glyphID's */
+ glyphId = xtalloc (n, TTF_USHORT);
+ for (i = 0; i < n; i++)
+ glyphId[i] = get_ushort ();
+ for (s = seg_tab; s - seg_tab < segCount; s++) {
+ for (i = s->startCode; i <= s->endCode; i++) {
+ if (i == 0xFFFF)
+ break;
+ if (s->idRangeOffset != 0xFFFF) {
+ if (s->idRangeOffset == 0)
+ index = (s->idDelta + i) & 0xFFFF;
+ else {
+ k = (i - s->startCode) + s->idRangeOffset / 2 +
+ (s - seg_tab) - segCount;
+ assert (k >= 0 && k < n);
+ index = glyphId[k];
+ if (index != 0)
+ index = (index + s->idDelta) & 0xFFFF;
+ }
+ if (index >= glyphs_count)
+ pdftex_fail ("cmap: glyph index %li out of range [0..%i)",
+ index, glyphs_count);
+ if (p->table[i] != -1)
+ pdftex_warn
+ ("cmap: multiple glyphs are mapped to unicode %.4lX, "
+ "only %i will be used (glyph %li being ignored)", i,
+ p->table[i], index);
+ else
+ p->table[i] = index;
+ }
+ }
+ }
+ xfree (seg_tab);
+ xfree (glyphId);
+ aa = avl_probe (ttf_cmap_tree, p);
+ assert (aa != NULL);
+ return p;
+}
+
+static void ttf_read_font (void)
+{
+ ttf_read_tabdir ();
+ if (ttf_name_lookup ("PCLT", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup ("fpgm", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup ("cvt ", false) == NULL)
+ new_ntabs--;
+ if (ttf_name_lookup ("prep", false) == NULL)
+ new_ntabs--;
+ ttf_read_mapx ();
+ ttf_read_head ();
+ ttf_read_hhea ();
+ ttf_read_pclt ();
+ ttf_read_hmtx ();
+ ttf_read_post ();
+ ttf_read_loca ();
+ ttf_read_name ();
+}
+
+static void ttf_reset_chksm (dirtab_entry * tab)
+{
+ checksum = 0;
+ tab_length = 0;
+ tmp_ulong = 0;
+ tab->offset = ttf_offset ();
+ if (tab->offset % 4 != 0)
+ pdftex_warn ("offset of `%4.4s' is not a multiple of 4", tab->tag);
+}
+
+
+static void ttf_set_chksm (dirtab_entry * tab)
+{
+ tab->length = ttf_offset () - tab->offset;
+ tab->checksum = ttf_getchksm ();
+}
+
+static void ttf_copytab (const char *name)
+{
+ long i;
+ dirtab_entry *tab = ttf_seek_tab (name, 0);
+ ttf_reset_chksm (tab);
+ for (i = tab->length; i > 0; i--)
+ copy_char ();
+ ttf_set_chksm (tab);
+}
+
+#define BYTE_ENCODING_LENGTH \
+ ((256)*TTF_BYTE_SIZE + 3*TTF_USHORT_SIZE)
+
+static void ttf_byte_encoding (void)
+{
+ ttfenc_entry *e;
+ (void) put_ushort (0); /* format number (0: byte encoding table) */
+ (void) put_ushort (BYTE_ENCODING_LENGTH); /* length of table */
+ (void) put_ushort (0); /* version number */
+ for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
+ if (e->newindex < 256) {
+ put_byte (e->newindex);
+ } else {
+ if (e->name != notdef)
+ pdftex_warn
+ ("glyph `%s' has been mapped to `%s' in `ttf_byte_encoding' cmap table",
+ e->name, notdef);
+ put_byte (0); /* notdef */
+ }
+}
+
+#define TRIMMED_TABLE_MAP_LENGTH (TTF_USHORT_SIZE*(5 + (256)))
+
+static void ttf_trimmed_table_map (void)
+{
+ ttfenc_entry *e;
+ (void) put_ushort (6); /* format number (6): trimmed table mapping */
+ (void) put_ushort (TRIMMED_TABLE_MAP_LENGTH);
+ (void) put_ushort (0); /* version number (0) */
+ (void) put_ushort (0); /* first character code */
+ (void) put_ushort (256); /* number of character code in table */
+ for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
+ (void) put_ushort (e->newindex);
+}
+
+#define SEG_MAP_DELTA_LENGTH ((16 + (256))*TTF_USHORT_SIZE)
+
+static void ttf_seg_map_delta (void)
+{
+ ttfenc_entry *e;
+ (void) put_ushort (4); /* format number (4: segment mapping to delta values) */
+ (void) put_ushort (SEG_MAP_DELTA_LENGTH);
+ (void) put_ushort (0); /* version number */
+ (void) put_ushort (4); /* 2*segCount */
+ (void) put_ushort (4); /* searchRange */
+ (void) put_ushort (1); /* entrySelector */
+ (void) put_ushort (0); /* rangeShift */
+ (void) put_ushort (0xF0FF); /* endCount[0] */
+ (void) put_ushort (0xFFFF); /* endCount[1] */
+ (void) put_ushort (0); /* reversedPad */
+ (void) put_ushort (0xF000); /* startCount[0] */
+ (void) put_ushort (0xFFFF); /* startCount[1] */
+ (void) put_ushort (0); /* idDelta[0] */
+ (void) put_ushort (1); /* idDelta[1] */
+ (void) put_ushort (2 * TTF_USHORT_SIZE); /* idRangeOffset[0] */
+ (void) put_ushort (0); /* idRangeOffset[1] */
+ for (e = ttfenc_tab; e - ttfenc_tab < 256; e++)
+ (void) put_ushort (e->newindex);
+}
+
+#define CMAP_ENTRY_LENGTH (2*TTF_USHORT_SIZE + TTF_ULONG_SIZE)
+
+static void ttf_select_cmap (void)
+{
+ assert (sizeof (new_cmap_tab) <= NEW_CMAP_SIZE * sizeof (cmap_entry));
+ new_cmap_tab[0].platform_id = 1; /* Macintosh */
+ new_cmap_tab[0].encoding_id = 0; /* Symbol; ignore code page */
+ new_cmap_tab[0].format = new_glyphs_count < 256 ? 0 /* byte encoding */
+ : 6; /* trimmed table mapping */
+ new_cmap_tab[1].platform_id = 3; /* Microsoft */
+ new_cmap_tab[1].encoding_id = 0; /* Symbol; ignore code page */
+ new_cmap_tab[1].format = 4; /* segment mapping to delta */
+}
+
+static void ttf_write_cmap (void)
+{
+ cmap_entry *ce;
+ long offset;
+ dirtab_entry *tab = ttf_name_lookup ("cmap", true);
+ ttf_select_cmap ();
+ ttf_reset_chksm (tab);
+ (void) put_ushort (0); /* table version number (0) */
+ (void) put_ushort (NEW_CMAP_SIZE); /* number of encoding tables */
+ offset = 2 * TTF_USHORT_SIZE + NEW_CMAP_SIZE * CMAP_ENTRY_LENGTH;
+ for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
+ ce->offset = offset;
+ switch (ce->format) {
+ case 0:
+ offset += BYTE_ENCODING_LENGTH;
+ break;
+ case 4:
+ offset += SEG_MAP_DELTA_LENGTH;
+ break;
+ case 6:
+ offset += TRIMMED_TABLE_MAP_LENGTH;
+ break;
+ default:
+ pdftex_fail ("invalid format (it should not have happened)");
+ }
+ (void) put_ushort (ce->platform_id);
+ (void) put_ushort (ce->encoding_id);
+ put_ulong (ce->offset);
+ }
+ for (ce = new_cmap_tab; ce - new_cmap_tab < NEW_CMAP_SIZE; ce++) {
+ switch (ce->format) {
+ case 0:
+ ttf_byte_encoding ();
+ break;
+ case 4:
+ ttf_seg_map_delta ();
+ break;
+ case 6:
+ ttf_trimmed_table_map ();
+ break;
+ }
+ }
+ ttf_set_chksm (tab);
+}
+
+static int prepend_subset_tags (int index, char *p)
+{
+ const boolean is_unicode = (name_tab[index].platform_id == 3);
+ int i;
+ assert (index > 0 && index < name_record_num && fd_cur->subset_tag != NULL);
+ if (is_unicode) {
+ for (i = 0; i < 6; ++i) {
+ *p++ = 0;
+ *p++ = fd_cur->subset_tag[i];
+ }
+ *p++ = 0;
+ *p++ = '+';
+ return 14;
+ } else {
+ strncpy (p, fd_cur->subset_tag, 6);
+ p += 6;
+ *p++ = '+';
+ return 7;
+ }
+}
+
+
+static void ttf_write_name (void)
+{
+ int i, l;
+ char *p;
+ int new_name_buf_size;
+ char *new_name_buf;
+ name_record *n;
+ dirtab_entry *tab = ttf_name_lookup ("name", true);
+ if (is_subsetted (fd_cur->fm)) {
+ l = 0;
+ for (i = 0; i < name_record_num; i++)
+ l += name_tab[i].length + 14; /* maximum lengh of new stogare area */
+ new_name_buf = xtalloc (l, char);
+ /* additional space for subset tags */
+ p = new_name_buf;
+ for (i = 0; i < name_record_num; i++) {
+ n = name_tab + i;
+ n->new_offset = p - new_name_buf;
+ if ((n->name_id == 1 || n->name_id == 3 ||
+ n->name_id == 4 || n->name_id == 6) &&
+ ((n->platform_id == 1 && n->encoding_id == 0) ||
+ (n->platform_id == 3 && n->encoding_id == 0) ||
+ (n->platform_id == 3 && n->encoding_id == 1))) {
+ l = prepend_subset_tags (i, p);
+ p += l;
+ } else
+ l = 0;
+ memcpy (p, name_buf + n->offset, n->length);
+ p += n->length;
+ n->new_length = n->length + l;
+ }
+ new_name_buf_size = p - new_name_buf;
+ } else {
+ new_name_buf = name_buf;
+ new_name_buf_size = name_buf_size;
+ }
+ ttf_reset_chksm (tab);
+ (void) put_ushort (0); /* Format selector */
+ (void) put_ushort (name_record_num);
+ (void) put_ushort (3 * TTF_USHORT_SIZE +
+ name_record_num * 6 * TTF_USHORT_SIZE);
+ for (i = 0; i < name_record_num; i++) {
+ (void) put_ushort (name_tab[i].platform_id);
+ (void) put_ushort (name_tab[i].encoding_id);
+ (void) put_ushort (name_tab[i].language_id);
+ (void) put_ushort (name_tab[i].name_id);
+ (void) put_ushort (name_tab[i].new_length);
+ (void) put_ushort (name_tab[i].new_offset);
+ }
+ for (p = new_name_buf; p - new_name_buf < new_name_buf_size; p++)
+ put_char (*p);
+ ttf_set_chksm (tab);
+ if (new_name_buf != name_buf)
+ xfree (new_name_buf);
+}
+
+static void ttf_write_dirtab (void)
+{
+ dirtab_entry *tab;
+ TTF_ULONG i, k;
+ char *p;
+ const integer save_offset = ttf_offset ();
+ ttf_seek_outbuf (TABDIR_OFF);
+ if (is_subsetted (fd_cur->fm)) {
+ for (i = 0; i < DEFAULT_NTABS; i++) {
+ tab = ttf_name_lookup (newtabnames[i], false);
+ if (tab == NULL)
+ continue;
+ for (k = 0; k < 4; k++)
+ put_char (tab->tag[k]);
+ put_ulong (tab->checksum);
+ put_ulong (tab->offset);
+ put_ulong (tab->length);
+ }
+ } else {
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ for (k = 0; k < 4; k++)
+ put_char (tab->tag[k]);
+ put_ulong (tab->checksum);
+ put_ulong (tab->offset);
+ put_ulong (tab->length);
+ }
+ }
+ /* adjust checkSumAdjustment */
+ tmp_ulong = 0;
+ checksum = 0;
+ for (p = fb_array, i = 0; i < (unsigned) save_offset;) {
+ tmp_ulong = (tmp_ulong << 8) + *p++;
+ i++;
+ if (i % 4 == 0) {
+ checksum += tmp_ulong;
+ tmp_ulong = 0;
+ }
+ }
+ if (i % 4 != 0) {
+ pdftex_warn ("font length is not a multiple of 4 (%li)", i);
+ checksum <<= 8 * (4 - i % 4);
+ }
+ k = 0xB1B0AFBA - checksum;
+ ttf_seek_outbuf (checkSumAdjustment_offset);
+ put_ulong (k);
+ ttf_seek_outbuf (save_offset);
+}
+
+static void ttf_write_glyf (void)
+{
+ long *id, k;
+ TTF_USHORT idx;
+ TTF_USHORT flags;
+ dirtab_entry *tab = ttf_name_lookup ("glyf", true);
+ const long glyf_offset = tab->offset;
+ const long new_glyf_offset = ttf_offset ();
+ ttf_reset_chksm (tab);
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph_tab[*id].newoffset = ttf_offset () - new_glyf_offset;
+ if (glyph_tab[*id].offset != glyph_tab[*id + 1].offset) {
+ ttf_seek_off (glyf_offset + glyph_tab[*id].offset);
+ k = copy_short ();
+ ttf_ncopy (4 * TTF_FWORD_SIZE);
+ if (k < 0) {
+ do {
+ flags = copy_ushort ();
+ idx = get_ushort ();
+ if (glyph_tab[idx].newindex < 0) {
+ glyph_tab[idx].newindex = new_glyphs_count;
+ glyph_index[new_glyphs_count++] = idx;
+ /*
+ N.B.: Here we change `new_glyphs_count',
+ which appears in the condition of the `for' loop
+ */
+ }
+ (void) put_ushort (glyph_tab[idx].newindex);
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ ttf_ncopy (2 * TTF_SHORT_SIZE);
+ else
+ ttf_ncopy (TTF_USHORT_SIZE);
+ if (flags & WE_HAVE_A_SCALE)
+ ttf_ncopy (TTF_F2DOT14_SIZE);
+ else if (flags & WE_HAVE_AN_X_AND_Y_SCALE)
+ ttf_ncopy (2 * TTF_F2DOT14_SIZE);
+ else if (flags & WE_HAVE_A_TWO_BY_TWO)
+ ttf_ncopy (4 * TTF_F2DOT14_SIZE);
+ } while (flags & MORE_COMPONENTS);
+ if (flags & WE_HAVE_INSTRUCTIONS)
+ ttf_ncopy (copy_ushort ());
+ } else
+ ttf_ncopy (glyph_tab[*id + 1].offset - glyph_tab[*id].offset -
+ TTF_USHORT_SIZE - 4 * TTF_FWORD_SIZE);
+ }
+ }
+ last_glyf_offset = ttf_offset () - new_glyf_offset;
+ ttf_set_chksm (tab);
+}
+
+static void ttf_reindex_glyphs(void)
+{
+ ttfenc_entry *e;
+ glyph_entry *glyph;
+ int index;
+ short *t;
+ ttf_cmap_entry *cmap = NULL;
+ boolean cmap_not_found = false;
+
+ /*
+ * reindexing glyphs: we append index of used glyphs to `glyph_index'
+ * while going through `ttfenc_tab'. After appending a new entry to
+ * `glyph_index' we set field `newindex' of corresponding entries in both
+ * `glyph_tab' and `ttfenc_tab' to the newly created index
+ */
+ for (e = ttfenc_tab; e - ttfenc_tab < 256; e++) {
+ e->newindex = 0; /* index of ".notdef" glyph */
+
+ /* handle case of subfonts first */
+ if (is_subfont(fd_cur->fm)) {
+ if (e->code == -1)
+ continue;
+ assert(fd_cur->fm->pid != -1 && fd_cur->fm->eid != -1);
+ if (cmap == NULL && !cmap_not_found) {
+ cmap =
+ ttf_read_cmap(fd_cur->fm->ff_name, fd_cur->fm->pid,
+ fd_cur->fm->eid, true);
+ if (cmap == NULL)
+ cmap_not_found = true;
+ }
+ if (cmap == NULL)
+ continue;
+ t = cmap->table;
+ assert(t != NULL && e->code < 0x10000);
+ if (t[e->code] < 0) {
+ pdftex_warn
+ ("subfont %s: wrong mapping: character %li --> 0x%4.4lX --> .notdef",
+ fd_cur->fm->tfm_name, (long) (e - ttfenc_tab), e->code);
+ continue;
+ }
+ assert(t[e->code] >= 0 && t[e->code] < glyphs_count); /* t has been read from ttf */
+ glyph = glyph_tab + t[e->code];
+ goto append_new_glyph;
+ }
+
+ /* handle case of reencoded fonts */
+ if (e->name == notdef)
+ continue;
+ /* scan form `index123' */
+ if (sscanf(e->name, GLYPH_PREFIX_INDEX "%i", &index) == 1) {
+ if (index >= glyphs_count) {
+ pdftex_warn("`%s' out of valid range [0..%i)",
+ e->name, glyphs_count);
+ continue;
+ }
+ glyph = glyph_tab + index;
+ goto append_new_glyph;
+ }
+ /* scan form `uniABCD' */
+ if (sscanf(e->name, GLYPH_PREFIX_UNICODE "%X", &index) == 1) {
+ if (cmap == NULL && !cmap_not_found) {
+ /* need to read the unicode mapping, ie (pid,eid) = (3,1) or (0,3) */
+ cmap = ttf_read_cmap(fd_cur->fm->ff_name, 3, 1, false);
+ if (cmap == NULL)
+ cmap = ttf_read_cmap(fd_cur->fm->ff_name, 0, 3, false);
+ if (cmap == NULL) {
+ pdftex_warn
+ ("no unicode mapping found, all `uniXXXX' names will be ignored");
+ cmap_not_found = true; /* once only */
+ }
+ }
+ if (cmap == NULL)
+ continue;
+ t = cmap->table;
+ assert(t != NULL);
+ if (t[index] != -1) {
+ if (t[index] >= glyphs_count) {
+ pdftex_warn
+ ("`%s' is mapped to index %i which is out of valid range [0..%i)",
+ e->name, t[index], glyphs_count);
+ continue;
+ }
+ glyph = glyph_tab + t[index];
+ goto append_new_glyph;
+ } else {
+ pdftex_warn("`unicode %s%.4X' is not mapped to any glyph",
+ GLYPH_PREFIX_UNICODE, index);
+ continue;
+ }
+ }
+ /* look up by name */
+ for (glyph = glyph_tab; glyph - glyph_tab < glyphs_count; glyph++)
+ if (glyph->name != notdef && strcmp(glyph->name, e->name) == 0)
+ break;
+ if (!(glyph - glyph_tab < glyphs_count)) {
+ pdftex_warn("glyph `%s' not found", e->name);
+ continue;
+ }
+ append_new_glyph:
+ assert(glyph > glyph_tab && glyph - glyph_tab < glyphs_count);
+ if (glyph->newindex < 0) {
+ glyph_index[new_glyphs_count] = (short) (glyph - glyph_tab);
+ glyph->newindex = new_glyphs_count;
+ new_glyphs_count++;
+ }
+ e->newindex = glyph->newindex;
+ }
+}
+
+static void ttf_write_head ()
+{
+ dirtab_entry *tab;
+ tab = ttf_seek_tab ("head", 0);
+ ttf_reset_chksm (tab);
+ ttf_ncopy (2 * TTF_FIXED_SIZE);
+ checkSumAdjustment_offset = ttf_offset ();
+ put_ulong (0);
+ ttf_skip (TTF_ULONG_SIZE); /* skip checkSumAdjustment */
+ ttf_ncopy (TTF_ULONG_SIZE + 2 * TTF_USHORT_SIZE + 16 +
+ 4 * TTF_FWORD_SIZE + 2 * TTF_USHORT_SIZE + TTF_SHORT_SIZE);
+ if (is_subsetted(fd_cur->fm)) {
+ (void) put_short (loca_format);
+ (void) put_short (0);
+ } else
+ ttf_ncopy (2 * TTF_SHORT_SIZE);
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_hhea (void)
+{
+ dirtab_entry *tab;
+ tab = ttf_seek_tab ("hhea", 0);
+ ttf_reset_chksm (tab);
+ ttf_ncopy (TTF_FIXED_SIZE + 3 * TTF_FWORD_SIZE + TTF_UFWORD_SIZE +
+ 3 * TTF_FWORD_SIZE + 8 * TTF_SHORT_SIZE);
+ (void) put_ushort (new_glyphs_count);
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_htmx (void)
+{
+ long *id;
+ dirtab_entry *tab = ttf_seek_tab ("hmtx", 0);
+ ttf_reset_chksm (tab);
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ put_ufword (glyph_tab[*id].advWidth);
+ put_ufword (glyph_tab[*id].lsb);
+ }
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_loca (void)
+{
+ long *id;
+ dirtab_entry *tab = ttf_seek_tab ("loca", 0);
+ ttf_reset_chksm (tab);
+ loca_format = 0;
+ if (last_glyf_offset >= 0x00020000 || (last_glyf_offset & 1))
+ loca_format = 1;
+ else
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ if (glyph_tab[*id].newoffset & 1) {
+ loca_format = 1;
+ break;
+ }
+ if (loca_format != 0) {
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ put_ulong (glyph_tab[*id].newoffset);
+ put_ulong (last_glyf_offset);
+ } else {
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++)
+ (void) put_ushort (glyph_tab[*id].newoffset / 2);
+ (void) put_ushort (last_glyf_offset / 2);
+ }
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_mapx (void)
+{
+ dirtab_entry *tab = ttf_seek_tab ("maxp", TTF_FIXED_SIZE + TTF_USHORT_SIZE);
+ ttf_reset_chksm (tab);
+ put_fixed (0x00010000);
+ (void) put_ushort (new_glyphs_count);
+ ttf_ncopy (13 * TTF_USHORT_SIZE);
+ ttf_set_chksm (tab);
+}
+
+static void ttf_write_OS2 (void)
+{
+ dirtab_entry *tab = ttf_seek_tab ("OS/2", 0);
+ TTF_USHORT version;
+ ttf_reset_chksm (tab);
+ version = get_ushort ();
+ if (version > 3)
+ pdftex_fail ("unknown version of OS/2 table (%.4X)", version);
+ (void) put_ushort (0x0001); /* fix version to 1 */
+ ttf_ncopy (2 * TTF_USHORT_SIZE + 13 * TTF_SHORT_SIZE + 10 * TTF_BYTE_SIZE);
+ ttf_skip (4 * TTF_ULONG_SIZE); /* ulUnicodeRange 1--4 */
+ put_ulong (0x00000003); /* Basic Latin + Latin-1 Supplement (0x0000--0x00FF) */
+ put_ulong (0x10000000); /* Private Use (0xE000--0xF8FF) */
+ put_ulong (0x00000000);
+ put_ulong (0x00000000);
+ ttf_ncopy (4 * TTF_CHAR_SIZE + TTF_USHORT_SIZE); /* achVendID + fsSelection */
+ ttf_skip (2 * TTF_USHORT_SIZE);
+ (void) put_ushort (0x0000); /* usFirstCharIndex */
+ (void) put_ushort (0xF0FF); /* usLastCharIndex */
+ ttf_ncopy (5 * TTF_USHORT_SIZE);
+ /* for version 0 the OS/2 table ends here, the rest is for version 1 */
+ put_ulong (0x80000000); /* Symbol Character Set---don't use any code page */
+ put_ulong (0x00000000);
+ ttf_set_chksm (tab);
+}
+
+static boolean unsafe_name (char *s)
+{
+ const char **p;
+ for (p = ambiguous_names; *p != NULL; p++)
+ if (strcmp (s, *p) == 0)
+ return true;
+ return false;
+}
+
+static void ttf_write_post (void)
+{
+ dirtab_entry *tab = ttf_seek_tab ("post", TTF_FIXED_SIZE);
+ glyph_entry *glyph;
+ char *s;
+ long *id;
+ int l;
+ ttf_reset_chksm (tab);
+ if (!fd_cur->write_ttf_glyph_names || post_format == 0x00030000) {
+ put_fixed (0x00030000);
+ ttf_ncopy (TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
+ } else {
+ put_fixed (0x00020000);
+ ttf_ncopy (TTF_FIXED_SIZE + 2 * TTF_FWORD_SIZE + 5 * TTF_ULONG_SIZE);
+ (void) put_ushort (new_glyphs_count);
+ k = 0;
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph = glyph_tab + *id;
+ if (glyph->name_index >= NMACGLYPHS || unsafe_name (glyph->name))
+ glyph->name_index = NMACGLYPHS + k++;
+ (void) put_ushort (glyph->name_index);
+ }
+ for (id = glyph_index; id - glyph_index < new_glyphs_count; id++) {
+ glyph = glyph_tab + *id;
+ if (glyph->name_index >= NMACGLYPHS) {
+ s = glyph->name;
+ l = strlen (s);
+ put_byte (l);
+ while (l-- > 0)
+ put_char (*s++);
+ }
+ }
+ }
+ ttf_set_chksm (tab);
+}
+
+static void ttf_init_font (int n)
+{
+ int i, k;
+ for (i = 1, k = 0; i <= n; i <<= 1, k++);
+ put_fixed (0x00010000); /* font version */
+ (void) put_ushort (n); /* number of tables */
+ (void) put_ushort (i << 3); /* search range */
+ (void) put_ushort (k - 1); /* entry selector */
+ (void) put_ushort ((n << 4) - (i << 3)); /* range shift */
+ ttf_seek_outbuf (TABDIR_OFF + n * 4 * TTF_ULONG_SIZE);
+}
+
+static void ttf_subset_font (void)
+{
+ ttf_init_font (new_ntabs);
+ if (ttf_name_lookup ("PCLT", false) != NULL)
+ ttf_copytab ("PCLT");
+ if (ttf_name_lookup ("fpgm", false) != NULL)
+ ttf_copytab ("fpgm");
+ if (ttf_name_lookup ("cvt ", false) != NULL)
+ ttf_copytab ("cvt ");
+ if (ttf_name_lookup ("prep", false) != NULL)
+ ttf_copytab ("prep");
+ ttf_reindex_glyphs ();
+ ttf_write_glyf ();
+ ttf_write_loca ();
+ ttf_write_OS2 ();
+ ttf_write_head ();
+ ttf_write_hhea ();
+ ttf_write_htmx ();
+ ttf_write_mapx ();
+ ttf_write_name ();
+ ttf_write_post ();
+ ttf_write_cmap ();
+ ttf_write_dirtab ();
+}
+
+static void ttf_copy_font (void)
+{
+ dirtab_entry *tab;
+ ttf_init_font (ntabs);
+ for (tab = dir_tab; tab - dir_tab < ntabs; tab++) {
+ if (strncmp (tab->tag, "head", 4) == 0)
+ ttf_write_head ();
+ else
+ ttf_copytab (tab->tag);
+ }
+ ttf_write_dirtab ();
+}
+
+void writettf(fd_entry * fd)
+{
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ fd_cur = fd; /* fd_cur is global inside writettf.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_truetype(fd_cur->fm));
+ assert(is_included(fd_cur->fm));
+
+ set_cur_file_name(fd_cur->fm->ff_name);
+
+ if (is_subsetted(fd_cur->fm) && (fd_cur->fe == NULL)
+ && !is_subfont(fd_cur->fm)) {
+ pdftex_warn ("Subset TrueType must be a reencoded or a subfont");
+ cur_file_name = NULL;
+ return;
+ }
+ ttf_curbyte=0;
+ ttf_size=0;
+ callback_id=callback_defined(find_truetype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+
+ callback_id=callback_defined(read_truetype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &ttf_buffer,&ttf_size) &&
+ file_opened && ttf_size>0) {
+ } else {
+ pdftex_fail ("cannot open TrueType font file for reading");
+ }
+ } else {
+ if (!ttf_open ()) {
+ pdftex_fail ("cannot open TrueType font file for reading");
+ }
+ ttf_read_file();
+ ttf_close();
+ }
+ cur_file_name = (char *) nameoffile + 1;
+ if (tracefilenames) {
+ if (is_subsetted(fd_cur->fm))
+ tex_printf ("<%s", cur_file_name);
+ else
+ tex_printf ("<<%s", cur_file_name);
+ }
+ fd_cur->ff_found = true;
+ new_glyphs_count = 2;
+ new_ntabs = DEFAULT_NTABS;
+ dir_tab = NULL;
+ glyph_tab = NULL;
+ glyph_index = NULL;
+ glyph_name_buf = NULL;
+ name_tab = NULL;
+ name_buf = NULL;
+ ttf_read_font ();
+
+ pdf_save_offset = pdfoffset ();
+ pdf_flush ();
+
+ if (is_subsetted(fd_cur->fm)) {
+ ttf_copy_encoding ();
+ ttf_subset_font ();
+ } else
+ ttf_copy_font ();
+ ttf_length = ttf_offset ();
+
+ xfree (dir_tab);
+ xfree (glyph_tab);
+ xfree (glyph_index);
+ xfree (glyph_name_buf);
+ xfree (name_tab);
+ xfree (name_buf);
+ if (tracefilenames) {
+ if (is_subsetted (fd_cur->fm))
+ tex_printf (">");
+ else
+ tex_printf (">>");
+ }
+ cur_file_name = NULL;
+}
+
+void do_writeotf(fd_entry * fd)
+{
+ long i;
+ dirtab_entry *tab;
+ dir_tab = NULL;
+ glyph_tab = NULL;
+ if (tracefilenames)
+ tex_printf ("<<%s", cur_file_name);
+ ttf_read_tabdir ();
+ /* read font parameters */
+ if (ttf_name_lookup ("head", false) != NULL)
+ ttf_read_head ();
+ if (ttf_name_lookup ("hhea", false) != NULL)
+ ttf_read_hhea ();
+ if (ttf_name_lookup ("PCLT", false) != NULL)
+ ttf_read_pclt ();
+ if (ttf_name_lookup ("post", false) != NULL)
+ ttf_read_post ();
+ /* copy font file */
+ tab = ttf_seek_tab ("CFF ", 0);
+ for (i = tab->length; i > 0; i--)
+ copy_char ();
+ xfree (dir_tab);
+ /* ttf_close ();*/
+ if (tracefilenames)
+ tex_printf (">>");
+}
+
+void writeotf (fd_entry * fd) {
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+
+
+ fd_cur = fd; /* fd_cur is global inside writettf.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_opentype(fd_cur->fm));
+ assert(is_included(fd_cur->fm));
+
+ set_cur_file_name(fd_cur->fm->ff_name);
+ ttf_curbyte=0;
+ ttf_size=0;
+ callback_id=callback_defined(find_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &ttf_buffer,&ttf_size) &&
+ file_opened && ttf_size>0) {
+ } else {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ } else {
+ if (!otf_open ()) {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ ttf_read_file();
+ ttf_close();
+ }
+
+ cur_file_name = (char *) nameoffile + 1;
+ fd_cur->ff_found = true;
+ do_writeotf(fd);
+ cur_file_name = NULL;
+}
+
+/*
+ To calculate the checkSum for the 'head' table which itself includes the
+ checkSumAdjustment entry for the entire font, do the following:
+
+ * Set the checkSumAdjustment to 0.
+ * Calculate the checksum for all the tables including the 'head' table
+ and enter that value into the table directory.
+ * Calculate the checksum for the entire font.
+ * Subtract that value from the hex value B1B0AFBA.
+ * Store the result in checkSumAdjustment.
+
+ The checkSum for the 'head table which includes the checkSumAdjustment
+ entry for the entire font is now incorrect. That is not a problem. Do not
+ change it. An application attempting to verify that the 'head' table has
+ not changed should calculate the checkSum for that table by not including
+ the checkSumAdjustment value, and compare the result with the entry in the
+ table directory.
+
+ The table directory also includes the offset of the associated tagged
+ table from the beginning of the font file and the length of that table.
+ */
diff --git a/Build/source/texk/web2c/luatexdir/font/writettf.h b/Build/source/texk/web2c/luatexdir/font/writettf.h
new file mode 100644
index 00000000000..ecfaa2c37e3
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writettf.h
@@ -0,0 +1,172 @@
+/*
+Copyright (c) 1996-2006 Han The Thanh, <thanh@pdftex.org>
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with pdfTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writettf.h 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+typedef signed char TTF_CHAR;
+typedef unsigned char TTF_BYTE;
+typedef signed short TTF_SHORT;
+typedef unsigned short TTF_USHORT;
+typedef signed long TTF_LONG;
+typedef unsigned long TTF_ULONG;
+typedef unsigned long TTF_FIXED;
+typedef unsigned short TTF_FUNIT;
+typedef signed short TTF_FWORD;
+typedef unsigned short TTF_UFWORD;
+typedef unsigned short TTF_F2DOT14;
+
+#define TTF_CHAR_SIZE 1
+#define TTF_BYTE_SIZE 1
+#define TTF_SHORT_SIZE 2
+#define TTF_USHORT_SIZE 2
+#define TTF_LONG_SIZE 4
+#define TTF_ULONG_SIZE 4
+#define TTF_FIXED_SIZE 4
+#define TTF_FWORD_SIZE 2
+#define TTF_UFWORD_SIZE 2
+#define TTF_F2DOT14_SIZE 2
+
+#define ARG_1_AND_2_ARE_WORDS (1<<0)
+#define ARGS_ARE_XY_VALUES (1<<1)
+#define ROUND_XY_TO_GRID (1<<2)
+#define WE_HAVE_A_SCALE (1<<3)
+#define RESERVED (1<<4)
+#define MORE_COMPONENTS (1<<5)
+#define WE_HAVE_AN_X_AND_Y_SCALE (1<<6)
+#define WE_HAVE_A_TWO_BY_TWO (1<<7)
+#define WE_HAVE_INSTRUCTIONS (1<<8)
+#define USE_MY_METRICS (1<<9)
+
+#define get_type(t) ((t)ttf_getnum(t##_SIZE))
+#define ttf_skip(n) ttf_getnum(n)
+
+#define get_byte() get_type(TTF_BYTE)
+#define get_char() get_type(TTF_CHAR)
+#define get_ushort() get_type(TTF_USHORT)
+#define get_short() get_type(TTF_SHORT)
+#define get_ulong() get_type(TTF_ULONG)
+#define get_long() get_type(TTF_LONG)
+#define get_fixed() get_type(TTF_FIXED)
+#define get_funit() get_type(TTF_FUNIT)
+#define get_fword() get_type(TTF_FWORD)
+#define get_ufword() get_type(TTF_UFWORD)
+#define get_f2dot14() get_type(TTF_F2DOT14)
+
+#define put_num(t,n) ((t)ttf_putnum(t##_SIZE, n))
+
+#define put_char(n) (void)put_num(TTF_CHAR, n)
+#define put_byte(n) (void)put_num(TTF_BYTE, n)
+#define put_short(n) put_num(TTF_SHORT, n)
+#define put_ushort(n) put_num(TTF_USHORT, n)
+#define put_long(n) put_num(TTF_LONG, n)
+#define put_ulong(n) (void)put_num(TTF_ULONG, n)
+#define put_fixed(n) (void)put_num(TTF_FIXED, n)
+#define put_funit(n) put_num(TTF_FUNIT, n)
+#define put_fword(n) put_num(TTF_FWORD, n)
+#define put_ufword(n) (void)put_num(TTF_UFWORD, n)
+#define put_f2dot14(n) put_num(TTF_F2DOT14, n)
+
+#define copy_byte() put_byte(get_byte())
+#define copy_char() put_char(get_char())
+#define copy_ushort() put_ushort(get_ushort())
+#define copy_short() put_short(get_short())
+#define copy_ulong() put_ulong(get_ulong())
+#define copy_long() put_long(get_long())
+#define copy_fixed() put_fixed(get_fixed())
+#define copy_funit() put_funit(get_funit())
+#define copy_fword() put_fword(get_fword())
+#define copy_ufword() put_ufword(get_ufword())
+#define copy_f2dot14() put_f2dot14(get_f2dot14())
+
+#define is_unicode_mapping(e) \
+ (e->platform_id == 0 || (e->platform_id == 3 || e->encoding_id == 1))
+
+
+#define NMACGLYPHS 258
+#define TABDIR_OFF 12
+#define ENC_BUF_SIZE 1024
+
+#define GLYPH_PREFIX_INDEX "index"
+#define GLYPH_PREFIX_UNICODE "uni"
+
+typedef struct {
+ char tag[4];
+ TTF_ULONG checksum;
+ TTF_ULONG offset;
+ TTF_ULONG length;
+} dirtab_entry;
+
+typedef struct {
+ TTF_USHORT platform_id;
+ TTF_USHORT encoding_id;
+ TTF_ULONG offset;
+ TTF_USHORT format;
+} cmap_entry;
+
+typedef struct {
+ TTF_USHORT endCode;
+ TTF_USHORT startCode;
+ TTF_USHORT idDelta;
+ TTF_USHORT idRangeOffset;
+} seg_entry;
+
+typedef struct {
+ TTF_LONG offset;
+ TTF_LONG newoffset;
+ TTF_UFWORD advWidth;
+ TTF_FWORD lsb;
+ char *name; /* name of glyph */
+ TTF_SHORT newindex; /* new index of glyph in output file */
+ TTF_USHORT name_index; /* index of name as read from font file */
+} glyph_entry;
+
+/* some functions and variables are used by writetype0.c */
+
+extern fd_entry *fd_cur; /* pointer to the current font descriptor */
+extern unsigned char *ttf_buffer;
+extern integer ttf_size;
+extern integer ttf_curbyte;
+extern glyph_entry *glyph_tab;
+extern dirtab_entry *dir_tab;
+extern dirtab_entry *ttf_name_lookup (const char *s, boolean required);
+extern dirtab_entry *ttf_seek_tab (const char *name, TTF_LONG offset);
+
+extern void ttf_read_tabdir (void);
+extern void ttf_read_head (void);
+extern void ttf_read_hhea (void);
+extern void ttf_read_pclt (void);
+extern void ttf_read_post (void);
+
+extern FILE *ttf_file;
+
+#define ttf_open() \
+ open_input(&ttf_file, kpse_truetype_format, FOPEN_RBIN_MODE)
+#define otf_open() \
+ open_input(&ttf_file, kpse_opentype_format, FOPEN_RBIN_MODE)
+#define ttf_read_file() \
+ readbinfile(ttf_file,&ttf_buffer,&ttf_size)
+#define ttf_close() xfclose(ttf_file,cur_file_name)
+#define ttf_getchar() ttf_buffer[ttf_curbyte++]
+#define ttf_eof() (ttf_curbyte>ttf_size)
+
+extern long ttf_putnum (int s, long n);
+extern long ttf_getnum (int s);
+
+
diff --git a/Build/source/texk/web2c/luatexdir/font/writetype0.c b/Build/source/texk/web2c/luatexdir/font/writetype0.c
new file mode 100644
index 00000000000..0f9eecaac7c
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writetype0.c
@@ -0,0 +1,124 @@
+/*
+Copyright (c) 2007 Taco Hoekwater, taco@luatex.org
+
+This file is part of luaTeX.
+
+luaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writetype0.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+
+#include "writettf.h"
+
+#include "writecff.h"
+
+void writetype0 (fd_entry * fd) {
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+ long i;
+ dirtab_entry *tab;
+ cff_font *cff;
+
+ dir_tab = NULL;
+ glyph_tab = NULL;
+
+ fd_cur = fd; /* fd_cur is global inside writettf.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_opentype(fd_cur->fm));
+ assert(is_included(fd_cur->fm));
+
+ set_cur_file_name(fd_cur->fm->ff_name);
+ ttf_curbyte=0;
+ ttf_size=0;
+ callback_id=callback_defined(find_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &ttf_buffer,&ttf_size) &&
+ file_opened && ttf_size>0) {
+ } else {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ } else {
+ if (!otf_open ()) {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ ttf_read_file();
+ ttf_close();
+ }
+
+ cur_file_name = (char *) nameoffile + 1;
+ fd_cur->ff_found = true;
+
+ if (tracefilenames) {
+ if (is_subsetted(fd_cur->fm))
+ tex_printf ("<%s", cur_file_name);
+ else
+ tex_printf ("<<%s", cur_file_name);
+ }
+ ttf_read_tabdir ();
+ /* read font parameters */
+ if (ttf_name_lookup ("head", false) != NULL)
+ ttf_read_head ();
+ if (ttf_name_lookup ("hhea", false) != NULL)
+ ttf_read_hhea ();
+ if (ttf_name_lookup ("PCLT", false) != NULL)
+ ttf_read_pclt ();
+ if (ttf_name_lookup ("post", false) != NULL)
+ ttf_read_post ();
+
+ /* copy font file */
+ tab = ttf_seek_tab ("CFF ", 0);
+
+ /* TODO the next 0 is a subfont index */
+ cff = read_cff(ttf_buffer+ttf_curbyte,tab->length,0);
+ if (cff != NULL) {
+ if (cff_is_cidfont(cff)) {
+ write_cid_cff(cff,fd_cur,0);
+ /*
+ for (i = tab->length; i > 0; i--)
+ fb_putchar (ttf_getnum(1));
+ */
+ } else {
+ write_cff(cff,fd_cur,0);
+ }
+ } else {
+ /* not understood, just do a copy */
+ for (i = tab->length; i > 0; i--)
+ fb_putchar (ttf_getnum(1));
+ }
+ xfree (dir_tab);
+ if (tracefilenames) {
+ if (is_subsetted (fd_cur->fm))
+ tex_printf (">");
+ else
+ tex_printf (">>");
+ }
+ cur_file_name = NULL;
+}
diff --git a/Build/source/texk/web2c/luatexdir/font/writetype2.c b/Build/source/texk/web2c/luatexdir/font/writetype2.c
new file mode 100644
index 00000000000..649c350b707
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/font/writetype2.c
@@ -0,0 +1,422 @@
+
+/*
+Copyright (c) 2007 Taco Hoekwater, taco@luatex.org
+
+This file is part of luaTeX.
+
+luaTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+luaTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with luaTeX; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+$Id: writetype2.c 1013 2008-02-14 00:09:02Z oneiros $
+*/
+
+#include "ptexlib.h"
+#include "writettf.h"
+#include "writecff.h"
+
+#include "sfnt.h"
+#include "tt_glyf.h"
+
+/* forward*/
+void make_tt_subset (fd_entry * fd,unsigned char *buffer, integer buflen) ;
+
+unsigned long cidtogid_obj = 0;
+
+/* low-level helpers */
+
+#define test_loc(l) \
+ if ((f->loc+l)>f->buflen) { \
+ fprintf (stderr,"File ended prematurely\n"); \
+ uexit(1); \
+ }
+
+
+BYTE get_unsigned_byte(sfnt* f) {
+ test_loc(1);
+ return (BYTE)f->buffer[(f->loc++)];
+};
+
+ICHAR get_signed_byte(sfnt* f) {
+ test_loc(1);
+ return (ICHAR)f->buffer[(f->loc++)];
+};
+
+USHORT get_unsigned_pair(sfnt* f){
+ USHORT l;
+ test_loc(2);
+ l = f->buffer[(f->loc++)];
+ l = l*0x100 + f->buffer[(f->loc++)];
+ return l;
+};
+
+SHORT get_signed_pair(sfnt* f){
+ long l;
+ test_loc(2);
+ l = f->buffer[(f->loc++)];
+ if (l>0x80) l -= 0x100;
+ l = l*0x100 + f->buffer[(f->loc++)];
+ return l;
+};
+
+ULONG get_unsigned_quad(sfnt* f){
+ ULONG l;
+ test_loc(4);
+ l = f->buffer[(f->loc++)];
+ l = l*0x100 + f->buffer[(f->loc++)];
+ l = l*0x100 + f->buffer[(f->loc++)];
+ l = l*0x100 + f->buffer[(f->loc++)];
+ return l;
+};
+
+int do_sfnt_read (unsigned char *dest, int len, sfnt *f) {
+ int i;
+ test_loc(len);
+ for (i=0;i<len;i++) {
+ *(dest+i)=f->buffer[f->loc+i];
+ }
+ f->loc += len;
+ return len;
+};
+
+pdf_obj *pdf_new_stream(void) {
+ pdf_obj *stream = xmalloc(sizeof(pdf_obj)) ;
+ stream->length =0;
+ stream->data=NULL;
+ return stream;
+};
+
+void pdf_add_stream(pdf_obj *stream, unsigned char *buf, long len) {
+ int i;
+ assert (stream!=NULL);
+ if (stream->data==NULL) {
+ stream->data = xmalloc(len);
+ } else {
+ stream->data = xrealloc(stream->data,len+stream->length);
+ }
+ for (i=0;i<len;i++) {
+ *(stream->data+stream->length+i)=*(buf+i);
+ }
+ stream->length+=len;
+};
+
+void pdf_release_obj(pdf_obj *stream) {
+ if (stream!=NULL) {
+ if (stream->data!=NULL) {
+ xfree(stream->data);
+ }
+ xfree(stream);
+ }
+};
+
+
+void
+writetype2 (fd_entry * fd) {
+ int callback_id;
+ int file_opened = 0;
+ char *ftemp = NULL;
+
+ glyph_tab = NULL;
+
+ fd_cur = fd; /* fd_cur is global inside writettf.c */
+ assert(fd_cur->fm != NULL);
+ assert(is_truetype(fd_cur->fm));
+
+ if (!is_subsetted(fd_cur->fm)) {
+ writettf(fd);
+ return;
+ }
+
+ assert(is_included(fd_cur->fm));
+
+ set_cur_file_name(fd_cur->fm->ff_name);
+ ttf_curbyte=0;
+ ttf_size=0;
+ callback_id=callback_defined(find_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) {
+ if(ftemp!=NULL&&strlen(ftemp)) {
+ free(nameoffile);
+ namelength = strlen(ftemp);
+ nameoffile = xmalloc(namelength+2);
+ strcpy((char *)(nameoffile+1),ftemp);
+ free(ftemp);
+ }
+ }
+ }
+ callback_id=callback_defined(read_opentype_file_callback);
+ if (callback_id>0) {
+ if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1),
+ &file_opened, &ttf_buffer,&ttf_size) &&
+ file_opened && ttf_size>0) {
+ } else {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ } else {
+ if (!otf_open ()) {
+ pdftex_fail ("cannot open OpenType font file for reading");
+ }
+ ttf_read_file();
+ ttf_close();
+ }
+
+ cur_file_name = (char *) nameoffile + 1;
+ fd_cur->ff_found = true;
+
+ if (tracefilenames) {
+ if (is_subsetted(fd_cur->fm))
+ tex_printf ("<%s", cur_file_name);
+ else
+ tex_printf ("<<%s", cur_file_name);
+ }
+
+ /* here is the real work */
+
+ make_tt_subset(fd,ttf_buffer,ttf_size);
+
+ /*xfree (dir_tab);*/
+ if (tracefilenames) {
+ if (is_subsetted (fd_cur->fm))
+ tex_printf (">");
+ else
+ tex_printf (">>");
+ }
+ cur_file_name = NULL;
+}
+
+/*
+ * PDF viewer applications use following tables (CIDFontType 2)
+ *
+ * head, hhea, loca, maxp, glyf, hmtx, fpgm, cvt_, prep
+ *
+ * - from PDF Ref. v.1.3, 2nd ed.
+ *
+ * The fpgm, cvt_, and prep tables appears only when TrueType instructions
+ * requires them. Those tables must be preserved if they exist.
+ * We use must_exist flag to indicate `preserve it if present'
+ * and to make sure not to cause an error when it does not exist.
+ *
+ * post and name table must exist in ordinary TrueType font file,
+ * but when a TrueType font is converted to CIDFontType 2 font, those tables
+ * are no longer required.
+ *
+ * The OS/2 table (required for TrueType font for Windows and OS/2) contains
+ * liscencing information, but PDF viewers seems not using them.
+ *
+ * The 'name' table added. See comments in ttf.c.
+ */
+
+static struct
+{
+ const char *name;
+ int must_exist;
+} required_table[] = {
+ {"OS/2", 0}, {"head", 1}, {"hhea", 1}, {"loca", 1}, {"maxp", 1},
+ {"name", 1}, {"glyf", 1}, {"hmtx", 1}, {"fpgm", 0}, {"cvt ", 0},
+ {"prep", 0}, {NULL, 0}
+};
+
+
+unsigned long ttc_read_offset (sfnt *sfont, int ttc_idx)
+{
+ long version;
+ unsigned long offset = 0;
+ unsigned long num_dirs = 0;
+
+ sfnt_seek_set (sfont, 4); /* skip version tag */
+
+ version = sfnt_get_ulong(sfont);
+ num_dirs = sfnt_get_ulong(sfont);
+ if (ttc_idx < 0 || ttc_idx > num_dirs - 1) {
+ fprintf(stderr,"Invalid TTC index number\n");
+ uexit(1);
+ }
+
+ sfnt_seek_set (sfont, 12 + ttc_idx * 4);
+ offset = sfnt_get_ulong (sfont);
+
+ return offset;
+}
+
+extern int ff_get_ttc_index(char *ffname, char*psname);
+
+void make_tt_subset (fd_entry * fd,unsigned char *buffer, integer buflen) {
+
+ long i, cid;
+ unsigned int last_cid;
+ glw_entry *glyph, *found;
+ struct avl_traverser t;
+ unsigned char *cidtogidmap ;
+ unsigned short num_glyphs, gid;
+ struct tt_glyphs *glyphs;
+ char *used_chars;
+ sfnt *sfont;
+ pdf_obj *fontfile;
+ int verbose = 0, error = 0;
+
+ cidtogidmap = NULL;
+
+ sfont = sfnt_open(buffer, buflen);
+
+ if (sfont->type == SFNT_TYPE_TTC) {
+ i = ff_get_ttc_index(fd->fm->ff_name,fd->fm->ps_name);
+ error = sfnt_read_table_directory(sfont, ttc_read_offset(sfont, i));
+ } else {
+ error = sfnt_read_table_directory(sfont, 0);
+ }
+
+ if (error < 0) {
+ fprintf(stderr,"Could not parse the ttf directory.\n");
+ uexit(1);
+ }
+
+ glyphs = tt_build_init();
+
+ last_cid = 0;
+ num_glyphs = 1; /* .notdef */
+
+ glyph = xtalloc(1,glw_entry);
+
+ avl_t_init(&t, fd->gl_tree);
+ for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
+ found != NULL;
+ found = (glw_entry *) avl_t_next(&t)) {
+ if (found->id > last_cid)
+ last_cid = found->id;
+ }
+
+#ifndef NO_GHOSTSCRIPT_BUG
+ cidtogidmap = NULL;
+#else
+ cidtogidmap = xmalloc(((last_cid + 1) * 2) * sizeof(unsigned char));
+ memset(cidtogidmap, 0, (last_cid + 1) * 2);
+#endif
+
+ /* fill used_chars */
+ used_chars = xmalloc((last_cid + 1) * sizeof(char));
+ memset(used_chars, 0, (last_cid + 1));
+ avl_t_init(&t, fd->gl_tree);
+ for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
+ found != NULL;
+ found = (glw_entry *) avl_t_next(&t)) {
+ used_chars[found->id] = 1;
+ }
+
+ /*
+ * Map CIDs to GIDs.
+ */
+
+ num_glyphs = 1; /* .notdef */
+ for (cid = 1; cid <= last_cid; cid++) {
+ if (used_chars[cid]==0)
+ continue;
+ gid = cid;
+
+
+#ifndef NO_GHOSTSCRIPT_BUG
+ gid = tt_add_glyph(glyphs, gid, cid);
+#else
+ gid = tt_add_glyph(glyphs, gid, num_glyphs);
+ cidtogidmap[2*cid ] = gid >> 8;
+ cidtogidmap[2*cid+1] = gid & 0xff;
+#endif /* !NO_GHOSTSCRIPT_BUG */
+
+ num_glyphs++;
+ }
+
+ if (num_glyphs==1) {
+ fprintf(stderr,"No glyphs in subset?.\n");
+ uexit(1);
+ }
+
+ if (tt_build_tables(sfont, glyphs) < 0) {
+ fprintf(stderr,"Could not parse the ttf buffer.\n");
+ uexit(1);
+ }
+
+ if (verbose > 1) {
+ fprintf(stdout,"[%u glyphs (Max CID: %u)]", glyphs->num_glyphs, last_cid);
+ }
+
+ tt_build_finish(glyphs);
+
+ /* Create font file */
+
+ for (i = 0; required_table[i].name; i++) {
+ if (sfnt_require_table(sfont,
+ required_table[i].name,
+ required_table[i].must_exist) < 0) {
+ fprintf(stderr,"Some required TrueType table does not exist.");
+ uexit(1);
+ }
+ }
+
+ fontfile = sfnt_create_FontFile_stream(sfont);
+
+ if (verbose > 1) {
+ fprintf(stdout,"[%ld bytes]", fontfile->length);
+ }
+
+ /* squeeze in the cidgidmap */
+ if (cidtogidmap!=NULL) {
+ cidtogid_obj = pdf_new_objnum();
+ pdf_begin_dict(cidtogid_obj, 0);
+ pdf_printf("/Length %i\n",((last_cid + 1) * 2));
+ pdf_end_dict();
+ pdf_printf("stream\n");
+ pdfroom ((last_cid + 1) * 2);
+ for (i = 0; i<((last_cid + 1) * 2); i++ ) {
+ pdf_buf[pdf_ptr++] = cidtogidmap[i];
+ }
+ pdf_printf("\nendstream\n");
+ }
+
+ /* the tff subset */
+ for (i = 0; i<fontfile->length; i++ )
+ fb_putchar (fontfile->data[i]);
+
+
+ /* other stuff that needs fixing: */
+
+ /*
+ * DW, W, DW2, and W2
+ */
+ /*
+ if (opt_flags & CIDFONT_FORCE_FIXEDPITCH) {
+ pdf_add_dict(font->fontdict,
+ pdf_new_name("DW"), pdf_new_number(1000.0));
+ } else {
+ add_TTCIDHMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
+ if (v_used_chars)
+ add_TTCIDVMetrics(font->fontdict, glyphs, used_chars, cidtogidmap, last_cid);
+ }
+ */
+
+ /*
+ * CIDSet
+ */
+ /*
+ {
+ pdf_obj *cidset;
+
+ cidset = pdf_new_stream(STREAM_COMPRESS);
+ pdf_add_stream(cidset, used_chars, last_cid/8 + 1);
+ pdf_add_dict(font->descriptor,
+ pdf_new_name("CIDSet"),
+ pdf_ref_obj(cidset));
+ pdf_release_obj(cidset);
+ }
+ */
+
+ return;
+}