diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/ttf2pk/subfont.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/ttf2pk/subfont.c')
-rw-r--r-- | Build/source/texk/ttf2pk/subfont.c | 396 |
1 files changed, 396 insertions, 0 deletions
diff --git a/Build/source/texk/ttf2pk/subfont.c b/Build/source/texk/ttf2pk/subfont.c new file mode 100644 index 00000000000..c919028dbe3 --- /dev/null +++ b/Build/source/texk/ttf2pk/subfont.c @@ -0,0 +1,396 @@ +/* + * subfont.c + * + * This file is part of the ttf2pk package. + * + * Copyright 1997-1999, 2000, 2002 by + * Frederic Loyer <loyer@ensta.fr> + * Werner Lemberg <wl@gnu.org> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> /* for size_t */ +#include <ctype.h> +#include <string.h> + +#include "filesrch.h" +#include "subfont.h" +#include "newobj.h" +#include "errormsg.h" + + +struct _realsubfont; +typedef struct _realsubfont realsubfont; + +struct _realsubfont +{ + realsubfont *next; + char *name; + FILE *file; +}; + +static realsubfont *real_sfd_name = NULL, *real_lig_name = NULL; + +static realsubfont * +really_init_sfd(char *name, Boolean fatal); +static Boolean +really_get_sfd(Font *fnt, Boolean next, realsubfont *rsf); +static void +really_close_sfd(realsubfont *real_name); + + +/* + * Initialize subfont functionality. The argument is the subfont + * definition file name. If `fatal' is `True', the routine exits + * with an error. If `fatal' is `False', a warning message is emitted + * and `False' returned if an error occurs; in case of success `True' + * will be returned. + */ + +Boolean +init_sfd(Font *fnt, Boolean fatal) +{ + real_sfd_name = really_init_sfd(fnt->sfdname, fatal); + if (fnt->ligname) + real_lig_name = really_init_sfd(fnt->ligname, fatal); + + return (real_sfd_name ? True : False); +} + + +static realsubfont * +really_init_sfd(char *name, Boolean fatal) +{ + char *sf; + char *buf, *p, *q; + realsubfont *rsf, *temp, *real_name = NULL; + + + buf = newstring(name); + p = buf; + + while (1) + { + if (*p == '\0') + { + if (real_name) + break; + else + { + if (fatal) + oops("No subfont definition file."); + else + { + warning("No subfont definition file."); + return NULL; + } + } + } + + q = p; + while (*q && *q != ',') /* search end of subfont name */ + q++; + if (*q) + *(q++) = '\0'; + + sf = newstring(p); + + p = q; + + rsf = (realsubfont *)mymalloc(sizeof (realsubfont)); + rsf->name = TeX_search_sfd_file(&sf); + if (!rsf->name) + { + if (fatal) + oops("Cannot find subfont definition file `%s'.", sf); + else + { + warning("Cannot find subfont definition file `%s'.", sf); + return NULL; + } + } + + rsf->file = fopen(rsf->name, "rt"); + if (rsf->file == NULL) + { + if (fatal) + oops("Cannot open subfont definition file `%s'.", rsf->name); + else + { + warning("Cannot open subfont definition file `%s'.", rsf->name); + return NULL; + } + } + + rsf->next = real_name; + real_name = rsf; + + free(sf); + } + + free(buf); + + /* reverse list */ + + rsf = NULL; + while (real_name) + { + temp = real_name; + real_name = real_name->next; + temp->next = rsf; + rsf = temp; + } + real_name = rsf; + + return real_name; +} + + +/* + * This function fills the font structure sequentially with subfont + * entries; it returns `False' if no more subfont entries are available, + * `True' otherwise. + * + * If `next' is `True', check `rsf' whether it contains entries for the + * current subfont name, overwriting subfont code points. + * + * fnt->subfont_name must be set to NULL before the first call. + * + * The subset parser was inspired by ttf2bdf.c . + */ + +Boolean get_sfd(Font *fnt, Boolean is_sfd) +{ + if (is_sfd) + return really_get_sfd(fnt, False, real_sfd_name); + else + return really_get_sfd(fnt, False, real_lig_name); +} + + +static Boolean +really_get_sfd(Font *fnt, Boolean next, realsubfont *rsf) +{ + long i, offset; + long begin, end = -1; + char *buffer, *oldbuffer, *bufp, *bufp2, *bufp3; + + + if (next) + rewind(rsf->file); + else + for (i = 0; i < 256; i++) + fnt->sf_code[i] = -1; + +again: + + buffer = get_line(rsf->file); + if (!buffer) + oops("Error reading subfont definition file `%s'.", rsf->name); + if (!*buffer) + return False; + + oldbuffer = newstring(buffer); + bufp = buffer; + offset = 0; + + while (*bufp) /* remove comment */ + { + if (*bufp == '#') + { + bufp++; + break; + } + bufp++; + } + *(--bufp) = '\0'; /* remove final newline character */ + + bufp = buffer; + + while (isspace(*bufp)) + bufp++; + + if (*bufp == '\0') /* empty line? */ + { + free(buffer); + free(oldbuffer); + goto again; + } + + while (*bufp && !isspace(*bufp)) /* subfont name */ + bufp++; + if (*bufp) + *(bufp++) = '\0'; + + while (isspace(*bufp)) + bufp++; + + if (*bufp == '\0') + oops("Invalid subfont entry in `%s'.", rsf->name); + + if (next) + { + if (strcmp(fnt->subfont_name, buffer)) + goto again; + } + else + { + if (fnt->subfont_name) + free(fnt->subfont_name); + fnt->subfont_name = newstring(buffer); + } + + while (1) + { + bufp3 = bufp; + + begin = strtol(bufp, &bufp2, 0); + + if (bufp == bufp2 || begin < 0 || begin > 0x16FFFF) + boops(oldbuffer, bufp - buffer, + "Invalid subfont range or offset entry."); + + if (*bufp2 == ':') /* offset */ + { + offset = begin; + if (offset > 0xFF) + boops(oldbuffer, bufp - buffer, "Invalid subfont offset."); + + bufp = bufp2 + 1; + + while (isspace(*bufp)) + bufp++; + + continue; + } + else if (*bufp2 == '_') /* range */ + { + bufp = bufp2 + 1; + if (!isdigit(*bufp)) + boops(oldbuffer, bufp - buffer, "Invalid subfont range entry."); + + end = strtol(bufp, &bufp2, 0); + + if (bufp == bufp2 || end < 0 || end > 0x16FFFFL) + boops(oldbuffer, bufp - buffer, "Invalid subfont range entry."); + if (*bufp2 && !isspace(*bufp2)) + boops(oldbuffer, bufp2 - buffer, "Invalid subfont range entry."); + if (end < begin) + boops(oldbuffer, bufp - buffer, "End of subfont range too small."); + if (offset + (end - begin) > 255) + boops(oldbuffer, bufp3 - buffer, + "Subfont range too large for current offset (%i).", offset); + } + else if (isspace(*bufp2) || !*bufp2) /* single value */ + end = begin; + else + boops(oldbuffer, bufp2 - buffer, "Invalid subfont range entry."); + + for (i = begin; i <= end; i++) + { + if (!next && fnt->sf_code[offset] != -1) + boops(oldbuffer, bufp3 - buffer, "Overlapping subfont ranges."); + + fnt->sf_code[offset++] = i; + } + + bufp = bufp2; + + while (isspace(*bufp)) + bufp++; + + if (!*bufp) + break; + } + + free(buffer); + free(oldbuffer); + + if (!next) + while ((rsf = rsf->next)) + (void)really_get_sfd(fnt, True, rsf); + + return True; +} + + +void +close_sfd(void) +{ + really_close_sfd(real_sfd_name); + really_close_sfd(real_lig_name); +} + + +static void +really_close_sfd(realsubfont *real_name) +{ + realsubfont *rsf; + + + while (real_name) + { + if (real_name->file) + fclose(real_name->file); + if (real_name->name) + free(real_name->name); + + rsf = real_name; + real_name = real_name->next; + free(rsf); + } +} + + +/* + * We extract the subfont definition file name. The name must + * be embedded between two `@' characters. If there is no sfd file, + * `sfd_begin' is set to -1. + * + * The `@' characters will be replaced with null characters. + */ + +void +handle_sfd(char *s, int *sfd_begin, int *postfix_begin) +{ + size_t len; + int i; + Boolean have_atsign; + + + have_atsign = False; + len = strlen(s); + *sfd_begin = -1; + *postfix_begin = -1; + + for (i = 0; s[i]; i++) + { + if (s[i] == '@') + { + if (have_atsign) + { + *postfix_begin = i + 1; + + s[i] = '\0'; + break; + } + have_atsign = True; + *sfd_begin = i + 1; + + s[i] = '\0'; + } + } + + if (*sfd_begin != -1 && + (*postfix_begin == -1 || *postfix_begin < *sfd_begin + 2)) + oops("Invalid subfont definition file name."); + + if (*postfix_begin > -1) + for (i = *postfix_begin; s[i]; i++) + if (s[i] == '/' || s[i] == ':' || s[i] == '\\' || s[i] == '@') + oops("`/', `:', `\\', and `@' not allowed after second `@'."); +} + + +/* end */ |