ref: 5c18bf016c0841ec61e1b144b45a8c4cb38356b6
parent: 66e510c36551eaa35584ec0213411d475bdb51f9
author: Ali Gholami Rudi <ali@rudi.ir>
date: Wed Aug 6 05:29:48 EDT 2014
font: assign distinct hashes to rules with specific second glyphs
--- a/font.c
+++ b/font.c
@@ -9,7 +9,7 @@
#define GF_PAT 1 /* gsub/gpos pattern glyph */
#define GF_REP 2 /* gsub replacement glyph */
#define GF_CON 4 /* context glyph */
-#define GF_ALT 8 /* pattern followed by alternative patterns */
+#define GF_ALT 8 /* glyph followed by alternative glyphs */
/* glyph pattern for gsub and gpos tables; each grule has some gpats */
struct gpat {
@@ -142,13 +142,18 @@
{
int g1 = -1, g2 = -1;
int i = 0;
- while (i < rule->len && rule->pats[i].flg == GF_REP)
+ /* finding the first glyph; -1 if it matches more than one glyph */
+ while (i < rule->len && rule->pats[i].flg & (GF_REP | GF_CON))
+ i++; /* skipping replacement and context glyphs */
+ g1 = i < rule->len && rule->pats[i].flg == GF_PAT ? rule->pats[i].g : -1;
+ while (g1 < 0 && i < rule->len && rule->pats[i].flg & GF_ALT)
i++;
- g1 = i < rule->len && rule->pats[i].flg == GF_PAT ? rule->pats[i++].g : -1;
- while (i < rule->len && rule->pats[i].flg == GF_REP)
- i++;
+ i++;
+ /* finding the second glyph; -1 if it matches more than one glyph */
+ while (i < rule->len && rule->pats[i].flg & GF_REP)
+ i++; /* skipping replacement glyphs */
g2 = i < rule->len && rule->pats[i].flg == GF_PAT ? rule->pats[i++].g : -1;
- return GHASH(g1, g1 < 0 ? -1 : g2);
+ return GHASH(g1, g2);
}
static int grule_find(struct grule *rules, int n, int hash)
@@ -211,17 +216,19 @@
static struct grule *font_findrule(struct font *fn, struct grule *rules, int n,
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 idx[4] = {-1, -1, -1, -1};
+ int hash[4];
int i, j;
- for (j = 0; j < LEN(hash) && j <= slen; j++)
+ for (j = 0; j < 4 && j < (slen << 1); j++) {
+ hash[j] = GHASH(j & 1 ? src[0] : -1, j & 2 ? src[1] : -1);
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;
+ i = -1; /* finding the first rule among idx[] */
+ for (j = 0; j < 4; j++)
+ if (idx[j] >= 0 && idx[j] < n && rules[idx[j]].hash == hash[j])
+ if (i < 0 || rules[idx[j]].pos <= rules[idx[i]].pos)
+ i = j;
if (i < 0)
break;
if (font_rulematches(fn, rules + idx[i], src, slen, dst, dlen))