/* This is a fallback for when we get a tone mark not preceded * by a syllable. */ static void render_isolated_tone (PangoFont *font, gunichar tone, PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset) { #if 0 /* FIXME: what kind of hack is it? it draws dummy glyphs. */ /* Find a base character to render the mark on */ int index = find_char (font, 0x25cc); /* DOTTED CIRCLE */ if (!index) index = find_char (font, 0x25cb); /* WHITE CIRCLE, in KSC-5601 */ if (!index) index = find_char (font, ' '); /* Space */ if (!index) /* Unknown glyph box with 0000 in it */ index = find_char (font, PANGO_GET_UNKNOWN_GLYPH (0)); /* Add the base character */ pango_glyph_string_set_size (glyphs, *n_glyphs + 1); set_glyph (font, glyphs, *n_glyphs, cluster_offset, index); (*n_glyphs)++; #endif /* And the tone mark */ render_tone(font, tone, glyphs, n_glyphs, cluster_offset); }
/* This is a fallback for when we get a tone mark not preceded * by a syllable. */ static void render_isolated_tone (PangoFont *font, gunichar tone, PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset) { /* Find a base character to render the mark on */ int index = find_char (font, 0x25cc); /* DOTTED CIRCLE */ if (!index) index = find_char (font, 0x25cb); /* WHITE CIRCLE, in KSC-5601 */ if (!index) index = find_char (font, ' '); /* Space */ if (!index) /* Unknown glyph box with 0000 in it */ index = find_char (font, get_unknown_glyph (font, 0)); /* Add the base character */ pango_glyph_string_set_size (glyphs, *n_glyphs + 1); set_glyph (font, glyphs, *n_glyphs, cluster_offset, index); (*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) { 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; 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 (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; } /* Render the remaining text as uncomposed forms as a fallback. */ for (i = 0; i < length; i++) { int jindex; int oldlen; if (text[i] == LFILL || text[i] == VFILL) 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); (*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; oldlen = *n_glyphs; 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 (font, wc) : 0; pango_glyph_string_set_size (glyphs, *n_glyphs + 1); if (!index) { *n_glyphs = oldlen; pango_glyph_string_set_size (glyphs, *n_glyphs + 1); set_glyph (font, glyphs, *n_glyphs, cluster_offset, get_unknown_glyph (font, text[i])); (*n_glyphs)++; break; } else set_glyph (font, glyphs, *n_glyphs, cluster_offset, index); (*n_glyphs)++; } } if (n_prev_glyphs == *n_glyphs) { index = find_char (font, 0x3164); 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)++; } if (tone) render_tone(font, tone, glyphs, n_glyphs, cluster_offset); }
static void render_syllable (PangoFont *font, const char *str, int length, PangoGlyphString *glyphs, int *n_glyphs, int cluster_offset) { int n_prev_glyphs = *n_glyphs; int index; gunichar wc = 0, tone = 0, text[4]; int i, j, composed = 0; const char *p; /* Normalize it only when the entire sequence is equivalent to a * precomposed syllable. It's usually better than prefix * normalization both for poor-featured fonts and for smart fonts. * I have seen no smart font which can render S+T as a syllable * form. */ if (length == 3 || length == 4) { p = str; text[0] = g_utf8_get_char(p); p = g_utf8_next_char(p); text[1] = g_utf8_get_char(p); p = g_utf8_next_char(p); text[2] = g_utf8_get_char(p); if (length == 4 && !IS_M(g_utf8_get_char(g_utf8_next_char(p)))) goto lvt_out; /* draw the tone mark later */ if (IS_L_S(text[0]) && IS_V_S(text[1]) && IS_T_S(text[2])) { composed = 3; wc = S_FROM_LVT(text[0], text[1], text[2]); str = g_utf8_next_char(p); goto normalize_out; } } lvt_out: if (length == 2 || length == 3) { p = str; text[0] = g_utf8_get_char(p); p = g_utf8_next_char(p); text[1] = g_utf8_get_char(p); if (length == 3 && !IS_M(g_utf8_get_char(g_utf8_next_char(p)))) goto lv_out; /* draw the tone mark later */ if (IS_L_S(text[0]) && IS_V_S(text[1])) { composed = 2; wc = S_FROM_LV(text[0], text[1]); str = g_utf8_next_char(p); } else if (IS_S(text[0] && !S_HAS_T(text[0]) && IS_T_S(text[1]))) { composed = 2; wc = text[0] + (text[1] - TBASE); str = g_utf8_next_char(p); goto normalize_out; } } lv_out: normalize_out: if (composed) { 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_GET_UNKNOWN_GLYPH (wc)); else set_glyph (font, glyphs, *n_glyphs, cluster_offset, index); (*n_glyphs)++; length -= composed; } /* Render the remaining text as uncomposed forms as a fallback. */ for (i = 0; i < length; i++, str = g_utf8_next_char(str)) { int jindex; int oldlen; wc = g_utf8_get_char(str); if (wc == LFILL || wc == VFILL) continue; if (IS_M(wc)) { tone = wc; break; } if (IS_S(wc)) { oldlen = *n_glyphs; text[0] = L_FROM_S(wc); text[1] = V_FROM_S(wc); if (S_HAS_T(wc)) { text[2] = T_FROM_S(wc); composed = 3; } else composed = 2; for (j = 0; j < composed; j++) { index = find_char (font, text[j]); if (index) { pango_glyph_string_set_size (glyphs, *n_glyphs + 1); set_glyph (font, glyphs, *n_glyphs, cluster_offset, index); (*n_glyphs)++; } else goto decompose_cancel; } continue; decompose_cancel: /* The font doesn't have jamos. Cancel it. */ *n_glyphs = oldlen; pango_glyph_string_set_size (glyphs, *n_glyphs); } index = find_char (font, wc); if (index) { pango_glyph_string_set_size (glyphs, *n_glyphs + 1); set_glyph (font, glyphs, *n_glyphs, cluster_offset, index); (*n_glyphs)++; continue; } else if (IS_S(wc)) { pango_glyph_string_set_size (glyphs, *n_glyphs + 1); set_glyph (font, glyphs, *n_glyphs, cluster_offset, PANGO_GET_UNKNOWN_GLYPH (wc)); (*n_glyphs)++; continue; } /* This font has no glyphs on the Hangul Jamo area! Find a fallback from the Hangul Compatibility Jamo area. */ jindex = wc - LBASE; oldlen = *n_glyphs; 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 (font, wc) : 0; pango_glyph_string_set_size (glyphs, *n_glyphs + 1); if (!index) { *n_glyphs = oldlen; pango_glyph_string_set_size (glyphs, *n_glyphs + 1); set_glyph (font, glyphs, *n_glyphs, cluster_offset, PANGO_GET_UNKNOWN_GLYPH (text[i])); (*n_glyphs)++; break; } else set_glyph (font, glyphs, *n_glyphs, cluster_offset, index); (*n_glyphs)++; } } if (n_prev_glyphs == *n_glyphs) { index = find_char (font, 0x3164); /* U+3164 HANGUL FILLER */ pango_glyph_string_set_size (glyphs, *n_glyphs + 1); if (!index) set_glyph (font, glyphs, *n_glyphs, cluster_offset, PANGO_GET_UNKNOWN_GLYPH (index)); else set_glyph (font, glyphs, *n_glyphs, cluster_offset, index); glyphs->log_clusters[*n_glyphs] = cluster_offset; (*n_glyphs)++; } if (tone) render_tone(font, tone, glyphs, n_glyphs, cluster_offset); }