From e286b0841cbcdb0e7123529f221e5ac17e883c4d Mon Sep 17 00:00:00 2001 From: handa Date: Fri, 31 Aug 2007 13:08:51 +0000 Subject: [PATCH] *** empty log message *** --- Makefile.am | 6 +- configure.ac | 1 + flt.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- m17n-imconf.c | 3 + 4 files changed, 282 insertions(+), 24 deletions(-) diff --git a/Makefile.am b/Makefile.am index 9fd4cc1..6182fa8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ noinst_PROGRAMS = \ linebreak replace mimdemo mimdaemon fifotest1 fifotest2 \ imtest findfont gdkdraw finddb imsim langname viewfile pangotest \ - flt-gui flt-otf flt-hb + flt-gui flt-otf flt-hb flt-pango mimdemo_LDADD = -lgd mimdaemon_LDADD = -lgd @@ -28,6 +28,10 @@ flt_hb_SOURCES = flt.c flt_hb_CFLAGS = ${baseCFLAGS} @M17NFLT_CFLAGS@ @HB_CFLAGS@ -DFLT_HB flt_hb_LDFLAGS = ${baseLIBS} @M17NFLT_LIBS@ @HB_LIBS@ +flt_pango_SOURCES = flt.c +flt_pango_CFLAGS = ${baseCFLAGS} @M17NFLT_CFLAGS@ @PANGO_CFLAGS@ -DFLT_PANGO +flt_pango_LDFLAGS = ${baseLIBS} @M17NFLT_LIBS@ @PANGO_LIBS@ + verify: linebreak @echo "checking line breaking..." @for arg in "" --sp-cm --korean-sp --ai-as-id; do \ diff --git a/configure.ac b/configure.ac index 7edbef7..a9d0213 100644 --- a/configure.ac +++ b/configure.ac @@ -9,6 +9,7 @@ PKG_CHECK_MODULES(FC, fontconfig) PKG_CHECK_MODULES(M17NGUI, m17n-gui) PKG_CHECK_MODULES(M17NFLT, m17n-flt) PKG_CHECK_MODULES(OTF, libotf) +PKG_CHECK_MODULES(PANGO, pangoft2) AC_ARG_WITH(harfbuzz, [Harfbuzz source directory], HBDIR="$withval", HBDIR="../harfbuzz") if test -d "$HBDIR/src/.libs"; then diff --git a/flt.c b/flt.c index 963209b..4b4a4f0 100644 --- a/flt.c +++ b/flt.c @@ -23,42 +23,65 @@ #include #define PROGNAME "flt-hb" -#else (defined (FLT_PANGO)) +#else /* (defined (FLT_PANGO)) */ #include -#include +#define PANGO_ENABLE_ENGINE +#define PANGO_ENABLE_BACKEND +#include #include -#include - +#include +#include #endif 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) @@ -837,7 +860,7 @@ drive_otf (MFLTFont *font, MFLTOtfSpec *spec, { FontInfoHB *font_info = (FontInfoHB *) font; int len = to - from; - int i, gidx; + int i; HB_Buffer buf; GsubGposInfo *ginfo; HB_UShort *apply_order_save; @@ -892,8 +915,6 @@ drive_otf (MFLTFont *font, MFLTOtfSpec *spec, gpos_applied = 1; } - gidx = out->used; - for (i = 0; i < buf->in_length; i++) { HB_GlyphItem hg = buf->in_string + i; @@ -984,31 +1005,45 @@ close_font (MFLTFont *font) #else /* (defined (FLT_PANGO) */ typedef struct { + int count; + guint *indices; + PangoOTRuleset *ruleset; +} FeatureInfo; + +typedef struct { + FeatureInfo gsub; + FeatureInfo gpos; +} GsubGposInfo; + +typedef struct { MFLTFont font; - PangoFcFont pango_fc_font; + PangoFontMap *fontmap; + PangoContext *context; + PangoFcFont *pango_font; + MPlist *otf_spec_cache; } FontInfoPango; int get_glyph_id (MFLTFont *font, MFLTGlyph *g) { FontInfoPango *font_info = (FontInfoPango *) font; - PangoGlyph pg = pango_fc_font_get_glyph (font_info->pango_fc_font, g->c); + PangoGlyph glyph = pango_fc_font_get_glyph (font_info->pango_font, g->c); - return (pg ? (int) pg : -1); + return (glyph ? (int) glyph : -1); } int -get_metric (MFLTFont *font, MFLTGlyphString *gstring, int form, int to) +get_metric (MFLTFont *font, MFLTGlyphString *gstring, int from, int to) { FontInfoPango *font_info = (FontInfoPango *) font; - PangoFcFont fc_font = font_info->pango_fc_font; int i; for (i = from; i < to; i++) { + MFLTGlyph *g = gstring->glyphs + from; PangoRectangle inc, logical; - pango_font_get_glyph_extents ((PangoFont *) fc_font, + pango_font_get_glyph_extents (PANGO_FONT (font_info->pango_font), gstring->glyphs[i].code, &inc, &logical); g->lbearing = inc.x; g->rbearing = inc.x + inc.width; @@ -1019,6 +1054,221 @@ get_metric (MFLTFont *font, MFLTGlyphString *gstring, int form, int to) } } +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; + int err; + 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); + for (i = 0; i < info->count; i++) + pango_ot_ruleset_add_feature (info->ruleset, type, info->indices[i], + PANGO_OT_ALL_GLYPHS); +} + +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->xoff = glyph_info->geometry.x_offset; + g->yoff = glyph_info->geometry.y_offset; + g->xadv = glyph_info->geometry.width; + 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); + } + 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); +} + +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)); +} + #endif int diff --git a/m17n-imconf.c b/m17n-imconf.c index 90eb87f..24db13f 100644 --- a/m17n-imconf.c +++ b/m17n-imconf.c @@ -177,6 +177,9 @@ call_config_common (int (*func) (MSymbol, MSymbol, MSymbol, MPlist *), ERROR (error_invalid_arg); if (TAILP (arg)) arg = NULL; + else if (mplist_key (arg) == Mplist + && mplist_key ((MPlist *) mplist_value (arg)) == Mnil) + arg = (MPlist *) mplist_value (arg); if (func (lang, name, target, arg) < 0) ERROR (error_command_fail); return NULL; -- 1.7.10.4