From 7b312fcae3460fd1385867b539911db32dbf6cb5 Mon Sep 17 00:00:00 2001 From: handa Date: Mon, 29 Oct 2007 02:33:25 +0000 Subject: [PATCH] (Mgenerator, Mend): New variables. (flt_min_coverage, flt_max_coverage): New variables. (GCPY): New macro. (GDUP): Use it. (Mfont_has): Renamed from Mexist. Referrers chagned. (gen_otf_tag): Handle the trailing whitespaces. (otf_count_features, otf_store_features): Fix for negative features. (parse_otf_command): Adjusted for the change of MFLTOtfSpec. (load_otf_command): Likewise. (free_flt_command): Adjusted for the change of MFLTOtfSpec. (load_flt): Argument changed. Caller changed. (free_flt_list): New function. (run_rule): Adjusted for the change of FontLayoutContext. (mflt_run): Adjusted for the change of FontLayoutContext. --- src/m17n-flt.c | 949 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 580 insertions(+), 369 deletions(-) diff --git a/src/m17n-flt.c b/src/m17n-flt.c index 80795ea..dcc610f 100644 --- a/src/m17n-flt.c +++ b/src/m17n-flt.c @@ -242,7 +242,10 @@ static int mdebug_flag = MDEBUG_FONT_FLT; MSymbol Mfont, Mlayouter; +static MSymbol Mgenerator, Mend; + static MPlist *flt_list; +static int flt_min_coverage, flt_max_coverage; enum GlyphInfoMask { @@ -269,16 +272,13 @@ enum GlyphInfoMask #define GET_MEASURED(g) ((g)->measured) #define SET_MEASURED(g, flag) ((g)->measured = (flag)) -#define GINIT(gstring, n) \ - do { \ - if (! (gstring)->glyph_size) \ - (gstring)->glyph_size = sizeof (MFLTGlyph); \ - if ((n) > 0) \ - { \ - (gstring)->glyphs = alloca ((gstring)->glyph_size * (n)); \ - (gstring)->allocated = (n); \ - (gstring)->used = 0; \ - } \ +#define GINIT(gstring, n) \ + do { \ + if (! (gstring)->glyph_size) \ + (gstring)->glyph_size = sizeof (MFLTGlyph); \ + (gstring)->glyphs = alloca ((gstring)->glyph_size * (n)); \ + (gstring)->allocated = (n); \ + (gstring)->used = 0; \ } while (0) #define GALLOCA (gstring) \ @@ -287,16 +287,21 @@ enum GlyphInfoMask #define GREF(gstring, idx) \ ((MFLTGlyph *) ((char *) ((gstring)->glyphs) + (gstring)->glyph_size * (idx))) -#define GDUP(ctx, idx) \ +#define GCPY(src, src_idx, n, tgt, tgt_idx) \ do { \ - MFLTGlyphString *src = ctx->in; \ - MFLTGlyphString *tgt = ctx->out; \ - if ((tgt)->allocated <= (tgt)->used) \ - return -2; \ - memcpy ((char *) (tgt->glyphs) + tgt->glyph_size * tgt->used, \ - (char *) (src->glyphs) + src->glyph_size * (idx), \ - (src)->glyph_size); \ - tgt->used++; \ + memcpy ((char *) ((tgt)->glyphs) + (tgt)->glyph_size * (tgt_idx), \ + (char *) ((src)->glyphs) + (src)->glyph_size * (src_idx), \ + (src)->glyph_size * (n)); \ + } while (0) + +#define GDUP(ctx, idx) \ + do { \ + MFLTGlyphString *src = (ctx)->in; \ + MFLTGlyphString *tgt = (ctx)->out; \ + if (tgt->allocated <= tgt->used) \ + return -2; \ + GCPY (src, (idx), 1, tgt, tgt->used); \ + tgt->used++; \ } while (0) static int @@ -350,7 +355,7 @@ GREPLACE (MFLTGlyphString *src, int src_from, int src_to, #define CMD_ID_TO_INDEX(id) (CMD_ID_OFFSET_INDEX - (id)) #define INDEX_TO_CMD_ID(idx) (CMD_ID_OFFSET_INDEX - (idx)) -static MSymbol Mcond, Mrange, Mexist; +static MSymbol Mcond, Mrange, Mfont_has; #define GLYPH_CODE_P(code) \ ((code) >= GLYPH_CODE_MIN && (code) <= GLYPH_CODE_MAX) @@ -442,6 +447,7 @@ struct _MFLT { MSymbol name; MSymbol family; + MSymbol registry; MFLTOtfSpec otf; MDatabase *mdb; MCharTable *coverage; @@ -452,70 +458,6 @@ struct _MFLT static int parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec); -static int -list_flt () -{ - MPlist *plist = mdatabase_list (Mfont, Mlayouter, Mnil, Mnil); - MPlist *pl; - - flt_list = mplist (); - MPLIST_DO (pl, plist) - { - MDatabase *mdb = MPLIST_VAL (pl); - MSymbol *tags = mdatabase_tag (mdb); - MPlist *properties = mdatabase__props (mdb), *p; - MFLT *flt; - - if (! MSTRUCT_CALLOC_SAFE (flt)) - goto memfull; - flt->name = tags[2]; - flt->mdb = mdb; - mplist_push (flt_list, flt->name, flt); - if (properties) - MPLIST_DO (properties, properties) - { - MSymbol sym = Mnil; - char *otf_spec; - - if (! MPLIST_PLIST_P (properties)) - continue; - p = MPLIST_PLIST (properties); - if (! MPLIST_SYMBOL_P (p)) - continue; - if (MPLIST_SYMBOL (p) != Mfont) - continue; - p = MPLIST_NEXT (p); - if (! MPLIST_PLIST_P (p)) - continue; - p = MPLIST_PLIST (p); - if (! MPLIST_SYMBOL_P (p)) - continue; - p = MPLIST_NEXT (p); - if (! MPLIST_SYMBOL_P (p)) - continue; - flt->family = MPLIST_SYMBOL (p); - MPLIST_DO (p, MPLIST_NEXT (p)) - if (MPLIST_SYMBOL_P (p)) - sym = MPLIST_SYMBOL (p); - if (sym - && (otf_spec = MSYMBOL_NAME (sym)) - && otf_spec[0] == ':' && otf_spec[1] == 'o' - && otf_spec[2] == 't' && otf_spec[3] == 'f') - { - if (parse_otf_command (sym, &flt->otf) == -2) - goto memfull; - } - } - } - M17N_OBJECT_UNREF (plist); - return 0; - - memfull: - M17N_OBJECT_UNREF (plist); - M17N_OBJECT_UNREF (flt_list); - MERROR (MERROR_MEMORY, -1); -} - /* Load a category table from PLIST. PLIST has this form: PLIST ::= ( FROM-CODE TO-CODE ? CATEGORY-CHAR ) * */ @@ -574,12 +516,16 @@ gen_otf_tag (char *p) for (i = 0; i < 4 && *p; i++, p++) tag = (tag << 8) | *p; - return (i < 4 ? 0 : tag); + for (; i < 4; i++) + tag = (tag << 8) | 0x20; + return tag; } static char * otf_count_features (char *p, char *end, char stopper, int *count) { + int negative = 0; + *count = 0; if (*p != stopper && *p != '\0') while (1) @@ -593,7 +539,11 @@ otf_count_features (char *p, char *end, char stopper, int *count) return NULL; } if (*p == '~') - p += 5; + { + if (negative++ == 0) + (*count)++; + p += 5; + } else p += 4; if (p > end) @@ -610,19 +560,25 @@ otf_count_features (char *p, char *end, char stopper, int *count) } static void -otf_store_features (char *p, char *end, int count, unsigned *buf) +otf_store_features (char *p, char *end, unsigned *buf) { + int negative = 0; int i; for (i = 0; p < end;) { if (*p == '*') - buf[i++] = 0, p += 2; + buf[i++] = 0xFFFFFFFF, p += 2, negative = 1; else if (*p == '~') - buf[--count] = gen_otf_tag (p + 1), p += 6; + { + if (negative++ == 0) + buf[i++] = 0xFFFFFFFF; + buf[i++] = gen_otf_tag (p + 1), p += 6; + } else buf[i++] = gen_otf_tag (p), p += 5; } + buf[i] = 0; } static int @@ -631,81 +587,71 @@ parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec) char *str = MSYMBOL_NAME (symbol); char *end = str + MSYMBOL_NAMELEN (symbol); unsigned int script, langsys; - unsigned int *gsub, *gpos; + char *gsub, *gpos; int gsub_count = 0, gpos_count = 0; char *p; + memset (spec, 0, sizeof (MFLTOtfSpec)); + spec->sym = symbol; str += 5; /* skip the heading ":otf=" */ script = gen_otf_tag (str); - if (! script) - return 0; str += 4; if (*str == '/') { langsys = gen_otf_tag (str); - if (! langsys) - MERROR (MERROR_FLT, -1); str += 4; } else langsys = 0; + gsub = str; if (*str != '=') - { - /* Apply all GSUB features. */ + /* Apply all GSUB features. */ gsub_count = 1; - gsub = alloca (sizeof *gsub); - *gsub = 0; - } else { p = str + 1; str = otf_count_features (p, end, '+', &gsub_count); if (! str) MERROR (MERROR_FLT, -1); - if (gsub_count > 0) - { - gsub = alloca (sizeof (unsigned int) * gsub_count); - otf_store_features (p, str, gsub_count, gsub); - } } + gpos = str; if (*str != '+') - { - /* Apply all GPOS features. */ - gpos_count = 1; - gpos = alloca (sizeof *gpos); - *gpos = 0; - } + /* Apply all GPOS features. */ + gpos_count = 1; else { p = str + 1; str = otf_count_features (p, end, '\0', &gpos_count); if (! str) MERROR (MERROR_FLT, -1); - if (gpos_count > 0) - { - gpos = alloca (sizeof (unsigned int) * gpos_count); - otf_store_features (p, str, gpos_count, gpos); - } } spec->script = script; spec->langsys = langsys; - spec->gsub_gpos[0].count = gsub_count; if (gsub_count > 0) { - spec->gsub_gpos[0].tags = malloc (sizeof (int) * gsub_count); - if (! spec->gsub_gpos[0].tags) - MERROR (MERROR_FLT, -2); - memcpy (spec->gsub_gpos[0].tags, gsub, sizeof (int) * gsub_count); + spec->features[0] = malloc (sizeof (int) * (gsub_count + 1)); + if (! spec->features[0]) + return -2; + if (*gsub == '=') + otf_store_features (gsub + 1, gpos, spec->features[0]); + else + spec->features[0][0] = 0xFFFFFFFF, spec->features[0][1] = 0; } - spec->gsub_gpos[1].count = gpos_count; if (gpos_count > 0) { - spec->gsub_gpos[1].tags = malloc (sizeof (int) * gpos_count); - if (! spec->gsub_gpos[1].tags) - MERROR (MERROR_FLT, -2); - memcpy (spec->gsub_gpos[1].tags, gpos, sizeof (int) * gpos_count); + spec->features[1] = malloc (sizeof (int) * (gpos_count + 1)); + if (! spec->features[1]) + { + if (spec->features[0]) + free (spec->features[0]); + return -2; + } + if (*gpos == '+') + otf_store_features (gpos + 1, str, spec->features[1]); + else + spec->features[1][0] = 0xFFFFFFFF, spec->features[1][1] = 0; } return 0; } @@ -736,8 +682,6 @@ load_otf_command (FontLayoutCmd *cmd, MSymbol sym) result = parse_otf_command (sym, &cmd->body.otf); if (result == -2) return result; - if (result < 0) - cmd->body.otf.gsub_gpos[0].count = cmd->body.otf.gsub_gpos[1].count = 0; cmd->type = FontLayoutCmdTypeOTF; return 0; } @@ -1005,7 +949,7 @@ load_command (FontLayoutStage *stage, MPlist *plist, } else if (MPLIST_SYMBOL_P (pl) && size <= 2) { - if (MPLIST_SYMBOL (pl) != Mexist) + if (MPLIST_SYMBOL (pl) != Mfont_has) MERROR (MERROR_FLT, INVALID_CMD_ID); cmd->body.rule.src_type = SRC_EXIST; if (size == 1) @@ -1133,10 +1077,10 @@ free_flt_command (FontLayoutCmd *cmd) free (cmd->body.cond.cmd_ids); else if (cmd->type == FontLayoutCmdTypeOTF) { - if (cmd->body.otf.gsub_gpos[0].count > 0) - free (cmd->body.otf.gsub_gpos[0].tags); - if (cmd->body.otf.gsub_gpos[1].count > 0) - free (cmd->body.otf.gsub_gpos[1].tags); + if (cmd->body.otf.features[0]) + free (cmd->body.otf.features[0]); + if (cmd->body.otf.features[1]) + free (cmd->body.otf.features[1]); } } @@ -1186,42 +1130,68 @@ load_generator (MPlist *plist) /* Load stages of the font layout table FLT. */ static int -load_flt (MFLT *flt, int full) +load_flt (MFLT *flt, MPlist *key_list) { - static MSymbol Mcategory, Mgenerator, Mend; - MPlist *top, *plist; + MPlist *top, *plist, *pl, *p; MCharTable *category = NULL; + MSymbol sym; - if (! Mcategory) - { - Mcategory = msymbol ("category"); - Mgenerator = msymbol ("generator"); - Mend = msymbol ("end"); - } - - if (full) - { - top = (MPlist *) mdatabase_load (flt->mdb); - } + if (key_list) + top = (MPlist *) mdatabase__load_for_keys (flt->mdb, key_list); else + top = (MPlist *) mdatabase_load (flt->mdb); + if (! top) + return -1; + if (! MPLIST_PLIST_P (top)) { - plist = mplist (); - mplist_add (plist, Mcategory, Mt); - top = (MPlist *) mdatabase__load_for_keys (flt->mdb, plist); - M17N_OBJECT_UNREF (plist); - } - if (! top || ! MPLIST_PLIST_P (top)) - { - if (top) - M17N_OBJECT_UNREF (top); + M17N_OBJECT_UNREF (top); MERROR (MERROR_FLT, -1); } - MPLIST_DO (plist, top) + if (key_list) { - MSymbol sym; - MPlist *elt; + plist = mdatabase__props (flt->mdb); + if (! plist) + MERROR (MERROR_FLT, -1); + MPLIST_DO (plist, plist) + if (MPLIST_PLIST_P (plist)) + { + pl = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (pl) + || MPLIST_SYMBOL (pl) != Mfont) + continue; + pl = MPLIST_NEXT (pl); + if (! MPLIST_PLIST_P (pl)) + continue; + p = MPLIST_PLIST (pl); + if (! MPLIST_SYMBOL_P (p)) + continue; + p = MPLIST_NEXT (p); + if (! MPLIST_SYMBOL_P (p)) + continue; + flt->family = MPLIST_SYMBOL (p); + MPLIST_DO (p, MPLIST_NEXT (p)) + if (MPLIST_SYMBOL_P (p)) + { + sym = MPLIST_SYMBOL (p); + if (MSYMBOL_NAME (sym)[0] != ':') + flt->registry = sym, sym = Mnil; + else + break; + } + if (sym) + { + char *otf_spec = MSYMBOL_NAME (sym); + if (otf_spec[0] == ':' && otf_spec[1] == 'o' + && otf_spec[2] == 't' && otf_spec[3] == 'f') + parse_otf_command (sym, &flt->otf); + } + break; + } + } + MPLIST_DO (plist, top) + { if (MPLIST_SYMBOL_P (plist) && MPLIST_SYMBOL (plist) == Mend) { @@ -1229,19 +1199,24 @@ load_flt (MFLT *flt, int full) break; } if (! MPLIST_PLIST (plist)) - break; - elt = MPLIST_PLIST (plist); - if (! MPLIST_SYMBOL_P (elt)) - break; - sym = MPLIST_SYMBOL (elt); - elt = MPLIST_NEXT (elt); - if (! elt) - break; + continue; + pl = MPLIST_PLIST (plist); + if (! MPLIST_SYMBOL_P (pl)) + continue; + sym = MPLIST_SYMBOL (pl); + pl = MPLIST_NEXT (pl); + if (! pl) + continue; if (sym == Mcategory) { if (category) M17N_OBJECT_UNREF (category); - category = load_category_table (elt); + else if (flt->coverage) + { + category = flt->coverage; + continue; + } + category = load_category_table (pl); if (! flt->coverage) { flt->coverage = category; @@ -1254,7 +1229,7 @@ load_flt (MFLT *flt, int full) if (! category) break; - stage = load_generator (elt); + stage = load_generator (pl); if (! stage) break; stage->category = category; @@ -1288,6 +1263,91 @@ free_flt_stage (FontLayoutStage *stage) free (stage); } +static void +free_flt_list () +{ + if (flt_list) + { + MPlist *plist, *pl; + + MPLIST_DO (plist, flt_list) + { + MFLT *flt = MPLIST_VAL (plist); + + if (flt->coverage) + M17N_OBJECT_UNREF (flt->coverage); + if (flt->stages) + { + MPLIST_DO (pl, MPLIST_NEXT (flt->stages)) + free_flt_stage (MPLIST_VAL (pl)); + M17N_OBJECT_UNREF (flt->stages); + } + } + M17N_OBJECT_UNREF (flt_list); + } +} + +static int +list_flt () +{ + MPlist *plist, *key_list = NULL; + MPlist *pl; + int result = 0; + + if (! (plist = mdatabase_list (Mfont, Mlayouter, Mnil, Mnil))) + return -1; + if (! (flt_list = mplist ())) + goto err; + if (! (key_list = mplist ())) + goto err; + if (! mplist_add (key_list, Mcategory, Mt)) + goto err; + + MPLIST_DO (pl, plist) + { + MDatabase *mdb = MPLIST_VAL (pl); + MSymbol *tags = mdatabase_tag (mdb); + MFLT *flt; + + if (! MSTRUCT_CALLOC_SAFE (flt)) + goto err; + flt->name = tags[2]; + flt->mdb = mdb; + if (load_flt (flt, key_list) < 0) + free (flt); + else + { + if (MPLIST_TAIL_P (flt_list)) + { + flt_min_coverage = mchartable_min_char (flt->coverage); + flt_max_coverage = mchartable_max_char (flt->coverage); + } + else + { + int c; + + c = mchartable_min_char (flt->coverage); + if (flt_min_coverage > c) + flt_min_coverage = c; + c = mchartable_max_char (flt->coverage); + if (flt_max_coverage < c) + flt_max_coverage = c; + } + if (! mplist_push (flt_list, flt->name, flt)) + goto err; + } + } + goto end; + + err: + free_flt_list (); + result = -1; + end: + M17N_OBJECT_UNREF (plist); + M17N_OBJECT_UNREF (key_list); + return result; +} + /* FLS (Font Layout Service) */ /* Structure to hold information about a context of FLS. */ @@ -1307,11 +1367,7 @@ typedef struct table into this array. An element is a category letter used for a regular expression matching. */ char *encoded; - /* [GIDX - ] gives a category for the glyph - index GIDX. */ - int encoded_offset; int *match_indices; - int gstring_size; int code_offset; int cluster_begin_idx; int cluster_begin_pos; @@ -1375,19 +1431,18 @@ run_rule (int depth, if (from > to) return 0; - saved_code = ctx->encoded[to - ctx->encoded_offset]; - ctx->encoded[to - ctx->encoded_offset] = '\0'; + saved_code = ctx->encoded[to]; + ctx->encoded[to] = '\0'; result = regexec (&(rule->src.re.preg), - ctx->encoded + from - ctx->encoded_offset, - NMATCH, pmatch, 0); + ctx->encoded + from, NMATCH, pmatch, 0); if (result == 0 && pmatch[0].rm_so == 0) { if (MDEBUG_FLAG () > 2) MDEBUG_PRINT5 ("\n [FLT] %*s(REGEX \"%s\" \"%s\" %d", depth, "", rule->src.re.pattern, - ctx->encoded + from - ctx->encoded_offset, + ctx->encoded + from, pmatch[0].rm_eo); - ctx->encoded[to - ctx->encoded_offset] = saved_code; + ctx->encoded[to] = saved_code; for (i = 0; i < NMATCH; i++) { if (pmatch[i].rm_so < 0) @@ -1403,7 +1458,7 @@ run_rule (int depth, } else { - ctx->encoded[to - ctx->encoded_offset] = saved_code; + ctx->encoded[to] = saved_code; return 0; } } @@ -1511,67 +1566,80 @@ run_otf (int depth, { MFLTFont *font = ctx->font; int from_idx = ctx->out->used; - MFLTGlyphAdjustment *adjustment; - int out_len; - int i; if (MDEBUG_FLAG () > 2) MDEBUG_PRINT3 ("\n [FLT] %*s%s", depth, "", MSYMBOL_NAME (otf_spec->sym)); font->get_glyph_id (font, ctx->in, from, to); - adjustment = alloca ((sizeof *adjustment) - * (ctx->out->allocated - ctx->out->used)); - if (! adjustment) - MERROR (MERROR_FLT, -1); - memset (adjustment, 0, - (sizeof *adjustment) * (ctx->out->allocated - ctx->out->used)); - to = font->drive_otf (font, otf_spec, ctx->in, from, to, ctx->out, adjustment); - if (to < 0) - return to; - out_len = ctx->out->used - from_idx; - if (otf_spec->gsub_gpos[1].count > 0) + if (! font->drive_otf) { - MFLTGlyphAdjustment *a; + if (ctx->out->used + (to - from) > ctx->out->allocated) + return -2; + font->get_metrics (font, ctx->in, from, to); + GCPY (ctx->in, from, to - from, ctx->out, ctx->out->used); + ctx->out->used += to - from; + } + else + { + MFLTGlyphAdjustment *adjustment; + int out_len; + int i; - for (i = 0, a = adjustment; i < out_len; i++, a++) - if (a->set) - break; - if (i < out_len) + adjustment = alloca ((sizeof *adjustment) + * (ctx->out->allocated - ctx->out->used)); + if (! adjustment) + MERROR (MERROR_FLT, -1); + memset (adjustment, 0, + (sizeof *adjustment) * (ctx->out->allocated - ctx->out->used)); + to = font->drive_otf (font, otf_spec, ctx->in, from, to, ctx->out, + adjustment); + if (to < 0) + return to; + out_len = ctx->out->used - from_idx; + if (otf_spec->features[1]) { - font->get_metrics (font, ctx->out, from_idx, ctx->out->used); + MFLTGlyphAdjustment *a; + for (i = 0, a = adjustment; i < out_len; i++, a++) + if (a->set) + break; + if (i < out_len) { - MFLTGlyph *g = GREF (ctx->out, from_idx + i); - - SET_MEASURED (g, 1); - if (a->xadv || a->yadv) + font->get_metrics (font, ctx->out, from_idx, ctx->out->used); + for (i = 0, a = adjustment; i < out_len; i++, a++) { - if (a->advance_is_absolute) + MFLTGlyph *g = GREF (ctx->out, from_idx + i); + + SET_MEASURED (g, 1); + if (a->xadv || a->yadv) { - g->xadv = a->xadv; - g->yadv = a->yadv; + if (a->advance_is_absolute) + { + g->xadv = a->xadv; + g->yadv = a->yadv; + } + else + { + g->xadv += a->xadv; + g->yadv += a->yadv; + } } - else + if (a->xoff || a->yoff) { - g->xadv += a->xadv; - g->yadv += a->yadv; - } - } - if (a->xoff || a->yoff) - { - int j; - MFLTGlyph *gg = g; - MFLTGlyphAdjustment *aa = a; + int j; + MFLTGlyph *gg = g; + MFLTGlyphAdjustment *aa = a; - g->xoff = a->xoff; - g->yoff = a->yoff; - while (aa->back > 0) - { - for (j = 0, gg--; j < aa->back; j++, gg--) - g->xoff -= gg->xadv; - aa = aa - aa->back; - g->xoff += aa->xoff; - g->yoff += aa->yoff; + g->xoff = a->xoff; + g->yoff = a->yoff; + while (aa->back > 0) + { + for (j = 0, gg--; j < aa->back; j++, gg--) + g->xoff -= gg->xadv; + aa = aa - aa->back; + g->xoff += aa->xoff; + g->yoff += aa->yoff; + } } } } @@ -1807,13 +1875,6 @@ run_stages (MFLTGlyphString *gstring, int from, int to, ctx->stage = (FontLayoutStage *) MPLIST_VAL (stages); table = ctx->stage->category; ctx->code_offset = ctx->combining_code = ctx->left_padding = 0; - if (ctx->encoded_offset < from) - { - for (i = ctx->encoded_offset; i < from; i++) - ctx->encoded[i] - = (int) mchartable_lookup (table, GREF (ctx->in, i)->c); - ctx->encoded[i++] = ' '; - } for (i = from; i < to; i++) { MFLTGlyph *g = GREF (ctx->in, i); @@ -1823,14 +1884,14 @@ run_stages (MFLTGlyphString *gstring, int from, int to, ? (int) mchartable_lookup (table, g->code) : ' '); - ctx->encoded[i - ctx->encoded_offset] = enc; + ctx->encoded[i] = enc; if (! enc && stage_idx == 0) { to = i; break; } } - ctx->encoded[i - ctx->encoded_offset] = '\0'; + ctx->encoded[i] = '\0'; ctx->match_indices[0] = from; ctx->match_indices[1] = to; for (i = 2; i < NMATCH; i++) @@ -1839,7 +1900,7 @@ run_stages (MFLTGlyphString *gstring, int from, int to, if (MDEBUG_FLAG () > 2) { MDEBUG_PRINT2 ("\n [FLT] (STAGE %d \"%s\"", stage_idx, - ctx->encoded); + ctx->encoded + from); MDEBUG_PRINT (" ("); for (i = from; i < to; i++) { @@ -1874,7 +1935,6 @@ run_stages (MFLTGlyphString *gstring, int from, int to, } ctx->out->used = 0; - ctx->encoded_offset = 0; from = 0; to = ctx->in->used; } @@ -1882,7 +1942,7 @@ run_stages (MFLTGlyphString *gstring, int from, int to, if (ctx->out->used > 0) { int *g_indices; - int x_ppem = ctx->font->x_ppem << 6, y_ppem = ctx->font->y_ppem << 6; + int x_ppem = ctx->font->x_ppem, y_ppem = ctx->font->y_ppem; /* Remove separator glyphs. */ for (i = 0; i < ctx->out->used;) @@ -2030,25 +2090,63 @@ run_stages (MFLTGlyphString *gstring, int from, int to, return to; } -#define CHECK_FLT_COVERAGE(flt) ((flt)->coverage || load_flt (flt, 0) == 0) -#define CHECK_FLT_STAGES(flt) ((flt)->stages || load_flt (flt, 1) == 0) +static int +combining_code_from_class (int class) +{ + int code; + + if (class < 200) + code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128); + else if (class == 200) /* below left attached */ + code = MAKE_COMBINING_CODE (2, 0, 0, 1, 128, 128); + else if (class == 202) /* below attached*/ + code = MAKE_COMBINING_CODE (2, 1, 0, 1, 128, 128); + else if (class == 204) /* below right attached */ + code = MAKE_COMBINING_CODE (2, 2, 0, 1, 128, 128); + else if (class == 208) /* left attached */ + code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 128); + else if (class == 210) /* right attached */ + code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 128); + else if (class == 212) /* above left attached */ + code = MAKE_COMBINING_CODE (0, 0, 2, 1, 128, 128); + else if (class == 214) /* above attached */ + code = MAKE_COMBINING_CODE (0, 1, 2, 1, 128, 128); + else if (class == 216) /* above right attached */ + code = MAKE_COMBINING_CODE (0, 2, 2, 1, 128, 128); + else if (class == 218) /* below left */ + code = MAKE_COMBINING_CODE (2, 0, 0, 1, 122, 128); + else if (class == 220) /* below */ + code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128); + else if (class == 222) /* below right */ + code = MAKE_COMBINING_CODE (2, 2, 0, 1, 122, 128); + else if (class == 224) /* left */ + code = MAKE_COMBINING_CODE (3, 0, 3, 2, 128, 122); + else if (class == 226) /* right */ + code = MAKE_COMBINING_CODE (3, 2, 3, 0, 128, 133); + else if (class == 228) /* above left */ + code = MAKE_COMBINING_CODE (0, 0, 2, 1, 133, 128); + else if (class == 230) /* above */ + code = MAKE_COMBINING_CODE (0, 1, 2, 1, 133, 128); + else if (class == 232) /* above right */ + code = MAKE_COMBINING_CODE (0, 2, 2, 1, 133, 128); + else if (class == 233) /* double below */ + code = MAKE_COMBINING_CODE (2, 2, 0, 2, 122, 128); + else if (class == 234) /* double above */ + code = MAKE_COMBINING_CODE (0, 2, 2, 2, 133, 128); + else if (class == 240) /* iota subscript */ + code = MAKE_COMBINING_CODE (2, 1, 0, 1, 122, 128); + else /* unknown */ + code = MAKE_COMBINING_CODE (3, 1, 3, 1, 128, 128); + return code; +} + +#define CHECK_FLT_STAGES(flt) ((flt)->stages || load_flt (flt, NULL) == 0) /* Internal API */ int m17n__flt_initialized; -unsigned -mfont__flt_encode_char (MFLT *flt, int c) -{ - unsigned code; - - if (! CHECK_FLT_STAGES (flt)) - return MCHAR_INVALID_CODE; - code = (unsigned) mchartable_lookup (flt->coverage, c); - return (code ? code : MCHAR_INVALID_CODE); -} - /* External API */ @@ -2071,15 +2169,15 @@ m17n_init_flt (void) } MDEBUG_PUSH_TIME (); - MDEBUG_PUSH_TIME (); Mcond = msymbol ("cond"); Mrange = msymbol ("range"); Mfont = msymbol ("font"); Mlayouter = msymbol ("layouter"); - Mexist = msymbol ("exist"); + Mfont_has = msymbol ("font-has"); + Mgenerator = msymbol ("generator"); + Mend = msymbol ("end"); - MDEBUG_POP_TIME (); MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize the flt modules.")); MDEBUG_POP_TIME (); } @@ -2088,35 +2186,13 @@ void m17n_fini_flt (void) { int mdebug_flag = MDEBUG_FINI; - MPlist *plist, *pl; if (m17n__flt_initialized == 0 || --m17n__flt_initialized > 0) return; MDEBUG_PUSH_TIME (); - MDEBUG_PUSH_TIME (); - MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize database module.")); - - if (flt_list) - { - MPLIST_DO (plist, flt_list) - { - MFLT *flt = MPLIST_VAL (plist); - - if (flt->coverage) - M17N_OBJECT_UNREF (flt->coverage); - if (flt->stages) - { - MPLIST_DO (pl, MPLIST_NEXT (flt->stages)) - free_flt_stage (MPLIST_VAL (pl)); - M17N_OBJECT_UNREF (flt->stages); - } - } - M17N_OBJECT_UNREF (flt_list); - } - - MDEBUG_POP_TIME (); + free_flt_list (); MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize the flt modules.")); MDEBUG_POP_TIME (); m17n_fini_core (); @@ -2125,106 +2201,170 @@ m17n_fini_flt (void) /*** @} */ #endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */ +/*** @addtogroup m17nFLT */ +/*** @{ */ +/*=*/ + +/*=*/ +/***en + @brief Return a FLT object whose name is NAME. + + The mflt_get () function returns a FLT object whose name is $NAME. + + @return + If the operation was successfully, mflt_get () returns a pointer + to a FLT object. Otherwise, it returns @c NULL. */ + MFLT * -mflt_get (char *name) +mflt_get (MSymbol name) { - MSymbol sym = msymbol (name); MFLT *flt; - if (! flt_list - && list_flt () < 0) + if (! flt_list && list_flt () < 0) return NULL; - flt = mplist_get (flt_list, sym); + flt = mplist_get (flt_list, name); if (flt && ! CHECK_FLT_STAGES (flt)) return NULL; return flt; } +/*=*/ +/***en + @brief Find a FLT suitable for a specified character and font. + + The mflt_find () function returns the most appropriate FLT for + rendering the character $C by font $FONT. + + @return + If the operation was successfully, mflt_find () returns a pointer + to a FLT object. Otherwise, it returns @c NULL. */ + MFLT * mflt_find (int c, MFLTFont *font) { MPlist *plist; MFLT *flt; + static MSymbol unicode_bmp = NULL, unicode_full = NULL; + + if (! unicode_bmp) + { + unicode_bmp = msymbol ("unicode-bmp"); + unicode_full = msymbol ("unicode-full"); + } if (! flt_list && list_flt () < 0) return NULL; if (font) { + MFLT *best = NULL; + MPLIST_DO (plist, flt_list) { flt = MPLIST_VAL (plist); - if (flt->family && flt->family != font->family) + if (flt->registry != unicode_bmp + && flt->registry != unicode_full) continue; - if (flt->otf.sym - && (! font->check_otf (font, &flt->otf))) + if (flt->family && flt->family != font->family) continue; if (c >= 0 - && (! CHECK_FLT_COVERAGE (flt) - || ! mchartable_lookup (flt->coverage, c))) + && ! mchartable_lookup (flt->coverage, c)) continue; - return flt; + if (flt->otf.sym) + { + MFLTOtfSpec *spec = &flt->otf; + + if (! font->check_otf) + { + if ((spec->features[0] && spec->features[0][0] != 0xFFFFFFFF) + || (spec->features[1] && spec->features[1][0] != 0xFFFFFFFF)) + continue; + } + else if (! font->check_otf (font, &flt->otf)) + continue; + return flt; + } + best = flt; } - return NULL; + return best; } if (c >= 0) { MPLIST_DO (plist, flt_list) { flt = MPLIST_VAL (plist); - if (CHECK_FLT_COVERAGE (flt) - && mchartable_lookup (flt->coverage, c)) + if (mchartable_lookup (flt->coverage, c)) return flt; } } return NULL; } -char * +/*=*/ +/***en + @brief Return a name of a FLT. + + The mflt_name () function returns the name of $FLT. */ + +const char * mflt_name (MFLT *flt) { return MSYMBOL_NAME (flt->name); } +/*=*/ +/***en + @brief Return a coverage of a FLT. + + The mflt_coverage () function returns a char-table that contains + nonzero value for characters supported by $FLT. */ + MCharTable * mflt_coverage (MFLT *flt) { - if (! CHECK_FLT_COVERAGE (flt)) - MERROR (MERROR_FLT, NULL); return flt->coverage; } +/*=*/ +/***en + @brief Layout characters by Font Layout Table. + + The mflt_run () function layout characters in $GSTRING between + $FROM (inclusive) and $TO (exclusive) by $FONT. If $FLT is + nonzero, it is used for all the charaters. Otherwise, appropriate + FLTs are automatically chosen. + + @retval >=0 + The operation was successful. The value is an index to the + $GSTRING->glyphs which was previously indexed by $TO. + + @retval -2 + $GSTRING->glyphs is too short to store the result. A caller can + call this fucntion again with the larger $GSTRING->glyphs. + + @retval -1 + Some other error occurred. */ + int mflt_run (MFLTGlyphString *gstring, int from, int to, MFLTFont *font, MFLT *flt) { - int i, j; FontLayoutContext ctx; int match_indices[NMATCH]; MFLTGlyph *g; MFLTGlyphString out; + int auto_flt = ! flt; + int c, i, j, k; + int this_from, this_to; - if (! CHECK_FLT_STAGES (flt)) - { - GREPLACE (NULL, 0, 0, gstring, from, to); - return from; - } + out = *gstring; + out.glyphs = NULL; + /* This is usually sufficient, but if not, we retry with the larger + values at most 3 times. This value is also used for the + allocating size of ctx.encoded. */ + out.allocated = (to - from) * 4; - MDEBUG_PRINT1 (" [FLT] (%s", MSYMBOL_NAME (flt->name)); - - /* Setup CTX. */ - memset (&ctx, 0, sizeof ctx); - ctx.cluster_begin_idx = -1; - /* Find previous glyphs that are also supported by the layouter. */ - for (i = from; - i > 0 && (g = GREF (gstring, i - 1)) - && g->c && mchartable_lookup (flt->coverage, g->c); - i--) - g->code = g->c; - ctx.encoded_offset = i; for (i = from; i < to; i++) { - int c; - g = GREF (gstring, i); c = g->c; memset (g, 0, sizeof (MFLTGlyph)); @@ -2232,73 +2372,136 @@ mflt_run (MFLTGlyphString *gstring, int from, int to, g->from = g->to = i; } - ctx.match_indices = match_indices; + for (this_from = from; this_from < to;) + { + if (! auto_flt) + { + for (this_to = this_from; this_to < to; i++) + if (mchartable_lookup (flt->coverage, GREF (gstring, this_to)->c)) + break; + } + else + { + if (! flt_list && list_flt () < 0) + { + font->get_glyph_id (font, gstring, this_from, to); + font->get_metrics (font, gstring, this_from, to); + this_from = to; + break; + } + for (this_to = this_from; this_to < to; this_to++) + { + c = GREF (gstring, this_to)->c; + if (c >= flt_min_coverage && c <= flt_max_coverage) + break; + } + for (; this_to < to; this_to++) + { + c = GREF (gstring, this_to)->c; + if (font->internal + && mchartable_lookup (((MFLT *) font->internal)->coverage, c)) + { + flt = font->internal; + break; + } + flt = mflt_find (c, font); + if (flt) + { + if (CHECK_FLT_STAGES (flt)) + { + font->internal = flt; + break; + } + } + } + } + + if (this_from < this_to) + { + font->get_glyph_id (font, gstring, this_from, this_to); + font->get_metrics (font, gstring, this_from, this_to); + this_from = this_to; + } + if (this_to == to) + break; - ctx.font = font; - ctx.in = gstring; - out = *gstring; - out.glyphs = NULL; - /* This is usually sufficient, but if not, we retry with the larger - values at most 3 times. This value is also used for the - allocating size of ctx.encoded. */ - out.allocated = (to - ctx.encoded_offset + 2) * 4; - ctx.out = &out; + MDEBUG_PRINT1 (" [FLT] (%s", MSYMBOL_NAME (flt->name)); - if (MDEBUG_FLAG ()) - { - MDEBUG_PRINT ("\n [FLT] (SOURCE"); - for (i = from, j = 0; i < to; i++, j++) + for (; this_to < to; this_to++) + if (! mchartable_lookup (flt->coverage, GREF (gstring, this_to)->c)) + break; + + if (MDEBUG_FLAG ()) { - if (j > 0 && j % 8 == 0) - MDEBUG_PRINT ("\n [FLT] "); - MDEBUG_PRINT1 (" %04X", GREF (gstring, i)->c); + MDEBUG_PRINT ("\n [FLT] (SOURCE"); + for (i = this_from, j = 0; i < this_to; i++, j++) + { + if (j > 0 && j % 8 == 0) + MDEBUG_PRINT ("\n [FLT] "); + MDEBUG_PRINT1 (" %04X", GREF (gstring, i)->c); + } + MDEBUG_PRINT (")"); } - MDEBUG_PRINT (")"); - } - for (i = 0; (i < 3 && - (to = run_stages (gstring, from, to, flt, &ctx)) == -2); - i++) - { - ctx.out = &out; - ctx.out->allocated *= 2; - } + for (i = 0; i < 3; i++) + { + /* Setup CTX. */ + memset (&ctx, 0, sizeof ctx); + ctx.match_indices = match_indices; + ctx.font = font; + ctx.cluster_begin_idx = -1; + ctx.in = gstring; + ctx.out = &out; + j = run_stages (gstring, this_from, this_to, flt, &ctx); + if (j != -2) + break; + out.allocated *= 2; + } -#if 0 - for (i = from; i < to; i++) - { - MFLTGlyph *g = GREF (gstring, i); - - g->ascent >>= 6; - g->descent >>= 6; - g->lbearing >>= 6; - g->rbearing >>= 6; - g->xadv >>= 6; - g->yadv >>= 6; - g->xoff >>= 6; - g->yoff >>= 6; + if (j < 0) + return j; + + to += j - this_to; + this_to = j; + + if (MDEBUG_FLAG ()) + { + MDEBUG_PRINT ("\n [FLT] (RESULT"); + if (MDEBUG_FLAG () > 1) + for (i = 0; this_from < this_to; this_from++, i++) + { + if (i > 0 && i % 4 == 0) + MDEBUG_PRINT ("\n [FLT] "); + g = GREF (gstring, this_from); + MDEBUG_PRINT4 (" (%04X %d %d %d)", + g->code, g->xadv, g->xoff, g->yoff); + } + else + for (; this_from < this_to; this_from++) + MDEBUG_PRINT1 (" %04X", GREF (gstring, this_from)->code); + MDEBUG_PRINT ("))\n"); + } + this_from = this_to; } -#endif - if (MDEBUG_FLAG ()) + if (gstring->r2l) { - MDEBUG_PRINT ("\n [FLT] (RESULT"); - if (MDEBUG_FLAG () > 1) - for (i = 0; from < to; from++, i++) - { - if (i > 0 && i % 4 == 0) - MDEBUG_PRINT ("\n [FLT] "); - g = GREF (gstring, from); - MDEBUG_PRINT4 (" (%04X %d %d %d)", - g->code, g->xadv, g->xoff, g->yoff); - } - else - for (; from < to; from++) - MDEBUG_PRINT1 (" %04X", GREF (gstring, from)->code); - MDEBUG_PRINT ("))\n"); + int len = to - from; + + GINIT (&out, len); + memcpy (((char *) out.glyphs), + ((char *) gstring->glyphs) + gstring->glyph_size * from, + gstring->glyph_size * len); + for (i = from, j = to; i < to;) + { + for (k = i + 1, j--; k < to && GREF (&out, k)->xadv == 0; + k++, j--); + GCPY (&out, i, (k - i), gstring, j); + i = k; + } } - return (to < 0 ? -1 : to); + return to; } @@ -2395,3 +2598,11 @@ mdebug_dump_flt (MFLT *flt, int indent) } fprintf (stderr, ")"); } + +/*** @} */ + +/* + Local Variables: + coding: euc-japan + End: +*/ -- 1.7.10.4