📄 ps_afm.c
字号:
/* rmkernmatch() {{{ * * Some routines to remove kerns that match certain patterns. */static KERN *rmkernmatch(PSDoc *psdoc, KERN *k, char *s){ KERN *nk, *ktmp ; while (k != NULL && strcmp(k->succ, s)==0) { psdoc->free(psdoc, k->succ); ktmp = k->next; psdoc->free(psdoc, k); k = ktmp; } if (k) { for (nk = k; nk; nk = nk->next) while (nk->next && strcmp(nk->next->succ, s)==0) { psdoc->free(psdoc, nk->next->succ); ktmp = nk->next->next; psdoc->free(psdoc, nk->next); nk->next = ktmp; } } return k ;}/* }}} *//* rmkern() {{{ * * Recursive to one level. */static void rmkern(PSDoc *psdoc, ght_hash_table_t *gadobechars, char *s1, char *s2, ADOBEINFO *ai){ ght_iterator_t iterator; char *p; if (ai == 0) { if (strcmp(s1, "*") == 0) { for(ai = ght_first(gadobechars, &iterator, (void **) &p); ai; ai = ght_next(gadobechars, &iterator, (void **) &p)) rmkern(psdoc, gadobechars, s1, s2, ai) ; return ; } else { ai = gfindadobe(gadobechars, s1) ; if (ai == 0) return ; } } if (strcmp(s2, "*")==0) { KERN *k, *ktmp; k = ai->kerns; while(k != NULL) { if(k->succ) psdoc->free(psdoc, k->succ); ktmp = k->next; psdoc->free(psdoc, k); k = ktmp; } ai->kerns = NULL ; /* drop them on the floor */ } else ai->kerns = rmkernmatch(psdoc, ai->kerns, s2) ;}/* }}} *//* copykern() {{{ * Make the kerning for character S1 equivalent to that for S2. * If either S1 or S2 do not exist, do nothing. * If S1 already has kerning, do nothing. */static void copykern(PSDoc *psdoc, ght_hash_table_t *gadobechars, char *s1, char *s2){ ADOBEINFO *ai1 = gfindadobe(gadobechars, s1); ADOBEINFO *ai2 = gfindadobe(gadobechars, s2); if (ai1 && ai2 && !ai1->kerns) { /* Put the new one at the head of the list, since order is immaterial. */ ADOBEPTR *ap = (ADOBEPTR *) psdoc->malloc(psdoc, (unsigned long) sizeof(ADOBEPTR), "copykern: adobeptr"); ap->next = ai2->kern_equivs; ap->ch = ai1; ai2->kern_equivs = ap; }}/* }}} */static int sawligkern ;/* checkligkern() {{{ * * Reads a ligkern line, if this is one. Assumes the first character * passed is `%'. */static void checkligkern(PSDoc *psdoc, ADOBEFONTMETRIC *metrics, char *s){ char *oparam = param ; char *mlist[5] ; int n ; ght_hash_table_t *gadobechars = metrics->gadobechars; s++ ; while (*s && *s <= ' ') s++ ; if (strncmp(s, "LIGKERN", 7)==0) { sawligkern = 1 ; s += 7 ; while (*s && *s <= ' ') s++ ; param = s ; while (*param) { for (n=0; n<5;) { if (*param == 0) break ; mlist[n] = paramstring() ; if (strcmp(mlist[n], ";") == 0) break ; n++ ; } if (n > 4) { ps_error(psdoc, PS_RuntimeError, _("Too many parameters in lig kern data.")); return; } if (n < 3) { ps_error(psdoc, PS_RuntimeError, _("Too few parameters in lig kern data.")); return; } if (n == 3 && strcmp(mlist[1], "{}") == 0) { /* rmkern command */ rmkern(psdoc, gadobechars, mlist[0], mlist[2], (ADOBEINFO *)0) ; } else if (n == 3 && strcmp(mlist[1], "<>") == 0) { /* copykern */ /* FIXME: What is the meaning of kern_equivs? * copykern() does not set the kern by kern_equivs which is not * used. */ copykern(psdoc, gadobechars, mlist[0], mlist[2]) ; } else if (n == 3 && strcmp(mlist[0], "||") == 0 && strcmp(mlist[1], "=") == 0) { /* bc command */ ADOBEINFO *ai = gfindadobe(gadobechars, "||") ; if (boundarychar != -1) { ps_error(psdoc, PS_RuntimeError, _("Multiple boundary character commands?")); return; } if (sscanf(mlist[2], "%d", &n) != 1) { ps_error(psdoc, PS_RuntimeError, _("Expected number assignment for boundary char.")); return; } if (n < 0 || n > 255) { ps_error(psdoc, PS_RuntimeError, _("Boundary character number must be 0..255.")); return; } boundarychar = n ; if (ai == 0) { ps_error(psdoc, PS_RuntimeError, _("Internal error: boundary char.")); return; } ai->texnum = n ; /* prime the pump, so to speak, for lig/kerns */ } else if (n == 4) { int op = -1 ; ADOBEINFO *ai ; for (n=0; encligops[n]; n++) if (strcmp(mlist[2], encligops[n])==0) { op = n ; break ; } if (op < 0) { ps_error(psdoc, PS_RuntimeError, _("Bad ligature operation specified.")); return; } if (0 != (ai = gfindadobe(gadobechars, mlist[0]))) { LIG *lig ; /* This does not make sense */ if (gfindadobe(gadobechars, mlist[2])) /* remove coincident kerns */ rmkern(psdoc, gadobechars, mlist[0], mlist[1], ai) ; if (strcmp(mlist[3], "||") == 0) { ps_error(psdoc, PS_RuntimeError, _("You can't lig to the boundary character!")); return; } /* FIXME: The following code is commented because the staticligkern * instruction didn't work anymore. For some reason e.g. the endash * wasn't found, though it was part of the font. I appears that * at this point the list of glyphs on gadobechars isn't complete */ /* if (gfindadobe(gadobechars, mlist[3])) { ps_error(psdoc, PS_RuntimeError, _("Ligature '%s' not available in font."), mlist[3]); return; } */ if (!metrics->fixedpitch) { /* fixed pitch fonts get *0* ligs */ for (lig=ai->ligs; lig; lig = lig->next) if (strcmp(lig->succ, mlist[1]) == 0) break ; /* we'll re-use this structure */// printf("Adding new lig %s %s -> %s\n", mlist[0], mlist[1], mlist[3]); if (lig == 0) { lig = newlig(psdoc) ; lig->succ = newstring(psdoc, mlist[1]) ; lig->next = ai->ligs ; ai->ligs = lig ; } if(lig->sub) psdoc->free(psdoc, lig->sub); lig->sub = newstring(psdoc, mlist[3]) ; lig->op = op ; if (strcmp(mlist[1], "||")==0) { lig->boundleft = 1 ; if (strcmp(mlist[0], "||")==0) { ps_error(psdoc, PS_RuntimeError, _("You can't lig boundary character to boundary character.")); return; } } else lig->boundleft = 0 ; } } } else { ps_error(psdoc, PS_RuntimeError, _("Bad form in LIGKERN command.")); return; } } } param = oparam ;}/* }}} *//* char *gettoken() {{{ * * Here we get a token from the encoding file. We parse just as much PostScript * as we expect to find in an encoding file. We allow commented lines and * names like 0, .notdef, _foo_. We do not allow //abc. * This function calls checkligkern() which reads extra ligatures which * are usually at the beginning of the file marked as PostScript comments. */static char smbuffer[100] ; /* for tokens */static char *gettoken(PSDoc *psdoc, ADOBEFONTMETRIC *metrics) { char *p, *q ; while (1) { while (param == NULL || *param == '\0') { if (getline(metrics->afmin) == 0) ps_error(psdoc, PS_RuntimeError, _("Premature end of encoding file.")); for (p=buffer; *p != '\0'; p++) if (*p == '%') { if (ignoreligkern == 0) checkligkern(psdoc, metrics, p) ; *p = '\0' ; break ; } } while (*param != '\0' && *param <= ' ') param++ ; if (*param) { if (*param == '[' || *param == ']' || *param == '{' || *param == '}') { smbuffer[0] = *param++ ; smbuffer[1] = '\0' ; return smbuffer ; } else if (*param == '/' || *param == '-' || *param == '_' || *param == '.' || ('0' <= *param && *param <= '9') || ('a' <= *param && *param <= 'z') || ('A' <= *param && *param <= 'Z')) { smbuffer[0] = *param ; for (p=param+1, q=smbuffer+1; *p == '-' || *p == '_' || *p == '.' || ('0' <= *p && *p <= '9') || ('a' <= *p && *p <= 'z') || ('A' <= *p && *p <= 'Z'); p++, q++) *q = *p ; *q = '\0' ; param = p ; return smbuffer ; } } }}/* }}} *//* getligkerndefaults() {{{ * * Set default ligatures */static void getligkerndefaults(PSDoc *psdoc, ADOBEFONTMETRIC *metrics) { int i ; for (i=0; staticligkern[i]; i++) { strncpy(buffer, staticligkern[i], BUFFERLEN) ; strncpy(obuffer, staticligkern[i], BUFFERLEN) ; param = buffer ; checkligkern(psdoc, metrics, buffer) ; }}/* }}} *//* readencoding() {{{ * * This routine reads in an encoding file, given the name. It modifies * the passed font metrics structure. It returns -1 in case of error and * 0 otherwise. It performs a number of consistency checks. * If enc is NULL it will use the default encoding from ps_fontenc.c */int readencoding(PSDoc *psdoc, ADOBEFONTMETRIC *metrics, const char *enc) { char *p ; int i ; ENCODING *e; sawligkern = 0 ; if (metrics->afmin) { ps_error(psdoc, PS_RuntimeError, _("Encoding file for this font seems to be already open.")); return -1; } if(enc) { metrics->afmin = ps_open_file_in_path(psdoc, enc) ; param = 0 ; if (metrics->afmin == NULL) { ps_error(psdoc, PS_RuntimeError, _("Could not open encoding file '%s'."), enc); return -1; } p = gettoken(psdoc, metrics) ; if (*p != '/' || p[1] == '\0') { ps_error(psdoc, PS_RuntimeError, _("Encoding file must start with name of encoding.")); return -1; } e = (ENCODING *) psdoc->malloc(psdoc, sizeof(ENCODING), _("Allocate memory for new encoding vector.")) ; if(NULL == e) { ps_error(psdoc, PS_MemoryError, _("Could not allocate memory for encoding vector.")); return -1; } e->name = newstring(psdoc, p+1) ; p = gettoken(psdoc, metrics) ; if (0 != strcmp(p, "[")) { ps_error(psdoc, PS_RuntimeError, _("Name of encoding must be followed by an '['.")); psdoc->free(psdoc, e->name); psdoc->free(psdoc, e); return -1; } for (i=0; i<256; i++) { p = gettoken(psdoc, metrics) ; if (*p != '/' || p[1] == '\0') { ps_error(psdoc, PS_RuntimeError, _("Encoding vector must contain 256 glyph names.")); for (i--; i>=0; i--) { psdoc->free(psdoc, e->vec[i]); } psdoc->free(psdoc, e->name); psdoc->free(psdoc, e); return -1; } e->vec[i] = newstring(psdoc, p+1) ; } p = gettoken(psdoc, metrics) ; if (0 != strcmp(p, "]")) { ps_error(psdoc, PS_RuntimeError, _("Encoding vector must be ended by an ']'.")); for (i=0; i<256; i++) { psdoc->free(psdoc, e->vec[i]); } psdoc->free(psdoc, e->name); psdoc->free(psdoc, e); return -1; } while (getline(metrics->afmin)) { for (p=buffer; *p != '\0'; p++) if (*p == '%') { if (ignoreligkern == 0) checkligkern(psdoc, metrics, p) ; *p = '\0' ; break ; } } fclose(metrics->afmin) ; metrics->afmin = NULL ; if (ignoreligkern == 0 && sawligkern == 0) { getligkerndefaults(psdoc, metrics) ; } metrics->fontenc = ps_build_enc_hash(psdoc, e); if(metrics->codingscheme) psdoc->free(psdoc, metrics->codingscheme); metrics->codingscheme = newstring(psdoc, e->name); /* FIXME: For now we through away the fontenc from the file and * take the predefined font encoding. */ for (i=0; i<256; i++) { psdoc->free(psdoc, e->vec[i]); } psdoc->free(psdoc, e->name); psdoc->free(psdoc, e); } else { /* not font encoding file name passed */ e = &fontencoding[0] ; getligkerndefaults(psdoc, metrics) ; metrics->fontenc = ps_build_enc_hash(psdoc, e); if(metrics->codingscheme) psdoc->free(psdoc, metrics->codingscheme); metrics->codingscheme = newstring(psdoc, e->name); } param = 0 ; return 0 ;}/* }}} *//* readadobe() ; if (fontspace == 0) { ADOBEINFO *ai ; } handlereencoding() ;*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -