X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/blobdiff_plain/44407fea05657f91da34fd83428b67e7100ab62b..7d7f8de9b0c38fc510a09b62e3bdf7574f06592f:/in_pf.c diff --git a/in_pf.c b/in_pf.c index 50e663e..f708ac1 100644 --- a/in_pf.c +++ b/in_pf.c @@ -2,33 +2,220 @@ #include "halibut.h" #include "paper.h" +static char *pf_read_token(FILE *fp); + void read_pfa_file(input *in) { - char buf[512], *p; + rdstringc rsc = { 0, 0, NULL }; + char *p; size_t len; char *fontname; font_info *fi; + FILE *fp = in->currfp; + int c; - len = fread(buf, 1, sizeof(buf) - 1, in->currfp); - buf[len] = 0; - if (strncmp(buf, "%!FontType1-", 12) && - strncmp(buf, "%!PS-AdobeFont-", 15)) + in->pos.line = 0; + do { + c = fgetc(fp); + if (c == EOF) { + sfree(rsc.text); + error(err_pfeof, &in->pos); + return; + } + rdaddc(&rsc, c); + } while (c != 012 && c != 015); + p = rsc.text; + if ((p = strchr(p, ':')) == NULL) { + sfree(rsc.text); + error(err_pfhead, &in->pos); return; - p = buf; - p += strcspn(p, ":") + 1; + } + p++; p += strspn(p, " \t"); len = strcspn(p, " \t"); fontname = snewn(len + 1, char); memcpy(fontname, p, len); fontname[len] = 0; + sfree(rsc.text); + for (fi = all_fonts; fi; fi = fi->next) { if (strcmp(fi->name, fontname) == 0) { fi->fp = in->currfp; + fi->pos = in->pos; + fi->length1 = fi->length2 = 0; sfree(fontname); return; } } + error(err_pfnoafm, &in->pos, fontname); fclose(in->currfp); sfree(fontname); } - - + +/* + * PostScript white space characters; PLRM3 table 3.1 + */ +static int pf_isspace(int c) { + return c == 000 || c == 011 || c == 012 || c == 014 || c == 015 || + c == ' '; +} + +/* + * PostScript special characters; PLRM3 page 27 + */ +static int pf_isspecial(int c) { + return c == '(' || c == ')' || c == '<' || c == '>' || c == '[' || + c == ']' || c == '{' || c == '}' || c == '/' || c == '%'; +} + +static long pf_length1(font_info *fi) { + FILE *fp = fi->fp; + char *tok; + + rewind(fp); + tok = pf_read_token(fp); + while (tok && strcmp(tok, "eexec") != 0) { + sfree(tok); + tok = pf_read_token(fp); + } + if (tok == NULL) { + error(err_pfeof, &fi->pos); + return 0; + } + return ftell(fp); +} + +/* + * Return the initial, unencrypted, part of a font. + */ +void pf_part1(font_info *fi, char **bufp, size_t *lenp) { + FILE *fp = fi->fp; + + if (fi->length1 == 0) + fi->length1 = pf_length1(fi); + rewind(fp); + *bufp = snewn(fi->length1, char); + *lenp = fi->length1; + if (fread(*bufp, 1, fi->length1, fp) != (size_t)fi->length1) { + error(err_pfeof, &fi->pos); + *lenp = 0; + sfree(*bufp); + *bufp = NULL; + } +} + +static int hexval(char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return c - 'A' + 0xA; + if (c >= 'a' && c <= 'f') return c - 'a' + 0xa; + return 0; +} + +/* + * Return the middle, encrypted, part of a font. + */ +void pf_part2(font_info *fi, char **bufp, size_t *lenp) { + FILE *fp = fi->fp; + rdstringc rsc = { 0, 0, NULL }; + char *tok, *p; + unsigned char nybble; + int havenybble = 0; + + if (fi->length1 == 0) + fi->length1 = pf_length1(fi); + fseek(fp, fi->length1, SEEK_SET); + tok = pf_read_token(fp); + while (tok && strcmp(tok, "cleartomark") != 0) { + for (p = tok; *p; p++) { + if (pf_isspace(*p)) continue; + if (!havenybble) + nybble = hexval(*p); + else + rdaddc(&rsc, (nybble << 4) | hexval(*p)); + havenybble = !havenybble; + } + sfree(tok); + tok = pf_read_token(fp); + } + if (tok == NULL) { + error(err_pfeof, &fi->pos); + *bufp = NULL; + *lenp = 0; + } + *bufp = rsc.text; + /* Trim off the trailing zeroes */ + if (rsc.pos >= 256) + *lenp = rsc.pos - 256; + else { + error(err_pfbad, &fi->pos); + *bufp = NULL; + *lenp = 0; + } +} + +static char *pf_read_litstring(FILE *fp) { + rdstringc rsc = { 0, 0, NULL }; + int depth = 1; + int c; + + rdaddc(&rsc, '('); + do { + c = fgetc(fp); + switch (c) { + case '(': + depth++; break; + case ')': + depth--; break; + case '\\': + rdaddc(&rsc, '\\'); + c = fgetc(fp); + break; + } + if (c != EOF) rdaddc(&rsc, c); + } while (depth > 0 && c != EOF); + return rsc.text; +} + +static char *pf_read_hexstring(FILE *fp) { + rdstringc rsc = { 0, 0, NULL }; + int c; + + rdaddc(&rsc, '<'); + do { + c = fgetc(fp); + if (c != EOF) rdaddc(&rsc, c); + } while (c != '>' && c != EOF); + return rsc.text; +} + +static char *pf_read_word(FILE *fp, int c) { + rdstringc rsc = { 0, 0, NULL }; + + rdaddc(&rsc, c); + if (c == '{' || c == '}' || c == '[' || c == ']') + return rsc.text; + for (;;) { + c = fgetc(fp); + if (pf_isspecial(c) || pf_isspace(c) || c == EOF) break; + rdaddc(&rsc, c); + } + if (pf_isspecial(c)) ungetc(c, fp); + return rsc.text; +} + +static char *pf_read_token(FILE *fp) { + int c; + + do { + c = fgetc(fp); + } while (pf_isspace(c)); + if (c == EOF) return NULL; + if (c == '%') { + do { + c = fgetc(fp); + } while (c != 012 && c != 015); + return pf_read_token(fp); + } + if (c == '(') return pf_read_litstring(fp); + if (c == '<') return pf_read_hexstring(fp); + return pf_read_word(fp, c); +}