#elif defined (FLT_HB)
#include <m17n-flt.h>
-#include <harfbuzz.h>
+#include <hb.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/pangcairo.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;
int
#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)
-{
- 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;
-}
-
#elif defined (FLT_OTF) || defined (FLT_HB)
typedef struct {
} 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 {
*str = '\0';
}
+static OTF_GlyphString otf_gstring;
+
+static void
+setup_otf_gstring (int size)
+{
+ if (otf_gstring.size == 0)
+ {
+ otf_gstring.glyphs = (OTF_Glyph *) xmalloc (sizeof (OTF_Glyph) * size);
+ otf_gstring.size = size;
+ }
+ else if (otf_gstring.size < size)
+ {
+ otf_gstring.glyphs = xrealloc (otf_gstring.glyphs,
+ sizeof (OTF_Glyph) * size);
+ otf_gstring.size = size;
+ }
+ otf_gstring.used = size;
+ memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
+}
+
int
drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
MFLTGlyphString *in, int from, int to,
MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
{
- int len = to - from;
- int i, gidx;
OTF *otf = ((FontInfoOTF *) font)->otf;
- OTF_GlyphString otf_gstring;
+ int len = to - from;
+ int i, j, gidx;
OTF_Glyph *otfg;
- char script[4], langsys[4];
+ char script[5], *langsys = NULL;
char *gsub_features = NULL, *gpos_features = NULL;
if (len == 0)
return from;
- if (! otf)
- goto simple_copy;
- otf_gstring.glyphs = NULL;
- if (OTF_get_table (otf, "head") < 0)
+ OTF_tag_name (spec->script, script);
+ if (spec->langsys)
{
- OTF_close (otf);
- ((FontInfoOTF *) font)->otf = NULL;
- goto simple_copy;
+ langsys = alloca (5);
+ OTF_tag_name (spec->langsys, langsys);
}
-
- tag_name (script, spec->script);
- tag_name (langsys, spec->langsys);
-
- if (spec->gsub_count > 0)
+ for (i = 0; i < 2; i++)
{
- gsub_features = alloca (6 * spec->gsub_count);
- if (gsub_features)
- {
- if (OTF_check_table (otf, "GSUB") < 0)
- gsub_features = NULL;
- else
- encode_features (gsub_features, spec->gsub_count, spec->gsub);
- }
- }
- if (spec->gpos_count)
- {
- gpos_features = alloca (6 * spec->gpos_count);
- if (gpos_features)
+ char *p;
+
+ if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
{
- if (OTF_check_table (otf, "GPOS") < 0)
- gpos_features = NULL;
+ for (j = 0; spec->features[i][j]; j++);
+ if (i == 0)
+ p = gsub_features = alloca (6 * j);
else
- encode_features (gpos_features, spec->gpos_count, spec->gpos);
+ p = gpos_features = alloca (6 * j);
+ for (j = 0; spec->features[i][j]; j++)
+ {
+ if (spec->features[i][j] == 0xFFFFFFFF)
+ *p++ = '*', *p++ = ',';
+ else
+ {
+ OTF_tag_name (spec->features[i][j], p);
+ p[4] = ',';
+ p += 5;
+ }
+ }
+ *--p = '\0';
}
}
- otf_gstring.size = otf_gstring.used = len;
- otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
- memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
+ setup_otf_gstring (len);
for (i = 0; i < len; i++)
{
otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
g->c = in->glyphs[j].c;
break;
}
- g->code = otfg->glyph_id;
+ 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);
font_info = malloc (sizeof (FontInfoOTF));
font_info->face = face;
font_info->otf = OTF_open_ft_face (face);
+ if (OTF_get_table (font_info->otf, "head") < 0)
+ {
+ OTF_close (font_info->otf);
+ FT_Done_Face (font_info->face);
+ free (font_info);
+ return NULL;
+ }
return ((MFLTFont *) font_info);
}
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)
{
} FontInfoPango;
int
-get_glyph_id (MFLTFont *font, MFLTGlyph *g)
+get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
{
FontInfoPango *font_info = (FontInfoPango *) font;
- g->code = pango_fc_font_get_glyph (font_info->pango_font, g->c);
- return (g->code ? 0 : -1);
+ 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_metric (MFLTFont *font, MFLTGlyphString *gstring, int from, int to)
+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;
- 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;
+ 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
}
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 *
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->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_object_unref (font_info->fontmap);
}
+#endif
+
+#ifdef FLT_GUI
+
int
-flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
+run_flt (MText *mt, int from, int to, MFLTFont *font, char *flt_name)
{
- MFLTGlyphString gstring;
- int len = to - from;
- int i;
+ MDrawControl control;
- 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));
+ 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)
{
exit (1);
}
font->get_glyph_id = get_glyph_id;
- font->get_metric = get_metric;
+ 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'))
if (j < 0)
j = len;
- to = flt (mt, i, j, font, flt_name);
+ to = run_flt (mt, i, j, font, flt_name);
if (to < 0)
{
fprintf (stderr, "Error in FLT processing.\n");
exit (1);
}
- while (to < j
-
+ i = j;
}
m17n_object_unref (mt);
+ free (buf);
close_font (font);
M17N_FINI ();
return 0;