? modules/hangul/diff
? modules/hangul/diff.temp
? modules/hangul/hangul-fc.c.new.2
? modules/hangul/hangul-fc.c.new.temp
? modules/hangul/hangul-fc.diff
? modules/hangul/hangul-fc.diff.cvs
? modules/hangul/hangul-fc.diff.cvs.2
? modules/hangul/hangul-utils.c
? modules/hangul/hangul-utils.h
? modules/hangul/hangul-xft.c.updated
? modules/hangul/ot.outline
? modules/hangul/tables-ext-jamos.i
? modules/hangul/tables-jamos2.i
Index: pango/pango-script-table.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-script-table.h,v
retrieving revision 1.1
diff -u -7 -p -r1.1 pango-script-table.h
--- pango/pango-script-table.h	3 Aug 2003 21:57:33 -0000	1.1
+++ pango/pango-script-table.h	27 Aug 2003 10:42:40 -0000
@@ -324,15 +324,16 @@ static const struct {
  { 0x2800,   256, PANGO_SCRIPT_BRAILLE },
  { 0x2e80,    26, PANGO_SCRIPT_HAN },
  { 0x2e9b,    89, PANGO_SCRIPT_HAN },
  { 0x2f00,   214, PANGO_SCRIPT_HAN },
  { 0x3005,     1, PANGO_SCRIPT_HAN },
  { 0x3007,     1, PANGO_SCRIPT_HAN },
  { 0x3021,     9, PANGO_SCRIPT_HAN },
- { 0x302a,     6, PANGO_SCRIPT_INHERITED },
+ { 0x302a,     4, PANGO_SCRIPT_INHERITED },
+ { 0x302e,     2, PANGO_SCRIPT_HANGUL },
  { 0x3038,     4, PANGO_SCRIPT_HAN },
  { 0x3041,    86, PANGO_SCRIPT_HIRAGANA },
  { 0x3099,     2, PANGO_SCRIPT_INHERITED },
  { 0x309d,     3, PANGO_SCRIPT_HIRAGANA },
  { 0x30a1,    90, PANGO_SCRIPT_KATAKANA },
  { 0x30fd,     3, PANGO_SCRIPT_KATAKANA },
  { 0x3105,    40, PANGO_SCRIPT_BOPOMOFO },
Index: modules/hangul/Makefile.am
===================================================================
RCS file: /cvs/gnome/pango/modules/hangul/Makefile.am,v
retrieving revision 1.28
diff -u -7 -p -r1.28 Makefile.am
--- modules/hangul/Makefile.am	3 Aug 2003 02:35:12 -0000	1.28
+++ modules/hangul/Makefile.am	27 Aug 2003 10:42:40 -0000
@@ -25,22 +25,26 @@ INCLUDES += $(FREETYPE_CFLAGS)
 if INCLUDE_HANGUL_FC
 noinst_LTLIBRARIES += libpango-hangul-fc.la
 else
 module_LTLIBRARIES += pango-hangul-fc.la
 endif
 endif
 
-fc_sources = hangul-fc.c hangul-defs.h
+fc_sources = hangul-utils.c hangul-utils.h hangul-fc.c hangul-defs.h
 
 pango_hangul_fc_la_LDFLAGS = -export-dynamic -avoid-version -module $(no_undefined)
 pango_hangul_fc_la_LIBADD = $(pangoft2libs)
 pango_hangul_fc_la_SOURCES = $(fc_sources)
 libpango_hangul_fc_la_SOURCES = $(fc_sources)
 libpango_hangul_fc_la_CFLAGS = -DPANGO_MODULE_PREFIX=_pango_hangul_fc
 
 
 EXTRA_DIST =			\
-	tables-jamos.i
+	tables-ksc5601.i	\
+	tables-johabfont.i	\
+	tables-jamos.i 		\
+	tables-jamos2.i 	\
+	tables-ext-jamos.i
 
 included-modules: $(noinst_LTLIBRARIES)
 
 .PHONY: included-modules
Index: modules/hangul/hangul-defs.h
===================================================================
RCS file: /cvs/gnome/pango/modules/hangul/hangul-defs.h,v
retrieving revision 1.4
diff -u -7 -p -r1.4 hangul-defs.h
--- modules/hangul/hangul-defs.h	3 Nov 2002 19:56:24 -0000	1.4
+++ modules/hangul/hangul-defs.h	27 Aug 2003 10:42:40 -0000
@@ -23,29 +23,26 @@
 /*
  * From 3.10 of the Unicode 2.0 Book; used for combining Jamos.
  */
 #define SBASE 0xAC00
 #define LBASE 0x1100
 #define VBASE 0x1161
 #define TBASE 0x11A7
+#define TSTART 0x11A8
 
 #define LEND 0x115F
 #define VEND 0x11A6
 #define TEND 0x11FF
 
 #define SCOUNT 11172
 #define LCOUNT 19
 #define VCOUNT 21
 #define TCOUNT 28
 #define NCOUNT (VCOUNT * TCOUNT)
 
-/*
- * Unicode 2.0 doesn't define the fill for trailing consonants, but
- * I'll use 0x11A7 as that purpose internally.
- */
 #define LFILL 0x115F
 #define VFILL 0x1160
 
 #define HTONE1 0x302E
 #define HTONE2 0x302F
 
 #define IS_L(wc) (wc >= LBASE && wc <= LEND)
Index: modules/hangul/hangul-fc.c
===================================================================
RCS file: /cvs/gnome/pango/modules/hangul/hangul-fc.c,v
retrieving revision 1.12
diff -u -7 -p -r1.12 hangul-fc.c
--- modules/hangul/hangul-fc.c	3 Aug 2003 21:57:28 -0000	1.12
+++ modules/hangul/hangul-fc.c	27 Aug 2003 10:42:41 -0000
@@ -23,15 +23,17 @@
 #include <string.h>
 
 #include "pango-engine.h"
 #include "pango-utils.h"
 #include "pangofc-font.h"
 
 #include "hangul-defs.h"
+#include "hangul-utils.h"
 #include "tables-jamos.i"
+#include "tables-ext-jamos.i"
 
 /* No extra fields needed */
 typedef PangoEngineShape      HangulEngineFc;
 typedef PangoEngineShapeClass HangulEngineFcClass ;
 
 #define SCRIPT_ENGINE_NAME "HangulScriptEngineFc"
 #define RENDER_TYPE PANGO_RENDER_TYPE_FC
@@ -48,14 +50,18 @@ static PangoEngineInfo script_engines[] 
     SCRIPT_ENGINE_NAME,
     PANGO_ENGINE_TYPE_SHAPE,
     RENDER_TYPE,
     hangul_ranges, G_N_ELEMENTS(hangul_ranges)
   }
 };
 
+typedef void (* RenderSyllableFunc) (PangoFont *font, gunichar *text, 
+                                     int length, PangoGlyphString *glyphs,
+                                     int *n_glyphs, int cluster_offset);
+
 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;
