boolean handle_subfont_fm(fm_entry * fm, int mode) { size_t l; char *p, *q, *r; sfd_entry *sfd; subfont_entry *sf; fm_entry *fm2; char buf[SMALL_BUF_SIZE]; assert(fm->tfm_name != NULL); p = fm->tfm_name; q = strchr(p, '@'); /* search for the first '@' */ if (q == NULL) return false; r = strchr(q + 1, '@'); /* search for the second '@' */ if (r == NULL) return false; if (q <= p || r <= q + 1 /* prefix or sfd name is empty */ || r - p != strlen(p) - 1) /* or the second '@' is not the last char yet */ return false; l = r - (q + 1); /* length of sfd name */ strncpy(buf, q + 1, l); buf[l] = 0; check_buf(strlen(buf) + 4, SMALL_BUF_SIZE); strcat(buf, ".sfd"); sfd = read_sfd(buf); if (sfd == NULL) return false; /* at this point we know fm is a subfont */ set_subfont(fm); xfree(fm->ps_name); fm->ps_name = NULL; /* set default values for PidEid */ if (fm->pid == -1) { fm->pid = 3; fm->eid = 1; } l = q - p; /* length of base tfm name (prefix) */ for (sf = sfd->subfont; sf != NULL; sf = sf->next) { strncpy(buf, p, l); buf[l] = 0; strcat(buf, sf->infix); fm2 = new_fm_entry(); fm2->tfm_name = xstrdup(buf); fm2->ff_name = xstrdup(fm->ff_name); fm2->type = fm->type; fm2->pid = fm->pid; fm2->eid = fm->eid; fm2->subfont = sf; if (avl_do_entry(fm2, mode) != 0) /* try to insert the entry */ delete_fm_entry(fm2); /* delete it if failed */ } delete_fm_entry(fm); return true; }
static void fm_scan_line() { int a, b, c, j, u = 0, v = 0; float d; fm_entry *fm; char fm_line[FM_BUF_SIZE], buf[FM_BUF_SIZE]; char *p, *q, *r, *s; switch (mitem->type) { case MAPFILE: p = fm_line; do { c = fm_getchar(); append_char_to_buf(c, p, fm_line, FM_BUF_SIZE); } while (c != 10 && !fm_eof()); *(--p) = '\0'; r = fm_line; break; case MAPLINE: r = mitem->line; /* work on string from makecstring() */ break; default: assert(0); } if (*r == '\0' || is_cfg_comment(*r)) return; fm = new_fm_entry(); read_field(r, q, buf); set_field(tfm_name); if (!isdigit(*r)) { /* 2nd field ps_name may not start with a digit */ read_field(r, q, buf); set_field(ps_name); } if (isdigit(*r)) { /* font descriptor /Flags given? */ for (s = r; isdigit(*s); s++); if (*s == ' ' || *s == '"' || *s == '<' || *s == '\0') { /* not e. g. 8r.enc */ fm->fd_flags = atoi(r); while (isdigit(*r)) r++; } } while (1) { /* loop through "specials", encoding, font file */ skip(r, ' '); switch (*r) { case '\0': goto done; case '"': /* opening quote */ r++; u = v = 0; do { skip(r, ' '); if (sscanf(r, "%f %n", &d, &j) > 0) { s = r + j; /* jump behind number, eat also blanks, if any */ if (*(s - 1) == 'E' || *(s - 1) == 'e') s--; /* e. g. 0.5ExtendFont: %f = 0.5E */ if (str_prefix(s, "SlantFont")) { d *= 1000.0; /* correct rounding also for neg. numbers */ fm->slant = (integer) (d > 0 ? d + 0.5 : d - 0.5); r = s + strlen("SlantFont"); } else if (str_prefix(s, "ExtendFont")) { d *= 1000.0; fm->extend = (integer) (d > 0 ? d + 0.5 : d - 0.5); if (fm->extend == 1000) fm->extend = 0; r = s + strlen("ExtendFont"); } else { /* unknown name */ for (r = s; *r != ' ' && *r != '"' && *r != '\0'; r++); /* jump over name */ c = *r; /* remember char for temporary end of string */ *r = '\0'; pdftex_warn ("invalid entry for `%s': unknown name `%s' ignored", fm->tfm_name, s); *r = c; } } else for (; *r != ' ' && *r != '"' && *r != '\0'; r++); } while (*r == ' '); if (*r == '"') /* closing quote */ r++; else { pdftex_warn ("invalid entry for `%s': closing quote missing", fm->tfm_name); goto bad_line; } break; case 'P': /* handle cases for subfonts like 'PidEid=3,1' */ if (sscanf(r, "PidEid=%i, %i %n", &a, &b, &c) >= 2) { fm->pid = a; fm->eid = b; r += c; break; } default: /* encoding or font file specification */ a = b = 0; if (*r == '<') { a = *r++; if (*r == '<' || *r == '[') b = *r++; } read_field(r, q, buf); /* encoding, formats: '8r.enc' or '<8r.enc' or '<[8r.enc' */ if (strlen(buf) > 4 && strcasecmp(strend(buf) - 4, ".enc") == 0) { fm->encname = add_encname(buf); u = v = 0; /* u, v used if intervening blank: "<< foo" */ } else if (strlen(buf) > 0) { /* file name given */ /* font file, formats: * subsetting: '<cmr10.pfa' * no subsetting: '<<cmr10.pfa' * no embedding: 'cmr10.pfa' */ if (a == '<' || u == '<') { set_included(fm); if ((a == '<' && b == 0) || (a == 0 && v == 0)) set_subsetted(fm); /* otherwise b == '<' (or '[') => no subsetting */ } set_field(ff_name); u = v = 0; } else { u = a; v = b; } } } done: if (fm->ps_name != NULL && check_std_t1font(fm->ps_name)) set_std_t1font(fm); if (is_fontfile(fm)) { if (strcasecmp(strend(fm_fontfile(fm)) - 4, ".ttf") == 0) set_truetype(fm); else if (strcasecmp(strend(fm_fontfile(fm)) - 4, ".otf") == 0) set_opentype(fm); else set_type1(fm); } else set_type1(fm); /* assume a builtin font is Type1 */ if (check_fm_entry(fm, true) != 0) goto bad_line; /* Until here the map line has been completely scanned without errors; fm points to a valid, freshly filled-out fm_entry structure. Now follows the actual work of registering/deleting. */ if (handle_subfont_fm(fm, mitem->mode)) /* is this a subfont? */ return; if (avl_do_entry(fm, mitem->mode) == 0) /* if success */ return; bad_line: delete_fm_entry(fm); }