summaryrefslogtreecommitdiff
path: root/modules/hangul/hangul-fc.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/hangul/hangul-fc.c')
-rw-r--r--modules/hangul/hangul-fc.c269
1 files changed, 269 insertions, 0 deletions
diff --git a/modules/hangul/hangul-fc.c b/modules/hangul/hangul-fc.c
new file mode 100644
index 00000000..13ff5fba
--- /dev/null
+++ b/modules/hangul/hangul-fc.c
@@ -0,0 +1,269 @@
+/* Pango
+ * hangul-xft.c:
+ *
+ * Copyright (C) 2002 Changwoo Ryu
+ * Author: Changwoo Ryu <cwryu@debian.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <string.h>
+
+#include "pangoxft.h"
+#include "pango-engine.h"
+#include "pango-utils.h"
+
+#include "hangul-defs.h"
+#include "tables-jamos.i"
+
+#define SCRIPT_ENGINE_NAME "HangulScriptEngineXft"
+
+static PangoEngineRange hangul_ranges[] = {
+ /* Language characters */
+ { 0x1100, 0x11FF, "*" }, /* Hangul Jamo */
+};
+
+static PangoEngineInfo script_engines[] = {
+ {
+ SCRIPT_ENGINE_NAME,
+ PANGO_ENGINE_TYPE_SHAPE,
+ PANGO_RENDER_TYPE_XFT,
+ hangul_ranges, G_N_ELEMENTS(hangul_ranges)
+ }
+};
+
+static void
+set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGlyph glyph)
+{
+ PangoRectangle logical_rect;
+
+ glyphs->glyphs[i].glyph = glyph;
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+ glyphs->log_clusters[i] = offset;
+
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+}
+
+static guint
+find_char (FT_Face face, PangoFont *font, gunichar wc)
+{
+ int index = FT_Get_Char_Index (face, wc);
+
+ if (index && index <= face->num_glyphs)
+ return index;
+ else
+ return 0;
+}
+
+static void
+render_syllable (FT_Face face, PangoFont *font, gunichar *text, int length,
+ PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
+{
+ int index;
+ gunichar wc;
+ int i, j, composed;
+
+ if (length >= 3 && IS_L_S(text[0]) && IS_V_S(text[1]) && IS_T_S(text[2]))
+ composed = 3;
+ else if (length >= 2 && IS_L_S(text[0]) && IS_V_S(text[1]))
+ composed = 2;
+ else
+ composed = 0;
+
+ if (composed)
+ {
+ if (composed == 3)
+ wc = S_FROM_LVT(text[0], text[1], text[2]);
+ else
+ wc = S_FROM_LV(text[0], text[1]);
+ index = find_char (face, font, wc);
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ if (!index)
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+ pango_xft_font_get_unknown_glyph (font, wc));
+ else
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ (*n_glyphs)++;
+ text += composed;
+ length -= composed;
+ }
+
+ /* Render the remaining text as uncomposed forms as a fallback. */
+ for (i = 0; i < length; i++)
+ {
+ int jindex;
+
+ index = find_char (face, font, text[i]);
+ if (index)
+ {
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ (*n_glyphs)++;
+ continue;
+ }
+
+ /* This font has no glyphs on the Hangul Jamo area! Find a
+ fallback from the Hangul Compatibility Jamo area. */
+ jindex = text[i] - LBASE;
+ for (j = 0; j < 3 && (__jamo_to_ksc5601[jindex][j] != 0); j++)
+ {
+ wc = __jamo_to_ksc5601[jindex][j] - KSC_JAMOBASE + UNI_JAMOBASE;
+ index = (wc >= 0x3131) ? find_char (face, font, wc) : 0;
+ pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+ if (!index)
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+ pango_xft_font_get_unknown_glyph (font, index));
+ else
+ set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+ (*n_glyphs)++;
+ }
+ }
+}
+
+static void
+hangul_engine_shape (PangoFont *font,
+ const char *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ int n_chars, n_glyphs;
+ int i;
+ const char *p, *start;
+ FT_Face face;
+
+ gunichar jamos_static[3];
+ guint max_jamos = G_N_ELEMENTS (jamos_static);
+ gunichar *jamos = jamos_static;
+ int n_jamos;
+
+ face = pango_xft_font_get_face (font);
+ g_assert (face);
+
+ n_chars = g_utf8_strlen (text, length);
+ n_glyphs = 0;
+ start = p = text;
+ n_jamos = 0;
+
+ for (i = 0; i < n_chars; i++)
+ {
+ gunichar wc;
+
+ wc = g_utf8_get_char (p);
+
+ /* Check syllable boundaries. */
+ if (n_jamos != 0 &&
+ ((IS_T (jamos[n_jamos - 1]) && IS_L (wc)) ||
+ (IS_V (jamos[n_jamos - 1]) && IS_L (wc)) ||
+ (IS_T (jamos[n_jamos - 1]) && IS_V (wc))))
+ {
+ /* Draw a syllable. */
+ render_syllable (face, font, jamos, n_jamos, glyphs,
+ &n_glyphs, start - text);
+ n_jamos = 0;
+ start = p;
+ }
+
+ if (n_jamos == max_jamos)
+ {
+ max_jamos++;
+ if (jamos == jamos_static)
+ jamos = g_new (gunichar, max_jamos);
+ else
+ jamos = g_renew (gunichar, jamos, max_jamos);
+ }
+
+ jamos[n_jamos++] = wc;
+ p = g_utf8_next_char (p);
+ }
+
+ if (n_jamos != 0)
+ render_syllable (face, font, jamos, n_jamos, glyphs, &n_glyphs,
+ start - text);
+
+ if (jamos != jamos_static)
+ g_free(jamos);
+}
+
+static PangoCoverage *
+hangul_engine_get_coverage (PangoFont *font,
+ PangoLanguage *lang)
+{
+ PangoCoverage *result = pango_coverage_new ();
+ int i;
+
+ /* Well, no unicode rendering engine could render Hangul Jamo area
+ _exactly_, I sure. */
+ for (i = 0x1100; i <= 0x11FF; i++)
+ pango_coverage_set (result, i, PANGO_COVERAGE_FALLBACK);
+ return result;
+}
+
+static PangoEngine *
+hangul_engine_xft_new ()
+{
+ PangoEngineShape *result;
+
+ result = g_new (PangoEngineShape, 1);
+
+ result->engine.id = SCRIPT_ENGINE_NAME;
+ result->engine.type = PANGO_ENGINE_TYPE_SHAPE;
+ result->engine.length = sizeof (result);
+ result->script_shape = hangul_engine_shape;
+ result->get_coverage = hangul_engine_get_coverage;
+
+ return (PangoEngine *)result;
+}
+
+/* The following three functions provide the public module API for
+ * Pango. If we are compiling it is a module, then we name the
+ * entry points script_engine_list, etc. But if we are compiling
+ * it for inclusion directly in Pango, then we need them to
+ * to have distinct names for this module, so we prepend
+ * _pango_hangul_xft__
+ */
+#ifdef XFT_MODULE_PREFIX
+#define MODULE_ENTRY(func) _pango_hangul_xft_##func
+#else
+#define MODULE_ENTRY(func) func
+#endif
+
+/* List the engines contained within this module
+ */
+void
+MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines)
+{
+ *engines = script_engines;
+ *n_engines = G_N_ELEMENTS (script_engines);
+}
+
+/* Load a particular engine given the ID for the engine
+ */
+PangoEngine *
+MODULE_ENTRY(script_engine_load) (const char *id)
+{
+ if (!strcmp (id, SCRIPT_ENGINE_NAME))
+ return hangul_engine_xft_new ();
+ else
+ return NULL;
+}
+
+void
+MODULE_ENTRY(script_engine_unload) (PangoEngine *engine)
+{
+}