@@ -73,15 +79,15 @@ set_glyph (PangoFont *font, PangoGlyphSt
  *   to attach it to.
  *   2. Adjust x_offset so that it is drawn to the left of a cluster.
  *   3. Set the logical width to zero. 
  */
 
 static void
 set_glyph_tone (PangoFont *font, PangoGlyphString *glyphs, int i,
-		            int offset, PangoGlyph glyph)
+		int offset, PangoGlyph glyph)
 {
   PangoRectangle logical_rect, ink_rect;
   PangoRectangle logical_rect_cluster;
 
   glyphs->glyphs[i].glyph = glyph;
   glyphs->glyphs[i].geometry.y_offset = 0;
   glyphs->log_clusters[i] = offset;
@@ -150,15 +156,15 @@ render_tone (PangoFont *font, gunichar t
       index = find_char (font, tone == HTONE1 ? 0x00b7 : 0x003a);
       if (index)
         {
           set_glyph_tone (font, glyphs, *n_glyphs, cluster_offset, index);
         }
       else 
         set_glyph (font, glyphs, *n_glyphs, cluster_offset,
-		   get_unknown_glyph (font, tone));
+                  get_unknown_glyph (font, tone));
     }
   (*n_glyphs)++;
 }
 
 /* This is a fallback for when we get a tone mark not preceded
  * by a syllable.
  */
@@ -183,62 +189,102 @@ render_isolated_tone (PangoFont *font, g
   (*n_glyphs)++;
 
   /* And the tone mrak
    */
   render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
 }
 
