MSymbol Mfont, Mlayouter;
+static MSymbol Mgenerator, Mend;
+
static MPlist *flt_list;
+static int flt_min_coverage, flt_max_coverage;
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) \
#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
#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)
{
MSymbol name;
MSymbol family;
+ MSymbol registry;
MFLTOtfSpec otf;
MDatabase *mdb;
MCharTable *coverage;
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 ) *
*/
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)
return NULL;
}
if (*p == '~')
- p += 5;
+ {
+ if (negative++ == 0)
+ (*count)++;
+ p += 5;
+ }
else
p += 4;
if (p > end)
}
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
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;
}
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;
}
}
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)
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]);
}
}
/* 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)
{
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;
if (! category)
break;
- stage = load_generator (elt);
+ stage = load_generator (pl);
if (! stage)
break;
stage->category = category;
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. */
table into this array. An element is a category letter used for
a regular expression matching. */
char *encoded;
- /* <encoded>[GIDX - <encoded_offset>] 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;
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)
}
else
{
- ctx->encoded[to - ctx->encoded_offset] = saved_code;
+ ctx->encoded[to] = saved_code;
return 0;
}
}
{
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;
+ }
}
}
}
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);
? (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++)
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++)
{
}
ctx->out->used = 0;
- ctx->encoded_offset = 0;
from = 0;
to = ctx->in->used;
}
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;)
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)
\f
/* 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);
-}
-
\f
/* External API */
}
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 ();
}
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 ();
/*** @} */
#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));
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;
}
\f
}
fprintf (stderr, ")");
}
+
+/*** @} */
+
+/*
+ Local Variables:
+ coding: euc-japan
+ End:
+*/