+2007-10-12 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.pc.in: Don't require m17n-shell.
+
+2007-08-15 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.pc.in (prefix): New file.
+
+ * configure.ac (AC_CONFIG_FILES): Add m17n-flt.pc.
+
+ * Makefile.am (EXTRA_DIST): Add m17n-flt.pc.in.
+ (BASICDATA): Add m17n-flt.pc.
+
2007-07-13 Kenichi Handa <handa@m17n.org>
* Version 1.4.0 released.
bin_SCRIPTS = m17n-config
EXTRA_DIST = m4/ChangeLog config.rpath mkinstalldirs \
- m17n-core.pc.in m17n-shell.pc.in m17n-gui.pc.in bootstrap.sh
+ m17n-core.pc.in m17n-shell.pc.in m17n-flt.pc.in m17n-gui.pc.in bootstrap.sh
pkgconfigdir = ${libdir}/pkgconfig
-BASICDATA = m17n-core.pc m17n-shell.pc
+BASICDATA = m17n-core.pc m17n-shell.pc m17n-flt.pc
if WITH_GUI
PKGDATA = $(BASICDATA) m17n-gui.pc
else
m17n-config
m17n-core.pc
m17n-shell.pc
+ m17n-flt.pc
m17n-gui.pc
])
end
define xgstring
-set dump_gstring (gstring, 0)
+set dump_gstring (gstring, 0, 0)
+echo \n
+end
+
+define xgstr
+set dump_gstring ($arg0, 0, 1)
echo \n
end
+2007-10-29 Kenichi Handa <handa@m17n.org>
+
+ * Makefile.am (common_ldflags_gui): Add
+ ${top_builddir}/src/libm17n-flt.la.
+
+ * .gdb.util (xgstring): Adjusted for the change of dump_gstring.
+ (xgtr): New command.
+
+2007-09-18 Kenichi Handa <handa@m17n.org>
+
+ * mdump.c (main): Use "generic" fontset by default.
+
2007-07-13 Kenichi Handa <handa@m17n.org>
* Version 1.4.0 released.
endif
common_ldflags = ${top_builddir}/src/libm17n-core.la ${top_builddir}/src/libm17n.la
-common_ldflags_gui = ${common_ldflags} ${top_builddir}/src/libm17n-gui.la
+common_ldflags_gui = ${common_ldflags} ${top_builddir}/src/libm17n-flt.la ${top_builddir}/src/libm17n-gui.la
AM_CPPFLAGS=@CONFIG_FLAGS@
m17n_date_SOURCES = mdate.c
MDrawMetric rect;
char *filename = "output";
int len, from;
- char *fontset_name = "truetype";
+ char *fontset_name = "generic";
/* Parse the command line arguments. */
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+version=@PACKAGE_VERSION@
+
+Name: m17n-flt
+Description: FLT API suport of the m17n library.
+Version: ${version}
+Requires: m17n-core = ${version}
+Libs: -L${libdir} -lm17n-core -lm17n-flt
+Cflags: -I${includedir}
-2007-08-14 Kenichi Handa <handa@m17n.org>
+2007-11-12 Kenichi Handa <handa@ni.aist.go.jp>
+
+ * font-ft.c (ft_check_otf): Fix arg to OTF_check_features.
+
+ * m17n-flt.c (Mcombining): New variable.
+ (Mfont_facility): Renamed from Mfont_has. Referrer changed.
+ (enum FontLayoutCmdRuleSrcType): Delete SRC_EXIST, add
+ SRC_HAS_GLYPH and SRC_OTF_SPEC.
+ (FontLayoutCmdRule): Delete src.exist, add src.supported_glyph and
+ src.otf_spec.
+ (load_command): Adjusted for the above changes.
+ (run_rule): Likewise.
+ (combining_code_from_class): Delete it.
+ (mflt_get): Check flt->name against Mcombining, not Mt.
- * font-ft.c (mfont__ft_drive_otf): Fix arg to OTF_check_features.
+ * internal-flt.h (Mcombining): Extern it.
+
+ * draw.c (compose_glyph_string): Call run_flt with Mcombining for
+ combining characters.
+
+2007-11-09 Kenichi Handa <handa@ni.aist.go.jp>
+
+ * face.c (mface__realize): Reset measured flag before calling
+ mfont__get_metric.
+
+ * m17n-flt.c (run_stages): Fix handing of off_x and off_y.
+ (setup_combining_coverage): New function.
+ (setup_combining_flt): New function.
+ (mflt_get): If flt is not found, return NULL. If name if Mt,
+ call setup_combining_flt.
+ (mflt_run): For debugging, print font family name.
+
+ * font-ft.c (ft_render): Fix handling of baseline_offset.
+ (ft_encapsulate): Set metrics in 26.6 fixed pixel.
+ (ft_render): Check pixel_mode to determine anti_alias.
+
+ * m17n-X.c (xfont_find_metric): Delete invalid "continue" line.
+ (xfont_find_metric): Set metrics in 26.6 fixed pixel.
+ (xfont_render): Set baseline_offset in pixel.
+ (xft_render): Fix handling of baseline_offset.
+
+ * draw.c (run_flt): Set font.font.family.
+ (compose_glyph_string): Fix handling of combining characters.
+
+ * fontset.c (try_font_list): Check if the named flt is surely
+ available.
+
+2007-11-07 Kenichi Handa <handa@ni.aist.go.jp>
+
+ * draw.c (analyse_bidi_level): New function.
+ (visual_order): Do reordering using the already decided
+ bidi-level.
+ (compose_glyph_string): Decide bidi-level before calling flt.
+
+ * m17n-flt.c (mflt_run): Fix typo.
+
+ * font-ft.c (ft_drive_otf): Fix indexing gstring->glyphs.
+
+2007-11-06 Kenichi Handa <handa@ni.aist.go.jp>
+
+ * draw.c (visual_order): Don't rely on the width of glyphs.
+ (run_flt): Fix culculation of g->g.to.
+
+ * m17n-flt.c (run_rule): Don't set error code here.
+ (run_cond): Likewise.
+ (run_otf): Fix culculation of xoff and yoff.
+ (run_command): Don't set error code here.
+ (PREV): New macro.
+ (NEXT): New macro.
+
+ * m17n-X.c (xfont_open): Keep rfont's metrics in 26.6 fixed pixels.
+ (xfont_find_metric): Set glyph's yadv to 0.
+ (xft_find_metric): Likewise.
+
+ * font-ft.c (ft_open): Keep rfont's metrics in 26.6 fixed pixels.
+ (ft_find_metric): Adjust glyph's metrics.
+ (ft_encapsulate): Keep rfont's metrics in 26.6 fixed pixels.
+ (ft_drive_otf): Set mark glyph's xadv to 0.
+
+ * face.c (mface__for_chars): Adjusts the unit of face's ascent and
+ descent.
+
+2007-10-29 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.h (struct _MFLTOtfSpec): Adjusted for the new FLT handling.
+ (mflt_get): Adjusted for the argument change.
+ (mflt_name): Adjusted for the return value change.
+
+ * m17n-flt.c (Mgenerator, Mend): New variables.
+ (flt_min_coverage, flt_max_coverage): New variables.
+ (GCPY): New macro.
+ (GDUP): Use it.
+ (Mfont_has): Renamed from Mexist. Referrers chagned.
+ (gen_otf_tag): Handle the trailing whitespaces.
+ (otf_count_features, otf_store_features): Fix for negative features.
+ (parse_otf_command): Adjusted for the change of MFLTOtfSpec.
+ (load_otf_command): Likewise.
+ (free_flt_command): Adjusted for the change of MFLTOtfSpec.
+ (load_flt): Argument changed. Caller changed.
+ (free_flt_list): New function.
+ (run_rule): Adjusted for the change of FontLayoutContext.
+ (mflt_run): Adjusted for the change of FontLayoutContext.
+
+ * m17n-gui.c (m17n_init_win): Call m17n_init_flt.
+ (m17n_fini_win): Call m17n_fini_flt.
+
+ * m17n-gui.h: Include m17n-flt.h.
+
+ * m17n-gd.c: Adusted for the change of MGlyph.
+
+ * m17n-X.c: Adusted for the change of MGlyph.
+ (xft_check_otf, xft_drive_otf): New functions.
+
+ * internal-gui.h (MGlyph): Modified for new FLT handling.
+
+ * fontset.c (try_font_list): Adusted for the change of MGlyph.
+
+ * font-ft.c: Adjusted for the change of MGlyph.
+ (ft_check_cap_otf): Renamed from ft_check_otf. Callers changed.
+ (get_glyph_metric): Deleted.
+ (ft_check_otf): New function.
+ (ft_drive_otf): New fucntion.
+
+ * font.c: Adjusted for the change of MGlyph.
+ (mfont__init): Don't call mfont__flt_init.
+ (mfont__fini): Don't call mfont__flt_fini.
+ (mfont__get_glyph_id, mfont__get_metrics): New functions.
+
+ * font.h (struct MRealizedFont): New members x_ppem and y_ppem.
+ (MFLTFontForRealized): New struct.
+ (struct MFontDriver): New members check_otf and drive_otf.
+ (mfont__get_glyph_id, mfont__get_metrics): Extern them.
+
+ * face.c: Adjusted for the change of MGlyph.
+
+ * draw.c: Adjusted for the change of MGlyph.
+
+ * m17n.c (m17n_init): Don't call mchar_init.
+
+ * m17n-core.c (m17n_init_core): Call mchar_init.
+
+ * m17n-core.h (mchartable_min_char, mchartable_max_char): Extern them.
+
+ * input.c: Include "m17n.h" instead of "m17n-gui.h".
+
+ * chartab.c (mchartable): Initialize table->min_char to -1.
+ (mchartable_min_char): New function.
+ (mchartable_max_char): New function.
+
+ * Makefile.am (GUI_SOURCES): Delete font-flt.c.
+ (libm17n_gui_la_LIBADD): Add ${top_builddir}/src/libm17n-flt.la.
+
+2007-10-12 Kenichi Handa <handa@m17n.org>
+
+ * m17n-core.h (Mcharset): Extern it.
+ Move detabase related declarations from m17n.h.
+
+ * m17n-flt.h: Include m17n-core.h instead of m17n.h.
+ (struct _MFLTOtfFeatures): New struct.
+ (struct _MFLTOtfSpec): Delete gsub, gpos, etc, add gsub_gpos.
+ (struct _MFLTFont): Delete otf, add check_otf.
+ (MCHAR_INVALID_CODE): Define it.
+
+ * plist.c (read_mtext_element): Simplify the code.
+
+ * m17n.h: Move database related declarations to m17n-core.h
+ (Mharset): Don't extern it.
+
+ * m17n.c (m17n_init): Don't call mdatabase__init.
+
+ * m17n-gd.c (read_rgb_txt): Check also /etc/X11/rgb.txt. Downcase
+ color names.
+
+ * m17n-flt.c: Include m17n-core.h instead of m17n.h.
+ (Mexist): New variable.
+ (enum FontLayoutCmdRuleSrcType): New enum SRC_EXIST.
+ (FontLayoutCmdRule): New member src.exist.
+ (parse_otf_command): Handle gsub_count and gpos_count separately.
+ (load_otf_command): Adjusted for the change of MFLTOtfSpec.
+ (load_command): Handle the command "exist".
+ (free_flt_command): Adjusted for the change of MFLTOtfSpec.
+ (run_rule): Handle the case SRC_EXIST.
+ (run_otf): Adjusted for the change of MFLTOtfSpec.
+ (run_command): Check the range of FROM.
+ (check_otf_spec): Delete it.
+ (m17n_init_flt): Call m17n_init_core instead of m17n_init.
+ Initialize Mexist.
+ (m17n_fini_flt): Call m17n_fini_core instead of m17n_fiini.
+ (mflt_find): Call font->check_otf instead of check_otf_spec.
+ (mflt_run): Keep the metrics in 26.6 fixed point.
+
+ * m17n-core.c (mdatabase__finder, mdatabase__loader): Delete them.
+ (m17n_init_core): Call mdatabase__init.
+
+ * m17n-X.c (device_open): Use mplist_add, not mplist_push.
+
+ * internal.h (mdatabase__finder, mdatabase__loader): Delete externs
+ of them.
+
+ * font-flt.c (Mexist): New variable.
+ (enum FontLayoutCmdRuleSrcType): New enum SRC_EXIST.
+ (FontLayoutCmdRule): New member src.exist.
+ (load_category_table): Use isalnum, not isalpha.
+ (load_command): Check the command "exist".
+ (run_rule): Hande the case SRC_EXIST.
+ (run_command): Check the range of FROM.
+ (mfont__flt_init): Initialize Mexist.
+
+ * draw.c (layout_glyphs): Fix calculation of off_x and off_y.
+
+ * database.h (mdatabase__load_charset_func): Extern it.
+
+ * database.c: Include m17n-core.h instead of m17n.h.
+ (load_chartable): Use mtext__from_data.
+ (load_charset): Moved to charset.c
+ (load_database): Call mdatabase__load_charset_func instead of
+ load_charset.
+ (mdatabase__load_charset_func): New variable.
+ (mdatabase__init): Initialize mdatabase__load_charset_func and
+ Mcharset. Don't set mdatabase__finder and mdatabase__loader.
+ (mdatabase__save): Use fwrite, not mconv_encode_stream.
+ (Mcharset): Declare it here.
+
+ * charset.c: Include "database.h.".
+ (load_charset): Moved from database.c.
+ (mcharset__init): Initialize mdatabase__load_charset_func, don't
+ initialize Mcharset.
+
+ * character.c (mchar_define_property): Call mdatabase_find directly.
+ (mchar_get_prop): Call mdatabase_add directly.
+ (mchar_put_prop): Call mdatabase_load directly.
+ (mchar_get_prop_table): Likewise.
+
+ * Makefile.am (libm17n_core_la_SOURCES): Add database.[ch].
+ (libm17n_la_SOURCES): Remove database.[ch].
+ (libm17n_flt_la_LIBADD): Delete libm17n.la, add libm17n-core.la.
+
+2007-09-18 Kenichi Handa <handa@m17n.org>
+
+ * face.c (mface__realize): Try Freetype based font at first.
+
+ * font.c: Include <ctype.h>
+
+2007-09-16 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.c (load_flt): New arg full. If full is zero, load only
+ coverage.
+ (run_otf): Call font->get_metrics, not font->get_metric.
+ (run_stages): Likewise.
+ (CHECK_FLT_COVERAGE): New macro.
+ (CHECK_FLT_STAGES): Call load_flt with the second arg 1.
+ (check_otf_spec): New function.
+ (m17n_fini_flt): Unref flt->coverage.
+ (mflt_find): Argument changed.
+ (mflt_name): New function.
+ (mflt_coverage): Use CHECK_FLT_COVERAGE.
+
+ * m17n-flt.h (MFLTFont): Member get_metrics renamed from get_metric.
+ (mflt_find): Prototype adjusted.
+ (mflt_name): Extern it.
+
+2007-09-14 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.h (struct _MFLTGlyph): Change signedness of members.
+
+ * font-flt.c (run_otf): Make debug info printing comaptible with
+ that of m17n-flt.c.
+ (run_command): Likewise.
+ (mfont__flt_run): Likewise.
+
+ * m17n-flt.c (UPDATE_CLUSTER_RANGE): ctx->cluster_begin_idx is
+ invalid only when it's negative.
+ (run_otf): Likewise.
+ (run_command): Likewise.
+ (mflt_run): Initialize ctx.cluster_begin_idx to -1.
+
+2007-09-10 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.h (struct _MFLTGlyph): New member encoded and measured.
+ (struct _MFLTFont): Prototype of get_glyph_id changed.
+
+ * m17n-flt.c (enum GlyphInfoMask): Delete EncodedMask and
+ PositionedMask.
+ (GAPPEND): Delete this macro.
+ (GET_ENCODED, SET_ENCODED, GET_MEASURED, SET_MEASURED): Adjusted
+ for the change of MFLTGlyph. Caller changed.
+ (run_otf): Simply calls font->get_glyph_id.
+ (run_command): Reset g->encoded and g->measured for direct code.
+ (positioning): Delete this function.
+ (run_stages): Simply calls font->get_glyph_id and font->get_metric.
+
+2007-09-07 Kenichi Handa <handa@m17n.org>
+
+ * draw.c (compose_glyph_string): Improve script detection.
+
+2007-09-06 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.h (mflt_get): Extern it.
+
+ * m17n-flt.c (run_stages): Call positioning only if
+ font->get_metric is non-NULL.
+ (CHECK_FLT_STAGES): Fix typo.
+ (mflt_get): New function.
+
+ * font-flt.c (mfont__flt_run): Improve debug info printing.
+
+2007-09-04 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.c (MFontLayoutTable): Delete this type.
+ (struct _MFLT): New member mdb and coverage.
+ (list_flt): Set flt->mdb.
+ (load_generator): Argument and return value changed. Caller
+ changed.
+ (get_font_layout_table): Delete this function.
+ (run_stages): Argument changed. Caller changed.
+ (CHECK_FLT_STAGES): New macro.
+ (mfont__flt_encode_char): Argument changed.
+ (mflt_find): Likewise.
+ (mflt_coverage): New function.
+ (mflt_run): Argument changed.
+ (mdebug_dump_flt): Likewise.
+
+ * m17n-flt.h (mflt_coverage): Extern it.
+ (mflt_find): Prototype adjusted.
+
+2007-09-03 Kenichi Handa <handa@m17n.org>
+
+ * internal.h (MTABLE_CALLOC_SAFE, MSTRUCT_CALLOC_SAFE): New macros.
+
+ * database.c (mdatabase__props): New function.
+
+ * database.h (mdatabase__props): Extern it.
+
+ * m17n-flt.h (struct _MFLTGlyphString): Delete user_data, add
+ script and langsys.
+ (struct _MFLTFont): Add suitable_p.
+ (mflt_find): Extern it.
+
+ * m17n-flt.c: Include "database.h".
+ (struct _MFLT): New struct.
+ (list_flt): New function.
+ (load_flt): Don't update flt_list.
+ (get_font_layout_table): Use flt_list.
+ (m17n_init_flt): Don't initialize flt_list.
+ (m17n_fini_flt): Adjusted for the change of flt_list.
+ (mflt_find): New function.
+ (mflt_run): Fix debug printing.
+
+2007-08-23 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.c (run_otf): Remove #ifdef HAVE_OTF and #endi.
+ (run_stages): Print separator in encoded string as "|".
+
+2007-08-23 Kenichi Handa <handa@m17n.org>
+
+ * font-flt.c (mfont__flt_run): Don't calculate a glyph metric if
+ the glyph is already handled by OTF.
+
+2007-08-21 Kenichi Handa <handa@m17n.org>
+
+ * font-ft.c (ft_check_capability): Check cap->script_tag at first.
+
+2007-08-20 Kenichi Handa <handa@m17n.org>
+
+ * font-flt.c (mfont__flt_run): Get glyph metrics before printing
+ debug information.
+
+2007-08-17 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.h (struct _MFLTGlyphString): Member pointer renamed to
+ user_data.
+ (MFLTOtfSpec): Renamed from MFLT_OTF_Spec.
+ (MFLTFont): Prototype of the member drive_otf adjusted.
+
+ * m17n-flt.c (run_stages): Fix handling of padding.
+
+ * font-ft.c (get_glyph_metric): New function.
+ (DEVICE_DELTA): Return 26.6 fixed point value.
+ (adjust_anchor): Likewise.
+ (mfont__ft_drive_otf): Use get_glyph_metric.
+
+ * font-flt.c (mfont__flt_run): Pay attention to padding on
+ printing debug info.
+
+2007-08-16 Kenichi Handa <handa@m17n.org>
+
+ * m17n-flt.c (run_stages): Fix typo.
+
+ * font-ft.c (adjust_anchor): Argument changed. Calculte based on
+ 26.6 fixed point.
+ (mfont__ft_drive_otf): Don't call OTF_check_features for GPOS.
+ Adjusted for the argument change of adjust_anchor. Calculte based
+ on 26.6 fixed point.
+
+2007-08-15 Kenichi Handa <handa@m17n.org>
+
+ * charset.c (mcharset__load_from_database): Set mdebug_flag
+ instead of mdebug_mask.
+
+ * coding.c (mcoding__load_from_database): Set mdebug_flag instead
+ of mdebug_mask.
+
+ * database.c (load_database): Set mdebug_flag instead of
+ mdebug_mask.
+ (mdatabase__load_for_keys): Likewise.
+
+ * draw.c: Include "internal-flt.h".
+ (dump_combining_code): Don't subtract 128 from combining code
+ off_x/y.
+
+ * font-flt.c: Include "internal-flt.h". Set mdebug_flag instead
+ of mdebug_mask.
+ (run_rule): Print debug info only when MDEBUG_FLAG is greater than
+ 2.
+ (run_cond): Likewise.
+ (run_otf): Likewise.
+ (run_command): Likewise.
+ (mfont__flt_run): Change format of debug info.
+
+ * font-ft.c: Include "internal-flt.h".
+ Set mdebug_flag instead of mdebug_mask.
+ (mfont__ft_drive_otf): Fix arg to OTF_check_features.
+
+ * input.c: Set mdebug_flag instead of mdebug_mask.
+ (shift_state): New MDEBUG_FLAG macro.
+ (preedit_commit): Likewise.
+ (filter): Likewise.
+
+ * internal-flt.h: New file.
+
+ * internal-gui.h (MAKE_COMBINING_CODE, COMBINING_CODE_OFF_Y)
+ (COMBINING_CODE_OFF_X, COMBINING_CODE_BASE_X)
+ (COMBINING_CODE_BASE_Y, COMBINING_CODE_ADD_X)
+ (COMBINING_CODE_ADD_Y, MAKE_COMBINING_CODE_BY_CLASS)
+ (COMBINING_BY_CLASS_P, COMBINING_CODE_CLASS)
+ (MAKE_PRECOMPUTED_COMBINDING_CODE, COMBINING_PRECOMPUTED_P): Move
+ these macros to internal-flt.h.
+
+ * internal.h (M17N_OBJECT_ADD_ARRAY): Adjusted for the change of
+ mdebug__flags.
+ (M17N_OBJECT_REGISTER, M17N_OBJECT_UNREGISTER): Likewise.
+ (enum MDebugMaskBit): Delete this enum.
+ (enum MDebugFlag): New enum.
+ (mdebug__flag): Don't extern it.
+ (mdebug__flags): Extern it.
+ (MDEBUG_FLAG): New macro.
+ (MDEBUG_PRINT0): Use the macro MDEBUG_FLAG.
+ (MDEBUG_DUMP, MDEBUG_PUSH_TIME, MDEBUG_POP_TIME)
+ (MDEBUG_PRINT_TIME): Likewise.
+
+ * m17n-X.c (xfont_open): Set mdebug_flag instead of mdebug_mask.
+ (xfont_list): Likewise.
+
+ * m17n-core.c (mdebug__flag): Delete this variable.
+ (mdebug__flags): New variable.
+ (SET_DEBUG_FLAG): Make it a function.
+ (m17n_init_core): Set mdebug_flag instead of mdebug_mask.
+ (m17n_fini_core): Likewise.
+
+ * m17n-gui.c (m17n_init_win): Set mdebug_flag instead of mdebug_mask.
+ (m17n_fini_win): Likewise.
+
+ * m17n-misc.h (enum MErrorCode): Add MERROR_FLT.
+
+ * m17n.c (m17n_init): Set mdebug_flag instead of mdebug_mask.
+ (m17n_fini): Likewise.
+
+ * symbol.c (msymbol__free_table): Adjusted for the change of
+ mdebug__flags.
+
+ * Makefile.am (BASICBUILDS): Add libm17n-flt.la.
+ (BASICHEADERS): Add m17n-flt.h.
+ (FLT_SOURCES): New variable.
+ (libm17n_flt_la_SOURCES, libm17n_flt_la_LIBADD)
+ (libm17n_flt_la_LDFLAGS): Likewise.
+
+ * m17n-flt.h: New file.
+
+ * m17n-flt.c: New file created by modifying font-flt.c.
2007-07-13 Kenichi Handa <handa@m17n.org>
VINFO = -version-info @API_VERSION@
-BASICBUILDS = libm17n-core.la libm17n.la
+BASICBUILDS = libm17n-core.la libm17n.la libm17n-flt.la
if WITH_GUI
BUILD_LIBS = $(BASICBUILDS) libm17n-gui.la libm17n-X.la libm17n-gd.la
else
libm17n_core_la_SOURCES = \
character.h character.c \
chartab.h chartab.c \
+ database.h database.c \
internal.h \
plist.h plist.c \
m17n-core.h m17n-core.c \
libm17n_la_SOURCES = \
charset.h charset.c \
coding.h coding.c \
- database.h database.c \
input.h input.c \
language.h language.c \
mlocale.h locale.c \
libm17n_la_LIBADD = ${top_builddir}/src/libm17n-core.la -ldl
libm17n_la_LDFLAGS = -export-dynamic ${VINFO}
+FLT_SOURCES = \
+ m17n-flt.h m17n-flt.c
+
+libm17n_flt_la_SOURCES = ${FLT_SOURCES}
+libm17n_flt_la_LIBADD = ${top_builddir}/src/libm17n-core.la
+libm17n_flt_la_LDFLAGS = -export-dynamic ${VINFO}
+
GUI_SOURCES = \
face.h face.c \
- font.h font.c font-ft.c font-flt.c \
+ font.h font.c font-ft.c \
fontset.h fontset.c \
draw.c \
input-gui.c \
@FONTCONFIG_LD_FLAGS@
libm17n_gui_la_SOURCES = ${GUI_SOURCES}
-libm17n_gui_la_LIBADD = ${OPTIONAL_LD_FLAGS} ${top_builddir}/src/libm17n.la
+libm17n_gui_la_LIBADD = ${OPTIONAL_LD_FLAGS} ${top_builddir}/src/libm17n-flt.la ${top_builddir}/src/libm17n.la
libm17n_gui_la_LDFLAGS = -export-dynamic ${VINFO}
X_LD_FLAGS = ${X_PRE_LIBS} ${X_LIBS} @X11_LD_FLAGS@ ${X_EXTRA_LIBS}
AM_CPPFLAGS = -DM17NDIR=\"@M17NDIR@\" -DGETTEXTDIR=\"@GETTEXTDIR@\"
-BASICHEADERS = m17n-core.h m17n.h m17n-misc.h
+BASICHEADERS = m17n-core.h m17n.h m17n-misc.h m17n-flt.h
if WITH_GUI
include_HEADERS = $(BASICHEADERS) m17n-gui.h m17n-X.h
else
MSymbol key = msymbol (name);
void *mdb;
- if (mdatabase__finder)
- mdb = (*mdatabase__finder) (Mchar_table, type, key, Mnil);
- else
- mdb = NULL;
+ mdb = mdatabase_find (Mchar_table, type, key, Mnil);
+ if (! mdb)
+ return Mnil;
mchar__define_prop (key, type, mdb);
return key;
}
return NULL;
if (record->mdb)
{
- record->table = (*mdatabase__loader) (record->mdb);
+ record->table = mdatabase_load (record->mdb);
if (! record->table)
MERROR (MERROR_DB, NULL);
record->mdb = NULL;
return -1;
if (record->mdb)
{
- record->table = (*mdatabase__loader) (record->mdb);
+ record->table = mdatabase_load (record->mdb);
if (! record->table)
MERROR (MERROR_DB, -1);
record->mdb = NULL;
return NULL;
if (record->mdb)
{
- record->table = (*mdatabase__loader) (record->mdb);
+ record->table = mdatabase_load (record->mdb);
if (! record->table)
MERROR (MERROR_DB, NULL);
record->mdb = NULL;
#include "m17n-misc.h"
#include "internal.h"
#include "symbol.h"
-#include "charset.h"
-#include "coding.h"
+#include "database.h"
#include "chartab.h"
#include "plist.h"
+#include "charset.h"
+#include "coding.h"
static int unified_max;
return 0;
}
+/** Load a data of type @c charset from the file FD. */
+
+static void *
+load_charset (FILE *fp, MSymbol charset_name)
+{
+ MCharset *charset = MCHARSET (charset_name);
+ int *decoder;
+ MCharTable *encoder;
+ int size;
+ int i, c;
+ int found = 0;
+ MPlist *plist;
+
+ if (! charset)
+ MERROR (MERROR_DB, NULL);
+ size = (charset->code_range[15]
+ - (charset->min_code - charset->code_range_min_code));
+ MTABLE_MALLOC (decoder, size, MERROR_DB);
+ for (i = 0; i < size; i++)
+ decoder[i] = -1;
+ encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
+
+ while ((c = getc (fp)) != EOF)
+ {
+ unsigned code1, code2, c1, c2;
+ int idx1, idx2;
+ char buf[256];
+
+ ungetc (c, fp);
+ fgets (buf, 256, fp);
+ if (c != '#')
+ {
+ if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
+ {
+ idx1 = CODE_POINT_TO_INDEX (charset, code1);
+ if (idx1 >= size)
+ continue;
+ idx2 = CODE_POINT_TO_INDEX (charset, code2);
+ if (idx2 >= size)
+ idx2 = size - 1;
+ c2 = c1 + (idx2 - idx1);
+ }
+ else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
+ {
+ idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
+ if (idx1 >= size)
+ continue;
+ c2 = c1;
+ }
+ else
+ continue;
+ if (idx1 >= 0 && idx2 >= 0)
+ {
+ decoder[idx1] = c1;
+ mchartable_set (encoder, c1, (void *) code1);
+ for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
+ {
+ code1 = INDEX_TO_CODE_POINT (charset, idx1);
+ decoder[idx1] = c1;
+ mchartable_set (encoder, c1, (void *) code1);
+ }
+ found++;
+ }
+ }
+ }
+
+ if (! found)
+ {
+ free (decoder);
+ M17N_OBJECT_UNREF (encoder);
+ return NULL;
+ }
+ plist = mplist ();
+ mplist_add (plist, Mt, decoder);
+ mplist_add (plist, Mt, encoder);
+ return plist;
+}
+
\f
/* Internal API */
unified_max = MCHAR_MAX;
+ mdatabase__load_charset_func = load_charset;
mcharset__cache = mplist ();
mplist_set (mcharset__cache, Mt, NULL);
memset (mcharset__iso_2022_table.classified, 0,
sizeof (mcharset__iso_2022_table.classified));
- Mcharset = msymbol ("charset");
-
Mmethod = msymbol ("method");
Moffset = msymbol ("offset");
Mmap = msymbol ("map");
MDatabase *mdb = mdatabase_find (msymbol ("charset-list"), Mnil, Mnil, Mnil);
MPlist *def_list, *plist;
MPlist *definitions = charset_definition_list;
- int mdebug_mask = MDEBUG_CHARSET;
+ int mdebug_flag = MDEBUG_CHARSET;
if (! mdb)
return 0;
#define MCHAR_INVALID_CODE
#endif
-/*=*/
-/***en
- @brief The symbol @c Mcharset.
-
- Any decoded M-text has a text property whose key is the predefined
- symbol @c Mcharset. The name of @c Mcharset is
- <tt>"charset"</tt>. */
-
-/***ja
- @brief ¥·¥ó¥Ü¥ë @c Mcharset.
-
- ¥Ç¥³¡¼¥É¤µ¤ì¤¿ M-text ¤Ï¡¢¥¡¼¤¬ @c Mcharset
- ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡£
- ¥·¥ó¥Ü¥ë @c Mcharset ¤Ï <tt>"charset"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£ */
-MSymbol Mcharset;
/*=*/
/***en
M17N_OBJECT (table, free_chartable, MERROR_CHARTABLE);
M17N_OBJECT_REGISTER (chartable_table, table);
table->key = key;
- table->min_char = 0;
+ table->min_char = -1;
table->max_char = -1;
SET_DEPTH_MIN_CHAR (&table->subtable, 0, 0);
table->subtable.default_value = default_value;
/*=*/
/***en
+ @brief Return the minimum character whose value is set in a chartabe.
+
+ The mchartable_min_char () function return the minimum character
+ whose value is set in chartable $TABLE. No character is set its
+ value, the function returns -1.
+ */
+
+int
+mchartable_min_char (MCharTable *table)
+{
+ return table->min_char;
+}
+
+/*=*/
+
+/***en
+ @brief Return the maximum character whose value is set in a chartabe.
+
+ The mchartable_max_char () function return the maximum character
+ whose value is set in chartable $TABLE. No character is set its
+ value, the function returns -1.
+ */
+
+int
+mchartable_max_char (MCharTable *table)
+{
+ return table->max_char;
+}
+
+/*=*/
+
+/***en
@brief Return the assigned value of a character in a chartable.
The mchartable_lookup () function returns the value assigned to
MDatabase *mdb = mdatabase_find (msymbol ("coding-list"), Mnil, Mnil, Mnil);
MPlist *def_list, *plist;
MPlist *definitions = coding_definition_list;
- int mdebug_mask = MDEBUG_CODING;
+ int mdebug_flag = MDEBUG_CODING;
if (! mdb)
return 0;
#include <time.h>
#include <libgen.h>
-#include "m17n.h"
+#include "m17n-core.h"
#include "m17n-misc.h"
#include "internal.h"
#include "mtext.h"
#include "character.h"
-#include "charset.h"
#include "database.h"
-#include "coding.h"
#include "plist.h"
/** The file containing a list of databases. */
/* VAL is an M-text. */
MText *mt;
if (c == '"')
- mt = mconv_decode_buffer (Mcoding_utf_8,
- (unsigned char *) (buf + i),
- len - i - 1);
+ mt = mtext__from_data (buf + i, len - i - 1, MTEXT_FORMAT_UTF_8, 1);
else
{
mt = mtext ();
}
-/** Load a data of type @c charset from the file FD. */
-
-static void *
-load_charset (FILE *fp, MSymbol charset_name)
-{
- MCharset *charset = MCHARSET (charset_name);
- int *decoder;
- MCharTable *encoder;
- int size;
- int i, c;
- int found = 0;
- MPlist *plist;
-
- if (! charset)
- MERROR (MERROR_DB, NULL);
- size = (charset->code_range[15]
- - (charset->min_code - charset->code_range_min_code));
- MTABLE_MALLOC (decoder, size, MERROR_DB);
- for (i = 0; i < size; i++)
- decoder[i] = -1;
- encoder = mchartable (Minteger, (void *) MCHAR_INVALID_CODE);
-
- while ((c = getc (fp)) != EOF)
- {
- unsigned code1, code2, c1, c2;
- int idx1, idx2;
- char buf[256];
-
- ungetc (c, fp);
- fgets (buf, 256, fp);
- if (c != '#')
- {
- if (sscanf (buf, "0x%x-0x%x 0x%x", &code1, &code2, &c1) == 3)
- {
- idx1 = CODE_POINT_TO_INDEX (charset, code1);
- if (idx1 >= size)
- continue;
- idx2 = CODE_POINT_TO_INDEX (charset, code2);
- if (idx2 >= size)
- idx2 = size - 1;
- c2 = c1 + (idx2 - idx1);
- }
- else if (sscanf (buf, "0x%x 0x%x", &code1, &c1) == 2)
- {
- idx1 = idx2 = CODE_POINT_TO_INDEX (charset, code1);
- if (idx1 >= size)
- continue;
- c2 = c1;
- }
- else
- continue;
- if (idx1 >= 0 && idx2 >= 0)
- {
- decoder[idx1] = c1;
- mchartable_set (encoder, c1, (void *) code1);
- for (idx1++, c1++; idx1 <= idx2; idx1++, c1++)
- {
- code1 = INDEX_TO_CODE_POINT (charset, idx1);
- decoder[idx1] = c1;
- mchartable_set (encoder, c1, (void *) code1);
- }
- found++;
- }
- }
- }
-
- if (! found)
- {
- free (decoder);
- M17N_OBJECT_UNREF (encoder);
- return NULL;
- }
- plist = mplist ();
- mplist_add (plist, Mt, decoder);
- mplist_add (plist, Mt, encoder);
- return plist;
-}
-
static char *
gen_database_name (char *buf, MSymbol *tags)
{
void *value;
char *filename = get_database_file (db_info, NULL, NULL);
FILE *fp;
- int mdebug_mask = MDEBUG_DATABASE;
+ int mdebug_flag = MDEBUG_DATABASE;
char buf[256];
MDEBUG_PRINT1 (" [DB] <%s>", gen_database_name (buf, tags));
if (tags[0] == Mchar_table)
value = load_chartable (fp, tags[1]);
else if (tags[0] == Mcharset)
- value = load_charset (fp, tags[1]);
+ {
+ if (! mdatabase__load_charset_func)
+ MERROR (MERROR_DB, NULL);
+ value = (*mdatabase__load_charset_func) (fp, tags[1]);
+ }
else
value = mplist__from_file (fp, NULL);
fclose (fp);
/** List of database directories. */
MPlist *mdatabase__dir_list;
+void *(*mdatabase__load_charset_func) (FILE *fp, MSymbol charset_name);
+
int
mdatabase__init ()
{
MDatabaseInfo *dir_info;
char *path;
+ mdatabase__load_charset_func = NULL;
+
Mchar_table = msymbol ("char-table");
+ Mcharset = msymbol ("charset");
Masterisk = msymbol ("*");
Mversion = msymbol ("version");
mplist_push (mdatabase__dir_list, Mt, get_dir_info (NULL));
}
- mdatabase__finder = ((void *(*) (MSymbol, MSymbol, MSymbol, MSymbol))
- mdatabase_find);
- mdatabase__loader = (void *(*) (void *)) mdatabase_load;
-
mdatabase__list = mplist ();
mdatabase__update ();
return 0;
MPlist *
mdatabase__load_for_keys (MDatabase *mdb, MPlist *keys)
{
- int mdebug_mask = MDEBUG_DATABASE;
+ int mdebug_flag = MDEBUG_DATABASE;
MDatabaseInfo *db_info;
char *filename;
FILE *fp;
M17N_OBJECT_UNREF (mt);
return -1;
}
- mconv_encode_stream (msymbol ("utf-8"), mt, fp);
- M17N_OBJECT_UNREF (mt);
+ if (mt->format > MTEXT_FORMAT_UTF_8)
+ mtext__adjust_format (mt, MTEXT_FORMAT_UTF_8);
+ fwrite (MTEXT_DATA (mt), 1, mtext_nchars (mt), fp);
fclose (fp);
+ M17N_OBJECT_UNREF (mt);
if ((ret = rename (db_info->uniq_file, file)) < 0)
unlink (db_info->uniq_file);
free (db_info->uniq_file);
return 0;
}
+MPlist *
+mdatabase__props (MDatabase *mdb)
+{
+ MDatabaseInfo *db_info;
+
+ if (mdb->loader != load_database)
+ return NULL;
+ db_info = mdb->extra_info;
+ return db_info->properties;
+}
+
/*** @} */
#endif /* !FOR_DOXYGEN || DOXYGEN_INTERNAL_MODULE */
\f
/* External API */
+/*** @addtogroup m17nCharset */
+/*** @{ */
+
+/***en
+ @brief The symbol @c Mcharset.
+
+ Any decoded M-text has a text property whose key is the predefined
+ symbol @c Mcharset. The name of @c Mcharset is
+ <tt>"charset"</tt>. */
+
+/***ja
+ @brief ¥·¥ó¥Ü¥ë @c Mcharset.
+
+ ¥Ç¥³¡¼¥É¤µ¤ì¤¿ M-text ¤Ï¡¢¥¡¼¤¬ @c Mcharset
+ ¤Ç¤¢¤ë¤è¤¦¤Ê¥Æ¥¥¹¥È¥×¥í¥Ñ¥Æ¥£¤ò»ý¤Ä¡£
+ ¥·¥ó¥Ü¥ë @c Mcharset ¤Ï <tt>"charset"</tt> ¤È¤¤¤¦Ì¾Á°¤ò»ý¤Ä¡£ */
+
+MSymbol Mcharset;
+/*=*/
+/*** @} */
+/*=*/
+
/*** @addtogroup m17nDatabase */
/*** @{ */
extern int mdatabase__unlock (MDatabase *mdb);
+extern MPlist *mdatabase__props (MDatabase *mdb);
+
+extern void *(*mdatabase__load_charset_func) (FILE *fp, MSymbol charset_name);
+
#endif /* not _M17N_DATABASE_H_ */
#include "mtext.h"
#include "textprop.h"
#include "internal-gui.h"
+#include "internal-flt.h"
#include "face.h"
#include "font.h"
static MSymbol MbidiS;
static MSymbol MbidiNSM;
-static void
-visual_order (MGlyphString *gstring)
+static int
+analyse_bidi_level (MGlyphString *gstring)
{
int len = gstring->used - 2;
- MGlyph *glyphs;
int bidi_sensitive = gstring->control.orientation_reversed;
+ int max_level;
MGlyph *g;
int i;
#ifdef HAVE_FRIBIDI
FriBidiCharType base = bidi_sensitive ? FRIBIDI_TYPE_RTL : FRIBIDI_TYPE_LTR;
FriBidiChar *logical = alloca (sizeof (FriBidiChar) * len);
- FriBidiChar *visual;
- FriBidiStrIndex *indices;
FriBidiLevel *levels;
+ FriBidiStrIndex *indices;
#else /* not HAVE_FRIBIDI */
int *logical = alloca (sizeof (int) * len);
- int *indices;
char *levels = alloca (len);
memset (levels, 0, sizeof (int) * len);
#endif /* not HAVE_FRIBIDI */
)
{
- MSymbol bidi = (MSymbol) mchar_get_prop (g->c, Mbidi_category);
+ MSymbol bidi = (MSymbol) mchar_get_prop (g->g.c, Mbidi_category);
if (bidi == MbidiR || bidi == MbidiAL
|| bidi == MbidiRLE || bidi == MbidiRLO)
levels[i] = 1;
#endif /* not HAVE_FRIBIDI */
}
- logical[i] = g->c;
+ logical[i] = g->g.c;
}
if (! bidi_sensitive)
- return;
+ return 0;
- glyphs = alloca (sizeof (MGlyph) * len);
- memcpy (glyphs, gstring->glyphs + 1, sizeof (MGlyph) * len);
#ifdef HAVE_FRIBIDI
- visual = alloca (sizeof (FriBidiChar) * (len + 1));
- indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
levels = alloca (sizeof (FriBidiLevel) * (len + 1));
+ indices = alloca (sizeof (FriBidiStrIndex) * (len + 1));
- fribidi_log2vis (logical, len, &base, visual, indices, NULL, levels);
-#else /* not HAVE_FRIBIDI */
- indices = alloca (sizeof (int) * len);
- for (i = 0; i < len; i++)
+ fribidi_log2vis (logical, len, &base, NULL, NULL, indices, levels);
+#endif /* not HAVE_FRIBIDI */
+
+ MGLYPH (0)->bidi_level = 0;
+ max_level = 0;
+ for (g = MGLYPH (1), i = 0; i < len; g++, i++)
{
- if (levels[i])
+ g->bidi_level = levels[i];
+ if (max_level < g->bidi_level)
+ max_level = g->bidi_level;
+ }
+ MGLYPH (i)->bidi_level = 0;
+ return max_level;
+}
+
+static void
+visual_order (MGlyphString *gstring)
+{
+ MGlyph *glyphs = alloca (sizeof (MGlyph) * gstring->used);
+ int i, j, gidx;
+
+ memcpy (glyphs, gstring->glyphs, sizeof (MGlyph) * gstring->used);
+
+ for (i = gidx = 0; i < gstring->used; gidx++)
+ {
+ int level = glyphs[i].bidi_level;
+
+ gstring->glyphs[gidx] = glyphs[i];
+ glyphs[i].rface = NULL;
+
+ if (level % 2)
{
- int j, k;
+ int prev_level = glyphs[i - 1].bidi_level;
- for (j = i + 1; j < len && levels[j]; j++);
- for (k = j--; i < k; i++, j--)
- indices[i] = j;
- i--;
+ if (prev_level == level)
+ i--;
+ else if (prev_level > level)
+ {
+ for (; glyphs[i - 1].bidi_level > level; i--);
+ if (glyphs[i].bidi_level % 2)
+ for (level = glyphs[i].bidi_level;
+ glyphs[i + 1].bidi_level == level; i++);
+ }
+ else
+ for (i++; ! glyphs[i].rface; i++);
}
else
- indices[i] = i;
- }
-#endif /* not HAVE_FRIBIDI */
+ {
+ int next_level = glyphs[i + 1].bidi_level;
- for (i = 0; i < len;)
- {
- /* Index into gstring->glyphs plus 1 for GLYPHS[i]. */
- int j = indices[i];
- /* Length of grapheme-cluster */
- int seglen;
+ if (next_level == level)
+ i++;
+ else if (next_level > level)
+ {
+ for (; glyphs[i + 1].bidi_level > level; i++);
+ if ((glyphs[i].bidi_level % 2) == 0)
+ for (level = glyphs[i].bidi_level;
+ glyphs[i - 1].bidi_level == level; i--);
+ }
+ else
+ {
+ int save = i + 1;
- g = glyphs + i;
-#ifdef HAVE_FRIBIDI
- if (visual[j] != logical[i])
- {
- /* Mirrored. */
- g->c = visual[j];
- if (g->rface->rfont)
- g->code = mfont__encode_char (NULL, (MFont *) g->rface->rfont,
- NULL, g->c);
+ for (i--; glyphs[i].bidi_level >= level; i--);
+ if (! glyphs[i].rface)
+ for (i = save; ! glyphs[i].rface; i++);
+ }
}
-#endif /* HAVE_FRIBIDI */
- g->bidi_level = levels[i];
- for (seglen = 1, g++;
- i + seglen < len && (glyphs[i].pos == glyphs[i + seglen].pos
- || glyphs[i + seglen].combining_code);
- seglen++, g++)
+ }
+ for (i = 1; i < gstring->used - 1; i++)
+ {
+ MGlyph *g = gstring->glyphs + i;
+
+ for (j = i; g->g.from == gstring->glyphs[j + 1].g.from; j++);
+ if (j > i)
{
- g->bidi_level = levels[i];
- if (indices[i + seglen] < j)
- j = indices[i + seglen];
+ memcpy (glyphs + i, gstring->glyphs + i,
+ sizeof (MGlyph) * (j - i + 1));
+ for (; i <= j; i++)
+ g[j - i] = glyphs[i];
+ i--;
}
- memcpy (MGLYPH (j + 1), glyphs + i, sizeof (MGlyph) * seglen);
- i += seglen;
}
}
+#if 0
static void
reorder_combining_chars (MGlyphString *gstring, int from, int to)
{
}
}
}
+#endif
+
+static int
+run_flt (MGlyphString *gstring, int from, int to, MRealizedFont *rfont,
+ MSymbol layouter)
+{
+ MFLTGlyphString flt_gstr;
+ MFLTFontForRealized font;
+ MFLT *flt;
+ int from_pos = MGLYPH (from)->g.from;
+ int len = to - from;
+ int i;
+ flt = mflt_get (layouter);
+ flt_gstr.glyph_size = sizeof (MGlyph);
+ flt_gstr.glyphs = (MFLTGlyph *) (gstring->glyphs);
+ flt_gstr.used = gstring->used;
+ flt_gstr.allocated = gstring->size;
+ flt_gstr.r2l = 0;
+ font.font.family = mfont_get_prop (rfont->font, Mfamily);
+ font.font.x_ppem = rfont->x_ppem;
+ font.font.y_ppem = rfont->y_ppem;
+ font.font.get_glyph_id = mfont__get_glyph_id;
+ font.font.get_metrics = mfont__get_metrics;
+ font.font.check_otf = rfont->driver->check_otf;
+ font.font.drive_otf = rfont->driver->drive_otf;
+ font.font.internal = NULL;
+ font.rfont = rfont;
+ for (i = 0; i < 3; i++)
+ {
+ to = mflt_run (&flt_gstr, from, to, &font.font, flt);
+ if (to != -2)
+ break;
+ APPEND_GLYPH (gstring, *MGLYPH (0));
+ APPEND_GLYPH (gstring, *MGLYPH (0));
+ gstring->used -= 2;
+ }
+ if (from + len != to)
+ gstring->used += to - (from + len);
+ for (i = from; i < to; i++)
+ {
+ MGlyph *g = MGLYPH (i);
+
+ g->g.from += from_pos - from;
+ g->g.to += from_pos - from + 1;
+ g->g.xadv >>= 6;
+ g->g.yadv >>= 6;
+ g->g.ascent >>= 6;
+ g->g.descent >>= 6;
+ g->g.lbearing >>= 6;
+ g->g.rbearing >>= 6;
+ g->g.xoff >>= 6;
+ g->g.yoff >>= 6;
+ }
+ return to;
+}
/** Scan M-text MT from FROM to TO, and compose glyphs in GSTRING for
displaying them on FRAME.
MRealizedFace *rface = default_rface;
MRealizedFont *rfont;
int size = gstring->control.fixed_width;
+ int max_bidi_level = 0;
int i;
MLIST_RESET (gstring);
/** Put anchor glyphs at the head and tail. */
g_tmp.type = GLYPH_ANCHOR;
- g_tmp.pos = g_tmp.to = from;
+ g_tmp.g.from = g_tmp.g.to = from;
APPEND_GLYPH (gstring, g_tmp);
stop = face_change = font_change = pos = from;
while (1)
c = '\n';
g_tmp.type
= (c == ' ' || c == '\n' || c == '\t') ? GLYPH_SPACE : GLYPH_CHAR;
- g_tmp.c = c;
- g_tmp.pos = pos++;
- g_tmp.to = pos;
+ g_tmp.g.c = c;
+ g_tmp.g.from = pos++;
+ g_tmp.g.to = pos;
g_tmp.rface = rface;
category = mchar_get_prop (c, Mcategory);
if (category == McatCf)
MGlyph ctrl[2];
ctrl[0] = ctrl[1] = g_tmp;
- ctrl[0].c = '^';
- ctrl[1].c = c < ' ' ? c + 0x40 : '?';
+ ctrl[0].g.c = '^';
+ ctrl[1].g.c = c < ' ' ? c + 0x40 : '?';
APPEND_GLYPH (gstring, ctrl[0]);
APPEND_GLYPH (gstring, ctrl[1]);
}
/* Append an anchor glyph. */
INIT_GLYPH (g_tmp);
g_tmp.type = GLYPH_ANCHOR;
- g_tmp.pos = g_tmp.to = pos;
+ g_tmp.g.from = g_tmp.g.to = pos;
APPEND_GLYPH (gstring, g_tmp);
gstring->to = pos;
+ if (gstring->control.enable_bidi)
+ max_bidi_level = analyse_bidi_level (gstring);
+
/* The next loop is to change each <rface> member for non-ASCII
characters if necessary. */
stop = charset_change = language_change = from;
rfont = default_rface->rfont;
for (last_g = g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
{
- int c = g->c;
+ int c = g->g.c;
MSymbol this_script;
if (c < 0x100)
{
this_script = (MSymbol) mchar_get_prop (c, Mscript);
if (this_script == Minherited || this_script == Mcommon)
- this_script = script;
- if (this_script == Mcommon)
+ {
+ if (g > MGLYPH (1))
+ {
+ MSymbol category = mchar_get_prop (g[-1].g.c, Mcategory);
+
+ if (MSYMBOL_NAME (category)[0] != 'Z')
+ this_script = script;
+ }
+ }
+ if (this_script == Mcommon && non_latin_script)
this_script = non_latin_script;
if (this_script == Mcommon)
{
MGlyph *g1;
for (g1 = g + 1; g1->type != GLYPH_ANCHOR; g1++)
- if (g1->c >= 0x100
- && (sym = mchar_get_prop (g1->c, Mscript)) != Mcommon
+ if (g1->g.c >= 0x100
+ && (sym = mchar_get_prop (g1->g.c, Mscript)) != Mcommon
&& sym != Minherited)
{
this_script = sym;
}
}
- pos = g->pos;
+ pos = g->g.from;
if (pos == stop || script != this_script || g->rface->rfont != rfont)
{
while (last_g < g)
if (this->rface->layouter != Mnil)
{
- MGlyph *prev;
- unsigned code;
-
- for (prev = MGLYPH (start - 1);
- (prev->type == GLYPH_CHAR
- && prev->category == GLYPH_CATEGORY_FORMATTER
- && (code = mfont__encode_char (NULL,
- (MFont *) this->rface->rfont,
- NULL, prev->c)
- != MCHAR_INVALID_CODE));
- start--, prev--)
- if (prev->rface->rfont != this->rface->rfont)
- {
- prev->rface->rfont = this->rface->rfont;
- prev->code = code;
- }
+ MGlyph *prev = MGLYPH (start - 1);
+
+ while (prev->type == GLYPH_CHAR
+ && prev->category == GLYPH_CATEGORY_FORMATTER
+ && (mfont__encode_char (NULL, (MFont *) this->rface->rfont,
+ NULL, prev->g.c)
+ != MCHAR_INVALID_CODE))
+ {
+ start--, prev--;
+ prev->rface->rfont = this->rface->rfont;
+ }
for (g++;
(g->type == GLYPH_CHAR
&& g->rface->layouter == this->rface->layouter
&& (g->rface->rfont == this->rface->rfont
|| (g->category == GLYPH_CATEGORY_FORMATTER
- && ((code = mfont__encode_char (NULL,
- (MFont *) this->rface->rfont,
- NULL,
- g->c))
+ && (mfont__encode_char (NULL,
+ (MFont *) this->rface->rfont,
+ NULL, g->g.c)
!= MCHAR_INVALID_CODE))));
i++, g++)
- if (g->rface->rfont != this->rface->rfont)
- {
- g->rface->rfont = this->rface->rfont;
- g->code = code;
- }
- i = mfont__flt_run (gstring, start, i, this->rface);
+ g->rface->rfont = this->rface->rfont;
+ i = run_flt (gstring, start, i, this->rface->rfont,
+ this->rface->layouter);
}
else
{
- while (this->type == GLYPH_CHAR
- && this->c >= 0x100
- && this->category == GLYPH_CATEGORY_MODIFIER
- && this->rface->rfont
- && this->rface->rfont->layouter == Mnil)
- {
- int class = (int) mchar_get_prop (this->c,
- Mcombining_class);
- this->combining_code
- = MAKE_COMBINING_CODE_BY_CLASS (class);
- i++, this++;
- }
+ g++;
+ while (g->type == GLYPH_CHAR
+ && g->g.c >= 0x100
+ && g->category == GLYPH_CATEGORY_MODIFIER
+ && g->rface->rfont
+ && g->rface->rfont->layouter == Mnil)
+ i++, g++;
if (start + 1 < i)
- reorder_combining_chars (gstring, start, i);
- if (this->type == GLYPH_ANCHOR)
- break;
+ run_flt (gstring, start, i, this->rface->rfont, Mcombining);
+ else
+ mfont__get_metric (gstring, start, i);
}
g = MGLYPH (i);
}
}
/* At last, reorder glyphs visually if necessary. */
- if (gstring->control.enable_bidi)
+ if (max_bidi_level > 0)
visual_order (gstring);
}
-
-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;
-}
-
-
typedef struct {
int width, lbearing, rbearing;
} MSubTextExtents;
int g_physical_ascent, g_physical_descent;
MGlyph *g = MGLYPH (from);
MGlyph *last_g = MGLYPH (to);
- int i;
g_physical_ascent = gstring->physical_ascent;
g_physical_descent = gstring->physical_descent;
extents->width = extents->lbearing = extents->rbearing = 0;
- for (i = from; i < to;)
+ for (g = MGLYPH (from); g < last_g; g++)
{
- if ( MGLYPH (i)->otf_encoded)
- i++;
- else
- {
- int j = i++;
-
- while (i < to && ! MGLYPH (i)->otf_encoded) i++;
- mfont__get_metric (gstring, j, i);
- }
- }
-
- g = MGLYPH (from);
- while (g < last_g)
- {
- MGlyph *base = g++;
- MRealizedFont *rfont = base->rface->rfont;
- int size = rfont->spec.size;
- int width, lbearing, rbearing;
-
- if (g == last_g || ! g->combining_code)
- {
- /* No combining. */
- if (base->width == 0 && ! base->left_padding && ! base->right_padding
- && GLYPH_INDEX (base) > from)
- {
- MGlyph *prev = base - 1;
-
- if (base->pos < prev->pos)
- prev->pos = base->pos;
- else
- base->pos = prev->pos;
- if (base->to > prev->to)
- prev->to = base->to;
- else
- base->to = prev->to;
- }
-
- if (base->left_padding && base->lbearing < 0)
- {
- base->xoff = - base->lbearing;
- if (base->rbearing < 0)
- base->width = base->rbearing - base->lbearing;
- else
- base->width += base->xoff;
- base->rbearing += base->xoff;
- base->lbearing = 0;
- }
- if (base->right_padding && base->rbearing > base->width)
- {
- base->width = base->rbearing;
- }
- lbearing = base->lbearing;
- rbearing = base->rbearing;
- }
- else
- {
- /* With combining glyphs. */
- int left = -base->width;
- int right = 0;
- int top = - base->ascent;
- int bottom = base->descent;
- int height = bottom - top;
- int begin = base->pos;
- int end = base->to;
- int i;
-
- width = base->width;
- lbearing = (base->lbearing < 0 ? base->lbearing : 0);
- rbearing = base->rbearing;
-
- while (g != last_g && g->combining_code)
- {
- int combining_code = g->combining_code;
-
- if (begin > g->pos)
- begin = g->pos;
- else if (end < g->to)
- end = g->to;
-
- if (! COMBINING_PRECOMPUTED_P (combining_code))
- {
- int base_x, base_y, add_x, add_y, off_x, off_y;
-
- if (COMBINING_BY_CLASS_P (combining_code))
- g->combining_code = combining_code
- = combining_code_from_class (COMBINING_CODE_CLASS
- (combining_code));
-
- rfont = g->rface->rfont;
- size = rfont->spec.size;
- off_x = (size * (COMBINING_CODE_OFF_X (combining_code) - 128)
- / 1000);
- off_y = (size * (COMBINING_CODE_OFF_Y (combining_code) - 128)
- / 1000);
- base_x = COMBINING_CODE_BASE_X (combining_code);
- base_y = COMBINING_CODE_BASE_Y (combining_code);
- add_x = COMBINING_CODE_ADD_X (combining_code);
- add_y = COMBINING_CODE_ADD_Y (combining_code);
-
- g->xoff = left + (width * base_x - g->width * add_x) / 2 + off_x;
- if (g->xoff < left)
- left = g->xoff;
- if (g->xoff + g->width > right)
- right = g->xoff + g->width;
- width = right - left;
-
- if (base_y < 3)
- g->yoff = top + height * base_y / 2;
- else
- g->yoff = 0;
- if (add_y < 3)
- g->yoff -= (g->ascent + g->descent) * add_y / 2 - g->ascent;
- g->yoff -= off_y;
- }
-
- if (g->xoff + g->lbearing < left + lbearing)
- lbearing = g->xoff + g->lbearing - left;
- if (g->xoff + g->rbearing > left + rbearing)
- rbearing = g->xoff + g->rbearing - left;
- if (g->yoff - g->ascent < top)
- top = g->yoff - g->ascent;
- if (g->yoff + g->descent > bottom)
- bottom = g->yoff + g->descent;
- height = bottom - top;
-
- g->width = 0;
- g++;
- }
-
- base->ascent = - top;
- base->descent = bottom;
- base->lbearing = lbearing;
- base->rbearing = rbearing;
- if (left < - base->width)
- {
- base->xoff = - base->width - left;
- base->width += base->xoff;
- base->rbearing += base->xoff;
- base->lbearing += base->xoff;
- }
- if (right > 0)
- {
- base->width += right;
- base->rbearing += right;
- base->right_padding = 1;
- for (i = 1; base + i != g; i++)
- base[i].xoff -= right;
- }
-
- for (i = 0; base + i != g; i++)
- {
- base[i].pos = begin;
- base[i].to = end;
- }
- if (base->left_padding && lbearing < 0)
- {
- base->xoff -= lbearing;
- base->width -= lbearing;
- lbearing = 0;
- }
- }
-
- g_physical_ascent = MAX (g_physical_ascent, base->ascent);
- g_physical_descent = MAX (g_physical_descent, base->descent);
- extents->lbearing = MIN (extents->lbearing, extents->width + lbearing);
- extents->rbearing = MAX (extents->rbearing, extents->width + rbearing);
- extents->width += base->width;
+ g_physical_ascent = MAX (g_physical_ascent, g->g.ascent);
+ g_physical_descent = MAX (g_physical_descent, g->g.descent);
+ extents->lbearing = MIN (extents->lbearing,
+ extents->width + g->g.lbearing);
+ extents->rbearing = MAX (extents->rbearing,
+ extents->width + g->g.rbearing);
+ extents->width += g->g.xadv;
}
gstring->physical_ascent = g_physical_ascent;
MGlyph box_glyph = g[-1];
box_glyph.type = GLYPH_BOX;
- box_glyph.width
+ box_glyph.g.xadv
= (control->fixed_width
? frame->space_width
: box->inner_hmargin + box->width + box->outer_hmargin);
- box_glyph.lbearing = 0;
- box_glyph.rbearing = box_glyph.width;
- box_glyph.xoff = 0;
+ box_glyph.g.lbearing = 0;
+ box_glyph.g.rbearing = box_glyph.g.xadv;
+ box_glyph.g.xoff = 0;
box_glyph.right_padding = 1;
- gstring->width += box_glyph.width;
- gstring->rbearing += box_glyph.width;
+ gstring->width += box_glyph.g.xadv;
+ gstring->rbearing += box_glyph.g.xadv;
INSERT_GLYPH (gstring, gidx, box_glyph);
gidx++;
g = MGLYPH (gidx);
if (box_line_height < box_height)
box_line_height = box_height;
box_glyph.type = GLYPH_BOX;
- box_glyph.width
+ box_glyph.g.xadv
= (control->fixed_width
? frame->space_width
: box->inner_hmargin + box->width + box->outer_hmargin);
- box_glyph.lbearing = 0;
- box_glyph.rbearing = box_glyph.width;
- box_glyph.xoff = 0;
+ box_glyph.g.lbearing = 0;
+ box_glyph.g.rbearing = box_glyph.g.xadv;
+ box_glyph.g.xoff = 0;
box_glyph.left_padding = 1;
- gstring->width += box_glyph.width;
- gstring->rbearing += box_glyph.width;
+ gstring->width += box_glyph.g.xadv;
+ gstring->rbearing += box_glyph.g.xadv;
INSERT_GLYPH (gstring, gidx, box_glyph);
gidx++;
g = MGLYPH (gidx);
for (g++; g->type == GLYPH_CHAR; g++)
if (! rfont != ! g->rface->rfont
|| box != g->rface->box
- || ((fromg->code == MCHAR_INVALID_CODE)
- != (g->code == MCHAR_INVALID_CODE))
+ || ((fromg->g.code == MCHAR_INVALID_CODE)
+ != (g->g.code == MCHAR_INVALID_CODE))
|| (g->category == GLYPH_CATEGORY_FORMATTER
&& ignore_formatting_char))
break;
- if (rfont && fromg->code != MCHAR_INVALID_CODE)
+ if (rfont && fromg->g.code != MCHAR_INVALID_CODE)
{
int extra_width;
int to = GLYPH_INDEX (g);
g = MGLYPH (from);
pad = *g;
pad.type = GLYPH_PAD;
- pad.xoff = 0;
- pad.lbearing = 0;
- pad.width = pad.rbearing = extra_width;
+ pad.g.xoff = 0;
+ pad.g.lbearing = 0;
+ pad.g.xadv = pad.g.rbearing = extra_width;
pad.left_padding = 1;
INSERT_GLYPH (gstring, from, pad);
to++;
face, or a default value of the current
frame, which is, however, not yet
implemented. */
- if (extra_width + 2 < g->width)
+ if (extra_width + 2 < g->g.xadv)
{
- g->width -= extra_width;
+ g->g.xadv -= extra_width;
}
else
{
- extra_width = g->width - 2;
- g->width = 2;
+ extra_width = g->g.xadv - 2;
+ g->g.xadv = 2;
}
gstring->width -= extra_width;
gstring->rbearing -= extra_width;
{
pad = g[-1];
pad.type = GLYPH_PAD;
- pad.xoff = 0;
- pad.lbearing = 0;
- pad.width = pad.rbearing = extra_width;
+ pad.g.xoff = 0;
+ pad.g.lbearing = 0;
+ pad.g.xadv = pad.g.rbearing = extra_width;
INSERT_GLYPH (gstring, to, pad);
to++;
g = MGLYPH (to);
}
else
- g[-1].width += extra_width;
+ g[-1].g.xadv += extra_width;
extents.width += extra_width;
}
{
for (; fromg < g; fromg++)
{
- if ((fromg->c >= 0x200B && fromg->c <= 0x200F)
- || (fromg->c >= 0x202A && fromg->c <= 0x202E))
- fromg->width = fromg->rbearing = 1;
+ if ((fromg->g.c >= 0x200B && fromg->g.c <= 0x200F)
+ || (fromg->g.c >= 0x202A && fromg->g.c <= 0x202E))
+ fromg->g.xadv = fromg->g.rbearing = 1;
else
- fromg->width = fromg->rbearing = rface->space_width;
- fromg->xoff = fromg->lbearing = 0;
- fromg->ascent = fromg->descent = 0;
- gstring->width += fromg->width;
- gstring->rbearing += fromg->width;
+ fromg->g.xadv = fromg->g.rbearing = rface->space_width;
+ fromg->g.xoff = fromg->g.lbearing = 0;
+ fromg->g.ascent = fromg->g.descent = 0;
+ gstring->width += fromg->g.xadv;
+ gstring->rbearing += fromg->g.xadv;
}
if (gstring->ascent < frame->rface->ascent)
gstring->ascent = frame->rface->ascent;
}
else if (g->type == GLYPH_SPACE)
{
- if (g->c == ' ')
- g->width = g->rface->space_width;
- else if (g->c == '\n')
+ if (g->g.c == ' ')
+ g->g.xadv = g->rface->space_width;
+ else if (g->g.c == '\n')
{
- g->width = control->cursor_width;
- if (g->width)
+ g->g.xadv = control->cursor_width;
+ if (g->g.xadv)
{
if (control->cursor_bidi)
- g->width = 3;
- else if (g->width < 0)
- g->width = g->rface->space_width;
+ g->g.xadv = 3;
+ else if (g->g.xadv < 0)
+ g->g.xadv = g->rface->space_width;
}
}
- else if (g->c == '\t')
+ else if (g->g.c == '\t')
{
- g->width = tab_width - ((gstring->indent + gstring->width)
- % tab_width);
+ g->g.xadv = tab_width - ((gstring->indent + gstring->width)
+ % tab_width);
tab_found = 1;
}
else
- g->width = 1;
+ g->g.xadv = 1;
if (g[-1].type == GLYPH_PAD)
{
/* This space glyph absorbs (maybe partially) the
previous padding glyph. */
- g->width -= g[-1].width;
- if (g->width < 1)
+ g->g.xadv -= g[-1].g.xadv;
+ if (g->g.xadv < 1)
/* But, keep at least some space width. For the
moment, we use the arbitrary width 2-pixel. */
- g->width = 2;
+ g->g.xadv = 2;
}
- g->rbearing = g->width;
- gstring->width += g->width;
- gstring->rbearing += g->width;
+ g->g.rbearing = g->g.xadv;
+ gstring->width += g->g.xadv;
+ gstring->rbearing += g->g.xadv;
if (g->rface->rfont)
{
if (gstring->ascent < g->rface->ascent)
}
else
{
- gstring->width += g->width;
- gstring->rbearing += g->width;
+ gstring->width += g->g.xadv;
+ gstring->rbearing += g->g.xadv;
g++;
}
}
MGlyph box_glyph = g[-1];
box_glyph.type = GLYPH_BOX;
- box_glyph.width
+ box_glyph.g.xadv
= (control->fixed_width
? frame->space_width
: box->inner_hmargin + box->width + box->outer_hmargin);
- box_glyph.lbearing = 0;
- box_glyph.rbearing = box_glyph.width;
- box_glyph.xoff = 0;
+ box_glyph.g.lbearing = 0;
+ box_glyph.g.rbearing = box_glyph.g.xadv;
+ box_glyph.g.xoff = 0;
box_glyph.right_padding = 1;
- gstring->width += box_glyph.width;
- gstring->rbearing += box_glyph.width;
+ gstring->width += box_glyph.g.xadv;
+ gstring->rbearing += box_glyph.g.xadv;
INSERT_GLYPH (gstring, gidx, box_glyph);
}
for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
{
- if (g->type == GLYPH_CHAR && g->c == '\t')
+ if (g->type == GLYPH_CHAR && g->g.c == '\t')
{
int this_width = tab_width - (width % tab_width);
if (g[1].type == GLYPH_PAD)
- this_width -= g[1].width;
+ this_width -= g[1].g.xadv;
if (g[-1].type == GLYPH_PAD)
- this_width -= g[-1].width;
+ this_width -= g[-1].g.xadv;
if (this_width < 2)
this_width = 2;
- gstring->width += this_width - g->width;
- gstring->rbearing += this_width - g->width;
- g->width = this_width;
+ gstring->width += this_width - g->g.xadv;
+ gstring->rbearing += this_width - g->g.xadv;
+ g->g.xadv = this_width;
width += this_width;
}
else
- width += g->width;
+ width += g->g.xadv;
}
}
}
*to_x = x;
while (g->type != GLYPH_ANCHOR)
{
- if (g->pos >= from && g->pos < to)
+ if (g->g.from >= from && g->g.from < to)
{
MGlyph *fromg = g, *cursor = NULL;
MRealizedFace *rface = g->rface;
if (! *from_idx)
*from_idx = GLYPH_INDEX (g);
- while (g->pos >= from && g->pos < to
+ while (g->g.from >= from && g->g.from < to
&& g->rface == rface)
{
g->enabled = 1;
if (g->type != GLYPH_BOX
- && g->pos <= cursor_pos && g->to > cursor_pos)
+ && g->g.from <= cursor_pos && g->g.to > cursor_pos)
{
if (! cursor)
cursor = g, cursor_x = x + width;
- cursor_width += g->width;
+ cursor_width += g->g.xadv;
}
- width += g++->width;
+ width += g++->g.xadv;
}
if (width > 0
&& (control->as_image
int this_x = x, this_width = width;
if (fromg->type == GLYPH_BOX)
- this_x += fromg->width, this_width -= fromg->width;
+ this_x += fromg->g.xadv, this_width -= fromg->g.xadv;
if (g[-1].type == GLYPH_BOX)
- this_width -= g[-1].width;
+ this_width -= g[-1].g.xadv;
(frame->driver->fill_space)
(frame, win, rface, 0,
this_x, y - gstring->text_ascent, this_width,
while (fromg < g)
{
if (fromg->type != GLYPH_BOX
- && fromg->pos <= prev_pos && fromg->to > prev_pos)
+ && fromg->g.from <= prev_pos && fromg->g.to > prev_pos)
{
if (! cursor)
cursor = fromg, cursor_x = x + temp_width;
- cursor_width += fromg->width;
+ cursor_width += fromg->g.xadv;
}
- temp_width += fromg++->width;
+ temp_width += fromg++->g.xadv;
}
if (cursor)
{
(*frame->driver->region_to_rect) (region, &rect);
if (rect.x > x)
{
- while (g != gend && x + g->rbearing <= rect.x)
+ while (g != gend && x + g->g.rbearing <= rect.x)
{
- x += g->width;
- width -= g++->width;
+ x += g->g.xadv;
+ width -= g++->g.xadv;
while (! g->enabled && g != gend)
g++;
}
if (rect.x < x + width)
{
while (g != gend
- && (x + width - gend[-1].width + gend[-1].lbearing >= rect.x))
+ && (x + width - gend[-1].g.xadv + gend[-1].g.lbearing >= rect.x))
{
- width -= (--gend)->width;
+ width -= (--gend)->g.xadv;
while (! gend->enabled && g != gend)
gend--;
}
if (g != gend)
- while (gend->type != GLYPH_ANCHOR && gend[-1].to == gend->to)
+ while (gend->type != GLYPH_ANCHOR && gend[-1].g.to == gend->g.to)
gend++;
}
}
if (g->enabled)
{
MRealizedFace *rface = g->rface;
- int width = g->width;
+ int width = g->g.xadv;
MGlyph *from_g = g++;
/* Handle the glyphs of the same type/face at once. */
while (g != gend
&& g->type == from_g->type
&& g->rface == rface
- && ((g->code == MCHAR_INVALID_CODE)
- == (from_g->code == MCHAR_INVALID_CODE))
+ && ((g->g.code == MCHAR_INVALID_CODE)
+ == (from_g->g.code == MCHAR_INVALID_CODE))
&& g->enabled)
- width += g++->width;
+ width += g++->g.xadv;
if (from_g->type == GLYPH_CHAR)
{
- if (rface->rfont && from_g->code != MCHAR_INVALID_CODE)
+ if (rface->rfont && from_g->g.code != MCHAR_INVALID_CODE)
(rface->rfont->driver->render) (win, x, y, gstring, from_g, g,
reverse, region);
else
for (g = MGLYPH (*left) - 1, x = 0; g->type != GLYPH_ANCHOR; g--)
{
- x -= g->width;
- if (x + g->rbearing > 0)
+ x -= g->g.xadv;
+ if (x + g->g.rbearing > 0)
{
- while (g[-1].pos == g->pos && g[-1].type != GLYPH_ANCHOR)
- x -= (--g)->width;
+ while (g[-1].g.from == g->g.from && g[-1].type != GLYPH_ANCHOR)
+ x -= (--g)->g.xadv;
left_idx = GLYPH_INDEX (g);
left_x = x;
}
for (g = MGLYPH (*right), x = 0; g->type != GLYPH_ANCHOR; g++)
{
- x += g->width;
- if (x - g->width + g->lbearing < 0)
+ x += g->g.xadv;
+ if (x - g->g.xadv + g->g.lbearing < 0)
{
- while (g->pos == g[1].pos && g[1].type != GLYPH_ANCHOR)
- x += (++g)->width;
+ while (g->g.from == g[1].g.from && g[1].type != GLYPH_ANCHOR)
+ x += (++g)->g.xadv;
right_idx = GLYPH_INDEX (g) + 1;
right_x = x;
}
if (rbearing)
*rbearing = 0;
for (g = MGLYPH (1), width = 0; g->type != GLYPH_ANCHOR; g++)
- if (g->pos >= from && g->pos < to)
+ if (g->g.from >= from && g->g.from < to)
{
- if (lbearing && width + g->lbearing < *lbearing)
- *lbearing = width + g->lbearing;
- if (rbearing && width + g->rbearing > *rbearing)
- *rbearing = width + g->rbearing;
- width += g->width;
+ if (lbearing && width + g->g.lbearing < *lbearing)
+ *lbearing = width + g->g.lbearing;
+ if (rbearing && width + g->g.rbearing > *rbearing)
+ *rbearing = width + g->g.rbearing;
+ width += g->g.xadv;
}
return width;
}
APPEND_GLYPH (gstring, g_tmp);
APPEND_GLYPH (gstring, g_tmp);
gstring->glyphs[1].type = GLYPH_SPACE;
- gstring->glyphs[1].c = '\n';
- gstring->glyphs[1].code = '\n';
+ gstring->glyphs[1].g.c = '\n';
+ gstring->glyphs[1].g.code = '\n';
}
gstring->from = pos;
g = MGLYPH (0);
g->rface = frame->rface;
- g->pos = g->to = pos;
+ g->g.from = g->g.to = pos;
g++;
g->rface = frame->rface;
- g->pos = pos++, g->to = pos;
+ g->g.from = pos++, g->g.to = pos;
g++;
g->rface = frame->rface;
- g->pos = g->to = pos;
+ g->g.from = g->g.to = pos;
gstring->to = pos;
}
else
MTABLE_ALLOCA (pos_width, gstring->to - gstring->from, MERROR_DRAW);
memset (pos_width, 0, sizeof (int) * (gstring->to - gstring->from));
for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
- pos_width[g->pos - gstring->from] += g->width;
+ pos_width[g->g.from - gstring->from] += g->g.xadv;
for (i = 0, width = 0; i < gstring->to - gstring->from; i++)
{
if (pos_width[i] > 0)
if (pos <= gstring->from)
{
g = find_glyph_in_gstring (gstring, gstring->from, 1);
- pos = g->to;
+ pos = g->g.to;
}
else if (pos >= gstring->to)
pos = gstring->to;
else if (i == 0)
{
g = find_glyph_in_gstring (gstring, gstring->from, 1);
- pos = g->to;
+ pos = g->g.to;
}
if (pos < gstring->to)
{
gst->to += offset;
for (i = 0; i < gst->used; i++)
{
- gst->glyphs[i].pos += offset;
- gst->glyphs[i].to += offset;
+ gst->glyphs[i].g.from += offset;
+ gst->glyphs[i].g.to += offset;
}
}
M17N_OBJECT_REF (gstring);
if (forwardp)
{
for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
- if (g->pos <= pos && g->to > pos)
+ if (g->g.from <= pos && g->g.to > pos)
break;
}
else
{
for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
- if (g->pos <= pos && g->to > pos)
+ if (g->g.from <= pos && g->g.to > pos)
break;
}
return g;
/* for debugging... */
char work[16];
-char *
-dump_combining_code (int code)
-{
- char *vallign = "tcbB";
- char *hallign = "lcr";
- char *p;
- int off_x, off_y;
-
- if (! code)
- return "none";
- if (COMBINING_BY_CLASS_P (code))
- code = combining_code_from_class (COMBINING_CODE_CLASS (code));
- work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
- work[1] = hallign[COMBINING_CODE_BASE_X (code)];
- off_y = COMBINING_CODE_OFF_Y (code) - 128;
- off_x = COMBINING_CODE_OFF_X (code) - 128;
- if (off_y > 0)
- sprintf (work + 2, "+%d", off_y);
- else if (off_y < 0)
- sprintf (work + 2, "%d", off_y);
- else if (off_x == 0)
- sprintf (work + 2, ".");
- p = work + strlen (work);
- if (off_x > 0)
- sprintf (p, ">%d", off_x);
- else if (off_x < 0)
- sprintf (p, "<%d", -off_x);
- p += strlen (p);
- p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
- p[1] = hallign[COMBINING_CODE_ADD_X (code)];
- p[2] = '\0';
- return work;
-}
-
void
-dump_gstring (MGlyphString *gstring, int indent)
+dump_gstring (MGlyphString *gstring, int indent, int type)
{
char *prefix = (char *) alloca (indent + 1);
- MGlyph *g, *last_g = gstring->glyphs + gstring->used;
+ MGlyph *g, *first_g, *last_g;
memset (prefix, 32, indent);
prefix[indent] = 0;
fprintf (stderr, "(glyph-string");
- for (g = MGLYPH (0); g < last_g; g++)
- fprintf (stderr,
- "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x cmb:%s w:%02d bidi:%d)",
- prefix,
- g - gstring->glyphs,
- (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
- : g->type == GLYPH_ANCHOR ? "ANC"
- : g->type == GLYPH_BOX ? "BOX" : "CHR"),
- g->pos, g->to, g->c, g->code, (unsigned) g->rface,
- dump_combining_code (g->combining_code),
- g->width, g->bidi_level);
+ if (type == 0)
+ {
+ first_g = MGLYPH (0);
+ last_g = first_g + gstring->used;
+ }
+ else
+ {
+ first_g = (MGlyph *) ((MFLTGlyphString *) gstring)->glyphs;
+ last_g = first_g + ((MFLTGlyphString *) gstring)->used;
+ }
+
+ for (g = first_g; g < last_g; g++)
+ {
+ fprintf (stderr,
+ "\n%s (%02d %s pos:%d-%d c:%04X code:%04X face:%x w:%02d bidi:%d",
+ prefix,
+ g - first_g,
+ (g->type == GLYPH_SPACE ? "SPC": g->type == GLYPH_PAD ? "PAD"
+ : g->type == GLYPH_ANCHOR ? "ANC"
+ : g->type == GLYPH_BOX ? "BOX" : "CHR"),
+ g->g.from, g->g.to, g->g.c, g->g.code, (unsigned) g->rface,
+ g->g.xadv, g->bidi_level);
+ if (g->g.xoff || g->g.yoff)
+ fprintf (stderr, " off:%d,%d", g->g.xoff, g->g.yoff);
+ fprintf (stderr, ")");
+ }
fprintf (stderr, ")");
}
\f
}
for (g = MGLYPH (1), x = 0; g->type != GLYPH_ANCHOR; g++)
- if (g->pos >= from && g->pos < to)
+ if (g->g.from >= from && g->g.from < to)
{
- int start = g->pos;
- int end = g->to;
- int width = g->width;
- int lbearing = g->lbearing;
- int rbearing = g->rbearing;
- int ascent = g->ascent;
- int descent = g->descent;
+ int start = g->g.from;
+ int end = g->g.to;
+ int width = g->g.xadv;
+ int lbearing = g->g.lbearing;
+ int rbearing = g->g.rbearing;
+ int ascent = g->g.ascent;
+ int descent = g->g.descent;
int logical_ascent;
int logical_descent;
logical_ascent = g->rface->ascent;
logical_descent = g->rface->descent;
}
- for (g++; g->type != GLYPH_ANCHOR && g->pos == start; g++)
+ for (g++; g->type != GLYPH_ANCHOR && g->g.from == start; g++)
{
- if (lbearing < width + g->lbearing)
- lbearing = width + g->lbearing;
- if (rbearing < width + g->rbearing)
- rbearing = width + g->rbearing;
- width += g->width;
- if (ascent < g->ascent)
- ascent = g->ascent;
- if (descent < g->descent)
- descent = g->descent;
+ if (lbearing < width + g->g.lbearing)
+ lbearing = width + g->g.lbearing;
+ if (rbearing < width + g->g.rbearing)
+ rbearing = width + g->g.rbearing;
+ width += g->g.xadv;
+ if (ascent < g->g.ascent)
+ ascent = g->g.ascent;
+ if (descent < g->g.descent)
+ descent = g->g.descent;
}
if (end > to)
{
width = gstring->indent;
for (g = MGLYPH (1); g->type != GLYPH_ANCHOR; g++)
- if (g->pos >= from && g->pos < to)
+ if (g->g.from >= from && g->g.from < to)
{
- width += g->width;
+ width += g->g.xadv;
if (width > x_offset)
break;
}
{
width = - gstring->indent;
for (g = MGLYPH (gstring->used - 2); g->type != GLYPH_ANCHOR; g--)
- if (g->pos >= from && g->pos < to)
+ if (g->g.from >= from && g->g.from < to)
{
- width -= g->width;
+ width -= g->g.xadv;
if (width < x_offset)
break;
}
}
if (g->type == GLYPH_ANCHOR
&& control->two_dimensional
- && g[-1].c == '\n')
+ && g[-1].g.c == '\n')
g--;
- from = g->pos;
+ from = g->g.from;
M17N_OBJECT_UNREF (gstring->top);
return from;
if (! control->orientation_reversed)
{
info->x = gstring->indent;
- for (g = MGLYPH (1); g->pos > pos || g->to <= pos; g++)
- info->x += g->width;
+ for (g = MGLYPH (1); g->g.from > pos || g->g.to <= pos; g++)
+ info->x += g->g.xadv;
}
else
{
info->x = - gstring->indent;
- for (g = MGLYPH (gstring->used - 2); g->pos > pos || g->to <= pos; g--)
- info->x -= g->width;
- while (g[-1].to == g->to)
+ for (g = MGLYPH (gstring->used - 2); g->g.from > pos || g->g.to <= pos; g--)
+ info->x -= g->g.xadv;
+ while (g[-1].g.to == g->g.to)
g--;
}
- info->from = g->pos;
- info->to = g->to;
- info->metrics.x = g->lbearing;
+ info->from = g->g.from;
+ info->to = g->g.to;
+ info->metrics.x = g->g.lbearing;
info->metrics.y = - gstring->line_ascent;
info->metrics.height = gstring->height;
- info->metrics.width = - g->lbearing + g->width;
+ info->metrics.width = - g->g.lbearing + g->g.xadv;
if (g->rface->rfont)
info->font = (MFont *) g->rface->rfont;
else
/* The logically previous glyph is on this line. */
MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->from - 1, 1);
- info->prev_from = g_tmp->pos;
+ info->prev_from = g_tmp->g.from;
}
else if (info->line_from > 0
&& gstring->from > 0)
gstring->from, control);
MGlyph *g_tmp = find_glyph_in_gstring (gst, info->from - 1, 1);
- info->prev_from = g_tmp->pos;
+ info->prev_from = g_tmp->g.from;
M17N_OBJECT_UNREF (gst->top);
}
else
info->prev_from = -1;
if (GLYPH_INDEX (g) > 1)
- info->left_from = g[-1].pos, info->left_to = g[-1].to;
+ info->left_from = g[-1].g.from, info->left_to = g[-1].g.to;
else if (! control->orientation_reversed)
{
if (info->line_from > 0)
gst = get_gstring (frame, mt, p, gstring->from, control);
g_tmp = gst->glyphs + (gst->used - 2);
- info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
+ info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
M17N_OBJECT_UNREF (gst->top);
}
else
gst = get_gstring (frame, mt, p, p + 1, control);
g_tmp = gst->glyphs + (gst->used - 2);
- info->left_from = g_tmp->pos, info->left_to = g_tmp->to;
+ info->left_from = g_tmp->g.from, info->left_to = g_tmp->g.to;
M17N_OBJECT_UNREF (gst->top);
}
else
/* The logically next glyph is on this line. */
MGlyph *g_tmp = find_glyph_in_gstring (gstring, info->to, 0);
- info->next_to = g_tmp->to;
+ info->next_to = g_tmp->g.to;
}
else if (info->to + (control->cursor_width == 0) <= mtext_nchars (mt))
{
MGlyphString *gst = get_gstring (frame, mt, p, p + 1, control);
MGlyph *g_tmp = find_glyph_in_gstring (gst, p, 0);
- info->next_to = g_tmp->to;
+ info->next_to = g_tmp->g.to;
M17N_OBJECT_UNREF (gst->top);
}
else
info->next_to = -1;
- for (info->logical_width = (g++)->width;
- g->pos == pos && g->type != GLYPH_ANCHOR;
- info->metrics.width += g->width, info->logical_width += (g++)->width);
- info->metrics.width += g[-1].rbearing - g[-1].width;
+ for (info->logical_width = (g++)->g.xadv;
+ g->g.from == pos && g->type != GLYPH_ANCHOR;
+ info->metrics.width += g->g.xadv, info->logical_width += (g++)->g.xadv);
+ info->metrics.width += g[-1].g.rbearing - g[-1].g.xadv;
if (g->type != GLYPH_ANCHOR)
- info->right_from = g->pos, info->right_to = g->to;
+ info->right_from = g->g.from, info->right_to = g->g.to;
else if (! control->orientation_reversed)
{
if (gstring->to + (control->cursor_width == 0) <= mtext_nchars (mt))
M17N_OBJECT_UNREF (gstring->top);
gstring = get_gstring (frame, mt, pos, pos + 1, control);
g = MGLYPH (1);
- info->right_from = g->pos, info->right_to = g->to;
+ info->right_from = g->g.from, info->right_to = g->g.to;
}
else
info->right_from = info->right_to = -1;
M17N_OBJECT_UNREF (gstring->top);
gstring = get_gstring (frame, mt, pos, pos + 1, control);
g = MGLYPH (1);
- info->right_from = g->pos, info->right_to = g->to;
+ info->right_from = g->g.from, info->right_to = g->g.to;
}
else
info->right_from = info->right_to = -1;
for (g = MGLYPH (1), n = 0; g->type != GLYPH_ANCHOR; g++)
{
if (g->type == GLYPH_BOX
- || g->pos < from || g->pos >= to)
+ || g->g.from < from || g->g.from >= to)
continue;
if (g->type == GLYPH_PAD)
{
if (g->left_padding)
- pad_width = g->width;
+ pad_width = g->g.xadv;
else if (n > 0)
{
pad_width = 0;
- glyphs[-1].x_advance += g->width;
+ glyphs[-1].x_advance += g->g.xadv;
}
continue;
}
if (n < array_size)
{
- glyphs->from = g->pos;
- glyphs->to = g->to;
- glyphs->glyph_code = g->code;
- glyphs->x_off = g->xoff + pad_width;
- glyphs->y_off = g->yoff;
- glyphs->lbearing = g->lbearing;
- glyphs->rbearing = g->rbearing;
- glyphs->ascent = g->ascent;
- glyphs->descent = g->descent;
- glyphs->x_advance = g->width + pad_width;
+ glyphs->from = g->g.from;
+ glyphs->to = g->g.to;
+ glyphs->glyph_code = g->g.code;
+ glyphs->x_off = g->g.xoff + pad_width;
+ glyphs->y_off = g->g.yoff;
+ glyphs->lbearing = g->g.lbearing;
+ glyphs->rbearing = g->g.rbearing;
+ glyphs->ascent = g->g.ascent;
+ glyphs->descent = g->g.descent;
+ glyphs->x_advance = g->g.xadv + pad_width;
glyphs->y_advance = 0;
if (g->rface->rfont)
{
font);
rfont = NULL;
mfont__set_spec_from_face (&spec, &merged_face);
- mfont_put_prop (&spec, Mregistry, Miso8859_1);
- spec.source = MFONT_SOURCE_X;
+ mfont_put_prop (&spec, Mregistry, Municode_bmp);
+ spec.source = MFONT_SOURCE_FT;
font = mfont__select (frame, &spec, 0);
if (font)
rfont = mfont__open (frame, font, &spec);
if (! rfont)
{
- mfont_put_prop (&spec, Mregistry, Municode_bmp);
- spec.source = MFONT_SOURCE_FT;
+ mfont_put_prop (&spec, Mregistry, Miso8859_1);
+ spec.source = MFONT_SOURCE_X;
font = mfont__select (frame, &spec, 0);
if (font)
rfont = mfont__open (frame, font, &spec);
rface->layouter = rfont->layouter;
rfont->layouter = Mnil;
work_gstring.glyphs[0].rface = rface;
- work_gstring.glyphs[0].code = MCHAR_INVALID_CODE;
+ work_gstring.glyphs[0].g.code = MCHAR_INVALID_CODE;
+ work_gstring.glyphs[0].g.measured = 0;
mfont__get_metric (&work_gstring, 0, 1);
- rface->ascent = work_gstring.glyphs[0].ascent;
- rface->descent = work_gstring.glyphs[0].descent;
- work_gstring.glyphs[0].code
+ rface->ascent = work_gstring.glyphs[0].g.ascent;
+ rface->descent = work_gstring.glyphs[0].g.descent;
+ work_gstring.glyphs[0].g.code
= mfont__encode_char (frame, (MFont *) rfont, NULL, ' ');
- if (work_gstring.glyphs[0].code != MCHAR_INVALID_CODE)
+ if (work_gstring.glyphs[0].g.code != MCHAR_INVALID_CODE)
{
+ work_gstring.glyphs[0].g.measured = 0;
mfont__get_metric (&work_gstring, 0, 1);
- rface->space_width = work_gstring.glyphs[0].width;
+ rface->space_width = work_gstring.glyphs[0].g.xadv;
}
else
rface->space_width = rfont->spec.size / 10;
if (rfont->average_width)
- rface->average_width = rfont->average_width;
+ rface->average_width = rfont->average_width >> 6;
else
{
- work_gstring.glyphs[0].code
+ work_gstring.glyphs[0].g.code
= mfont__encode_char (frame, (MFont *) rfont, NULL, 'x');
- if (work_gstring.glyphs[0].code != MCHAR_INVALID_CODE)
+ if (work_gstring.glyphs[0].g.code != MCHAR_INVALID_CODE)
{
+ work_gstring.glyphs[0].g.measured = 0;
mfont__get_metric (&work_gstring, 0, 1);
- rface->average_width = work_gstring.glyphs[0].width;
+ rface->average_width = work_gstring.glyphs[0].g.xadv;
}
else
rface->average_width = rface->space_width;
if (! rfont)
{
for (; from_g < to_g && from_g->rface->font; from_g++)
- from_g->code = MCHAR_INVALID_CODE;
+ from_g->g.code = MCHAR_INVALID_CODE;
}
else
{
new->layouter = rfont->layouter;
rfont->layouter = Mnil;
new->non_ascii_list = NULL;
- new->ascent = rfont->ascent;
- new->descent = rfont->descent;
+ new->ascent = rfont->ascent >> 6;
+ new->descent = rfont->descent >> 6;
}
for (; from_g < to_g && from_g->rface->font; from_g++)
{
from_g->rface = new;
if (new->layouter)
{
- from_g->code = mfont__flt_encode_char (new->layouter,
- from_g->c);
- if (from_g->code == MCHAR_INVALID_CODE)
+ MFLT *flt = mflt_get (new->layouter);
+ MCharTable *coverage;
+
+ if (! flt
+ || ((coverage = mflt_coverage (flt))
+ && ! (from_g->g.code
+ = (unsigned) mchartable_lookup (coverage,
+ from_g->g.c))))
{
from_g->rface = rface;
- from_g->code = mfont__encode_char (rfont->frame,
- (MFont *) rfont,
- NULL, from_g->c);
+ from_g->g.code = mfont__encode_char (rfont->frame,
+ (MFont *) rfont,
+ NULL, from_g->g.c);
}
}
else
- from_g->code = mfont__encode_char (rfont->frame,
- (MFont *) rfont,
- NULL, from_g->c);
+ from_g->g.code = mfont__encode_char (rfont->frame,
+ (MFont *) rfont,
+ NULL, from_g->g.c);
}
}
return from_g;
for (i = 0; i < num; i++)
{
unsigned code = mfont__encode_char (rfont->frame, (MFont *) rfont,
- NULL, from_g[i].c);
+ NULL, from_g[i].g.c);
if (code == MCHAR_INVALID_CODE)
break;
- from_g[i].code = code;
+ from_g[i].g.code = code;
}
if (i == num || from_g[i].rface->font)
return from_g + i;
}
else
{
- from_g->code = MCHAR_INVALID_CODE;
+ from_g->g.code = MCHAR_INVALID_CODE;
num = 1;
rfont = NULL;
layouter = Mnil;
new->non_ascii_list = NULL;
if (rfont)
{
- new->ascent = rfont->ascent;
- new->descent = rfont->descent;
+ new->ascent = rfont->ascent >> 6;
+ new->descent = rfont->descent >> 6;
}
}
while (g < from_g)
#include "mtext.h"
#include "symbol.h"
#include "plist.h"
+#include "internal-flt.h"
#include "internal-gui.h"
#include "font.h"
#include "face.h"
*/
-static int mdebug_mask = MDEBUG_FONT_FLT;
+static int mdebug_flag = MDEBUG_FONT_FLT;
MSymbol Mlayouter;
#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;
+static MSymbol Mcond, Mrange, Mexist;
#define GLYPH_CODE_P(code) \
((code) >= GLYPH_CODE_MIN && (code) <= GLYPH_CODE_MAX)
SRC_REGEX,
SRC_INDEX,
SRC_SEQ,
- SRC_RANGE
+ SRC_RANGE,
+ SRC_EXIST
};
typedef struct
struct {
int from, to;
} range;
+ struct {
+ int c;
+ } exist;
} src;
int n_cmds;
MERROR (MERROR_FONT, NULL);
category_code = MPLIST_INTEGER (elt);
}
- if (! isalpha (category_code))
+ if (! isalnum (category_code))
MERROR (MERROR_FONT, NULL);
if (from == to)
cmd->body.rule.src.range.to
= (unsigned) MPLIST_INTEGER (pl);
}
+ else if (MPLIST_SYMBOL_P (pl) && size <= 2)
+ {
+ if (MPLIST_SYMBOL (pl) != Mexist)
+ MERROR (MERROR_FLT, INVALID_CMD_ID);
+ cmd->body.rule.src_type = SRC_EXIST;
+ if (size == 1)
+ cmd->body.rule.src.exist.c = -1;
+ else
+ {
+ pl = MPLIST_NEXT (pl);
+ if (! MPLIST_INTEGER_P (pl))
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+ cmd->body.rule.src.exist.c = MPLIST_INTEGER (pl);
+ }
+ }
else
MERROR (MERROR_DRAW, INVALID_CMD_ID);
}
if (i < len)
return 0;
to = from + len;
- MDEBUG_PRINT3 ("\n [FLT] %*s(SEQ 0x%X", depth, "",
- rule->src.seq.codes[0]);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s(SEQ 0x%X", depth, "",
+ rule->src.seq.codes[0]);
}
else if (rule->src_type == SRC_RANGE)
{
return 0;
ctx->code_offset = head - rule->src.range.from;
to = from + 1;
- MDEBUG_PRINT4 ("\n [FLT] %*s(RANGE 0x%X-0x%X", depth, "",
- rule->src.range.from, rule->src.range.to);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT4 ("\n [FLT] %*s(RANGE 0x%X-0x%X", depth, "",
+ rule->src.range.from, rule->src.range.to);
}
else if (rule->src_type == SRC_REGEX)
{
NMATCH, pmatch, 0);
if (result == 0 && pmatch[0].rm_so == 0)
{
- MDEBUG_PRINT5 ("\n [FLT] %*s(REGEX \"%s\" \"%s\" %d", depth, "",
- rule->src.re.pattern,
- ctx->encoded + from - ctx->encoded_offset,
- pmatch[0].rm_eo);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT5 ("\n [FLT] %*s(REGEX \"%s\" \"%s\" %d", depth, "",
+ rule->src.re.pattern,
+ ctx->encoded + from - ctx->encoded_offset,
+ pmatch[0].rm_eo);
ctx->encoded[to - ctx->encoded_offset] = saved_code;
for (i = 0; i < NMATCH; i++)
{
if (from < 0)
return 0;
to = ctx->match_indices[rule->src.match_idx * 2 + 1];
- MDEBUG_PRINT3 ("\n [FLT] %*s(INDEX %d", depth, "", rule->src.match_idx);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s(INDEX %d", depth, "", rule->src.match_idx);
+ }
+ else if (rule->src_type == SRC_EXIST)
+ {
+ MGlyph *g = MGLYPH (from);
+ int encoded = g->otf_encoded;
+ unsigned code;
+
+ if (rule->src.exist.c < 0)
+ {
+ if (from >= to)
+ return 0;
+ code = g->code;
+ to = from + 1;
+ }
+ else
+ {
+ code = rule->src.exist.c;
+ to = from;
+ encoded = 0;
+ }
+ if (! encoded)
+ {
+ code = (g->rface->rfont->driver->encode_char
+ (NULL, (MFont *) g->rface->rfont, NULL, code));
+ if (code == MCHAR_INVALID_CODE)
+ return 0;
+ }
}
consumed = 0;
}
ctx->match_indices = saved_match_indices;
- MDEBUG_PRINT (")");
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT (")");
return (rule->src_type == SRC_INDEX ? orig_from : to);
}
{
int i, pos = 0;
- MDEBUG_PRINT2 ("\n [FLT] %*s(COND", depth, "");
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT2 ("\n [FLT] %*s(COND", depth, "");
depth++;
for (i = 0; i < cond->n_cmds; i++)
{
}
if (pos < 0)
MERROR (MERROR_DRAW, -1);
- MDEBUG_PRINT (")");
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT (")");
return (pos);
}
#ifdef HAVE_OTF
int from_idx = gstring->used;
- MDEBUG_PRINT4 ("\n [FLT] %*s(OTF %s,%s)", depth, "",
- (! otf_cmd->features[MFONT_OTT_GSUB].str ? ""
- : otf_cmd->features[MFONT_OTT_GSUB].str),
- (! otf_cmd->features[MFONT_OTT_GPOS].str ? ""
- : otf_cmd->features[MFONT_OTT_GPOS].str));
+ if (MDEBUG_FLAG () > 2)
+#if 0
+ MDEBUG_PRINT4 ("\n [FLT] %*s(OTF %s,%s)", depth, "",
+ (! otf_cmd->features[MFONT_OTT_GSUB].str ? ""
+ : otf_cmd->features[MFONT_OTT_GSUB].str),
+ (! otf_cmd->features[MFONT_OTT_GPOS].str ? ""
+ : otf_cmd->features[MFONT_OTT_GPOS].str));
+#else
+ MDEBUG_PRINT3 ("\n [FLT] %*s:otf=%s", depth, "",
+ MSYMBOL_NAME (otf_cmd->otf));
+#endif
to = mfont__ft_drive_otf (gstring, from, to, otf_cmd);
if (ctx->cluster_begin_idx)
for (; from_idx < gstring->used; from_idx++)
/* Direct code (== id + ctx->code_offset) output.
The source is not consumed. */
- if (from < to)
+ if (from < to || from == 1)
g = *(MGLYPH (from));
else
g = *(MGLYPH (from - 1));
g.type = GLYPH_CHAR;
g.code = ctx->code_offset + id;
- MDEBUG_PRINT3 ("\n [FLT] %*s(DIRECT 0x%X", depth, "", g.code);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s(DIRECT 0x%X", depth, "", g.code);
if (ctx->combining_code)
g.combining_code = ctx->combining_code;
if (ctx->left_padding)
APPEND_GLYPH (gstring, g);
UPDATE_CLUSTER_RANGE (ctx, g);
ctx->code_offset = ctx->combining_code = ctx->left_padding = 0;
- MDEBUG_PRINT (")");
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT (")");
return (from);
}
if (id <= CMD_ID_OFFSET_COMBINING)
{
ctx->combining_code = CMD_ID_TO_COMBINING_CODE (id);
- MDEBUG_PRINT3 ("\n [FLT] %*s(CMB %s)", depth, "",
- dump_combining_code (ctx->combining_code));
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s(CMB %s)", depth, "",
+ dump_combining_code (ctx->combining_code));
return from;
}
g.left_padding = ctx->left_padding;
APPEND_GLYPH (gstring, g);
UPDATE_CLUSTER_RANGE (ctx, g);
- MDEBUG_PRINT3 ("\n [FLT] %*s(COPY 0x%X)", depth, "", g.code);
+ if (MDEBUG_FLAG () > 2)
+ {
+ if (g.type == GLYPH_PAD)
+ MDEBUG_PRINT2 ("\n [FLT] %*s(COPY |)", depth, "");
+ else
+ MDEBUG_PRINT3 ("\n [FLT] %*s(COPY 0x%X)", depth, "", g.code);
+ }
ctx->code_offset = ctx->combining_code = ctx->left_padding = 0;
return (from + 1);
}
case CMD_ID_CLUSTER_BEGIN:
if (! ctx->cluster_begin_idx)
{
- MDEBUG_PRINT3 ("\n [FLT] %*s<%d", depth, "", MGLYPH (from)->pos);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s<%d", depth, "", MGLYPH (from)->pos);
ctx->cluster_begin_idx = gstring->used;
ctx->cluster_begin_pos = MGLYPH (from)->pos;
ctx->cluster_end_pos = MGLYPH (from)->to;
{
int i;
- MDEBUG_PRINT1 (" %d>", ctx->cluster_end_pos);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT1 (" %d>", ctx->cluster_end_pos);
for (i = ctx->cluster_begin_idx; i < gstring->used; i++)
{
MGLYPH (i)->pos = ctx->cluster_begin_pos;
}
case CMD_ID_LEFT_PADDING:
- MDEBUG_PRINT2 ("\n [FLT] %*s[", depth, "");
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT2 ("\n [FLT] %*s[", depth, "");
ctx->left_padding = 1;
return from;
case CMD_ID_RIGHT_PADDING:
if (gstring->used > 0)
{
- MDEBUG_PRINT2 ("\n [FLT] %*s]", depth, "");
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT2 ("\n [FLT] %*s]", depth, "");
gstring->glyphs[gstring->used - 1].right_padding = 1;
}
return from;
Mcond = msymbol ("cond");
Mrange = msymbol ("range");
Mlayouter = msymbol ("layouter");
+ Mexist = msymbol ("exist");
flt_list = mplist ();
return 0;
}
from_pos = MGLYPH (from)->pos;
to_pos = MGLYPH (to)->pos;
+ if (MDEBUG_FLAG ())
+ {
+ MDEBUG_PRINT ("\n [FLT] (SOURCE");
+ for (i = from; i < to; i++)
+ {
+ if (i > from && (i - from) % 8 == 0)
+ MDEBUG_PRINT ("\n [FLT] ");
+ MDEBUG_PRINT1 (" %04X", MGLYPH (i)->c);
+ }
+ MDEBUG_PRINT (")");
+ }
+
for (stage_idx = 0; 1; stage_idx++)
{
int len = to - from;
int result;
ctx.code_offset = ctx.combining_code = ctx.left_padding = 0;
- MDEBUG_PRINT2 ("\n [FLT] (STAGE %d \"%s\"", stage_idx, ctx.encoded);
- if (mdebug__flag & mdebug_mask
- && ctx.encoded_offset < to)
+ if (MDEBUG_FLAG () > 2)
{
- if (gstring->glyphs[ctx.encoded_offset].type == GLYPH_PAD)
- fprintf (stderr, " (|");
- else
- fprintf (stderr, " (%X", gstring->glyphs[ctx.encoded_offset].code);
- for (i = ctx.encoded_offset + 1; i < to; i++)
+ MDEBUG_PRINT2 ("\n [FLT] (STAGE %d \"%s\"", stage_idx,
+ ctx.encoded + from - ctx.encoded_offset);
+ fprintf (stderr, " (");
+ for (i = from; i < to ; i++)
{
if (gstring->glyphs[i].type == GLYPH_PAD)
- fprintf (stderr, " |");
+ fprintf (stderr, "%*s|", (i > from), "");
else
- fprintf (stderr, " %X", gstring->glyphs[i].code);
+ fprintf (stderr, "%*s%04X", (i > from), "",
+ gstring->glyphs[i].code);
}
fprintf (stderr, ")");
}
result = run_command (4, INDEX_TO_CMD_ID (0), gstring,
ctx.encoded_offset, to, &ctx);
- MDEBUG_PRINT (")");
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT (")");
if (result < 0)
return -1;
to = from + (gstring->used - gidx);
latest = glyphs[i];
}
}
- MDEBUG_PRINT ("\n [FLT] (RESULT (");
- if (mdebug__flag & mdebug_mask
- && ctx.encoded_offset < to)
+ if (MDEBUG_FLAG ())
{
- if (gstring->glyphs[from].type == GLYPH_PAD)
- fprintf (stderr, "|");
- else
- fprintf (stderr, "%X", gstring->glyphs[from].code);
- for (from++; from < to; from++)
+ MDEBUG_PRINT ("\n [FLT] (RESULT");
+ for (i = from; i < to;)
{
- if (gstring->glyphs[from].type == GLYPH_PAD)
- fprintf (stderr, " |");
+ if (MGLYPH (i)->otf_encoded)
+ i++;
else
- fprintf (stderr, " %X", gstring->glyphs[from].code);
+ {
+ int j = i++;
+
+ while (i < to && ! MGLYPH (i)->otf_encoded) i++;
+ mfont__get_metric (gstring, j, i);
+ }
}
- fprintf (stderr, "))");
+ if (MDEBUG_FLAG () > 1)
+ for (i = 0; from < to; from++, i++)
+ {
+ MGlyph *g;
+ int width, xoff, yoff;
+
+ if (i > 0 && i % 4 == 0)
+ MDEBUG_PRINT ("\n [FLT] ");
+ g = MGLYPH (from);
+ g->otf_encoded = 1;
+ width = g->width, xoff = g->xoff, yoff = g->yoff;
+ if (g->right_padding && g->rbearing > g->width)
+ width = g->rbearing;
+ if (g->left_padding && g->lbearing < 0)
+ {
+ width += - g->lbearing;
+ xoff += - g->lbearing;
+ }
+ MDEBUG_PRINT4 (" (%04X %d %d %d)", g->code, width, xoff, yoff);
+ }
+ else
+ for (; from < to; from++)
+ {
+ MGLYPH (from)->otf_encoded = 1;
+ MDEBUG_PRINT1 (" %04X", MGLYPH (from)->code);
+ }
+ MDEBUG_PRINT ("))\n");
}
- MDEBUG_PRINT (")\n");
return to;
}
#include "plist.h"
#include "symbol.h"
#include "language.h"
+#include "internal-flt.h"
#include "internal-gui.h"
#include "font.h"
#include "face.h"
#include FT_BDF_H
#endif
-static int mdebug_mask = MDEBUG_FONT;
+static int mdebug_flag = MDEBUG_FONT;
#ifdef HAVE_FONTCONFIG
#include <fontconfig/fcfreetype.h>
}
static int
-ft_check_otf (MFontFT *ft_info, MFontCapability *cap, FT_Face ft_face)
+ft_check_cap_otf (MFontFT *ft_info, MFontCapability *cap, FT_Face ft_face)
{
#ifdef HAVE_OTF
if (ft_info->otf == invalid_otf)
{
for (pl = plist; ! MPLIST_TAIL_P (pl);)
{
- if (ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0)
+ if (ft_check_cap_otf (MPLIST_VAL (pl), cap, NULL) < 0)
mplist_pop (pl);
else
pl = MPLIST_NEXT (pl);
for (pl = plist; ! MPLIST_TAIL_P (pl);)
{
- if (cap->script_tag && ft_check_otf (MPLIST_VAL (pl), cap, NULL) < 0)
+ if (cap->script_tag && ft_check_cap_otf (MPLIST_VAL (pl), cap, NULL) < 0)
{
mplist_pop (pl);
continue;
rfont->driver = &mfont__ft_driver;
rfont->info = ft_rfont;
rfont->fontp = ft_face;
- rfont->ascent = ft_face->size->metrics.ascender >> 6;
- rfont->descent = - ft_face->size->metrics.descender >> 6;
- rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
+ rfont->ascent = ft_face->size->metrics.ascender;
+ rfont->descent = - ft_face->size->metrics.descender;
+ rfont->max_advance = ft_face->size->metrics.max_advance;
rfont->baseline_offset = 0;
+ rfont->x_ppem = ft_face->size->metrics.x_ppem;
+ rfont->y_ppem = ft_face->size->metrics.y_ppem;
#ifdef HAVE_FTBDF_H
{
BDF_PropertyRec prop;
if (! FT_IS_SCALABLE (ft_face)
&& FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
{
- rfont->baseline_offset = prop.u.integer;
- rfont->ascent += prop.u.integer;
- rfont->descent -= prop.u.integer;
+ rfont->baseline_offset = prop.u.integer << 6;
+ rfont->ascent += prop.u.integer << 6;
+ rfont->descent -= prop.u.integer << 6;
}
}
#endif /* HAVE_FTBDF_H */
if (FT_IS_SCALABLE (ft_face))
rfont->average_width = 0;
else
- rfont->average_width = ft_face->available_sizes->width;
+ rfont->average_width = ft_face->available_sizes->width << 6;
rfont->next = MPLIST_VAL (frame->realized_font_list);
MPLIST_VAL (frame->realized_font_list) = rfont;
MDEBUG_PRINT (" ok\n");
for (; g != gend; g++)
{
- if (g->code == MCHAR_INVALID_CODE)
+ if (g->g.measured)
+ continue;
+ if (g->g.code == MCHAR_INVALID_CODE)
{
if (FT_IS_SCALABLE (ft_face))
{
- unsigned unitsPerEm10 = ft_face->units_per_EM * 10;
- int size = rfont->spec.size;
-
- g->lbearing = 0;
- g->rbearing = ft_face->max_advance_width * size / unitsPerEm10;
- g->width = g->rbearing;
- g->ascent = ft_face->ascender * size / unitsPerEm10;
- g->descent = (- ft_face->descender) * size / unitsPerEm10;
+ g->g.lbearing = 0;
+ g->g.rbearing = ft_face->size->metrics.max_advance;
+ g->g.xadv = g->g.rbearing;
+ g->g.ascent = ft_face->size->metrics.ascender;
+ g->g.descent = - ft_face->size->metrics.descender;
}
else
{
BDF_PropertyRec prop;
#endif /* HAVE_FTBDF_H */
- g->lbearing = 0;
- g->rbearing = g->width = ft_face->available_sizes->width;
+ g->g.lbearing = 0;
+ g->g.rbearing = g->g.xadv = ft_face->available_sizes->width << 6;
#ifdef HAVE_FTBDF_H
if (FT_Get_BDF_Property (ft_face, "ASCENT", &prop) == 0)
{
- g->ascent = prop.u.integer;
+ g->g.ascent = prop.u.integer << 6;
FT_Get_BDF_Property (ft_face, "DESCENT", &prop);
- g->descent = prop.u.integer;
+ g->g.descent = prop.u.integer << 6;
if (FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET",
& prop) == 0)
{
- g->ascent += prop.u.integer;
- g->descent -= prop.u.integer;
+ g->g.ascent += prop.u.integer << 6;
+ g->g.descent -= prop.u.integer << 6;
}
}
else
#endif /* HAVE_FTBDF_H */
{
- g->ascent = ft_face->available_sizes->height;
- g->descent = 0;
+ g->g.ascent = ft_face->available_sizes->height << 6;
+ g->g.descent = 0;
}
}
}
{
FT_Glyph_Metrics *metrics;
- FT_Load_Glyph (ft_face, (FT_UInt) g->code, FT_LOAD_DEFAULT);
+ FT_Load_Glyph (ft_face, (FT_UInt) g->g.code, FT_LOAD_DEFAULT);
metrics = &ft_face->glyph->metrics;
- g->lbearing = (metrics->horiBearingX >> 6);
- g->rbearing = (metrics->horiBearingX + metrics->width) >> 6;
- g->width = metrics->horiAdvance >> 6;
- g->ascent = metrics->horiBearingY >> 6;
- g->descent = (metrics->height - metrics->horiBearingY) >> 6;
+ g->g.lbearing = metrics->horiBearingX;
+ g->g.rbearing = metrics->horiBearingX + metrics->width;
+ g->g.xadv = metrics->horiAdvance;
+ g->g.ascent = metrics->horiBearingY;
+ g->g.descent = metrics->height - metrics->horiBearingY;
}
- g->ascent += rfont->baseline_offset;
- g->descent -= rfont->baseline_offset;
+ g->g.yadv = 0;
+ g->g.ascent += rfont->baseline_offset;
+ g->g.descent -= rfont->baseline_offset;
+ g->g.measured = 1;
}
}
int i, j;
MPointTable point_table[8];
int baseline_offset;
+ int pixel_mode = -1;
if (from == to)
return;
/* It is assured that the all glyphs in the current range use the
same realized face. */
ft_face = rface->rfont->fontp;
- baseline_offset = rface->rfont->baseline_offset;
+ baseline_offset = rface->rfont->baseline_offset >> 6;
if (! gstring->anti_alias)
{
for (i = 0; i < 8; i++)
point_table[i].p = point_table[i].points;
- for (g = from; g < to; x += g++->width)
+ for (g = from; g < to; x += g++->g.xadv)
{
unsigned char *bmp;
int intensity;
int xoff, yoff;
int width, pitch;
- FT_Load_Glyph (ft_face, (FT_UInt) g->code, load_flags);
- yoff = y - ft_face->glyph->bitmap_top + g->yoff;
+ FT_Load_Glyph (ft_face, (FT_UInt) g->g.code, load_flags);
+ if (pixel_mode < 0)
+ pixel_mode = ft_face->glyph->bitmap.pixel_mode;
+ yoff = y - ft_face->glyph->bitmap_top + g->g.yoff;
bmp = ft_face->glyph->bitmap.buffer;
width = ft_face->glyph->bitmap.width;
pitch = ft_face->glyph->bitmap.pitch;
- if (! gstring->anti_alias)
- pitch *= 8;
- if (width > pitch)
- width = pitch;
- if (gstring->anti_alias)
+ if (pixel_mode != FT_PIXEL_MODE_MONO)
for (i = 0; i < ft_face->glyph->bitmap.rows;
i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
{
- xoff = x + ft_face->glyph->bitmap_left + g->xoff;
+ xoff = x + ft_face->glyph->bitmap_left + g->g.xoff;
for (j = 0; j < width; j++, xoff++)
{
intensity = bmp[j] >> 5;
for (i = 0; i < ft_face->glyph->bitmap.rows;
i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
{
- xoff = x + ft_face->glyph->bitmap_left + g->xoff;
+ xoff = x + ft_face->glyph->bitmap_left + g->g.xoff;
for (j = 0; j < width; j++, xoff++)
{
intensity = bmp[j / 8] & (1 << (7 - (j % 8)));
}
}
- if (gstring->anti_alias)
+ if (pixel_mode != FT_PIXEL_MODE_MONO)
{
for (i = 1; i < 8; i++)
if (point_table[i].p != point_table[i].points)
MRealizedFontFT *ft_rfont = rfont->info;
MFontCapability *cap = mfont__get_capability (capability);
- if (cap->script != Mnil
- && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0)
+ if (cap->script_tag)
+ {
+ if (ft_check_cap_otf (ft_info, cap, ft_rfont->ft_face) < 0)
+ return -1;
+ }
+ else if (cap->script != Mnil
+ && ft_check_script (ft_info, cap->script, ft_rfont->ft_face) < 0)
return -1;
if (cap->language != Mnil
&& ft_check_language (ft_info, cap->language, ft_rfont->ft_face) < 0)
return -1;
- if (cap->script_tag && ft_check_otf (ft_info, cap, ft_rfont->ft_face) < 0)
- return -1;
return 0;
}
rfont->descent = - ft_face->size->metrics.descender >> 6;
rfont->max_advance = ft_face->size->metrics.max_advance >> 6;
rfont->baseline_offset = 0;
+ rfont->x_ppem = ft_face->size->metrics.x_ppem;
+ rfont->y_ppem = ft_face->size->metrics.y_ppem;
#ifdef HAVE_FTBDF_H
{
BDF_PropertyRec prop;
if (! FT_IS_SCALABLE (ft_face)
&& FT_Get_BDF_Property (ft_face, "_MULE_BASELINE_OFFSET", &prop) == 0)
{
- rfont->baseline_offset = prop.u.integer;
- rfont->ascent += prop.u.integer;
- rfont->descent -= prop.u.integer;
+ rfont->baseline_offset = prop.u.integer << 6;
+ rfont->ascent += prop.u.integer << 6;
+ rfont->descent -= prop.u.integer << 6;
}
}
#endif /* HAVE_FTBDF_H */
if (FT_IS_SCALABLE (ft_face))
rfont->average_width = 0;
else
- rfont->average_width = ft_face->available_sizes->width;
+ rfont->average_width = ft_face->available_sizes->width << 6;
rfont->next = MPLIST_VAL (frame->realized_font_list);
MPLIST_VAL (frame->realized_font_list) = rfont;
free (rfont);
}
+static int
+ft_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
+{
+#ifdef HAVE_OTF
+ MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+ MFontFT *ft_info = (MFontFT *) rfont->font;
+ OTF *otf;
+ OTF_Tag *tags;
+ int i, n, negative;
+
+ if (ft_info->otf == invalid_otf)
+ goto not_otf;
+ otf = ft_info->otf;
+ if (! otf)
+ {
+ MRealizedFontFT *ft_rfont = rfont->info;
+
+#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
+ otf = OTF_open_ft_face (ft_rfont->ft_face);
+#else
+ otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
+#endif
+ if (! otf)
+ {
+ ft_info->otf = invalid_otf;
+ goto not_otf;
+ }
+ ft_info->otf = otf;
+ }
+
+ for (i = 0; i < 2; i++)
+ {
+ if (! spec->features[i])
+ continue;
+ for (n = 0; spec->features[i][n]; n++);
+ tags = alloca (sizeof (OTF_Tag) * n);
+ for (n = 0, negative = 0; spec->features[i][n]; n++)
+ {
+ if (spec->features[i][n] == 0xFFFFFFFF)
+ negative = 1;
+ else if (negative)
+ tags[n - 1] = spec->features[i][n] | 0x80000000;
+ else
+ tags[n] = spec->features[i][n];
+ }
+ if (n - negative > 0
+ && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
+ tags, n - negative) != 1)
+ return 0;
+ }
+ return 1;
+#endif /* HAVE_OTF */
+ not_otf:
+ return ((! spec->features[0] || spec->features[0][0] == 0xFFFFFFFF)
+ && (! spec->features[1] || spec->features[1][0] == 0xFFFFFFFF));
+}
+
+#ifdef HAVE_OTF
+
+#define DEVICE_DELTA(table, size) \
+ (((size) >= (table).StartSize && (size) <= (table).EndSize) \
+ ? (table).DeltaValue[(size) - (table).StartSize] << 6 \
+ : 0)
+
+void
+adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
+ unsigned code, int x_ppem, int y_ppem, int *x, int *y)
+{
+ if (anchor->AnchorFormat == 2)
+ {
+ FT_Outline *outline;
+ int ap = anchor->f.f1.AnchorPoint;
+
+ FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
+ outline = &ft_face->glyph->outline;
+ if (ap < outline->n_points)
+ {
+ *x = outline->points[ap].x << 6;
+ *y = outline->points[ap].y << 6;
+ }
+ }
+ else if (anchor->AnchorFormat == 3)
+ {
+ if (anchor->f.f2.XDeviceTable.offset)
+ *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, x_ppem);
+ if (anchor->f.f2.YDeviceTable.offset)
+ *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, y_ppem);
+ }
+}
+#endif /* HAVE_OTF */
+
+static int
+ft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
+ MFLTGlyphString *in, int from, int to,
+ MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
+{
+ int len = to - from;
+ int i, j, gidx;
+ MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+ MRealizedFontFT *ft_rfont = rfont->info;
+ MFontFT *ft_info = (MFontFT *) rfont->font;
+#ifdef HAVE_OTF
+ MGlyph *in_glyphs = (MGlyph *) (in->glyphs);
+ MGlyph *out_glyphs = (MGlyph *) (out->glyphs);
+ OTF *otf;
+ OTF_GlyphString otf_gstring;
+ OTF_Glyph *otfg;
+ char script[5], *langsys = NULL;
+ char *gsub_features = NULL, *gpos_features = NULL;
+
+ if (len == 0)
+ return from;
+ if (ft_info->otf == invalid_otf)
+ goto simple_copy;
+ otf = ft_info->otf;
+ if (! otf)
+ {
+ MRealizedFontFT *ft_rfont = rfont->info;
+
+#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
+ otf = OTF_open_ft_face (ft_rfont->ft_face);
+#else
+ otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
+#endif
+ if (! otf)
+ {
+ ft_info->otf = invalid_otf;
+ goto simple_copy;
+ }
+ ft_info->otf = otf;
+ }
+
+ if (OTF_get_table (otf, "head") < 0)
+ {
+ OTF_close (otf);
+ ft_info->otf = invalid_otf;
+ goto simple_copy;
+ }
+
+ OTF_tag_name (spec->script, script);
+ if (spec->langsys)
+ {
+ langsys = alloca (5);
+ OTF_tag_name (spec->langsys, langsys);
+ }
+ for (i = 0; i < 2; i++)
+ {
+ char *p;
+
+ if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
+ {
+ for (j = 0; spec->features[i][j]; j++);
+ if (i == 0)
+ p = gsub_features = alloca (6 * j);
+ else
+ 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);
+ for (i = 0; i < len; i++)
+ {
+ otf_gstring.glyphs[i].c = ((MGlyph *)in->glyphs)[from + i].g.c;
+ otf_gstring.glyphs[i].glyph_id = ((MGlyph *)in->glyphs)[from + i].g.code;
+ }
+
+ OTF_drive_gdef (otf, &otf_gstring);
+ gidx = out->used;
+
+ if (gsub_features)
+ {
+ if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
+ < 0)
+ goto simple_copy;
+ if (out->allocated < out->used + otf_gstring.used)
+ return -2;
+ for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
+ {
+ MGlyph *g = out_glyphs + out->used;
+ int j;
+
+ *g = in_glyphs[from + otfg->f.index.from];
+ g->g.c = 0;
+ for (j = from + otfg->f.index.from; j <= from + otfg->f.index.to; j++)
+ if (in_glyphs[j].g.code == otfg->glyph_id)
+ {
+ g->g.c = in_glyphs[j].g.c;
+ break;
+ }
+ if (g->g.code != otfg->glyph_id)
+ {
+ g->g.code = otfg->glyph_id;
+ g->g.measured = 0;
+ }
+ out->used++;
+ }
+ }
+ else
+ {
+ if (out->allocated < out->used + len)
+ return -2;
+ for (i = 0; i < len; i++)
+ out_glyphs[out->used++] = in_glyphs[from + i];
+ }
+
+ if (gpos_features)
+ {
+ FT_Face face;
+ MGlyph *base = NULL, *mark = NULL, *g;
+ int x_ppem, y_ppem, x_scale, y_scale;
+
+ if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
+ < 0)
+ return to;
+
+ face = ft_rfont->ft_face;
+ x_ppem = face->size->metrics.x_ppem;
+ y_ppem = face->size->metrics.y_ppem;
+ x_scale = face->size->metrics.x_scale;
+ y_scale = face->size->metrics.y_scale;
+
+ for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
+ i < otf_gstring.used; i++, otfg++, g++)
+ {
+ MGlyph *prev;
+
+ if (! otfg->glyph_id)
+ continue;
+ switch (otfg->positioning_type)
+ {
+ case 0:
+ break;
+ case 1: /* Single */
+ case 2: /* Pair */
+ {
+ int format = otfg->f.f1.format;
+
+ if (format & OTF_XPlacement)
+ adjustment[i].xoff
+ = otfg->f.f1.value->XPlacement * x_scale / 0x10000;
+ if (format & OTF_XPlaDevice)
+ adjustment[i].xoff
+ += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, x_ppem);
+ if (format & OTF_YPlacement)
+ adjustment[i].yoff
+ = - (otfg->f.f1.value->YPlacement * y_scale / 0x10000);
+ if (format & OTF_YPlaDevice)
+ adjustment[i].yoff
+ -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, y_ppem);
+ if (format & OTF_XAdvance)
+ adjustment[i].xadv
+ += otfg->f.f1.value->XAdvance * x_scale / 0x10000;
+ if (format & OTF_XAdvDevice)
+ adjustment[i].xadv
+ += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, x_ppem);
+ if (format & OTF_YAdvance)
+ adjustment[i].yadv
+ += otfg->f.f1.value->YAdvance * y_scale / 0x10000;
+ if (format & OTF_YAdvDevice)
+ adjustment[i].yadv
+ += DEVICE_DELTA (otfg->f.f1.value->YAdvDevice, y_ppem);
+ adjustment[i].set = 1;
+ }
+ break;
+ case 3: /* Cursive */
+ /* Not yet supported. */
+ break;
+ case 4: /* Mark-to-Base */
+ case 5: /* Mark-to-Ligature */
+ if (! base)
+ break;
+ prev = base;
+ goto label_adjust_anchor;
+ default: /* i.e. case 6 Mark-to-Mark */
+ if (! mark)
+ break;
+ prev = mark;
+
+ label_adjust_anchor:
+ {
+ int base_x, base_y, mark_x, mark_y;
+ int this_from, this_to;
+
+ base_x = otfg->f.f4.base_anchor->XCoordinate * x_scale / 0x10000;
+ base_y = otfg->f.f4.base_anchor->YCoordinate * y_scale / 0x10000;
+ mark_x = otfg->f.f4.mark_anchor->XCoordinate * x_scale / 0x10000;
+ mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;;
+
+ if (otfg->f.f4.base_anchor->AnchorFormat != 1)
+ adjust_anchor (otfg->f.f4.base_anchor, face, prev->g.code,
+ x_ppem, y_ppem, &base_x, &base_y);
+ if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
+ adjust_anchor (otfg->f.f4.mark_anchor, face, g->g.code,
+ x_ppem, y_ppem, &mark_x, &mark_y);
+ adjustment[i].xoff = (base_x - mark_x);
+ adjustment[i].yoff = - (base_y - mark_y);
+ adjustment[i].back = (g - prev);
+ adjustment[i].xadv = 0;
+ adjustment[i].advance_is_absolute = 1;
+ adjustment[i].set = 1;
+ this_from = g->g.from;
+ this_to = g->g.to;
+ for (j = 0; prev + j < g; j++)
+ {
+ if (this_from > prev[j].g.from)
+ this_from = prev[j].g.from;
+ if (this_to < prev[j].g.to)
+ this_to = prev[j].g.to;
+ }
+ for (; prev <= g; prev++)
+ {
+ prev->g.from = this_from;
+ prev->g.to = this_to;
+ }
+ }
+ }
+ if (otfg->GlyphClass == OTF_GlyphClass0)
+ base = mark = g;
+ else if (otfg->GlyphClass == OTF_GlyphClassMark)
+ mark = g;
+ else
+ base = g;
+ }
+ }
+ free (otf_gstring.glyphs);
+ return to;
+
+ simple_copy:
+#endif /* HAVE_OTF */
+ if (out->allocated < out->used + len)
+ return -2;
+ font->get_metrics (font, in, from, to);
+ memcpy ((MGlyph *)out->glyphs + out->used, (MGlyph *) in->glyphs + from,
+ sizeof (MGlyph) * len);
+ out->used += len;
+ if (otf_gstring.glyphs)
+ free (otf_gstring.glyphs);
+ return to;
+}
\f
/* Internal API */
MFontDriver mfont__ft_driver =
{ ft_select, ft_open, ft_find_metric, ft_has_char, ft_encode_char,
ft_render, ft_list, ft_list_family_names, ft_check_capability,
- ft_encapsulate, ft_close };
+ ft_encapsulate, ft_close, ft_check_otf, ft_drive_otf };
int
mfont__ft_init ()
msymbol_put (monospace, Mgeneric_family, monospace);
msymbol_put (msymbol ("mono"), Mgeneric_family, monospace);
}
-#endif
+#endif /* HAVE_FONTCONFIG */
return 0;
}
}
#endif /* HAVE_FONTCONFIG */
-\f
-#ifdef HAVE_OTF
-
-#define DEVICE_DELTA(table, size) \
- (((size) >= (table).StartSize && (size) <= (table).EndSize) \
- ? (table).DeltaValue[(size) - (table).StartSize] \
- : 0)
-
-void
-adjust_anchor (OTF_Anchor *anchor, FT_Face ft_face,
- unsigned code, int size, int *x, int *y)
-{
- if (anchor->AnchorFormat == 2)
- {
- FT_Outline *outline;
- int ap = anchor->f.f1.AnchorPoint;
-
- FT_Load_Glyph (ft_face, (FT_UInt) code, FT_LOAD_MONOCHROME);
- outline = &ft_face->glyph->outline;
- if (ap < outline->n_points)
- {
- *x = outline->points[ap].x;
- *y = outline->points[ap].y;
- }
- }
- else if (anchor->AnchorFormat == 3)
- {
- if (anchor->f.f2.XDeviceTable.offset)
- *x += DEVICE_DELTA (anchor->f.f2.XDeviceTable, size);
- if (anchor->f.f2.YDeviceTable.offset)
- *y += DEVICE_DELTA (anchor->f.f2.YDeviceTable, size);
- }
-}
-
-int
-mfont__ft_drive_otf (MGlyphString *gstring, int from, int to,
- MFontCapability *cap)
-{
- int len = to - from;
- MGlyph *g = MGLYPH (from);
- int i, gidx;
- MRealizedFont *rfont;
- MFontFT *ft_info;
- OTF *otf;
- OTF_GlyphString otf_gstring;
- OTF_Glyph *otfg;
- char *script, *langsys;
- char *gsub_features, *gpos_features;
- int need_cmap;
-
- if (len == 0)
- return from;
-
- otf_gstring.glyphs = NULL;
- rfont = g->rface->rfont;
- ft_info = (MFontFT *) rfont->font;
- if (ft_info->otf == invalid_otf)
- goto simple_copy;
- otf = ft_info->otf;
- if (! otf)
- {
- MRealizedFontFT *ft_rfont = rfont->info;
-
-#if (LIBOTF_MAJOR_VERSION > 0 || LIBOTF_MINOR_VERSION > 9 || LIBOTF_RELEASE_NUMBER > 4)
- otf = OTF_open_ft_face (ft_rfont->ft_face);
-#else
- otf = OTF_open (MSYMBOL_NAME (ft_info->font.file));
-#endif
- if (! otf)
- {
- ft_info->otf = invalid_otf;
- goto simple_copy;
- }
- ft_info->otf = otf;
- }
- if (OTF_get_table (otf, "head") < 0)
- {
- OTF_close (otf);
- ft_info->otf = invalid_otf;
- goto simple_copy;
- }
-
- if (cap->script_tag)
- {
- script = alloca (5);
- OTF_tag_name (cap->script_tag, script);
- }
- else
- script = NULL;
- if (cap->langsys_tag)
- {
- langsys = alloca (5);
- OTF_tag_name (cap->langsys_tag, langsys);
- }
- else
- langsys = NULL;
- gsub_features = cap->features[MFONT_OTT_GSUB].str;
- if (gsub_features && OTF_check_table (otf, "GSUB") < 0)
- gsub_features = NULL;
- gpos_features = cap->features[MFONT_OTT_GPOS].str;
- if (gpos_features && OTF_check_table (otf, "GPOS") < 0)
- gpos_features = NULL;
-
- 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);
- for (i = 0, need_cmap = 0; i < len; i++)
- {
- if (gstring->glyphs[from + i].otf_encoded)
- {
- otf_gstring.glyphs[i].c = gstring->glyphs[from + i].c;
- otf_gstring.glyphs[i].glyph_id = gstring->glyphs[from + i].code;
- }
- else
- {
- otf_gstring.glyphs[i].c = gstring->glyphs[from + i].code;
- need_cmap++;
- }
- }
- if (need_cmap
- && OTF_drive_cmap (otf, &otf_gstring) < 0)
- goto simple_copy;
-
- OTF_drive_gdef (otf, &otf_gstring);
- gidx = gstring->used;
-
- if (gsub_features)
- {
- if (OTF_drive_gsub (otf, &otf_gstring, script, langsys, gsub_features)
- < 0)
- goto simple_copy;
- for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; i++, otfg++)
- {
- MGlyph temp = *(MGLYPH (from + otfg->f.index.from));
-
- temp.c = otfg->c;
- temp.combining_code = 0;
- if (otfg->glyph_id)
- {
- temp.code = otfg->glyph_id;
- temp.otf_encoded = 1;
- }
- else
- {
- temp.code = temp.c;
- temp.otf_encoded = 0;
- }
- temp.to = MGLYPH (from + otfg->f.index.to)->to;
- MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
- }
- }
- else
- for (i = 0; i < len; i++)
- {
- MGlyph temp = gstring->glyphs[from + i];
-
- if (otf_gstring.glyphs[i].glyph_id)
- {
- temp.code = otf_gstring.glyphs[i].glyph_id;
- temp.otf_encoded = 1;
- }
- MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
- }
-
- (rfont->driver->find_metric) (rfont, gstring, gidx, gstring->used);
-
- if (gpos_features)
- {
- int u;
- int size10, size;
- MGlyph *base = NULL, *mark = NULL;
-
- if (OTF_check_features (otf, 0,
- cap->script_tag, cap->langsys_tag,
- cap->features[MFONT_OTT_GPOS].tags,
- cap->features[MFONT_OTT_GPOS].nfeatures) != 1
- || (OTF_drive_gpos (otf, &otf_gstring, script, langsys,
- gpos_features) < 0))
- return to;
-
- u = otf->head->unitsPerEm;
- size10 = rfont->spec.size;
- size = size10 / 10;
-
- for (i = 0, otfg = otf_gstring.glyphs, g = MGLYPH (gidx);
- i < otf_gstring.used; i++, otfg++, g++)
- {
- MGlyph *prev;
-
- if (! otfg->glyph_id)
- continue;
- switch (otfg->positioning_type)
- {
- case 0:
- break;
- case 1: case 2:
- {
- int format = otfg->f.f1.format;
-
- if (format & OTF_XPlacement)
- g->xoff = otfg->f.f1.value->XPlacement * size10 / u / 10;
- if (format & OTF_XPlaDevice)
- g->xoff += DEVICE_DELTA (otfg->f.f1.value->XPlaDevice, size);
- if (format & OTF_YPlacement)
- g->yoff = - (otfg->f.f1.value->YPlacement * size10 / u / 10);
- if (format & OTF_YPlaDevice)
- g->yoff -= DEVICE_DELTA (otfg->f.f1.value->YPlaDevice, size);
- if (format & OTF_XAdvance)
- g->width += otfg->f.f1.value->XAdvance * size10 / u / 10;
- if (format & OTF_XAdvDevice)
- g->width += DEVICE_DELTA (otfg->f.f1.value->XAdvDevice, size);
- }
- break;
- case 3:
- /* Not yet supported. */
- break;
- case 4: case 5:
- if (! base)
- break;
- prev = base;
- goto label_adjust_anchor;
- default: /* i.e. case 6 */
- if (! mark)
- break;
- prev = mark;
-
- label_adjust_anchor:
- {
- int base_x, base_y, mark_x, mark_y;
-
- base_x = otfg->f.f4.base_anchor->XCoordinate * size10 / u / 10;
- base_y = otfg->f.f4.base_anchor->YCoordinate * size10 / u / 10;
- mark_x = otfg->f.f4.mark_anchor->XCoordinate * size10 / u / 10;
- mark_y = otfg->f.f4.mark_anchor->YCoordinate * size10 / u / 10;
-
- if (otfg->f.f4.base_anchor->AnchorFormat != 1)
- adjust_anchor (otfg->f.f4.base_anchor, rfont->fontp,
- prev->code, size, &base_x, &base_y);
- if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
- adjust_anchor (otfg->f.f4.mark_anchor, rfont->fontp,
- g->code, size, &mark_x, &mark_y);
- g->xoff = prev->xoff + (base_x - prev->width) - mark_x;
- g->yoff = prev->yoff + mark_y - base_y;
- g->combining_code = MAKE_PRECOMPUTED_COMBINDING_CODE ();
- }
- }
- if (otfg->GlyphClass == OTF_GlyphClass0)
- base = mark = g;
- else if (otfg->GlyphClass == OTF_GlyphClassMark)
- mark = g;
- else
- base = g;
- }
- }
- free (otf_gstring.glyphs);
- return to;
-
- simple_copy:
- for (i = 0; i < len; i++)
- {
- MGlyph *g = MGLYPH (from + i);
-
- if (! g->otf_encoded)
- {
- g->code = rfont->driver->encode_char (gstring->frame, (MFont *) rfont,
- NULL, g->code);
- g->otf_encoded = 1;
- }
- }
-
- rfont->driver->find_metric (rfont, gstring, from, to);
- for (i = 0; i < len; i++)
- {
- MGlyph temp = gstring->glyphs[from + i];
- MLIST_APPEND1 (gstring, glyphs, temp, MERROR_FONT_OTF);
- }
- if (otf_gstring.glyphs)
- free (otf_gstring.glyphs);
- return to;
-}
-
-
-int
-mfont__ft_decode_otf (MGlyph *g)
-{
- MFontFT *ft_info = (MFontFT *) g->rface->rfont->font;
- int c = OTF_get_unicode (ft_info->otf, (OTF_GlyphID) g->code);
-
- return (c ? c : -1);
-}
-
-#endif /* HAVE_OTF */
-
#endif /* HAVE_FREETYPE */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include "m17n-gui.h"
#include "m17n-misc.h"
if (mfont__ft_init () < 0)
return -1;
#endif /* HAVE_FREETYPE */
- if (mfont__flt_init () < 0)
- return -1;
return 0;
}
MPlist *plist;
int i;
- mfont__flt_fini ();
#ifdef HAVE_FREETYPE
mfont__ft_fini ();
#endif /* HAVE_FREETYPE */
MGlyph *from_g = MGLYPH (from), *to_g = MGLYPH (to), *g;
MRealizedFont *rfont = from_g->rface->rfont;
- for (g = from_g; g != to_g; g++)
- if (g->rface->rfont != rfont)
+ for (g = from_g; ; g++)
+ if (g == to_g || g->rface->rfont != rfont)
{
int idx = GLYPH_INDEX (g);
(rfont->driver->find_metric) (rfont, gstring, from, idx);
- from_g = g;
+ while (from_g < g)
+ {
+ from_g->g.xadv >>= 6;
+ from_g->g.yadv >>= 6;
+ from_g->g.xoff >>= 6;
+ from_g->g.yoff >>= 6;
+ from_g->g.ascent >>= 6;
+ from_g->g.descent >>= 6;
+ from_g->g.lbearing >>= 6;
+ from_g->g.rbearing >>= 6;
+ from_g++;
+ }
+ if (g == to_g)
+ break;
rfont = g->rface->rfont;
from = idx;
}
- (rfont->driver->find_metric) (rfont, gstring, from, GLYPH_INDEX (g));
}
+int
+mfont__get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring,
+ int from, int to)
+{
+ MFont *mfont = (MFont *) ((MFLTFontForRealized *) font)->rfont;
+ MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+ MFontEncoding *encoding;
+ MFontDriver *driver = NULL;
+ MGlyph *glyphs = (MGlyph *) gstring->glyphs;
+
+ encoding = mfont->encoding ? mfont->encoding : find_encoding (mfont);
+ for (; from < to; from++)
+ {
+ MGlyph *g = glyphs + from;
+
+ if (g->g.encoded)
+ continue;
+ if (! encoding->encoding_charset)
+ g->g.code = MCHAR_INVALID_CODE;
+ else if (mfont->source == MFONT_SOURCE_X && encoding->repertory_charset)
+ g->g.code = ENCODE_CHAR (encoding->repertory_charset, g->g.c);
+ else
+ {
+ g->g.code = ENCODE_CHAR (encoding->encoding_charset, g->g.c);
+ if (g->g.code != MCHAR_INVALID_CODE)
+ {
+ if (! driver)
+ {
+ if (mfont->type == MFONT_TYPE_REALIZED)
+ driver = rfont->driver;
+ else
+ {
+ driver = mplist_get (rfont->frame->font_driver_list,
+ mfont->source == MFONT_SOURCE_X
+ ? Mx : Mfreetype);
+ if (! driver)
+ MFATAL (MERROR_FONT);
+ }
+ }
+ g->g.code
+ = (driver->encode_char) (rfont->frame, rfont->font, mfont,
+ g->g.code);
+ }
+ }
+ g->g.encoded = 1;
+ }
+ return 0;
+}
+
+int
+mfont__get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
+ int from, int to)
+{
+ MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+ MGlyphString gstr;
+
+ gstr.glyphs = (MGlyph *) gstring->glyphs;
+ (rfont->driver->find_metric) (rfont, &gstr, from, to);
+ return 0;
+}
/* KEY <= MFONT_REGISTRY */
non-NULL, it must be a pointer to a managed object. */
void *info;
+ int x_ppem, y_ppem;
+
int ascent, descent, max_advance, average_width, baseline_offset;
/* Pointer to the font structure. */
MRealizedFont *next;
};
+typedef struct MFLTFontForRealized {
+ MFLTFont font;
+ MRealizedFont *rfont;
+} MFLTFontForRealized;
+
typedef struct {
MFont *font;
int score;
MRealizedFont *(*encapsulate) (MFrame *frame, MSymbol source, void *data);
void (*close) (MRealizedFont *rfont);
+
+ int (*check_otf) (MFLTFont *font, MFLTOtfSpec *spec);
+
+ int (*drive_otf) (MFLTFont *font, MFLTOtfSpec *spec,
+ MFLTGlyphString *in, int from, int to,
+ MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment);
};
/** Initialize the members of FONT. */
extern unsigned mfont__encode_char (MFrame *frame, MFont *font, MFont *spec,
int c);
+extern int mfont__get_glyph_id (MFLTFont *font, MFLTGlyphString *gstring,
+ int from, int to);
+
extern MFont *mfont__select (MFrame *frame, MFont *font, int max_size);
extern MFontList *mfont__list (MFrame *frame, MFont *spec, MFont *request,
extern void mfont__get_metric (MGlyphString *gstring, int from, int to);
+extern int mfont__get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
+ int from, int to);
+
extern void mfont__set_property (MFont *font, enum MFontProperty key,
MSymbol val);
/* Check if this font can display all glyphs. */
for (j = 0; j < *num; j++)
{
- int c = g[j].type == GLYPH_CHAR ? g[j].c : ' ';
+ int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' ';
+ MFLT *flt;
+ MCharTable *coverage;
+
if (layouter != Mt
- ? mfont__flt_encode_char (layouter, c) == MCHAR_INVALID_CODE
+ ? ((flt = mflt_get (layouter))
+ ? (coverage = mflt_coverage (flt),
+ ! mchartable_lookup (coverage, c))
+ : 0)
: ! mfont__has_char (frame, font, &font_list->object, c))
break;
}
continue;
if (j == *num || !all)
{
+ MCharTable *coverage = NULL;
+
/* We found a font that can display the requested range of
glyphs. */
if (font->type == MFONT_TYPE_REALIZED)
font_list->fonts[i].font = (MFont *) rfont;
}
rfont->layouter = layouter == Mt ? Mnil : layouter;
+ if (rfont->layouter)
+ {
+ MFLT *flt = mflt_get (rfont->layouter);
+
+ if (flt)
+ coverage = mflt_coverage (flt);
+ }
*num = j;
for (j = 0; j < *num; j++)
{
- int c = g[j].type == GLYPH_CHAR ? g[j].c : ' ';
+ int c = g[j].type == GLYPH_CHAR ? g[j].g.c : ' ';
- g[j].code = (rfont->layouter
- ? mfont__flt_encode_char (rfont->layouter, c)
- : mfont__encode_char (frame, (MFont *) rfont,
- &font_list->object, c));
+ g[j].g.code = (coverage
+ ? (unsigned ) mchartable_lookup (coverage, c)
+ : mfont__encode_char (frame, (MFont *) rfont,
+ &font_list->object, c));
}
return rfont;
}
#include <dlfcn.h>
#endif
-#include "m17n-gui.h"
+#include "m17n.h"
#include "m17n-misc.h"
#include "internal.h"
#include "mtext.h"
#include "database.h"
#include "charset.h"
-static int mdebug_mask = MDEBUG_INPUT;
+static int mdebug_flag = MDEBUG_INPUT;
static int fully_initialized;
state = (MIMState *) MPLIST_VAL (im_info->states);
}
- if (mdebug__flag & mdebug_mask)
+ if (MDEBUG_FLAG ())
{
if (orig_state)
MDEBUG_PRINT2 ("\n [IM] [%s] (shift %s)\n",
mtext_put_prop_values (ic->preedit, 0, mtext_nchars (ic->preedit),
Mcandidate_index, NULL, 0);
mtext_cat (ic->produced, ic->preedit);
- if (mdebug__flag & mdebug_mask)
+ if (MDEBUG_FLAG ())
{
int i;
if (mtext_nchars (ic->produced) > 0)
{
- if (mdebug__flag & mdebug_mask)
+ if (MDEBUG_FLAG ())
{
MDEBUG_PRINT1 ("\n [IM] [%s] (produced",
MSYMBOL_NAME (ic_info->state->name));
--- /dev/null
+/* internal-flt.h -- common header file for the internal FLT API.
+ Copyright (C) 2007
+ National Institute of Advanced Industrial Science and Technology (AIST)
+ Registration Number H15PRO112
+
+ This file is part of the m17n library.
+
+ The m17n library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ The m17n library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the m17n library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ 02111-1307, USA. */
+
+#ifndef _M_INTERNAL_FLT_H
+#define _M_INTERNAL_FLT_H
+
+#define MAKE_COMBINING_CODE(base_y, base_x, add_y, add_x, off_y, off_x) \
+ (((off_y) << 16) \
+ | ((off_x) << 8) \
+ | ((base_x) << 6) \
+ | ((base_y) << 4) \
+ | ((add_x) << 2) \
+ | (add_y))
+
+#define COMBINING_CODE_OFF_Y(code) ((((code) >> 16) & 0xFF) - 128)
+#define COMBINING_CODE_OFF_X(code) ((((code) >> 8) & 0xFF) - 128)
+#define COMBINING_CODE_BASE_X(code) (((code) >> 6) & 0x3)
+#define COMBINING_CODE_BASE_Y(code) (((code) >> 4) & 0x3)
+#define COMBINING_CODE_ADD_X(code) (((code) >> 2) & 0x3)
+#define COMBINING_CODE_ADD_Y(code) ((code) & 0x3)
+
+#define MAKE_COMBINING_CODE_BY_CLASS(class) (0x1000000 | class)
+
+#define COMBINING_BY_CLASS_P(code) ((code) & 0x1000000)
+
+#define COMBINING_CODE_CLASS(code) ((code) & 0xFFFFFF)
+
+#define MAKE_PRECOMPUTED_COMBINDING_CODE() (0x2000000)
+
+#define COMBINING_PRECOMPUTED_P(code) ((code) & 0x2000000)
+
+extern MSymbol Mcombining;
+
+#endif /* _M_INTERNAL_FLT_H */
typedef struct
{
- int pos, to;
- int c;
- unsigned code;
+ MFLTGlyph g;
MRealizedFace *rface;
- short width, ascent, descent, lbearing, rbearing;
- short xoff, yoff;
- unsigned enabled : 1;
unsigned left_padding : 1;
unsigned right_padding : 1;
- unsigned otf_encoded : 1;
+ unsigned enabled : 1;
unsigned bidi_level : 6;
unsigned category : 2;
unsigned type : 3;
- int combining_code;
} MGlyph;
struct MGlyphString
(gstring)->used -= newlen; \
} while (0)
-#define MAKE_COMBINING_CODE(base_y, base_x, add_y, add_x, off_y, off_x) \
- (((off_y) << 16) \
- | ((off_x) << 8) \
- | ((base_x) << 6) \
- | ((base_y) << 4) \
- | ((add_x) << 2) \
- | (add_y))
-
-#define COMBINING_CODE_OFF_Y(code) (((code) >> 16) & 0xFF)
-#define COMBINING_CODE_OFF_X(code) (((code) >> 8) & 0xFF)
-#define COMBINING_CODE_BASE_X(code) (((code) >> 6) & 0x3)
-#define COMBINING_CODE_BASE_Y(code) (((code) >> 4) & 0x3)
-#define COMBINING_CODE_ADD_X(code) (((code) >> 2) & 0x3)
-#define COMBINING_CODE_ADD_Y(code) ((code) & 0x3)
-
-#define MAKE_COMBINING_CODE_BY_CLASS(class) (0x1000000 | class)
-
-#define COMBINING_BY_CLASS_P(code) ((code) & 0x1000000)
-
-#define COMBINING_CODE_CLASS(code) ((code) & 0xFFFFFF)
-
-#define MAKE_PRECOMPUTED_COMBINDING_CODE() (0x2000000)
-
-#define COMBINING_PRECOMPUTED_P(code) ((code) & 0x2000000)
-
typedef struct MGlyphString MGlyphString;
typedef struct
MEMORY_FULL (err); \
} while (0)
+#define MTABLE_CALLOC_SAFE(p, size) \
+ ((p) = (void *) calloc (sizeof (*(p)), (size)))
+
/** The macro MTABLE_REALLOC () changes the size of memory block
pointed to by P to a size suitable for an array of SIZE objects.
#define MSTRUCT_CALLOC(p, err) MTABLE_CALLOC ((p), 1, (err))
+#define MSTRUCT_CALLOC_SAFE(p) MTABLE_CALLOC_SAFE ((p), 1)
+
#define USE_SAFE_ALLOCA \
int sa_must_free = 0, sa_size = 0
extern void mdebug__add_object_array (M17NObjectArray *array, char *name);
#define M17N_OBJECT_ADD_ARRAY(array, name) \
- if (mdebug__flag & MDEBUG_FINI) \
+ if (mdebug__flags[MDEBUG_FINI]) \
mdebug__add_object_array (&array, name); \
else
extern void mdebug__register_object (M17NObjectArray *array, void *object);
#define M17N_OBJECT_REGISTER(array, object) \
- if (mdebug__flag & MDEBUG_FINI) \
+ if (mdebug__flags[MDEBUG_FINI]) \
mdebug__register_object (&array, object); \
else
extern void mdebug__unregister_object (M17NObjectArray *array, void *object);
#define M17N_OBJECT_UNREGISTER(array, object) \
- if (mdebug__flag & MDEBUG_FINI) \
+ if (mdebug__flags[MDEBUG_FINI]) \
mdebug__unregister_object (&array, object); \
else
\f
-enum MDebugMaskBit
+enum MDebugFlag
{
- MDEBUG_INIT = 0x01,
- MDEBUG_FINI = 0x02,
- MDEBUG_CHARSET = 0x04,
- MDEBUG_CODING = 0x08,
- MDEBUG_DATABASE = 0x10,
- MDEBUG_FONT = 0x0100,
- MDEBUG_FONT_FLT = 0x0200,
- MDEBUG_FONT_OTF = 0x0400,
- MDEBUG_INPUT = 0x0800,
- MDEBUG_ALL = 0xFFFF,
- MDEBUG_MAX
+ MDEBUG_INIT,
+ MDEBUG_FINI,
+ MDEBUG_CHARSET,
+ MDEBUG_CODING,
+ MDEBUG_DATABASE,
+ MDEBUG_FONT,
+ MDEBUG_FONT_FLT,
+ MDEBUG_FONT_OTF,
+ MDEBUG_INPUT,
+ MDEBUG_ALL,
+ MDEBUG_MAX = MDEBUG_ALL
};
-extern int mdebug__flag;
+extern int mdebug__flags[MDEBUG_MAX];
extern FILE *mdebug__output;
extern void mdebug__push_time ();
extern void mdebug__pop_time ();
extern void mdebug__print_time ();
+#define MDEBUG_FLAG() mdebug__flags[mdebug_flag]
+
#define MDEBUG_PRINT0(FPRINTF) \
do { \
- if (mdebug__flag & mdebug_mask) \
+ if (MDEBUG_FLAG ()) \
{ \
FPRINTF; \
fflush (mdebug__output); \
#define MDEBUG_DUMP(prefix, postfix, call) \
do { \
- if (mdebug__flag & mdebug_mask) \
+ if (MDEBUG_FLAG ()) \
{ \
fprintf (mdebug__output, "%s", prefix); \
call; \
} \
} while (0)
-#define MDEBUG_PUSH_TIME() \
- do { \
- if (mdebug__flag & mdebug_mask) \
- mdebug__push_time (); \
+#define MDEBUG_PUSH_TIME() \
+ do { \
+ if (MDEBUG_FLAG ()) \
+ mdebug__push_time (); \
} while (0)
-#define MDEBUG_POP_TIME() \
- do { \
- if (mdebug__flag & mdebug_mask) \
- mdebug__pop_time (); \
+#define MDEBUG_POP_TIME() \
+ do { \
+ if (MDEBUG_FLAG ()) \
+ mdebug__pop_time (); \
} while (0)
#define MDEBUG_PRINT_TIME(tag, ARG_LIST) \
do { \
- if (mdebug__flag & mdebug_mask) \
+ if (MDEBUG_FLAG ()) \
{ \
fprintf (mdebug__output, " [%s] ", tag); \
mdebug__print_time (); \
| (((c) & 0xFF00) << 8) | (((c) & 0xFF) << 24))
-extern void *(*mdatabase__finder) (MSymbol tag1, MSymbol tag2,
- MSymbol tag3, MSymbol tag4);
-extern void *(*mdatabase__loader) (void *);
-
/* Initialize/finalize function. */
extern int msymbol__init ();
static MFontDriver xfont_driver =
{ xfont_select, xfont_open,
xfont_find_metric, xfont_has_char, xfont_encode_char,
- xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability };
+ xfont_render, xfont_list, xfont_list_family_names, xfont_check_capability
+ };
static int
font_compare (const void *p1, const void *p2)
char *name;
Display *display = FRAME_DISPLAY (frame);
XFontStruct *xfont;
- int mdebug_mask = MDEBUG_FONT;
+ int mdebug_flag = MDEBUG_FONT;
MFont this;
size = spec->size;
rfont->baseline_offset
= (XGetFontProperty (xfont, disp_info->MULE_BASELINE_OFFSET, &value)
- ? (int) value : 0);
+ ? (int) (value << 6) : 0);
rfont->average_width
= (XGetFontProperty (xfont, disp_info->AVERAGE_WIDTH, &value)
- ? (int) value / 10 : 0);
+ ? (int) (value << 6) / 10 : 0);
}
- rfont->ascent = xfont->ascent + rfont->baseline_offset;
- rfont->descent = xfont->descent - rfont->baseline_offset;
- rfont->max_advance = xfont->max_bounds.width;
+ rfont->ascent = (xfont->ascent << 6) + rfont->baseline_offset;
+ rfont->descent = (xfont->descent << 6) - rfont->baseline_offset;
+ rfont->max_advance = xfont->max_bounds.width << 6;
+ rfont->x_ppem = rfont->y_ppem = size / 10;
rfont->fontp = xfont;
rfont->next = MPLIST_VAL (frame->realized_font_list);
MPLIST_VAL (frame->realized_font_list) = rfont;
MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
for (; g != gend; g++)
- {
- if (g->code == MCHAR_INVALID_CODE)
- {
- g->lbearing = xfont->max_bounds.lbearing;
- g->rbearing = xfont->max_bounds.rbearing;
- g->width = xfont->max_bounds.width;
- g->ascent = xfont->ascent;
- g->descent = xfont->descent;
- }
- else
- {
- int byte1 = g->code >> 8, byte2 = g->code & 0xFF;
- XCharStruct *pcm = NULL;
-
- if (xfont->per_char != NULL)
- {
- if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
- {
- if (byte1 == 0
- && byte2 >= xfont->min_char_or_byte2
- && byte2 <= xfont->max_char_or_byte2)
- pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
- }
- else
- {
- if (byte1 >= xfont->min_byte1
- && byte1 <= xfont->max_byte1
- && byte2 >= xfont->min_char_or_byte2
- && byte2 <= xfont->max_char_or_byte2)
- {
- pcm = (xfont->per_char
- + ((xfont->max_char_or_byte2
- - xfont->min_char_or_byte2 + 1)
- * (byte1 - xfont->min_byte1))
- + (byte2 - xfont->min_char_or_byte2));
- }
- }
- }
-
- if (pcm)
- {
- g->lbearing = pcm->lbearing;
- g->rbearing = pcm->rbearing;
- g->width = pcm->width;
- g->ascent = pcm->ascent;
- g->descent = pcm->descent;
- }
- else
- {
- /* If the per_char pointer is null, all glyphs between
- the first and last character indexes inclusive have
- the same information, as given by both min_bounds and
- max_bounds. */
- g->lbearing = 0;
- g->rbearing = xfont->max_bounds.width;
- g->width = xfont->max_bounds.width;
- g->ascent = xfont->ascent;
- g->descent = xfont->descent;
- }
- }
- g->ascent += rfont->baseline_offset;
- g->descent -= rfont->baseline_offset;
- }
+ if (! g->g.measured)
+ {
+ if (g->g.code == MCHAR_INVALID_CODE)
+ {
+ g->g.lbearing = xfont->max_bounds.lbearing << 6;
+ g->g.rbearing = xfont->max_bounds.rbearing << 6;
+ g->g.xadv = xfont->max_bounds.width << 6;
+ g->g.ascent = xfont->ascent << 6;
+ g->g.descent = xfont->descent << 6;
+ }
+ else
+ {
+ int byte1 = g->g.code >> 8, byte2 = g->g.code & 0xFF;
+ XCharStruct *pcm = NULL;
+
+ if (xfont->per_char != NULL)
+ {
+ if (xfont->min_byte1 == 0 && xfont->max_byte1 == 0)
+ {
+ if (byte1 == 0
+ && byte2 >= xfont->min_char_or_byte2
+ && byte2 <= xfont->max_char_or_byte2)
+ pcm = xfont->per_char + byte2 - xfont->min_char_or_byte2;
+ }
+ else
+ {
+ if (byte1 >= xfont->min_byte1
+ && byte1 <= xfont->max_byte1
+ && byte2 >= xfont->min_char_or_byte2
+ && byte2 <= xfont->max_char_or_byte2)
+ {
+ pcm = (xfont->per_char
+ + ((xfont->max_char_or_byte2
+ - xfont->min_char_or_byte2 + 1)
+ * (byte1 - xfont->min_byte1))
+ + (byte2 - xfont->min_char_or_byte2));
+ }
+ }
+ }
+
+ if (pcm)
+ {
+ g->g.lbearing = pcm->lbearing << 6;
+ g->g.rbearing = pcm->rbearing << 6;
+ g->g.xadv = pcm->width << 6;
+ g->g.ascent = pcm->ascent << 6;
+ g->g.descent = pcm->descent << 6;
+ }
+ else
+ {
+ /* If the per_char pointer is null, all glyphs between
+ the first and last character indexes inclusive have
+ the same information, as given by both min_bounds and
+ max_bounds. */
+ g->g.lbearing = 0;
+ g->g.rbearing = xfont->max_bounds.width << 6;
+ g->g.xadv = xfont->max_bounds.width << 6;
+ g->g.ascent = xfont->ascent << 6;
+ g->g.descent = xfont->descent << 6;
+ }
+ }
+ g->g.yadv = 0;
+ g->g.ascent += rfont->baseline_offset;
+ g->g.descent -= rfont->baseline_offset;
+ g->g.measured = 1;
+ }
}
if (from == to)
return;
- baseline_offset = rface->rfont->baseline_offset;
+ baseline_offset = rface->rfont->baseline_offset >> 6;
if (region)
gc = set_region (rface->frame, gc, region);
XSetFont (display, gc, ((XFontStruct *) rface->rfont->fontp)->fid);
code = (XChar2b *) alloca (sizeof (XChar2b) * (to - from));
for (i = 0, g = from; g < to; i++, g++)
{
- code[i].byte1 = g->code >> 8;
- code[i].byte2 = g->code & 0xFF;
+ code[i].byte1 = g->g.code >> 8;
+ code[i].byte2 = g->g.code & 0xFF;
}
g = from;
while (g < to)
{
if (g->type == GLYPH_PAD)
- x += g++->width;
+ x += g++->g.xadv;
else if (g->type == GLYPH_SPACE)
for (; g < to && g->type == GLYPH_SPACE; g++)
- x += g->width;
+ x += g->g.xadv;
else if (! g->rface->rfont)
{
- if ((g->c >= 0x200B && g->c <= 0x200F)
- || (g->c >= 0x202A && g->c <= 0x202E))
- x += g++->width;
+ if ((g->g.c >= 0x200B && g->g.c <= 0x200F)
+ || (g->g.c >= 0x202A && g->g.c <= 0x202E))
+ x += g++->g.xadv;
else
{
/* As a font is not found for this character, draw an
empty box. */
- int box_width = g->width;
+ int box_width = g->g.xadv;
int box_height = gstring->ascent + gstring->descent;
if (box_width > 4)
box_height -= 2;
XDrawRectangle (display, (Window) win, gc,
x, y - gstring->ascent, box_width, box_height);
- x += g++->width;
+ x += g++->g.xadv;
}
}
- else if (g->xoff != 0 || g->yoff != 0 || g->right_padding)
+ else if (g->g.xoff != 0 || g->g.yoff != 0 || g->right_padding)
{
XDrawString16 (display, (Window) win, gc,
- x + g->xoff, y + g->yoff - baseline_offset,
+ x + g->g.xoff, y + g->g.yoff - baseline_offset,
code + (g - from), 1);
- x += g->width;
+ x += g->g.xadv;
g++;
}
else
int code_idx = g - from;
for (i = 0;
- g < to && g->type == GLYPH_CHAR && g->xoff == 0 && g->yoff == 0;
+ g < to && g->type == GLYPH_CHAR && g->g.xoff == 0 && g->g.yoff == 0;
i++, g++)
- x += g->width;
+ x += g->g.xadv;
XDrawString16 (display, (Window) win, gc,
orig_x, y - baseline_offset, code + code_idx, i);
}
int size = font ? font->size : 0;
MPlist *pl, *p;
int num = 0;
- int mdebug_mask = MDEBUG_FONT;
+ int mdebug_flag = MDEBUG_FONT;
MDEBUG_PRINT2 (" [X-FONT] listing %s-%s...",
family ? msymbol_name (family) : "*",
static void xft_render (MDrawWindow, int, int, MGlyphString *,
MGlyph *, MGlyph *, int, MDrawRegion);
static int xft_check_capability (MRealizedFont *rfont, MSymbol capability);
+static int xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec);
+static int xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
+ MFLTGlyphString *in, int from, int to,
+ MFLTGlyphString *out,
+ MFLTGlyphAdjustment *adjustment);
static MFontDriver xft_driver =
{ NULL, xft_open,
xft_find_metric, xft_has_char, xft_encode_char, xft_render, NULL, NULL,
- xft_check_capability
+ xft_check_capability, NULL, NULL, xft_check_otf, xft_drive_otf
};
static void
rfont->max_advance = max_advance;
rfont->average_width = average_width;
rfont->baseline_offset = baseline_offset;
+ rfont->x_ppem = ft_face->size->metrics.x_ppem;
+ rfont->y_ppem = ft_face->size->metrics.y_ppem;
rfont->fontp = xft_font;
rfont->next = MPLIST_VAL (frame->realized_font_list);
MPLIST_VAL (frame->realized_font_list) = rfont;
MGlyph *g = MGLYPH (from), *gend = MGLYPH (to);
for (; g != gend; g++)
- {
- if (g->code == MCHAR_INVALID_CODE)
- {
- g->lbearing = 0;
- g->rbearing = xft_font->max_advance_width;
- g->width = g->rbearing;
- g->ascent = xft_font->ascent;
- g->descent = xft_font->descent;
- }
- else
- {
- XGlyphInfo extents;
-
- XftGlyphExtents (display, xft_font, &g->code, 1, &extents);
- g->lbearing = - extents.x;
- g->rbearing = extents.width - extents.x;
- g->width = extents.xOff;
- g->ascent = extents.y;
- g->descent = extents.height - extents.y;
- }
- }
+ if (! g->g.measured)
+ {
+ if (g->g.code == MCHAR_INVALID_CODE)
+ {
+ g->g.lbearing = 0;
+ g->g.rbearing = xft_font->max_advance_width << 6;
+ g->g.xadv = g->g.rbearing << 6;
+ g->g.ascent = xft_font->ascent << 6;
+ g->g.descent = xft_font->descent << 6;
+ }
+ else
+ {
+ XGlyphInfo extents;
+
+ XftGlyphExtents (display, xft_font, &g->g.code, 1, &extents);
+ g->g.lbearing = (- extents.x) << 6;
+ g->g.rbearing = (extents.width - extents.x) << 6;
+ g->g.xadv = extents.xOff << 6;
+ g->g.ascent = extents.y << 6;
+ g->g.descent = (extents.height - extents.y) << 6;
+ }
+ g->g.yadv = 0;
+ g->g.measured = 0;
+ }
}
static int
XftDrawChange (xft_draw, (Drawable) win);
XftDrawSetClip (xft_draw, (Region) region);
- y -= rfont->baseline_offset;
+ y -= rfont->baseline_offset >> 6;
glyphs = alloca (sizeof (FT_UInt) * (to - from));
- for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->width)
+ for (last_x = x, nglyphs = 0, g = from; g < to; x += g++->g.xadv)
{
- if (g->xoff == 0 && g->yoff == 0 && !g->left_padding && !g->right_padding)
- glyphs[nglyphs++] = g->code;
+ if (g->g.xoff == 0 && g->g.yoff == 0 && !g->left_padding && !g->right_padding)
+ glyphs[nglyphs++] = g->g.code;
else
{
if (nglyphs > 0)
last_x, y, glyphs, nglyphs);
nglyphs = 0;
XftDrawGlyphs (xft_draw, xft_color, xft_font,
- x + g->xoff, y + g->yoff, (FT_UInt *) &g->code, 1);
- last_x = x + g->width;
+ x + g->g.xoff, y + g->g.yoff, (FT_UInt *) &g->g.code, 1);
+ last_x = x + g->g.xadv;
}
}
if (nglyphs > 0)
return result;
}
+static int
+xft_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
+{
+ MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+ MRealizedFontXft *rfont_xft = rfont->info;
+ int result;
+
+ rfont->info = rfont_xft->info;
+ result = mfont__ft_driver.check_otf (font, spec);
+ rfont->info = rfont_xft;
+ return result;
+}
+
+static int
+xft_drive_otf (MFLTFont *font, MFLTOtfSpec *spec,
+ MFLTGlyphString *in, int from, int to,
+ MFLTGlyphString *out,
+ MFLTGlyphAdjustment *adjustment)
+{
+ MRealizedFont *rfont = ((MFLTFontForRealized *) font)->rfont;
+ MRealizedFontXft *rfont_xft = rfont->info;
+ int result;
+
+ rfont->info = rfont_xft->info;
+ result = mfont__ft_driver.drive_otf (font, spec, in, from, to, out,
+ adjustment);
+ rfont->info = rfont_xft;
+ return result;
+}
+
#endif /* HAVE_XFT2 */
\f
for (; from < to; from++)
{
XDrawRectangle (display, (Window) win, gc,
- x, y - gstring->ascent + 1, from->width - 1,
+ x, y - gstring->ascent + 1, from->g.xadv - 1,
gstring->ascent + gstring->descent - 2);
- x += from->width;
+ x += from->g.xadv;
}
}
int x0, x1;
if (g->left_padding)
- x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
+ x0 = x + box->outer_hmargin, x1 = x + g->g.xadv - 1;
else
- x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
+ x0 = x, x1 = x + g->g.xadv - box->outer_hmargin - 1;
/* Draw the top side. */
for (i = 0; i < box->width; i++)
mplist_add (frame->font_driver_list, Mfreetype, &mfont__ft_driver);
#endif /* HAVE_FREETYPE */
if (use_xfont || MPLIST_TAIL_P (frame->font_driver_list))
- mplist_push (frame->font_driver_list, Mx, &xfont_driver);
+ mplist_add (frame->font_driver_list, Mx, &xfont_driver);
frame->realized_font_list = device->realized_font_list;
frame->realized_face_list = device->realized_face_list;
int m17n__shell_initialized;
int m17n__gui_initialized;
-void *(*mdatabase__finder) (MSymbol tag1, MSymbol tag2,
- MSymbol tag3, MSymbol tag4);
-void *(*mdatabase__loader) (void *);
-
-int mdebug__flag;
+int mdebug__flags[MDEBUG_MAX];
FILE *mdebug__output;
void
time_stack[time_stack_index - 1] = tv;
}
-#define SET_DEBUG_FLAG(env_name, mask) \
- do { \
- char *env_value = getenv (env_name); \
- \
- if (env_value) \
- { \
- if (env_value[0] == '1') \
- mdebug__flag |= (mask); \
- else if (env_value[0] == '0') \
- mdebug__flag &= ~(mask); \
- } \
- } while (0)
+static void
+SET_DEBUG_FLAG (char *env_name, enum MDebugFlag flag)
+{
+ char *env_value = getenv (env_name);
+ if (env_value)
+ {
+ int int_value = atoi (env_value);
+
+ if (flag == MDEBUG_ALL)
+ {
+ int i;
+ for (i = 0; i < MDEBUG_MAX; i++)
+ mdebug__flags[i] = int_value;
+ }
+ else
+ mdebug__flags[flag] = int_value;
+ }
+}
void
mdebug__add_object_array (M17NObjectArray *array, char *name)
void
m17n_init_core (void)
{
- int mdebug_mask = MDEBUG_INIT;
+ int mdebug_flag = MDEBUG_INIT;
merror_code = MERROR_NONE;
if (m17n__core_initialized++)
m17n_memory_full_handler = default_error_handler;
- mdebug__flag = 0;
SET_DEBUG_FLAG ("MDEBUG_ALL", MDEBUG_ALL);
SET_DEBUG_FLAG ("MDEBUG_INIT", MDEBUG_INIT);
SET_DEBUG_FLAG ("MDEBUG_FINI", MDEBUG_FINI);
if (mplist__init () < 0)
goto err;
MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize plist module."));
+ if (mchar__init () < 0)
+ goto err;
+ MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize character module."));
if (mchartable__init () < 0)
goto err;
MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize chartable module."));
- if (mtext__init () < 0)
- goto err;
- if (mtext__prop_init () < 0)
+ if (mtext__init () < 0 || mtext__prop_init () < 0)
goto err;
MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize mtext module."));
-
- mdatabase__finder = NULL;
- mdatabase__loader = NULL;
+ if (mdatabase__init () < 0)
+ goto err;
+ MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize database module."));
#if ENABLE_NLS
bindtextdomain ("m17n-lib", GETTEXTDIR);
void
m17n_fini_core (void)
{
- int mdebug_mask = MDEBUG_FINI;
+ int mdebug_flag = MDEBUG_FINI;
if (m17n__core_initialized == 0
|| --m17n__core_initialized > 0)
MDEBUG_POP_TIME ();
MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize the core modules."));
MDEBUG_POP_TIME ();
- if (mdebug__flag & MDEBUG_FINI)
+ if (mdebug__flags[MDEBUG_FINI])
report_object_array ();
msymbol__free_table ();
if (mdebug__output != stderr)
extern MSymbol Mstring;
extern MSymbol Msymbol;
extern MSymbol Mtext;
+extern MSymbol Mcharset;
/* Return a symbol of name NAME. */
extern MSymbol msymbol (const char *name);
extern MCharTable *mchartable (MSymbol key, void *default_value);
+extern int mchartable_min_char (MCharTable *table);
+
+extern int mchartable_max_char (MCharTable *table);
+
extern void *mchartable_lookup (MCharTable *table, int c);
extern int mchartable_set (MCharTable *table, int c, void *val);
extern MText *mtext_deserialize (MText *mt);
+/*** @ingroup m17nCore */
+/***en @defgroup m17nDatabase Database */
+/***ja @defgroup m17nDatabase ¥Ç¡¼¥¿¥Ù¡¼¥¹ */
+/*=*/
+
+/* Directory of an application specific databases. */
+extern char *mdatabase_dir;
+/*=*/
+/***
+ @ingroup m17nDatabase */
+/***en
+ @brief Type of database.
+
+ The type #MDatabase is for a database object. Its internal
+ structure is concealed from an application program. */
+/***ja
+ @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î·¿Àë¸À.
+
+ #MDatabase ·¿¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹¥ª¥Ö¥¸¥§¥¯¥ÈÍѤι½Â¤ÂΤǤ¢¤ë¡£
+ ÆâÉô¹½Â¤¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¤¡£
+ */
+
+typedef struct MDatabase MDatabase;
+
+/*=*/
+
+/* Look for a data. */
+extern MDatabase *mdatabase_find (MSymbol tag1, MSymbol tag2,
+ MSymbol tag3, MSymbol tag4);
+
+extern MPlist *mdatabase_list (MSymbol tag0, MSymbol tag1,
+ MSymbol tag2, MSymbol tag3);
+
+/* Load a data. */
+void *mdatabase_load (MDatabase *mdb);
+
+/* Get tags of a data. */
+extern MSymbol *mdatabase_tag (MDatabase *mdb);
+
+/* Define a data. */
+extern MDatabase *mdatabase_define (MSymbol tag1, MSymbol tag2,
+ MSymbol tag3, MSymbol tag4,
+ void *(*loader) (MSymbol *, void *),
+ void *extra_info);
+
M17N_END_HEADER
#endif /* _M17N_CORE_H_ */
--- /dev/null
+/* m17n-flt.c -- Font Layout Table sub-module.
+ Copyright (C) 2003, 2004, 2007
+ National Institute of Advanced Industrial Science and Technology (AIST)
+ Registration Number H15PRO112
+
+ This file is part of the m17n library.
+
+ The m17n library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ The m17n library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the m17n library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ 02111-1307, USA. */
+
+/***en
+ @addtogroup m17nFLT
+ @brief FLT support for a window system.
+
+ This section defines the m17n FLT API concerning character
+ layouting facility using FLT (Font Layout Table). */
+
+/*=*/
+
+#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
+/*** @addtogroup m17nInternal
+ @{ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <regex.h>
+
+#include "m17n-core.h"
+#include "m17n-flt.h"
+#include "m17n-misc.h"
+#include "internal.h"
+#include "mtext.h"
+#include "symbol.h"
+#include "plist.h"
+#include "database.h"
+#include "internal-flt.h"
+
+/* Font Layouter */
+
+/* Font Layout Table (FLT)
+
+Predefined terms: SYMBOL, INTEGER, STRING
+
+FLT ::= '(' STAGE + ')'
+
+STAGE ::= CATEGORY-TABLE ? FONT-LAYOUT-RULE
+
+;; Each STAGE consumes a source (code sequence) and produces another
+;; code sequence that is given to the next STAGE as a source. The
+;; source given to the first stage is a sequence of character codes
+;; that are assigned category codes by CATEGORY-TABLE. The output of
+;; the last stage is a glyph code sequence given to the renderer.
+
+CATEGORY-TABLE ::=
+ '(' 'category' CATEGORY-SPEC + ')'
+CATEGORY-SPEC ::=
+ '(' CODE [ CODE ] CATEGORY ')'
+CODE ::= INTEGER
+CATEGORY ::= INTEGER
+;; ASCII character codes of alphabet ('A' .. 'Z' 'a' .. 'z').
+;; Ex: CATEGORY-TABLE
+;; (category
+;; (0x0900 0x097F ?E) ; All Devanagari characters
+;; (0x093C ?N)) ; DEVANAGARI-LETTER NUKTA
+;; Assign the category 'E' to all Devanagari characters but 0x093C,
+;; assign the category 'N' to 0x093C.
+
+FONT-LAYOUT-RULE ::=
+ '(' 'generator' RULE MACRO-DEF * ')'
+
+RULE ::= COMMAND | REGEXP-RULE | MATCH-RULE | MAP-RULE
+ | COND-STRUCT | MACRO-NAME
+
+COMMAND ::=
+ DIRECT-CODE | COMBINING | PREDEFIND-COMMAND | OTF-COMMAND
+
+DIRECT-CODE ::= INTEGER
+;; Always succeed. Produce the code. Consume no source.
+
+PREDEFIND-COMMAND ::=
+ '=' | '*' | '<' | '>' | '|'
+
+;; '=': Succeed when the current run contains at least one code.
+;; Consume the first code in the current run, and produce it as is.
+
+;; '*': If the the previous command succeeded, repeat it until it
+;; fails.
+
+;; '<': Produce a special code that indicates the start of grapheme
+;; cluster. Succeed always, consume nothing.
+
+;; '>': Produce a special code that indicates the end of grapheme
+;; cluster. Succeed always, consume nothing.
+
+;; '|': Produce a special code whose category is ' '. Succeed always,
+;; consume nothing.
+
+OTF-COMMAND ::=
+ 'otf:''SCRIPT'[':'['LANGSYS'][':'[GSUB-FEATURES][':'GPOS-FEATURES]]]
+;; Run the Open Type Layout Table on the current run. Succeed always,
+;; consume nothing.
+
+SCRIPT ::= OTF-TAG
+;; OTF's ScriptTag name (four letters) listed at:
+;; <http://www.microsoft.om/typograph/otspec/scripttags.htm>
+LANGSYS ::= OTF-TAG
+;; OTF's Language System name (four letters) listed at:
+;; <http://www.microsoft.om/typograph/otspec/languagetags.htm>
+
+GSUB-FEATURES ::= [FEATURE[,FEATURE]*] | ' '
+GPOS-FEATURES ::= [FEATURE[,FEATURE]*] | ' '
+FEATURE ::= OTF-TAG
+;; OTF's Feature name (four letters) listed at:
+;; <http://www.microsoft.om/typograph/otspec/???.htm>
+
+OTF-TAG ::= PRINTABLE-CHAR PRINTABLE-CHAR PRINTABLE-CHAR PRINTABLE-CHAR
+
+;; Ex. OTF-COMMAND
+;; 'otf:deva'
+;; Run all features in the default langsys of 'deva' script.
+;; 'otf:deva::nukt:haln'
+;; Run all GSUB features, run 'nukt' and 'haln' GPOS features.
+;; 'otf:deva:: :'
+;; Run all GSUB features, run no GPOS features.
+
+REGEXP-RULE ::=
+ '(' REGEXP RULE * ')'
+
+;; Succeed if REGXP matches the head of source. Run RULEs while
+;; limiting the source to the matching part. Consume that part.
+
+REGEXP ::= STRING
+;; Must be composed only from ASCII characters. 'A' - 'Z', 'a' - 'z'
+;; correspond to CATEGORY.
+
+;; Ex: REGEXP-RULE
+;; ("VA?"
+;; < | vowel * | >)
+
+MATCH-RULE ::=
+ '(' MATCH-IDX RULE * ')'
+
+;; Succeed if the previous REGEXP-RULE found a matching part for
+;; MATCH-IDX. Run RULEs while limiting the source to the matching
+;; part. If MATCH-IDX is zero, consume the whole part, else consume
+;; nothing.
+
+MATCH-IDX ::= INTEGER
+;; Must be 0..20.
+
+;; Ex. MATCH-RULE
+;; (2 consonant *)
+
+MAP-RULE ::=
+ '(' ( SOURCE-SEQ | SOURCE-RANGE ) RULE * ')'
+
+;; Succeed if the source matches SOURCE-SEQ or SOURCE-RANGE. Run
+;; RULEs while limiting the source to the matching part. Consume that
+;; part.
+
+SOURCE-SEQ ::=
+ '(' CODE + ')'
+SOURCE-RANGE ::=
+ '(' 'range' CODE CODE ')'
+;; Ex. MAP-RULE
+;; ((0x0915 0x094D) 0x43)
+;; If the source code sequence is 0x0915 0x094D, produce 0x43.
+;; ((range 0x0F40 0x0F6A) 0x2221)
+;; If the first source code CODE is in the range 0x0F40..0x0F6A,
+;; produce (0x2221 + (CODE - 0x0F40)).
+
+COND-STRUCT ::=
+ '(' 'cond' RULE + ')'
+
+;; Try each rule in sequence until one succeeds. Succeed if one
+;; succeeds. Consume nothing.
+
+;; Ex. COND-STRUCT
+;; (cond
+;; ((0x0915 0x094D) 0x43)
+;; ((range 0x0F40 0x0F6A) 0x2221)
+;; = )
+
+COMBINING ::= 'V''H''O''V''H'
+V ::= ( 't' | 'c' | 'b' | 'B' )
+H ::= ( 'l' | 'c' | 'r' )
+O ::= ( '.' | XOFF | YOFF | XOFF YOFF )
+XOFF ::= '<'INTEGER | '>'INTEGER
+YOFF ::= '+'INTEGER | '-'INTEGER
+;; INTEGER must be integer 0..127
+
+;; VH pair indicates 12 reference points of a glyph as below:
+;;
+;; 0----1----2 <---- ascent 0:tl (top-left)
+;; | | 1:tc (top-center)
+;; | | 2:tr (top-right)
+;; | | 3:Bl (base-left)
+;; 9 10 11 <---- center 4:Bc (base-center)
+;; | | 5:Br (base-right)
+;; --3----4----5-- <-- baseline 6:bl (bottom-left)
+;; | | 7:bc (bottom-center)
+;; 6----7----8 <---- descent 8:br (bottom-right)
+;; 9:cl (center-left)
+;; | | | 10:cc (center-center)
+;; left center right 11:cr (center-right)
+;;
+;; Ex. COMBINING
+;; 'tc.bc':
+;; Align top-left point of the previous glyph and bottom-center
+;; point of the current glyph.
+;; 'Bl<20-10Br'
+;; Align 20% left and 10% below of base-left point of the previous
+;; glyph and base-right point of the current glyph.
+
+MACRO-DEF ::=
+ '(' MACRO-NAME RULE + ')'
+MACRO-NAME ::= SYMBOL
+
+*/
+
+static int mdebug_flag = MDEBUG_FONT_FLT;
+
+MSymbol Mfont, Mlayouter, Mcombining;
+
+static MSymbol Mgenerator, Mend;
+
+static MPlist *flt_list;
+static int flt_min_coverage, flt_max_coverage;
+
+enum GlyphInfoMask
+{
+ CombiningCodeMask = 0xFFFFFFF,
+ LeftPaddingMask = 1 << 28,
+ RightPaddingMask = 1 << 29
+};
+
+#define SET_GLYPH_INFO(g, mask, ctx, info) \
+ ((g)->internal = (((g)->internal & ~(mask)) | (info)), \
+ (ctx)->check_mask |= (mask))
+
+#define GET_COMBINING_CODE(g) ((g)->internal & CombiningCodeMask)
+#define SET_COMBINING_CODE(g, ctx, code) \
+ SET_GLYPH_INFO (g, CombiningCodeMask, ctx, code)
+#define GET_LEFT_PADDING(g) ((g)->internal & LeftPaddingMask)
+#define SET_LEFT_PADDING(g, ctx, flag) \
+ SET_GLYPH_INFO (g, LeftPaddingMask, ctx, flag)
+#define GET_RIGHT_PADDING(g) ((g)->internal & RightPaddingMask)
+#define SET_RIGHT_PADDING(g, ctx, flag) \
+ SET_GLYPH_INFO (g, RightPaddingMask, ctx, flag)
+#define GET_ENCODED(g) ((g)->encoded)
+#define SET_ENCODED(g, flag) ((g)->encoded = (flag))
+#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); \
+ (gstring)->glyphs = alloca ((gstring)->glyph_size * (n)); \
+ (gstring)->allocated = (n); \
+ (gstring)->used = 0; \
+ } while (0)
+
+#define GALLOCA (gstring) \
+ ((MFLTGlyph *) alloca ((gstring)->glyph_size))
+
+#define GREF(gstring, idx) \
+ ((MFLTGlyph *) ((char *) ((gstring)->glyphs) + (gstring)->glyph_size * (idx)))
+
+#define PREV(gstring, g) \
+ ((MFLTGlyph *) ((char *) (g) - (gstring)->glyph_size))
+
+#define NEXT(gstring, g) \
+ ((MFLTGlyph *) ((char *) (g) + (gstring)->glyph_size))
+
+#define GCPY(src, src_idx, n, tgt, tgt_idx) \
+ do { \
+ 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
+GREPLACE (MFLTGlyphString *src, int src_from, int src_to,
+ MFLTGlyphString *tgt, int tgt_from, int tgt_to)
+{
+ int src_len = src_to - src_from;
+ int tgt_len = tgt_to - tgt_from;
+ int inc = src_len - tgt_len;
+
+ if (tgt->allocated < tgt->used + inc)
+ return -2;
+ if (inc != 0 && tgt_to < tgt->used)
+ memmove ((char *) tgt->glyphs + tgt->glyph_size * (tgt_from + src_len),
+ (char *) tgt->glyphs + tgt->glyph_size * tgt_to,
+ tgt->glyph_size * (tgt->used - tgt_to));
+ if (src_len)
+ memcpy ((char *) tgt->glyphs + tgt->glyph_size * tgt_from,
+ (char *) src->glyphs + src->glyph_size * src_from,
+ src->glyph_size * src_len);
+ tgt->used += inc;
+ return 0;
+}
+
+
+/* Command ID:
+ 0 ... : direct code
+ -1 : invalid
+ -0x0F .. -2 : builtin commands
+ -0x100000F .. -0x10 : combining code
+ ... -0x1000010: index to FontLayoutStage->cmds
+ */
+
+#define INVALID_CMD_ID -1
+#define CMD_ID_OFFSET_BUILTIN -3
+#define CMD_ID_OFFSET_COMBINING -0x10
+#define CMD_ID_OFFSET_INDEX -0x1000010
+
+/* Builtin commands. */
+#define CMD_ID_COPY -3 /* '=' */
+#define CMD_ID_REPEAT -4 /* '*' */
+#define CMD_ID_CLUSTER_BEGIN -5 /* '<' */
+#define CMD_ID_CLUSTER_END -6 /* '>' */
+#define CMD_ID_SEPARATOR -7 /* '|' */
+#define CMD_ID_LEFT_PADDING -8 /* '[' */
+#define CMD_ID_RIGHT_PADDING -9 /* ']' */
+
+#define CMD_ID_TO_COMBINING_CODE(id) (CMD_ID_OFFSET_COMBINING - (id))
+#define COMBINING_CODE_TO_CMD_ID(code) (CMD_ID_OFFSET_COMBINING - (code))
+
+#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, Mfont_facility;
+
+#define GLYPH_CODE_P(code) \
+ ((code) >= GLYPH_CODE_MIN && (code) <= GLYPH_CODE_MAX)
+
+#define GLYPH_CODE_INDEX(code) ((code) - GLYPH_CODE_MIN)
+
+#define UPDATE_CLUSTER_RANGE(ctx, g) \
+ do { \
+ if ((ctx)->cluster_begin_idx >= 0) \
+ { \
+ if (ctx->cluster_begin_pos > (g)->from) \
+ ctx->cluster_begin_pos = (g)->from; \
+ if (ctx->cluster_end_pos < (g)->to) \
+ ctx->cluster_end_pos = (g)->to; \
+ } \
+ } while (0)
+
+enum FontLayoutCmdRuleSrcType
+ {
+ SRC_REGEX,
+ SRC_INDEX,
+ SRC_SEQ,
+ SRC_RANGE,
+ SRC_HAS_GLYPH,
+ SRC_OTF_SPEC
+ };
+
+typedef struct
+{
+ enum FontLayoutCmdRuleSrcType src_type;
+ union {
+ struct {
+ char *pattern;
+ regex_t preg;
+ } re;
+ int match_idx;
+ struct {
+ int n_codes;
+ int *codes;
+ } seq;
+ struct {
+ int from, to;
+ } range;
+ int supported_glyph;
+ MFLTOtfSpec otf_spec;
+ } src;
+
+ int n_cmds;
+ int *cmd_ids;
+} FontLayoutCmdRule;
+
+typedef struct
+{
+ /* Beginning and end indices of series of SEQ commands. */
+ int seq_beg, seq_end;
+ /* Range of the first character appears in the above series. */
+ int seq_from, seq_to;
+
+ int n_cmds;
+ int *cmd_ids;
+} FontLayoutCmdCond;
+
+enum FontLayoutCmdType
+ {
+ FontLayoutCmdTypeRule,
+ FontLayoutCmdTypeCond,
+ FontLayoutCmdTypeOTF,
+ FontLayoutCmdTypeMAX
+ };
+
+typedef struct
+{
+ enum FontLayoutCmdType type;
+ union {
+ FontLayoutCmdRule rule;
+ FontLayoutCmdCond cond;
+ MFLTOtfSpec otf;
+ } body;
+} FontLayoutCmd;
+
+typedef struct
+{
+ MCharTable *category;
+ int size, inc, used;
+ FontLayoutCmd *cmds;
+} FontLayoutStage;
+
+struct _MFLT
+{
+ MSymbol name;
+ MSymbol family;
+ MSymbol registry;
+ MFLTOtfSpec otf;
+ MDatabase *mdb;
+ MCharTable *coverage;
+ MPlist *stages;
+};
+
+/* Font layout table loader */
+
+static int parse_otf_command (MSymbol symbol, MFLTOtfSpec *spec);
+
+/* Load a category table from PLIST. PLIST has this form:
+ PLIST ::= ( FROM-CODE TO-CODE ? CATEGORY-CHAR ) *
+*/
+
+static MCharTable *
+load_category_table (MPlist *plist)
+{
+ MCharTable *table;
+
+ table = mchartable (Minteger, (void *) 0);
+
+ MPLIST_DO (plist, plist)
+ {
+ MPlist *elt;
+ int from, to, category_code;
+
+ if (! MPLIST_PLIST (plist))
+ MERROR (MERROR_FONT, NULL);
+ elt = MPLIST_PLIST (plist);
+ if (! MPLIST_INTEGER_P (elt))
+ MERROR (MERROR_FONT, NULL);
+ from = MPLIST_INTEGER (elt);
+ elt = MPLIST_NEXT (elt);
+ if (! MPLIST_INTEGER_P (elt))
+ MERROR (MERROR_FONT, NULL);
+ to = MPLIST_INTEGER (elt);
+ elt = MPLIST_NEXT (elt);
+ if (MPLIST_TAIL_P (elt))
+ {
+ category_code = to;
+ to = from;
+ }
+ else
+ {
+ if (! MPLIST_INTEGER_P (elt))
+ MERROR (MERROR_FONT, NULL);
+ category_code = MPLIST_INTEGER (elt);
+ }
+ if (! isalnum (category_code))
+ MERROR (MERROR_FONT, NULL);
+
+ if (from == to)
+ mchartable_set (table, from, (void *) category_code);
+ else
+ mchartable_set_range (table, from, to, (void *) category_code);
+ }
+
+ return table;
+}
+
+static unsigned int
+gen_otf_tag (char *p)
+{
+ unsigned int tag = 0;
+ int i;
+
+ for (i = 0; i < 4 && *p; i++, p++)
+ tag = (tag << 8) | *p;
+ 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)
+ {
+ (*count)++;
+ if (*p == '*')
+ {
+ p++;
+ if (*p == stopper || *p == '\0')
+ break;
+ return NULL;
+ }
+ if (*p == '~')
+ {
+ if (negative++ == 0)
+ (*count)++;
+ p += 5;
+ }
+ else
+ p += 4;
+ if (p > end)
+ return NULL;
+ if (*p == stopper || *p == '\0')
+ break;
+ if (*p != ',')
+ return NULL;
+ p++;
+ if (! *p)
+ return NULL;
+ }
+ return p;
+}
+
+static void
+otf_store_features (char *p, char *end, unsigned *buf)
+{
+ int negative = 0;
+ int i;
+
+ for (i = 0; p < end;)
+ {
+ if (*p == '*')
+ buf[i++] = 0xFFFFFFFF, p += 2, negative = 1;
+ else if (*p == '~')
+ {
+ 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
+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 *p;
+
+ memset (spec, 0, sizeof (MFLTOtfSpec));
+
+ spec->sym = symbol;
+ str += 5; /* skip the heading ":otf=" */
+ script = gen_otf_tag (str);
+ str += 4;
+ if (*str == '/')
+ {
+ langsys = gen_otf_tag (str);
+ str += 4;
+ }
+ else
+ langsys = 0;
+ gsub = str;
+ if (*str != '=')
+ /* Apply all GSUB features. */
+ gsub_count = 1;
+ else
+ {
+ p = str + 1;
+ str = otf_count_features (p, end, '+', &gsub_count);
+ if (! str)
+ MERROR (MERROR_FLT, -1);
+ }
+ gpos = str;
+ if (*str != '+')
+ /* 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);
+ }
+
+ 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]);
+ 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;
+}
+
+
+/* Parse OTF command name NAME and store the result in CMD.
+ NAME has this form:
+ :SCRIPT[/[LANGSYS][=[GSUB-FEATURES][+GPOS-FEATURES]]]
+ where GSUB-FEATURES and GPOS-FEATURES have this form:
+ [FEATURE[,FEATURE]*] | ' ' */
+
+static int
+load_otf_command (FontLayoutCmd *cmd, MSymbol sym)
+{
+ char *name = MSYMBOL_NAME (sym);
+ int result;
+
+ if (name[0] != ':')
+ {
+ /* This is old format of "otf:...". Change it to ":otf=...". */
+ char *str = alloca (MSYMBOL_NAMELEN (sym) + 2);
+
+ sprintf (str, ":otf=");
+ strcat (str, name + 4);
+ sym = msymbol (str);
+ }
+
+ result = parse_otf_command (sym, &cmd->body.otf);
+ if (result == -2)
+ return result;
+ cmd->type = FontLayoutCmdTypeOTF;
+ return 0;
+}
+
+
+/* Read a decimal number from STR preceded by one of "+-><". '+' and
+ '>' means a plus sign, '-' and '<' means a minus sign. If the
+ number is greater than 127, limit it to 127. */
+
+static int
+read_decimal_number (char **str)
+{
+ char *p = *str;
+ int sign = (*p == '-' || *p == '<') ? -1 : 1;
+ int n = 0;
+
+ p++;
+ while (*p >= '0' && *p <= '9')
+ n = n * 10 + *p++ - '0';
+ *str = p;
+ if (n == 0)
+ n = 5;
+ return (n < 127 ? n * sign : 127 * sign);
+}
+
+
+/* Read a horizontal and vertical combining positions from STR, and
+ store them in the place pointed by X and Y. The horizontal
+ position left, center, and right are represented by 0, 1, and 2
+ respectively. The vertical position top, center, bottom, and base
+ are represented by 0, 1, 2, and 3 respectively. If successfully
+ read, return 0, else return -1. */
+
+static int
+read_combining_position (char *str, int *x, int *y)
+{
+ int c = *str++;
+ int i;
+
+ /* Vertical position comes first. */
+ for (i = 0; i < 4; i++)
+ if (c == "tcbB"[i])
+ {
+ *y = i;
+ break;
+ }
+ if (i == 4)
+ return -1;
+ c = *str;
+ /* Then comse horizontal position. */
+ for (i = 0; i < 3; i++)
+ if (c == "lcr"[i])
+ {
+ *x = i;
+ return 0;
+ }
+ return -1;
+}
+
+
+/* Return a combining code corresponding to SYM. */
+
+static int
+get_combining_command (MSymbol sym)
+{
+ char *str = msymbol_name (sym);
+ int base_x, base_y, add_x, add_y, off_x, off_y;
+ int c;
+
+ if (read_combining_position (str, &base_x, &base_y) < 0)
+ return 0;
+ str += 2;
+ c = *str;
+ if (c == '.')
+ {
+ off_x = off_y = 128;
+ str++;
+ }
+ else
+ {
+ if (c == '+' || c == '-')
+ {
+ off_y = read_decimal_number (&str) + 128;
+ c = *str;
+ }
+ else
+ off_y = 128;
+ if (c == '<' || c == '>')
+ off_x = read_decimal_number (&str) + 128;
+ else
+ off_x = 128;
+ }
+ if (read_combining_position (str, &add_x, &add_y) < 0)
+ return 0;
+
+ c = MAKE_COMBINING_CODE (base_y, base_x, add_y, add_x, off_y, off_x);
+ return (COMBINING_CODE_TO_CMD_ID (c));
+}
+
+
+/* Load a command from PLIST into STAGE, and return that
+ identification number. If ID is not INVALID_CMD_ID, that means we
+ are loading a top level command or a macro. In that case, use ID
+ as the identification number of the command. Otherwise, generate a
+ new id number for the command. MACROS is a list of raw macros. */
+
+static int
+load_command (FontLayoutStage *stage, MPlist *plist,
+ MPlist *macros, int id)
+{
+ int i;
+ int result;
+
+ if (MPLIST_INTEGER_P (plist))
+ {
+ int code = MPLIST_INTEGER (plist);
+
+ if (code < 0)
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+ return code;
+ }
+ else if (MPLIST_PLIST_P (plist))
+ {
+ /* PLIST ::= ( cond ... ) | ( STRING ... ) | ( INTEGER ... )
+ | ( ( INTEGER INTEGER ) ... )
+ | ( ( range INTEGER INTEGER ) ... )
+ | ( ( font-facilty [ INTEGER ] ) ... )
+ | ( ( font-facilty OTF-SPEC ) ... ) */
+ MPlist *elt = MPLIST_PLIST (plist);
+ int len = MPLIST_LENGTH (elt) - 1;
+ FontLayoutCmd *cmd;
+
+ if (id == INVALID_CMD_ID)
+ {
+ FontLayoutCmd dummy;
+ id = INDEX_TO_CMD_ID (stage->used);
+ MLIST_APPEND1 (stage, cmds, dummy, MERROR_DRAW);
+ }
+ cmd = stage->cmds + CMD_ID_TO_INDEX (id);
+
+ if (MPLIST_SYMBOL_P (elt))
+ {
+ FontLayoutCmdCond *cond;
+
+ if (MPLIST_SYMBOL (elt) != Mcond)
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+ elt = MPLIST_NEXT (elt);
+ cmd->type = FontLayoutCmdTypeCond;
+ cond = &cmd->body.cond;
+ cond->seq_beg = cond->seq_end = -1;
+ cond->seq_from = cond->seq_to = 0;
+ cond->n_cmds = len;
+ MTABLE_CALLOC (cond->cmd_ids, len, MERROR_DRAW);
+ for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
+ {
+ int this_id = load_command (stage, elt, macros, INVALID_CMD_ID);
+
+ if (this_id == INVALID_CMD_ID || this_id == -2)
+ MERROR (MERROR_DRAW, this_id);
+ /* The above load_command may relocate stage->cmds. */
+ cmd = stage->cmds + CMD_ID_TO_INDEX (id);
+ cond = &cmd->body.cond;
+ cond->cmd_ids[i] = this_id;
+ if (this_id <= CMD_ID_OFFSET_INDEX)
+ {
+ FontLayoutCmd *this_cmd
+ = stage->cmds + CMD_ID_TO_INDEX (this_id);
+
+ if (this_cmd->type == FontLayoutCmdTypeRule
+ && this_cmd->body.rule.src_type == SRC_SEQ)
+ {
+ int first_char = this_cmd->body.rule.src.seq.codes[0];
+
+ if (cond->seq_beg < 0)
+ {
+ /* The first SEQ command. */
+ cond->seq_beg = i;
+ cond->seq_from = cond->seq_to = first_char;
+ }
+ else if (cond->seq_end < 0)
+ {
+ /* The following SEQ command. */
+ if (cond->seq_from > first_char)
+ cond->seq_from = first_char;
+ else if (cond->seq_to < first_char)
+ cond->seq_to = first_char;
+ }
+ }
+ else
+ {
+ if (cond->seq_beg >= 0 && cond->seq_end < 0)
+ /* The previous one is the last SEQ command. */
+ cond->seq_end = i;
+ }
+ }
+ else
+ {
+ if (cond->seq_beg >= 0 && cond->seq_end < 0)
+ /* The previous one is the last SEQ command. */
+ cond->seq_end = i;
+ }
+ }
+ if (cond->seq_beg >= 0 && cond->seq_end < 0)
+ /* The previous one is the last SEQ command. */
+ cond->seq_end = i;
+ }
+ else
+ {
+ cmd->type = FontLayoutCmdTypeRule;
+ if (MPLIST_MTEXT_P (elt))
+ {
+ MText *mt = MPLIST_MTEXT (elt);
+ char *str = (char *) MTEXT_DATA (mt);
+
+ if (str[0] != '^')
+ {
+ mtext_ins_char (mt, 0, '^', 1);
+ str = (char *) MTEXT_DATA (mt);
+ }
+ if (regcomp (&cmd->body.rule.src.re.preg, str, REG_EXTENDED))
+ MERROR (MERROR_FONT, INVALID_CMD_ID);
+ cmd->body.rule.src_type = SRC_REGEX;
+ cmd->body.rule.src.re.pattern = strdup (str);
+ }
+ else if (MPLIST_INTEGER_P (elt))
+ {
+ cmd->body.rule.src_type = SRC_INDEX;
+ cmd->body.rule.src.match_idx = MPLIST_INTEGER (elt);
+ }
+ else if (MPLIST_PLIST_P (elt))
+ {
+ MPlist *pl = MPLIST_PLIST (elt);
+ int size = MPLIST_LENGTH (pl);
+
+ if (MPLIST_INTEGER_P (pl))
+ {
+ int i;
+
+ cmd->body.rule.src_type = SRC_SEQ;
+ cmd->body.rule.src.seq.n_codes = size;
+ MTABLE_CALLOC (cmd->body.rule.src.seq.codes, size,
+ MERROR_FONT);
+ for (i = 0; i < size; i++, pl = MPLIST_NEXT (pl))
+ {
+ if (! MPLIST_INTEGER_P (pl))
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+ cmd->body.rule.src.seq.codes[i]
+ = (unsigned) MPLIST_INTEGER (pl);
+ }
+ }
+ else if (MPLIST_SYMBOL_P (pl) && size == 3)
+ {
+ if (MPLIST_SYMBOL (pl) != Mrange)
+ MERROR (MERROR_FLT, INVALID_CMD_ID);
+ cmd->body.rule.src_type = SRC_RANGE;
+ pl = MPLIST_NEXT (pl);
+ if (! MPLIST_INTEGER_P (pl))
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+ cmd->body.rule.src.range.from
+ = (unsigned) MPLIST_INTEGER (pl);
+ pl = MPLIST_NEXT (pl);
+ if (! MPLIST_INTEGER_P (pl))
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+ cmd->body.rule.src.range.to
+ = (unsigned) MPLIST_INTEGER (pl);
+ }
+ else if (MPLIST_SYMBOL_P (pl) && size <= 2)
+ {
+ if (MPLIST_SYMBOL (pl) != Mfont_facility)
+ MERROR (MERROR_FLT, INVALID_CMD_ID);
+ pl = MPLIST_NEXT (pl);
+ if (MPLIST_SYMBOL_P (pl))
+ {
+ MSymbol sym = MPLIST_SYMBOL (pl);
+ 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, &cmd->body.rule.src.otf_spec);
+ else
+ MERROR (MERROR_FLT, INVALID_CMD_ID);
+ cmd->body.rule.src_type = SRC_OTF_SPEC;
+ }
+ else
+ {
+ cmd->body.rule.src_type = SRC_HAS_GLYPH;
+ if (MPLIST_INTEGER_P (pl))
+ cmd->body.rule.src.supported_glyph
+ = MPLIST_INTEGER (pl);
+ else
+ cmd->body.rule.src.supported_glyph = -1;
+ }
+ }
+ else
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+ }
+ else
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+
+ elt = MPLIST_NEXT (elt);
+ cmd->body.rule.n_cmds = len;
+ MTABLE_CALLOC (cmd->body.rule.cmd_ids, len, MERROR_DRAW);
+ for (i = 0; i < len; i++, elt = MPLIST_NEXT (elt))
+ {
+ int this_id = load_command (stage, elt, macros, INVALID_CMD_ID);
+
+ if (this_id == INVALID_CMD_ID || this_id == -2)
+ MERROR (MERROR_DRAW, this_id);
+ /* The above load_command may relocate stage->cmds. */
+ cmd = stage->cmds + CMD_ID_TO_INDEX (id);
+ cmd->body.rule.cmd_ids[i] = this_id;
+ }
+ }
+ }
+ else if (MPLIST_SYMBOL_P (plist))
+ {
+ MPlist *elt;
+ MSymbol sym = MPLIST_SYMBOL (plist);
+ char *name = msymbol_name (sym);
+ int len = strlen (name);
+ FontLayoutCmd cmd;
+
+ if (len > 4
+ && ((name[0] == 'o' && name[1] == 't'
+ && name[2] == 'f' && name[3] == ':')
+ || (name[0] == ':' && name[1] == 'o' && name[2] == 't'
+ && name[3] == 'f' && name[4] == '=')))
+ {
+ result = load_otf_command (&cmd, sym);
+ if (result < 0)
+ return result;
+ if (id == INVALID_CMD_ID)
+ {
+ id = INDEX_TO_CMD_ID (stage->used);
+ MLIST_APPEND1 (stage, cmds, cmd, MERROR_DRAW);
+ }
+ else
+ stage->cmds[CMD_ID_TO_INDEX (id)] = cmd;
+ return id;
+ }
+
+ if (len == 1)
+ {
+ if (*name == '=')
+ return CMD_ID_COPY;
+ else if (*name == '*')
+ return CMD_ID_REPEAT;
+ else if (*name == '<')
+ return CMD_ID_CLUSTER_BEGIN;
+ else if (*name == '>')
+ return CMD_ID_CLUSTER_END;
+ else if (*name == '|')
+ return CMD_ID_SEPARATOR;
+ else if (*name == '[')
+ return CMD_ID_LEFT_PADDING;
+ else if (*name == ']')
+ return CMD_ID_RIGHT_PADDING;
+ else
+ id = 0;
+ }
+ else
+ {
+ id = get_combining_command (sym);
+ if (id)
+ return id;
+ }
+
+ i = 1;
+ MPLIST_DO (elt, macros)
+ {
+ if (sym == MPLIST_SYMBOL (MPLIST_PLIST (elt)))
+ {
+ id = INDEX_TO_CMD_ID (i);
+ if (stage->cmds[i].type == FontLayoutCmdTypeMAX)
+ id = load_command (stage, MPLIST_NEXT (MPLIST_PLIST (elt)),
+ macros, id);
+ return id;
+ }
+ i++;
+ }
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+ }
+ else
+ MERROR (MERROR_DRAW, INVALID_CMD_ID);
+
+ return id;
+}
+
+static void
+free_flt_command (FontLayoutCmd *cmd)
+{
+ if (cmd->type == FontLayoutCmdTypeRule)
+ {
+ FontLayoutCmdRule *rule = &cmd->body.rule;
+
+ if (rule->src_type == SRC_REGEX)
+ {
+ free (rule->src.re.pattern);
+ regfree (&rule->src.re.preg);
+ }
+ else if (rule->src_type == SRC_SEQ)
+ free (rule->src.seq.codes);
+ free (rule->cmd_ids);
+ }
+ else if (cmd->type == FontLayoutCmdTypeCond)
+ free (cmd->body.cond.cmd_ids);
+ else if (cmd->type == FontLayoutCmdTypeOTF)
+ {
+ 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 a generator from PLIST into a newly allocated FontLayoutStage,
+ and return it. PLIST has this form:
+ PLIST ::= ( COMMAND ( CMD-NAME COMMAND ) * )
+*/
+
+static FontLayoutStage *
+load_generator (MPlist *plist)
+{
+ FontLayoutStage *stage;
+ MPlist *elt, *pl;
+ FontLayoutCmd dummy;
+ int result;
+
+ MSTRUCT_CALLOC (stage, MERROR_DRAW);
+ MLIST_INIT1 (stage, cmds, 32);
+ dummy.type = FontLayoutCmdTypeMAX;
+ MLIST_APPEND1 (stage, cmds, dummy, MERROR_FONT);
+ MPLIST_DO (elt, MPLIST_NEXT (plist))
+ {
+ if (! MPLIST_PLIST_P (elt))
+ MERROR (MERROR_FONT, NULL);
+ pl = MPLIST_PLIST (elt);
+ if (! MPLIST_SYMBOL_P (pl))
+ MERROR (MERROR_FONT, NULL);
+ MLIST_APPEND1 (stage, cmds, dummy, MERROR_FONT);
+ }
+
+ /* Load the first command from PLIST into STAGE->cmds[0]. Macros
+ called in the first command are also loaded from MPLIST_NEXT
+ (PLIST) into STAGE->cmds[n]. */
+ result = load_command (stage, plist, MPLIST_NEXT (plist),
+ INDEX_TO_CMD_ID (0));
+ if (result == INVALID_CMD_ID || result == -2)
+ {
+ MLIST_FREE1 (stage, cmds);
+ free (stage);
+ return NULL;
+ }
+
+ return stage;
+}
+
+
+/* Load stages of the font layout table FLT. */
+
+static int
+load_flt (MFLT *flt, MPlist *key_list)
+{
+ MPlist *top, *plist, *pl, *p;
+ MCharTable *category = NULL;
+ MSymbol sym;
+
+ 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))
+ {
+ M17N_OBJECT_UNREF (top);
+ MERROR (MERROR_FLT, -1);
+ }
+
+ if (key_list)
+ {
+ 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)
+ {
+ mplist_set (plist, Mnil, NULL);
+ break;
+ }
+ if (! MPLIST_PLIST (plist))
+ 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);
+ else if (flt->coverage)
+ {
+ category = flt->coverage;
+ continue;
+ }
+ category = load_category_table (pl);
+ if (! flt->coverage)
+ {
+ flt->coverage = category;
+ M17N_OBJECT_REF (category);
+ }
+ }
+ else if (sym == Mgenerator)
+ {
+ FontLayoutStage *stage;
+
+ if (! category)
+ break;
+ stage = load_generator (pl);
+ if (! stage)
+ break;
+ stage->category = category;
+ M17N_OBJECT_REF (category);
+ if (! flt->stages)
+ flt->stages = mplist ();
+ mplist_add (flt->stages, Mt, stage);
+ }
+ }
+ if (category)
+ M17N_OBJECT_UNREF (category);
+ M17N_OBJECT_UNREF (top);
+ if (! MPLIST_TAIL_P (plist))
+ {
+ M17N_OBJECT_UNREF (flt->stages);
+ MERROR (MERROR_FLT, -1);
+ }
+ return 0;
+}
+
+
+static void
+free_flt_stage (FontLayoutStage *stage)
+{
+ int i;
+
+ M17N_OBJECT_UNREF (stage->category);
+ for (i = 0; i < stage->used; i++)
+ free_flt_command (stage->cmds + i);
+ MLIST_FREE1 (stage, cmds);
+ 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. */
+
+typedef struct
+{
+ /* Pointer to the current stage. */
+ FontLayoutStage *stage;
+
+ /* Pointer to the font. */
+ MFLTFont *font;
+
+ /* Input and output glyph string. */
+ MFLTGlyphString *in, *out;
+
+ /* Encode each character or code of a glyph by the current category
+ table into this array. An element is a category letter used for
+ a regular expression matching. */
+ char *encoded;
+ int *match_indices;
+ int code_offset;
+ int cluster_begin_idx;
+ int cluster_begin_pos;
+ int cluster_end_pos;
+ int combining_code;
+ int left_padding;
+ int check_mask;
+} FontLayoutContext;
+
+static int run_command (int, int, int, int, FontLayoutContext *);
+
+#define NMATCH 20
+
+static int
+run_rule (int depth,
+ FontLayoutCmdRule *rule, int from, int to, FontLayoutContext *ctx)
+{
+ int *saved_match_indices = ctx->match_indices;
+ int match_indices[NMATCH * 2];
+ int consumed;
+ int i;
+ int orig_from = from;
+
+ if (rule->src_type == SRC_SEQ)
+ {
+ int len;
+
+ len = rule->src.seq.n_codes;
+ if (len > (to - from))
+ return 0;
+ for (i = 0; i < len; i++)
+ if (rule->src.seq.codes[i] != GREF (ctx->in, from + i)->code)
+ break;
+ if (i < len)
+ return 0;
+ to = from + len;
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s(SEQ 0x%X", depth, "",
+ rule->src.seq.codes[0]);
+ }
+ else if (rule->src_type == SRC_RANGE)
+ {
+ int head;
+
+ if (from >= to)
+ return 0;
+ head = GREF (ctx->in, from)->code;
+ if (head < rule->src.range.from || head > rule->src.range.to)
+ return 0;
+ ctx->code_offset = head - rule->src.range.from;
+ to = from + 1;
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT4 ("\n [FLT] %*s(RANGE 0x%X-0x%X", depth, "",
+ rule->src.range.from, rule->src.range.to);
+ }
+ else if (rule->src_type == SRC_REGEX)
+ {
+ regmatch_t pmatch[NMATCH];
+ char saved_code;
+ int result;
+
+ if (from > to)
+ return 0;
+ saved_code = ctx->encoded[to];
+ ctx->encoded[to] = '\0';
+ result = regexec (&(rule->src.re.preg),
+ 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,
+ pmatch[0].rm_eo);
+ ctx->encoded[to] = saved_code;
+ for (i = 0; i < NMATCH; i++)
+ {
+ if (pmatch[i].rm_so < 0)
+ match_indices[i * 2] = match_indices[i * 2 + 1] = -1;
+ else
+ {
+ match_indices[i * 2] = from + pmatch[i].rm_so;
+ match_indices[i * 2 + 1] = from + pmatch[i].rm_eo;
+ }
+ }
+ ctx->match_indices = match_indices;
+ to = match_indices[1];
+ }
+ else
+ {
+ ctx->encoded[to] = saved_code;
+ return 0;
+ }
+ }
+ else if (rule->src_type == SRC_INDEX)
+ {
+ if (rule->src.match_idx >= NMATCH)
+ return 0;
+ from = ctx->match_indices[rule->src.match_idx * 2];
+ if (from < 0)
+ return 0;
+ to = ctx->match_indices[rule->src.match_idx * 2 + 1];
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s(INDEX %d", depth, "", rule->src.match_idx);
+ }
+ else if (rule->src_type == SRC_HAS_GLYPH)
+ {
+ int encoded;
+ unsigned code;
+
+ if (rule->src.supported_glyph < 0)
+ {
+ if (from >= to)
+ return 0;
+ code = GREF (ctx->in, from)->code;
+ to = from + 1;
+ encoded = GREF (ctx->in, from)->encoded;
+ }
+ else
+ {
+ code = rule->src.supported_glyph;
+ to = from;
+ encoded = 0;
+ }
+ if (! encoded)
+ {
+ static MFLTGlyphString gstring;
+
+ if (! gstring.glyph_size)
+ {
+ gstring.glyph_size = ctx->in->glyph_size;
+ gstring.glyphs = calloc (1, gstring.glyph_size);
+ gstring.allocated = 1;
+ gstring.used = 1;
+ }
+ gstring.glyphs[0].code = code;
+ if (ctx->font->get_glyph_id (ctx->font, &gstring, 0, 1) < 0
+ || ! gstring.glyphs[0].encoded)
+ return 0;
+ }
+ }
+ else if (rule->src_type == SRC_OTF_SPEC)
+ {
+ MFLTOtfSpec *spec = &rule->src.otf_spec;
+
+ if (! ctx->font->check_otf)
+ {
+ if ((spec->features[0] && spec->features[0][0] != 0xFFFFFFFF)
+ || (spec->features[1] && spec->features[1][0] != 0xFFFFFFFF))
+ return 0;
+ }
+ else if (! ctx->font->check_otf (ctx->font, spec))
+ return 0;
+ }
+
+ consumed = 0;
+ depth++;
+ for (i = 0; i < rule->n_cmds; i++)
+ {
+ int pos;
+
+ if (rule->cmd_ids[i] == CMD_ID_REPEAT)
+ {
+ if (! consumed)
+ continue;
+ i--;
+ }
+ pos = run_command (depth, rule->cmd_ids[i], from, to, ctx);
+ if (pos < 0)
+ return pos;
+ consumed = pos > from;
+ if (consumed)
+ from = pos;
+ }
+
+ ctx->match_indices = saved_match_indices;
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT (")");
+ return (rule->src_type == SRC_INDEX ? orig_from : to);
+}
+
+static int
+run_cond (int depth,
+ FontLayoutCmdCond *cond, int from, int to, FontLayoutContext *ctx)
+{
+ int i, pos = 0;
+
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT2 ("\n [FLT] %*s(COND", depth, "");
+ depth++;
+ for (i = 0; i < cond->n_cmds; i++)
+ {
+ /* TODO: Write a code for optimization utilizaing the info
+ cond->seq_XXX. */
+ if ((pos = run_command (depth, cond->cmd_ids[i], from, to, ctx))
+ != 0)
+ break;
+ }
+ if (pos < 0)
+ return pos;
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT (")");
+ return (pos);
+}
+
+static int
+run_otf (int depth,
+ MFLTOtfSpec *otf_spec, int from, int to, FontLayoutContext *ctx)
+{
+ MFLTFont *font = ctx->font;
+ int from_idx = ctx->out->used;
+
+ 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 (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;
+
+ 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])
+ {
+ MFLTGlyphAdjustment *a;
+ MFLTGlyph *g;
+
+ for (i = 0, a = adjustment; i < out_len; i++, a++)
+ if (a->set)
+ break;
+ if (i < out_len)
+ {
+ font->get_metrics (font, ctx->out, from_idx, ctx->out->used);
+ for (i = 0, g = GREF (ctx->out, from_idx + i), a = adjustment;
+ i < out_len; i++, a++, g = NEXT (ctx->out, g))
+ {
+ SET_MEASURED (g, 1);
+ if (a->advance_is_absolute)
+ {
+ g->xadv = a->xadv;
+ g->yadv = a->yadv;
+ }
+ else if (a->xadv || a->yadv)
+ {
+ g->xadv += a->xadv;
+ g->yadv += a->yadv;
+ }
+ if (a->xoff || a->yoff)
+ {
+ int j;
+ MFLTGlyph *gg = PREV (ctx->out, g);
+ MFLTGlyphAdjustment *aa = a;
+
+ g->xoff = a->xoff;
+ g->yoff = a->yoff;
+ while (aa->back > 0)
+ {
+ for (j = 0; j < aa->back;
+ j++, gg = PREV (ctx->out, gg))
+ g->xoff -= gg->xadv;
+ aa = aa - aa->back;
+ g->xoff += aa->xoff;
+ g->yoff += aa->yoff;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (ctx->cluster_begin_idx >= 0)
+ for (; from_idx < ctx->out->used; from_idx++)
+ {
+ MFLTGlyph *g = GREF (ctx->out, from_idx);
+ UPDATE_CLUSTER_RANGE (ctx, g);
+ }
+ return to;
+}
+
+static char work[16];
+
+static char *
+dump_combining_code (int code)
+{
+ char *vallign = "tcbB";
+ char *hallign = "lcr";
+ char *p;
+ int off_x, off_y;
+
+ if (! code)
+ return "none";
+ work[0] = vallign[COMBINING_CODE_BASE_Y (code)];
+ work[1] = hallign[COMBINING_CODE_BASE_X (code)];
+ off_y = COMBINING_CODE_OFF_Y (code);
+ off_x = COMBINING_CODE_OFF_X (code);
+ if (off_y > 0)
+ sprintf (work + 2, "+%d", off_y);
+ else if (off_y < 0)
+ sprintf (work + 2, "%d", off_y);
+ else if (off_x == 0)
+ sprintf (work + 2, ".");
+ p = work + strlen (work);
+ if (off_x > 0)
+ sprintf (p, ">%d", off_x);
+ else if (off_x < 0)
+ sprintf (p, "<%d", -off_x);
+ p += strlen (p);
+ p[0] = vallign[COMBINING_CODE_ADD_Y (code)];
+ p[1] = hallign[COMBINING_CODE_ADD_X (code)];
+ p[2] = '\0';
+ return work;
+}
+
+static int
+run_command (int depth, int id, int from, int to, FontLayoutContext *ctx)
+{
+ MFLTGlyph *g;
+
+ if (id >= 0)
+ {
+ int i;
+
+ /* Direct code (== ctx->code_offset + id) output.
+ The source is not consumed. */
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s(DIRECT 0x%X", depth, "",
+ ctx->code_offset + id);
+ i = (from < to || from == 0) ? from : from - 1;
+ GDUP (ctx, i);
+ g = GREF (ctx->out, ctx->out->used - 1);
+ g->code = ctx->code_offset + id;
+ SET_ENCODED (g, 0);
+ SET_MEASURED (g, 0);
+ if (ctx->combining_code)
+ SET_COMBINING_CODE (g, ctx, ctx->combining_code);
+ if (ctx->left_padding)
+ SET_LEFT_PADDING (g, ctx, LeftPaddingMask);
+ for (i = from; i < to; i++)
+ {
+ MFLTGlyph *tmp = GREF (ctx->in, i);
+
+ if (g->from > tmp->from)
+ g->from = tmp->from;
+ else if (g->to < tmp->to)
+ g->to = tmp->to;
+ }
+ UPDATE_CLUSTER_RANGE (ctx, g);
+ ctx->code_offset = ctx->combining_code = ctx->left_padding = 0;
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT (")");
+ return (from);
+ }
+
+ if (id <= CMD_ID_OFFSET_INDEX)
+ {
+ int idx = CMD_ID_TO_INDEX (id);
+ FontLayoutCmd *cmd;
+
+ if (idx >= ctx->stage->used)
+ MERROR (MERROR_DRAW, -1);
+ cmd = ctx->stage->cmds + idx;
+ if (cmd->type == FontLayoutCmdTypeRule)
+ to = run_rule (depth, &cmd->body.rule, from, to, ctx);
+ else if (cmd->type == FontLayoutCmdTypeCond)
+ to = run_cond (depth, &cmd->body.cond, from, to, ctx);
+ else if (cmd->type == FontLayoutCmdTypeOTF)
+ to = run_otf (depth, &cmd->body.otf, from, to, ctx);
+ return to;
+ }
+
+ if (id <= CMD_ID_OFFSET_COMBINING)
+ {
+ ctx->combining_code = CMD_ID_TO_COMBINING_CODE (id);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s(CMB %s)", depth, "",
+ dump_combining_code (ctx->combining_code));
+ return from;
+ }
+
+ switch (id)
+ {
+ case CMD_ID_COPY:
+ {
+ if (from >= to)
+ return from;
+ GDUP (ctx, from);
+ g = GREF (ctx->out, ctx->out->used - 1);
+ if (ctx->combining_code)
+ SET_COMBINING_CODE (g, ctx, ctx->combining_code);
+ if (ctx->left_padding)
+ SET_LEFT_PADDING (g, ctx, LeftPaddingMask);
+ UPDATE_CLUSTER_RANGE (ctx, g);
+ if (MDEBUG_FLAG () > 2)
+ {
+ if (g->c < 0)
+ MDEBUG_PRINT2 ("\n [FLT] %*s(COPY |)", depth, "");
+ else
+ MDEBUG_PRINT3 ("\n [FLT] %*s(COPY 0x%X)", depth, "", g->code);
+ }
+ ctx->code_offset = ctx->combining_code = ctx->left_padding = 0;
+ return (from + 1);
+ }
+
+ case CMD_ID_CLUSTER_BEGIN:
+ if (ctx->cluster_begin_idx < 0)
+ {
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT3 ("\n [FLT] %*s<%d", depth, "",
+ GREF (ctx->in, from)->from);
+ ctx->cluster_begin_idx = ctx->out->used;
+ ctx->cluster_begin_pos = GREF (ctx->in, from)->from;
+ ctx->cluster_end_pos = GREF (ctx->in, from)->to;
+ }
+ return from;
+
+ case CMD_ID_CLUSTER_END:
+ if (ctx->cluster_begin_idx >= 0
+ && ctx->cluster_begin_idx < ctx->out->used)
+ {
+ int i;
+
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT1 (" %d>", ctx->cluster_end_pos + 1);
+ for (i = ctx->cluster_begin_idx; i < ctx->out->used; i++)
+ {
+ GREF (ctx->out, i)->from = ctx->cluster_begin_pos;
+ GREF (ctx->out, i)->to = ctx->cluster_end_pos;
+ }
+ ctx->cluster_begin_idx = -1;
+ }
+ return from;
+
+ case CMD_ID_SEPARATOR:
+ {
+ int i;
+
+ 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, 0);
+ SET_MEASURED (g, 0);
+ return from;
+ }
+
+ case CMD_ID_LEFT_PADDING:
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT2 ("\n [FLT] %*s[", depth, "");
+ ctx->left_padding = 1;
+ return from;
+
+ case CMD_ID_RIGHT_PADDING:
+ if (ctx->out->used > 0)
+ {
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT2 ("\n [FLT] %*s]", depth, "");
+ g = GREF (ctx->out, ctx->out->used - 1);
+ SET_RIGHT_PADDING (g, ctx, RightPaddingMask);
+ }
+ return from;
+ }
+
+ MERROR (MERROR_DRAW, -1);
+}
+
+static int
+run_stages (MFLTGlyphString *gstring, int from, int to,
+ MFLT *flt, FontLayoutContext *ctx)
+{
+ MFLTGlyphString buf, *temp;
+ int stage_idx = 0;
+ int orig_from = from, orig_to = to;
+ int from_pos, to_pos, len;
+ int i, j;
+ MFLTGlyph *g;
+ MPlist *stages = flt->stages;
+
+ from_pos = GREF (ctx->in, from)->from;
+ to_pos = GREF (ctx->in, to - 1)->to;
+ len = to_pos - from_pos;
+
+ buf = *(ctx->in);
+ buf.glyphs = NULL;
+ GINIT (ctx->out, ctx->out->allocated);
+ ctx->encoded = alloca (ctx->out->allocated);
+ if (! ctx->out->glyphs || ! ctx->encoded)
+ return -1;
+
+ for (stage_idx = 0; 1; stage_idx++)
+ {
+ MCharTable *table;
+ int result;
+
+ ctx->stage = (FontLayoutStage *) MPLIST_VAL (stages);
+ table = ctx->stage->category;
+ ctx->code_offset = ctx->combining_code = ctx->left_padding = 0;
+ for (i = from; i < to; i++)
+ {
+ MFLTGlyph *g = GREF (ctx->in, i);
+ char enc = (GET_ENCODED (g)
+ ? (g->c > 0 ? (int) mchartable_lookup (table, g->c) : 1)
+ : g->code
+ ? (int) mchartable_lookup (table, g->code)
+ : ' ');
+
+ ctx->encoded[i] = enc;
+ if (! enc && stage_idx == 0)
+ {
+ to = i;
+ break;
+ }
+ }
+ ctx->encoded[i] = '\0';
+ ctx->match_indices[0] = from;
+ ctx->match_indices[1] = to;
+ for (i = 2; i < NMATCH; i++)
+ ctx->match_indices[i] = -1;
+
+ if (MDEBUG_FLAG () > 2)
+ {
+ MDEBUG_PRINT2 ("\n [FLT] (STAGE %d \"%s\"", stage_idx,
+ ctx->encoded + from);
+ MDEBUG_PRINT (" (");
+ for (i = from; i < to; i++)
+ {
+ g = GREF (ctx->in, i);
+ if (g->c == -1)
+ MDEBUG_PRINT2 ("%*s|", (i > 0), "");
+ else
+ MDEBUG_PRINT3 ("%*s%04X", (i > 0), "", GREF (ctx->in, i)->code);
+ }
+ MDEBUG_PRINT (")");
+ }
+ result = run_command (4, INDEX_TO_CMD_ID (0), from, to, ctx);
+ if (MDEBUG_FLAG () > 2)
+ MDEBUG_PRINT (")");
+ if (result < 0)
+ return result;
+
+ stages = MPLIST_NEXT (stages);
+ /* If this is the last stage, break the loop. */
+ if (MPLIST_TAIL_P (stages))
+ break;
+
+ /* Otherwise, prepare for the next stage. */
+ temp = ctx->in;
+ ctx->in = ctx->out;
+ if (buf.glyphs)
+ ctx->out = temp;
+ else
+ {
+ GINIT (&buf, ctx->out->allocated);
+ ctx->out = &buf;
+ }
+ ctx->out->used = 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;
+
+ /* Remove separator glyphs. */
+ for (i = 0; i < ctx->out->used;)
+ {
+ g = GREF (ctx->out, i);
+ if (g->c < 0)
+ GREPLACE (NULL, 0, 0, ctx->out, i, i + 1);
+ else
+ i++;
+ }
+
+ /* Get actual glyph IDs of glyphs. */
+ ctx->font->get_glyph_id (ctx->font, ctx->out, 0, ctx->out->used);
+
+ /* Check if all characters in the range are covered by some
+ glyph(s). If not, change <from> and <to> of glyphs to cover
+ uncovered characters. */
+ g_indices = alloca (sizeof (int) * len);
+ if (! g_indices)
+ return -1;
+ for (i = 0; i < len; i++) g_indices[i] = -1;
+ for (i = 0; i < ctx->out->used; i++)
+ {
+ int pos;
+
+ g = GREF (ctx->out, i);
+ for (pos = g->from; pos <= g->to; pos++)
+ if (g_indices[pos - orig_from] < 0)
+ g_indices[pos - orig_from] = i;
+ }
+ for (i = 0; i < len; i++)
+ if (g_indices[i] < 0)
+ {
+ if (i == 0)
+ {
+ int this_from;
+
+ for (i++; i < len && g_indices[i] < 0; i++);
+ j = g_indices[i];
+ g = GREF (ctx->out, j);
+ this_from = g->from;
+ do {
+ g->from = orig_from + i;
+ } while (++j < ctx->out->used
+ && (g = GREF (ctx->out, j))
+ && g->from == this_from);
+ }
+ else
+ {
+ int this_to;
+
+ j = g_indices[i - 1];
+ g = GREF (ctx->out, j);
+ this_to = g->to;
+ do {
+ g->to = orig_from + i + 1;
+ } while (--j >= 0
+ && (g = GREF (ctx->out, j))
+ && g->to == this_to);
+ }
+ }
+
+ ctx->font->get_metrics (ctx->font, ctx->out, 0, ctx->out->used);
+
+ /* Handle combining. */
+ if (ctx->check_mask & CombiningCodeMask)
+ {
+ MFLTGlyph *base = GREF (ctx->out, 0);
+ int base_height = base->ascent + base->descent;
+ int combining_code;
+
+ for (i = 1; i < ctx->out->used; i++)
+ {
+ if ((g = GREF (ctx->out, i))
+ && (combining_code = GET_COMBINING_CODE (g)))
+ {
+ int height = g->ascent + g->descent;
+ int base_x, base_y, add_x, add_y, off_x, off_y;
+
+ if (base->from > g->from)
+ base->from = g->from;
+ else if (base->to < g->to)
+ base->to = g->to;
+
+ base_x = COMBINING_CODE_BASE_X (combining_code);
+ base_y = COMBINING_CODE_BASE_Y (combining_code);
+ add_x = COMBINING_CODE_ADD_X (combining_code);
+ add_y = COMBINING_CODE_ADD_Y (combining_code);
+ off_x = COMBINING_CODE_OFF_X (combining_code);
+ off_y = COMBINING_CODE_OFF_Y (combining_code);
+
+ g->xoff = ((base->xadv * base_x - g->xadv * add_x) / 2
+ + x_ppem * off_x / 100 - base->xadv);
+ if (base_y < 3)
+ g->yoff = base_height * base_y / 2 - base->ascent;
+ else
+ g->yoff = 0;
+ if (add_y < 3)
+ g->yoff -= height * add_y / 2 - g->ascent;
+ g->yoff -= y_ppem * off_y / 100;
+ if (base->lbearing > base->xadv + g->lbearing + g->xoff)
+ base->lbearing = base->xadv + g->lbearing + g->xoff;
+ if (base->rbearing < base->xadv + g->xadv + g->xoff)
+ base->rbearing = base->xadv + g->xadv + g->xoff;
+ if (base->ascent < g->ascent - g->yoff)
+ base->ascent = g->ascent - g->yoff;
+ if (base->descent < g->descent - g->yoff)
+ base->descent = g->descent - g->yoff;
+ g->xadv = g->yadv = 0;
+ if (GET_RIGHT_PADDING (g))
+ SET_RIGHT_PADDING (base, ctx, RightPaddingMask);
+ }
+ else
+ {
+ base = g;
+ base_height = g->ascent + g->descent;
+ }
+ }
+ }
+
+ /* Handle padding */
+ if (ctx->check_mask & (LeftPaddingMask | RightPaddingMask))
+ for (i = 0; i < ctx->out->used; i++)
+ {
+ g = GREF (ctx->out, i);
+ if (! GET_COMBINING_CODE (g))
+ {
+ if (GET_RIGHT_PADDING (g) && g->rbearing > g->xadv)
+ {
+ g->xadv = g->rbearing;
+ }
+ if (GET_LEFT_PADDING (g) && g->lbearing < 0)
+ {
+ g->xoff += - g->lbearing;
+ g->xadv += - g->lbearing;
+ g->rbearing += - g->lbearing;
+ g->lbearing = 0;
+ }
+ }
+ }
+ }
+
+ GREPLACE (ctx->out, 0, ctx->out->used, gstring, orig_from, orig_to);
+ to = orig_from + ctx->out->used;
+ return to;
+}
+
+static void
+setup_combining_coverage (int from, int to, void *val, void *arg)
+{
+ int combining_class = (int) val;
+ int category = 0;
+
+ if (combining_class < 200)
+ category = 'a';
+ else if (combining_class <= 204)
+ {
+ if ((combining_class % 2) == 0)
+ category = "bcd"[(combining_class - 200) / 2];
+ }
+ else if (combining_class <= 232)
+ {
+ if ((combining_class % 2) == 0)
+ category = "efghijklmnopq"[(combining_class - 208) / 2];
+ }
+ else if (combining_class == 233)
+ category = 'r';
+ else if (combining_class == 234)
+ category = 's';
+ else if (combining_class == 240)
+ category = 't';
+ mchartable_set_range ((MCharTable *) arg, from, to, (void *) category);
+}
+
+static void
+setup_combining_flt (MFLT *flt)
+{
+ MSymbol type;
+ MCharTable *combininig_class_table
+ = mchar_get_prop_table (Mcombining_class, &type);
+
+ mchartable_set_range (flt->coverage, 0, 0x10FFFF, (void *) 'u');
+ if (combininig_class_table)
+ mchartable_map (combininig_class_table, (void *) 0,
+ setup_combining_coverage, flt->coverage);
+}
+
+#define CHECK_FLT_STAGES(flt) ((flt)->stages || load_flt (flt, NULL) == 0)
+
+\f
+/* Internal API */
+
+int m17n__flt_initialized;
+
+\f
+/* External API */
+
+/* The following two are actually not exposed to a user but concealed
+ by the macro M17N_INIT (). */
+
+void
+m17n_init_flt (void)
+{
+ int mdebug_flag = MDEBUG_INIT;
+
+ merror_code = MERROR_NONE;
+ if (m17n__flt_initialized++)
+ return;
+ m17n_init_core ();
+ if (merror_code != MERROR_NONE)
+ {
+ m17n__flt_initialized--;
+ return;
+ }
+
+ MDEBUG_PUSH_TIME ();
+
+ Mcond = msymbol ("cond");
+ Mrange = msymbol ("range");
+ Mfont = msymbol ("font");
+ Mlayouter = msymbol ("layouter");
+ Mcombining = msymbol ("combining");
+ Mfont_facility = msymbol ("font-facility");
+ Mgenerator = msymbol ("generator");
+ Mend = msymbol ("end");
+
+ MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize the flt modules."));
+ MDEBUG_POP_TIME ();
+}
+
+void
+m17n_fini_flt (void)
+{
+ int mdebug_flag = MDEBUG_FINI;
+
+ if (m17n__flt_initialized == 0
+ || --m17n__flt_initialized > 0)
+ return;
+
+ MDEBUG_PUSH_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 (MSymbol name)
+{
+ MFLT *flt;
+
+ if (! flt_list && list_flt () < 0)
+ return NULL;
+ flt = mplist_get (flt_list, name);
+ if (! flt || ! CHECK_FLT_STAGES (flt))
+ return NULL;
+ if (flt->name == Mcombining
+ && ! mchartable_lookup (flt->coverage, 0))
+ setup_combining_flt (flt);
+
+ 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->registry != unicode_bmp
+ && flt->registry != unicode_full)
+ continue;
+ if (flt->family && flt->family != font->family)
+ continue;
+ if (c >= 0
+ && ! mchartable_lookup (flt->coverage, c))
+ continue;
+ 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, spec))
+ continue;
+ return flt;
+ }
+ best = flt;
+ }
+ return best;
+ }
+ if (c >= 0)
+ {
+ MPLIST_DO (plist, flt_list)
+ {
+ flt = MPLIST_VAL (plist);
+ if (mchartable_lookup (flt->coverage, c))
+ return flt;
+ }
+ }
+ return NULL;
+}
+
+/*=*/
+/***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)
+{
+ 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)
+{
+ FontLayoutContext ctx;
+ int match_indices[NMATCH];
+ MFLTGlyph *g;
+ MFLTGlyphString out;
+ int auto_flt = ! flt;
+ int c, i, j, k;
+ int this_from, this_to;
+
+ 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;
+
+ for (i = from; i < to; i++)
+ {
+ g = GREF (gstring, i);
+ c = g->c;
+ memset (g, 0, sizeof (MFLTGlyph));
+ g->code = g->c = c;
+ g->from = g->to = i;
+ }
+
+ for (this_from = from; this_from < to;)
+ {
+ if (! auto_flt)
+ {
+ for (this_to = this_from; this_to < to; this_to++)
+ 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;
+
+ MDEBUG_PRINT1 (" [FLT] (%s", MSYMBOL_NAME (flt->name));
+
+ for (; this_to < to; this_to++)
+ if (! mchartable_lookup (flt->coverage, GREF (gstring, this_to)->c))
+ break;
+
+ if (MDEBUG_FLAG ())
+ {
+ if (font->family)
+ MDEBUG_PRINT1 (" (%s)", MSYMBOL_NAME (font->family));
+ 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 (")");
+ }
+
+ 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 (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;
+ }
+
+ if (gstring->r2l)
+ {
+ 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;
+}
+
+\f
+/* for debugging... */
+
+static void
+dump_flt_cmd (FontLayoutStage *stage, int id, int indent)
+{
+ char *prefix = (char *) alloca (indent + 1);
+
+ memset (prefix, 32, indent);
+ prefix[indent] = 0;
+
+ if (id >= 0)
+ fprintf (stderr, "0x%02X", id);
+ else if (id <= CMD_ID_OFFSET_INDEX)
+ {
+ int idx = CMD_ID_TO_INDEX (id);
+ FontLayoutCmd *cmd = stage->cmds + idx;
+
+ if (cmd->type == FontLayoutCmdTypeRule)
+ {
+ FontLayoutCmdRule *rule = &cmd->body.rule;
+ int i;
+
+ fprintf (stderr, "(rule ");
+ if (rule->src_type == SRC_REGEX)
+ fprintf (stderr, "\"%s\"", rule->src.re.pattern);
+ else if (rule->src_type == SRC_INDEX)
+ fprintf (stderr, "%d", rule->src.match_idx);
+ else if (rule->src_type == SRC_SEQ)
+ fprintf (stderr, "(seq)");
+ else if (rule->src_type == SRC_RANGE)
+ fprintf (stderr, "(range)");
+ else
+ fprintf (stderr, "(invalid src)");
+
+ for (i = 0; i < rule->n_cmds; i++)
+ {
+ fprintf (stderr, "\n%s ", prefix);
+ dump_flt_cmd (stage, rule->cmd_ids[i], indent + 2);
+ }
+ fprintf (stderr, ")");
+ }
+ else if (cmd->type == FontLayoutCmdTypeCond)
+ {
+ FontLayoutCmdCond *cond = &cmd->body.cond;
+ int i;
+
+ fprintf (stderr, "(cond");
+ for (i = 0; i < cond->n_cmds; i++)
+ {
+ fprintf (stderr, "\n%s ", prefix);
+ dump_flt_cmd (stage, cond->cmd_ids[i], indent + 2);
+ }
+ fprintf (stderr, ")");
+ }
+ else if (cmd->type == FontLayoutCmdTypeOTF)
+ {
+ fprintf (stderr, "(otf)");
+ }
+ else
+ fprintf (stderr, "(error-command)");
+ }
+ else if (id <= CMD_ID_OFFSET_COMBINING)
+ fprintf (stderr, "cominging-code");
+ else
+ fprintf (stderr, "(predefiend %d)", id);
+}
+
+void
+mdebug_dump_flt (MFLT *flt, int indent)
+{
+ char *prefix = (char *) alloca (indent + 1);
+ MPlist *plist;
+ int stage_idx = 0;
+
+ memset (prefix, 32, indent);
+ prefix[indent] = 0;
+ fprintf (stderr, "(flt");
+ MPLIST_DO (plist, flt->stages)
+ {
+ FontLayoutStage *stage = (FontLayoutStage *) MPLIST_VAL (plist);
+ int i;
+
+ fprintf (stderr, "\n%s (stage %d", prefix, stage_idx);
+ for (i = 0; i < stage->used; i++)
+ {
+ fprintf (stderr, "\n%s ", prefix);
+ dump_flt_cmd (stage, INDEX_TO_CMD_ID (i), indent + 4);
+ }
+ fprintf (stderr, ")");
+ stage_idx++;
+ }
+ fprintf (stderr, ")");
+}
+
+/*** @} */
+
+/*
+ Local Variables:
+ coding: euc-japan
+ End:
+*/
--- /dev/null
+/* m17n-flt.h -- header file for the FLT API of the m17n library.
+ Copyright (C) 2007
+ National Institute of Advanced Industrial Science and Technology (AIST)
+ Registration Number H15PRO112
+
+ This file is part of the m17n library.
+
+ The m17n library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public License
+ as published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ The m17n library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the m17n library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ 02111-1307, USA. */
+
+#ifndef _M17N_FLT_H_
+#define _M17N_FLT_H_
+
+#ifndef _M17N_CORE_H_
+#include <m17n-core.h>
+#endif
+
+M17N_BEGIN_HEADER
+
+#if !defined (FOR_DOXYGEN) || defined (DOXYGEN_INTERNAL_MODULE)
+
+extern void m17n_init_flt (void);
+#undef M17N_INIT
+#define M17N_INIT() m17n_init_flt ()
+
+extern void m17n_fini_flt (void);
+#undef M17N_FINI
+#define M17N_FINI() m17n_fini_flt ()
+
+#endif
+
+/***en @defgroup m17nFLT FLT API */
+/***ja @defgroup m17nFLT FLT API */
+/*=*/
+
+/*** @addtogroup m17nFLT */
+/*** @{ */
+/*=*/
+
+/***en
+ @brief Type of information about a glyph.
+
+ The type #MFLTGlyph is the structure that contains information
+ about a glyph. */
+
+typedef struct _MFLTGlyph MFLTGlyph;
+
+struct _MFLTGlyph
+{
+ /***en @brief Character code (Unicode) of the glyph. This is the sole
+ member to be set before calling the functions mflt_find () and
+ mflt_run (). */
+ int c;
+ /***en Glyph-id of the font of the glyph. */
+ unsigned int code;
+ /***en Glyph indices indicating the start of the original glyphs. */
+ int from;
+ /***en Glyph indices indicating the end of the original glyphs. */
+ int to;
+ /***en Advance width for horizontal layout expressed in 26.6
+ fractional pixel format. */
+ int xadv;
+ /***en Advance height for vertical layout expressed in 26.6
+ fractional pixel format. */
+ int yadv;
+ /***en Ink metrics of the glyph expressed in 26.6 fractional pixel
+ format. */
+ int ascent, descent, lbearing, rbearing;
+ /***en Horizontal and vertical adjustments for the glyph positioning
+ expressed in 26.6 fractional pixel format. */
+ int xoff, yoff;
+ /***en Flag to tell if the member <code> is already encoded into a
+ glyph ID of a font. */
+ unsigned encoded : 1;
+ /***en Flag to tell if the metrics of the glyph (members <xadv> thru
+ <rbearing>) are already calculated. */
+ unsigned measured : 1;
+ /***en For m17n-lib's internal use only. */
+ unsigned internal : 30;
+
+ /* Arbitrary data can follow. */
+};
+
+/*=*/
+
+/***en
+ @brief Type of information about a glyph position adjustment.
+
+ The type #MFLTGlyphAdjustment is the structure to store
+ information about a glyph metrics/position adjustment. It is
+ given to the callback function #drive_otf of #MFLTFont. */
+
+typedef struct _MFLTGlyphAdjustment MFLTGlyphAdjustment;
+
+struct _MFLTGlyphAdjustment
+{
+ /***en Adjustments for advance width for horizontal layout and
+ advance height for vertical layout expressed in 26.6 fractional
+ pixel format. */
+ int xadv, yadv;
+ /***en Horizontal and vertical adjustments for a glyph positioning
+ expressed in 26.6 fractional pixel format. */
+ int xoff, yoff;
+ /***en Number of glyphs to go back for drawing a glyph. */
+ short back;
+ /***en If nonzero, the member <xadv> and <yadv> are absolute, i.e.,
+ they should not be added to a glyph's origianl advance width and
+ height. */
+ unsigned advance_is_absolute : 1;
+ /***en Should be set to 1 iff at least one of the other members has
+ a nonzero value. */
+ unsigned set : 1;
+};
+
+/***en
+ @brief Type of information about a glyph sequence.
+
+ The type #MFLTGlyphString is the structure that contains
+ information about a sequence of glyphs. */
+
+typedef struct _MFLTGlyphString MFLTGlyphString;
+
+struct _MFLTGlyphString
+{
+ /***en The actual byte size of elements of the array pointed by the
+ member #glyphs. It must be equal to or greater than "sizeof
+ (MFLTGlyph)". */
+ int glyph_size;
+ /***en Array of glyphs. */
+ MFLTGlyph *glyphs;
+ /***en How many elements are allocated in #glyphs. */
+ int allocated;
+ /***en How many elements in #glyphs are in use. */
+ int used;
+ /***en Flag to tell if the glyphs should be drawn from right-to-left
+ or not. */
+ unsigned int r2l;
+};
+
+/***en
+ @brief Type of specification of GSUB and GPOS OpenType tables.
+
+ The type #MFLTOtfSpec is the structure that contains information
+ about GSUB and GPOS features of a specific script and language
+ system to be applied to a glyph sequence. */
+
+typedef struct _MFLTOtfSpec MFLTOtfSpec;
+
+struct _MFLTOtfSpec
+{
+ /***en Unique symbol representing the spec. This is the same as the
+ #OTF-SPEC of the FLT. */
+ MSymbol sym;
+
+ /***en Tags for script and language system. */
+ unsigned int script, langsys;
+
+ /***en Array of GSUB (1st element) and GPOS (2nd element) features.
+ Each array is terminated by 0. If an element is 0xFFFFFFFF,
+ apply the previous features in that order, and apply all the
+ other features except those appearing in the following elements.
+ It may be NULL if there's no feature. */
+ unsigned int *features[2];
+};
+
+/***en
+ @brief Type of font to be used by the FLT driver.
+
+ The type #MFLTFont is the structure that contains information
+ about a font used by the FLT driver. */
+
+typedef struct _MFLTFont MFLTFont;
+
+struct _MFLTFont
+{
+ /***en Family name of the font. It may be #Mnil if the family name
+ is not important in finding a Font Layout Table suitable for the
+ font (for instance, in the case that the font is an OpenType
+ font). */
+ MSymbol family;
+
+ /***en Horizontal and vertical font sizes in pixel per EM. */
+ int x_ppem, y_ppem;
+
+ /***en Callback function to get glyph IDs for glyphs between FROM
+ (inclusive) and TO (exclusive) of GSTRING. If <encoded> member
+ of a glyph is zero, the <code> member of the glyph is a character
+ code. The function must convert it to the glyph ID of FONT. */
+ int (*get_glyph_id) (MFLTFont *font, MFLTGlyphString *gstring,
+ int from, int to);
+
+ /*** Callback function to get metrics of glyphs between FROM
+ (inclusive) and TO (exclusive) of GSTRING. If <measured> member
+ of a glyph is zero, the function must set members <xadv>, <yadv>,
+ <ascent>, <descent>, <lbearing>, and <rbearing> of the glyph. */
+ int (*get_metrics) (MFLTFont *font, MFLTGlyphString *gstring,
+ int from, int to);
+
+ /***en Callback function to check if the font has OpenType GSUB/GPOS
+ features for a specific script/language. The function must
+ return 1 if the font satisfy SPEC, else return 0. It must be
+ NULL if the font doesn't have OpenType tables. */
+ int (*check_otf) (MFLTFont *font, MFLTOtfSpec *spec);
+
+ /*** Callback function to apply OpenType features in SPEC to glyphs
+ between FROM (inclusive) and TO (exclusive) of IN. The resulting
+ glyphs should be appended to the tail of OUT. If OUT doesn't
+ have a room to store all resulting glyphs, it must return -2.
+ It must be NULL if the font doesn't have OpenType tables. */
+ int (*drive_otf) (MFLTFont *font, MFLTOtfSpec *spec,
+ MFLTGlyphString *in, int from, int to,
+ MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment);
+
+ /***en For m17n-lib's internal use only. It should be initialized
+ to NULL. */
+ void *internal;
+};
+
+/***en
+ @brief Type of FLT (Font Layout Table).
+
+ The type #MFLT is for a FLT object. Its internal structure is
+ concealed from application program. */
+
+typedef struct _MFLT MFLT;
+
+extern MFLT *mflt_get (MSymbol name);
+
+extern MFLT *mflt_find (int c, MFLTFont *font);
+
+extern const char *mflt_name (MFLT *flt);
+
+extern MCharTable *mflt_coverage (MFLT *flt);
+
+extern int mflt_run (MFLTGlyphString *gstring, int from, int to,
+ MFLTFont *font, MFLT *flt);
+
+/*=*/
+/*** @} */
+
+M17N_END_HEADER
+
+#endif /* _M17N_FLT_H_ */
+
+/*
+ Local Variables:
+ coding: euc-japan
+ End:
+*/
read_rgb_txt ()
{
FILE *fp;
- int r, g, b;
+ int r, g, b, i;
/* At first, support HTML 4.0 color names. */
msymbol_put (msymbol ("black"), M_rgb, (void *) 0x000000);
msymbol_put (msymbol ("teal"), M_rgb, (void *) 0x008080);
msymbol_put (msymbol ("aqua"), M_rgb, (void *) 0x00FFFF);
- fp = fopen ("/usr/lib/X11/rgb.txt", "r");
- if (! fp)
- fp = fopen ("/usr/X11R6/lib/X11/rgb.txt", "r");
- if (! fp)
- return;
+ {
+ char *rgb_path[]
+ = {"/usr/lib/X11/rgb.txt", "/usr/X11R6/lib/X11/rgb.txt",
+ "/etc/X11/rgb.txt" };
+
+ fp = NULL;
+ for (i = 0; i < (sizeof rgb_path) / (sizeof rgb_path[0]); i++)
+ if ((fp = fopen ("/usr/lib/X11/rgb.txt", "r")))
+ break;
+ if (! fp)
+ return;
+ }
while (1)
{
char buf[256];
buf[0] = c;
fgets (buf + 1, 255, fp);
len = strlen (buf);
+ for (i = 0; i < len; i++)
+ buf[i] = tolower (buf[i]);
if (buf[len - 1] == '\n')
buf[len - 1] = '\0';
b |= (r << 16) | (g << 8);
#endif
}
- for (; from < to; x += from++->width)
+ for (; from < to; x += from++->g.xadv)
{
unsigned char *bmp;
int xoff, yoff;
int width, pitch;
- FT_Load_Glyph (ft_face, (FT_UInt) from->code, load_flags);
- yoff = y - ft_face->glyph->bitmap_top + from->yoff;
+ FT_Load_Glyph (ft_face, (FT_UInt) from->g.code, load_flags);
+ yoff = y - ft_face->glyph->bitmap_top + from->g.yoff;
bmp = ft_face->glyph->bitmap.buffer;
width = ft_face->glyph->bitmap.width;
pitch = ft_face->glyph->bitmap.pitch;
for (i = 0; i < ft_face->glyph->bitmap.rows;
i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
{
- xoff = x + ft_face->glyph->bitmap_left + from->xoff;
+ xoff = x + ft_face->glyph->bitmap_left + from->g.xoff;
for (j = 0; j < width; j++, xoff++)
if (bmp[j] > 0)
{
for (i = 0; i < ft_face->glyph->bitmap.rows;
i++, bmp += ft_face->glyph->bitmap.pitch, yoff++)
{
- xoff = x + ft_face->glyph->bitmap_left + from->xoff;
+ xoff = x + ft_face->glyph->bitmap_left + from->g.xoff;
for (j = 0; j < width; j++, xoff++)
if (bmp[j / 8] & (1 << (7 - (j % 8))))
gdImageSetPixel (img, xoff, yoff, pixel);
y -= gstring->ascent - 1;
height = gstring->ascent + gstring->descent - 2;
if (! region)
- for (; from < to; x += from++->width)
- gdImageRectangle (img, x, y, x + from->width - 2, y + height - 1, color);
+ for (; from < to; x += from++->g.xadv)
+ gdImageRectangle (img, x, y, x + from->g.xadv - 2, y + height - 1, color);
else
{
gdImagePtr cpy;
MGlyph *g;
int width, x1;
- for (g = from, width = 0; g < to; width += g++->width);
+ for (g = from, width = 0; g < to; width += g++->g.xadv);
cpy = get_scrach_image (img, width, height);
MPLIST_DO (plist, region_list)
{
gdImageCopy (cpy, img, rect->x - x, rect->y - y, rect->x, rect->y,
rect->x + rect->width, rect->y + rect->height);
}
- for (x1 = 0; from < to; x1 += from++->width)
- gdImageRectangle (cpy, x1, 0, x1 + from->width - 2, height - 1, color);
+ for (x1 = 0; from < to; x1 += from++->g.xadv)
+ gdImageRectangle (cpy, x1, 0, x1 + from->g.xadv - 2, height - 1, color);
MPLIST_DO (plist, region_list)
{
MDrawMetric *rect = MPLIST_VAL (plist);
gdImagePtr cpy;
if (g->type == GLYPH_BOX)
- width = g->width;
+ width = g->g.xadv;
cpy = get_scrach_image (img, width, height);
MPLIST_DO (plist, region_list)
{
int x0, x1;
if (g->left_padding)
- x0 = x + box->outer_hmargin, x1 = x + g->width - 1;
+ x0 = x + box->outer_hmargin, x1 = x + g->g.xadv - 1;
else
- x0 = x, x1 = x + g->width - box->outer_hmargin - 1;
+ x0 = x, x1 = x + g->g.xadv - box->outer_hmargin - 1;
/* Draw the top side. */
color = RESOLVE_COLOR (img, colors[COLOR_BOX_TOP]);
gd_font_driver.has_char = mfont__ft_driver.has_char;
gd_font_driver.encode_char = mfont__ft_driver.encode_char;
gd_font_driver.list = mfont__ft_driver.list;
+ gd_font_driver.check_otf = mfont__ft_driver.check_otf;
+ gd_font_driver.drive_otf = mfont__ft_driver.drive_otf;
return 0;
}
void
m17n_init_win (void)
{
- int mdebug_mask = MDEBUG_INIT;
+ int mdebug_flag = MDEBUG_INIT;
merror_code = MERROR_NONE;
if (m17n__gui_initialized++)
return;
m17n_init ();
+ m17n_init_flt ();
if (merror_code != MERROR_NONE)
{
m17n__gui_initialized--;
void
m17n_fini_win (void)
{
- int mdebug_mask = MDEBUG_FINI;
+ int mdebug_flag = MDEBUG_FINI;
MPlist *plist;
if (m17n__gui_initialized == 0
MDEBUG_POP_TIME ();
MDEBUG_PRINT_TIME ("FINI", (stderr, " to finalize the gui modules."));
MDEBUG_POP_TIME ();
+ m17n_fini_flt ();
m17n_fini ();
}
#ifndef _M17N_GUI_H_
#define _M17N_GUI_H_
+#ifndef _M17N_FLT_H_
+#include <m17n-flt.h>
+#endif
+
#ifndef _M17N_H_
#include <m17n.h>
#endif
MERROR_FRAME,
MERROR_FACE,
MERROR_DRAW,
+ MERROR_FLT,
MERROR_FONT,
MERROR_FONTSET,
MERROR_FONT_OTF,
void
m17n_init (void)
{
- int mdebug_mask = MDEBUG_INIT;
+ int mdebug_flag = MDEBUG_INIT;
merror_code = MERROR_NONE;
if (m17n__shell_initialized++)
if (mcoding__init () < 0)
goto err;
MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize conv module."));
- if (mdatabase__init () < 0)
- goto err;
- MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize database module."));
if (mcharset__load_from_database () < 0)
goto err;
MDEBUG_PRINT_TIME ("INIT", (stderr, " to load charset definitions."));
if (mcoding__load_from_database () < 0)
goto err;
MDEBUG_PRINT_TIME ("INIT", (stderr, " to load coding definitions."));
- if (mchar__init () < 0)
- goto err;
- MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize character module."));
if (mlang__init () < 0)
goto err;
MDEBUG_PRINT_TIME ("INIT", (stderr, " to initialize language module"));
void
m17n_fini (void)
{
- int mdebug_mask = MDEBUG_FINI;
+ int mdebug_flag = MDEBUG_FINI;
if (m17n__shell_initialized == 0
|| --m17n__shell_initialized > 0)
*/
/*=*/
-/*** @ingroup m17nShell */
-/***en @defgroup m17nDatabase Database */
-/***ja @defgroup m17nDatabase ¥Ç¡¼¥¿¥Ù¡¼¥¹ */
-/*=*/
-
-/* Directory of an application specific databases. */
-extern char *mdatabase_dir;
-/*=*/
-/***
- @ingroup m17nDatabase */
-/***en
- @brief Type of database.
-
- The type #MDatabase is for a database object. Its internal
- structure is concealed from an application program. */
-/***ja
- @brief ¥Ç¡¼¥¿¥Ù¡¼¥¹¤Î·¿Àë¸À.
-
- #MDatabase ·¿¤Ï¥Ç¡¼¥¿¥Ù¡¼¥¹¥ª¥Ö¥¸¥§¥¯¥ÈÍѤι½Â¤ÂΤǤ¢¤ë¡£
- ÆâÉô¹½Â¤¤Ï¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥×¥í¥°¥é¥à¤«¤é¤Ï¸«¤¨¤Ê¤¤¡£
- */
-
-typedef struct MDatabase MDatabase;
-
-/*=*/
-
-/* Look for a data. */
-extern MDatabase *mdatabase_find (MSymbol tag1, MSymbol tag2,
- MSymbol tag3, MSymbol tag4);
-
-extern MPlist *mdatabase_list (MSymbol tag0, MSymbol tag1,
- MSymbol tag2, MSymbol tag3);
-
-/* Load a data. */
-void *mdatabase_load (MDatabase *mdb);
-
-/* Get tags of a data. */
-extern MSymbol *mdatabase_tag (MDatabase *mdb);
-
-/* Define a data. */
-extern MDatabase *mdatabase_define (MSymbol tag1, MSymbol tag2,
- MSymbol tag3, MSymbol tag4,
- void *(*loader) (MSymbol *, void *),
- void *extra_info);
-
/*=*/
/* (S2) Charset staffs */
/*=*/
extern MSymbol Msuperset;
/* etc. */
-extern MSymbol Mcharset;
-
extern MSymbol mchar_define_charset (const char *name, MPlist *plist);
extern MSymbol mchar_resolve_charset (MSymbol symbol);
static MPlist *
read_mtext_element (MPlist *plist, MStream *st, int skip)
{
- union {
- int chars[READ_MTEXT_BUF_SIZE];
- unsigned char bytes[sizeof (int) * READ_MTEXT_BUF_SIZE];
- } buffer;
- unsigned char *bytes = buffer.bytes;
- int nbytes = sizeof (int) * READ_MTEXT_BUF_SIZE;
- int *chars = NULL;
- int nchars = 0;
- int c, i, j;
+ unsigned char buffer[READ_MTEXT_BUF_SIZE], *buf = buffer;
+ int nbytes = READ_MTEXT_BUF_SIZE;
+ int c, i;
i = 0;
while ((c = GETC (st)) != EOF && c != '"')
if (! skip)
{
- if (is_char && ! chars)
+ if (i + MAX_UTF8_CHAR_BYTES >= nbytes)
{
- chars = buffer.chars;
- for (j = i - 1; j >= 0; j--)
- chars[j] = bytes[j];
- nchars = READ_MTEXT_BUF_SIZE;
- if (bytes != buffer.bytes)
- free (bytes);
- }
-
- if (chars)
- {
- if (i + 1 >= nchars)
+ if (buf == buffer)
{
- nchars *= 2;
- if (chars == buffer.chars)
- {
- MTABLE_MALLOC (chars, nchars, MERROR_PLIST);
- memcpy (chars, buffer.chars, sizeof (int) * i);
- }
- else
- MTABLE_REALLOC (chars, nchars, MERROR_PLIST);
+ nbytes *= 2;
+ buf = malloc (nbytes);
+ memcpy (buf, buffer, i);
}
- chars[i++] = c;
- }
- else
- {
- if (i + MAX_UTF8_CHAR_BYTES >= nbytes)
+ else
{
- nbytes *= 2;
- if (bytes == buffer.bytes)
- {
- MTABLE_MALLOC (bytes, nbytes, MERROR_PLIST);
- memcpy (bytes, buffer.bytes, i);
- }
- else
- MTABLE_REALLOC (bytes, nbytes, MERROR_PLIST);
+ nbytes += READ_MTEXT_BUF_SIZE;
+ buf = realloc (buf, nbytes);
}
- bytes[i++] = c;
}
+
+ if (is_char)
+ i += CHAR_STRING_UTF8 (c, buf);
+ else
+ buf[i++] = c;
}
}
{
MText *mt;
- if (chars)
- {
- mt = mtext__from_data (chars, i, MTEXT_FORMAT_UTF_32, 1);
- if (chars != buffer.chars)
- free (chars);
- }
+ if (buf == buffer)
+ mt = mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 1);
else
{
- mt = mtext__from_data (bytes, i, MTEXT_FORMAT_UTF_8, 1);
- if (bytes != buffer.bytes)
- free (bytes);
+ mt = mtext__from_data (buf, i, MTEXT_FORMAT_UTF_8, 0);
+ free (buf);
}
MPLIST_SET_ADVANCE (plist, Mtext, mt);
}
}
symbol_table[i] = NULL;
}
- if (mdebug__flag & MDEBUG_FINI)
+ if (mdebug__flags[MDEBUG_FINI])
fprintf (stderr, "%16s %7d %7d %7d\n", "Symbol",
num_symbols, freed_symbols, num_symbols - freed_symbols);
num_symbols = 0;