From: ben Date: Sat, 6 Jan 2007 17:32:34 +0000 (+0000) Subject: Overhaul of glyph-name handling in the paper backends. Before, we had X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/halibut/commitdiff_plain/d5bc1c48d6a59db9480a3c8ce43fd8ca8a3b6a21 Overhaul of glyph-name handling in the paper backends. Before, we had a separate dense array of glyph names for each font, and referenced glyphs by indicies into that array, which meant that the array had to be set up before we could generate any indices. Now we have an overall array of glyph names, and use the same glyph indicies for all fonts. Some arrays have had to turn into tree234s as a result. git-svn-id: svn://svn.tartarus.org/sgt/halibut@7061 cda61777-01e9-0310-a592-d414129be87e --- diff --git a/bk_paper.c b/bk_paper.c index fc9f91b..c17dfc8 100644 --- a/bk_paper.c +++ b/bk_paper.c @@ -1350,14 +1350,80 @@ static font_encoding *new_font_encoding(font_data *font) fe->free_pos = 0x21; for (i = 0; i < 256; i++) { - fe->vector[i] = NULL; - fe->indices[i] = -1; + fe->vector[i] = NOGLYPH; fe->to_unicode[i] = 0xFFFF; } return fe; } +static subfont_map_entry *encode_glyph_at(glyph g, wchar_t u, + font_encoding *fe, int pos) +{ + subfont_map_entry *sme = snew(subfont_map_entry); + + sme->subfont = fe; + sme->position = pos; + fe->vector[pos] = g; + fe->to_unicode[pos] = u; + add234(fe->font->subfont_map, sme); + return sme; +} + +static int new_sfmap_cmp(void *a, void *b) +{ + glyph ga = *(glyph *)a; + subfont_map_entry *sb = b; + glyph gb = sb->subfont->vector[sb->position]; + + if (ga < gb) return -1; + if (ga > gb) return 1; + return 0; +} + +static subfont_map_entry *encode_glyph(glyph g, wchar_t u, font_data *font) +{ + subfont_map_entry *sme; + int c; + + sme = find234(font->subfont_map, &g, new_sfmap_cmp); + if (sme) return sme; + + /* + * This character is not yet in a subfont. Assign one. + */ + if (font->latest_subfont->free_pos >= 0x100) + font->latest_subfont = new_font_encoding(font); + + c = font->latest_subfont->free_pos++; + if (font->latest_subfont->free_pos == 0x7F) + font->latest_subfont->free_pos = 0xA1; + + return encode_glyph_at(g, u, font->latest_subfont, c); +} + +static int sfmap_cmp(void *a, void *b) +{ + subfont_map_entry *sa = a, *sb = b; + glyph ga = sa->subfont->vector[sa->position]; + glyph gb = sb->subfont->vector[sb->position]; + + if (ga < gb) return -1; + if (ga > gb) return 1; + return 0; +} + +int width_cmp(void *a, void *b) +{ + glyph_width const *wa = a, *wb = b; + + if (wa->glyph < wb->glyph) + return -1; + if (wa->glyph > wb->glyph) + return 1; + return 0; +} + int kern_cmp(void *a, void *b) { kern_pair const *ka = a, *kb = b; @@ -1388,50 +1454,12 @@ int lig_cmp(void *a, void *b) return 0; } -/* This wouldn't be necessary if C had closures. */ -static font_info *glyph_cmp_fi; - -static int glyph_cmp(void const *a, void const *b) -{ - return strcmp(glyph_cmp_fi->glyphs[*(unsigned short *)a], - glyph_cmp_fi->glyphs[*(unsigned short *)b]); -} - -/* - * Set up the glyphsbyname index for a font. - */ -void font_index_glyphs(font_info *fi) { - int i; - - fi->glyphsbyname = snewn(fi->nglyphs, unsigned short); - for (i = 0; i < fi->nglyphs; i++) - fi->glyphsbyname[i] = i; - glyph_cmp_fi = fi; - qsort(fi->glyphsbyname, fi->nglyphs, sizeof(fi->glyphsbyname[0]), - glyph_cmp); -} - -int find_glyph(font_info const *fi, char const *name) { - int i, j, k, r; - - i = -1; - j = fi->nglyphs; - while (j-i > 1) { - k = (i + j) / 2; - r = strcmp(fi->glyphs[fi->glyphsbyname[k]], name); - if (r == 0) - return fi->glyphsbyname[k]; - else if (r > 0) - j = k; - else - i = k; - } - return -1; +static int utoglyph(font_info const *fi, wchar_t u) { + return (u < 0 || u > 0xFFFF ? NOGLYPH : fi->bmp[u]); } static font_data *make_std_font(font_list *fontlist, char const *name) { - int nglyphs; font_info const *fi; font_data *f; font_encoding *fe; @@ -1449,8 +1477,7 @@ static font_data *make_std_font(font_list *fontlist, char const *name) f->list = fontlist; f->info = fi; - nglyphs = f->info->nglyphs; - f->subfont_map = snewn(nglyphs, subfont_map_entry); + f->subfont_map = newtree234(sfmap_cmp); /* * Our first subfont will contain all of US-ASCII. This isn't @@ -1463,34 +1490,33 @@ static font_data *make_std_font(font_list *fontlist, char const *name) fe->free_pos = 0xA1; /* only the top half is free */ f->latest_subfont = fe; - for (i = 0; i < nglyphs; i++) { - wchar_t ucs; - ucs = ps_glyph_to_unicode(f->info->glyphs[i]); - if (ucs >= 0x20 && ucs <= 0x7E) { - fe->vector[ucs] = f->info->glyphs[i]; - fe->indices[ucs] = i; - fe->to_unicode[ucs] = ucs; - f->subfont_map[i].subfont = fe; - f->subfont_map[i].position = ucs; - } else { - /* - * This character is not yet assigned to a subfont. - */ - f->subfont_map[i].subfont = NULL; - f->subfont_map[i].position = 0; - } + for (i = 0x21; i <= 0x7E; i++) { + glyph g = utoglyph(fi, i); + if (g != NOGLYPH) + encode_glyph_at(g, i, fe, i); } return f; } /* NB: arguments are glyph numbers from font->bmp. */ +int find_width(font_data *font, glyph index) +{ + glyph_width wantw; + glyph_width const *w; + + wantw.glyph = index; + w = find234(font->info->widths, &wantw, NULL); + if (!w) return 0; + return w->width; +} + static int find_kern(font_data *font, int lindex, int rindex) { kern_pair wantkp; kern_pair const *kp; - if (lindex == 0xFFFF || rindex == 0xFFFF) + if (lindex == NOGLYPH || rindex == NOGLYPH) return 0; wantkp.left = lindex; wantkp.right = rindex; @@ -1505,20 +1531,16 @@ static int find_lig(font_data *font, int lindex, int rindex) ligature wantlig; ligature const *lig; - if (lindex == 0xFFFF || rindex == 0xFFFF) - return 0xFFFF; + if (lindex == NOGLYPH || rindex == NOGLYPH) + return NOGLYPH; wantlig.left = lindex; wantlig.right = rindex; lig = find234(font->info->ligs, &wantlig, NULL); if (lig == NULL) - return 0xFFFF; + return NOGLYPH; return lig->lig; } -static int utoglyph(font_info const *fi, wchar_t u) { - return (u < 0 || u > 0xFFFF ? 0xFFFF : fi->bmp[u]); -} - static int string_width(font_data *font, wchar_t const *string, int *errs, unsigned flags) { @@ -1528,22 +1550,21 @@ static int string_width(font_data *font, wchar_t const *string, int *errs, if (errs) *errs = 0; - oindex = 0xFFFF; + oindex = NOGLYPH; index = utoglyph(font->info, *string); for (; *string; string++) { nindex = utoglyph(font->info, string[1]); - if (index == 0xFFFF) { + if (index == NOGLYPH) { if (errs) *errs = 1; } else { if (!(flags & RS_NOLIG) && - (lindex = find_lig(font, index, nindex)) != 0xFFFF) { + (lindex = find_lig(font, index, nindex)) != NOGLYPH) { index = lindex; continue; } - width += find_kern(font, oindex, index) + - font->info->widths[index]; + width += find_kern(font, oindex, index) + find_width(font, index); } oindex = index; index = nindex; @@ -1987,24 +2008,25 @@ static int render_string(page_data *page, font_data *font, int fontsize, char *text; int textpos, textwid, kern, nglyph, glyph, oglyph, lig; font_encoding *subfont = NULL, *sf; + subfont_map_entry *sme; text = snewn(1 + ustrlen(str), char); textpos = textwid = 0; - glyph = 0xFFFF; + glyph = NOGLYPH; nglyph = utoglyph(font->info, *str); while (*str) { oglyph = glyph; glyph = nglyph; nglyph = utoglyph(font->info, str[1]); - if (glyph == 0xFFFF) { + if (glyph == NOGLYPH) { str++; continue; /* nothing more we can do here */ } if (!(flags & RS_NOLIG) && - (lig = find_lig(font, glyph, nglyph)) != 0xFFFF) { + (lig = find_lig(font, glyph, nglyph)) != NOGLYPH) { nglyph = lig; str++; continue; @@ -2013,29 +2035,8 @@ static int render_string(page_data *page, font_data *font, int fontsize, /* * Find which subfont this character is going in. */ - sf = font->subfont_map[glyph].subfont; - - if (!sf) { - int c; - - /* - * This character is not yet in a subfont. Assign one. - */ - if (font->latest_subfont->free_pos >= 0x100) - font->latest_subfont = new_font_encoding(font); - - c = font->latest_subfont->free_pos++; - if (font->latest_subfont->free_pos == 0x7F) - font->latest_subfont->free_pos = 0xA1; - - font->subfont_map[glyph].subfont = font->latest_subfont; - font->subfont_map[glyph].position = c; - font->latest_subfont->vector[c] = font->info->glyphs[glyph]; - font->latest_subfont->indices[c] = glyph; - font->latest_subfont->to_unicode[c] = *str; - - sf = font->latest_subfont; - } + sme = encode_glyph(glyph, *str, font); + sf = sme->subfont; kern = find_kern(font, oglyph, glyph) * fontsize; @@ -2053,8 +2054,8 @@ static int render_string(page_data *page, font_data *font, int fontsize, subfont = sf; } - text[textpos++] = font->subfont_map[glyph].position; - textwid += font->info->widths[glyph] * fontsize; + text[textpos++] = sme->position; + textwid += find_width(font, glyph) * fontsize; str++; } diff --git a/bk_pdf.c b/bk_pdf.c index bdce859..3a0ec75 100644 --- a/bk_pdf.c +++ b/bk_pdf.c @@ -159,14 +159,14 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords, for (i = 0; i < 256; i++) { char buf[20]; - if (!fe->vector[i]) + if (fe->vector[i] == NOGLYPH) continue; if (i != prev + 1) { sprintf(buf, "\n%d", i); objtext(font, buf); } objtext(font, i % 8 ? "/" : "\n/"); - objtext(font, fe->vector[i]); + objtext(font, glyph_extern(fe->vector[i])); prev = i; } @@ -190,7 +190,7 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords, font_info const *fi = fe->font->info; int flags; for (i = 0; i < 256; i++) - if (fe->indices[i] >= 0) { + if (fe->vector[i] != NOGLYPH) { if (firstchar < 0) firstchar = i; lastchar = i; } @@ -202,10 +202,10 @@ void pdf_backend(paragraph *sourceform, keywordlist *keywords, objtext(widths, "[\n"); for (i = firstchar; i <= lastchar; i++) { double width; - if (fe->indices[i] < 0) + if (fe->vector[i] == NOGLYPH) width = 0.0; else - width = fi->widths[fe->indices[i]]; + width = find_width(fe->font, fe->vector[i]); sprintf(buf, "%g\n", 1000.0 * width / FUNITS_PER_PT); objtext(widths, buf); } diff --git a/bk_ps.c b/bk_ps.c index 46652e9..5d1a951 100644 --- a/bk_ps.c +++ b/bk_ps.c @@ -230,8 +230,7 @@ void ps_backend(paragraph *sourceform, keywordlist *keywords, ps_token(fp, &cc, "{1 index /FID ne {def} {pop pop} ifelse} forall\n"); ps_token(fp, &cc, "/Encoding [\n"); for (i = 0; i < 256; i++) - ps_token(fp, &cc, "/%s", - fe->vector[i] ? fe->vector[i] : ".notdef"); + ps_token(fp, &cc, "/%s", glyph_extern(fe->vector[i])); ps_token(fp, &cc, "] def\n"); ps_token(fp, &cc, "currentdict end\n"); ps_token(fp, &cc, "/fontname-%s exch definefont /%s exch def\n", diff --git a/in_afm.c b/in_afm.c index a4dd0f6..d3d5ecb 100644 --- a/in_afm.c +++ b/in_afm.c @@ -55,9 +55,7 @@ void read_afm_file(input *in) { fi = snew(font_info); fi->name = NULL; - fi->nglyphs = 0; - fi->glyphs = NULL; - fi->widths = NULL; + fi->widths = newtree234(width_cmp); fi->fp = NULL; fi->kerns = newtree234(kern_cmp); fi->ligs = newtree234(lig_cmp); @@ -153,19 +151,17 @@ void read_afm_file(input *in) { } fi->italicangle = atof(val); } else if (strcmp(key, "StartCharMetrics") == 0) { - char const **glyphs; - int *widths; - int i; + int nglyphs, i; if (!(val = strtok(NULL, " \t"))) { error(err_afmval, &in->pos, key, 1); goto giveup; } - fi->nglyphs = atoi(val); + nglyphs = atoi(val); sfree(line); - glyphs = snewn(fi->nglyphs, char const *); - widths = snewn(fi->nglyphs, int); - for (i = 0; i < fi->nglyphs; i++) { - glyphs[i] = NULL; + for (i = 0; i < nglyphs; i++) { + int width = 0; + glyph g = NOGLYPH; + line = afm_read_line(in); if (line == NULL) goto giveup; @@ -177,14 +173,14 @@ void read_afm_file(input *in) { error(err_afmval, &in->pos, key, 1); goto giveup; } - widths[i] = atoi(val); + width = atoi(val); } else if (strcmp(key, "N") == 0) { if (!(val = strtok(NULL, " \t")) || !strcmp(val, ";")) { error(err_afmval, &in->pos, key, 1); goto giveup; } - glyphs[i] = dupstr(val); + g = glyph_intern(val); } do { key = strtok(NULL, " \t"); @@ -192,21 +188,22 @@ void read_afm_file(input *in) { key = strtok(NULL, " \t"); } sfree(line); + if (width != 0 && g != NOGLYPH) { + wchar_t ucs; + glyph_width *w = snew(glyph_width); + w->glyph = g; + w->width = width; + add234(fi->widths, w); + ucs = ps_glyph_to_unicode(glyph_extern(g)); + if (ucs < 0xFFFF) + fi->bmp[ucs] = g; + } } line = afm_read_line(in); if (!line || !afm_require_key(line, "EndCharMetrics", in)) goto giveup; sfree(line); - fi->glyphs = glyphs; - fi->widths = widths; - for (i = 0; i < fi->nglyphs; i++) { - wchar_t ucs; - ucs = ps_glyph_to_unicode(fi->glyphs[i]); - if (ucs < 0xFFFF) - fi->bmp[ucs] = i; - } - font_index_glyphs(fi); } else if (strcmp(key, "StartKernPairs") == 0 || strcmp(key, "StartKernPairs0") == 0) { int nkerns, i; @@ -234,8 +231,8 @@ void read_afm_file(input *in) { error(err_afmval, &in->pos, key, 3); goto giveup; } - l = find_glyph(fi, nl); - r = find_glyph(fi, nr); + l = glyph_intern(nl); + r = glyph_intern(nr); if (l == -1 || r == -1) continue; kp = snew(kern_pair); kp->left = l; diff --git a/paper.h b/paper.h index 9bea29d..bab9e4f 100644 --- a/paper.h +++ b/paper.h @@ -12,7 +12,12 @@ #define UNITS_PER_PT 1000 #define FUNITS_PER_PT 1000.0 +/* Glyphs are represented by integer indicies into a table of names. */ +typedef unsigned short glyph; +#define NOGLYPH 0xFFFF + typedef struct document_Tag document; +typedef struct glyph_width_Tag glyph_width; typedef struct kern_pair_Tag kern_pair; typedef struct ligature_Tag ligature; typedef struct font_info_Tag font_info; @@ -42,11 +47,20 @@ struct document_Tag { }; /* + * This data structure represents the normal width of a single glyph + * in a font. + */ +struct glyph_width_Tag { + glyph glyph; + int width; +}; + +/* * This data structure represents a kerning pair within a font. */ struct kern_pair_Tag { - /* Glyph indices, in font_data.glyphs. */ - unsigned short left, right; + /* Glyph indices. */ + glyph left, right; /* Kern amount, in internal units. */ int kern; }; @@ -55,7 +69,7 @@ struct kern_pair_Tag { * ... and this one represents a ligature. */ struct ligature_Tag { - unsigned short left, right, lig; + glyph left, right, lig; }; /* @@ -81,19 +95,8 @@ struct font_info_Tag { * Lengths of the unencrypted and encrypted portions of the font. */ long length1, length2; - /* - * An array of pointers to the available glyph names, and their - * corresponding character widths. These two arrays have - * parallel indices. - */ - int nglyphs; - const char *const *glyphs; - const int *widths; - /* - * Glyph indices sorted into glyph-name order, for name-to-index - * mapping. - */ - unsigned short *glyphsbyname; + /* A tree of glyph_widths */ + tree234 *widths; /* A tree of kern_pairs */ tree234 *kerns; /* ... and one of ligatures */ @@ -105,7 +108,7 @@ struct font_info_Tag { * know that no glyph in the Adobe Glyph List falls outside * it), whose elements are indices into the above two arrays. */ - unsigned short bmp[65536]; + glyph bmp[65536]; /* * Various bits of metadata needed for the /FontDescriptor dictionary * in PDF. @@ -128,12 +131,12 @@ struct font_data_Tag { font_info const *info; /* * At some point I'm going to divide the font into sub-fonts - * with largely non-overlapping encoding vectors. This array + * with largely non-overlapping encoding vectors. This tree * will track which glyphs go into which subfonts. Also here I * keep track of the latest subfont of any given font, so I can * go back and extend its encoding. */ - subfont_map_entry *subfont_map; + tree234 *subfont_map; font_encoding *latest_subfont; /* * The font list to which this font belongs. @@ -156,8 +159,7 @@ struct font_encoding_Tag { char *name; /* used by client backends */ font_data *font; /* the parent font structure */ - const char *vector[256]; /* the actual encoding vector */ - int indices[256]; /* indices back into main font struct */ + glyph vector[256]; /* the actual encoding vector */ wchar_t to_unicode[256]; /* PDF will want to know this */ int free_pos; /* space left to extend encoding */ }; @@ -372,15 +374,16 @@ struct outline_element_Tag { /* * Functions exported from bk_paper.c */ +int width_cmp(void *, void *); /* use when setting up widths */ int kern_cmp(void *, void *); /* use when setting up kern_pairs */ int lig_cmp(void *, void *); /* use when setting up ligatures */ -void font_index_glyphs(font_info *fi); -int find_glyph(font_info const *fi, char const *name); - +int find_width(font_data *, glyph); /* * Functions and data exported from psdata.c. */ +glyph glyph_intern(char const *); +char const *glyph_extern(glyph); wchar_t ps_glyph_to_unicode(char const *glyph); extern const char *const ps_std_glyphs[]; void init_std_fonts(void); diff --git a/psdata.c b/psdata.c index e9cad9c..66354d3 100644 --- a/psdata.c +++ b/psdata.c @@ -7,23 +7,18 @@ #include "halibut.h" #include "paper.h" -/* ---------------------------------------------------------------------- - * Mapping between PS character names (/aacute, /zcaron etc) and - * Unicode code points. - * - * Generated from the Adobe Glyph List at - * - * http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt - * - * by a succession of Perl/sh fragments, quoted alongside each - * array. - */ - /* + * Within the paper backends, PostScript glyph names are represented + * by small integers. For standard glyphs, these are indicies into + * a table generated from the Adobe Glyph List from + * . + * Since all the scripts that generate fragments of code for this file + * need that list, it's worth generating a file containing just the names. -grep '^[^#;][^;]*;[^ ][^ ][^ ][^ ]$' glyphlist.txt | sort -t\; +0 -1 | \ - cut -f1 -d\; | perl -ne 'chomp; print "\"$_\", "' | \ - fold -s -w68 | sed 's/^/ /'; echo +grep '^[^#;][^;]*;[^ ][^ ][^ ][^ ]$' glyphlist.txt | sort -t\; -k1,2 | \ + cut -f1 -d\; > glyphnames.txt + +< glyphnames.txt xargs printf '"%s", ' | fold -s -w68 | sed 's/^/ /'; echo */ static const char *const ps_glyphs_alphabetic[] = { @@ -1120,7 +1115,44 @@ static const char *const ps_glyphs_alphabetic[] = { "zretroflexhook", "zstroke", "zuhiragana", "zukatakana", }; -/* +glyph glyph_intern(char const *glyphname) +{ + int i, j, k, c; + + i = -1; + j = lenof(ps_glyphs_alphabetic); + while (j-i > 1) { + k = (i + j) / 2; + c = strcmp(glyphname, ps_glyphs_alphabetic[k]); + + if (c == 0) + return k; + else if (c < 0) + j = k; + else + i = k; + } + + return NOGLYPH; /* illegal value means not found */ +} + +char const *glyph_extern(glyph glyph) +{ + + if (glyph == NOGLYPH) return ".notdef"; + assert(glyph < lenof(ps_glyphs_alphabetic)); + return ps_glyphs_alphabetic[glyph]; +} + +/* ---------------------------------------------------------------------- + * Mapping between PS character names (/aacute, /zcaron etc) and + * Unicode code points. + * + * Generated from the Adobe Glyph List at + * + * http://partners.adobe.com/public/developer/en/opentype/glyphlist.txt + * + * by another Perl/sh fragment. grep '^[^#;][^;]*;[^ ][^ ][^ ][^ ]$' glyphlist.txt | sort -t\; +0 -1 | \ cut -f2 -d\; | perl -ne 'chomp; print "0x$_, "' | \ @@ -1655,25 +1687,12 @@ static const unsigned short ps_codes_alphabetic[] = { 0xFF5A, 0x305E, 0x30BE, 0x24B5, 0x0290, 0x01B6, 0x305A, 0x30BA, }; -wchar_t ps_glyph_to_unicode(char const *glyph) +wchar_t ps_glyph_to_unicode(char const *glyphname) { - int i, j, k, c; - - i = -1; - j = lenof(ps_glyphs_alphabetic); - while (j-i > 1) { - k = (i + j) / 2; - c = strcmp(glyph, ps_glyphs_alphabetic[k]); - - if (c == 0) - return ps_codes_alphabetic[k]; - else if (c < 0) - j = k; - else - i = k; - } - - return 0xFFFF; /* illegal value means not found */ + glyph g = glyph_intern(glyphname); + + if (g == NOGLYPH) return 0xFFFF; + return ps_codes_alphabetic[g]; } /* ---------------------------------------------------------------------- @@ -1803,23 +1822,27 @@ fonts="Times-Roman Times-Italic Times-Bold Times-BoldItalic \ for i in $fonts; do printf 'static const kern_pair %s_kerns[] = {\n' $(echo $i | tr 'A-Z\-' a-z_) perl -e ' -open G, "stdchars.txt" or die; -chomp(@g = ); %g = map(($_, $i++), @g); +open S, "stdchars.txt" or die; +chomp(@s = ); +open G, "glyphnames.txt" or die; +chomp(@g = ); %g = map(($_, $i++), @g); %g = map(($_, $g{$_}), @s); open M, "$ARGV[0].afm" or die; while () { /KPX (\S+) (\S+) (\S+)/ and exists $g{$1} and exists $g{$2} and print "{$g{$1},$g{$2},$3}, "; } print "\n"' $i |\ fold -sw 68 | sed 's/^/ /' - printf ' {0xFFFF,0xFFFF,0}\n};\n' + printf ' {NOGLYPH,NOGLYPH,0}\n};\n' printf 'static const ligature %s_ligs[] = {\n' $(echo $i | tr 'A-Z\-' a-z_) perl -e ' -open G, "stdchars.txt" or die; -chomp(@g = ); %g = map(($_, $i++), @g); +open S, "stdchars.txt" or die; +chomp(@s = ); +open G, "glyphnames.txt" or die; +chomp(@g = ); %g = map(($_, $i++), @g); %g = map(($_, $g{$_}), @s); open M, "$ARGV[0].afm" or die; while () { / N (\S+) / and $l = $1; while (/ L (\S+) (\S+) /g) { exists $g{$l} and exists $g{$1} and exists $g{$2} and print "{$g{$l},$g{$1},$g{$2}}, "; } } print "\n"' $i |\ fold -sw 68 | sed 's/^/ /' - printf ' {0xFFFF,0xFFFF,0xFFFF}\n};\n' + printf ' {NOGLYPH,NOGLYPH,NOGLYPH}\n};\n' done cat <fp = NULL; fi->name = ps_std_fonts[i].name; - fi->nglyphs = lenof(ps_std_glyphs) - 1; - fi->glyphs = ps_std_glyphs; - fi->widths = ps_std_fonts[i].widths; - fi->kerns = newtree234(kern_cmp); - for (kern = ps_std_fonts[i].kerns; kern->left != 0xFFFF; kern++) - add234(fi->kerns, (void *)kern); - fi->ligs = newtree234(lig_cmp); - for (lig = ps_std_fonts[i].ligs; lig->left != 0xFFFF; lig++) - add234(fi->ligs, (void *)lig); + fi->widths = newtree234(width_cmp); for (j = 0; j < (int)lenof(fi->bmp); j++) - fi->bmp[j] = 0xFFFF; - for (j = 0; j < fi->nglyphs; j++) { + fi->bmp[j] = NOGLYPH; + for (j = 0; j < (int)lenof(ps_std_glyphs) - 1; j++) { + glyph_width *w = snew(glyph_width); wchar_t ucs; - ucs = ps_glyph_to_unicode(fi->glyphs[j]); + w->glyph = glyph_intern(ps_std_glyphs[j]); + w->width = ps_std_fonts[i].widths[j]; + add234(fi->widths, w); + ucs = ps_glyph_to_unicode(ps_std_glyphs[j]); assert(ucs != 0xFFFF); - fi->bmp[ucs] = j; + fi->bmp[ucs] = w->glyph; } + fi->kerns = newtree234(kern_cmp); + for (kern = ps_std_fonts[i].kerns; kern->left != NOGLYPH; kern++) + add234(fi->kerns, (void *)kern); + fi->ligs = newtree234(lig_cmp); + for (lig = ps_std_fonts[i].ligs; lig->left != NOGLYPH; lig++) + add234(fi->ligs, (void *)lig); fi->next = all_fonts; all_fonts = fi; }