summaryrefslogtreecommitdiff
path: root/modules/basic/basic-x.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/basic/basic-x.c')
-rw-r--r--modules/basic/basic-x.c203
1 files changed, 87 insertions, 116 deletions
diff --git a/modules/basic/basic-x.c b/modules/basic/basic-x.c
index 838b5c42..6c851228 100644
--- a/modules/basic/basic-x.c
+++ b/modules/basic/basic-x.c
@@ -34,11 +34,14 @@ typedef struct _CharCache CharCache;
typedef struct _MaskTable MaskTable;
typedef PangoGlyph (*ConvFunc) (CharCache *cache,
- const char *id,
+ Charset *charset,
const gchar *input);
+#define MAX_CHARSETS 32
+
struct _Charset
{
+ int index;
char *id;
char *x_charset;
ConvFunc conv_func;
@@ -53,8 +56,6 @@ struct _CharRange
struct _MaskTable
{
- guint mask;
-
int n_subfonts;
PangoXSubfont *subfonts;
@@ -63,18 +64,18 @@ struct _MaskTable
struct _CharCache
{
- GSList *mask_tables;
- GHashTable *converters;
+ MaskTable *mask_tables[256];
+ iconv_t converters[MAX_CHARSETS];
};
-static PangoGlyph conv_8bit (CharCache *cache,
- const char *id,
+static PangoGlyph conv_8bit (CharCache *cache,
+ Charset *charset,
const char *input);
static PangoGlyph conv_euc (CharCache *cache,
- const char *id,
+ Charset *charset,
const char *input);
static PangoGlyph conv_ucs4 (CharCache *cache,
- const char *id,
+ Charset *charset,
const char *input);
#include "tables-big.i"
@@ -127,79 +128,37 @@ basic_engine_lang_new ()
* X window system script engine portion
*/
-static guint
-find_char_mask (GUChar4 wc)
-{
- int start, end, middle;
-
- start = 0;
- end = G_N_ELEMENTS(ranges) - 1;
-
- if (ranges[start].start > wc || ranges[end].end < wc)
- return 0;
-
- while (1)
- {
- middle = (start + end) / 2;
- if (middle == start)
- {
- if (ranges[middle].start > wc || ranges[middle].end < wc)
- return ENC_ISO_10646;
- else
- return ranges[middle].charsets | ENC_ISO_10646;
- }
- else
- {
- if (ranges[middle].start <= wc)
- start = middle;
- else if (ranges[middle].end >= wc)
- end = middle;
- else
- return ENC_ISO_10646;
- }
- }
-}
-
static CharCache *
char_cache_new (void)
{
CharCache *result;
+ int i;
- result = g_new (CharCache, 1);
- result->mask_tables = NULL;
- result->converters = g_hash_table_new (g_str_hash, g_str_equal);
+ result = g_new0 (CharCache, 1);
- return result;
-}
+ for (i=0; i<MAX_CHARSETS; i++)
+ result->converters[i] = (iconv_t)-1;
-static void
-char_cache_converters_foreach (gpointer key, gpointer value, gpointer data)
-{
- g_free (key);
- iconv_close ((iconv_t)value);
+ return result;
}
static void
char_cache_free (CharCache *cache)
{
- GSList *tmp_list;
-
- tmp_list = cache->mask_tables;
- while (tmp_list)
- {
- MaskTable *mask_table = tmp_list->data;
- tmp_list = tmp_list->next;
-
- g_free (mask_table->subfonts);
- g_free (mask_table->charsets);
-
- g_free (mask_table);
- }
-
- g_slist_free (cache->mask_tables);
+ int i;
- g_hash_table_foreach (cache->converters, char_cache_converters_foreach, NULL);
- g_hash_table_destroy (cache->converters);
+ for (i=0; i<256; i++)
+ if (cache->mask_tables[i])
+ {
+ g_free (cache->mask_tables[i]->subfonts);
+ g_free (cache->mask_tables[i]->charsets);
+
+ g_free (cache->mask_tables[i]);
+ }
+
+ for (i=0; i<MAX_CHARSETS; i++)
+ if (cache->converters[i] != (iconv_t)-1)
+ iconv_close (cache->converters[i]);
g_free (cache);
}
@@ -207,34 +166,28 @@ char_cache_free (CharCache *cache)
PangoGlyph
find_char (CharCache *cache, PangoFont *font, GUChar4 wc, const char *input)
{
- guint mask = find_char_mask (wc);
- GSList *tmp_list;
+ int mask_index;
MaskTable *mask_table;
int i;
- tmp_list = cache->mask_tables;
- while (tmp_list)
- {
- mask_table = tmp_list->data;
-
- if (mask_table->mask == mask)
- break;
-
- tmp_list = tmp_list->next;
- }
+ if (wc >= G_N_ELEMENTS (char_masks))
+ mask_index = 0;
+ else
+ mask_index = char_masks[wc];
- if (!tmp_list)
+ if (cache->mask_tables[mask_index])
+ mask_table = cache->mask_tables[mask_index];
+ else
{
char *charset_names[G_N_ELEMENTS(charsets)];
Charset *charsets_map[G_N_ELEMENTS(charsets)];
-
+ guint mask;
int n_charsets = 0;
-
int *subfont_charsets;
mask_table = g_new (MaskTable, 1);
- mask_table->mask = mask;
+ mask = char_mask_map[mask_index] | ENC_ISO_10646;
/* Find the character sets that are included in this mask
*/
@@ -258,7 +211,7 @@ find_char (CharCache *cache, PangoFont *font, GUChar4 wc, const char *input)
g_free (subfont_charsets);
- cache->mask_tables = g_slist_prepend (cache->mask_tables, mask_table);
+ cache->mask_tables[mask_index] = mask_table;
}
for (i=0; i < mask_table->n_subfonts; i++)
@@ -266,7 +219,7 @@ find_char (CharCache *cache, PangoFont *font, GUChar4 wc, const char *input)
PangoGlyph index;
PangoGlyph glyph;
- index = (*mask_table->charsets[i]->conv_func) (cache, mask_table->charsets[i]->id, input);
+ index = (*mask_table->charsets[i]->conv_func) (cache, mask_table->charsets[i], input);
glyph = PANGO_X_MAKE_GLYPH (mask_table->subfonts[i], index);
@@ -294,13 +247,14 @@ set_glyph (PangoFont *font, PangoGlyphString *glyphs, int i, int offset, PangoGl
}
static iconv_t
-find_converter (CharCache *cache, const char *id)
+find_converter (CharCache *cache, Charset *charset)
{
- iconv_t cd = g_hash_table_lookup (cache->converters, id);
- if (!cd)
+ iconv_t cd = cache->converters[charset->index];
+ if (cd == (iconv_t)-1)
{
- cd = iconv_open (id, "UTF-8");
- g_hash_table_insert (cache->converters, g_strdup(id), (gpointer)cd);
+ cd = iconv_open (charset->id, "UTF-8");
+ g_assert (cd != (iconv_t)-1);
+ cache->converters[charset->index] = cd;
}
return cd;
@@ -308,7 +262,7 @@ find_converter (CharCache *cache, const char *id)
static PangoGlyph
conv_8bit (CharCache *cache,
- const char *id,
+ Charset *charset,
const char *input)
{
iconv_t cd;
@@ -323,8 +277,7 @@ conv_8bit (CharCache *cache,
_pango_utf8_iterate (input, &p, NULL);
inbytesleft = p - input;
- cd = find_converter (cache, id);
- g_assert (cd != (iconv_t)-1);
+ cd = find_converter (cache, charset);
iconv (cd, (const char **)&inptr, &inbytesleft, &outptr, &outbytesleft);
@@ -333,7 +286,7 @@ conv_8bit (CharCache *cache,
static PangoGlyph
conv_euc (CharCache *cache,
- const char *id,
+ Charset *charset,
const char *input)
{
iconv_t cd;
@@ -348,8 +301,7 @@ conv_euc (CharCache *cache,
_pango_utf8_iterate (input, &p, NULL);
inbytesleft = p - input;
- cd = find_converter (cache, id);
- g_assert (cd != (iconv_t)-1);
+ cd = find_converter (cache, charset);
iconv (cd, &inptr, &inbytesleft, &outptr, &outbytesleft);
@@ -361,12 +313,12 @@ conv_euc (CharCache *cache,
static PangoGlyph
conv_ucs4 (CharCache *cache,
- const char *id,
+ Charset *charset,
const char *input)
{
GUChar4 wc;
- _pango_utf8_iterate (input, NULL, &wc);
+ unicode_get_utf8 (input, &wc);
return wc;
}
@@ -448,26 +400,39 @@ basic_engine_shape (PangoFont *font,
_pango_guchar4_to_utf8 (wc, buf);
input = buf;
}
-
- index = find_char (cache, font, wc, input);
- if (index)
+ if (wc == 0x200B) /* Zero-width space */
{
- set_glyph (font, glyphs, i, p - text, index);
-
- if (unicode_type (wc) == UNICODE_NON_SPACING_MARK)
+ index = find_char (cache, font, ' ', input);
+ if (index)
+ {
+ set_glyph (font, glyphs, i, p - text, index);
+ glyphs->glyphs[i].geometry.width = 0;
+ }
+ else
+ set_glyph (font, glyphs, i, p - text, pango_x_get_unknown_glyph (font));
+ }
+ else
+ {
+ index = find_char (cache, font, wc, input);
+ if (index)
{
- if (i > 0)
+ set_glyph (font, glyphs, i, p - text, index);
+
+ if (unicode_type (wc) == UNICODE_NON_SPACING_MARK)
{
- glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
- glyphs->glyphs[i].geometry.width);
- glyphs->glyphs[i-1].geometry.width = 0;
- glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
+ if (i > 0)
+ {
+ glyphs->glyphs[i].geometry.width = MAX (glyphs->glyphs[i-1].geometry.width,
+ glyphs->glyphs[i].geometry.width);
+ glyphs->glyphs[i-1].geometry.width = 0;
+ glyphs->log_clusters[i] = glyphs->log_clusters[i-1];
+ }
}
}
+ else
+ set_glyph (font, glyphs, i, p - text, pango_x_get_unknown_glyph (font));
}
- else
- set_glyph (font, glyphs, i, p - text, pango_x_get_unknown_glyph (font));
p = next;
}
@@ -534,15 +499,21 @@ basic_engine_x_new ()
/* The following three functions provide the public module API for
* Pango
*/
+#ifdef MODULE_PREFIX
+#define MODULE_ENTRY(func) _pango_basic_##func
+#else
+#define MODULE_ENTRY(func) func
+#endif
+
void
-script_engine_list (PangoEngineInfo **engines, gint *n_engines)
+MODULE_ENTRY(script_engine_list) (PangoEngineInfo **engines, gint *n_engines)
{
*engines = script_engines;
*n_engines = n_script_engines;
}
PangoEngine *
-script_engine_load (const char *id)
+MODULE_ENTRY(script_engine_load) (const char *id)
{
if (!strcmp (id, "BasicScriptEngineLang"))
return basic_engine_lang_new ();
@@ -553,7 +524,7 @@ script_engine_load (const char *id)
}
void
-script_engine_unload (PangoEngine *engine)
+MODULE_ENTRY(script_engine_unload) (PangoEngine *engine)
{
}