-static void
-render_syllable (PangoFont *font, gunichar *text, int length,
-		 PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
+static int
+render_as_precomp_syllable (PangoFont 	     *font, 
+			    gunichar 	     *text, 
+			    int 	     *length,
+			    PangoGlyphString *glyphs,
+			    int 	     *n_glyphs, 
+			    int              cluster_offset,
+			    gboolean         spacing_jamo)
 {
-  int n_prev_glyphs = *n_glyphs;
-  int index;
-  gunichar wc, tone;
-  int i, j, composed;
+  int composed;
 
-  if (IS_M (text[length - 1]))
-    {
-      tone = text[length - 1];
-      length--;
-    }
-  else
-    tone = 0;
-
-  if (length >= 3 && IS_L_S(text[0]) && IS_V_S(text[1]) && IS_T_S(text[2]))
+  if ((*length == 3 || (spacing_jamo && *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]))
+  else if ((*length == 2 || (spacing_jamo && *length > 2)) &&
+	   IS_L_S(text[0])  && IS_V_S(text[1]))
     composed = 2;
   else
     composed = 0;
 
   if (composed)
     {
+      gunichar wc;
+      int index;
       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 (font, wc);
       pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
       if (!index)
 	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
 		   get_unknown_glyph (font, wc));
       else
 	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
       (*n_glyphs)++;
-      text += composed;
-      length -= composed;
+      *length -= composed;
+    }
+  return composed;
+
+}
+
+static void
+render_syllable_base (PangoFont	       *font, 
+		      gunichar	       *text, 
+		      int	       length,
+		      PangoGlyphString *glyphs, 
+		      int	       *n_glyphs, 
+		      int	       cluster_offset,
+		      gboolean         spacing_jamo)
+{
+  int index;
+  gunichar wc,*text0;
+  int i, j;
+  gunichar tone;
+
+  if (IS_M (text[length - 1]))
+    {
+      tone = text[length - 1];
+      length--;
     }
+  else
+    tone = 0;
+
+  /* XXX : need to check if we have an isolated precomp. syllable and
+   * expedite things to avoid decomposition/recomposition in that case.
+   * At the moment, we don't have to because hangul_engine_shape()
+   * decomposes a precomposed syllble into a jamo seq.
+   */
+
+  text = _normalize_jamo (text, &length);
+  text0 = text;  /* preserve the addrs. for g_free */
+
+  text += render_as_precomp_syllable (font, text, &length, glyphs, n_glyphs,
+          cluster_offset, spacing_jamo);
+
 
   /* Render the remaining text as uncomposed forms as a fallback.  */
   for (i = 0; i < length; i++)
     {
       int jindex;
 
-      if (text[i] == LFILL || text[i] == VFILL)
+      /* skip VFILL if  VFILL is not the only char. in a given syllable.
+       * There's a strange problem with pango-break(). For an unknown reason,
+       * (the code in break.c has no problem handling Jamo breaks.)
+       * sometimes L+Vf is broken into L and Vf and shaping engine gets them
+       * one by one.*/
+      if ( text[i] == VFILL && length > 1)
 	continue;
 
       index = find_char (font, text[i]);
       if (index)
 	{
 	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
 	  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
@@ -258,28 +304,503 @@ render_syllable (PangoFont *font, gunich
 	    set_glyph (font, glyphs, *n_glyphs, cluster_offset,
 		       get_unknown_glyph (font, index));
 	  else
 	    set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
 	  (*n_glyphs)++;
 	}
     }
-  if (n_prev_glyphs == *n_glyphs)
+
+  if (tone)
+    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+
+  g_free (text0);
+}  
+
+static void
+render_syllable_with_spacing_jamo (PangoFont	      *font, 
+			     	   gunichar	      *text, 
+			     	   int	      	      length,
+			     	   PangoGlyphString   *glyphs, 
+			     	   int	              *n_glyphs, 
+				   int	              cluster_offset)
+{
+  render_syllable_base (font, text, length, glyphs, n_glyphs, cluster_offset, TRUE);
+}
+
+static void
+render_syllable_with_combining_jamo (PangoFont	      *font, 
+			     	     gunichar	      *text, 
+			     	     int	      length,
+			     	     PangoGlyphString *glyphs, 
+			     	     int	      *n_glyphs, 
+				     int	      cluster_offset)
+{
+  render_syllable_base (font, text, length, glyphs, n_glyphs, cluster_offset, FALSE);
+}
+
+
+/*  og_transform() :
+ *  1. shift jamo sequences to three disjoint code blocks in
+ *     PUA (0xF000 for LC, 0xF1000 for VO, 0xF200 for TC).
+ *  2. replace a jamo sequence with a precomposed OG-extended 
+ *     cluster jamo code point in PUA
+ *  3. this replacement is done 'in place' 
+ */
+
+static void 
+og_transform (gunichar *text, int *length)
+{
+  int i;
+  /* translate jamo code points to temporary code points in PUA */
+  for (i = 0; i < *length; i++)
+    {
+      if (IS_L(text[i]))
+	text[i] += LC_OFFSET;
+      else if (IS_V(text[i]))
+	text[i] += VO_OFFSET;
+      else if (IS_T(text[i]))
+	text[i] += TC_OFFSET;
+    }
+
+  /* LV or LVT : no need to search for and replace jamo sequences */
+  if ((*length == 2 && OG_IS_L(text[0]) && OG_IS_V(text[1])) || 
+      (*length == 3 && OG_IS_L(text[0]) && OG_IS_V(text[1]) && OG_IS_T(text[2])))
+    return;
+
+  /* replace a sequence of Jamos with the corresponding precomposed 
+   * Jamo cluster in PUA */
+  _jamo_srch_repl (__ext_lc_clusters_group1,
+		   G_N_ELEMENTS (__ext_lc_clusters_group1), text, length, 3); 
+  _jamo_srch_repl (__ext_lc_clusters_group2,
+		   G_N_ELEMENTS (__ext_lc_clusters_group2), text, length, 2); 
+  _jamo_srch_repl (__ext_vo_clusters_group1,
+		   G_N_ELEMENTS (__ext_vo_clusters_group1), text, length, 3); 
+  _jamo_srch_repl (__ext_vo_clusters_group2, 
+		   G_N_ELEMENTS (__ext_vo_clusters_group2), text, length, 2); 
+  _jamo_srch_repl (__ext_tc_clusters_group1, 
+		   G_N_ELEMENTS (__ext_tc_clusters_group1), text, length, 3); 
+  _jamo_srch_repl (__ext_tc_clusters_group2, 
+		   G_N_ELEMENTS (__ext_tc_clusters_group2), text, length, 2); 
+
+}
+
+static int (*ojns_comp) (const void* , const void*) = _jamo_norm_map_comp; 
+
+static void
+render_syllable_with_ogulim (PangoFont	      *font, 
+			     gunichar	      *text, 
+			     int	      length,
+			     PangoGlyphString *glyphs, 
+			     int	      *n_glyphs, 
+			     int	      cluster_offset)
+{
+  int index;
+  gunichar wc;
+  int i = 0;
+  gunichar tone;
+
+  if (IS_M (text[length - 1]))
+    {
+      tone = text[length - 1];
+      length--;
+    }
+  else
+    tone = 0;
+
+
+  text = _normalize_jamo (text, &length);
+  og_transform (text, &length);
+
+  if (length != 2 && length != 3)
+    goto fallback; 
+
+  if (! OG_IS_L (text[0]) || ! OG_IS_V (text[1]) || 
+      (length == 3 && ! OG_IS_T (text[2])))
+    goto fallback;
+
+
+  /*  Now that text[0..2] are identified as L,V, and T, it's safe to 
+   *  shift them back to U+1100 block although their ranges overlap
+   *  each other.
+   */
+
+  text[0] -= LC_OFFSET;
+  text[1] -= VO_OFFSET;
+  if (length==3)
+    text[2] -= TC_OFFSET;
+
+  /* 
+   * Ogulim font doesn't have glyphs for Vfill and Lfill. Vfill can
+   * be just skipped, but Lfill can't. As a work around, draw
+   * two 'SPACE's for Lfill
+   */
+  if (length != 3)   /* L V syllable */
+    {
+      text[0] = (text[0] == LFILL) ?  0x20 : 
+	        __ogulim_lc_gidx[text[0] - LBASE] * 6 + 
+                __ogulim_v2l_map[text[1] - VFILL] + OG_LBASE;
+      if (text[1] != VFILL)
+        text[1] = __ogulim_vo_gidx[text[1] - VFILL] * 2 + OG_VBASE;
+      else           /* skip VFILL */
+	--length;
+    }
+  else             /* L V T syllable */
+    {
+      text[0] = (text[0] == LFILL) ?  0x20 : 
+                __ogulim_lc_gidx[text[0] - LBASE] * 6 + 
+                __ogulim_v2lt_map[text[1] - VFILL] + OG_LBASE;
+      text[2] = __ogulim_tc_gidx[text[2] - TSTART] * 4 + 
+                __ogulim_v2t_map[text[1] - VFILL] + OG_TBASE; 
+      if (text[1] != VFILL)  
+        text[1] = __ogulim_vo_gidx[text[1] - VFILL] * 2 + OG_VBASE + 1; 
+      else           /* skip VFILL */
+        {
+          --length;
+	  text[1] = text[2]; 
+	}
+    }
+  /* 
+   * draw the first of two 0x20's in place of LFill. The other
+   * will be drawn inside for-loop 
+   */
+  if (text[0] == 0x20)  
+    {
+      index = find_char (font, text[i]);
+      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+      set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+      (*n_glyphs)++;
+    }
+
+  for (i = 0; i < length; i++)
+    {
+      index = find_char (font, text[i]);
+      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+      if (!index)
+	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+		   get_unknown_glyph (font, index));
+      else
+	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+      (*n_glyphs)++;
+    }
+
+  if (tone)
+    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+
+  g_free (text);
+
+  return; 
+
+
+  /* If jamo sequence is not convertible to a jamo cluster,
+   * just enumerate stand-alone jamos. Prepend V and T with  Lf.
+   *
+   * XXX: It might be better to search for a sub-sequence (not just at the
+   * beginning of a cluster but also in the middle or at the end.) 
+   * that can be rendered as precomposed and render it as such and enumerate
+   * jamos in the rest. This approach is useful when a simple Xkb-based input
+   * is used. The same is true in render_...._with_ngulim().
+   */
+
+fallback: 
+  for (i = 0; i < length; i++)
+    {
+      gunichar wc2=0;
+      /* skip Lfill and Vfill if they're not the sole char. in a cluster */
+      if ( length > 1 && 
+	   (text[i] - LC_OFFSET == LFILL || text[i] - VO_OFFSET == VFILL))
+	continue;
+      else if (OG_IS_L (text[i]))
+         wc = __ogulim_lc_gidx[text[i] - LC_OFFSET - LBASE] * 6 + OG_LBASE;
+      else 
+        {
+	  /* insert Lfill glyph to advance cursor pos. for V and T */
+	  wc = OG_LBASE;
+	  /* don't have to draw Vfill. Drawing Lfill is sufficient. */ 
+	  if (text[i] - VO_OFFSET != VFILL) 
+	    wc2 = OG_IS_V (text[i]) ? 
+	        __ogulim_vo_gidx[text[i] - VO_OFFSET - VFILL] * 2 + OG_VBASE:
+	        __ogulim_tc_gidx[text[i] - TC_OFFSET - TSTART] * 4 + OG_TBASE + 3;
+        }
+
+        index = find_char (font, wc); 
+        pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+        set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+        (*n_glyphs)++;
+	if (wc2) {
+          index =  find_char (font, wc2); 
+          pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+          set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+          (*n_glyphs)++;
+        }
+    }
+
+  if (tone)
+    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+
+  g_free (text);
+}
+
+static void
+render_syllable_with_ngulim (PangoFont	      *font, 
+			     gunichar	      *text, 
+			     int	      length,
+			     PangoGlyphString *glyphs, 
+			     int	      *n_glyphs, 
+			     int	      cluster_offset)
+{
+  int index;
+  gunichar wc;
+  int i;
+  gunichar *text0 = NULL;
+  OgJamosToNgSyllable key,*match;
+  gunichar tone = 0;
+
+#if 0
+  gunichar buf_static[9];
+  guint buf_size = G_N_ELEMENTS (buf_static);
+  gunichar *text1 = buf_static;
+  int length1;
+#endif
+
+  if (IS_M (text[length - 1]))
+    {
+      tone = text[length - 1];
+      length--;
+    }
+
+  /* XXX : need to check if we have an isolated precomp. syllable and
+   * expedite things to avoid decomposition/recomposition in that case.
+   * At the moment, we don't have to because hangul_engine_shape()
+   * decomposes a precomposed syllble into a jamo seq.
+   */
+
+  text = _normalize_jamo (text, &length);
+  text0 = text;
+
+  if (length == 1) 
+    {
+#if 1
+      text[0] += LC_OFFSET;  /* fallback assumes OG position */
+#else
+      text1[0] = text[0];
+      length1 = 1;
+#endif
+      goto fallback;
+    }
+
+
+  text += render_as_precomp_syllable (font, text, &length, glyphs, n_glyphs,
+          cluster_offset, FALSE);
+
+  if (! length)
+    {
+      if (tone)
+        render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+      g_free (text0);
+      return;
+    }
+
+#if 0
+  if (length > buf_siz)
+    text1 = g_new (gunichar, length);
+  memcpy (text1, text, length * sizeof (gunichar));
+  length1 = length;
+#endif
+
+  og_transform (text, &length);
+
+  if (length != 2 && length != 3)
+    goto fallback; 
+
+  if (! OG_IS_L (text[0]) || ! OG_IS_V (text[1]) || 
+      (length == 3 && ! OG_IS_T (text[2])))
+    goto fallback;
+
+  /* Look-up the precomposed syllable table */
+
+  key.seq[0] = text[0];
+  key.seq[1] = text[1];
+  key.seq[2] = length == 3 ? text[2] : 0; 
+  match = bsearch (&key, __og_jamos_to_ng_syllable, 
+           	   G_N_ELEMENTS (__og_jamos_to_ng_syllable), 
+		   sizeof (key), ojns_comp);
+
+  if (match)
     {
-      index = find_char (font, 0x3164);
+      index = find_char (font, match->liga);
       pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
       if (!index)
 	set_glyph (font, glyphs, *n_glyphs, cluster_offset,
 		   get_unknown_glyph (font, index));
       else
 	set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
-      glyphs->log_clusters[*n_glyphs] = cluster_offset;
       (*n_glyphs)++;
     }
+
+  /* Use Jamo glyphs for simple over-striking */
+  else 
+    {
+      text[0] = __ogulim_lc_gidx[text[0] - LBASE - LC_OFFSET] + NG_LBASE;
+      text[1] = __ogulim_vo_gidx[text[1] - VFILL - VO_OFFSET] + NG_VBASE;
+
+  /* Unless a character is explicitly specified in fonts.conf file 
+   * as beling allowed to have a blank glyph, fontconfig regards it as 
+   * invalid and tries to come up with  sth. else. LFILL will be included 
+   * in fonts.conf distribution as a blank characters
+   * wheras we cannot expect ordinary users to add font-specific PUA 
+   * codepoints to the blank character list. Therefore, use LFILL in place 
+   * of Filler in PUA. NG_VBASE (VFill) is skipped below because it's 
+   * not only blank but also has zero-width so that its absence makes 
+   * no difference in  rendering. 
+   */
+      if (text[0] == NG_LBASE )
+        text[0] = LFILL; 
+
+      if (length == 3)
+        text[2] = __ogulim_tc_gidx[text[2] - TSTART - TC_OFFSET] + NG_TBASE;
+
+      for (i = 0; i < length; i++)
+        {
+          if (text[i] == NG_VBASE)  /* skip VFILL in PUA */
+            continue;
+          index = find_char (font, text[i]);
+          pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+          if (!index)
+            set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+            get_unknown_glyph (font, index));
+          else
+    	    set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+          (*n_glyphs)++;
+        }
+    }
+
   if (tone)
     render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+  g_free (text0);
