ref: 781e4139f4c6ff4606c131fbc9649108862041b2
parent: 19c01743a735453e0529767156a42df75c817523
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Aug 5 05:12:03 EDT 2014
font: prefer rules appearing first in the font
--- a/font.c
+++ b/font.c
@@ -23,6 +23,7 @@
struct gpat *pats;
short len; /* pats[] length */
short feat; /* feature owning this rule */
+ short pos; /* position of this rule in the file */
int hash; /* hash of this rule for sorting and comparison */
};
@@ -113,9 +114,12 @@
return g ? g - fn->glyphs : -1;
}
+/* compare their hashes, then their positions to make qsort() stable */
static int grulecmp(void *v1, void *v2)
{
- return ((struct grule *) v1)->hash - ((struct grule *) v2)->hash;
+ struct grule *r1 = v1;
+ struct grule *r2 = v2;
+ return r1->hash == r2->hash ? r1->pos - r2->pos : r1->hash - r2->hash;
}
/* the hashing function for grule structs, based on their first two glyphs */
@@ -193,14 +197,21 @@
int *src, int slen, int *dst, int dlen)
{
int hash[] = {GHASH(-1, -1), GHASH(src[0], -1), GHASH(src[0], src[1])};
+ int idx[] = {-1, -1, -1};
int i, j;
- for (j = 0; j < LEN(hash) && j <= slen; j++) {
- int idx = grule_find(rules, n, hash[j]);
- if (idx < 0)
- continue;
- for (i = idx; i < n && rules[i].hash == hash[j]; i++)
- if (font_rulematches(fn, rules + i, src, slen, dst, dlen))
- return rules + i;
+ for (j = 0; j < LEN(hash) && j <= slen; j++)
+ idx[j] = grule_find(rules, n, hash[j]);
+ while (1) {
+ i = -1; /* finding the first position */
+ for (j = 0; j < LEN(hash); j++)
+ if (idx[j] >= 0 && idx[j] < n && hash[j] == rules[idx[j]].hash &&
+ (i < 0 || rules[idx[i]].pos < rules[idx[j]].pos))
+ i = j;
+ if (i < 0)
+ break;
+ if (font_rulematches(fn, rules + idx[i], src, slen, dst, dlen))
+ return rules + idx[i];
+ idx[i]++;
}
return NULL;
}
@@ -306,7 +317,7 @@
static struct gpat *font_gpat(struct font *fn, int len)
{
int pos = fn->pats_pos;
- if (pos + 9 > LEN(fn->pats) && pos + 6 < LEN(fn->pats))
+ if (pos < LEN(fn->pats) - 10 && pos + len > LEN(fn->pats) - 10)
errmsg("neatroff: NGPATS too low\n");
if (pos + len > LEN(fn->pats))
return NULL;
@@ -503,6 +514,10 @@
for (i = 0; i < ligs_n; i++)
font_lig(fn, ligs[i]);
fclose(fin);
+ for (i = 0; i < fn->gsub_n; i++)
+ fn->gsub[i].pos = i;
+ for (i = 0; i < fn->gpos_n; i++)
+ fn->gpos[i].pos = i;
for (i = 0; i < fn->gsub_n; i++)
fn->gsub[i].hash = grule_hash(&fn->gsub[i]);
for (i = 0; i < fn->gpos_n; i++)