integer myatodim(char **s) { register long w, num, den, sc ; register const char *q ; char *p ; int negative = 0, i ; p = *s ; if (**s == '-') { p++ ; negative = 1 ; } w = myatol(&p) ; if (w < 0) { pdftex_warn("number too large; 1000 used") ; w = 1000 ; } num = 0 ; den = 1 ; if (*p == '.') { p++ ; while ('0' <= *p && *p <= '9') { if (den <= 1000) { den *= 10 ; num = num * 10 + *p - '0' ; } else if (den == 10000) { den *= 2 ; num = num * 2 + (*p - '0') / 5 ; } p++ ; } } skip(p, ' '); true_dimen = false; if (strncmp(p, "true", strlen("true")) == 0) { true_dimen = true; p += strlen("true"); skip(p, ' '); } for (i=0, q=scalenames; ; i++, q += 2) if (*q == 0) { pdftex_warn("expected units in %s, assuming inches.", *s); sc = scalevals[8] ; break ; } else if (*p == *q && p[1] == q[1]) { sc = scalevals[i] ; p += 2 ; break ; } w = scale(w, num, den, sc) ; *s = p ; return(negative?-w:w) ; }
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; tex_printf("{%s", cur_file_name); while (!fm_eof()) { fm_scan_line(); mitem->lineno++; } fm_close(); tex_printf("}"); fm_file = NULL; } break; case MAPLINE: cur_file_name = NULL; /* makes pdftex_warn() shorter */ fm_scan_line(); break; default: assert(0); } mitem->line = NULL; /* done with this line */ cur_file_name = NULL; return; }
/* * Convert a sequence of digits into a long; return -1 if no digits. * Advance the passed pointer as well. */ integer myatol(char **s) { register char *p ; register long result ; result = 0 ; p = *s ; while ('0' <= *p && *p <= '9') { if (result > 100000000) pdftex_warn("arithmetic overflow in parameter") ; result = 10 * result + *p++ - '0' ; } if (p == *s) { pdftex_warn("expected number in %s returning 10", *s) ; return 10 ; } else { *s = p ; return(result) ; } }
static long scale(long whole, long num, long den, long sf) { long v ; v = whole * sf + num * (sf / den) ; if (v / sf != whole || v < 0 || v > 0x40000000L) pdftex_warn("arithmetic overflow in parameter") ; sf = sf % den ; v += (sf * num * 2 + den) / (2 * den) ; return(v) ; }
static void fix_fontmetrics(fd_entry * fd) { intparm *p = (intparm *) fd->font_dim; if (!p[FONTBBOX1_CODE].set || !p[FONTBBOX2_CODE].set || !p[FONTBBOX3_CODE].set || !p[FONTBBOX4_CODE].set) { pdftex_warn("font `%s' doesn't have a BoundingBox", fd->fm->ff_name); return; } if (!p[ASCENT_CODE].set) { p[ASCENT_CODE].val = p[FONTBBOX4_CODE].val; p[ASCENT_CODE].set = true; } if (!p[DESCENT_CODE].set) { p[DESCENT_CODE].val = p[FONTBBOX2_CODE].val; p[DESCENT_CODE].set = true; } if (!p[CAPHEIGHT_CODE].set) { p[CAPHEIGHT_CODE].val = p[FONTBBOX4_CODE].val; p[CAPHEIGHT_CODE].set = true; } }
void deftounicode(strnumber glyph, strnumber unistr) { char buf[SMALL_BUF_SIZE], *p; char buf2[SMALL_BUF_SIZE], *q; int valid_unistr; /* 0: invalid; 1: unicode value; 2: string */ int i, l; glyph_unicode_entry *gu, t; void **aa; p = makecstring(glyph); assert(strlen(p) < SMALL_BUF_SIZE); strcpy(buf, p); /* copy the result to buf before next call of makecstring() */ p = makecstring(unistr); while (*p == ' ') p++; /* ignore leading spaces */ l = strlen(p); while (l > 0 && p[l - 1] == ' ') l--; /* ignore traling spaces */ valid_unistr = 1; /* a unicode value is the most common case */ for (i = 0; i < l; i++) { if (p[i] == ' ') valid_unistr = 2; /* if a space occurs we treat this entry as a string */ else if (!isXdigit(p[i])) { valid_unistr = 0; break; } } if (l == 0 || valid_unistr == 0 || strlen(buf) == 0 || strcmp(buf, notdef) == 0) { pdftex_warn("ToUnicode: invalid parameter(s): `%s' => `%s'", buf, p); return; } if (glyph_unicode_tree == NULL) { glyph_unicode_tree = avl_create(comp_glyph_unicode_entry, NULL, &avl_xallocator); assert(glyph_unicode_tree != NULL); } t.name = buf; /* allow overriding existing entries */ if ((gu = (glyph_unicode_entry *) avl_find(glyph_unicode_tree, &t)) != NULL) { if (gu->code == UNI_STRING) { assert(gu->unicode_seq != NULL); xfree(gu->unicode_seq); } } else { /* make new entry */ gu = new_glyph_unicode_entry(); gu->name = xstrdup(buf); } if (valid_unistr == 2) { /* a string with space(s) */ /* copy p to buf2, ignoring spaces */ for (q = buf2; *p != 0; p++) if (*p != ' ') *q++ = *p; *q = 0; gu->code = UNI_STRING; gu->unicode_seq = xstrdup(buf2); } else { i = sscanf(p, "%lX", &(gu->code)); assert(i == 1); } aa = avl_probe(glyph_unicode_tree, gu); assert(aa != NULL); }
integer write_tounicode(char **glyph_names, char *name) { char buf[SMALL_BUF_SIZE], *p; static char builtin_suffix[] = "-builtin"; short range_size[257]; glyph_unicode_entry gtab[257]; integer objnum; int i, j; int bfchar_count, bfrange_count, subrange_count; assert(strlen(name) + strlen(builtin_suffix) < SMALL_BUF_SIZE); if (glyph_unicode_tree == NULL) { pdftex_warn("no GlyphToUnicode entry has been inserted yet!"); fixedgentounicode = 0; return 0; } strcpy(buf, name); if ((p = strrchr(buf, '.')) != NULL && strcmp(p, ".enc") == 0) *p = 0; /* strip ".enc" from encoding name */ else strcat(buf, builtin_suffix); /* ".enc" not present, this is a builtin encoding so the name is eg "cmr10-builtin" */ objnum = pdfnewobjnum(); pdfbegindict(objnum, 0); pdfbeginstream(); pdf_printf("%%!PS-Adobe-3.0 Resource-CMap\n" "%%%%DocumentNeededResources: ProcSet (CIDInit)\n" "%%%%IncludeResource: ProcSet (CIDInit)\n" "%%%%BeginResource: CMap (TeX-%s-0)\n" "%%%%Title: (TeX-%s-0 TeX %s 0)\n" "%%%%Version: 1.000\n" "%%%%EndComments\n" "/CIDInit /ProcSet findresource begin\n" "12 dict begin\n" "begincmap\n" "/CIDSystemInfo\n" "<< /Registry (TeX)\n" "/Ordering (%s)\n" "/Supplement 0\n" ">> def\n" "/CMapName /TeX-%s-0 def\n" "/CMapType 2 def\n" "1 begincodespacerange\n" "<00> <FF>\n" "endcodespacerange\n", buf, buf, buf, buf, buf); /* set gtab */ for (i = 0; i < 256; ++i) { gtab[i].code = UNI_UNDEF; set_glyph_unicode(glyph_names[i], >ab[i]); } gtab[256].code = UNI_UNDEF; /* set range_size */ for (i = 0; i < 256;) { if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) { range_size[i] = 1; /* single entry */ i++; } else if (gtab[i].code == UNI_UNDEF) { range_size[i] = 0; /* no entry */ i++; } else { /* gtab[i].code >= 0 */ j = i; while (i < 256 && gtab[i + 1].code >= 0 && gtab[i].code + 1 == gtab[i + 1].code) i++; /* at this point i is the last entry of the subrange */ i++; /* move i to the next entry */ range_size[j] = i - j; } } /* calculate bfrange_count and bfchar_count */ bfrange_count = 0; bfchar_count = 0; for (i = 0; i < 256;) { if (range_size[i] == 1) { bfchar_count++; i++; } else if (range_size[i] > 1) { bfrange_count++; i += range_size[i]; } else i++; } /* write out bfrange */ i = 0; write_bfrange: if (bfrange_count > 100) subrange_count = 100; else subrange_count = bfrange_count; bfrange_count -= subrange_count; pdf_printf("%i beginbfrange\n", subrange_count); for (j = 0; j < subrange_count; j++) { while (range_size[i] <= 1 && i < 256) i++; assert(i < 256); pdf_printf("<%02X> <%02X> <%s>\n", i, i + range_size[i] - 1, utf16be_str(gtab[i].code)); i += range_size[i]; } pdf_printf("endbfrange\n"); if (bfrange_count > 0) goto write_bfrange; /* write out bfchar */ i = 0; write_bfchar: if (bfchar_count > 100) subrange_count = 100; else subrange_count = bfchar_count; bfchar_count -= subrange_count; pdf_printf("%i beginbfchar\n", subrange_count); for (j = 0; j < subrange_count; j++) { while (i < 256) { if (range_size[i] > 1) i += range_size[i]; else if (range_size[i] == 0) i++; else /* range_size[i] == 1 */ break; } assert(i < 256 && gtab[i].code != UNI_UNDEF); if (gtab[i].code == UNI_STRING || gtab[i].code == UNI_EXTRA_STRING) { assert(gtab[i].unicode_seq != NULL); pdf_printf("<%02X> <%s>\n", i, gtab[i].unicode_seq); } else pdf_printf("<%02X> <%s>\n", i, utf16be_str(gtab[i].code)); i++; } pdf_printf("endbfchar\n"); if (bfchar_count > 0) goto write_bfchar; /* free strings allocated by set_glyph_unicode() */ for (i = 0; i < 256; ++i) { if (gtab[i].code == UNI_EXTRA_STRING) xfree(gtab[i].unicode_seq); } pdf_printf("endcmap\n" "CMapName currentdict /CMap defineresource pop\n" "end\n" "end\n" "%%%%EndResource\n" "%%%%EOF\n"); pdfendstream(); return objnum; }
static sfd_entry *read_sfd (char *sfd_name) { void **aa; sfd_entry *sfd, tmp_sfd; subfont_entry *sf; char *ftemp = NULL; char buf[SMALL_BUF_SIZE], *p; long int i, j, k; int n; int callback_id=0; int file_opened=0; /* check whether this sfd has been read */ tmp_sfd.name = sfd_name; if (sfd_tree == NULL) { sfd_tree = avl_create (comp_sfd_entry, NULL, &avl_xallocator); assert (sfd_tree != NULL); } sfd = (sfd_entry *) avl_find (sfd_tree, &tmp_sfd); if (sfd != NULL) return sfd; set_cur_file_name (sfd_name); if (sfd_buffer!=NULL) { xfree(sfd_buffer); sfd_buffer=NULL; } sfd_curbyte=0; sfd_size=0; callback_id=callback_defined(find_sfd_file_callback); if (callback_id>0) { if(run_callback(callback_id,"S->S",cur_file_name,&ftemp)) { if(ftemp!=NULL&&strlen(ftemp)) { if (cur_file_name) free(cur_file_name); cur_file_name = xstrdup(ftemp); free(ftemp); } } } callback_id=callback_defined(read_sfd_file_callback); if (callback_id>0) { if(! (run_callback(callback_id,"S->bSd",cur_file_name, &file_opened, &sfd_buffer,&sfd_size) && file_opened && sfd_size>0 ) ) { pdftex_warn ("cannot open SFD file for reading"); cur_file_name = NULL; return NULL; } sfd_read_file(); sfd_close(); } tex_printf ("{"); tex_printf (cur_file_name); sfd = new_sfd_entry (); sfd->name = xstrdup (sfd_name); while (!sfd_eof ()) { sfd_getline (true); if (*sfd_line == 10) /* empty line indicating eof */ break; sf = new_subfont_entry (); sf->next = sfd->subfont; sfd->subfont = sf; sscanf (sfd_line, "%s %n", buf, &n); sf->infix = xstrdup (buf); p = sfd_line + n; /* skip to the next word */ k = 0; read_ranges: for (;;) { if (*p == '\\') { /* continue on next line */ sfd_getline (false); p = sfd_line; goto read_ranges; } else if (*p == 0) /* end of subfont */ break; if (sscanf (p, " %li %n", &i, &n) == 0) pdftex_fail ("invalid token:\n%s", p); p += n; if (*p == ':') { /* offset */ k = i; p++; } else if (*p == '_') { /* range */ if (sscanf (p + 1, " %li %n", &j, &n) == 0) pdftex_fail ("invalid token:\n%s", p); if (i > j || k + (j - i) > 255) pdftex_fail ("invalid range:\n%s", p); while (i <= j) sf->charcodes[k++] = i++; p += n + 1; } else /* codepoint */ sf->charcodes[k++] = i; } } tex_printf ("}"); aa = avl_probe (sfd_tree, sfd); assert (aa != NULL); return sfd; }
void fm_read_info () { int callback_id; int file_opened = 0; char *ftemp = NULL; if (tfm_tree == NULL) create_avl_trees (); if (mitem->line == NULL) /* nothing to do */ return; mitem->lineno = 1; switch (mitem->type) { case MAPFILE: set_cur_file_name (mitem->line); if (fm_buffer!=NULL) { xfree(fm_buffer); fm_buffer=NULL; } fm_curbyte=0; fm_size=0; callback_id=callback_defined(find_map_file_callback); if (callback_id>0) { if(run_callback(callback_id,"S->S",(char *)(nameoffile+1),&ftemp)) { if(ftemp!=NULL&&strlen(ftemp)) { free(nameoffile); namelength = strlen(ftemp); nameoffile = xmalloc(namelength+2); strcpy((char *)(nameoffile+1),ftemp); free(ftemp); } } } callback_id=callback_defined(read_map_file_callback); if (callback_id>0) { if(run_callback(callback_id,"S->bSd",(char *)(nameoffile+1), &file_opened, &fm_buffer,&fm_size)) { if(file_opened) { if (fm_size>0) { cur_file_name = (char *) nameoffile + 1; if (tracefilenames) tex_printf ("{%s", cur_file_name); while (!fm_eof ()) { fm_scan_line (); mitem->lineno++; } if (tracefilenames) tex_printf ("}"); fm_file = NULL; } } else { pdftex_warn ("cannot open font map file"); } } else { pdftex_warn ("cannot open font map file"); } } else { if (!fm_open ()) { pdftex_warn ("cannot open font map file"); } else { fm_read_file(); cur_file_name = (char *) nameoffile + 1; tex_printf ("{%s", cur_file_name); while (!fm_eof ()) { fm_scan_line (); mitem->lineno++; } fm_close (); tex_printf ("}"); fm_file = NULL; } } break; case MAPLINE: cur_file_name = NULL; /* makes pdftex_warn() shorter */ fm_scan_line (); break; default: assert (0); } mitem->line = NULL; /* done with this line */ cur_file_name = NULL; return; }
static 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); }
int check_fm_entry(fm_entry * fm, boolean warn) { int a = 0; assert(fm != NULL); if (is_fontfile(fm) && !is_included(fm)) { if (warn) pdftex_warn ("ambiguous entry for `%s': font file present but not included, " "will be treated as font file not present", fm->tfm_name); xfree(fm->ff_name); /* do not set variable |a| as this entry will be still accepted */ } /* if both ps_name and font file are missing, drop this entry */ if (fm->ps_name == NULL && !is_fontfile(fm)) { if (warn) pdftex_warn ("invalid entry for `%s': both ps_name and font file missing", fm->tfm_name); a += 1; } /* TrueType fonts cannot be reencoded without subsetting */ if (is_truetype(fm) && is_reencoded(fm) && !is_subsetted(fm)) { if (warn) pdftex_warn ("invalid entry for `%s': only subsetted TrueType font can be reencoded", fm->tfm_name); a += 2; } /* SlantFont and ExtendFont can be used only with Type1 fonts */ if ((fm->slant != 0 || fm->extend != 0) && !(is_t1fontfile(fm) && is_included(fm))) { if (warn) pdftex_warn ("invalid entry for `%s': SlantFont/ExtendFont can be used only with embedded Type1 fonts", fm->tfm_name); a += 4; } /* the value of SlantFont and ExtendFont must be reasonable */ if (abs(fm->slant) > 1000) { if (warn) pdftex_warn ("invalid entry for `%s': too big value of SlantFont (%g)", fm->tfm_name, fm->slant / 1000.0); a += 8; } if (abs(fm->extend) > 2000) { if (warn) pdftex_warn ("invalid entry for `%s': too big value of ExtendFont (%g)", fm->tfm_name, fm->extend / 1000.0); a += 16; } /* subfonts must be used with subsetted non-reencoded TrueType fonts */ if (fm->pid != -1 && !(is_truetype(fm) && is_subsetted(fm) && !is_reencoded(fm))) { if (warn) pdftex_warn ("invalid entry for `%s': PidEid can be used only with subsetted non-reencoded TrueType fonts", fm->tfm_name); a += 32; } return a; }
int avl_do_entry(fm_entry * fm, int mode) { fm_entry *p; void *a; void **aa; /* handle tfm_name link */ if (strcmp(fm->tfm_name, nontfm)) { p = (fm_entry *) avl_find(tfm_tree, fm); if (p != NULL) { switch (mode) { case FM_DUPIGNORE: pdftex_warn ("fontmap entry for `%s' already exists, duplicates ignored", fm->tfm_name); goto exit; break; case FM_REPLACE: case FM_DELETE: if (p->in_use) { pdftex_warn ("fontmap entry for `%s' has been used, replace/delete not allowed", fm->tfm_name); goto exit; } a = avl_delete(tfm_tree, p); assert(a != NULL); unset_tfmlink(p); if (!has_pslink(p)) delete_fm_entry(p); break; default: assert(0); } } if (mode != FM_DELETE) { aa = avl_probe(tfm_tree, fm); assert(aa != NULL); set_tfmlink(fm); } } /* handle ps_name link */ if (fm->ps_name != NULL) { p = (fm_entry *) avl_find(ps_tree, fm); if (p != NULL) { switch (mode) { case FM_DUPIGNORE: goto exit; break; case FM_REPLACE: case FM_DELETE: if (p->in_use) goto exit; a = avl_delete(ps_tree, p); assert(a != NULL); unset_pslink(p); if (!has_tfmlink(p)) delete_fm_entry(p); break; default: assert(0); } } if (mode != FM_DELETE && is_t1fontfile(fm) && is_included(fm)) { aa = avl_probe(ps_tree, fm); assert(aa != NULL); set_pslink(fm); } } exit: if (!has_tfmlink(fm) && !has_pslink(fm)) /* e. g. after FM_DELETE */ return 1; /* deallocation of fm_entry structure required */ else return 0; }