FreeType 1.31.1
This commit is contained in:
275
contrib/ttf2pk/ligkern.c
Normal file
275
contrib/ttf2pk/ligkern.c
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* ligkern.c
|
||||
*
|
||||
* This file is part of the ttf2pk package.
|
||||
*
|
||||
* Copyright 1997-1999 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 void
|
||||
rmkern(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 void
|
||||
addkern(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 `%'.
|
||||
*/
|
||||
|
||||
void
|
||||
checkligkern(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[2], 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);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
getligkerndefaults(Font *fnt)
|
||||
{
|
||||
int i;
|
||||
char *buffer;
|
||||
|
||||
|
||||
for (i = 0; staticligkern[i]; i++)
|
||||
{
|
||||
buffer = newstring(staticligkern[i]);
|
||||
checkligkern(buffer, fnt);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* end */
|
||||
Reference in New Issue
Block a user