diff options
author | Taco Hoekwater <taco@elvenkind.com> | 2006-11-20 14:43:48 +0000 |
---|---|---|
committer | Taco Hoekwater <taco@elvenkind.com> | 2006-11-20 14:43:48 +0000 |
commit | 5952e40b396499c0cd62bdbcf1853538873b76c1 (patch) | |
tree | 968b37e966ba1825e2de091a071774af1a7ffa9b /Build/source/texk/web2c/mpdir | |
parent | 9fcf4d90b8b3a11712287d4ddf3fd47614a7ea68 (diff) |
Metapost 0.99 sources, except dmp
git-svn-id: svn://tug.org/texlive/trunk@2470 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/mpdir')
-rw-r--r-- | Build/source/texk/web2c/mpdir/Makefile.in | 40 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/avl.c | 792 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/avl.h | 118 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/avlstuff.c | 50 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/avlstuff.h | 29 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/makecpool.c | 58 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/mapfile.c | 993 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/mp.defines | 54 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/mplib.h | 300 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/mpmac.h | 218 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/mpostlib.mk | 29 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/utils.c | 719 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/writeenc.c | 142 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/writefont.c | 244 | ||||
-rw-r--r-- | Build/source/texk/web2c/mpdir/writet1.c | 1736 |
15 files changed, 5522 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/mpdir/Makefile.in b/Build/source/texk/web2c/mpdir/Makefile.in new file mode 100644 index 00000000000..c6abb102f2d --- /dev/null +++ b/Build/source/texk/web2c/mpdir/Makefile.in @@ -0,0 +1,40 @@ +# Makefile for libmpost - taco@elvenkind.com, but +# mostly ripped off from Makefile.in from pdftex +# $Id $ + +kpse_include ../make/common.mk +kpse_include ../make/programs.mk +kpse_include ../make/library.mk + +kpathsea_srcdir_parent = $(srcdir)/../.. +kpathsea_dir_parent = ../.. + +ALL_CXXFLAGS = @CXXFLAGS@ @DEFS@ $(XXCFLAGS) -I. -I$(srcdir) -I$(kpathsea_dir_parent) -I$(kpathsea_srcdir_parent) +CXX = @CXX@ + +XCPPFLAGS=-I.. -I$(srcdir)/.. -I../.. -I$(srcdir)/../.. + +OBJS = mapfile.o avl.o avlstuff.o utils.o writeenc.o writet1.o writefont.o + +all: libmpost.a makecpool + +libmpost.a: $(OBJS) + rm -f $@ + $(AR) $(ARFLAGS) $@ $(OBJS) + $(RANLIB) $@ + +makecpool: makecpool.o + $(link_command) makecpool.o + +kpse_include ../make/clean.mk + +clean:: + rm -f libmpost.a makecpool + +depend: + rm -f $(OBJS) + XXCFLAGS=-MM XCFLAGS=-MM $(MAKE) -k $(OBJS) | \ + grep -v "^$(CC)\|$(CXX)\|$(AR)\|make\|klibtool" | \ + sed 's: [^ ]*/\.\./libs/[^ ]*::g' > $(srcdir)/depend.mk + +kpse_include mpdir/depend.mk diff --git a/Build/source/texk/web2c/mpdir/avl.c b/Build/source/texk/web2c/mpdir/avl.c new file mode 100644 index 00000000000..703c4b2e72d --- /dev/null +++ b/Build/source/texk/web2c/mpdir/avl.c @@ -0,0 +1,792 @@ +/* Produced by texiweb from libavl.w on 2003/01/06 at 18:07. */ + +/* libavl - library for manipulation of binary trees. + Copyright (C) 1998-2002 Free Software Foundation, Inc. + + 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. + + The author may be contacted at <blp@gnu.org> on the Internet, or + write to Ben Pfaff, Stanford University, Computer Science Dept., 353 + Serra Mall, Stanford CA 94305, USA. +*/ + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "avl.h" + +/* Creates and returns a new table + with comparison function |compare| using parameter |param| + and memory allocator |allocator|. + Returns |NULL| if memory allocation failed. */ +struct avl_table *avl_create (avl_comparison_func * compare, void *param, + struct libavl_allocator *allocator) +{ + struct avl_table *tree; + + assert (compare != NULL); + + if (allocator == NULL) + allocator = &avl_allocator_default; + + tree = allocator->libavl_malloc (allocator, sizeof *tree); + if (tree == NULL) + return NULL; + + tree->avl_root = NULL; + tree->avl_compare = compare; + tree->avl_param = param; + tree->avl_alloc = allocator; + tree->avl_count = 0; + tree->avl_generation = 0; + + return tree; +} + +/* Search |tree| for an item matching |item|, and return it if found. + Otherwise return |NULL|. */ +void *avl_find (const struct avl_table *tree, const void *item) +{ + const struct avl_node *p; + + assert (tree != NULL && item != NULL); + for (p = tree->avl_root; p != NULL;) { + int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param); + + if (cmp < 0) + p = p->avl_link[0]; + else if (cmp > 0) + p = p->avl_link[1]; + else /* |cmp == 0| */ + return p->avl_data; + } + + return NULL; +} + +/* Inserts |item| into |tree| and returns a pointer to |item|'s address. + If a duplicate item is found in the tree, + returns a pointer to the duplicate without inserting |item|. + Returns |NULL| in case of memory allocation failure. */ +void **avl_probe (struct avl_table *tree, void *item) +{ + struct avl_node *y, *z; /* Top node to update balance factor, and parent. */ + struct avl_node *p, *q; /* Iterator, and parent. */ + struct avl_node *n; /* Newly inserted node. */ + struct avl_node *w; /* New root of rebalanced subtree. */ + int dir; /* Direction to descend. */ + + unsigned char da[AVL_MAX_HEIGHT]; /* Cached comparison results. */ + int k = 0; /* Number of cached results. */ + + assert (tree != NULL && item != NULL); + + z = (struct avl_node *) &tree->avl_root; + y = tree->avl_root; + dir = 0; + for (q = z, p = y; p != NULL; q = p, p = p->avl_link[dir]) { + int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param); + if (cmp == 0) + return &p->avl_data; + + if (p->avl_balance != 0) + z = q, y = p, k = 0; + da[k++] = dir = cmp > 0; + } + + n = q->avl_link[dir] = + tree->avl_alloc->libavl_malloc (tree->avl_alloc, sizeof *n); + if (n == NULL) + return NULL; + + tree->avl_count++; + n->avl_data = item; + n->avl_link[0] = n->avl_link[1] = NULL; + n->avl_balance = 0; + if (y == NULL) + return &n->avl_data; + + for (p = y, k = 0; p != n; p = p->avl_link[da[k]], k++) + if (da[k] == 0) + p->avl_balance--; + else + p->avl_balance++; + + if (y->avl_balance == -2) { + struct avl_node *x = y->avl_link[0]; + if (x->avl_balance == -1) { + w = x; + y->avl_link[0] = x->avl_link[1]; + x->avl_link[1] = y; + x->avl_balance = y->avl_balance = 0; + } else { + assert (x->avl_balance == +1); + w = x->avl_link[1]; + x->avl_link[1] = w->avl_link[0]; + w->avl_link[0] = x; + y->avl_link[0] = w->avl_link[1]; + w->avl_link[1] = y; + if (w->avl_balance == -1) + x->avl_balance = 0, y->avl_balance = +1; + else if (w->avl_balance == 0) + x->avl_balance = y->avl_balance = 0; + else /* |w->avl_balance == +1| */ + x->avl_balance = -1, y->avl_balance = 0; + w->avl_balance = 0; + } + } else if (y->avl_balance == +2) { + struct avl_node *x = y->avl_link[1]; + if (x->avl_balance == +1) { + w = x; + y->avl_link[1] = x->avl_link[0]; + x->avl_link[0] = y; + x->avl_balance = y->avl_balance = 0; + } else { + assert (x->avl_balance == -1); + w = x->avl_link[0]; + x->avl_link[0] = w->avl_link[1]; + w->avl_link[1] = x; + y->avl_link[1] = w->avl_link[0]; + w->avl_link[0] = y; + if (w->avl_balance == +1) + x->avl_balance = 0, y->avl_balance = -1; + else if (w->avl_balance == 0) + x->avl_balance = y->avl_balance = 0; + else /* |w->avl_balance == -1| */ + x->avl_balance = +1, y->avl_balance = 0; + w->avl_balance = 0; + } + } else + return &n->avl_data; + z->avl_link[y != z->avl_link[0]] = w; + + tree->avl_generation++; + return &n->avl_data; +} + +/* Inserts |item| into |table|. + Returns |NULL| if |item| was successfully inserted + or if a memory allocation error occurred. + Otherwise, returns the duplicate item. */ +void *avl_insert (struct avl_table *table, void *item) +{ + void **p = avl_probe (table, item); + return p == NULL || *p == item ? NULL : *p; +} + +/* Inserts |item| into |table|, replacing any duplicate item. + Returns |NULL| if |item| was inserted without replacing a duplicate, + or if a memory allocation error occurred. + Otherwise, returns the item that was replaced. */ +void *avl_replace (struct avl_table *table, void *item) +{ + void **p = avl_probe (table, item); + if (p == NULL || *p == item) + return NULL; + else { + void *r = *p; + *p = item; + return r; + } +} + +/* Deletes from |tree| and returns an item matching |item|. + Returns a null pointer if no matching item found. */ +void *avl_delete (struct avl_table *tree, const void *item) +{ + /* Stack of nodes. */ + struct avl_node *pa[AVL_MAX_HEIGHT]; /* Nodes. */ + unsigned char da[AVL_MAX_HEIGHT]; /* |avl_link[]| indexes. */ + int k; /* Stack pointer. */ + + struct avl_node *p; /* Traverses tree to find node to delete. */ + int cmp; /* Result of comparison between |item| and |p|. */ + + assert (tree != NULL && item != NULL); + + k = 0; + p = (struct avl_node *) &tree->avl_root; + for (cmp = -1; cmp != 0; + cmp = tree->avl_compare (item, p->avl_data, tree->avl_param)) { + int dir = cmp > 0; + + pa[k] = p; + da[k++] = dir; + + p = p->avl_link[dir]; + if (p == NULL) + return NULL; + } + item = p->avl_data; + + if (p->avl_link[1] == NULL) + pa[k - 1]->avl_link[da[k - 1]] = p->avl_link[0]; + else { + struct avl_node *r = p->avl_link[1]; + if (r->avl_link[0] == NULL) { + r->avl_link[0] = p->avl_link[0]; + r->avl_balance = p->avl_balance; + pa[k - 1]->avl_link[da[k - 1]] = r; + da[k] = 1; + pa[k++] = r; + } else { + struct avl_node *s; + int j = k++; + + for (;;) { + da[k] = 0; + pa[k++] = r; + s = r->avl_link[0]; + if (s->avl_link[0] == NULL) + break; + + r = s; + } + + s->avl_link[0] = p->avl_link[0]; + r->avl_link[0] = s->avl_link[1]; + s->avl_link[1] = p->avl_link[1]; + s->avl_balance = p->avl_balance; + + pa[j - 1]->avl_link[da[j - 1]] = s; + da[j] = 1; + pa[j] = s; + } + } + + tree->avl_alloc->libavl_free (tree->avl_alloc, p); + + assert (k > 0); + while (--k > 0) { + struct avl_node *y = pa[k]; + + if (da[k] == 0) { + y->avl_balance++; + if (y->avl_balance == +1) + break; + else if (y->avl_balance == +2) { + struct avl_node *x = y->avl_link[1]; + if (x->avl_balance == -1) { + struct avl_node *w; + assert (x->avl_balance == -1); + w = x->avl_link[0]; + x->avl_link[0] = w->avl_link[1]; + w->avl_link[1] = x; + y->avl_link[1] = w->avl_link[0]; + w->avl_link[0] = y; + if (w->avl_balance == +1) + x->avl_balance = 0, y->avl_balance = -1; + else if (w->avl_balance == 0) + x->avl_balance = y->avl_balance = 0; + else /* |w->avl_balance == -1| */ + x->avl_balance = +1, y->avl_balance = 0; + w->avl_balance = 0; + pa[k - 1]->avl_link[da[k - 1]] = w; + } else { + y->avl_link[1] = x->avl_link[0]; + x->avl_link[0] = y; + pa[k - 1]->avl_link[da[k - 1]] = x; + if (x->avl_balance == 0) { + x->avl_balance = -1; + y->avl_balance = +1; + break; + } else + x->avl_balance = y->avl_balance = 0; + } + } + } else { + y->avl_balance--; + if (y->avl_balance == -1) + break; + else if (y->avl_balance == -2) { + struct avl_node *x = y->avl_link[0]; + if (x->avl_balance == +1) { + struct avl_node *w; + assert (x->avl_balance == +1); + w = x->avl_link[1]; + x->avl_link[1] = w->avl_link[0]; + w->avl_link[0] = x; + y->avl_link[0] = w->avl_link[1]; + w->avl_link[1] = y; + if (w->avl_balance == -1) + x->avl_balance = 0, y->avl_balance = +1; + else if (w->avl_balance == 0) + x->avl_balance = y->avl_balance = 0; + else /* |w->avl_balance == +1| */ + x->avl_balance = -1, y->avl_balance = 0; + w->avl_balance = 0; + pa[k - 1]->avl_link[da[k - 1]] = w; + } else { + y->avl_link[0] = x->avl_link[1]; + x->avl_link[1] = y; + pa[k - 1]->avl_link[da[k - 1]] = x; + if (x->avl_balance == 0) { + x->avl_balance = +1; + y->avl_balance = -1; + break; + } else + x->avl_balance = y->avl_balance = 0; + } + } + } + } + + tree->avl_count--; + tree->avl_generation++; + return (void *) item; +} + +/* Refreshes the stack of parent pointers in |trav| + and updates its generation number. */ +static void trav_refresh (struct avl_traverser *trav) +{ + assert (trav != NULL); + + trav->avl_generation = trav->avl_table->avl_generation; + + if (trav->avl_node != NULL) { + avl_comparison_func *cmp = trav->avl_table->avl_compare; + void *param = trav->avl_table->avl_param; + struct avl_node *node = trav->avl_node; + struct avl_node *i; + + trav->avl_height = 0; + for (i = trav->avl_table->avl_root; i != node;) { + assert (trav->avl_height < AVL_MAX_HEIGHT); + assert (i != NULL); + + trav->avl_stack[trav->avl_height++] = i; + i = i->avl_link[cmp (node->avl_data, i->avl_data, param) > 0]; + } + } +} + +/* Initializes |trav| for use with |tree| + and selects the null node. */ +void avl_t_init (struct avl_traverser *trav, struct avl_table *tree) +{ + trav->avl_table = tree; + trav->avl_node = NULL; + trav->avl_height = 0; + trav->avl_generation = tree->avl_generation; +} + +/* Initializes |trav| for |tree| + and selects and returns a pointer to its least-valued item. + Returns |NULL| if |tree| contains no nodes. */ +void *avl_t_first (struct avl_traverser *trav, struct avl_table *tree) +{ + struct avl_node *x; + + assert (tree != NULL && trav != NULL); + + trav->avl_table = tree; + trav->avl_height = 0; + trav->avl_generation = tree->avl_generation; + + x = tree->avl_root; + if (x != NULL) + while (x->avl_link[0] != NULL) { + assert (trav->avl_height < AVL_MAX_HEIGHT); + trav->avl_stack[trav->avl_height++] = x; + x = x->avl_link[0]; + } + trav->avl_node = x; + + return x != NULL ? x->avl_data : NULL; +} + +/* Initializes |trav| for |tree| + and selects and returns a pointer to its greatest-valued item. + Returns |NULL| if |tree| contains no nodes. */ +void *avl_t_last (struct avl_traverser *trav, struct avl_table *tree) +{ + struct avl_node *x; + + assert (tree != NULL && trav != NULL); + + trav->avl_table = tree; + trav->avl_height = 0; + trav->avl_generation = tree->avl_generation; + + x = tree->avl_root; + if (x != NULL) + while (x->avl_link[1] != NULL) { + assert (trav->avl_height < AVL_MAX_HEIGHT); + trav->avl_stack[trav->avl_height++] = x; + x = x->avl_link[1]; + } + trav->avl_node = x; + + return x != NULL ? x->avl_data : NULL; +} + +/* Searches for |item| in |tree|. + If found, initializes |trav| to the item found and returns the item + as well. + If there is no matching item, initializes |trav| to the null item + and returns |NULL|. */ +void *avl_t_find (struct avl_traverser *trav, struct avl_table *tree, + void *item) +{ + struct avl_node *p, *q; + + assert (trav != NULL && tree != NULL && item != NULL); + trav->avl_table = tree; + trav->avl_height = 0; + trav->avl_generation = tree->avl_generation; + for (p = tree->avl_root; p != NULL; p = q) { + int cmp = tree->avl_compare (item, p->avl_data, tree->avl_param); + + if (cmp < 0) + q = p->avl_link[0]; + else if (cmp > 0) + q = p->avl_link[1]; + else { /* |cmp == 0| */ + + trav->avl_node = p; + return p->avl_data; + } + + assert (trav->avl_height < AVL_MAX_HEIGHT); + trav->avl_stack[trav->avl_height++] = p; + } + + trav->avl_height = 0; + trav->avl_node = NULL; + return NULL; +} + +/* Attempts to insert |item| into |tree|. + If |item| is inserted successfully, it is returned and |trav| is + initialized to its location. + If a duplicate is found, it is returned and |trav| is initialized to + its location. No replacement of the item occurs. + If a memory allocation failure occurs, |NULL| is returned and |trav| + is initialized to the null item. */ +void *avl_t_insert (struct avl_traverser *trav, struct avl_table *tree, + void *item) +{ + void **p; + + assert (trav != NULL && tree != NULL && item != NULL); + + p = avl_probe (tree, item); + if (p != NULL) { + trav->avl_table = tree; + trav->avl_node = ((struct avl_node *) + ((char *) p - offsetof (struct avl_node, avl_data))); + trav->avl_generation = tree->avl_generation - 1; + return *p; + } else { + avl_t_init (trav, tree); + return NULL; + } +} + +/* Initializes |trav| to have the same current node as |src|. */ +void *avl_t_copy (struct avl_traverser *trav, const struct avl_traverser *src) +{ + assert (trav != NULL && src != NULL); + + if (trav != src) { + trav->avl_table = src->avl_table; + trav->avl_node = src->avl_node; + trav->avl_generation = src->avl_generation; + if (trav->avl_generation == trav->avl_table->avl_generation) { + trav->avl_height = src->avl_height; + memcpy (trav->avl_stack, (const void *) src->avl_stack, + sizeof *trav->avl_stack * trav->avl_height); + } + } + + return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL; +} + +/* Returns the next data item in inorder + within the tree being traversed with |trav|, + or if there are no more data items returns |NULL|. */ +void *avl_t_next (struct avl_traverser *trav) +{ + struct avl_node *x; + + assert (trav != NULL); + + if (trav->avl_generation != trav->avl_table->avl_generation) + trav_refresh (trav); + + x = trav->avl_node; + if (x == NULL) { + return avl_t_first (trav, trav->avl_table); + } else if (x->avl_link[1] != NULL) { + assert (trav->avl_height < AVL_MAX_HEIGHT); + trav->avl_stack[trav->avl_height++] = x; + x = x->avl_link[1]; + + while (x->avl_link[0] != NULL) { + assert (trav->avl_height < AVL_MAX_HEIGHT); + trav->avl_stack[trav->avl_height++] = x; + x = x->avl_link[0]; + } + } else { + struct avl_node *y; + + do { + if (trav->avl_height == 0) { + trav->avl_node = NULL; + return NULL; + } + + y = x; + x = trav->avl_stack[--trav->avl_height]; + } + while (y == x->avl_link[1]); + } + trav->avl_node = x; + + return x->avl_data; +} + +/* Returns the previous data item in inorder + within the tree being traversed with |trav|, + or if there are no more data items returns |NULL|. */ +void *avl_t_prev (struct avl_traverser *trav) +{ + struct avl_node *x; + + assert (trav != NULL); + + if (trav->avl_generation != trav->avl_table->avl_generation) + trav_refresh (trav); + + x = trav->avl_node; + if (x == NULL) { + return avl_t_last (trav, trav->avl_table); + } else if (x->avl_link[0] != NULL) { + assert (trav->avl_height < AVL_MAX_HEIGHT); + trav->avl_stack[trav->avl_height++] = x; + x = x->avl_link[0]; + + while (x->avl_link[1] != NULL) { + assert (trav->avl_height < AVL_MAX_HEIGHT); + trav->avl_stack[trav->avl_height++] = x; + x = x->avl_link[1]; + } + } else { + struct avl_node *y; + + do { + if (trav->avl_height == 0) { + trav->avl_node = NULL; + return NULL; + } + + y = x; + x = trav->avl_stack[--trav->avl_height]; + } + while (y == x->avl_link[0]); + } + trav->avl_node = x; + + return x->avl_data; +} + +/* Returns |trav|'s current item. */ +void *avl_t_cur (struct avl_traverser *trav) +{ + assert (trav != NULL); + + return trav->avl_node != NULL ? trav->avl_node->avl_data : NULL; +} + +/* Replaces the current item in |trav| by |new| and returns the item replaced. + |trav| must not have the null item selected. + The new item must not upset the ordering of the tree. */ +void *avl_t_replace (struct avl_traverser *trav, void *new) +{ + void *old; + + assert (trav != NULL && trav->avl_node != NULL && new != NULL); + old = trav->avl_node->avl_data; + trav->avl_node->avl_data = new; + return old; +} + +static void +copy_error_recovery (struct avl_node **stack, int height, + struct avl_table *new, avl_item_func * destroy) +{ + assert (stack != NULL && height >= 0 && new != NULL); + + for (; height > 2; height -= 2) + stack[height - 1]->avl_link[1] = NULL; + avl_destroy (new, destroy); +} + +/* Copies |org| to a newly created tree, which is returned. + If |copy != NULL|, each data item in |org| is first passed to |copy|, + and the return values are inserted into the tree, + with |NULL| return values taken as indications of failure. + On failure, destroys the partially created new tree, + applying |destroy|, if non-null, to each item in the new tree so far, + and returns |NULL|. + If |allocator != NULL|, it is used for allocation in the new tree. + Otherwise, the same allocator used for |org| is used. */ +struct avl_table *avl_copy (const struct avl_table *org, avl_copy_func * copy, + avl_item_func * destroy, + struct libavl_allocator *allocator) +{ + struct avl_node *stack[2 * (AVL_MAX_HEIGHT + 1)]; + int height = 0; + + struct avl_table *new; + const struct avl_node *x; + struct avl_node *y; + + assert (org != NULL); + new = avl_create (org->avl_compare, org->avl_param, + allocator != NULL ? allocator : org->avl_alloc); + if (new == NULL) + return NULL; + new->avl_count = org->avl_count; + if (new->avl_count == 0) + return new; + + x = (const struct avl_node *) &org->avl_root; + y = (struct avl_node *) &new->avl_root; + for (;;) { + while (x->avl_link[0] != NULL) { + assert (height < 2 * (AVL_MAX_HEIGHT + 1)); + + y->avl_link[0] = + new->avl_alloc->libavl_malloc (new->avl_alloc, + sizeof *y->avl_link[0]); + if (y->avl_link[0] == NULL) { + if (y != (struct avl_node *) &new->avl_root) { + y->avl_data = NULL; + y->avl_link[1] = NULL; + } + + copy_error_recovery (stack, height, new, destroy); + return NULL; + } + + stack[height++] = (struct avl_node *) x; + stack[height++] = y; + x = x->avl_link[0]; + y = y->avl_link[0]; + } + y->avl_link[0] = NULL; + + for (;;) { + y->avl_balance = x->avl_balance; + if (copy == NULL) + y->avl_data = x->avl_data; + else { + y->avl_data = copy (x->avl_data, org->avl_param); + if (y->avl_data == NULL) { + y->avl_link[1] = NULL; + copy_error_recovery (stack, height, new, destroy); + return NULL; + } + } + + if (x->avl_link[1] != NULL) { + y->avl_link[1] = + new->avl_alloc->libavl_malloc (new->avl_alloc, + sizeof *y->avl_link[1]); + if (y->avl_link[1] == NULL) { + copy_error_recovery (stack, height, new, destroy); + return NULL; + } + + x = x->avl_link[1]; + y = y->avl_link[1]; + break; + } else + y->avl_link[1] = NULL; + + if (height <= 2) + return new; + + y = stack[--height]; + x = stack[--height]; + } + } +} + +/* Frees storage allocated for |tree|. + If |destroy != NULL|, applies it to each data item in inorder. */ +void avl_destroy (struct avl_table *tree, avl_item_func * destroy) +{ + struct avl_node *p, *q; + + assert (tree != NULL); + + for (p = tree->avl_root; p != NULL; p = q) + if (p->avl_link[0] == NULL) { + q = p->avl_link[1]; + if (destroy != NULL && p->avl_data != NULL) + destroy (p->avl_data, tree->avl_param); + tree->avl_alloc->libavl_free (tree->avl_alloc, p); + } else { + q = p->avl_link[0]; + p->avl_link[0] = q->avl_link[1]; + q->avl_link[1] = p; + } + + tree->avl_alloc->libavl_free (tree->avl_alloc, tree); +} + +/* Allocates |size| bytes of space using |malloc()|. + Returns a null pointer if allocation fails. */ +void *avl_malloc (struct libavl_allocator *allocator, size_t size) +{ + assert (allocator != NULL && size > 0); + return malloc (size); +} + +/* Frees |block|. */ +void avl_free (struct libavl_allocator *allocator, void *block) +{ + assert (allocator != NULL && block != NULL); + free (block); +} + +/* Default memory allocator that uses |malloc()| and |free()|. */ +struct libavl_allocator avl_allocator_default = { + avl_malloc, + avl_free +}; + +#undef NDEBUG +#include <assert.h> + +/* Asserts that |avl_insert()| succeeds at inserting |item| into |table|. */ +void + (avl_assert_insert) (struct avl_table * table, void *item) { + void **p = avl_probe (table, item); + assert (p != NULL && *p == item); +} + +/* Asserts that |avl_delete()| really removes |item| from |table|, + and returns the removed item. */ +void *(avl_assert_delete) (struct avl_table * table, void *item) { + void *p = avl_delete (table, item); + assert (p != NULL); + return p; +} diff --git a/Build/source/texk/web2c/mpdir/avl.h b/Build/source/texk/web2c/mpdir/avl.h new file mode 100644 index 00000000000..acdf8bacc53 --- /dev/null +++ b/Build/source/texk/web2c/mpdir/avl.h @@ -0,0 +1,118 @@ +/* Produced by texiweb from libavl.w on 2003/01/06 at 18:07. */ + +/* libavl - library for manipulation of binary trees. + Copyright (C) 1998-2002 Free Software Foundation, Inc. + + 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. + + The author may be contacted at <blp@gnu.org> on the Internet, or + write to Ben Pfaff, Stanford University, Computer Science Dept., 353 + Serra Mall, Stanford CA 94305, USA. +*/ + +#ifndef AVL_H +# define AVL_H 1 + +# include <stddef.h> +# if defined(__cplusplus) +extern "C" { +# endif + + +/* Function types. */ + typedef int avl_comparison_func (const void *avl_a, const void *avl_b, + void *avl_param); + typedef void avl_item_func (void *avl_item, void *avl_param); + typedef void *avl_copy_func (void *avl_item, void *avl_param); + +# ifndef LIBAVL_ALLOCATOR +# define LIBAVL_ALLOCATOR +/* Memory allocator. */ + struct libavl_allocator { + void *(*libavl_malloc) (struct libavl_allocator *, size_t libavl_size); + void (*libavl_free) (struct libavl_allocator *, void *libavl_block); + }; +# endif + +/* Default memory allocator. */ + extern struct libavl_allocator avl_allocator_default; + void *avl_malloc (struct libavl_allocator *, size_t); + void avl_free (struct libavl_allocator *, void *); + +/* Maximum AVL height. */ +# ifndef AVL_MAX_HEIGHT +# define AVL_MAX_HEIGHT 32 +# endif + +/* Tree data structure. */ + struct avl_table { + struct avl_node *avl_root; /* Tree's root. */ + avl_comparison_func *avl_compare; /* Comparison function. */ + void *avl_param; /* Extra argument to |avl_compare|. */ + struct libavl_allocator *avl_alloc; /* Memory allocator. */ + size_t avl_count; /* Number of items in tree. */ + unsigned long avl_generation; /* Generation number. */ + }; + +/* An AVL tree node. */ + struct avl_node { + struct avl_node *avl_link[2]; /* Subtrees. */ + void *avl_data; /* Pointer to data. */ + signed char avl_balance; /* Balance factor. */ + }; + +/* AVL traverser structure. */ + struct avl_traverser { + struct avl_table *avl_table; /* Tree being traversed. */ + struct avl_node *avl_node; /* Current node in tree. */ + struct avl_node *avl_stack[AVL_MAX_HEIGHT]; + /* All the nodes above |avl_node|. */ + size_t avl_height; /* Number of nodes in |avl_parent|. */ + unsigned long avl_generation; /* Generation number. */ + }; + +/* Table functions. */ + struct avl_table *avl_create (avl_comparison_func *, void *, + struct libavl_allocator *); + struct avl_table *avl_copy (const struct avl_table *, avl_copy_func *, + avl_item_func *, struct libavl_allocator *); + void avl_destroy (struct avl_table *, avl_item_func *); + void **avl_probe (struct avl_table *, void *); + void *avl_insert (struct avl_table *, void *); + void *avl_replace (struct avl_table *, void *); + void *avl_delete (struct avl_table *, const void *); + void *avl_find (const struct avl_table *, const void *); + void avl_assert_insert (struct avl_table *, void *); + void *avl_assert_delete (struct avl_table *, void *); + +# define avl_count(table) ((size_t) (table)->avl_count) + +/* Table traverser functions. */ + void avl_t_init (struct avl_traverser *, struct avl_table *); + void *avl_t_first (struct avl_traverser *, struct avl_table *); + void *avl_t_last (struct avl_traverser *, struct avl_table *); + void *avl_t_find (struct avl_traverser *, struct avl_table *, void *); + void *avl_t_insert (struct avl_traverser *, struct avl_table *, void *); + void *avl_t_copy (struct avl_traverser *, const struct avl_traverser *); + void *avl_t_next (struct avl_traverser *); + void *avl_t_prev (struct avl_traverser *); + void *avl_t_cur (struct avl_traverser *); + void *avl_t_replace (struct avl_traverser *, void *); + +# if defined(__cplusplus) +} +# endif +#endif /* avl.h */ diff --git a/Build/source/texk/web2c/mpdir/avlstuff.c b/Build/source/texk/web2c/mpdir/avlstuff.c new file mode 100644 index 00000000000..300cd2c5218 --- /dev/null +++ b/Build/source/texk/web2c/mpdir/avlstuff.c @@ -0,0 +1,50 @@ +/* +Copyright (c) 2004-2005 Han The Thanh, <thanh@pdftex.org> + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by Free +Software Foundation; either version 2 of the License, or (at your option) +any later version. + +This file 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 file; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: avlstuff.c,v 1.12 2005/07/11 20:27:39 hahe Exp hahe $ + +*/ + +#include "mplib.h" +#include <kpathsea/c-vararg.h> +#include <kpathsea/c-proto.h> +#include "avl.h" + +static const char perforce_id[] = + "$Id: avlstuff.c,v 1.12 2005/07/11 20:27:39 hahe Exp hahe $"; + +/* memory management functions for avl */ + +void *avl_xmalloc (struct libavl_allocator *allocator, size_t size) +{ + assert (allocator != NULL && size > 0); + return xmalloc (size); +} + +void avl_xfree (struct libavl_allocator *allocator, void *block) +{ + assert (allocator != NULL && block != NULL); + xfree (block); +} + +struct libavl_allocator avl_xallocator = { + avl_xmalloc, + avl_xfree +}; + + +/**********************************************************************/ diff --git a/Build/source/texk/web2c/mpdir/avlstuff.h b/Build/source/texk/web2c/mpdir/avlstuff.h new file mode 100644 index 00000000000..2ffa57b627d --- /dev/null +++ b/Build/source/texk/web2c/mpdir/avlstuff.h @@ -0,0 +1,29 @@ +/* +Copyright (c) 2004 Han The Thanh, <thanh@pdftex.org> + +This file is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by Free +Software Foundation; either version 2 of the License, or (at your option) +any later version. + +This file 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 file; if not, write to the Free Software Foundation, Inc., +59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/avlstuff.h#5 $ + +formatted by indent -kr +*/ + +#include "avl.h" + +/* memory management functions for avl */ + +extern struct libavl_allocator avl_xallocator; + +/* end of file avlstuff.h */ diff --git a/Build/source/texk/web2c/mpdir/makecpool.c b/Build/source/texk/web2c/mpdir/makecpool.c new file mode 100644 index 00000000000..02ce0f94bea --- /dev/null +++ b/Build/source/texk/web2c/mpdir/makecpool.c @@ -0,0 +1,58 @@ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +int main(int argc, char *argv[]) { + if (argc!=3) { + puts("Need exactly two arguments: pool_name and header_name"); + exit(1); + } + char *filename = argv[1]; + char *headername = argv[2]; + FILE *fh = fopen(filename,"r"); + char data[1024]; + printf( + "/* This file is auto-generated by makecpool */\n" + "\n" + "#include <stdio.h>\n" + "#include \"%s\"\n" + "\n" + "static char *poolfilearr[] = {\n",headername); + while (fgets(data,1024,fh)) { + int len = strlen(data); + int o = 0; // skip first o characters + int i; + if (data[len-1]=='\n') { // chomp; + data[len-1] = 0; + len--; + } + if (data[0]=='*') break; // last if /^\*/; + if (data[0]>='0' && data[0]<='9' && data[1]>='0' && data[1]<='9') { + o=2; // $data =~ s/^\d\d//; + } + printf(" \""); + for (i=o; i<len; i++) { + if (data[i]=='"' || data[i]=='\\') putchar('\\'); + if (data[i]=='?') printf("\" \""); /* suppress trigraphs */ + putchar(data[i]); + } // $data =~ s/(["\\])/\\$1/g; + printf("\",\n"); + } + fclose(fh); + printf(" NULL };\n" + "int loadpoolstrings (integer spare_size) {\n" + " strnumber g=0;\n" + " int i=0,j=0;\n" + " char *s;\n" + " while ((s = poolfilearr[j++])) {\n" + " int l = strlen (s);\n" + " i += l;\n" + " if (i>=spare_size) return 0;\n" + " while (l-- > 0) strpool[poolptr++] = *s++;\n" + " g = makestring();\n" + " strref[g]= 127;\n" + " }\n" + " return g;\n" + "}\n"); + return 0; +} diff --git a/Build/source/texk/web2c/mpdir/mapfile.c b/Build/source/texk/web2c/mpdir/mapfile.c new file mode 100644 index 00000000000..25d5818f5c0 --- /dev/null +++ b/Build/source/texk/web2c/mpdir/mapfile.c @@ -0,0 +1,993 @@ +/* Copyright (c) 2006 Taco Hoekwater <taco@elvenkind.com> + +This file is part of MetaPost. + +MetaPost 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. + +MetaPost 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 MetaPost; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id: mapfile.c,v 1.20 2005/10/16 17:41:51 hahe Exp hahe $ + +*/ + +#include <math.h> +#include "mplib.h" +#include <kpathsea/c-auto.h> +#include <kpathsea/c-memstr.h> +#include <string.h> + +static const char perforce_id[] = + "$Id: mapfile.c,v 1.20 2005/10/16 17:41:51 hahe Exp hahe $"; + +#define FM_BUF_SIZE 1024 + +static FILE *fm_file; + +#define fm_open() \ + open_input (&fm_file, kpse_fontmap_format, FOPEN_RBIN_MODE) +#define fm_close() xfclose(fm_file, cur_file_name) +#define fm_getchar() xgetc(fm_file) +#define fm_eof() feof(fm_file) + +enum _mode { FM_DUPIGNORE, FM_REPLACE, FM_DELETE }; +enum _ltype { MAPFILE, MAPLINE }; +enum _tfmavail { TFM_UNCHECKED, TFM_FOUND, TFM_NOTFOUND }; + +typedef struct mitem { + int mode; /* FM_DUPIGNORE or FM_REPLACE or FM_DELETE */ + int 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; + +fm_entry *fm_cur; +static const char nontfm[] = "<nontfm>"; +static fm_entry *loaded_tfm_found; +static fm_entry *avail_tfm_found; +static fm_entry *non_tfm_found; +static fm_entry *not_avail_tfm_found; + +#define read_field(r, q, buf) do { \ + q = buf; \ + while (*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) + +#define cmp_return(a, b) \ + if (a > b) \ + return 1; \ + if (a < b) \ + return -1 + +fm_entry *new_fm_entry (void) +{ + fm_entry *fm; + fm = xtalloc (1, fm_entry); + fm->tfm_name = NULL; + fm->ps_name = NULL; + fm->flags = 4; + fm->ff_name = NULL; + fm->subset_tag = NULL; + fm->encoding = NULL; + fm->tfm_num = getnullfont (); + fm->tfm_avail = TFM_UNCHECKED; + fm->type = 0; + fm->slant = 0; + fm->extend = 0; + fm->ff_objnum = 0; + fm->fn_objnum = 0; + fm->fd_objnum = 0; + fm->charset = NULL; + fm->all_glyphs = false; + fm->links = 0; + fm->pid = -1; + fm->eid = -1; + fm->subfont = NULL; + return fm; +} + +void delete_fm_entry (fm_entry * fm) +{ + xfree (fm->tfm_name); + xfree (fm->ps_name); + xfree (fm->ff_name); + xfree (fm->subset_tag); + xfree (fm->charset); + 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; +} + +char *mk_base_tfm (char *tfmname, int *i) +{ + static char buf[SMALL_BUF_SIZE]; + char *p = tfmname, *r = strend (p) - 1, *q = r; + while (q > p && isdigit (*q)) + --q; + if (!(q > p) || q == r || (*q != '+' && *q != '-')) + return NULL; + check_buf (q - p + 1, SMALL_BUF_SIZE); + strncpy (buf, p, (size_t) (q - p)); + buf[q - p] = '\0'; + *i = atoi (q); + return buf; +} + +static fmentryptr fmlookup (fontnumber); + +boolean hasfmentry (fontnumber f) +{ + if (mpfontmap[f] == NULL) + mpfontmap[f] = fmlookup (f); + assert (mpfontmap[f] != NULL); + return mpfontmap[f] != (fmentryptr) dummy_fm_entry (); +} + +/**********************************************************************/ + +struct avl_table *tfm_tree = NULL; +struct avl_table *ps_tree = NULL; +struct avl_table *ff_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) +{ + const fm_entry *p1 = (const fm_entry *) pa, *p2 = (const fm_entry *) pb; + int i; + 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); + if (p1->tfm_name != NULL && p2->tfm_name != NULL && + (i = strcmp (p1->tfm_name, p2->tfm_name))) + return i; + 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 () +{ + if (tfm_tree == NULL) { + tfm_tree = avl_create (comp_fm_entry_tfm, NULL, &avl_xallocator); + assert (tfm_tree != NULL); + } + if (ps_tree == NULL) { + ps_tree = avl_create (comp_fm_entry_ps, NULL, &avl_xallocator); + assert (ps_tree != NULL); + } + if (ff_tree == NULL) { + ff_tree = avl_create (comp_ff_entry, NULL, &avl_xallocator); + assert (ff_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 * fp, int mode) +{ + fm_entry *p; + void *a; + void **aa; + + /* handle tfm_name link */ + + if (strcmp (fp->tfm_name, nontfm)) { + p = (fm_entry *) avl_find (tfm_tree, fp); + if (p != NULL) { + if (mode == FM_DUPIGNORE) { + pdftex_warn + ("fontmap entry for `%s' already exists, duplicates ignored", + fp->tfm_name); + goto exit; + } else { /* mode == FM_REPLACE / FM_DELETE */ + if (fontsizes[p->tfm_num]!=0) { + pdftex_warn + ("fontmap entry for `%s' has been used, replace/delete not allowed", + fp->tfm_name); + goto exit; + } + a = avl_delete (tfm_tree, p); + assert (a != NULL); + unset_tfmlink (p); + if (!has_pslink (p)) + delete_fm_entry (p); + } + } + if (mode != FM_DELETE) { + aa = avl_probe (tfm_tree, fp); + assert (aa != NULL); + set_tfmlink (fp); + } + } + + /* handle ps_name link */ + + if (fp->ps_name != NULL) { + assert (fp->tfm_name != NULL); + p = (fm_entry *) avl_find (ps_tree, fp); + if (p != NULL) { + if (mode == FM_DUPIGNORE) { + pdftex_warn + ("ps_name entry for `%s' already exists, duplicates ignored", + fp->ps_name); + goto exit; + } else { /* mode == FM_REPLACE / FM_DELETE */ + if (fontsizes[p->tfm_num]!=0) { + /* REPLACE/DELETE not allowed */ + pdftex_warn + ("fontmap entry for `%s' has been used, replace/delete not allowed", + p->tfm_name); + goto exit; + } + a = avl_delete (ps_tree, p); + assert (a != NULL); + unset_pslink (p); + if (!has_tfmlink (p)) + delete_fm_entry (p); + } + } + if (mode != FM_DELETE) { + aa = avl_probe (ps_tree, fp); + assert (aa != NULL); + set_pslink (fp); + } + } + exit: + if (!has_tfmlink (fp) && !has_pslink (fp)) /* e. g. after FM_DELETE */ + return 1; /* deallocation of fm_entry structure required */ + else + return 0; +} + +/**********************************************************************/ +/* consistency check for map entry, with warn flag */ + +int check_fm_entry (fm_entry * fm, boolean warn) +{ + int a = 0; + assert (fm != NULL); + if (fm->ps_name != NULL) { + if (is_basefont (fm)) { + if (is_fontfile (fm) && !is_included (fm)) { + if (warn) + pdftex_warn + ("invalid entry for `%s': font file must be included or omitted for base fonts", + fm->tfm_name); + a += 1; + } + } else { /* not a base font */ + /* if no font file given, drop this entry */ + /* if (!is_fontfile (fm)) { + if (warn) + pdftex_warn + ("invalid entry for `%s': font file missing", + fm->tfm_name); + a += 2; + } + */ + } + } + 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 += 4; + } + if ((fm->slant != 0 || fm->extend != 0) && + (is_truetype (fm))) { + if (warn) + pdftex_warn + ("invalid entry for `%s': SlantFont/ExtendFont can be used only with embedded T1 fonts", + fm->tfm_name); + a += 8; + } + 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 += 16; + } + 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 += 32; + } + if (fm->pid != -1 && + !(is_truetype (fm) && is_included (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 += 64; + } + return a; +} + +/**********************************************************************/ +/* returns true if s is one of the 14 std. font names; speed-trimmed. */ + +boolean check_basefont (char *s) +{ + static const char *basefont_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 (basefont_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); + *(--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); + p = r; + read_field (r, q, buf); + if (*buf != '<' && *buf != '"') + set_field (ps_name); + else + r = p; /* unget the field */ + if (isdigit (*r)) { /* font flags given */ + fm->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->encoding = add_enc (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_basefont (fm->ps_name)) + set_basefont (fm); + if (is_fontfile (fm) + && strcasecmp (strend (fm_fontfile (fm)) - 4, ".ttf") == 0) + set_truetype (fm); + 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 () +{ + 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_open ()) { + pdftex_warn ("cannot open font map file"); + } else { + cur_file_name = (char *) nameoffile + 1; + mp_printf ("{%s", cur_file_name); + while (!fm_eof ()) { + fm_scan_line (); + mitem->lineno++; + } + fm_close (); + mp_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; +} + +/**********************************************************************/ + +fontnumber tfmoffm (fmentryptr fm_pt) +{ + return ((fm_entry *) fm_pt)->tfm_num; +} + +static fm_entry *mk_ex_fm (fontnumber f, fm_entry * basefm, int ex) +{ + fm_entry *fm; + integer e = basefm->extend; + if (e == 0) + e = 1000; + fm = new_fm_entry (); + fm->flags = basefm->flags; + fm->encoding = basefm->encoding; + fm->type = basefm->type; + fm->slant = basefm->slant; + fm->extend = roundxnoverd (e, 1000 + ex, 1000); /* modify ExtentFont to simulate expansion */ + if (fm->extend == 1000) + fm->extend = 0; + fm->tfm_name = xstrdup (makecstring (fontname[f])); + if (basefm->ps_name != NULL) + fm->ps_name = xstrdup (basefm->ps_name); + fm->ff_name = xstrdup (basefm->ff_name); + fm->ff_objnum = 0; + fm->tfm_num = f; + fm->tfm_avail = TFM_FOUND; + assert (strcmp (fm->tfm_name, nontfm)); + return fm; +} + +static void init_fm (fm_entry * fm, fontnumber f) +{ + // if (fm->fd_objnum == 0 && !no_font_desc (fm)) + // fm->fd_objnum = pdfnewobjnum (); + // if (fm->ff_objnum == 0 && is_included (fm)) + // fm->ff_objnum = pdfnewobjnum (); + if (fm->tfm_num == getnullfont ()) { + fm->tfm_num = f; + fm->tfm_avail = TFM_FOUND; + } +} + +static fmentryptr fmlookup (fontnumber f) +{ + char *tfm; + fm_entry *fm, *exfm; + fm_entry tmp; + int ai, e; + if (tfm_tree == NULL) + fm_read_info (); /* only to read default map file */ + tfm = makecstring (fontname[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) { + init_fm (fm, f); + return (fmentryptr) fm; + } + tfm = mk_base_tfm (makecstring (fontname[f]), &e); + if (tfm == NULL) /* not an expanded font, nothing to do */ + return (fmentryptr) dummy_fm_entry (); + + tmp.tfm_name = tfm; + fm = (fm_entry *) avl_find (tfm_tree, &tmp); + if (fm != NULL) { /* found an entry with the base tfm name, e.g. cmr10 */ + return (fmentryptr) fm; /* font expansion uses the base font */ + /* the following code would be obsolete, as would be mk_ex_fm() */ + if (!is_t1fontfile (fm) || !is_included (fm)) { + pdftex_warn + ("font %s cannot be expanded (not an included Type1 font)", + tfm); + return (fmentryptr) dummy_fm_entry (); + } + exfm = mk_ex_fm (f, fm, e); /* copies all fields from fm except tfm name */ + init_fm (exfm, f); + ai = avl_do_entry (exfm, FM_DUPIGNORE); + assert (ai == 0); + return (fmentryptr) exfm; + } + return (fmentryptr) dummy_fm_entry (); +} + +/* + Early check whether a font file exists. Used e. g. for replacing fonts + of embedded PDF files: Without font file, the font within the embedded + PDF-file is used. 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 (fm_entry * fm) +{ + ff_entry *ff; + ff_entry tmp; + void **aa; + + assert (fm->ff_name != NULL); + tmp.ff_name = fm->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 (fm->ff_name); + if (is_truetype (fm)) + ff->ff_path = kpse_find_file (fm->ff_name, kpse_truetype_format, 0); + else + ff->ff_path = kpse_find_file (fm->ff_name, kpse_type1_format, 0); + aa = avl_probe (ff_tree, ff); + assert (aa != NULL); + } + return ff; +} + +/**********************************************************************/ + +static boolean used_tfm (fm_entry * p) +{ + fontnumber f; + strnumber s; + ff_entry *ff; + + /* check if the font file is not a TrueType font */ + /* font replacement makes sense only for included Type1 files */ + if (is_truetype (p) || !is_included (p)) + return false; + + /* check if the font file is available */ + ff = check_ff_exist (p); + if (ff->ff_path == NULL) + return false; + + /* check whether this font has been used */ + if (fontsizes[p->tfm_num]!=0) + return true; + assert (p->tfm_name != NULL); + + /* check whether we didn't find a loaded font yet, + * and this font has been loaded */ + if (loaded_tfm_found == NULL && strcmp (p->tfm_name, nontfm)) { + s = maketexstring (p->tfm_name); + if ((f = tfmlookup (s, 0)) != getnullfont ()) { + loaded_tfm_found = p; + if (mpfontmap[f] == NULL) + mpfontmap[f] = (fmentryptr) p; + if (p->tfm_num == getnullfont ()) + p->tfm_num = f; + assert (p->tfm_num == f); + /* don't call flushstr() here as it has been called by tfmlookup() */ + } else + flushstr (s); + } + + /* check whether we didn't find either a loaded or a loadable font yet, + * and this font is loadable */ + if (avail_tfm_found == NULL && loaded_tfm_found == NULL && + strcmp (p->tfm_name, nontfm)) { + if (p->tfm_avail == TFM_UNCHECKED) { + if (kpse_find_file (p->tfm_name, kpse_tfm_format, 0) != NULL) { + avail_tfm_found = p; + p->tfm_avail = TFM_FOUND; + } else { + p->tfm_avail = TFM_NOTFOUND; + if (not_avail_tfm_found == NULL) + not_avail_tfm_found = p; + } + } + } + + /* check whether the current entry is a <nontfm> entry */ + if (non_tfm_found == NULL && !strcmp (p->tfm_name, nontfm)) + non_tfm_found = p; + + return false; +} + +/* lookup_ps_name looks for an entry with a given ps name + slant + extend; + * return NULL if not found. + * + * As there may exist several such entries, we need to select the `right' + * one. We do so by checking all such entries and return the first one that + * fulfils the following criteria (in descending priority): + * + * - the tfm has been used (some char from this font has been typeset) + * - the tfm has been loaded (but not used yet) + * - the tfm can be loaded (but not loaded yet) + * - the tfm is present in map files, but cannot be loaded. In this case a + * dummy tfm can be loaded instead, and a warning should be written out + */ + +static fm_entry *lookup_ps_name (fm_entry * fm) +{ + fm_entry *p, *p2; + struct avl_traverser t, t2; + int a; + + loaded_tfm_found = NULL; + avail_tfm_found = NULL; + non_tfm_found = NULL; + not_avail_tfm_found = NULL; + + assert (fm->tfm_name == NULL); + p = (fm_entry *) avl_t_find (&t, ps_tree, fm); + if (p == NULL) + return NULL; + t2 = t; + p2 = (fm_entry *) avl_t_prev (&t2); + + /* search forward */ + do { + if (used_tfm (p)) + return p; + p = (fm_entry *) avl_t_next (&t); + } + while (p != NULL && comp_fm_entry_ps (fm, p, NULL) == 0); + + /* search backward */ + while (p2 != NULL && comp_fm_entry_ps (fm, p2, NULL) == 0) { + if (used_tfm (p2)) + return p2; + p2 = (fm_entry *) avl_t_prev (&t2); + } + + if (loaded_tfm_found != NULL) + p = loaded_tfm_found; + else if (avail_tfm_found != NULL) { + /* TH: do not do this for metapost, there is no embedding anyway */ + /* p = avail_tfm_found; + * p->tfm_num = readfontinfo (getnullcs (), maketexstring (p->tfm_name), + * getnullstr (), -1000); + * p->tfm_avail = TFM_FOUND; + */ + } else if (non_tfm_found != NULL) { + p = non_tfm_found; + p->tfm_num = newdummyfont (); + p->tfm_avail = TFM_FOUND; + } else if (not_avail_tfm_found != NULL) { + p = not_avail_tfm_found; + pdftex_warn ("`%s' not loadable, use a dummy tfm instead", p->tfm_name); + p2 = new_fm_entry (); + p2->flags = p->flags; + p2->encoding = p->encoding; + p2->type = p->type; + p2->slant = p->slant; + p2->extend = p->extend; + p2->tfm_name = xstrdup (nontfm); + p2->ps_name = xstrdup (p->ps_name); + if (p->ff_name != NULL) + p2->ff_name = xstrdup (p->ff_name); + p2->tfm_num = newdummyfont (); + p2->tfm_avail = TFM_FOUND; + a = avl_do_entry (p2, FM_DUPIGNORE); + assert (a == 0); + p = p2; + } else + return NULL; + assert (p->tfm_num != getnullfont ()); + return p; +} + + +/**********************************************************************/ +/* +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 mpmapfile (strnumber t) +{ + char *s = xstrdup(makecstring (t)); + process_map_item (s, MAPFILE); + xfree (s); +} + +void mpmapline (strnumber t) +{ + char *s = xstrdup(makecstring (t)); + process_map_item (s, MAPLINE); + xfree (s); +} + +void mpinitmapfile (void) +{ + assert (mitem == NULL); + mitem = xtalloc (1, mapitem); + mitem->mode = FM_DUPIGNORE; + mitem->type = MAPFILE; + if (kpse_find_file("mpost.map", kpse_fontmap_format,0)) + mitem->line = xstrdup ("mpost.map"); + else + mitem->line = xstrdup ("pdftex.map"); +} + +/**********************************************************************/ +/* 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); + if (ps_tree != NULL) + avl_destroy (ps_tree, destroy_fm_entry_ps); + if (ff_tree != NULL) + avl_destroy (ff_tree, destroy_ff_entry); +} + +/**********************************************************************/ +/* end of mapfile.c */ diff --git a/Build/source/texk/web2c/mpdir/mp.defines b/Build/source/texk/web2c/mpdir/mp.defines new file mode 100644 index 00000000000..bdd51f83332 --- /dev/null +++ b/Build/source/texk/web2c/mpdir/mp.defines @@ -0,0 +1,54 @@ +{ +Copyright (c) 2006 Taco Hoekwater <taco@elvenkind.com> + +This file is part of MetaPost. + +MetaPost 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. + +MetaPost 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 MetaPost; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id$ +} + +{ functions from loadpool.c } + +@define function loadpoolstrings(); + +{ functions from mapfile.c } + +@define function hasfmentry(); +@define function tfmoffm(); +@define procedure mpmapfile(); +@define procedure mpmapline(); +@define procedure mpinitmapfile; + +{ functions from writefont.c } + +@define procedure mploadencodings(); +@define procedure mpfontencodings(); +@define function fontisreencoded(); +@define function fontisincluded(); +@define function fontissubsetted(); + +@define function fmencodingname(); +@define function fmfontname(); +@define function fmfontsubsetname(); +@define function fmfontslant(); +@define function fmfontextend(); + +@define function dopsfont(); + +{ functions from utils.c } + +@define procedure setjobid(); + diff --git a/Build/source/texk/web2c/mpdir/mplib.h b/Build/source/texk/web2c/mpdir/mplib.h new file mode 100644 index 00000000000..363836a994d --- /dev/null +++ b/Build/source/texk/web2c/mpdir/mplib.h @@ -0,0 +1,300 @@ +/* +Copyright (c) 2006 Taco Hoekwater <taco@elvenkind.com> + +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$ +*/ + +#ifndef MPOSTLIB +# define MPOSTLIB + +/* WEB2C macros and prototypes */ +# if !defined(MPOSTCOERCE) +# define EXTERN extern +# include "mpd.h" +# endif + +/* pdftexlib macros */ +# include "mpmac.h" + +# include "avlstuff.h" + + +/* pdftexlib type declarations */ +typedef struct { + const char *pdfname; + const char *t1name; + float value; + boolean valid; +} key_entry; + +typedef struct { + boolean loaded; /* the encoding has been loaded? */ + char *name; /* encoding file name */ + char *encname; /* encoding true name */ + integer objnum; /* object number */ + char **glyph_names; + integer tounicode; /* object number of associated ToUnicode entry */ +} enc_entry; + +struct _subfont_entry; +typedef struct _subfont_entry subfont_entry; + +struct _subfont_entry { + char *infix; /* infix for this subfont, eg "01" */ + long charcodes[256]; /* the mapping for this subfont as read from sfd */ + subfont_entry *next; +}; + +typedef struct { + char *name; /* sfd name, eg "Unicode" */ + subfont_entry *subfont; /* linked list of subfonts */ +} sfd_entry; + +typedef struct { + char *name; /* glyph name */ + long code; /* -1 = undefined; -2 = multiple codes, stored + as string in unicode_seq; otherwise unicode value */ + char *unicode_seq; /* multiple unicode sequence */ +} glyph_unicode_entry; + +typedef struct { + char *tfm_name; /* TFM file name */ + char *ps_name; /* PostScript name */ + integer flags; /* font flags */ + char *ff_name; /* font file name */ + char *subset_tag; /* pseudoUniqueTag for subsetted font */ + enc_entry *encoding; /* pointer to corresponding encoding */ + fontnumber tfm_num; /* number of the TFM refering this entry */ + unsigned short type; /* font type (T1/TTF/...) */ + short slant; /* SlantFont */ + short extend; /* ExtendFont */ + integer ff_objnum; /* FontFile object number */ + integer fn_objnum; /* FontName/BaseName object number */ + integer fd_objnum; /* FontDescriptor object number */ + char *charset; /* string containing used glyphs */ + boolean all_glyphs; /* embed all glyphs? */ + unsigned short links; /* link flags from tfm_tree and ps_tree */ + short tfm_avail; /* flags whether a tfm is available */ + short pid; /* Pid for truetype fonts */ + short eid; /* Eid for truetype fonts */ + subfont_entry *subfont; /* subfont mapping */ +} fm_entry; + +typedef struct { + char *ff_name; /* base name of font file */ + char *ff_path; /* full path to font file */ +} ff_entry; + +typedef short shalfword; +typedef struct { + integer charcode, cwidth, cheight, xoff, yoff, xescape, rastersize; + halfword *raster; +} chardesc; + +/* pdftexlib variable declarations */ +extern boolean fontfile_found; +extern boolean is_otf_font; +extern boolean true_dimen; +extern boolean write_ttf_glyph_names; +extern char **t1_glyph_names, *t1_builtin_glyph_names[]; +extern char *cur_file_name; +extern const char notdef[]; +extern integer t1_length1, t1_length2, t1_length3; +extern integer ttf_length; +extern key_entry font_keys[]; +extern strnumber last_tex_string; +extern size_t last_ptr_index; +extern char fontname_buf[]; + +/* pdftexlib function prototypes */ + +/* epdf.c */ +extern integer get_fontfile_num (int); +extern integer get_fontname_num (int); +extern void epdf_free (void); +extern int is_type1 (fm_entry *); + +/* mapfile.c */ +extern char *mk_basename (char *); +extern char *mk_exname (char *, int); +extern fm_entry *lookup_fontmap (char *); +extern boolean hasfmentry (fontnumber); +extern fontnumber tfmoffm (fmentryptr); +extern void checkextfm (strnumber, integer); +extern void fm_free (void); +extern void fm_read_info (void); +extern ff_entry *check_ff_exist (fm_entry *); +extern void pdfmapfile (integer); +extern void pdfmapline (integer); +extern void pdfinitmapfile (string map_name); +extern fm_entry *new_fm_entry (void); +extern void delete_fm_entry (fm_entry *); +extern int avl_do_entry (fm_entry *, int); + +/* papersiz.c */ +extern integer myatodim (char **); +extern integer myatol (char **); + +/* pkin.c */ +extern int readchar (boolean, chardesc *); + +/* subfont.c */ +extern void sfd_free (void); +extern boolean handle_subfont_fm (fm_entry *, int); + +/* tounicode.c */ +extern void glyph_unicode_free (void); +extern void deftounicode (strnumber, strnumber); +extern integer write_tounicode (char **, char *); + +/* utils.c */ +extern boolean str_eq_cstr (strnumber, char *); +extern char *makecstring (integer); +extern int xfflush (FILE *); +extern int xgetc (FILE *); +extern int xputc (int, FILE *); +extern scaled extxnoverd (scaled, scaled, scaled); +extern size_t xfwrite (void *, size_t size, size_t nmemb, FILE *); +extern strnumber getresnameprefix (void); +extern strnumber maketexstring (const char *); +extern integer fb_offset (void); +extern void fb_flush (void); +extern void fb_putchar (eightbits b); +extern void fb_seek (integer); +extern void libpdffinish (void); +extern char *makecfilename (strnumber s); +extern void make_subset_tag (fm_entry *, char **, int); +extern void pdf_printf (const char *, ...); +extern void pdf_puts (const char *); +extern void pdftex_fail (const char *, ...); +extern void pdftex_warn (const char *, ...); +extern void setjobid (int, int, int, int); +extern void mp_printf (const char *, ...); +extern void writestreamlength (integer, integer); +extern char *convertStringToPDFString (const char *in, int len); +extern void printID (strnumber); +extern void printcreationdate (); +extern void printmoddate (); +extern void escapename (poolpointer in); +extern void escapestring (poolpointer in); +extern void escapehex (poolpointer in); +extern void unescapehex (poolpointer in); +extern void getcreationdate (); +extern void getfilemoddate (strnumber s); +extern void getfilesize (strnumber s); +extern void getmd5sum (strnumber s, boolean file); +extern void getfiledump (strnumber s, int offset, int length); +extern void matchstrings (strnumber s, strnumber t, int subcount, + boolean icase); +extern void getmatch (int i); +extern void makepdftexbanner (void); +extern void initstarttime (); +extern void removepdffile (void); +extern void garbagewarning (void); +extern void stripspaces (char *p); +extern void initversionstring (char **versions); +extern int newcolorstack (integer s, integer literal_mode, boolean pagestart); +extern int colorstackused (); +extern integer colorstackset (int colstack_no, integer s); +extern integer colorstackpush (int colstack_no, integer s); +extern integer colorstackpop (int colstack_no); +extern integer colorstackcurrent (int colstack_no); +extern integer colorstackskippagestart (int colstack_no); +extern void checkpdfsave (int cur_h, int cur_v); +extern void checkpdfrestore (int cur_h, int cur_v); +extern void pdfshipoutbegin (boolean shipping_page); +extern void pdfshipoutend (boolean shipping_page); +extern void pdfsetmatrix (poolpointer in, scaled cur_h, scaled cur_v); +extern void matrixtransformpoint (scaled x, scaled y); +extern void matrixtransformrect (scaled llx, scaled lly, scaled urx, + scaled ury); +extern boolean matrixused (); +extern void matrixrecalculate (scaled urx); +extern scaled getllx (); +extern scaled getlly (); +extern scaled geturx (); +extern scaled getury (); + +/* vfpacket.c */ +extern eightbits packetbyte (void); +extern integer newvfpacket (fontnumber); +extern void poppacketstate (void); +extern void pushpacketstate (void); +extern void startpacket (fontnumber, integer); +extern void storepacket (integer, integer, integer); +extern void vf_free (void); + +/* writeenc.c */ +extern boolean indexed_enc (fm_entry *); +extern enc_entry *add_enc (char *); +extern void enc_free (void); +extern void read_enc (enc_entry *); +extern void write_enc (char **, enc_entry *, integer); + +/* writefont.c */ +extern boolean dopsfont (fontnumber); + +/* writeimg.c */ +extern boolean checkimageb (integer); +extern boolean checkimagec (integer); +extern boolean checkimagei (integer); +extern boolean ispdfimage (integer); +extern integer epdforigx (integer); +extern integer epdforigy (integer); +extern integer imageheight (integer); +extern integer imagepages (integer); +extern integer imagewidth (integer); +extern integer imagexres (integer); +extern integer imageyres (integer); +extern integer readimage (strnumber, integer, strnumber, integer, integer, + integer, integer); +extern void deleteimage (integer); +extern void img_free (void); +extern void updateimageprocset (integer); +extern void writeimage (integer); +extern integer imagecolordepth (integer img); + +/* writejbig2.c */ +extern void flushjbig2page0objects (); + +/* writet1.c */ +extern boolean t1_subset (char *, char *, unsigned char *); +extern void load_enc (char *, char **, char **); +extern void writet1 (int, fm_entry *); +extern void t1_free (void); + +#define bitfile psfile + +/* writet3.c */ +extern void writet3 (int, fontnumber); +extern scaled getpkcharwidth (fontnumber, scaled); + +/* writettf.c */ +extern void writettf (void); +extern void writeotf (void); +extern void ttf_free (void); + +/* writezip.c */ +extern void writezip (boolean); + +/* avlstuff.c */ +extern void avlputobj (integer, integer); +extern integer avlfindobj (integer, integer, integer); + +#endif /* MPOSTLIB */ diff --git a/Build/source/texk/web2c/mpdir/mpmac.h b/Build/source/texk/web2c/mpdir/mpmac.h new file mode 100644 index 00000000000..bc9e6a79640 --- /dev/null +++ b/Build/source/texk/web2c/mpdir/mpmac.h @@ -0,0 +1,218 @@ +/* +Copyright (c) 2006 Taco Hoekwater <taco@elvenkind.com> + +This file is part of MetaPost. + +MetaPost 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. + +MetaPost 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 MetaPost; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id $ +*/ + +#ifndef MPOSTMAC +# define MPOSTMAC + +/* Not all systems define it. */ +# ifndef M_PI +# define M_PI 3.14159265358979323846 + /* pi */ +# define M_PI_2 1.5707963267948966192E0 + /*Hex 2^ 0 * 1.921FB54442D18 */ +# define M_PI_4 7.8539816339744830962E-1 + /*Hex 2^-1 * 1.921FB54442D18 */ +# endif + +# ifdef WIN32 +// Why relying on gmalloc() ??? +# define gmalloc(n) xmalloc(n) +# define gfree(p) free(p) +# define inline __inline +# define srandom(n) srand(n) +# define random() rand() +# endif + +/* Pascal WEB macros */ +# define maxinteger 0x7FFFFFFF +# define maxdimen 0x3FFFFFFF + +# define objinfo(n) objtab[n].int0 + +# define pdfroom(n) do { \ + if ((unsigned)(n + pdfptr) > (unsigned)pdfbufsize) { \ + if (pdfosmode) \ + zpdfosgetosbuf(n); \ + else { \ + if ((unsigned)(n) > (unsigned)pdfbufsize) \ + pdftex_fail("PDF output buffer overflowed"); \ + else \ + pdfflush(); \ + } \ + } \ +} while (0) + +# define pdfout(c) do { \ + pdfroom(1); \ + pdfbuf[pdfptr++] = c; \ +} while (0) + +# define pdfoffset() (pdfgone + pdfptr) +# define pdfinitfont(f) {tmpf = f; pdfcreatefontobj();} + +# define MAX_CHAR_CODE 255 +# define PRINTF_BUF_SIZE 1024 +# define MAX_CSTRING_LEN 1024 * 1024 +# define MAX_PSTRING_LEN 1024 +# define SMALL_BUF_SIZE 256 +# define SMALL_ARRAY_SIZE 256 +# define FONTNAME_BUF_SIZE 128 + /* a PDF name can be maximum 127 chars long */ + +# define pdftex_debug tex_printf + +# define check_buf(size, buf_size) \ + if ((unsigned)(size) > (unsigned)(buf_size)) \ + pdftex_fail("buffer overflow: (%d,%d) at file %s, line %d",size,buf_size, __FILE__, __LINE__ ) + +# define append_char_to_buf(c, p, buf, buf_size) do { \ + if (c == 9) \ + c = 32; \ + if (c == 13 || c == EOF) \ + c = 10; \ + if (c != ' ' || (p > buf && p[-1] != 32)) { \ + check_buf(p - buf + 1, (buf_size)); \ + *p++ = c; \ + } \ +} while (0) + +# define append_eol(p, buf, buf_size) do { \ + check_buf(p - buf + 2, (buf_size)); \ + if (p - buf > 1 && p[-1] != 10) \ + *p++ = 10; \ + if (p - buf > 2 && p[-2] == 32) { \ + p[-2] = 10; \ + p--; \ + } \ + *p = 0; \ +} while (0) + +# define remove_eol(p, buf) do { \ + p = strend(buf) - 1; \ + if (*p == 10) \ + *p = 0; \ +} while (0) + +# define skip(p, c) if (*p == c) p++ + +# define alloc_array(T, n, s) do { \ + if (T##_array == NULL) { \ + T##_limit = (s); \ + if ((unsigned)(n) > T##_limit) \ + T##_limit = (n); \ + T##_array = xtalloc(T##_limit, T##_entry); \ + T##_ptr = T##_array; \ + } \ + else if ((unsigned)(T##_ptr - T##_array + (n)) > T##_limit) { \ + last_ptr_index = T##_ptr - T##_array; \ + T##_limit *= 2; \ + if ((unsigned)(T##_ptr - T##_array + (n)) > T##_limit) \ + T##_limit = T##_ptr - T##_array + (n); \ + xretalloc(T##_array, T##_limit, T##_entry); \ + T##_ptr = T##_array + last_ptr_index; \ + } \ +} while (0) + +# define is_cfg_comment(c) \ + (c == 10 || c == '*' || c == '#' || c == ';' || c == '%') + +# define define_array(T) \ +T##_entry *T##_ptr, *T##_array = NULL; \ +size_t T##_limit + +# define xfree(p) do { if (p != NULL) free(p); p = NULL; } while (0) +# define strend(s) strchr(s, 0) +# define xtalloc XTALLOC +# define xretalloc XRETALLOC + +# define ASCENT_CODE 0 +# define CAPHEIGHT_CODE 1 +# define DESCENT_CODE 2 +# define FONTNAME_CODE 3 +# define ITALIC_ANGLE_CODE 4 +# define STEMV_CODE 5 +# define XHEIGHT_CODE 6 +# define FONTBBOX1_CODE 7 +# define FONTBBOX2_CODE 8 +# define FONTBBOX3_CODE 9 +# define FONTBBOX4_CODE 10 +# define MAX_KEY_CODE (FONTBBOX1_CODE + 1) +# define FONT_KEYS_NUM (FONTBBOX4_CODE + 1) + +# define F_INCLUDED 0x01 +# define F_SUBSETTED 0x02 +# define F_TRUETYPE 0x04 +# define F_BASEFONT 0x08 +# define F_SUBFONT 0x10 + +# define set_included(fm) ((fm)->type |= F_INCLUDED) +# define set_subsetted(fm) ((fm)->type |= F_SUBSETTED) +# define set_truetype(fm) ((fm)->type |= F_TRUETYPE) +# define set_basefont(fm) ((fm)->type |= F_BASEFONT) +# define set_subfont(fm) ((fm)->type |= F_SUBFONT) + +# define unset_included(fm) ((fm)->type &= ~F_INCLUDED) +# define unset_subsetted(fm) ((fm)->type &= ~F_SUBSETTED) +# define unset_truetype(fm) ((fm)->type &= ~F_TRUETYPE) +# define unset_basefont(fm) ((fm)->type &= ~F_BASEFONT) +# define unset_subfont(fm) ((fm)->type &= ~F_SUBFONT) + +# define unset_fontfile(fm) xfree((fm)->ff_name) + +# define is_included(fm) ((fm)->type & F_INCLUDED) +# define is_subsetted(fm) ((fm)->type & F_SUBSETTED) +# define is_truetype(fm) ((fm)->type & F_TRUETYPE) +# define is_basefont(fm) ((fm)->type & F_BASEFONT) +# define is_subfont(fm) ((fm)->type & F_SUBFONT) +# define no_font_desc(fm) (is_basefont(fm) && !is_included(fm)) + +# define fm_slant(fm) (fm)->slant +# define fm_extend(fm) (fm)->extend +# define fm_fontfile(fm) (fm)->ff_name + +# define is_reencoded(fm) ((fm)->encoding != NULL) +# define is_fontfile(fm) (fm_fontfile(fm) != NULL) +# define is_t1fontfile(fm) (is_fontfile(fm) && !is_truetype(fm)) + +# define LINK_TFM 0x01 +# define LINK_PS 0x02 +# define set_tfmlink(fm) ((fm)->links |= LINK_TFM) +# define set_pslink(fm) ((fm)->links |= LINK_PS) +# define unset_tfmlink(fm) ((fm)->links &= ~LINK_TFM) +# define unset_pslink(fm) ((fm)->links &= ~LINK_PS) +# define has_tfmlink(fm) ((fm)->links & LINK_TFM) +# define has_pslink(fm) ((fm)->links & LINK_PS) + + +# define set_cur_file_name(s) \ + cur_file_name = s; \ + packfilename(maketexstring(cur_file_name), getnullstr(), getnullstr()) + +# define cmp_return(a, b) \ + if (a > b) \ + return 1; \ + if (a < b) \ + return -1 + +# define str_prefix(s1, s2) (strncmp((s1), (s2), strlen(s2)) == 0) + +#endif /* MPOSTMAC */ diff --git a/Build/source/texk/web2c/mpdir/mpostlib.mk b/Build/source/texk/web2c/mpdir/mpostlib.mk new file mode 100644 index 00000000000..01d798b60bb --- /dev/null +++ b/Build/source/texk/web2c/mpdir/mpostlib.mk @@ -0,0 +1,29 @@ +## mpostlib.mk - Makefile fragment for libraries used by mpost +# Public domain. + +# Include dependencies to get the built if we don't do make +# from the top-level directory. + +Makefile: mpdir/mpostlib.mk + +# libmpost +mpostlib = mpdir/libmpost.a +mpostlib_sources = $(srcdir)/mpdir/*.c $(srcdir)/mpdir/*.h + +mpdir/libmpost.a: $(mpostlib_sources) + cd mpdir && $(MAKE) $(common_makeargs) libmpost.a + +# makecpool + +makecpool = mpdir/makecpool + +mpdir/makecpool: mpdir/makecpool.c + cd mpdir && $(MAKE) $(common_makeargs) makecpool + +# Convenience variables. + +mpostlibs = $(mpostlib) +mpostlibsdep = $(mpostlib) $(makecpool) + +## end of mpostlib.mk - Makefile fragment for libraries used by mpost + diff --git a/Build/source/texk/web2c/mpdir/utils.c b/Build/source/texk/web2c/mpdir/utils.c new file mode 100644 index 00000000000..16de3f5a8d3 --- /dev/null +++ b/Build/source/texk/web2c/mpdir/utils.c @@ -0,0 +1,719 @@ +/* Copyright (c) 2006 Taco Hoekwater <taco@elvenkind.com> + +This file is part of MetaPost. + +MetaPost 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. + +MetaPost 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 MetaPost; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id $ +*/ + +#ifdef HAVE_ASPRINTF /* asprintf is not defined in openbsd-compat.h, but in stdio.h */ +# include <stdio.h> +#endif +#include <sys/types.h> + +#include <kpathsea/c-proto.h> +#include <kpathsea/c-stat.h> +#include <kpathsea/c-fopen.h> +#include <string.h> +#include <time.h> +#include <float.h> /* for DBL_EPSILON */ +#include "mplib.h" + +/* define char_ptr, char_array & char_limit */ +typedef char char_entry; +define_array (char); + +#define Z_NULL 0 + +typedef unsigned char Byte; +typedef Byte Bytef; + +#define check_nprintf(size_get, size_want) \ + if ((unsigned)(size_get) >= (unsigned)(size_want)) \ + pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__); + +/*@unused@*/ +static const char perforce_id[] = + "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/utils.c#24 $"; + +char *cur_file_name = NULL; +strnumber last_tex_string; +static char print_buf[PRINTF_BUF_SIZE]; +static char *jobname_cstr = NULL; +static char *job_id_string = NULL; +extern string ptexbanner; /* from web2c/lib/texmfmp.c */ +extern string versionstring; /* from web2c/lib/version.c */ +extern KPSEDLL string kpathsea_version_string; /* from kpathsea/version.c */ + +size_t last_ptr_index; /* for use with alloc_array */ + + + +void pdf_puts (const char *s) +{ + while (*s) + fputc(*s++,psfile); +} + +void pdf_printf (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args); + pdf_puts (print_buf); + va_end (args); +} + +strnumber maketexstring (const char *s) +{ + size_t l; + if (s == NULL || *s == 0) + return getnullstr (); + l = strlen (s); + check_buf (poolptr + l, poolsize); + while (l-- > 0) + strpool[poolptr++] = *s++; + last_tex_string = makestring (); + return last_tex_string; +} + +void mp_printf (const char *fmt, ...) +{ + va_list args; + int saved_selector; + saved_selector = selector; + va_start (args, fmt); + vsnprintf (print_buf, PRINTF_BUF_SIZE, fmt, args); + selector = gettermandlogid(); + print (maketexstring (print_buf)); + flushstr (last_tex_string); + xfflush (stdout); + va_end (args); + selector = saved_selector; /* ps_file_only, probably */ +} + +/* Helper for pdftex_fail. */ +static void safe_print (const char *str) +{ + const char *c; + for (c = str; *c; ++c) + print (*c); +} + +/* pdftex_fail may be called when a buffer overflow has happened/is + happening, therefore may not call mktexstring. However, with the + current implementation it appears that error messages are misleading, + possibly because pool overflows are detected too late. + + The output format of this fuction must be the same as pdf_error in + pdftex.web! */ + +void pdftex_fail (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + fputs ("\nError: module writet1", stderr); + if (cur_file_name) + fprintf (stderr, " (file %s)", cur_file_name); + fputs (": ", stderr); + vsprintf (print_buf, fmt, args); + fputs (print_buf, stderr); + fputs + ("\n ==> Fatal error occurred, the output PS file is not finished!\n", + stderr); + va_end (args); + exit (1); +} + +/* The output format of this fuction must be the same as pdf_warn in + pdftex.web! */ +void pdftex_warn (const char *fmt, ...) +{ + va_list args; + va_start (args, fmt); + fputs ("\nWarning: module writet1", stderr); + if (cur_file_name) + fprintf (stderr, " (file %s)", cur_file_name); + fputs (": ", stderr); + vsprintf (print_buf, fmt, args); + fputs (print_buf, stderr); + fputs ("\n", stderr); + va_end (args); +} + + +static char *cstrbuf = NULL; + +char *makecstring (integer s) +{ + char *p; + static int allocsize; + int allocgrow, i, l ; + if (s==0) + return ""; + l = strstart[nextstr[s]] - strstart[s]; + if (l==0) + return ""; + check_buf (l + 1, MAX_CSTRING_LEN); + if (cstrbuf == NULL) { + allocsize = l + 1; + cstrbuf = xmallocarray (char, allocsize); + } else if (l + 1 > allocsize) { + allocgrow = allocsize * 0.2; + if (l + 1 - allocgrow > allocsize) + allocsize = l + 1; + else if (allocsize < MAX_CSTRING_LEN - allocgrow) + allocsize += allocgrow; + else + allocsize = MAX_CSTRING_LEN; + cstrbuf = xrealloc (cstrbuf, sizeof (char) * allocsize); + } + p = cstrbuf; + for (i = 0; i < l; i++) + *p++ = strpool[i + strstart[s]]; + *p = 0; + return cstrbuf; +} + +size_t xfwrite (void *ptr, size_t size, size_t nmemb, FILE * stream) +{ + if (fwrite (ptr, size, nmemb, stream) != nmemb) + pdftex_fail ("fwrite() failed"); + return nmemb; +} + +int xfflush (FILE * stream) +{ + if (fflush (stream) != 0) + pdftex_fail ("fflush() failed"); + return 0; +} + +int xgetc (FILE * stream) +{ + int c = getc (stream); + if (c < 0 && c != EOF) + pdftex_fail ("getc() failed"); + return c; +} + +int xputc (int c, FILE * stream) +{ + int i = putc (c, stream); + if (i < 0) + pdftex_fail ("putc() failed"); + return i; +} + + +scaled extxnoverd (scaled x, scaled n, scaled d) +{ + double r = (((double) x) * ((double) n)) / ((double) d); + if (r > DBL_EPSILON) + r += 0.5; + else + r -= 0.5; + if (r >= (double) maxinteger || r <= -(double) maxinteger) + pdftex_warn ("arithmetic: number too big"); + return (scaled) r; +} + +/* Converts any string given in in in an allowed PDF string which can be + * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and + * control characters are octal encoded. + * This assumes that the string does not contain any already escaped + * characters! + */ +char *convertStringToPDFString (const char *in, int len) +{ + static char pstrbuf[MAX_PSTRING_LEN]; + char *out = pstrbuf; + int i, j = 0, k; + char buf[5]; + for (i = 0; i < len; i++) { + check_buf (j + sizeof (buf), MAX_PSTRING_LEN); + if (((unsigned char) in[i] < '!') || ((unsigned char) in[i] > '~')) { + /* convert control characters into oct */ + k = snprintf (buf, sizeof (buf), + "\\%03o", (unsigned int) (unsigned char) in[i]); + check_nprintf (k, sizeof (buf)); + out[j++] = buf[0]; + out[j++] = buf[1]; + out[j++] = buf[2]; + out[j++] = buf[3]; + } else if ((in[i] == '(') || (in[i] == ')')) { + /* escape paranthesis */ + out[j++] = '\\'; + out[j++] = in[i]; + } else if (in[i] == '\\') { + /* escape backslash */ + out[j++] = '\\'; + out[j++] = '\\'; + } else { + /* copy char :-) */ + out[j++] = in[i]; + } + } + out[j] = '\0'; + return pstrbuf; +} + + +/* Converts any string given in in in an allowed PDF string which can be + * handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and + * control characters are octal encoded. + * This assumes that the string does not contain any already escaped + * characters! + * + * See escapename for parameter description. + */ +void escapestring (poolpointer in) +{ + const poolpointer out = poolptr; + unsigned char ch; + while (in < out) { + if (poolptr + 4 >= poolsize) { + poolptr = poolsize; + /* error by str_toks that calls str_room(1) */ + return; + } + + ch = (unsigned char) strpool[in++]; + + if ((ch < '!') || (ch > '~')) { + /* convert control characters into oct */ + int i = snprintf ((char *) &strpool[poolptr], 5, + "\\%.3o", (unsigned int) ch); + check_nprintf (i, 5); + poolptr += i; + continue; + } + if ((ch == '(') || (ch == ')') || (ch == '\\')) { + /* escape parenthesis and backslash */ + strpool[poolptr++] = '\\'; + } + /* copy char :-) */ + strpool[poolptr++] = ch; + } +} + +/* Convert any given string in a PDF name using escaping mechanism + of PDF 1.2. The result does not include the leading slash. + + PDF specification 1.6, section 3.2.6 "Name Objects" explains: + <blockquote> + Beginning with PDF 1.2, any character except null (character code 0) may + be included in a name by writing its 2-digit hexadecimal code, preceded + by the number sign character (#); see implementation notes 3 and 4 in + Appendix H. This syntax is required to represent any of the delimiter or + white-space characters or the number sign character itself; it is + recommended but not required for characters whose codes are outside the + range 33 (!) to 126 (~). + </blockquote> + The following table shows the conversion that are done by this + function: + code result reason + ----------------------------------- + 0 ignored not allowed + 1..32 escaped must for white-space: + 9 (tab), 10 (lf), 12 (ff), 13 (cr), 32 (space) + recommended for the other control characters + 35 escaped escape char "#" + 37 escaped delimiter "%" + 40..41 escaped delimiters "(" and ")" + 47 escaped delimiter "/" + 60 escaped delimiter "<" + 62 escaped delimiter ">" + 91 escaped delimiter "[" + 93 escaped delimiter "]" + 123 escaped delimiter "{" + 125 escaped delimiter "}" + 127..255 escaped recommended + else copy regular characters + + Parameter "in" is a pointer into the string pool where + the input string is located. The output string is written + as temporary string right after the input string. + Thus at the begin of the procedure the global variable + "poolptr" points to the start of the output string and + after the end when the procedure returns. +*/ +void escapename (poolpointer in) +{ + const poolpointer out = poolptr; + unsigned char ch; + int i; + + while (in < out) { + if (poolptr + 3 >= poolsize) { + poolptr = poolsize; + /* error by str_toks that calls str_room(1) */ + return; + } + + ch = (unsigned char) strpool[in++]; + + if ((ch >= 1 && ch <= 32) || ch >= 127) { + /* escape */ + i = snprintf ((char *) &strpool[poolptr], 4, + "#%.2X", (unsigned int) ch); + check_nprintf (i, 4); + poolptr += i; + continue; + } + switch (ch) { + case 0: + /* ignore */ + break; + case 35: + case 37: + case 40: + case 41: + case 47: + case 60: + case 62: + case 91: + case 93: + case 123: + case 125: + /* escape */ + i = snprintf ((char *) &strpool[poolptr], 4, + "#%.2X", (unsigned int) ch); + check_nprintf (i, 4); + poolptr += i; + break; + default: + /* copy */ + strpool[poolptr++] = ch; + } + } +} + +/* Convert any given string in a PDF hexadecimal string. The + result does not include the angle brackets. + + This procedure uses uppercase hexadecimal letters. + + See escapename for description of parameters. +*/ +void escapehex (poolpointer in) +{ + const poolpointer out = poolptr; + unsigned char ch; + int i; + + while (in < out) { + if (poolptr + 2 >= poolsize) { + poolptr = poolsize; + /* error by str_toks that calls str_room(1) */ + return; + } + + ch = (unsigned char) strpool[in++]; + + i = snprintf ((char *) &strpool[poolptr], 3, "%.2X", (unsigned int) ch); + check_nprintf (i, 3); + poolptr += 2; + } +} + +/* Unescape any given hexadecimal string. + + Last hex digit can be omitted, it is replaced by zero, see + PDF specification. + + Invalid digits are silently ignored. + + See escapename for description of parameters. +*/ +void unescapehex (poolpointer in) +{ + const poolpointer out = poolptr; + unsigned char ch; + unsigned char a = 0; /* to avoid warning about uninitialized use of a */ + boolean first = true; + + while (in < out) { + if (poolptr + 1 >= poolsize) { + poolptr = poolsize; + /* error by str_toks that calls str_room(1) */ + return; + } + + ch = (unsigned char) strpool[in++]; + + if ((ch >= '0') && (ch <= '9')) { + ch -= '0'; + } else if ((ch >= 'A') && (ch <= 'F')) { + ch -= 'A' - 10; + } else if ((ch >= 'a') && (ch <= 'f')) { + ch -= 'a' - 10; + } else { + continue; /* ignore wrong character */ + } + + if (first) { + a = ch << 4; + first = false; + continue; + } + + strpool[poolptr++] = a + ch; + first = true; + } + if (!first) { /* last hex digit is omitted */ + strpool[poolptr++] = ch << 4; + } +} + + +/* Converts any string given in in in an allowed PDF string which is + * hexadecimal encoded; + * sizeof(out) should be at least lin*2+1. + */ +static void convertStringToHexString (const char *in, char *out, int lin) +{ + int i, j, k; + char buf[3]; + j = 0; + for (i = 0; i < lin; i++) { + k = snprintf (buf, sizeof (buf), + "%02X", (unsigned int) (unsigned char) in[i]); + check_nprintf (k, sizeof (buf)); + out[j++] = buf[0]; + out[j++] = buf[1]; + } + out[j] = '\0'; +} + + + +/* makecfilename + input/ouput same as makecstring: + input: string number + output: C string with quotes removed. + That means, file names that are legal on some operation systems + cannot any more be used since pdfTeX version 1.30.4. +*/ +char *makecfilename (strnumber s) +{ + char *name = makecstring (s); + char *p = name; + char *q = name; + + while (*p) { + if (*p != '"') + *q++ = *p; + p++; + } + *q = '\0'; + return name; +} + +/* function strips trailing zeros in string with numbers; */ +/* leading zeros are not stripped (as in real life) */ +char *stripzeros (char *a) +{ + enum { NONUM, DOTNONUM, INT, DOT, LEADDOT, FRAC } s = NONUM, t = NONUM; + char *p, *q, *r; + for (p = q = r = a; *p != '\0';) { + switch (s) { + case NONUM: + if (*p >= '0' && *p <= '9') + s = INT; + else if (*p == '.') + s = LEADDOT; + break; + case DOTNONUM: + if (*p != '.' && (*p < '0' || *p > '9')) + s = NONUM; + break; + case INT: + if (*p == '.') + s = DOT; + else if (*p < '0' || *p > '9') + s = NONUM; + break; + case DOT: + case LEADDOT: + if (*p >= '0' && *p <= '9') + s = FRAC; + else if (*p == '.') + s = DOTNONUM; + else + s = NONUM; + break; + case FRAC: + if (*p == '.') + s = DOTNONUM; + else if (*p < '0' || *p > '9') + s = NONUM; + break; + default:; + } + switch (s) { + case DOT: + r = q; + break; + case LEADDOT: + r = q + 1; + break; + case FRAC: + if (*p > '0') + r = q + 1; + break; + case NONUM: + if ((t == FRAC || t == DOT) && r != a) { + q = r--; + if (*r == '.') /* was a LEADDOT */ + *r = '0'; + r = a; + } + break; + default:; + } + *q++ = *p++; + t = s; + } + *q = '\0'; + return a; +} + +void stripspaces (char *p) +{ + char *q; + for (q = p; *p != '\0'; p++) { + if (*p != ' ') + *q++ = *p; + } + *q = '\0'; +} + +void initversionstring (char **versions) +{ +} + +void setjobid (int year, int month, int day, int time) +{ + char *name_string, *format_string, *s; + size_t slen; + int i; + + if (job_id_string != NULL) + return; + + name_string = xstrdup (makecstring (jobname)); + format_string = xstrdup (makecstring (memident)); + + slen = SMALL_BUF_SIZE + + strlen (name_string) + + strlen (format_string) + + //strlen (banner) + + strlen (versionstring) + strlen (kpathsea_version_string); + s = xtalloc (slen, char); + /* The Web2c version string starts with a space. */ + i = snprintf (s, slen, + "%.4d/%.2d/%.2d %.2d:%.2d %s %s%s %s", + (year>>16), (month>>16), (day>>16), (time>>16) / 60, (time>>16) % 60, + name_string, format_string, //ptexbanner, + versionstring, kpathsea_version_string); + check_nprintf (i, slen); + job_id_string = xstrdup (s); + xfree (s); + xfree (name_string); + xfree (format_string); +} + + + +static void fnstr_append (const char *s) +{ + size_t l = strlen (s) + 1; + alloc_array (char, l, SMALL_ARRAY_SIZE); + strcat (char_ptr, s); + char_ptr = strend (char_ptr); +} + +/* this is not really a true crc32, but it should be just enough to keep + subsets prefixes somewhat disjunct */ +unsigned long crc32 (int oldcrc, const Byte *buf, int len) { + unsigned long ret; + int i; + if (oldcrc==0) + ret = (23<<24)+(45<<16)+(67<<8)+89; + else + for (i=0;i<len;i++) + ret = (ret<<2)+buf[i]; + return ret; +} + +void make_subset_tag (fm_entry * fm_cur, char **glyph_names, int tex_font) +{ + char tag[7]; + unsigned long crc; + int i; + size_t l ; + if (job_id_string ==NULL) + exit; + l = strlen (job_id_string) + 1; + + alloc_array (char, l, SMALL_ARRAY_SIZE); + strcpy (char_array, job_id_string); + char_ptr = strend (char_array); + if (fm_cur->tfm_name != NULL) { + fnstr_append (" TFM name: "); + fnstr_append (fm_cur->tfm_name); + } + fnstr_append (" PS name: "); + //if (font_keys[FONTNAME_CODE].valid) + // fnstr_append (fontname_buf); + //else + if (fm_cur->ps_name != NULL) + fnstr_append (fm_cur->ps_name); + fnstr_append (" Encoding: "); + if (fm_cur->encoding != NULL && (fm_cur->encoding)->name != NULL) + fnstr_append ((fm_cur->encoding)->name); + else + fnstr_append ("built-in"); + fnstr_append (" CharSet: "); + assert (glyph_names != NULL); + for (i = 0; i < 256; i++) + if (mpcharmarked (tex_font, i) && glyph_names[i] != notdef) { + if (glyph_names[i]!=NULL) { + fnstr_append ("/"); + fnstr_append (glyph_names[i]); + } + } + if (fm_cur->charset != NULL) { + fnstr_append (" Extra CharSet: "); + fnstr_append (fm_cur->charset); + } + crc = crc32 (0L, Z_NULL, 0); + crc = crc32 (crc, (Bytef *) char_array, strlen (char_array)); + /* we need to fit a 32-bit number into a string of 6 uppercase chars long; + * there are 26 uppercase chars ==> each char represents a number in range + * 0..25. The maximal number that can be represented by the tag is + * 26^6 - 1, which is a number between 2^28 and 2^29. Thus the bits 29..31 + * of the CRC must be dropped out. + */ + for (i = 0; i < 6; i++) { + tag[i] = 'A' + crc % 26; + crc /= 26; + } + tag[6] = 0; + fm_cur->subset_tag = xstrdup (tag); +} + diff --git a/Build/source/texk/web2c/mpdir/writeenc.c b/Build/source/texk/web2c/mpdir/writeenc.c new file mode 100644 index 00000000000..30673cd6aa3 --- /dev/null +++ b/Build/source/texk/web2c/mpdir/writeenc.c @@ -0,0 +1,142 @@ +/* Copyright (c) 2006 Taco Hoekwater <taco@elvenkind.com> + +This file is part of MetaPost. + +MetaPost 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. + +MetaPost 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 MetaPost; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id $ +*/ + +#include "mplib.h" + +/*@unused@*/ +static const char perforce_id[] = + "$Id: writeenc.c,v 1.3 2005/12/26 14:20:13 hahe Exp hahe $"; + +void read_enc (enc_entry * e) +{ + assert (e != NULL); + if (e->loaded) + return; + e->encname = NULL; + load_enc (e->name, &e->encname, e->glyph_names); + e->loaded = true; +} + +/* write_enc is used to write either external encoding (given in map file) or + * internal encoding (read from the font file); when glyph_names is NULL + * the 2nd argument is a pointer to the encoding entry; otherwise the 3rd is + * the object number of the Encoding object + */ +void write_enc (char **glyph_names, enc_entry * e, integer eobjnum) +{ + boolean is_notdef; + int i; + int s; + int foffset; + char **g; + if (glyph_names == NULL) { + assert (e != NULL); + if (e->objnum != 0) /* the encoding has been written already */ + return; + e->objnum = 1; + g = e->glyph_names; + } else { + g = glyph_names; + } + pdf_printf("\n%%%%BeginResource: encoding %s",e->encname); + pdf_printf ("\n/%s [ ", e->encname); + foffset = strlen(e->name)+3; + for (i = 0; i < 256; i++) { + s = strlen(g[i]); + if (s+1+foffset>=80) { + pdf_printf ("\n"); + foffset = 0; + } + foffset += s+2; + pdf_printf ("/%s ", g[i]); + } + if (foffset>75) + pdf_printf ("\n"); + pdf_puts ("] def\n"); + pdf_printf("%%%%EndResource"); +} + +/**********************************************************************/ +/* All encoding entries go into AVL tree for fast search by name. */ + +struct avl_table *enc_tree = NULL; + +/* AVL sort enc_entry into enc_tree by name */ + +static int comp_enc_entry (const void *pa, const void *pb, void *p) +{ + return strcmp (((const enc_entry *) pa)->name, + ((const enc_entry *) pb)->name); +} + +enc_entry *add_enc (char *s) +{ + int i; + enc_entry tmp, *p; + void **aa; + + assert (s != NULL); + if (enc_tree == NULL) { + enc_tree = avl_create (comp_enc_entry, NULL, &avl_xallocator); + assert (enc_tree != NULL); + } + tmp.name = s; + p = (enc_entry *) avl_find (enc_tree, &tmp); + if (p != NULL) /* encoding already registered */ + return p; + p = xtalloc (1, enc_entry); + p->loaded = false; + p->name = xstrdup (s); + p->objnum = 0; + p->tounicode = 0; + p->glyph_names = xtalloc (256, char *); + for (i = 0; i < 256; i++) + p->glyph_names[i] = (char *) notdef; + aa = avl_probe (enc_tree, p); + assert (aa != NULL); + return p; +} + +/**********************************************************************/ +/* cleaning up... */ + +static void destroy_enc_entry (void *pa, void *pb) +{ + enc_entry *p; + int i; + + p = (enc_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 (enc_tree != NULL) + avl_destroy (enc_tree, destroy_enc_entry); +} + +/**********************************************************************/ diff --git a/Build/source/texk/web2c/mpdir/writefont.c b/Build/source/texk/web2c/mpdir/writefont.c new file mode 100644 index 00000000000..e88b4dbab7d --- /dev/null +++ b/Build/source/texk/web2c/mpdir/writefont.c @@ -0,0 +1,244 @@ +/* +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,v 1.3 2005/12/27 19:04:42 hahe Exp $ +*/ + +#include "mplib.h" + +static const char perforce_id[] = + "$Id: writefont.c,v 1.3 2005/12/27 19:04:42 hahe Exp $"; + +boolean fontfile_found; +boolean is_otf_font; +char fontname_buf[FONTNAME_BUF_SIZE]; + +boolean fontisreencoded (int f) { + fm_entry *fm; + if (fontsizes[f]!=0 && hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL + && (fm->ps_name != NULL) + && is_reencoded (fm)) + return 1; + } + return 0; +} + +boolean fontisincluded (int f) { + fm_entry *fm; + if (fontsizes[f]!=0 && hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL + && (fm->ps_name != NULL && fm->ff_name != NULL) + && is_included (fm)) + return 1; + } + return 0; +} + +boolean fontissubsetted (int f) { + fm_entry *fm; + if (fontsizes[f]!=0 && hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL + && (fm->ps_name != NULL && fm->ff_name != NULL) + && is_included (fm) && is_subsetted (fm)) + return 1; + } + return 0; +} + + +strnumber fmencodingname (int f) { + enc_entry *e; + fm_entry *fm; + if (hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL && (fm->ps_name != NULL)) { + if (is_reencoded (fm)) { + e = fm->encoding; + if (e->encname!=NULL) { + return maketexstring(e->encname); + } + } else { + return 0; + } + } + } + pdftex_fail ("fontmap encoding problems for font %s",makecstring (fontname[f])); + return 0; +} + +strnumber fmfontname (int f) { + fm_entry *fm; + if (hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL && (fm->ps_name != NULL)) { + if (fontisincluded(f) && !fontpsnamefixed[f]) { + /* find the real fontname, and update ps_name and subset_tag if needed */ + if(t1_updatefm(f,fm)) { + fontpsnamefixed[f] = true; + } else { + pdftex_fail ("font loading problems for font %s",makecstring (fontname[f])); + } + } + return maketexstring(fm->ps_name); + } + } + pdftex_fail ("fontmap name problems for font %s",makecstring (fontname[f])); + return 0; +} + +strnumber fmfontsubsetname (int f) { + fm_entry *fm; + char *s; + if (hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL && (fm->ps_name != NULL)) { + if (is_subsetted(fm)) { + s = xmalloc(strlen(fm->ps_name)+8); + snprintf(s,strlen(fm->ps_name)+8,"%s-%s",fm->subset_tag,fm->ps_name); + return maketexstring(s); + } else { + return maketexstring(fm->ps_name); + } + } + } + pdftex_fail ("fontmap name problems for font %s",makecstring (fontname[f])); + return 0; +} + + + +integer fmfontslant (int f) { + fm_entry *fm; + if (hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL && (fm->ps_name != NULL)) { + return fm->slant; + } + } + return 0; +} + +integer fmfontextend (int f) { + fm_entry *fm; + if (hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL && (fm->ps_name != NULL)) { + return fm->extend; + } + } + return 0; +} + + + +void mploadencodings (int lastfnum) { + int nullfont; + int f; + enc_entry *e; + fm_entry *fm_cur; + nullfont = getnullfont(); + for (f=nullfont+1;f<=lastfnum;f++) { + if (fontsizes[f]!=0 && hasfmentry (f)) { + fm_cur = (fm_entry *) mpfontmap[f]; + if (fm_cur != NULL && + fm_cur->ps_name != NULL && + is_reencoded (fm_cur)) { + e = fm_cur->encoding; + read_enc (e); + } + } + } +} + +void mpfontencodings (int lastfnum, int encodings_only) { + int nullfont; + int f,ff; + enc_entry *e; + fm_entry *fm; + nullfont = getnullfont(); + for (f=nullfont+1;f<=lastfnum;f++) { + if (fontsizes[f]!=0 && hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL && (fm->ps_name != NULL)) { + if (is_reencoded (fm)) { + if (encodings_only || (!is_subsetted (fm))) { + e = fm->encoding; + write_enc (NULL, e, 0); + } + } + } + } + } + for (f=nullfont+1;f<=lastfnum;f++) { + if (fontsizes[f]!=0 && hasfmentry (f)) { + fm = (fm_entry *) mpfontmap[f]; + if (fm != NULL && (fm->ps_name != NULL)) { + if (is_reencoded (fm)) { + if (encodings_only || (!is_subsetted (fm))) { + /* clear for next run */ + e->objnum = 0; + } + } + } + } + } +} + +boolean dopsfont (fontnumber f) +{ + int i; + fm_entry *fm_cur; + if (mpfontmap[f] == NULL) + pdftex_fail ("pdffontmap not initialized for font %s", + makecstring (fontname[f])); + if (hasfmentry (f)) + fm_cur = (fm_entry *) mpfontmap[f]; + else + fm_cur = NULL; + if (fm_cur == NULL) + return 1; + if (is_truetype(fm_cur) || + (fm_cur->ps_name == NULL && fm_cur->ff_name == NULL)) { + return 0; + } + + if (is_included(fm_cur)) { + printnl(maketexstring("%%BeginResource: font ")); + flushstr (last_tex_string); + if (is_subsetted(fm_cur)) { + print(maketexstring(fm_cur->subset_tag)); + flushstr (last_tex_string); + print(maketexstring("-")); + flushstr (last_tex_string); + } + print(maketexstring(fm_cur->ps_name)); + flushstr (last_tex_string); + println(); + writet1 (f,fm_cur); + printnl(maketexstring("%%EndResource")); + flushstr (last_tex_string); + println(); + } + return 1; +} + diff --git a/Build/source/texk/web2c/mpdir/writet1.c b/Build/source/texk/web2c/mpdir/writet1.c new file mode 100644 index 00000000000..bbfd398aa3b --- /dev/null +++ b/Build/source/texk/web2c/mpdir/writet1.c @@ -0,0 +1,1736 @@ +/* Copyright (c) 2006 Taco Hoekwater <taco@elvenkind.com> + +This file is part of MetaPost. + +MetaPost 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. + +MetaPost 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 MetaPost; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +$Id$ + +*/ + +static const char perforce_id[] = + "$Id: //depot/Build/source.development/TeX/texk/web2c/pdftexdir/writet1.c#25 $"; + +# include "mplib.h" +# define t1_open() \ + open_input(&t1_file, kpse_type1_format, FOPEN_RBIN_MODE) +# define enc_open() \ + open_input(&enc_file, kpse_enc_format, FOPEN_RBIN_MODE) +# define external_enc() (fm_cur->encoding)->glyph_names + +# define full_file_name() cur_file_name +# define get_length1() +# define get_length2() +# define get_length3() +# define is_used_char(c) mpcharmarked(tex_font, c) +# define out_eexec_char t1_outhex +# define save_offset() +# define end_last_eexec_line() \ + hexline_length = HEXLINE_WIDTH; \ + end_hexline(); \ + t1_eexec_encrypt = false +# define t1_log(s) mp_printf(s) +# define t1_putchar(c) fputc(c, bitfile) +# define embed_all_glyphs(tex_font) false +# undef pdfmovechars +# ifdef SHIFTLOWCHARS +extern char errbuf[]; +extern Boolean shiftlowchars; +# define pdfmovechars shiftlowchars +# define t1_char(c) T1Char(c) +# else /* SHIFTLOWCHARS */ +# define t1_char(c) c +# define pdfmovechars 0 +# endif /* SHIFTLOWCHARS */ +# define extra_charset() dvips_extra_charset +# define update_subset_tag() + +# define fixedcontent true + +static char *dvips_extra_charset; +static char *cur_enc_name; +static unsigned char *grid; +static char *ext_glyph_names[256]; +static char print_buf[PRINTF_BUF_SIZE]; +static int hexline_length; +const char notdef[] = ".notdef"; +/* static size_t last_ptr_index; */ + +#include <kpathsea/c-vararg.h> +#include <kpathsea/c-proto.h> +#include <string.h> + +#define t1_getchar() getc(t1_file) +#define t1_ungetchar(c) ungetc(c, t1_file) +#define t1_eof() feof(t1_file) +#define t1_close() xfclose(t1_file, cur_file_name) + +#define enc_getchar() getc(enc_file) +#define enc_eof() feof(enc_file) +#define enc_close() xfclose(enc_file, cur_file_name) + +#define valid_code(c) (c >= 0 && c < 256) + +static const char *standard_glyph_names[256] = + { notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, 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", + notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, "exclamdown", "cent", + "sterling", "fraction", "yen", "florin", "section", "currency", + "quotesingle", "quotedblleft", "guillemotleft", + "guilsinglleft", "guilsinglright", "fi", "fl", notdef, "endash", + "dagger", "daggerdbl", "periodcentered", notdef, + "paragraph", "bullet", "quotesinglbase", "quotedblbase", + "quotedblright", "guillemotright", "ellipsis", "perthousand", + notdef, "questiondown", notdef, "grave", "acute", "circumflex", + "tilde", "macron", "breve", "dotaccent", "dieresis", notdef, + "ring", "cedilla", notdef, "hungarumlaut", "ogonek", "caron", "emdash", + notdef, notdef, notdef, notdef, notdef, notdef, + notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, notdef, + notdef, "AE", notdef, "ordfeminine", notdef, notdef, + notdef, notdef, "Lslash", "Oslash", "OE", "ordmasculine", notdef, + notdef, notdef, notdef, notdef, "ae", notdef, notdef, + notdef, "dotlessi", notdef, notdef, "lslash", "oslash", "oe", + "germandbls", notdef, notdef, notdef, notdef +}; + +static char charstringname[] = "/CharStrings"; + +char **t1_glyph_names; +char *t1_builtin_glyph_names[256]; +char charsetstr[0x4000]; +static boolean read_encoding_only; +static int t1_encoding; + +#define T1_BUF_SIZE 0x10 +#define ENC_BUF_SIZE 0x1000 + +#define ENC_STANDARD 0 +#define ENC_BUILTIN 1 + +#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_count, 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; + +#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") + + +#ifndef pdfTeX +# define HEXLINE_WIDTH 64 + +static void end_hexline () +{ + if (hexline_length == HEXLINE_WIDTH) { + fputs ("\n", bitfile); + hexline_length = 0; + } +} + +static void t1_outhex (byte b) +{ + static char *hexdigits = "0123456789ABCDEF"; + t1_putchar (hexdigits[b / 16]); + t1_putchar (hexdigits[b % 16]); + hexline_length += 2; + end_hexline (); +} +#endif /* pdfTeX */ + + +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); + append_eol (p, enc_line, ENC_BUF_SIZE); + if (p - enc_line < 2 || *enc_line == '%') + goto restart; +} + +void load_enc (char *enc_name, char **enc_encname, char **glyph_names) +{ + char buf[ENC_BUF_SIZE], *p, *r; + int names_count; + char *myname; + set_cur_file_name (enc_name); + if (!enc_open ()) { + pdftex_warn ("cannot open encoding file for reading"); + cur_file_name = NULL; + return; + } + t1_log ("{"); + t1_log (cur_file_name = full_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); + } + while (*(r-1)==' ') r--; /* strip trailing spaces from encoding name */ + myname = xmalloc(r-enc_line); + memcpy(myname,enc_line+1,(r-enc_line)-1); + *(myname+(r-enc_line-1))=0; + *enc_encname = myname; + while (*r!='[') r++; + r++; /* skip '[' */ + names_count = 0; + 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 (str_prefix (r, "] def")) + 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: + enc_close (); + t1_log ("}"); + cur_file_name = NULL; +} + +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 ()) + 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) + out_eexec_char (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 (); +} + +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) +{ + if ((open_name_prefix != NULL) && strlen(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) +{ + if ((close_name_suffix != NULL) && strlen(close_name_suffix)) { + t1_log (close_name_suffix); + } + t1_close (); + 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 (fm_entry *fm_cur) +{ + int i; + if (is_included (fm_cur)) { + 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; + if (!read_encoding_only) + if (is_included (fm_cur)) + t1_putline (); /* to put the first four bytes */ +} + +static void t1_stop_eexec (fm_entry *fm_cur) +{ + int c; + if (is_included (fm_cur)) { + get_length2 (); + save_offset (); + } + end_last_eexec_line (); + 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; +} + +#ifdef pdfTeX +/* 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 (fm_cur) != 0) + do_slant (a, fm_slant (fm_cur) * 1E-3); + if (fm_extend (fm_cur) != 0) + do_extend (a, fm_extend (fm_cur) * 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 (fm_cur) == 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 (fm_cur) * 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); + font_keys[ITALIC_ANGLE_CODE].value = round (a); + font_keys[ITALIC_ANGLE_CODE].valid = true; +} + +#else + +static void t1_modify_fm (void) +{ + // t1_line_ptr = eol (t1_line_array); +} + +static void t1_modify_italic (void) +{ + // t1_line_ptr = eol (t1_line_array); +} + +#endif /* pdfTeX */ + +key_entry font_keys[FONT_KEYS_NUM] = { + {"Ascent", "Ascender", 0, false}, + {"CapHeight", "CapHeight", 0, false}, + {"Descent", "Descender", 0, false}, + {"FontName", "FontName", 0, false}, + {"ItalicAngle", "ItalicAngle", 0, false}, + {"StemV", "StdVW", 0, false}, + {"XHeight", "XHeight", 0, false}, + {"FontBBox", "FontBBox", 0, false}, + {"", "", 0, false}, + {"", "", 0, false}, + {"", "", 0, false} +}; + + +static void t1_scan_keys (int tex_font,fm_entry *fm_cur) +{ + int i, k; + char *p, *q, *r; + key_entry *key; + if (fm_extend (fm_cur) != 0 || fm_slant (fm_cur) != 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 metapost", i); + return; + } + for (key = font_keys; key - font_keys < MAX_KEY_CODE; key++) + if (str_prefix (t1_line_array + 1, key->t1name)) + break; + if (key - font_keys == MAX_KEY_CODE) + return; + key->valid = true; + p = t1_line_array + strlen (key->t1name) + 1; + skip (p, ' '); + if ((k = key - font_keys) == FONTNAME_CODE) { + if (*p != '/') { + remove_eol (p, t1_line_array); + pdftex_fail ("a name expected: `%s'", t1_line_array); + } + r = ++p; /* skip the slash */ + if (is_included (fm_cur)) { + /* save the fontname */ + strncpy (fontname_buf, p, FONTNAME_BUF_SIZE); + for (i=0; fontname_buf[i] != 10; i++); + fontname_buf[i]=0; + + if(is_subsetted (fm_cur)) { + if (fm_cur->encoding!=NULL && fm_cur->encoding->glyph_names!=NULL) + make_subset_tag (fm_cur, fm_cur->encoding->glyph_names, tex_font); + else + make_subset_tag (fm_cur, t1_builtin_glyph_names, tex_font); + + alloc_array (t1_line, (r-t1_line_array+6+1+strlen(fontname_buf)+1), T1_BUF_SIZE); + strncpy (r, fm_cur->subset_tag , 6); + *(r+6) = '-'; + strncpy (r+7, fontname_buf, strlen(fontname_buf)+1); + t1_line_ptr = eol (r); + } else { + /* for (q = p; *q != ' ' && *q != 10; *q++);*/ + /**q = 0;*/ + 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++) { + key[i].value = t1_scan_num (p, &r); + p = r; + } + return; + } + key->value = t1_scan_num (p, 0); +} + +static void t1_scan_param (int tex_font,fm_entry *fm_cur) +{ + 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 (tex_font,fm_cur); +} + +static void copy_glyph_names (char **glyph_names, int a, int b) +{ + if (glyph_names[b] != notdef) { + free (glyph_names[b]); + glyph_names[b] = (char *) notdef; + } + if (glyph_names[a] != notdef) { + glyph_names[b] = xstrdup (glyph_names[a]); + } +} + +static void t1_builtin_enc (void) +{ + int i, a, b, c, counter = 0; + char *r, *p; + /* + * At this moment "/Encoding" is the prefix of t1_line_array + */ + if (t1_suffix ("def")) { /* predefined encoding */ + sscanf (t1_line_array + strlen ("/Encoding"), "%256s", t1_buf_array); + if (strcmp (t1_buf_array, "StandardEncoding") == 0) { + for (i = 0; i < 256; i++) + if (standard_glyph_names[i] == notdef) + t1_builtin_glyph_names[i] = (char *) notdef; + else + t1_builtin_glyph_names[i] = + xstrdup (standard_glyph_names[i]); + t1_encoding = ENC_STANDARD; + } else + pdftex_fail + ("cannot subset font (unknown predefined encoding `%s')", + t1_buf_array); + return; + } else + t1_encoding = ENC_BUILTIN; + /* + * 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 + */ + for (i = 0; i < 256; i++) + t1_builtin_glyph_names[i] = (char *) notdef; + 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) + t1_builtin_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) + t1_builtin_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 (t1_builtin_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 (t1_builtin_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; + /* + skip an unrecognizable word + */ + else { + while (*p != ' ' && *p != 10) + p++; + skip (p, ' '); + } + } + } +} + +static void t1_check_end (void) +{ + if (t1_eof ()) + return; + t1_getline (); + if (t1_prefix ("{restore}")) + t1_putline (); +} + +static boolean t1_open_fontfile (fm_entry *fm_cur,const char *open_name_prefix) +{ + ff_entry *ff; + ff = check_ff_exist (fm_cur); + if (ff->ff_path != NULL) + t1_file = xfopen (cur_file_name = ff->ff_path, FOPEN_RBIN_MODE); + else { + set_cur_file_name (fm_cur->ff_name); + pdftex_warn ("cannot open Type 1 font file for reading"); + return false; + } + t1_init_params (open_name_prefix); + fontfile_found = true; + return true; +} + +static void t1_scan_only (int tex_font, fm_entry *fm_cur) +{ + do { + t1_getline (); + t1_scan_param (tex_font, fm_cur); + } + while (t1_in_eexec == 0); + t1_start_eexec (fm_cur); + do { + t1_getline (); + t1_scan_param (tex_font, fm_cur); + } + while (!(t1_charstrings () || t1_subrs ())); +} + +static void t1_include (int tex_font, fm_entry *fm_cur) +{ + do { + t1_getline (); + t1_scan_param (tex_font, fm_cur); + t1_putline (); + } + while (t1_in_eexec == 0); + t1_start_eexec (fm_cur); + do { + t1_getline (); + t1_scan_param (tex_font, fm_cur); + t1_putline (); + } + while (!(t1_charstrings () || t1_subrs ())); + t1_cs = true; + do { + t1_getline (); + t1_putline (); + } + while (!t1_end_eexec ()); + t1_stop_eexec (fm_cur); + 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) + +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; +} + +static void t1_subset_ascii_part (int tex_font, fm_entry *fm_cur) +{ + int i, j; + t1_getline (); + while (!t1_prefix ("/Encoding")) { + t1_scan_param (tex_font, fm_cur); + t1_putline (); + t1_getline (); + } + t1_builtin_enc (); + if (is_reencoded (fm_cur)) + t1_glyph_names = external_enc (); + else + t1_glyph_names = t1_builtin_glyph_names; + /* + if (is_included (fm_cur) && is_subsetted (fm_cur)) { + make_subset_tag (fm_cur, t1_glyph_names, tex_font); + update_subset_tag (); + } + */ + if ((!is_subsetted (fm_cur)) && 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"); + for (i = 0, j = 0; i < 256; i++) { + if (is_used_char (i) && t1_glyph_names[i] != notdef) { + j++; + t1_printf ("dup %i /%s put\n", (int) t1_char (i), + t1_glyph_names[i]); + } + } + /* We didn't mark anything for the Encoding array. */ + /* We add "dup 0 /.notdef put" for compatibility */ + /* with Acrobat 5.0. */ + if (j == 0) + t1_puts ("dup 0 /.notdef put\n"); + t1_puts ("readonly def\n"); + } + do { + t1_getline (); + t1_scan_param (tex_font, fm_cur); + if (!t1_prefix ("/UniqueID")) /* ignore UniqueID for subsetted fonts */ + t1_putline (); + } + while (t1_in_eexec == 0); +} + +#define t1_subr_flush() t1_flush_cs(true) +#define t1_cs_flush() t1_flush_cs(false) + +static void t1_flush_cs (boolean); + +static void cs_init (void) +{ + cs_ptr = cs_tab = NULL; + cs_dict_start = cs_dict_end = NULL; + cs_count = 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_mark_glyphs (int tex_font); + +static void t1_read_subrs (int tex_font, fm_entry *fm_cur) +{ + int i, s; + cs_entry *ptr; + t1_getline (); + while (!(t1_charstrings () || t1_subrs ())) { + t1_scan_param (tex_font, fm_cur); + 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); + subr_tab = (cs_entry *)malloc (subr_size*sizeof (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; + } +} + +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 = 0; /* to avoid warning about uninitialized use of 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_count; + } + 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 (); + + /* 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 %i %u", (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 %i %u%s ", (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 (int tex_font) +{ + int i; + char *charset = extra_charset (); + char *g, *s, *r; + cs_entry *ptr; + if (t1_synthetic || embed_all_glyphs (tex_font)) { /* 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); + for (i = 0; i < 256; i++) + if (is_used_char (i)) { + if (t1_glyph_names[i] == notdef) + pdftex_warn ("character %i is mapped to %s", i, notdef); + else + mark_cs (t1_glyph_names[i]); + } + if (charset == NULL) + goto set_subr_max; + g = s = charset + 1; /* skip the first '/' */ + r = strend (g); + while (g < r) { + while (*s != '/' && s < r) + s++; + *s = 0; /* terminate g by rewriting '/' to 0 */ + mark_cs (g); + g = s + 1; + } + set_subr_max: + 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 (int tex_font) +{ + 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 (tex_font); + 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_count = 0, ptr = cs_tab; ptr < cs_ptr; ptr++) + if (ptr->used) + cs_count++; + t1_cs_flush (); +} + +static void t1_subset_end (fm_entry *fm_cur) +{ + 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 (fm_cur); + 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 (); +} + +int t1_updatefm (int f, fm_entry *fm) +{ + char *s, *p; + read_encoding_only = true; + if (!t1_open_fontfile (fm,NULL)) { + return 0; + } + t1_scan_only (f, fm); + s = xstrdup(fontname_buf); + for (p=s; *p != ' ' && *p != 0; *p++); + *p=0; + fm->ps_name = s; + t1_close_font_file (""); + return 1; +} + + +void writet1 (int tex_font, fm_entry *fm_cur) +{ + read_encoding_only = false; + if (!is_included (fm_cur)) { /* scan parameters from font file */ + if (!t1_open_fontfile (fm_cur,"{")) + return; + t1_scan_only (tex_font, fm_cur); + t1_close_font_file ("}"); + return; + } + if (!is_subsetted (fm_cur)) { /* include entire font */ + if (!t1_open_fontfile (fm_cur,"<<")) + return; + t1_include (tex_font,fm_cur); + t1_close_font_file (">>"); + return; + } + /* partial downloading */ + if (!t1_open_fontfile (fm_cur,"<")) + return; + t1_subset_ascii_part (tex_font,fm_cur); + t1_start_eexec (fm_cur); + cc_init (); + cs_init (); + t1_read_subrs (tex_font, fm_cur); + t1_subset_charstrings (tex_font); + t1_subset_end (fm_cur); + t1_close_font_file (">"); +} + +void t1_free () +{ + xfree (t1_line_array); + xfree (t1_buf_array); +} |