+#if 0
+  if (length1 > buf_size)
+    g_free (text1);
+#endif
+
+  return; 
+
+
+  /* If jamo sequence is not convertible to a jamo cluster,
+   * just enumerate stand-alone jamos. 
+   * XXX : Would it be better to reverse the og_transform (the content of text[]
+   * can be stowed into text1[]  before OG_Transform and be retrieved here.)
+   * and render stand-alone Jamos with glyphs at U+1100 block? 
+   */ 
+
+fallback: 
+#if 1
+  for (i = 0; i < length; i++)
+    {
+      gunichar wc2=0;
+
+      /* skip Lfill and Vfill if they're not the sole char. in a cluster */
+      if (length > 1 && 
+	  (text[i] - LC_OFFSET == LFILL || text[i] - VO_OFFSET == VFILL))
+	continue;
+      else if (OG_IS_L (text[i]))
+        wc = __ogulim_lc_gidx[text[i] - LC_OFFSET - LBASE]  + NG_LBASE;
+      else 
+        {
+	  /* insert Lfill glyph in non-PUA to advance cursor pos. for V and T */
+	  wc = LFILL;  
+	  if (text[i] != VO_TMPPOS) /* don't have to render VFill */
+	    wc2 = OG_IS_V (text[i]) ? 
+	        __ogulim_vo_gidx[text[i] - VO_OFFSET - VFILL]  + NG_VBASE :
+	        __ogulim_tc_gidx[text[i] - TC_OFFSET - TSTART]  + NG_TBASE;
+        }
+
+
+      /* replace NG_LBASE(Lf in Ngulim font) with LFILL(U+115F)
+       * because fontconfig hates an unlisted blank glyph. 
+       */
+      wc = (wc == NG_LBASE ? LFILL : wc); 
+
+      index = find_char (font, wc); 
+      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+      if (!index)
+        set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+           get_unknown_glyph (font, index));
+      else
+        set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+      (*n_glyphs)++;
+
+      if (wc2) 
+        {
+          index = find_char (font, wc2); 
+          pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+          if (!index)
+  	    set_glyph (font, glyphs, *n_glyphs, cluster_offset,
+	               get_unknown_glyph (font, index));
+          else
+  	    set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+          (*n_glyphs)++;
+        }
+    }
+#else 
+  for (i = 0; i < length1; i++)
+    {
+      index =  find_char (font, text1[i]);
+      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+      set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+      (*n_glyphs)++;
+    }
+  if (length1 > buf_size)
+    g_free (text1);
+#endif
+
+  if (tone)
+    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+
+  g_free (text0);
+
+}
+
+static
+void set_render_func (PangoFont          *font, 
+		      RenderSyllableFunc *render_func)
+{
+  guint gindex;
+  PangoFcFont *fc_font;
+
+  g_return_if_fail(font != NULL && render_func != NULL);
+
+  fc_font = PANGO_FC_FONT (font);
+  FT_Face    face = pango_fc_font_lock_face (fc_font);
+  g_assert (face != NULL);
+
+
+  if ( ! strcmp (face->family_name,"Gulim Old Hangul Jamo") ||
+       ! strcmp (face->family_name,"Batng Old Hangul Jamo") ||
+       ! strcmp (face->family_name,"Gungseo Old Hangul Jamo")|| 
+       ! strcmp (face->family_name,"Dotum Old Hangul Jamo"))
+    *render_func = render_syllable_with_ogulim;
+  else if ( ! strcmp ( face->family_name,"New Gulim") ||
+	    ! strcmp (face->family_name,"New Batng")  ||
+	    ! strcmp (face->family_name,"New Gungseo") || 
+	    ! strcmp (face->family_name,"New Dotum"))
+    *render_func = render_syllable_with_ngulim;
+  /* if VBASE (U+1161 : the first vowel) is non-spacing/zero-width,
+   * assume that a font has combining Jamo glyphs.
+   */
+  else if ((gindex=find_char (font, VBASE)))
+    {
+      PangoRectangle l_rect;
+      pango_font_get_glyph_extents (font, (PangoGlyph) gindex, NULL, &l_rect);
+      if ( ! l_rect.width ) 
+	*render_func = render_syllable_with_combining_jamo;
+      else 
+	*render_func = render_syllable_with_spacing_jamo;
+    }
+  else
+    *render_func = render_syllable_with_spacing_jamo;
 }
 
 static void 
 hangul_engine_shape (PangoEngineShape *engine,
 		     PangoFont        *font,
 		     const char       *text,
 		     gint              length,
@@ -291,43 +812,45 @@ hangul_engine_shape (PangoEngineShape *e
   const char *p, *start;
 
   gunichar jamos_static[8];
   guint max_jamos = G_N_ELEMENTS (jamos_static);
   gunichar *jamos = jamos_static;
   int n_jamos;
 
+  RenderSyllableFunc render_func = NULL;
+
   n_chars = g_utf8_strlen (text, length);
   n_glyphs = 0;
   start = p = text;
   n_jamos = 0;
 
+
+  set_render_func (font,&render_func);
+
   for (i = 0; i < n_chars; i++)
     {
+      gunichar prev = jamos[n_jamos - 1];
       gunichar wc;
 
       wc = g_utf8_get_char (p);
 
       /* Check syllable boundaries. */
-      if (n_jamos)
+      if (n_jamos &&
+	  ((!IS_L (prev) && IS_S (wc)) ||
+	   (IS_T (prev) && IS_L (wc)) ||
+	   (IS_V (prev) && IS_L (wc)) ||
+	   (IS_T (prev) && IS_V (wc)) ||
+	   IS_M(prev)))
 	{
-	  gunichar prev = jamos[n_jamos - 1];
-	  if ((!IS_L (prev) && IS_S (wc)) ||
-	      (IS_T (prev) && IS_L (wc)) ||
-	      (IS_V (prev) && IS_L (wc)) ||
-	      (IS_T (prev) && IS_V (wc)) ||
-	      IS_M(prev))
-	    {
-	      /* Draw a syllable. */
-	      render_syllable (font, jamos, n_jamos, glyphs,
-			       &n_glyphs, start - text);
-	      n_jamos = 0;
-	      start = p;
-	    }
+	  /* Draw a syllable. */
+	  render_func (font, jamos, n_jamos, glyphs, &n_glyphs, start - text);
+	  n_jamos = 0;
+	  start = p;
 	}
-	  
+
       if (n_jamos == max_jamos)
 	{
 	  max_jamos += 3;	/* at most 3 for each syllable code (L+V+T) */
 	  if (jamos == jamos_static)
 	    {
 	      jamos = g_new (gunichar, max_jamos);
 	      memcpy (jamos, jamos_static, n_jamos*sizeof(gunichar));
@@ -350,20 +873,19 @@ hangul_engine_shape (PangoEngineShape *e
 	  start = g_utf8_next_char (p);
 	}
       else
 	jamos[n_jamos++] = wc;
       p = g_utf8_next_char (p);
     }
 
-  if (n_jamos != 0)
-    render_syllable (font, jamos, n_jamos, glyphs, &n_glyphs,
-		     start - text);
+  if (n_jamos != 0) 
+    render_func (font, jamos, n_jamos, glyphs, &n_glyphs, start - text);
 
   if (jamos != jamos_static)
-    g_free(jamos);
+    g_free (jamos);
 }
 
 static void
 hangul_engine_fc_class_init (PangoEngineShapeClass *class)
 {
   class->script_shape = hangul_engine_shape;
 }
@@ -380,15 +902,15 @@ PANGO_MODULE_ENTRY(init) (GTypeModule *m
 void 
 PANGO_MODULE_ENTRY(exit) (void)
 {
 }
 
 void 
 PANGO_MODULE_ENTRY(list) (PangoEngineInfo **engines,
-			  int              *n_engines)
+	  		  int              *n_engines)
 {
   *engines = script_engines;
   *n_engines = G_N_ELEMENTS (script_engines);
 }
 
 PangoEngine *
 PANGO_MODULE_ENTRY(create) (const char *id)
Index: modules/hangul/hangul-xft.c
===================================================================
RCS file: /cvs/gnome/pango/modules/hangul/Attic/hangul-xft.c,v
retrieving revision 1.8
diff -u -7 -p -r1.8 hangul-xft.c
--- modules/hangul/hangul-xft.c	17 Dec 2002 02:07:37 -0000	1.8
+++ modules/hangul/hangul-xft.c	27 Aug 2003 10:42:42 -0000
@@ -23,15 +23,17 @@
 #include <string.h>
 
 #include "pangoxft.h"
 #include "pango-engine.h"
 #include "pango-utils.h"
 
 #include "hangul-defs.h"
+#include "hangul-utils.h"
 #include "tables-jamos.i"
+#include "tables-ext-jamos.i"
 
 #define SCRIPT_ENGINE_NAME "HangulScriptEngineXft"
 
 static PangoEngineRange hangul_ranges[] = {
   /* Language characters */
   { 0x1100, 0x11ff, "*" }, /* Hangul Jamo */
   { 0x302e, 0x302f, "*" }, /* Hangul Tone Marks */
@@ -43,14 +45,18 @@ static PangoEngineInfo script_engines[] 
     SCRIPT_ENGINE_NAME,
     PANGO_ENGINE_TYPE_SHAPE,
     PANGO_RENDER_TYPE_XFT,
     hangul_ranges, G_N_ELEMENTS(hangul_ranges)
   }
 };
 
+typedef void (* RenderSyllableFunc) (PangoFont *font, gunichar *text, 
+                                     int length, PangoGlyphString *glyphs,
+                                     int *n_glyphs, int cluster_offset);
+
 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;
@@ -68,15 +74,15 @@ set_glyph (PangoFont *font, PangoGlyphSt
  *   to attach it to.
  *   2. Adjust x_offset so that it is drawn to the left of a cluster.
  *   3. Set the logical width to zero. 
  */
 
 static void
 set_glyph_tone (PangoFont *font, PangoGlyphString *glyphs, int i,
-		            int offset, PangoGlyph glyph)
+		int offset, PangoGlyph glyph)
 {
   PangoRectangle logical_rect, ink_rect;
   PangoRectangle logical_rect_cluster;
 
   glyphs->glyphs[i].glyph = glyph;
   glyphs->glyphs[i].geometry.y_offset = 0;
   glyphs->log_clusters[i] = offset;
@@ -117,18 +123,16 @@ set_glyph_tone (PangoFont *font, PangoGl
           glyphs->glyphs[j + 1].geometry.x_offset += ink_rect.width;
 	}
     }
 
   glyphs->glyphs[i].geometry.width = 0;
 }
 
-
 #define find_char pango_xft_font_get_glyph
 
-
 static void
 render_tone (PangoFont *font, gunichar tone, PangoGlyphString *glyphs,
              int *n_glyphs, int cluster_offset)
 {
   int index;
 
   index = find_char (font, tone);
@@ -176,62 +180,102 @@ render_isolated_tone (PangoFont *font, g
   (*n_glyphs)++;
 
   /* And the tone mrak
    */
   render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
 }
 
-static void
-render_syllable (PangoFont *font, gunichar *text, int length,
-		 PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset)
+static int
+render_as_precomp_syllable (PangoFont 	     *font, 
+			    gunichar 	     *text, 
+			    int 	     *length,
+			    PangoGlyphString *glyphs,
+			    int 	     *n_glyphs, 
+			    int              cluster_offset,
+			    gboolean         spacing_jamo)
 {
-  int n_prev_glyphs = *n_glyphs;
-  int index;
-  gunichar wc, tone;
-  int i, j, composed;
-
-  if (IS_M (text[length - 1]))
-    {
-      tone = text[length - 1];
-      length--;
-    }
-  else
-    tone = 0;
+  int composed;
 
-  if (length >= 3 && IS_L_S(text[0]) && IS_V_S(text[1]) && IS_T_S(text[2]))
+  if ((*length == 3 || (spacing_jamo && *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]))
+  else if ((*length == 2 || (spacing_jamo && *length > 2)) &&
+	   IS_L_S(text[0])  && IS_V_S(text[1]))
     composed = 2;
   else
     composed = 0;
 
   if (composed)
     {
+      gunichar wc;
+      int index;
       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 (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;
+      *length -= composed;
     }
+  return composed;
+
+}
+
+static void
+render_syllable_base (PangoFont	       *font, 
+		      gunichar	       *text, 
+		      int	       length,
+		      PangoGlyphString *glyphs, 
+		      int	       *n_glyphs, 
+		      int	       cluster_offset,
+		      gboolean         spacing_jamo)
+{
+  int index;
+  gunichar wc,*text0;
+  int i, j;
+  gunichar tone;
+
+  if (IS_M (text[length - 1]))
+    {
+      tone = text[length - 1];
+      length--;
+    }
+  else
+    tone = 0;
+
+  /* XXX : need to check if we have an isolated precomp. syllable and
+   * expedite things to avoid decomposition/recomposition in that case.
+   * At the moment, we don't have to because hangul_engine_shape()
+   * decomposes a precomposed syllble into a jamo seq.
+   */
+
+  text = _normalize_jamo (text, &length);
+  text0 = text;  /* preserve the addrs. for g_free */
+
+  text += render_as_precomp_syllable (font, text, &length, glyphs, n_glyphs,
+          cluster_offset, spacing_jamo);
+
 
   /* Render the remaining text as uncomposed forms as a fallback.  */
   for (i = 0; i < length; i++)
     {
       int jindex;
 
-      if (text[i] == LFILL || text[i] == VFILL)
+      /* skip VFILL if  VFILL is not the only char. in a given syllable.
+       * There's a strange problem with pango-break(). For an unknown reason,
+       * (the code in break.c has no problem handling Jamo breaks.)
+       * sometimes L+Vf is broken into L and Vf and shaping engine gets them
+       * one by one.*/
+      if ( text[i] == VFILL && length > 1)
 	continue;
 
       index = find_char (font, text[i]);
       if (index)
 	{
 	  pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
 	  set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
@@ -251,28 +295,496 @@ render_syllable (PangoFont *font, gunich
 	    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)++;
 	}
     }
-  if (n_prev_glyphs == *n_glyphs)
+
+  if (tone)
+    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+
+  g_free (text0);
+}  
+
+static void
+render_syllable_with_spacing_jamo (PangoFont	      *font, 
+			     	   gunichar	      *text, 
+			     	   int	      	      length,
+			     	   PangoGlyphString   *glyphs, 
+			     	   int	              *n_glyphs, 
+				   int	              cluster_offset)
+{
+  render_syllable_base (font, text, length, glyphs, n_glyphs, cluster_offset, TRUE);
+}
+
+static void
+render_syllable_with_combining_jamo (PangoFont	      *font, 
+			     	     gunichar	      *text, 
+			     	     int	      length,
+			     	     PangoGlyphString *glyphs, 
+			     	     int	      *n_glyphs, 
+				     int	      cluster_offset)
+{
+  render_syllable_base (font, text, length, glyphs, n_glyphs, cluster_offset, FALSE);
+}
+
+
+/*  og_transform() :
+ *  1. shift jamo sequences to three disjoint code blocks in
+ *     PUA (0xF000 for LC, 0xF1000 for VO, 0xF200 for TC).
+ *  2. replace a jamo sequence with a precomposed OG-extended 
+ *     cluster jamo code point in PUA
+ *  3. this replacement is done 'in place' 
+ */
+
+static void 
+og_transform (gunichar *text, int *length)
+{
+  int i;
+  /* translate jamo code points to temporary code points in PUA */
+  for (i = 0; i < *length; i++)
+    {
+      if (IS_L(text[i]))
+	text[i] += LC_OFFSET;
+      else if (IS_V(text[i]))
+	text[i] += VO_OFFSET;
+      else if (IS_T(text[i]))
+	text[i] += TC_OFFSET;
+    }
+
+  /* LV or LVT : no need to search for and replace jamo sequences */
+  if ((*length == 2 && OG_IS_L(text[0]) && OG_IS_V(text[1])) || 
+      (*length == 3 && OG_IS_L(text[0]) && OG_IS_V(text[1]) && OG_IS_T(text[2])))
+    return;
+
+  /* replace a sequence of Jamos with the corresponding precomposed 
+   * Jamo cluster in PUA */
+  _jamo_srch_repl (__ext_lc_clusters_group1,
+		   G_N_ELEMENTS (__ext_lc_clusters_group1), text, length, 3); 
+  _jamo_srch_repl (__ext_lc_clusters_group2,
+		   G_N_ELEMENTS (__ext_lc_clusters_group2), text, length, 2); 
+  _jamo_srch_repl (__ext_vo_clusters_group1,
+		   G_N_ELEMENTS (__ext_vo_clusters_group1), text, length, 3); 
+  _jamo_srch_repl (__ext_vo_clusters_group2, 
+		   G_N_ELEMENTS (__ext_vo_clusters_group2), text, length, 2); 
+  _jamo_srch_repl (__ext_tc_clusters_group1, 
+		   G_N_ELEMENTS (__ext_tc_clusters_group1), text, length, 3); 
+  _jamo_srch_repl (__ext_tc_clusters_group2, 
+		   G_N_ELEMENTS (__ext_tc_clusters_group2), text, length, 2); 
+
+}
+
+static int (*ojns_comp) (const void* , const void*) = _jamo_norm_map_comp; 
+
+static void
+render_syllable_with_ogulim (PangoFont	      *font, 
+			     gunichar	      *text, 
+			     int	      length,
+			     PangoGlyphString *glyphs, 
+			     int	      *n_glyphs, 
+			     int	      cluster_offset)
+{
+  int index;
+  gunichar wc;
+  int i = 0;
+  gunichar tone;
+
+  if (IS_M (text[length - 1]))
+    {
+      tone = text[length - 1];
+      length--;
+    }
+  else
+    tone = 0;
+
+
+  text = _normalize_jamo (text, &length);
+  og_transform (text, &length);
+
+  if (length != 2 && length != 3)
+    goto fallback; 
+
+  if (! OG_IS_L (text[0]) || ! OG_IS_V (text[1]) || 
+      (length == 3 && ! OG_IS_T (text[2])))
+    goto fallback;
+
+
+  /*  Now that text[0..2] are identified as L,V, and T, it's safe to 
+   *  shift them back to U+1100 block although their ranges overlap
+   *  each other.
+   */
+
+  text[0] -= LC_OFFSET;
+  text[1] -= VO_OFFSET;
+  if (length==3)
+    text[2] -= TC_OFFSET;
+
+  /* 
+   * Ogulim font doesn't have glyphs for Vfill and Lfill. Vfill can
+   * be just skipped, but Lfill can't. As a work around, draw
+   * two 'SPACE's for Lfill
+   */
+  if (length != 3)   /* L V syllable */
+    {
+      text[0] = (text[0] == LFILL) ?  0x20 : 
+	        __ogulim_lc_gidx[text[0] - LBASE] * 6 + 
+                __ogulim_v2l_map[text[1] - VFILL] + OG_LBASE;
+      if (text[1] != VFILL)
+        text[1] = __ogulim_vo_gidx[text[1] - VFILL] * 2 + OG_VBASE;
+      else           /* skip VFILL */
+	--length;
+    }
+  else             /* L V T syllable */
+    {
+      text[0] = (text[0] == LFILL) ?  0x20 : 
+                __ogulim_lc_gidx[text[0] - LBASE] * 6 + 
+                __ogulim_v2lt_map[text[1] - VFILL] + OG_LBASE;
+      text[2] = __ogulim_tc_gidx[text[2] - TSTART] * 4 + 
+                __ogulim_v2t_map[text[1] - VFILL] + OG_TBASE; 
+      if (text[1] != VFILL)  
+        text[1] = __ogulim_vo_gidx[text[1] - VFILL] * 2 + OG_VBASE + 1; 
+      else           /* skip VFILL */
+        {
+          --length;
+	  text[1] = text[2]; 
+	}
+    }
+  /* 
+   * draw the first of two 0x20's in place of LFill. The other
+   * will be drawn inside for-loop 
+   */
+  if (text[0] == 0x20)  
+    {
+      index = find_char (font, text[i]);
+      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+      set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+      (*n_glyphs)++;
+    }
+
+  for (i = 0; i < length; i++)
+    {
+      index = find_char (font, text[i]);
+      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)++;
+    }
+
+  if (tone)
+    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+
+  g_free (text);
+
+  return; 
+
+
+  /* If jamo sequence is not convertible to a jamo cluster,
+   * just enumerate stand-alone jamos. Prepend V and T with  Lf.
+   *
+   * XXX: It might be better to search for a sub-sequence (not just at the
+   * beginning of a cluster but also in the middle or at the end.) 
+   * that can be rendered as precomposed and render it as such and enumerate
+   * jamos in the rest. This approach is useful when a simple Xkb-based input
+   * is used. The same is true in render_...._with_ngulim().
+   */
+
+fallback: 
+  for (i = 0; i < length; i++)
+    {
+      gunichar wc2=0;
+      /* skip Lfill and Vfill if they're not the sole char. in a cluster */
+      if ( length > 1 && 
+	   (text[i] - LC_OFFSET == LFILL || text[i] - VO_OFFSET == VFILL))
+	continue;
+      else if (OG_IS_L (text[i]))
+         wc = __ogulim_lc_gidx[text[i] - LC_OFFSET - LBASE] * 6 + OG_LBASE;
+      else 
+        {
+	  /* insert Lfill glyph to advance cursor pos. for V and T */
+	  wc = OG_LBASE;
+	  /* don't have to draw Vfill. Drawing Lfill is sufficient. */ 
+	  if (text[i] - VO_OFFSET != VFILL) 
+	    wc2 = OG_IS_V (text[i]) ? 
+	        __ogulim_vo_gidx[text[i] - VO_OFFSET - VFILL] * 2 + OG_VBASE:
+	        __ogulim_tc_gidx[text[i] - TC_OFFSET - TSTART] * 4 + OG_TBASE + 3;
+        }
+
+        index = find_char (font, wc); 
+        pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+        set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+        (*n_glyphs)++;
+	if (wc2) {
+          index =  find_char (font, wc2); 
+          pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+          set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+          (*n_glyphs)++;
+        }
+    }
+
+  if (tone)
+    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+
+  g_free (text);
+}
+
+static void
+render_syllable_with_ngulim (PangoFont	      *font, 
+			     gunichar	      *text, 
+			     int	      length,
+			     PangoGlyphString *glyphs, 
+			     int	      *n_glyphs, 
+			     int	      cluster_offset)
+{
+  int index;
+  gunichar wc;
+  int i;
+  gunichar *text0 = NULL;
+  OgJamosToNgSyllable key,*match;
+  gunichar tone = 0;
+
+#if 0
+  gunichar buf_static[9];
+  guint buf_size = G_N_ELEMENTS (buf_static);
+  gunichar *text1 = buf_static;
+  int length1;
+#endif
+
+  if (IS_M (text[length - 1]))
+    {
+      tone = text[length - 1];
+      length--;
+    }
+
+  /* XXX : need to check if we have an isolated precomp. syllable and
+   * expedite things to avoid decomposition/recomposition in that case.
+   * At the moment, we don't have to because hangul_engine_shape()
+   * decomposes a precomposed syllble into a jamo seq.
+   */
+
+  text = _normalize_jamo (text, &length);
+  text0 = text;
+
+  if (length == 1) 
+    {
+#if 1
+      text[0] += LC_OFFSET;  /* fallback assumes OG position */
+#else
+      text1[0] = text[0];
+      length1 = 1;
+#endif
+      goto fallback;
+    }
+
+
+  text += render_as_precomp_syllable (font, text, &length, glyphs, n_glyphs,
+          cluster_offset, FALSE);
+
+  if (! length)
     {
-      index = find_char (font, 0x3164);
+      if (tone)
+        render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+      g_free (text0);
+      return;
+    }
+
+#if 0
+  if (length > buf_siz)
+    text1 = g_new (gunichar, length);
+  memcpy (text1, text, length * sizeof (gunichar));
+  length1 = length;
+#endif
+
+  og_transform (text, &length);
+
+  if (length != 2 && length != 3)
+    goto fallback; 
+
+  if (! OG_IS_L (text[0]) || ! OG_IS_V (text[1]) || 
+      (length == 3 && ! OG_IS_T (text[2])))
+    goto fallback;
+
+  /* Look-up the precomposed syllable table */
+
+  key.seq[0] = text[0];
+  key.seq[1] = text[1];
+  key.seq[2] = length == 3 ? text[2] : 0; 
+  match = bsearch (&key, __og_jamos_to_ng_syllable, 
+           	   G_N_ELEMENTS (__og_jamos_to_ng_syllable), 
+		   sizeof (key), ojns_comp);
+
+  if (match)
+    {
+      index = find_char (font, match->liga);
       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);
-      glyphs->log_clusters[*n_glyphs] = cluster_offset;
       (*n_glyphs)++;
     }
+
+  /* Use Jamo glyphs for simple over-striking */
+  else 
+    {
+      text[0] = __ogulim_lc_gidx[text[0] - LBASE - LC_OFFSET] + NG_LBASE;
+      text[1] = __ogulim_vo_gidx[text[1] - VFILL - VO_OFFSET] + NG_VBASE;
+
+  /* Unless a character is explicitly specified in fonts.conf file 
+   * as beling allowed to have a blank glyph, fontconfig regards it as 
+   * invalid and tries to come up with  sth. else. LFILL will be included 
+   * in fonts.conf distribution as a blank characters
+   * wheras we cannot expect ordinary users to add font-specific PUA 
+   * codepoints to the blank character list. Therefore, use LFILL in place 
+   * of Filler in PUA. NG_VBASE (VFill) is skipped below because it's 
+   * not only blank but also has zero-width so that its absence makes 
+   * no difference in  rendering. 
+   */
+      if (text[0] == NG_LBASE )
+        text[0] = LFILL; 
+
+      if (length == 3)
+        text[2] = __ogulim_tc_gidx[text[2] - TSTART - TC_OFFSET] + NG_TBASE;
+
+      for (i = 0; i < length; i++)
+        {
+          if (text[i] == NG_VBASE)  /* skip VFILL in PUA */
+            continue;
+          index = find_char (font, text[i]);
+          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)++;
+        }
+    }
+
   if (tone)
     render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+  g_free (text0);
+#if 0
+  if (length1 > buf_size)
+    g_free (text1);
+#endif
+
+  return; 
+
+
+  /* If jamo sequence is not convertible to a jamo cluster,
+   * just enumerate stand-alone jamos. 
+   * XXX : Would it be better to reverse the og_transform (the content of text[]
+   * can be stowed into text1[]  before OG_Transform and be retrieved here.)
+   * and render stand-alone Jamos with glyphs at U+1100 block? 
+   */ 
+
+fallback: 
+#if 1
+  for (i = 0; i < length; i++)
+    {
+      gunichar wc2=0;
+
+      /* skip Lfill and Vfill if they're not the sole char. in a cluster */
+      if (length > 1 && 
+	  (text[i] - LC_OFFSET == LFILL || text[i] - VO_OFFSET == VFILL))
+	continue;
+      else if (OG_IS_L (text[i]))
+        wc = __ogulim_lc_gidx[text[i] - LC_OFFSET - LBASE]  + NG_LBASE;
+      else 
+        {
+	  /* insert Lfill glyph in non-PUA to advance cursor pos. for V and T */
+	  wc = LFILL;  
+	  if (text[i] != VO_TMPPOS) /* don't have to render VFill */
+	    wc2 = OG_IS_V (text[i]) ? 
+	        __ogulim_vo_gidx[text[i] - VO_OFFSET - VFILL]  + NG_VBASE :
+	        __ogulim_tc_gidx[text[i] - TC_OFFSET - TSTART]  + NG_TBASE;
+        }
+
+
+      /* replace NG_LBASE(Lf in Ngulim font) with LFILL(U+115F)
+       * because fontconfig hates an unlisted blank glyph. 
+       */
+      wc = (wc == NG_LBASE ? LFILL : wc); 
+
+      index = find_char (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, index));
+      else
+        set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+      (*n_glyphs)++;
+
+      if (wc2) 
+        {
+          index = find_char (font, wc2); 
+          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)++;
+        }
+    }
+#else 
+  for (i = 0; i < length1; i++)
+    {
+      index =  find_char (font, text1[i]);
+      pango_glyph_string_set_size (glyphs, *n_glyphs + 1);
+      set_glyph (font, glyphs, *n_glyphs, cluster_offset, index);
+      (*n_glyphs)++;
+    }
+  if (length1 > buf_size)
+    g_free (text1);
+#endif
+
+  if (tone)
+    render_tone(font, tone, glyphs, n_glyphs, cluster_offset);
+
+  g_free (text0);
+
+}
+
+static
+void set_render_func (PangoFont          *font, 
+		      RenderSyllableFunc *render_func)
+{
+  guint gindex;
+  FT_Face face=pango_xft_font_lock_face (font); 
+
+  if ( ! strcmp (face->family_name,"Gulim Old Hangul Jamo") ||
+       ! strcmp (face->family_name,"Batng Old Hangul Jamo") ||
+       ! strcmp (face->family_name,"Gungseo Old Hangul Jamo")|| 
+       ! strcmp (face->family_name,"Dotum Old Hangul Jamo"))
+    *render_func = render_syllable_with_ogulim;
+  else if ( ! strcmp ( face->family_name,"New Gulim") ||
+	    ! strcmp (face->family_name,"New Batng")  ||
+	    ! strcmp (face->family_name,"New Gungseo") || 
+	    ! strcmp (face->family_name,"New Dotum"))
+    *render_func = render_syllable_with_ngulim;
+  /* if VBASE (U+1161 : the first vowel) is non-spacing/zero-width,
+   * assume that a font has combining Jamo glyphs.
+   */
+  else if ((gindex=find_char (font, VBASE)))
+    {
+      PangoRectangle l_rect;
+      pango_font_get_glyph_extents (font, (PangoGlyph) gindex, NULL, &l_rect);
+      if ( ! l_rect.width ) 
+	*render_func = render_syllable_with_combining_jamo;
+      else 
+	*render_func = render_syllable_with_spacing_jamo;
+    }
+  else
+    *render_func = render_syllable_with_spacing_jamo;
 }
 
 static void 
 hangul_engine_shape (PangoFont        *font,
 		     const char       *text,
 		     gint              length,
 		     PangoAnalysis    *analysis,
@@ -283,19 +795,24 @@ hangul_engine_shape (PangoFont        *f
   const char *p, *start;
 
   gunichar jamos_static[8];
   guint max_jamos = G_N_ELEMENTS (jamos_static);
   gunichar *jamos = jamos_static;
   int n_jamos;
 
+  RenderSyllableFunc render_func = NULL;
+
   n_chars = g_utf8_strlen (text, length);
   n_glyphs = 0;
   start = p = text;
   n_jamos = 0;
 
+
+  set_render_func (font,&render_func);
+
   for (i = 0; i < n_chars; i++)
     {
       gunichar prev = jamos[n_jamos - 1];
       gunichar wc;
 
       wc = g_utf8_get_char (p);
 
@@ -304,16 +821,15 @@ hangul_engine_shape (PangoFont        *f
 	  ((!IS_L (prev) && IS_S (wc)) ||
 	   (IS_T (prev) && IS_L (wc)) ||
 	   (IS_V (prev) && IS_L (wc)) ||
 	   (IS_T (prev) && IS_V (wc)) ||
 	   IS_M(prev)))
 	{
 	  /* Draw a syllable. */
-	  render_syllable (font, jamos, n_jamos, glyphs,
-			   &n_glyphs, start - text);
+	  render_func (font, jamos, n_jamos, glyphs, &n_glyphs, start - text);
 	  n_jamos = 0;
 	  start = p;
 	}
 
       if (n_jamos == max_jamos)
 	{
 	  max_jamos += 3;	/* at most 3 for each syllable code (L+V+T) */
@@ -340,20 +856,19 @@ hangul_engine_shape (PangoFont        *f
 	  start = g_utf8_next_char (p);
 	}
       else
 	jamos[n_jamos++] = wc;
       p = g_utf8_next_char (p);
     }
 
-  if (n_jamos != 0)
-    render_syllable (font, jamos, n_jamos, glyphs, &n_glyphs,
-		     start - text);
+  if (n_jamos != 0) 
+    render_func (font, jamos, n_jamos, glyphs, &n_glyphs, start - text);
 
   if (jamos != jamos_static)
-    g_free(jamos);
+    g_free (jamos);
 }
 
 static PangoCoverage *
 hangul_engine_get_coverage (PangoFont  *font,
 			   PangoLanguage *lang)
 {
   PangoCoverage *result = pango_coverage_new ();
