#include #include #include #include struct gmap { struct gmap *next, *prev; int glyph; int width; unsigned char rules[4*8]; int len; int offset; }; static struct gmap *ctab[0x30000]; #define GMAP_WIDTH 1 #define GMAP_FINAL1 0 #define GMAP_FINAL2 1 #define GMAP_GLYPH1 2 #define GMAP_GLYPH2 3 #define RULE_RANGE 4 #define RULE_ATTACHED_TO 5 #define RULE_WITH_ATTACHED 6 #define RULE_FOLLOWS 7 #define RULE_PRECEDES 8 #define CTAB_MASK 0x3fffffff #define CTAB_INDIRECT 0x80000000 #define CTAB_WIDTH 30 static void put_u32(int n) { putchar(n>>24); putchar(n>>16); putchar(n>>8); putchar(n); } int main() { char buf[256], *s; int i; int ch; struct gmap *gm; int type, begin, len; int w=8, h=16; unsigned char gbuf[32]; char tmp[3]; int width; int nglyphs = 0; unsigned char *glyphs = 0; struct { unsigned begin, len, rel; } *ranges = 0; int nranges = 0; int ctab_len = 0; int gmap_len = 0; while ((s=fgets(buf, sizeof buf, stdin))) { if (*s++ != ':') continue; for (tmp[2]=i=0; iglyph = nglyphs-width; gm->width = width; gm->next = 0; gm->prev = ctab[ch]; if (ctab[ch]) ctab[ch]->next = gm; ctab[ch] = gm; i=0; while(irules)-12 && *s && !isspace(*s)) { switch (*s++) { case '+': type = RULE_WITH_ATTACHED; break; case '-': type = RULE_ATTACHED_TO; break; case '<': type = RULE_PRECEDES; break; case '>': type = RULE_FOLLOWS; break; default: exit(1); } if (*s == '[') { begin = strtol(++s, &s, 16); if (*s++ != '-') exit(1); len = strtol(s, &s, 16) - begin + 1; if (*s++ != ']') exit(1); gm->rules[i++] = type; gm->rules[i++] = begin>>16; gm->rules[i++] = begin>>8; gm->rules[i++] = begin; gm->rules[i++] = RULE_RANGE; gm->rules[i++] = len>>16; gm->rules[i++] = len>>8; gm->rules[i++] = len; } else if (isxdigit(*s)) { begin = strtol(s, &s, 16); gm->rules[i++] = type; gm->rules[i++] = begin>>16; gm->rules[i++] = begin>>8; gm->rules[i++] = begin; } else exit(1); } gm->rules[i++] = GMAP_GLYPH1 | (gm->width-1); gm->rules[i++] = (gm->glyph)>>16; gm->rules[i++] = (gm->glyph)>>8; gm->rules[i++] = (gm->glyph); gm->len = i; } } /* Count total glyph mapping rules and figure the table offsets */ for (ch=0; ch < sizeof(ctab)/sizeof(ctab[0]); ch++) { for (gm = ctab[ch]; gm && gm->prev; gm = gm->prev); /* Exclude rules that can be replaced by a trivial mapping */ if (!gm || (!gm->next && gm->len == 4)) { if (gm) gm->len = 0; continue; } for (ctab[ch] = gm; gm; gm = gm->next) { /* Terminate the rules list */ if (!gm->next) gm->rules[gm->len-4] &= GMAP_WIDTH; gm->offset = gmap_len; gmap_len += gm->len; } } /* Compact empty intervals and intervals with trivial glyph mapping */ begin = 1; for (ch=1; ch <= sizeof(ctab)/sizeof(ctab[0]); ch++) { if (ch == sizeof(ctab)/sizeof(ctab[0]) || (ctab[ch-1] != ctab[ch] &&(!ctab[ch-1] || !ctab[ch] || ctab[ch-1]->prev || ctab[ch-1]->len > 4 || ctab[ch]->prev || ctab[ch]->len > 4 || ctab[ch]->glyph != ctab[ch-1]->glyph + ctab[ch-1]->width || ctab[ch]->width != ctab[ch-1]->width))) { if (ch - begin >= 1024) { ranges = realloc(ranges, sizeof(ranges[0])*(nranges+1)); ranges[nranges].begin = begin; ranges[nranges++].len = ch-begin; } begin = ch+1; } } ranges[nranges-1].len = 0x110000; /* Count total size of the character table */ ranges[0].rel = ranges[0].begin; ctab_len = 1 + nranges*2 + ranges[0].begin; for (i=1; ilen == 0) put_u32(ctab[ch]->glyph | ctab[ch]->width-1<<30); else put_u32(ctab[ch]->offset | 0x80000000); } // offset 32 + ctab_len for (ch=0; ch < sizeof(ctab)/sizeof(ctab[0]); ch++) for (gm = ctab[ch]; gm; gm = gm->next) fwrite(gm->rules, 1, gm->len, stdout); // offset 30 + ctab_len + gmap_len fwrite(glyphs, 16, nglyphs, stdout); return 0; }