ref: ad676d4665a58d390dd9ce06477ad97c5b98fc91
parent: 8f5f11d521897752ff40bad2648c18a970f1536e
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Nov 19 19:01:19 EST 2013
font: new syntax for defining characters and kerning pairs
--- a/font.c
+++ b/font.c
@@ -3,21 +3,13 @@
#include <string.h>
#include "post.h"
-static void skipline(FILE* filp)
-{
- int c;
- do {
- c = getc(filp);
- } while (c != '\n' && c != EOF);
-}
-
struct glyph *font_find(struct font *fn, char *name)
{
- int i = fn->head[(unsigned char) name[0]];
+ int i = fn->chead[(unsigned char) name[0]];
while (i >= 0) {
if (!strcmp(name, fn->c[i]))
return fn->g[i];
- i = fn->next[i];
+ i = fn->cnext[i];
}
return NULL;
}
@@ -24,141 +16,69 @@
struct glyph *font_glyph(struct font *fn, char *id)
{
- int i;
- for (i = 0; i < fn->nglyphs; i++)
+ int i = fn->ghead[(unsigned char) id[0]];
+ while (i >= 0) {
if (!strcmp(fn->glyphs[i].id, id))
return &fn->glyphs[i];
+ i = fn->gnext[i];
+ }
return NULL;
}
-static int font_idx(struct font *fn, struct glyph *g)
+struct glyph *font_glyphput(struct font *fn, char *id, char *name, int wid, int type)
{
- return g ? g - fn->glyphs : -1;
+ int i = fn->nglyphs++;
+ struct glyph *g;
+ g = &fn->glyphs[i];
+ strcpy(g->id, id);
+ strcpy(g->name, name);
+ g->wid = wid;
+ g->type = type;
+ g->font = fn;
+ fn->gnext[i] = fn->ghead[(unsigned char) id[0]];
+ fn->ghead[(unsigned char) id[0]] = i;
+ return g;
}
-/*
- * Given a list of characters in the reverse order, font_lig()
- * returns the number of characters from the beginning of this
- * list that form a ligature in this font. Zero naturally means
- * no ligature was matched.
- */
-int font_lig(struct font *fn, char **c, int n)
+static int font_readchar(struct font *fn, FILE *fin)
{
- int i;
- /* concatenated characters in c[], in the correct order */
- char s[GNLEN * 2] = "";
- /* b[i] is the number of character of c[] in s + i */
- int b[GNLEN * 2] = {0};
- int len = 0;
- for (i = 0; i < n; i++) {
- char *cur = c[n - i - 1];
- b[len] = n - i;
- strcpy(s + len, cur);
- len += strlen(cur);
- }
- for (i = 0; i < fn->nlig; i++) {
- int l = strlen(fn->lig[i]);
- if (b[len - l] && !strcmp(s + len - l, fn->lig[i]))
- if (font_find(fn, fn->lig[i]))
- return b[len - l];
- }
- return 0;
-}
-
-/* return pairwise kerning value between c1 and c2 */
-int font_kern(struct font *fn, char *c1, char *c2)
-{
- int i1, i2, i;
- i1 = font_idx(fn, font_find(fn, c1));
- i2 = font_idx(fn, font_find(fn, c2));
- if (i1 < 0 || i2 < 0)
- return 0;
- i = fn->knhead[i1];
- while (i >= 0) {
- if (fn->knpair[i] == i2)
- return fn->knval[i];
- i = fn->knnext[i];
- }
- return 0;
-}
-
-static int font_section(struct font *fn, FILE *fin, char *name);
-
-static void font_charset(struct font *fn, FILE *fin)
-{
char tok[ILNLEN];
char name[ILNLEN];
char id[ILNLEN];
struct glyph *glyph = NULL;
- struct glyph *prev = NULL;
int wid, type;
- while (fscanf(fin, "%s", name) == 1) {
- if (!font_section(fn, fin, name))
- break;
- if (fn->n >= NGLYPHS) {
- skipline(fin);
- continue;
- }
- fscanf(fin, "%s", tok);
- glyph = prev;
- if (!strcmp("---", name))
- sprintf(name, "c%04d", fn->n);
- if (strcmp("\"", tok)) {
- wid = atoi(tok);
- fscanf(fin, "%d %s", &type, id);
- skipline(fin);
- glyph = &fn->glyphs[fn->nglyphs++];
- strcpy(glyph->id, id);
- strcpy(glyph->name, name);
- glyph->wid = wid;
- glyph->type = type;
- glyph->font = fn;
- }
- prev = glyph;
- strcpy(fn->c[fn->n], name);
- fn->g[fn->n] = glyph;
- fn->next[fn->n] = fn->head[(unsigned char) name[0]];
- fn->head[(unsigned char) name[0]] = fn->n;
- fn->n++;
+ if (fn->n >= NGLYPHS)
+ return 1;
+ if (fscanf(fin, "%s %s", name, tok) != 2)
+ return 1;
+ if (!strcmp("---", name))
+ sprintf(name, "c%04d", fn->n);
+ if (strcmp("\"", tok)) {
+ wid = atoi(tok);
+ if (fscanf(fin, "%d %s", &type, id) != 2)
+ return 1;
+ glyph = font_glyph(fn, id);
+ if (!glyph)
+ glyph = font_glyphput(fn, id, name, wid, type);
+ } else {
+ glyph = fn->g[fn->n - 1];
}
+ strcpy(fn->c[fn->n], name);
+ fn->g[fn->n] = glyph;
+ fn->cnext[fn->n] = fn->chead[(unsigned char) name[0]];
+ fn->chead[(unsigned char) name[0]] = fn->n;
+ fn->n++;
+ return 0;
}
-static void font_kernpairs(struct font *fn, FILE *fin)
+static void skipline(FILE* filp)
{
- char c1[ILNLEN], c2[ILNLEN];
- int i1, i2, val;
- while (fscanf(fin, "%s", c1) == 1) {
- if (!font_section(fn, fin, c1))
- break;
- if (fscanf(fin, "%s %d", c2, &val) != 2)
- break;
- if (fn->knn < NKERNS) {
- i1 = font_idx(fn, font_find(fn, c1));
- i2 = font_idx(fn, font_find(fn, c2));
- if (i1 >= 0 && i2 >= 0) {
- fn->knnext[fn->knn] = fn->knhead[i1];
- fn->knhead[i1] = fn->knn;
- fn->knval[fn->knn] = val;
- fn->knpair[fn->knn] = i2;
- fn->knn++;
- }
- }
- }
+ int c;
+ do {
+ c = getc(filp);
+ } while (c != '\n' && c != EOF);
}
-static int font_section(struct font *fn, FILE *fin, char *name)
-{
- if (!strcmp("charset", name)) {
- font_charset(fn, fin);
- return 0;
- }
- if (!strcmp("kernpairs", name)) {
- font_kernpairs(fn, fin);
- return 0;
- }
- return 1;
-}
-
struct font *font_open(char *path)
{
struct font *fn;
@@ -169,48 +89,35 @@
if (!fin)
return NULL;
fn = malloc(sizeof(*fn));
+ if (!fn) {
+ fclose(fin);
+ return NULL;
+ }
memset(fn, 0, sizeof(*fn));
- for (i = 0; i < LEN(fn->head); i++)
- fn->head[i] = -1;
- for (i = 0; i < LEN(fn->knhead); i++)
- fn->knhead[i] = -1;
+ for (i = 0; i < LEN(fn->ghead); i++)
+ fn->ghead[i] = -1;
+ for (i = 0; i < LEN(fn->chead); i++)
+ fn->chead[i] = -1;
while (fscanf(fin, "%s", tok) == 1) {
- if (tok[0] == '#') {
- skipline(fin);
- continue;
- }
- if (!strcmp("spacewidth", tok)) {
+ if (!strcmp("char", tok)) {
+ font_readchar(fn, fin);
+ } else if (!strcmp("spacewidth", tok)) {
fscanf(fin, "%d", &fn->spacewid);
- continue;
- }
- if (!strcmp("special", tok)) {
+ } else if (!strcmp("special", tok)) {
fn->special = 1;
- continue;
- }
- if (!strcmp("name", tok)) {
+ } else if (!strcmp("name", tok)) {
fscanf(fin, "%s", fn->name);
- continue;
- }
- if (!strcmp("fontname", tok)) {
+ } else if (!strcmp("fontname", tok)) {
fscanf(fin, "%s", fn->fontname);
- continue;
- }
- if (!strcmp("named", tok)) {
- skipline(fin);
- continue;
- }
- if (!strcmp("ligatures", tok)) {
- while (fscanf(fin, "%s", tok) == 1) {
+ } else if (!strcmp("ligatures", tok)) {
+ while (fscanf(fin, "%s", tok) == 1)
if (!strcmp("0", tok))
break;
- if (fn->nlig < NLIGS)
- strcpy(fn->lig[fn->nlig++], tok);
- }
- skipline(fin);
- continue;
- }
- if (!font_section(fn, fin, tok))
+ } else if (!strcmp("charset", tok)) {
+ while (!font_readchar(fn, fin))
+ ;
break;
+ }
skipline(fin);
}
fclose(fin);
--- a/out.c
+++ b/out.c
@@ -1,4 +1,3 @@
-#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -46,8 +45,7 @@
static void o_queue(struct glyph *g)
{
- int type = 1 + !isdigit((g)->id[0]);
- int num = atoi(g->id);
+ int type = 1 + (g->pos <= 0);
if (o_qtype != type || o_qend != o_h || o_qv != o_v) {
o_flush();
o_qh = o_h;
@@ -56,10 +54,11 @@
outf(type == 1 ? "(" : "[");
}
if (o_qtype == 1) {
- if (num >= ' ' && num <= '~')
- outf("%s%c", strchr("()\\", num) ? "\\" : "", num);
+ if (g->pos >= ' ' && g->pos <= '~')
+ outf("%s%c", strchr("()\\", g->pos) ? "\\" : "", g->pos);
else
- outf("\\%d%d%d", (num >> 6) & 7, (num >> 3) & 7, num & 7);
+ outf("\\%d%d%d", (g->pos >> 6) & 7,
+ (g->pos >> 3) & 7, g->pos & 7);
} else {
outf("/%s", g->id);
}
--- a/post.h
+++ b/post.h
@@ -2,13 +2,10 @@
#define PATHLEN 1024 /* path length */
#define NFONTS 32 /* number of fonts */
#define NGLYPHS 1024 /* glyphs in fonts */
-#define NLIGS 32 /* number of font ligatures */
-#define NKERNS 512 /* number of font pairwise kerning pairs */
#define FNLEN 64 /* font name length */
#define GNLEN 32 /* glyph name length */
#define ILNLEN 1000 /* line limit of input files */
#define LNLEN 4000 /* line buffer length (ren.c/out.c) */
-#define LIGLEN 4 /* length of ligatures */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) < (b) ? (b) : (a))
@@ -21,11 +18,12 @@
extern int dev_ver;
struct glyph {
- char name[GNLEN]; /* name of the glyph */
char id[GNLEN]; /* device-dependent glyph identifier */
+ char name[GNLEN]; /* the first character mapped to this glyph */
struct font *font; /* glyph font */
int wid; /* character width */
int type; /* character type; ascender/descender */
+ int pos; /* glyph code */
};
struct font {
@@ -35,21 +33,17 @@
int nglyphs;
int spacewid;
int special;
- char c[NGLYPHS][FNLEN]; /* character names in charset */
+ int cs, bd; /* for .cs and .bd requests */
+ /* glyph list based on the first character of their id fields in glyphs[] */
+ int ghead[256]; /* glyph list head */
+ int gnext[NGLYPHS]; /* next item in glyph list */
+ /* charset section characters */
+ char c[NGLYPHS][GNLEN]; /* character names in charset */
struct glyph *g[NGLYPHS]; /* character glyphs in charset */
int n; /* number of characters in charset */
- /* font ligatures */
- char lig[NLIGS][LIGLEN * GNLEN];
- int nlig;
- /* glyph list based on the first character of glyph names */
- int head[256]; /* glyph list head */
- int next[NGLYPHS]; /* next item in glyph list */
- /* kerning pair list per glyph */
- int knhead[NGLYPHS]; /* kerning pairs of glyphs[] */
- int knnext[NKERNS]; /* next item in knhead[] list */
- int knpair[NKERNS]; /* kerning pair 2nd glyphs */
- int knval[NKERNS]; /* font pairwise kerning value */
- int knn; /* number of kerning pairs */
+ /* glyph list based on the first character of glyph names in c[] */
+ int chead[256]; /* glyph list head */
+ int cnext[NGLYPHS]; /* next item in glyph list */
};
/* output device functions */
@@ -67,8 +61,6 @@
void font_close(struct font *fn);
struct glyph *font_glyph(struct font *fn, char *id);
struct glyph *font_find(struct font *fn, char *name);
-int font_lig(struct font *fn, char **c, int n);
-int font_kern(struct font *fn, char *c1, char *c2);
/* output functions */
void out(char *s, ...);