summaryrefslogtreecommitdiff
path: root/modules/arabic/arabic-x.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2000-03-30 22:13:13 +0000
committerOwen Taylor <otaylor@src.gnome.org>2000-03-30 22:13:13 +0000
commitc1198ebb48f2eaf3e71a5f37b4ceaae16cba84d7 (patch)
tree6aa116dfc63b08175102874c9945fadbb31f6b15 /modules/arabic/arabic-x.c
parent5b5698e8ad4fa0f0f5da0286ab34b5ba1fa8ecae (diff)
downloadpango-c1198ebb48f2eaf3e71a5f37b4ceaae16cba84d7.tar.gz
New version of Arabic module from Karl Koehler, supporting:
Thu Mar 30 17:06:39 2000 Owen Taylor <otaylor@redhat.com> * modules/arabic/*.[ch]: New version of Arabic module from Karl Koehler, supporting: - More extensive ligatures - Some Hamza handling - Vowel marks - mule-arabic font - LangBox font - Persian (farsi) (needs testing)
Diffstat (limited to 'modules/arabic/arabic-x.c')
-rw-r--r--modules/arabic/arabic-x.c456
1 files changed, 256 insertions, 200 deletions
diff --git a/modules/arabic/arabic-x.c b/modules/arabic/arabic-x.c
index 18ee4ce1..805c7bba 100644
--- a/modules/arabic/arabic-x.c
+++ b/modules/arabic/arabic-x.c
@@ -1,7 +1,8 @@
/* Pango - Arabic module
* arabic module
*
- * (C) 2000 K. Koehler <koehler@or.uni-bonn.de>
+ * (C) 2000 Karl Koehler<koehler@or.uni-bonn.de>
+ * Owen Taylor <otayler@redhat.com>
*
*/
@@ -13,28 +14,31 @@
#include <unicode.h>
#include "arconv.h"
+#include "mulefont.h"
+
+/* #define DEBUG */
+#ifdef DEBUG
+#include <stdio.h>
+#endif
-/*
-** I hope thing's work easily ...
-*/
static PangoEngineRange arabic_range[] = {
- { 0x060B, 0x067F, "*" },
+ { 0x060B, 0x06D3, "*" } /* 0x060B, 0x06D3 */
};
static PangoEngineInfo script_engines[] = {
- {
- "ArabicScriptEngineLang",
- PANGO_ENGINE_TYPE_LANG,
- PANGO_RENDER_TYPE_NONE,
- arabic_range, G_N_ELEMENTS(arabic_range)
- },
- {
- "ArabicScriptEngineX",
- PANGO_ENGINE_TYPE_SHAPE,
- PANGO_RENDER_TYPE_X,
- arabic_range, G_N_ELEMENTS(arabic_range)
- }
+ {
+ "ArabicScriptEngineLang",
+ PANGO_ENGINE_TYPE_LANG,
+ PANGO_RENDER_TYPE_NONE,
+ arabic_range, G_N_ELEMENTS(arabic_range)
+ },
+ {
+ "ArabicScriptEngineX",
+ PANGO_ENGINE_TYPE_SHAPE,
+ PANGO_RENDER_TYPE_X,
+ arabic_range, G_N_ELEMENTS(arabic_range)
+ }
};
static gint n_script_engines = G_N_ELEMENTS (script_engines);
@@ -47,79 +51,109 @@ static gint n_script_engines = G_N_ELEMENTS (script_engines);
*/
static void
-arabic_engine_break (const char *text,
+arabic_engine_break (const char *text,
int len,
PangoAnalysis *analysis,
PangoLogAttr *attrs)
{
- /* Most of the code comes from tamil_engine_break
- * only difference is char stop based on modifiers
- */
-
- const char *cur = text;
- const char *next;
- gint i = 0;
- GUChar4 wc;
-
- while (*cur)
- {
- if (!_pango_utf8_iterate (cur, &next, &wc))
- return;
- if (cur == next)
- break;
- if ((next - text) > len)
- break;
- cur = next;
-
- attrs[i].is_white = (wc == ' ' || wc == '\t' || wc == 'n') ? 1 : 0;
- attrs[i].is_break = (i > 0 && attrs[i-1].is_white) || attrs[i].is_white;
- attrs[i].is_char_stop = 1;
- attrs[i].is_word_stop = (i == 0) || attrs[i-1].is_white;
-
- i++;
- }
+ /* Most of the code comes from tamil_engine_break
+ * only difference is char stop based on modifiers
+ */
+
+ const char *cur = text;
+ const char *next;
+ gint i = 0;
+ GUChar4 wc;
+
+ while (*cur)
+ {
+ if (!_pango_utf8_iterate (cur, &next, &wc))
+ return;
+ if (cur == next)
+ break;
+ if ((next - text) > len)
+ break;
+ cur = next;
+
+ attrs[i].is_white = (wc == ' ' || wc == '\t' || wc == 'n') ? 1 : 0;
+ attrs[i].is_break = (i > 0 && attrs[i-1].is_white) || attrs[i].is_white;
+ attrs[i].is_char_stop = 1;
+ attrs[i].is_word_stop = (i == 0) || attrs[i-1].is_white;
+ /* actually, is_word_stop in not correct, but simple and good enough. */
+ i++;
+ }
}
static PangoEngine *
arabic_engine_lang_new ()
{
- PangoEngineLang *result;
+ PangoEngineLang *result;
- result = g_new (PangoEngineLang, 1);
+ result = g_new (PangoEngineLang, 1);
- result->engine.id = "ArabicScriptEngine";
- result->engine.type = PANGO_ENGINE_TYPE_LANG;
- result->engine.length = sizeof (result);
- result->script_break = arabic_engine_break;
+ result->engine.id = "ArabicScriptEngine";
+ result->engine.type = PANGO_ENGINE_TYPE_LANG;
+ result->engine.length = sizeof (result);
+ result->script_break = arabic_engine_break;
- return (PangoEngine *)result;
+ return (PangoEngine *)result;
}
/*
* X window system script engine portion
*/
-static PangoXSubfont
-find_unic_font (PangoFont *font,char* charsets[])
+static int
+find_unic_font (PangoFont *font,char* charsets[],PangoXSubfont* rfonts)
{
- PangoXSubfont *subfonts;
- int *subfont_charsets;
- int n_subfonts;
- PangoXSubfont result = 0;
-
- n_subfonts = pango_x_list_subfonts (font, charsets, 1, &subfonts, &subfont_charsets);
-
- if (n_subfonts > 0)
- result = subfonts[0];
-
- g_free (subfonts);
- g_free (subfont_charsets);
-
- return result;
+ PangoXSubfont *subfonts;
+ int *subfont_charsets;
+ int n_subfonts;
+ int i;
+ int result = 0;
+
+ n_subfonts = pango_x_list_subfonts (font, charsets, 2,
+ &subfonts, &subfont_charsets);
+
+ for (i=0; i < n_subfonts; i++)
+ {
+ if ( (strcmp (charsets[subfont_charsets[i]], "mulearabic-2") == 0)
+ && arabic_muleinit(font,rfonts) )
+ {
+ result = 1; /* we know we have a mulearabic-font ... */
+ break;
+ }
+ else
+ { /* test if the font has Alif-Madda; if so assume it is ok */
+ if ( pango_x_has_glyph /* Alif-Madda */
+ (font,PANGO_X_MAKE_GLYPH(subfonts[i],0xFE81)))
+ {
+ rfonts[0] = subfonts[i];
+ result = 2;
+ }
+ if ( pango_x_has_glyph /* Shadda+Kasra */
+ (font,PANGO_X_MAKE_GLYPH(subfonts[i],0xFC62)))
+ {
+ result = 3; /* extra vowels in font, hopefully */
+ }
+ if ( pango_x_has_glyph /* Lam-Min alone */
+ (font,PANGO_X_MAKE_GLYPH(subfonts[i],0xFC42)))
+ {
+ result = 4; /* extra ligatures in font, hopefully */
+ }
+ break;
+ }
+ }
+
+ g_free (subfonts);
+ g_free (subfont_charsets);
+
+ return result;
}
static char *default_charset[] = {
- "iso10646-1"
+ "iso10646-1",
+ "mulearabic-2"
};
@@ -127,25 +161,36 @@ static char *default_charset[] = {
static void
set_glyph (PangoGlyphString *glyphs,
PangoFont *font, PangoXSubfont subfont,
- int i, int cluster_start, int glyph)
+ int i, int cluster_start, int glyph)
{
- PangoRectangle logical_rect;
+ PangoRectangle logical_rect;
+#ifdef DEBUG
+ if ( i < 0){
+ fprintf(stderr,"[ar] setglyph: setting glyph %x at index %i, cluster %i\n",
+ glyph,i,cluster_start);
+ raise(6);
+ } else {
+ fprintf(stderr,"[ar] setglyph: setting glyph %x at index %i, "
+ "cluster %i ( subfont %x )\n",
+ glyph,i,cluster_start,subfont);
+ }
+#endif
- glyphs->glyphs[i].glyph = PANGO_X_MAKE_GLYPH (subfont, glyph);
+ glyphs->glyphs[i].glyph = PANGO_X_MAKE_GLYPH (subfont, glyph);
- glyphs->glyphs[i].geometry.x_offset = 0;
- glyphs->glyphs[i].geometry.y_offset = 0;
-
- pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
- glyphs->log_clusters[i] = cluster_start;
- if (arabic_isvowel(glyph))
- {
- glyphs->glyphs[i].geometry.width = 0;
- }
- else
- {
- glyphs->glyphs[i].geometry.width = logical_rect.width;
- }
+ glyphs->glyphs[i].geometry.x_offset = 0;
+ glyphs->glyphs[i].geometry.y_offset = 0;
+
+ pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+ glyphs->log_clusters[i] = cluster_start;
+ if (arabic_isvowel(glyph))
+ {
+ glyphs->glyphs[i].geometry.width = 0;
+ }
+ else
+ {
+ glyphs->glyphs[i].geometry.width = logical_rect.width;
+ }
}
@@ -158,106 +203,115 @@ arabic_engine_shape (PangoFont *font,
PangoAnalysis *analysis,
PangoGlyphString *glyphs)
{
- PangoXSubfont subfont;
-
- int n_chars, n_glyph;
- int i;
- const char *p;
- const char *pold;
- const char *next;
- GUChar4 *wc;
-
- g_return_if_fail (font != NULL);
- g_return_if_fail (text != NULL);
- g_return_if_fail (length >= 0);
- g_return_if_fail (analysis != NULL);
-
- /* We assume we have an unicode-font like 10x20 which containes
- ** the needed chars
- */
+ PangoXSubfont subfont;
+ PangoXSubfont arfonts[3];
+
+
+ int n_chars, n_glyph;
+ int i;
+ const char *p;
+ const char *pold;
+ const char *next;
+ GUChar4 *wc;
+ int lvl = 1;
+
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (text != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (analysis != NULL);
+
+ /* We assume we have an unicode-font like 10x20 which containes
+ ** the needed chars -- or tree mulearabic-coded fonts ...
+ */
- n_chars = n_glyph = unicode_strlen (text, length);
-
- if (!(subfont = find_unic_font (font, default_charset)))
- {
- PangoGlyph unknown_glyph = pango_x_get_unknown_glyph (font);
+ n_chars = n_glyph = unicode_strlen (text, length);
+
+ if (!(lvl = find_unic_font (font, default_charset,arfonts)))
+ {
+
+ PangoGlyph unknown_glyph = pango_x_get_unknown_glyph (font);
+
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ p = text;
+ for (i=0; i<n_chars; i++)
+ {
+ set_glyph (glyphs, font, arfonts[0], i,
+ p - text, unknown_glyph);
+ p = unicode_next_utf8 (p);
+ }
+ return;
+ }
+ subfont = arfonts[0];
+
+ if (analysis->level % 2 == 0)
+ {
+ /* We were called on a LTR directional run (e.g. some numbers);
+ fallback as simple as possible */
+
+ pango_glyph_string_set_size (glyphs, n_chars);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ GUChar4 tmp_char;
- pango_glyph_string_set_size (glyphs, n_chars);
-
- p = text;
- for (i=0; i<n_chars; i++)
- {
- set_glyph (glyphs, font, subfont, i, p - text, unknown_glyph);
- p = unicode_next_utf8 (p);
- }
-
- return;
- }
-
- if (analysis->level % 2 == 0)
- {
- /* We were called on a LTR directional run (e.g. some numbers);
- fallback as simply as possible */
-
- pango_glyph_string_set_size (glyphs, n_chars);
-
- p = text;
- for (i=0; i < n_chars; i++)
- {
- GUChar4 tmp_char;
-
- _pango_utf8_iterate (p, &next, &tmp_char);
- set_glyph (glyphs, font, subfont, i, p - text, tmp_char);
- p = next;
- }
-
- return;
- }
-
- wc = (GUChar4 *)g_malloc(sizeof(GUChar4)*n_chars);
-
- p = text;
- for (i=0; i < n_chars; i++)
- {
- _pango_utf8_iterate (p, &next, &wc[n_chars - i - 1]);
- p = next;
- }
+ _pango_utf8_iterate (p, &next, &tmp_char);
+ set_glyph (glyphs, font, subfont, i, p - text, tmp_char);
+ p = next;
+ }
+
+ return;
+ }
+
+ wc = (GUChar4 *)g_malloc(sizeof(GUChar4)*n_chars);
+
+ p = text;
+ for (i=0; i < n_chars; i++)
+ {
+ _pango_utf8_iterate (p, &next, &wc[n_chars - i - 1]);
+ p = next;
+ }
- reshape(&n_glyph,wc);
-/* raise(2); */
-
- pango_glyph_string_set_size (glyphs, n_glyph);
-
- p = text;
- pold = p;
- i = n_chars-1;
- while(i >= 0)
- {
- if (wc[i] == 0)
- {
- p = unicode_next_utf8 (p);
- i--;
- }
- else
- {
- set_glyph (glyphs, font, subfont, n_glyph - 1, p - text, wc[i]);
- if ( arabic_isvowel(wc[i]))
- {
- glyphs->log_clusters[n_glyph-1] = pold - text;
- }
+ arabic_reshape(&n_glyph,wc,lvl);
+
+ pango_glyph_string_set_size (glyphs, n_glyph);
+
+ p = text;
+ pold = p;
+ i = n_chars-1;
+ while(i >= 0)
+ {
+ if (wc[i] == 0)
+ {
+ p = unicode_next_utf8 (p);
+ i--;
+ }
+ else
+ {
+ int cluster_start = arabic_isvowel (wc[i])
+ ? pold - text : p - text;
+ if ( lvl == 1 )
+ {
+#ifdef DEBUG
+ fprintf(stderr,"[ar] mule-recoding char %x",
+ wc[i]);
+#endif
+ arabic_mule_recode(&subfont,&(wc[i]),arfonts);
+ }
+
+ set_glyph(glyphs, font, subfont, n_glyph - 1,
+ cluster_start, wc[i]);
- pold = p;
- p = unicode_next_utf8 (p);
- n_glyph--;
- i--;
- };
- }
-
-/* if ((i != 0)||(n_glyph-1 != 0)){ */
-/* printf(" i= %x , n_glyph = %x "); */
-/* }; */
- g_free(wc);
+ pold = p;
+ p = unicode_next_utf8 (p);
+ n_glyph--;
+ i--;
+ }
+ }
+
+ g_free(wc);
}
@@ -265,29 +319,31 @@ static PangoCoverage *
arabic_engine_get_coverage (PangoFont *font,
const char *lang)
{
- GUChar4 i;
- PangoCoverage *result = pango_coverage_new ();
+ GUChar4 i;
+ PangoCoverage *result = pango_coverage_new ();
- for (i = 0x60B; i <= 0x67E; i++)
- pango_coverage_set (result, i, PANGO_COVERAGE_EXACT);
+ for (i = 0x60B; i <= 0x66D; i++)
+ pango_coverage_set (result, i, PANGO_COVERAGE_EXACT);
+ for (i = 0x670; i <= 0x6D3; i++)
+ pango_coverage_set (result, i, PANGO_COVERAGE_EXACT);
- return result;
+ return result;
}
static PangoEngine *
arabic_engine_x_new ()
{
- PangoEngineShape *result;
+ PangoEngineShape *result;
- result = g_new (PangoEngineShape, 1);
+ result = g_new (PangoEngineShape, 1);
- result->engine.id = "ArabicScriptEngine";
- result->engine.type = PANGO_ENGINE_TYPE_LANG;
- result->engine.length = sizeof (result);
- result->script_shape = arabic_engine_shape;
- result->get_coverage = arabic_engine_get_coverage;
+ result->engine.id = "ArabicScriptEngine";
+ result->engine.type = PANGO_ENGINE_TYPE_LANG;
+ result->engine.length = sizeof (result);
+ result->script_shape = arabic_engine_shape;
+ result->get_coverage = arabic_engine_get_coverage;
- return (PangoEngine *)result;
+ return (PangoEngine *)result;
}
@@ -300,19 +356,19 @@ arabic_engine_x_new ()
void
script_engine_list (PangoEngineInfo **engines, int *n_engines)
{
- *engines = script_engines;
- *n_engines = n_script_engines;
+ *engines = script_engines;
+ *n_engines = n_script_engines;
}
PangoEngine *
script_engine_load (const char *id)
{
- if (!strcmp (id, "ArabicScriptEngineLang"))
- return arabic_engine_lang_new ();
- else if (!strcmp (id, "ArabicScriptEngineX"))
- return arabic_engine_x_new ();
- else
- return NULL;
+ if (!strcmp (id, "ArabicScriptEngineLang"))
+ return arabic_engine_lang_new ();
+ else if (!strcmp (id, "ArabicScriptEngineX"))
+ return arabic_engine_x_new ();
+ else
+ return NULL;
}
void