/* m17n-flt.c -- Font Layout Table sub-module.
- Copyright (C) 2003, 2004, 2007, 2008, 2009
+ Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H15PRO112
{
CategoryCodeMask = 0x7F,
CombiningCodeMask = 0xFFFFFF,
- CombinedMask = 1 << 27,
- LeftPaddingMask = 1 << 28,
- RightPaddingMask = 1 << 29
+ CombinedMask = 1 << 28,
+ LeftPaddingMask = 1 << 29,
+ RightPaddingMask = 1 << 30
};
#define SET_GLYPH_INFO(g, mask, ctx, info) \
elt = MPLIST_PLIST (p);
if (MPLIST_SYMBOL_P (elt))
{
- MPlist *next = MPLIST_NEXT (elt);
+ MPlist *next;
+
+ if (! mflt_enable_new_feature)
+ {
+ M17N_OBJECT_UNREF (table);
+ return NULL;
+ }
+ next = MPLIST_NEXT (elt);
if (! MPLIST_INTEGER_P (next))
MERROR_GOTO (MERROR_FLT, end);
if (! feature_table_head)
}
else if (MPLIST_SYMBOL_P (elt))
{
+ if (! mflt_enable_new_feature)
+ {
+ M17N_OBJECT_UNREF (table);
+ return NULL;
+ }
if (font)
{
MFLTOtfSpec spec;
buf[i] = 0;
}
+/* SYMBOL's name features[0] for checking for applying
+ features[1] GSUB GPOS GSUB GPOS
+ ------------- ------------------ ------------- ------------
+ SCRIPT [-1,0] [-1,0] any | any all all
+ SCRIPT= NULL [-1,0] none & 1 none all
+ SCRIPT+ [-1,0] NULL 1 & none all none
+ SCRIPT=+ NULL NULL none & none none none
+ SCRIPT=F1 [F1,0] [-1,0] F1 & 1 F1 all
+ SCRIPT+F1 [-1][0] [F1,0] 1 & F1 none F1
+ SCRIPT=F1+ [F1,0] NULL F1 & none F1 none
+ SCRIPT=~F2 [-1,F2,0] [-1,0] ~F2 & 1 all~F2 all
+ SCRIPT=F1,~F2 [F1,-1,F2,0][-1,0] F1&~F2 & 1 F1 (*1) all
+
+ (*1) Invalid specification
+ */
+
static int
parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec)
{
char *str = MSYMBOL_NAME (symbol);
char *end = str + MSYMBOL_NAMELEN (symbol);
unsigned int script, langsys;
- char *gsub, *gpos;
- int gsub_count = 0, gpos_count = 0;
+ char *features[3];
+ int feature_count[2]; /* [0]:GSUB, [1]:GPOS */
+ int i;
char *p;
memset (spec, 0, sizeof (MFLTOtfSpec));
spec->sym = symbol;
- str += 5; /* skip the heading ":otf=" */
- script = gen_otf_tag (str, 8);
+ str += 5; /* skip the heading ":otf=" or ":otf?" */
+ if (str[-1] == '?')
+ {
+ if (! mflt_enable_new_feature)
+ /* The client can't use this command. */
+ return -1;
+ if (! *str)
+ /* This is a spec to reset category codes. */
+ return 0;
+ }
+ spec->script = gen_otf_tag (str, 8);
str += 4;
if (*str == '/')
{
- langsys = gen_otf_tag (str, 8);
+ spec->langsys = gen_otf_tag (str, 8);
str += 4;
}
else
- langsys = 0;
- gsub = str;
+ spec->langsys = 0;
+ features[0] = str;
if (*str != '=')
/* Apply all GSUB features. */
- gsub_count = 1;
+ feature_count[0] = -1;
else
{
p = str + 1;
- str = otf_count_features (p, end, '+', &gsub_count);
+ str = otf_count_features (p, end, '+', feature_count);
if (! str)
MERROR (MERROR_FLT, -1);
}
- gpos = str;
+ features[1] = str;
if (*str != '+')
/* Apply all GPOS features. */
- gpos_count = 1;
+ feature_count[1] = -1;
else
{
p = str + 1;
- str = otf_count_features (p, end, '\0', &gpos_count);
+ str = otf_count_features (p, end, '\0', feature_count + 1);
if (! str)
MERROR (MERROR_FLT, -1);
}
-
- spec->script = script;
- spec->langsys = langsys;
- if (gsub_count > 0)
- {
- 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;
- }
- if (gpos_count > 0)
- {
- spec->features[1] = malloc (sizeof (int) * (gpos_count + 1));
- if (! spec->features[1])
- {
- if (spec->features[0])
- free (spec->features[0]);
+ features[2] = str;
+ for (i = 0; i < 2; i++)
+ if (feature_count[i])
+ {
+ spec->features[i] = malloc (sizeof (int)
+ * (feature_count[i] < 0 ? 2
+ : feature_count[i] + 1));
+ if (! spec->features[i])
return -2;
- }
- if (*gpos == '+')
- otf_store_features (gpos + 1, str, spec->features[1]);
- else
- spec->features[1][0] = 0xFFFFFFFF, spec->features[1][1] = 0;
- }
+ if (feature_count[i] > 0)
+ otf_store_features (features[i] + 1, features[i + 1],
+ spec->features[i]);
+ else
+ spec->features[i][0] = 0xFFFFFFFF, spec->features[i][1] = 0;
+ }
+
return 0;
}
char *name = MSYMBOL_NAME (sym);
int result;
- if (name[0] != ':' && name[0] != '?')
+ if (name[0] != ':')
{
/* This is old format of "otf:...". Change it to ":otf=...". */
char *str = alloca (MSYMBOL_NAMELEN (sym) + 2);
continue;
}
category = load_category_table (pl, NULL);
+ if (! category)
+ goto err;
if (! flt->coverage)
{
flt->coverage = category;
}
if (category)
unref_category_table (category);
-
+ err:
if (! MPLIST_TAIL_P (plist))
{
M17N_OBJECT_UNREF (top);
static int run_command (int, int, int, int, FontLayoutContext *);
static int run_otf (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
-static int run_otf_category (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
+static int try_otf (int, MFLTOtfSpec *, int, int, FontLayoutContext *);
#define NMATCH 20
{
if (MPLIST_INTEGER_P (p))
{
- GREF (&gstring, i)->code = MPLIST_INTEGER (p);
+ GREF (&gstring, i)->c = MPLIST_INTEGER (p);
GREF (&gstring, i)->encoded = 0;
}
else
{
- GREF (&gstring, i)->code = GREF (ctx->in, idx)->code;
+ GREF (&gstring, i)->c = GREF (ctx->in, idx)->code;
GREF (&gstring, i)->encoded = GREF (ctx->in, idx)->encoded;
idx++;
}
unsigned int tag = g->internal & 0xFFFFFFF;
char enc;
+ if (GET_COMBINED (g))
+ continue;
if (! category)
{
SET_CATEGORY_CODE (g, 0);
continue;
}
+ enc = '\0';
if (tag & 0xFFFFF80)
{
int i;
- g->internal &= 0x30000000;
- for (i = 0, enc = '\0'; i < category->feature_table.size; i++)
+ /* Clear the feature tag code. */
+ g->internal &= ~0xFFFFFFF;
+ for (i = 0; i < category->feature_table.size; i++)
if (category->feature_table.tag[i] == tag)
{
enc = category->feature_table.code[i];
break;
}
}
- else
- enc = GET_COMBINED (g) ? '\0' : GET_CATEGORY_CODE (g);
if (! enc)
- enc = g->c > 0 ? (int) mchartable_lookup (category->table, g->c) : 1;
+ enc = (g->c > 0 ? (int) mchartable_lookup (category->table, g->c)
+ : g->c == 0 ? 1 : ' ');
SET_CATEGORY_CODE (g, enc);
}
}
}
static int
-run_otf_category (int depth, MFLTOtfSpec *otf_spec, int from, int to,
- FontLayoutContext *ctx)
+try_otf (int depth, MFLTOtfSpec *otf_spec, int from, int to,
+ FontLayoutContext *ctx)
{
MFLTFont *font = ctx->font;
- int from_idx = ctx->out->used;
-
- if (ctx->stage->category->feature_table.size == 0)
- return from;
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);
- if (font->drive_otf)
+ if (! otf_spec->features[0] && ! otf_spec->features[1])
{
- int out_len;
+ /* Reset categories. */
+ MCharTable *table = ctx->category->table;
int i;
- to = font->drive_otf (font, otf_spec, ctx->in, from, to, NULL, NULL);
+ for (i = from; i < to; i++)
+ {
+ MFLTGlyph *g = GREF (ctx->in, i);
+
+ if (! GET_COMBINED (g))
+ {
+ char enc = (GET_ENCODED (g)
+ ? (g->c > 0 ? (int) mchartable_lookup (table, g->c)
+ : 1)
+ : g->code
+ ? (int) mchartable_lookup (table, g->code)
+ : ' ');
+ SET_CATEGORY_CODE (g, enc);
+ ctx->encoded[i - ctx->encoded_offset] = enc;
+ }
+ }
+ return from;
+ }
+
+ if (ctx->stage->category->feature_table.size == 0)
+ return from;
+
+ font->get_glyph_id (font, ctx->in, from, to);
+ if (mflt_try_otf)
+ {
+ to = mflt_try_otf (font, otf_spec, ctx->in, from, to);
if (to < 0)
return from;
decode_packed_otf_tag (ctx, ctx->in, from, to, ctx->stage->category);
else if (cmd->type == FontLayoutCmdTypeOTF)
to = run_otf (depth, &cmd->body.otf, from, to, ctx);
else if (cmd->type == FontLayoutCmdTypeOTFCategory)
- to = run_otf_category (depth, &cmd->body.otf, from, to, ctx);
+ to = try_otf (depth, &cmd->body.otf, from, to, ctx);
return to;
}
g = GREF (ctx->out, ctx->out->used - 1);
if (ctx->combining_code)
SET_COMBINING_CODE (g, ctx, ctx->combining_code);
- else if (! GET_COMBINED (g) && ctx->category)
- {
- MCharTable *table = ctx->category->table;
- char enc = (GET_ENCODED (g)
- ? (g->c > 0 ? (int) mchartable_lookup (table, g->c)
- : 1)
- : g->code
- ? (int) mchartable_lookup (table, g->code)
- : ' ');
- SET_CATEGORY_CODE (g, enc);
- }
if (ctx->left_padding)
SET_LEFT_PADDING (g, ctx, LeftPaddingMask);
if (ctx->cluster_begin_idx >= 0)
{
int i;
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT2 ("\n [FLT] %*s|", depth, "");
i = from < to ? from : from - 1;
GDUP (ctx, i);
g = GREF (ctx->out, ctx->out->used - 1);
g->c = -1, g->code = 0;
g->xadv = g->yadv = 0;
SET_ENCODED (g, 1);
- SET_MEASURED (g, 1);
+ SET_MEASURED (g, 0);
SET_CATEGORY_CODE (g, ' ');
return from;
}
int i, j;
MFLTGlyph *g;
MPlist *stages = flt->stages;
+ FontLayoutCategory *prev_category = NULL;
from_pos = GREF (ctx->in, from)->from;
to_pos = GREF (ctx->in, to - 1)->to;
MFLTGlyph *g = GREF (ctx->in, i);
char enc;
- if (GET_COMBINED (g))
- enc = (GET_ENCODED (g)
- ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) : 1)
- : g->code
- ? (int) mchartable_lookup (table, g->code)
- : ' ');
+ if (GET_COMBINED (g)
+ || (prev_category && prev_category != ctx->stage->category))
+ {
+ enc = (GET_ENCODED (g)
+ ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) : 1)
+ : g->code
+ ? (int) mchartable_lookup (table, g->code)
+ : ' ');
+ if (! GET_COMBINED (g))
+ SET_CATEGORY_CODE (g, enc);
+ }
else
enc = GET_CATEGORY_CODE (g);
ctx->encoded[i - from] = enc;
break;
/* Otherwise, prepare for the next stage. */
+ prev_category = ctx->stage->category;
temp = ctx->in;
ctx->in = ctx->out;
if (buf.glyphs)
Mgenerator = msymbol ("generator");
Mend = msymbol ("end");
+ mflt_enable_new_feature = 0;
mflt_iterate_otf_feature = NULL;
mflt_font_id = NULL;
+ mflt_try_otf = NULL;
- MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize the flt modules."));
+ MDEBUG_PRINT_TIME ("INIT", (mdebug__output, " to initialize the flt modules."));
MDEBUG_POP_TIME ();
}
MDEBUG_PUSH_TIME ();
free_flt_list ();
- MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize the flt modules."));
+ MDEBUG_PRINT_TIME ("FINI", (mdebug__output, " to finalize the flt modules."));
MDEBUG_POP_TIME ();
m17n_fini_core ();
}
}
best = flt;
}
+ if (best == NULL)
+ return NULL;
flt = best;
goto found;
}
{
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);
- }
+ {
+ int idx = -1;
+ for (i = 0; this_from < this_to; i++, this_from++)
+ {
+ g = GREF (gstring, this_from);
+ if (g->from != idx)
+ {
+ if (i > 0)
+ MDEBUG_PRINT2 ("\n [FLT] %02d-%02d",
+ g->from, g->to);
+ else
+ MDEBUG_PRINT2 (" %02d-%02d", g->from, g->to);
+ idx = g->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);
return to;
}
+int mflt_enable_new_feature;
+
int (*mflt_iterate_otf_feature) (struct _MFLTFont *font,
MFLTOtfSpec *spec,
int from, int to,
MSymbol (*mflt_font_id) (struct _MFLTFont *font);
+int (*mflt_try_otf) (struct _MFLTFont *font, MFLTOtfSpec *spec,
+ MFLTGlyphString *gstring, int from, int to);
+
\f
/* for debugging... */
prefix[indent] = 0;
if (id >= 0)
- fprintf (stderr, "0x%02X", id);
+ fprintf (mdebug__output, "0x%02X", id);
else if (id <= CMD_ID_OFFSET_INDEX)
{
int idx = CMD_ID_TO_INDEX (id);
FontLayoutCmdRule *rule = &cmd->body.rule;
int i;
- fprintf (stderr, "(rule ");
+ fprintf (mdebug__output, "(rule ");
if (rule->src_type == SRC_REGEX)
- fprintf (stderr, "\"%s\"", rule->src.re.pattern);
+ fprintf (mdebug__output, "\"%s\"", rule->src.re.pattern);
else if (rule->src_type == SRC_INDEX)
- fprintf (stderr, "%d", rule->src.match_idx);
+ fprintf (mdebug__output, "%d", rule->src.match_idx);
else if (rule->src_type == SRC_SEQ)
- fprintf (stderr, "(seq)");
+ fprintf (mdebug__output, "(seq)");
else if (rule->src_type == SRC_RANGE)
- fprintf (stderr, "(range)");
+ fprintf (mdebug__output, "(range)");
else
- fprintf (stderr, "(invalid src)");
+ fprintf (mdebug__output, "(invalid src)");
for (i = 0; i < rule->n_cmds; i++)
{
- fprintf (stderr, "\n%s ", prefix);
+ fprintf (mdebug__output, "\n%s ", prefix);
dump_flt_cmd (stage, rule->cmd_ids[i], indent + 2);
}
- fprintf (stderr, ")");
+ fprintf (mdebug__output, ")");
}
else if (cmd->type == FontLayoutCmdTypeCond)
{
FontLayoutCmdCond *cond = &cmd->body.cond;
int i;
- fprintf (stderr, "(cond");
+ fprintf (mdebug__output, "(cond");
for (i = 0; i < cond->n_cmds; i++)
{
- fprintf (stderr, "\n%s ", prefix);
+ fprintf (mdebug__output, "\n%s ", prefix);
dump_flt_cmd (stage, cond->cmd_ids[i], indent + 2);
}
- fprintf (stderr, ")");
+ fprintf (mdebug__output, ")");
}
else if (cmd->type == FontLayoutCmdTypeOTF)
{
- fprintf (stderr, "(otf)");
+ fprintf (mdebug__output, "(otf)");
}
else
- fprintf (stderr, "(error-command)");
+ fprintf (mdebug__output, "(error-command)");
}
else if (id <= CMD_ID_OFFSET_COMBINING)
- fprintf (stderr, "cominging-code");
+ fprintf (mdebug__output, "cominging-code");
else
- fprintf (stderr, "(predefiend %d)", id);
+ fprintf (mdebug__output, "(predefiend %d)", id);
}
/***en
@brief Dump a Font Layout Table.
The mdebug_dump_flt () function prints the Font Layout Table $FLT
- in a human readable way to the stderr. $INDENT specifies how many
- columns to indent the lines but the first one.
+ in a human readable way to the stderr or to what specified by the
+ environment variable MDEBUG_OUTPUT_FILE. $INDENT specifies how
+ many columns to indent the lines but the first one.
@return
This function returns $FLT. */
memset (prefix, 32, indent);
prefix[indent] = 0;
- fprintf (stderr, "(flt");
+ fprintf (mdebug__output, "(flt");
MPLIST_DO (plist, flt->stages)
{
FontLayoutStage *stage = (FontLayoutStage *) MPLIST_VAL (plist);
int i;
- fprintf (stderr, "\n%s (stage %d", prefix, stage_idx);
+ fprintf (mdebug__output, "\n%s (stage %d", prefix, stage_idx);
for (i = 0; i < stage->used; i++)
{
- fprintf (stderr, "\n%s ", prefix);
+ fprintf (mdebug__output, "\n%s ", prefix);
dump_flt_cmd (stage, INDEX_TO_CMD_ID (i), indent + 4);
}
- fprintf (stderr, ")");
+ fprintf (mdebug__output, ")");
stage_idx++;
}
- fprintf (stderr, ")");
+ fprintf (mdebug__output, ")");
return flt;
}
{
int i;
- fprintf (stderr, "(flt-gstring");
+ fprintf (mdebug__output, "(flt-gstring");
for (i = 0; i < gstring->used; i++)
{
MFLTGlyph *g = GREF (gstring, i);
- fprintf (stderr, "\n (%02d pos:%d-%d c:%04X code:%04X cat:%c)",
+ fprintf (mdebug__output, "\n (%02d pos:%d-%d c:%04X code:%04X cat:%c)",
i, g->from, g->to, g->c, g->code, GET_CATEGORY_CODE (g));
}
- fprintf (stderr, ")\n");
+ fprintf (mdebug__output, ")\n");
}
/*** @} */