📄 ligkern.c
字号:
/* * ligkern.c * * This file is part of the ttf2pk package. * * Copyright 1997-1999, 2000 by * Frederic Loyer <loyer@ensta.fr> * Werner Lemberg <wl@gnu.org> */#include <string.h>#include <stdlib.h>#include <stddef.h> /* for size_t */#include <ctype.h>#include "ttf2tfm.h"#include "ligkern.h"#include "ttfenc.h"#include "texenc.h"#include "newobj.h"#include "errormsg.h"static char *paramstring(char **curp){ register char *p, *q; p = *curp; while (*p && !isspace(*p)) p++; q = *curp; if (*p != '\0') *p++ = '\0'; while (isspace(*p)) p++; *curp = p; return q;}/* * Some routines to remove kerns that match certain patterns. */static kern *rmkernmatch(kern *k, char *s){ kern *nk; while (k && strcmp(k->succ, s) == 0) k = k->next; if (k) { for (nk = k; nk; nk = nk->next) while (nk->next && strcmp(nk->next->succ, s) == 0) nk->next = nk->next->next; } return k;}/* * Recursive to one level. */static voidrmkern(char *s1, char *s2, ttfinfo *ti, Font *fnt){ if (ti == NULL) { if (strcmp(s1, "*") == 0) { for (ti = fnt->charlist; ti; ti = ti->next) rmkern(s1, s2, ti, fnt); return; } else { ti = findadobe(s1, fnt->charlist); if (ti == NULL) return; } } if (strcmp(s2, "*") == 0) ti->kerns = NULL; /* drop them on the floor */ else ti->kerns = rmkernmatch(ti->kerns, s2);}/* * 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 voidaddkern(char *s1, char *s2, Font *fnt){ ttfinfo *ti1 = findadobe(s1, fnt->charlist); ttfinfo *ti2 = findadobe(s2, fnt->charlist); if (ti1 && ti2 && !ti1->kerns) { /* Put the new one at the head of the list, since order is immaterial. */ ttfptr *ap = (ttfptr *)mymalloc(sizeof (ttfptr)); ap->next = ti2->kern_equivs; ap->ch = ti1; ti2->kern_equivs = ap; }}/* * Reads a ligkern line, if this is one. Assumes the first character * passed is `%'. */voidcheckligkern(char *s, Font *fnt){ char *mlist[5]; char *os; char *orig_s, *pos; size_t offset[5]; int n; os = newstring(s); orig_s = s; s++; while (isspace(*s)) s++; if (strncmp(s, "LIGKERN", 7) == 0) { fnt->sawligkern = True; s += 7; while (isspace(*s)) s++; pos = s; while (*pos) { for (n = 0; n < 5;) { if (*pos == '\0') break; offset[n] = pos - orig_s; mlist[n] = paramstring(&pos); if (strcmp(mlist[n], ";") == 0) break; n++; } if (n > 4) boops(os, pos - orig_s, "Too many parameters in lig kern data."); if (n < 3) boops(os, pos - orig_s, "Too few parameters in lig kern data."); if (n == 3 && strcmp(mlist[1], "{}") == 0) /* rmkern command */ rmkern(mlist[0], mlist[2], (ttfinfo *)0, fnt); else if (n == 3 && strcmp(mlist[1], "<>") == 0) /* addkern */ addkern(mlist[0], mlist[2], fnt); else if (n == 3 && strcmp(mlist[0], "||") == 0 && strcmp(mlist[1], "=") == 0) /* bc command */ { ttfinfo *ti = findadobe("||", fnt->charlist); if (fnt->boundarychar != -1) boops(os, offset[0], "Multiple boundary character commands?"); if (sscanf(mlist[2], "%d", &n) != 1) boops(os, offset[2], "Expected number assignment for boundary char."); if (n < 0 || n > 0xFF) boops(os, offset[2], "Boundary character number must be 0..0xFF."); fnt->boundarychar = n; if (ti == NULL) oops("Internal error: boundary char."); ti->outcode = n; /* prime the pump, so to speak, for lig/kerns */ } else if (n == 4) { int op = -1; ttfinfo *ti; for (n = 0; encligops[n]; n++) if (strcmp(mlist[2], encligops[n]) == 0) { op = n; break; } if (op < 0) boops(os, offset[2], "Bad ligature op specified."); if (NULL != (ti = findadobe(mlist[0], fnt->charlist))) { lig *lig; if (findadobe(mlist[1], fnt->charlist)) /* remove coincident kerns */ rmkern(mlist[0], mlist[1], ti, fnt); if (strcmp(mlist[3], "||") == 0) boops(os, offset[3], "You can't lig to the boundary character!"); if (!fnt->fixedpitch) /* fixed pitch fonts get *0* ligs */ { for (lig = ti->ligs; lig; lig = lig->next) if (strcmp(lig->succ, mlist[1]) == 0) break; /* we'll re-use this structure */ if (lig == NULL) { lig = newlig(); lig->succ = newstring(mlist[1]); lig->next = ti->ligs; ti->ligs = lig; } lig->sub = newstring(mlist[3]); lig->op = op; if (strcmp(mlist[1], "||") == 0) { lig->boundleft = 1; if (strcmp(mlist[0], "||") == 0) boops(os, offset[0], "You can't lig boundarychar boundarychar!"); } else lig->boundleft = 0; } } } else boops(os, offset[0], "Bad form in LIGKERN command."); } } free(os);}voidgetligkerndefaults(Font *fnt){ int i; char *buffer; for (i = 0; staticligkern[i]; i++) { buffer = newstring(staticligkern[i]); checkligkern(buffer, fnt); free(buffer); }}/* end */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -