#include <otf.h>
#define PROGNAME "flt-otf"
-#else /* defined (FLT_HB) */
+#elif defined (FLT_HB)
#include <m17n-flt.h>
#include <harfbuzz.h>
#define PROGNAME "flt-hb"
+#else /* (defined (FLT_PANGO)) */
+
+#include <m17n-flt.h>
+#define PANGO_ENABLE_ENGINE
+#define PANGO_ENABLE_BACKEND
+#include <pango/pango.h>
+#include <pango/pango-ot.h>
+#include <pango/pangoft2.h>
+#include <pango/pangofc-font.h>
+
#endif
+#include <m17n-misc.h>
+
static FT_Library ft_library;
-FT_Face
-new_face (char *fontname, char **err)
+int
+parse_font_name (char *fontname, char **family, int *size, char **err)
{
FcPattern *pat;
- FcChar8 *fam, *file;
+ FcChar8 *fam;
double pixelsize;
- FcFontSet *fs;
- FcObjectSet *os;
- FT_Face face;
pat = FcNameParse ((FcChar8 *) fontname);
if (! pat)
{
*err = "invalid name format";
- return NULL;
+ return -1;
}
if (FcPatternGetString (pat, FC_FAMILY, 0, &fam) != FcResultMatch)
{
+ FcPatternDestroy (pat);
*err = "no family name";
- return NULL;
+ return -1;
}
if (FcPatternGetDouble (pat, FC_PIXEL_SIZE, 0, &pixelsize) != FcResultMatch)
pixelsize = 20;
- FcPatternAddBool (pat, FC_SCALABLE, FcTrue);
- FcPatternDel (pat, FC_PIXEL_SIZE);
+ *family = strdup ((char *) fam);
+ *size = pixelsize;
+ FcPatternDestroy (pat);
+ return 0;
+}
+
+FT_Face
+new_face (char *fontname, char **err)
+{
+ FcPattern *pat;
+ FcChar8 *fam, *file;
+ int size;
+ double pixelsize;
+ FcFontSet *fs;
+ FcObjectSet *os;
+ FT_Face face;
+
+ if (parse_font_name (fontname, (char **) &fam, &size, err) < 0)
+ return NULL;
+ pixelsize = size;
+ pat = FcPatternBuild (0,
+ FC_FAMILY, FcTypeString, fam,
+ FC_SCALABLE, FcTypeBool, FcTrue,
+ NULL);
+ free (fam);
os = FcObjectSetBuild (FC_FILE, NULL);
fs = FcFontList (NULL, pat, os);
if (fs->nfont == 0)
#ifdef FLT_GUI
-typedef struct
+typedef struct _MFLTFont MFLTFont;
+
+struct _MFLTFont
{
+ int x_ppem, y_ppem;
+ void (*get_glyph_id) (void);
+ void (*get_metrics) (void);
+ void (*suitable_p) (void);
+ void (*drive_otf) (void);
MFont *font;
FT_Face face;
-} MFLTFont;
+};
+
+void get_glyph_id (void) {}
+void get_metrics (void) {}
+void suitable_p (void) {}
+void drive_otf (void) {}
MFrame *frame;
m17n_object_unref (frame);
}
-int
-flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
-{
- mtext_put_prop (mt, from, to, Mfont, font->font);
- mdraw_text_extents (frame, mt, from, to, NULL, NULL, NULL, NULL);
- return 0;
-}
-
-#else /* FLT_OTF or FLT_HB */
+#elif defined (FLT_OTF) || defined (FLT_HB)
typedef struct {
MFLTFont font;
} FontInfo;
int
-get_glyph_id (MFLTFont *font, MFLTGlyph *g)
+get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
{
FT_Face face = ((FontInfo *) font)->face;
- g->code = FT_Get_Char_Index (face, g->code);
+ for (; from < to; from++)
+ {
+ MFLTGlyph *g = gstring->glyphs + from;
- return (g->code ? 0 : -1);
+ if (! g->encoded
+ && ! (g->code = FT_Get_Char_Index (face, g->code)))
+ return -1;
+ g->encoded = 1;
+ }
+ return 0;
}
int
-get_metric (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
+get_metrics (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
{
FT_Face face = ((FontInfo *) font)->face;
for (; from < to; from++)
{
MFLTGlyph *g = gstring->glyphs + from;
- FT_Glyph_Metrics *metrics;
- if (FT_Load_Glyph (face, g->code, FT_LOAD_DEFAULT))
- return -1;
- metrics = &face->glyph->metrics;
- g->lbearing = metrics->horiBearingX;
- g->rbearing = metrics->horiBearingX + metrics->width;
- g->xadv = metrics->horiAdvance;
- g->yadv = metrics->vertAdvance;
- g->ascent = metrics->horiBearingY;
- g->descent = metrics->height - metrics->horiBearingY;
+ if (! g->measured)
+ {
+ FT_Glyph_Metrics *metrics;
+
+ if (FT_Load_Glyph (face, g->code, FT_LOAD_DEFAULT))
+ return -1;
+ metrics = &face->glyph->metrics;
+ g->lbearing = metrics->horiBearingX;
+ g->rbearing = metrics->horiBearingX + metrics->width;
+ g->xadv = metrics->horiAdvance;
+ g->yadv = metrics->vertAdvance;
+ g->ascent = metrics->horiBearingY;
+ g->descent = metrics->height - metrics->horiBearingY;
+ g->measured = 1;
+ }
}
return 0;
}
-int
-flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
-{
- MFLTGlyphString gstring;
- int len = to - from;
- int i;
-
- memset (&gstring, 0, sizeof (MFLTGlyphString));
- gstring.glyph_size = sizeof (MFLTGlyph);
- gstring.allocated = len * 2;
- gstring.glyphs = alloca (sizeof (MFLTGlyph) * gstring.allocated);
- for (i = 0; i < len; i++)
- gstring.glyphs[i].c = mtext_ref_char (mt, from + i);
- gstring.used = len;
- return mflt_run (&gstring, 0, len, font, msymbol (flt_name));
-}
-
#ifdef FLT_OTF
typedef struct {
}
int
-drive_otf (MFLTFont *font, MFLT_OTF_Spec *spec,
+drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
MFLTGlyphString *in, int from, int to,
MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
{
for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
{
MFLTGlyph *g = out->glyphs + out->used;
+ int j;
*g = in->glyphs[from + otfg->f.index.from];
- g->c = otfg->c;
- g->code = otfg->glyph_id;
+ g->c = 0;
+ for (j = from + otfg->f.index.from; j <= from + otfg->f.index.to; j++)
+ if (in->glyphs[j].code == otfg->glyph_id)
+ {
+ g->c = in->glyphs[j].c;
+ break;
+ }
+ if (g->code != otfg->glyph_id)
+ {
+ g->code = otfg->glyph_id;
+ g->measured = 0;
+ }
out->used++;
}
}
out->glyphs[out->used++] = in->glyphs[from + i];
}
- font->get_metric (font, out, gidx, out->used);
-
if (gpos_features)
{
FT_Face face;
return to;
simple_copy:
- font->get_metric (font, in, from, to);
+ font->get_metrics (font, in, from, to);
for (i = 0; i < len; i++)
{
MFLTGlyph *g = in->glyphs + (from + i);
if (! face)
return NULL;
font_info = malloc (sizeof (FontInfoOTF));
- font_info->font.get_glyph_id = get_glyph_id;
- font_info->font.get_metric = get_metric;
- font_info->font.drive_otf = drive_otf;
font_info->face = face;
font_info->otf = OTF_open_ft_face (face);
return ((MFLTFont *) font_info);
getPointInOutline, getGlyphMetrics, getFontMetric
};
-HB_Error
-setup_features (int gsubp, FontInfoHB *font_info, MFLT_OTF_Spec *spec,
+void
+setup_features (int gsubp, FontInfoHB *font_info, MFLTOtfSpec *spec,
FeatureInfo *info)
{
int count, preordered;
FT_UShort req_feature, index;
FT_UInt *feature_list;
int i, j, k;
- HB_Error err;
if (gsubp)
{
if (! font_info->gsub)
{
- if ((err = load_gsub (font_info)) != HB_Err_Ok)
- return err;
+ if (load_gsub (font_info) != HB_Err_Ok)
+ return;
}
- if ((err = HB_GSUB_Select_Script (font_info->gsub, spec->script, &script))
+ if (HB_GSUB_Select_Script (font_info->gsub, spec->script, &script)
!= HB_Err_Ok)
- return err;
+ return;
if (spec->langsys)
{
- if ((err = HB_GSUB_Select_Language (font_info->gsub, spec->langsys,
- script, &langsys, &req_feature))
+ if (HB_GSUB_Select_Language (font_info->gsub, spec->langsys,
+ script, &langsys, &req_feature)
!= HB_Err_Ok)
- return err;
+ return;
}
else
langsys = req_feature = 0xFFFF;
{
if (! font_info->gpos)
{
- if ((err = load_gpos (font_info)) != HB_Err_Ok)
- return err;
+ if (load_gpos (font_info) != HB_Err_Ok)
+ return;
}
- if ((err = HB_GPOS_Select_Script (font_info->gpos, spec->script, &script))
+ if (HB_GPOS_Select_Script (font_info->gpos, spec->script, &script)
!= HB_Err_Ok)
- return err;
+ return;
if (spec->langsys)
{
- if ((err = HB_GPOS_Select_Language (font_info->gpos, spec->langsys,
- script, &langsys, &req_feature))
+ if (HB_GPOS_Select_Language (font_info->gpos, spec->langsys,
+ script, &langsys, &req_feature)
!= HB_Err_Ok)
- return err;
+ return;
}
else
langsys = req_feature = 0xFFFF;
for (preordered = 0; preordered < count; preordered++)
if (features[preordered] == 0)
{
- if ((err = (gsubp
- ? HB_GSUB_Query_Features (font_info->gsub, script, langsys,
- &feature_list)
- : HB_GPOS_Query_Features (font_info->gpos, script, langsys,
- &feature_list)))
+ if ((gsubp ? HB_GSUB_Query_Features (font_info->gsub, script, langsys,
+ &feature_list)
+ : HB_GPOS_Query_Features (font_info->gpos, script, langsys,
+ &feature_list))
!= HB_Err_Ok)
- return err;
+ return;
break;
}
if (feature_list)
if (req_feature != 0xFFFF)
info->indices[i++] = req_feature;
for (j = 0; j < preordered; j++)
- if ((err = (gsubp
- ? HB_GSUB_Select_Feature (font_info->gsub, features[j],
- script, langsys, &index)
- : HB_GPOS_Select_Feature (font_info->gpos, features[j],
- script, langsys, &index)))
+ if ((gsubp ? HB_GSUB_Select_Feature (font_info->gsub, features[j],
+ script, langsys, &index)
+ : HB_GPOS_Select_Feature (font_info->gpos, features[j],
+ script, langsys, &index))
== HB_Err_Ok)
info->indices[i++] = index;
if (feature_list)
script, langsys, &index)
: HB_GPOS_Select_Feature (font_info->gpos, feature_list[j],
script, langsys, &index))
- == FT_Err_Ok))
+ == HB_Err_Ok))
info->indices[i++] = index;
}
info->count = i;
- return HB_Err_Ok;
}
GsubGposInfo *
-setup_otf_spec (MFLTFont *font, MFLT_OTF_Spec *spec)
+setup_otf_spec (MFLTFont *font, MFLTOtfSpec *spec)
{
FontInfoHB *font_info = (FontInfoHB *) font;
GsubGposInfo *ginfo;
return (ginfo->gsub.count + ginfo->gpos.count > 0 ? ginfo : NULL);
ginfo = calloc (1, sizeof (GsubGposInfo));
mplist_push (font_info->otf_spec_cache, spec->sym, ginfo);
- if (setup_features (1, font_info, spec, &(ginfo->gsub)) != HB_Err_Ok)
- return NULL;
- if (setup_features (0, font_info, spec, &(ginfo->gpos)) != HB_Err_Ok)
- return NULL;
+ setup_features (1, font_info, spec, &(ginfo->gsub));
+ setup_features (0, font_info, spec, &(ginfo->gpos));
return ginfo;
}
int
-drive_otf (MFLTFont *font, MFLT_OTF_Spec *spec,
+drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
MFLTGlyphString *in, int from, int to,
MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
{
FontInfoHB *font_info = (FontInfoHB *) font;
int len = to - from;
- int i, gidx;
+ int i;
HB_Buffer buf;
GsubGposInfo *ginfo;
HB_UShort *apply_order_save;
gpos_applied = 1;
}
- gidx = out->used;
-
for (i = 0; i < buf->in_length; i++)
{
HB_GlyphItem hg = buf->in_string + i;
out->glyphs[out->used] = in->glyphs[hg->cluster];
g = out->glyphs + out->used++;
if (g->code != hg->gindex)
- g->c = 0, g->code = hg->gindex;
+ {
+ g->c = 0;
+ g->code = hg->gindex;
+ g->measured = 0;
+ }
adjustment[i].set = gpos_applied;
if (gpos_applied)
{
if (! face)
return NULL;
font_info = calloc (1, sizeof (FontInfoHB));
- font_info->font.get_glyph_id = get_glyph_id;
- font_info->font.get_metric = get_metric;
- font_info->font.drive_otf = drive_otf;
font_info->face = face;
font_info->hb_font.klass = &hb_fontClass;
font_info->hb_font.faceData = face;
}
#endif
+
+#else /* (defined (FLT_PANGO) */
+
+typedef struct {
+ int count;
+ guint *indices;
+ PangoOTRuleset *ruleset;
+} FeatureInfo;
+
+typedef struct {
+ FeatureInfo gsub;
+ FeatureInfo gpos;
+} GsubGposInfo;
+
+typedef struct {
+ MFLTFont font;
+ PangoFontMap *fontmap;
+ PangoContext *context;
+ PangoFcFont *pango_font;
+ MPlist *otf_spec_cache;
+} FontInfoPango;
+
+int
+get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
+{
+ FontInfoPango *font_info = (FontInfoPango *) font;
+
+ for (; from < to; from++)
+ {
+ MFLTGlyph *g = gstring->glyphs + from;
+
+ if (! g->encoded
+ && ! (g->code = pango_fc_font_get_glyph (font_info->pango_font,
+ g->code)))
+ return -1;
+ g->encoded = 1;
+ }
+ return 0;
+}
+
+#define PANGO_SCALE_TO_26_6 (PANGO_SCALE / (1<<6))
+
+int
+get_metrics (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
+{
+ FontInfoPango *font_info = (FontInfoPango *) font;
+ int i;
+
+ for (i = from; i < to; i++)
+ {
+ MFLTGlyph *g = gstring->glyphs + from;
+
+ if (! g->measured)
+ {
+ PangoRectangle inc, logical;
+
+ pango_font_get_glyph_extents (PANGO_FONT (font_info->pango_font),
+ gstring->glyphs[i].code, &inc, &logical);
+ g->lbearing = inc.x / PANGO_SCALE_TO_26_6;
+ g->rbearing = (inc.x + inc.width) / PANGO_SCALE_TO_26_6;
+ g->xadv = logical.width / PANGO_SCALE_TO_26_6;
+ g->yadv = 0;
+ g->ascent = - inc.y / PANGO_SCALE_TO_26_6;
+ g->descent = (inc.height + inc.y) / PANGO_SCALE_TO_26_6;
+ g->measured = 1;
+ }
+ }
+ return 0;
+}
+
+
+#ifndef PANGO_OT_DEFAULT_LANGUAGE
+#define PANGO_OT_DEFAULT_LANGUAGE ((guint) 0xFFFF)
+#endif
+#ifndef PANGO_OT_ALL_GLYPHS
+#define PANGO_OT_ALL_GLYPHS ((guint) 0xFFFF)
+#endif
+
+void
+setup_features (PangoOTTableType type, FontInfoPango *font_info,
+ MFLTOtfSpec *spec, FeatureInfo *info)
+{
+ int count, preordered;
+ unsigned int *features;
+ guint script, langsys;
+ guint req_feature, index;
+ guint *feature_list;
+ int i, j, k;
+ FT_Face face;
+ PangoOTInfo *ot_info;
+
+ face = pango_fc_font_lock_face (font_info->pango_font);
+ ot_info = pango_ot_info_get (face);
+ pango_fc_font_unlock_face (font_info->pango_font);
+
+ if (! pango_ot_info_find_script (ot_info, type, spec->script, &script))
+ return;
+ if (spec->langsys)
+ {
+ if (! pango_ot_info_find_language (ot_info, type, script,
+ spec->langsys,
+ &langsys, &req_feature))
+ return;
+ }
+ else
+ {
+ langsys = PANGO_OT_DEFAULT_LANGUAGE;
+ req_feature = 0xFFFF;
+ }
+ if (type == PANGO_OT_TABLE_GSUB)
+ {
+ count = spec->gsub_count;
+ features = spec->gsub;
+ }
+ else
+ {
+ count = spec->gpos_count;
+ features = spec->gpos;
+ }
+ feature_list = NULL;
+ for (preordered = 0; preordered < count; preordered++)
+ if (features[preordered] == 0)
+ {
+ feature_list = pango_ot_info_list_features (ot_info, type, 0,
+ script, langsys);
+ if (! feature_list)
+ return;
+ break;
+ }
+ if (feature_list)
+ for (i = 0; feature_list[i]; i++);
+ else
+ i = preordered;
+ info->indices = malloc (sizeof (guint) * ((req_feature != 0xFFFF) + i));
+ i = 0;
+ if (req_feature != 0xFFFF)
+ info->indices[i++] = req_feature;
+ for (j = 0; j < preordered; j++)
+ if (pango_ot_info_find_feature (ot_info, type, features[j],
+ script, langsys, &index))
+ info->indices[i++] = index;
+ if (feature_list)
+ for (j = 0; feature_list[j]; j++)
+ {
+ for (k = preordered + 1; k < count; k++)
+ if (feature_list[j] == features[k])
+ break;
+ if (k == count
+ && pango_ot_info_find_feature (ot_info, type, feature_list[j],
+ script, langsys, &index))
+ info->indices[i++] = index;
+ }
+ info->count = i;
+ info->ruleset = pango_ot_ruleset_new (ot_info);
+#if 1
+ for (i = 0; i < info->count; i++)
+ pango_ot_ruleset_add_feature (info->ruleset, type, info->indices[i],
+ PANGO_OT_ALL_GLYPHS);
+#else
+ for (i = info->count - 1; i >= 0; i--)
+ pango_ot_ruleset_add_feature (info->ruleset, type, info->indices[i],
+ PANGO_OT_ALL_GLYPHS);
+#endif
+}
+
+GsubGposInfo *
+setup_otf_spec (FontInfoPango *font_info, MFLTOtfSpec *spec)
+{
+ GsubGposInfo *ginfo;
+
+ if (spec->gsub_count + spec->gpos_count == 0)
+ return NULL;
+ ginfo = mplist_get (font_info->otf_spec_cache, spec->sym);
+ if (ginfo)
+ return (ginfo->gsub.count + ginfo->gpos.count > 0 ? ginfo : NULL);
+ ginfo = calloc (1, sizeof (GsubGposInfo));
+ mplist_push (font_info->otf_spec_cache, spec->sym, ginfo);
+ setup_features (PANGO_OT_TABLE_GSUB, font_info, spec, &(ginfo->gsub));
+ setup_features (PANGO_OT_TABLE_GPOS, font_info, spec, &(ginfo->gpos));
+ return ginfo;
+}
+
+int
+drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
+ MFLTGlyphString *in, int from, int to,
+ MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
+{
+ FontInfoPango *font_info = (FontInfoPango *) font;
+ PangoOTBuffer *buffer;
+ GsubGposInfo *ginfo;
+ PangoGlyphString *glyphs;
+ int i;
+
+ buffer = pango_ot_buffer_new (font_info->pango_font);
+ for (i = from; i < to; i++)
+ pango_ot_buffer_add_glyph (buffer, in->glyphs[i].code, 0, i);
+ ginfo = setup_otf_spec (font_info, spec);
+ if (! ginfo)
+ goto simple_copy;
+ if (ginfo->gsub.count > 0)
+ pango_ot_ruleset_substitute (ginfo->gsub.ruleset, buffer);
+ if (ginfo->gpos.count > 0)
+ pango_ot_ruleset_position (ginfo->gpos.ruleset, buffer);
+ glyphs = pango_glyph_string_new ();
+ pango_ot_buffer_output (buffer, glyphs);
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ PangoGlyphInfo *glyph_info = glyphs->glyphs + i;
+ MFLTGlyph *g;
+
+ out->glyphs[out->used] = in->glyphs[glyphs->log_clusters[i]];
+ g = out->glyphs + out->used++;
+ if (g->code != glyph_info->glyph)
+ {
+ g->c = 0;
+ g->code = glyph_info->glyph;
+ g->measured = 0;
+ }
+ g->xoff = glyph_info->geometry.x_offset / PANGO_SCALE_TO_26_6;
+ g->yoff = glyph_info->geometry.y_offset / PANGO_SCALE_TO_26_6;
+ g->xadv = glyph_info->geometry.width / PANGO_SCALE_TO_26_6;
+ g->yadv = 0;
+ adjustment[i].set = 0;
+ }
+ pango_ot_buffer_destroy (buffer);
+ pango_glyph_string_free (glyphs);
+ return to;
+
+ simple_copy:
+ pango_ot_buffer_destroy (buffer);
+ for (i = from; i < to; i++)
+ out->glyphs[out->used++] = in->glyphs[i];
+ return to;
+}
+
+
+MFLTFont *
+open_font (char *fontname, char **err)
+{
+ FontInfoPango *font_info = NULL;
+ PangoFontMap *fontmap;
+ PangoContext *context;
+ PangoFontDescription *desc;
+ PangoFont *pango_font;
+ char *family;
+ int size;
+ double pango_size;
+
+ if (parse_font_name (fontname, &family, &size, err) < 0)
+ return NULL;
+ desc = pango_font_description_new ();
+ pango_font_description_set_family (desc, family);
+ free (family);
+ pango_size = size * PANGO_SCALE;
+ pango_font_description_set_absolute_size (desc, pango_size);
+
+ fontmap = pango_ft2_font_map_new ();
+ context = pango_context_new ();
+ pango_context_set_font_map (context, fontmap);
+ pango_font = pango_context_load_font (context, desc);
+ pango_font_description_free (desc);
+ if (pango_font)
+ {
+ font_info = calloc (1, sizeof (FontInfoPango));
+ font_info->fontmap = fontmap;
+ font_info->context = context;
+ font_info->pango_font = PANGO_FC_FONT (pango_font);
+ font_info->otf_spec_cache = mplist ();
+ }
+ else
+ {
+ g_object_unref (context);
+ g_object_unref (fontmap);
+ }
+ return (MFLTFont *) font_info;
+}
+
+void
+close_font (MFLTFont *font)
+{
+ FontInfoPango *font_info = (FontInfoPango *) font;
+
+ g_object_unref (font_info->context);
+ g_object_unref (font_info->fontmap);
+}
+
+#endif
+
+#ifdef FLT_GUI
+
+int
+run_flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
+{
+ MDrawControl control;
+
+ memset (&control, 0, sizeof (MDrawControl));
+ control.two_dimensional = 1;
+ control.enable_bidi = 1;
+ control.anti_alias = 1;
+ /*control.disable_caching = 1;*/
+ mtext_put_prop (mt, from, to, Mfont, font->font);
+ mdraw_text_extents (frame, mt, from, to, &control, NULL, NULL, NULL);
+ return 0;
+}
+
+#else
+
+int
+run_flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
+{
+ static MFLT *flt = NULL;
+ MCharTable *coverage;
+ static MFLTGlyphString gstring;
+
+ if (! flt
+ && ! (flt = mflt_get (flt_name)))
+ {
+ fprintf (stderr, "Invalid FLT name: %s\n", flt_name);
+ exit (1);
+ }
+ coverage = mflt_coverage (flt);
+ while (from < to)
+ {
+ int len = 0, i;
+
+ for (; from < to; from++)
+ if (mchartable_lookup (coverage, mtext_ref_char (mt, from)))
+ {
+ for (i = from + 1; i < to; i++)
+ if (! mchartable_lookup (coverage, mtext_ref_char (mt, i)))
+ break;
+ len = i - from;
+ break;
+ }
+ if (len > 0)
+ {
+ if (gstring.allocated < len)
+ {
+ gstring.allocated = len * 2;
+ gstring.glyphs = realloc (gstring.glyphs,
+ sizeof (MFLTGlyph) * len * 2);
+ }
+ gstring.glyph_size = sizeof (MFLTGlyph);
+ for (i = 0; i < len; i++)
+ gstring.glyphs[i].c = mtext_ref_char (mt, from + i);
+ gstring.used = len;
+ i = mflt_run (&gstring, 0, len, font, flt);
+ if (i < 0)
+ return i;
+ from += len;
+ }
+ }
+ return to;
+}
#endif
+
int
main (int argc, char **argv)
{
MText *mt;
MFLTFont *font;
int len, i, j;
+ unsigned char *buf;
if (argc < 3)
{
fprintf (stderr, "Font error: %s: %s\n", argv[1], err);
exit (1);
}
+ font->get_glyph_id = get_glyph_id;
+ font->get_metrics = get_metrics;
+ font->drive_otf = drive_otf;
- mt = mconv_decode_stream (msymbol ("utf-8"), stdin);
+ i = 0;
+ buf = malloc (4096);
+ while ((j = fread (buf + i, 1, 4096, stdin)) == 4096)
+ {
+ i += 4096;
+ buf = realloc (buf, i + 4096);
+ }
+ mt = mtext_from_data (buf, i, MTEXT_FORMAT_UTF_8);
len = mtext_len (mt);
for (i = 0, j = mtext_character (mt, i, len, '\n'); i < len;
i = j + 1, j = mtext_character (mt, i, len, '\n'))
{
+ int to;
+
if (j < 0)
j = len;
- if (flt (mt, i, j, font, flt_name) < 0)
+ to = run_flt (mt, i, j, font, flt_name);
+ if (to < 0)
{
fprintf (stderr, "Error in FLT processing.\n");
exit (1);
}
+ i = j;
}
m17n_object_unref (mt);
+ free (buf);
close_font (font);
M17N_FINI ();
return 0;