From 584ea8413de181015aca64d1bd729ab99410c16c Mon Sep 17 00:00:00 2001 From: handa Date: Mon, 5 Oct 2009 10:56:48 +0000 Subject: [PATCH] (FontLayoutCategory): New typedef. (FontLayoutStage): Type of the member `category' changed. (struct _MFLT): Type of the member `coverage' changed. New member need_config and font_id. (apply_otf_feature): New function. (load_category_table): New arg FONT. If FONT is non-NULL, call apply_otf_feature. Setup category->definition. (ref_category_table): New macro. (unref_category_table): New function. (load_flt): Adjusted for the type change of category. (free_flt_stage): New arg FLT. (list_flt): Adjusted for the type change of category. (run_stages): Adjusted for the type change of category. (configure_category, configure_flt): New function. (m17n_init_flt): Initialize mflt_iterate_otf_feature and mflt_font_id to NULL. (mflt_get): Skip the heading configured FLTs. (mflt_find): Likewise. If necessary, configure the found flt. (mflt_run): Handle mflt_iterate_otf_feature and mflt_font_id. Adjusted for the type change of category. (mflt_iterate_otf_feature, mflt_font_id): New variable. --- src/m17n-flt.c | 272 +++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 219 insertions(+), 53 deletions(-) diff --git a/src/m17n-flt.c b/src/m17n-flt.c index 4aba740..0ca5d80 100644 --- a/src/m17n-flt.c +++ b/src/m17n-flt.c @@ -448,9 +448,17 @@ typedef struct } body; } FontLayoutCmd; +typedef struct +{ + MCharTable *table; + /* Non-null if the table must be re-configured by OTF specs included + in the definition. */ + MPlist *definition; +} FontLayoutCategory; + typedef struct { - MCharTable *category; + FontLayoutCategory *category; int size, inc, used; FontLayoutCmd *cmds; } FontLayoutStage; @@ -462,39 +470,62 @@ struct _MFLT MSymbol registry; MFLTOtfSpec otf; MDatabase *mdb; - MCharTable *coverage; + FontLayoutCategory *coverage; MPlist *stages; + int need_config; + /* Font for which coverage or some of categories are configured. */ + MSymbol font_id; }; /* Font layout table loader */ static int parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec); +static void +apply_otf_feature (MFLTFont *font, MFLTOtfSpec *spec, + int from, int to, MCharTable *table, int category) +{ + unsigned char *buf; + int i; + + if (! mflt_iterate_otf_feature) + return; + buf = alloca (to + 1 - from); + memset (buf, 0, to + 1 - from); + if (mflt_iterate_otf_feature (font, spec, from, to, buf) < 0) + return; + for (i = to - from; i >= 0; i--) + if (buf[i]) + mchartable_set (table, from + i, (void *) category); +} + /* Load a category table from PLIST. PLIST has this form: PLIST ::= ( FROM-CODE TO-CODE ? CATEGORY-CHAR ) * */ -static MCharTable * -load_category_table (MPlist *plist) +static FontLayoutCategory * +load_category_table (MPlist *plist, MFLTFont *font) { + FontLayoutCategory *category; MCharTable *table; + MPlist *p; + int need_otf = 0; table = mchartable (Minteger, (void *) 0); - - MPLIST_DO (plist, plist) + MPLIST_DO (p, plist) { MPlist *elt; int from, to, category_code; - if (! MPLIST_PLIST (plist)) - MERROR (MERROR_FONT, NULL); - elt = MPLIST_PLIST (plist); + if (! MPLIST_PLIST (p)) + MERROR_GOTO (MERROR_FONT, end); + elt = MPLIST_PLIST (p); if (! MPLIST_INTEGER_P (elt)) - MERROR (MERROR_FONT, NULL); + MERROR_GOTO (MERROR_FONT, end); from = MPLIST_INTEGER (elt); elt = MPLIST_NEXT (elt); if (! MPLIST_INTEGER_P (elt)) - MERROR (MERROR_FONT, NULL); + MERROR_GOTO (MERROR_FONT, end); to = MPLIST_INTEGER (elt); elt = MPLIST_NEXT (elt); if (MPLIST_TAIL_P (elt)) @@ -502,14 +533,33 @@ load_category_table (MPlist *plist) category_code = to; to = from; } + else if (MPLIST_SYMBOL_P (elt)) + { + if (font) + { + MFLTOtfSpec spec; + if (parse_otf_command (MPLIST_SYMBOL (elt), &spec) < 0) + MERROR_GOTO (MERROR_FONT, end); + elt = MPLIST_NEXT (elt); + if (! MPLIST_INTEGER_P (elt)) + MERROR_GOTO (MERROR_FONT, end); + category_code = MPLIST_INTEGER (elt); + if (! isalnum (category_code)) + MERROR_GOTO (MERROR_FONT, end); + apply_otf_feature (font, &spec, from, to, table, category_code); + } + else + need_otf = 1; + continue; + } else { if (! MPLIST_INTEGER_P (elt)) - MERROR (MERROR_FONT, NULL); + MERROR_GOTO (MERROR_FONT, end); category_code = MPLIST_INTEGER (elt); } if (! isalnum (category_code)) - MERROR (MERROR_FONT, NULL); + MERROR_GOTO (MERROR_FONT, end); if (from == to) mchartable_set (table, from, (void *) category_code); @@ -517,7 +567,31 @@ load_category_table (MPlist *plist) mchartable_set_range (table, from, to, (void *) category_code); } - return table; + end: + category = malloc (sizeof (FontLayoutCategory)); + category->table = table; + if (need_otf) + { + category->definition = plist; + M17N_OBJECT_REF (plist); + } + else + category->definition = NULL; + return category; +} + +#define ref_category_table(CATEGORY) M17N_OBJECT_REF ((CATEGORY)->table) + +static void +unref_category_table (FontLayoutCategory *category) +{ + M17N_OBJECT_UNREF (category->table); + if (! category->table) + { + if (category->definition) + M17N_OBJECT_UNREF (category->definition); + free (category); + } } static unsigned int @@ -1169,7 +1243,7 @@ static int load_flt (MFLT *flt, MPlist *key_list) { MPlist *top, *plist, *pl, *p; - MCharTable *category = NULL; + FontLayoutCategory *category = NULL; MSymbol sym; if (key_list) @@ -1246,20 +1320,21 @@ load_flt (MFLT *flt, MPlist *key_list) if (sym == Mcategory) { if (category) - M17N_OBJECT_UNREF (category); + unref_category_table (category); else if (flt->coverage) { category = flt->coverage; + ref_category_table (category); continue; } - category = load_category_table (pl); - if (! category) - category = mchartable (Minteger, (void *) 0); + category = load_category_table (pl, NULL); if (! flt->coverage) { flt->coverage = category; - M17N_OBJECT_REF (category); + ref_category_table (category); } + if (category->definition) + flt->need_config = 1; } else if (sym == Mgenerator) { @@ -1271,14 +1346,15 @@ load_flt (MFLT *flt, MPlist *key_list) if (! stage) break; stage->category = category; - M17N_OBJECT_REF (category); + M17N_OBJECT_REF (category->table); if (! flt->stages) flt->stages = mplist (); mplist_add (flt->stages, Mt, stage); } } if (category) - M17N_OBJECT_UNREF (category); + unref_category_table (category); + if (! MPLIST_TAIL_P (plist)) { M17N_OBJECT_UNREF (top); @@ -1291,14 +1367,17 @@ load_flt (MFLT *flt, MPlist *key_list) static void -free_flt_stage (FontLayoutStage *stage) +free_flt_stage (MFLT *flt, FontLayoutStage *stage) { int i; - M17N_OBJECT_UNREF (stage->category); - for (i = 0; i < stage->used; i++) - free_flt_command (stage->cmds + i); - MLIST_FREE1 (stage, cmds); + unref_category_table (stage->category); + if (! flt->font_id) + { + for (i = 0; i < stage->used; i++) + free_flt_command (stage->cmds + i); + MLIST_FREE1 (stage, cmds); + } free (stage); } @@ -1314,13 +1393,15 @@ free_flt_list () MFLT *flt = MPLIST_VAL (plist); if (flt->coverage) - M17N_OBJECT_UNREF (flt->coverage); + unref_category_table (flt->coverage); if (flt->stages) { MPLIST_DO (pl, MPLIST_NEXT (flt->stages)) - free_flt_stage (MPLIST_VAL (pl)); + free_flt_stage (flt, MPLIST_VAL (pl)); M17N_OBJECT_UNREF (flt->stages); } + free (flt); + MPLIST_VAL (plist) = NULL; } M17N_OBJECT_UNREF (flt_list); } @@ -1358,17 +1439,17 @@ list_flt () { if (MPLIST_TAIL_P (flt_list)) { - flt_min_coverage = mchartable_min_char (flt->coverage); - flt_max_coverage = mchartable_max_char (flt->coverage); + flt_min_coverage = mchartable_min_char (flt->coverage->table); + flt_max_coverage = mchartable_max_char (flt->coverage->table); } else { int c; - c = mchartable_min_char (flt->coverage); + c = mchartable_min_char (flt->coverage->table); if (flt_min_coverage > c) flt_min_coverage = c; - c = mchartable_max_char (flt->coverage); + c = mchartable_max_char (flt->coverage->table); if (flt_max_coverage < c) flt_max_coverage = c; } @@ -2011,7 +2092,7 @@ run_stages (MFLTGlyphString *gstring, int from, int to, int result; ctx->stage = (FontLayoutStage *) MPLIST_VAL (stages); - table = ctx->stage->category; + table = ctx->stage->category->table; ctx->code_offset = ctx->combining_code = ctx->left_padding = 0; ctx->encoded_offset = from; for (i = from; i < to; i++) @@ -2270,14 +2351,67 @@ setup_combining_flt (MFLT *flt) MCharTable *combininig_class_table = mchar_get_prop_table (Mcombining_class, &type); - mchartable_set_range (flt->coverage, 0, 0x10FFFF, (void *) 'u'); + mchartable_set_range (flt->coverage->table, 0, 0x10FFFF, (void *) 'u'); if (combininig_class_table) mchartable_map (combininig_class_table, (void *) 0, - setup_combining_coverage, flt->coverage); + setup_combining_coverage, flt->coverage->table); } #define CHECK_FLT_STAGES(flt) ((flt)->stages || load_flt (flt, NULL) == 0) +static FontLayoutCategory * +configure_category (FontLayoutCategory *category, MFLTFont *font) +{ + if (! mflt_font_id || ! mflt_iterate_otf_feature) + { + FontLayoutCategory *new = malloc (sizeof (FontLayoutCategory)); + new->definition = NULL; + new->table = category->table; + M17N_OBJECT_REF (new->table); + return new; + } + return load_category_table (category->definition, font); +} + +static MFLT * +configure_flt (MFLT *flt, MFLTFont *font, MSymbol font_id) +{ + MPlist *plist; + MFLT *configured; + + if (! mflt_font_id || ! mflt_iterate_otf_feature) + return flt; + MPLIST_DO (plist, flt_list) + { + configured = MPLIST_VAL (plist); + if (! configured->font_id) + break; + if (configured->name == flt->name + && configured->font_id == font_id) + return configured; + } + if (! MSTRUCT_CALLOC_SAFE (configured)) + return flt; + *configured = *flt; + configured->stages = mplist_copy (flt->stages); + MPLIST_DO (plist, configured->stages) + { + FontLayoutStage *stage = MPLIST_VAL (plist); + if (stage->category->definition) + { + MSTRUCT_CALLOC (stage, MERROR_FLT); + *stage = *((FontLayoutStage *) MPLIST_VAL (plist)); + stage->category = configure_category (stage->category, font); + MPLIST_VAL (plist) = stage; + } + else + M17N_OBJECT_REF (stage->category->table); + } + configured->need_config = 0; + configured->font_id = font_id; + mplist_push (flt_list, flt->name, configured); + return configured; +} /* Internal API */ @@ -2316,6 +2450,9 @@ m17n_init_flt (void) Mgenerator = msymbol ("generator"); Mend = msymbol ("end"); + mflt_iterate_otf_feature = NULL; + mflt_font_id = NULL; + MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize the flt modules.")); MDEBUG_POP_TIME (); } @@ -2366,14 +2503,18 @@ MFLT * mflt_get (MSymbol name) { MFLT *flt; + MPlist *plist; if (! flt_list && list_flt () < 0) return NULL; - flt = mplist_get (flt_list, name); + for (plist = flt_list; plist; plist = plist->next) + if (((MFLT *) MPLIST_VAL (plist))->font_id == Mnil) + break; + flt = mplist_get (plist, name); if (! flt || ! CHECK_FLT_STAGES (flt)) return NULL; if (flt->name == Mcombining - && ! mchartable_lookup (flt->coverage, 0)) + && ! mchartable_lookup (flt->coverage->table, 0)) setup_combining_flt (flt); return flt; @@ -2403,7 +2544,7 @@ mflt_get (MSymbol name) MFLT * mflt_find (int c, MFLTFont *font) { - MPlist *plist; + MPlist *plist, *pl; MFLT *flt; static MSymbol unicode_bmp = NULL, unicode_full = NULL; @@ -2415,23 +2556,27 @@ mflt_find (int c, MFLTFont *font) if (! flt_list && list_flt () < 0) return NULL; + /* Skip configured FLTs. */ + MPLIST_DO (plist, flt_list) + if (((MFLT *) MPLIST_VAL (plist))->font_id == Mnil) + break; if (font) { MFLT *best = NULL; - MPLIST_DO (plist, flt_list) + MPLIST_DO (pl, plist) { - flt = MPLIST_VAL (plist); + flt = MPLIST_VAL (pl); if (flt->registry != unicode_bmp && flt->registry != unicode_full) continue; if (flt->family && flt->family != font->family) continue; if (flt->name == Mcombining - && ! mchartable_lookup (flt->coverage, 0)) + && ! mchartable_lookup (flt->coverage->table, 0)) setup_combining_flt (flt); if (c >= 0 - && ! mchartable_lookup (flt->coverage, c)) + && ! mchartable_lookup (flt->coverage->table, c)) continue; if (flt->otf.sym) { @@ -2445,22 +2590,30 @@ mflt_find (int c, MFLTFont *font) } else if (! font->check_otf (font, spec)) continue; - return flt; + goto found; } best = flt; } - return best; + flt = best; + goto found; } if (c >= 0) { - MPLIST_DO (plist, flt_list) + MPLIST_DO (pl, plist) { - flt = MPLIST_VAL (plist); - if (mchartable_lookup (flt->coverage, c)) - return flt; + flt = MPLIST_VAL (pl); + if (mchartable_lookup (flt->coverage->table, c)) + goto found; } } return NULL; + + found: + if (! CHECK_FLT_STAGES (flt)) + return NULL; + if (font && flt->need_config) + flt = configure_flt (flt, font, mflt_font_id (font)); + return flt; } /*=*/ @@ -2496,7 +2649,7 @@ mflt_name (MFLT *flt) MCharTable * mflt_coverage (MFLT *flt) { - return flt->coverage; + return flt->coverage->table; } /*=*/ @@ -2550,6 +2703,7 @@ mflt_run (MFLTGlyphString *gstring, int from, int to, int auto_flt = ! flt; int c, i, j, k; int this_from, this_to; + MSymbol font_id = mflt_font_id ? mflt_font_id (font) : Mnil; out = *gstring; out.glyphs = NULL; @@ -2575,7 +2729,8 @@ mflt_run (MFLTGlyphString *gstring, int from, int to, if (! auto_flt) { for (this_to = this_from; this_to < to; this_to++) - if (mchartable_lookup (flt->coverage, GREF (gstring, this_to)->c)) + if (mchartable_lookup (flt->coverage->table, + GREF (gstring, this_to)->c)) break; } else @@ -2597,7 +2752,7 @@ mflt_run (MFLTGlyphString *gstring, int from, int to, { c = GREF (gstring, this_to)->c; if (font->internal - && mchartable_lookup (((MFLT *) font->internal)->coverage, c)) + && mchartable_lookup (((MFLT *) font->internal)->coverage->table, c)) { flt = font->internal; break; @@ -2625,8 +2780,12 @@ mflt_run (MFLTGlyphString *gstring, int from, int to, MDEBUG_PRINT1 (" [FLT] (%s", MSYMBOL_NAME (flt->name)); + if (flt->need_config) + flt = configure_flt (flt, font, font_id); + for (; this_to < to; this_to++) - if (! mchartable_lookup (flt->coverage, GREF (gstring, this_to)->c)) + if (! mchartable_lookup (flt->coverage->table, + GREF (gstring, this_to)->c)) break; if (MDEBUG_FLAG ()) @@ -2704,6 +2863,13 @@ mflt_run (MFLTGlyphString *gstring, int from, int to, return to; } +int (*mflt_iterate_otf_feature) (struct _MFLTFont *font, + MFLTOtfSpec *spec, + int from, int to, + unsigned char *table); + +MSymbol (*mflt_font_id) (struct _MFLTFont *font); + /* for debugging... */ -- 1.7.10.4