summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@src.gnome.org>2000-01-13 04:12:07 +0000
committerOwen Taylor <otaylor@src.gnome.org>2000-01-13 04:12:07 +0000
commit282fb5fc9f9d01c4d933a6eb6bee6ae9f0d512c7 (patch)
tree0b19c69692a2fe52a1b33d5e27c97b26a64417e3 /pango
parent66ae87f9fc45f5f564acf5014e9bd1341d052958 (diff)
downloadpango-282fb5fc9f9d01c4d933a6eb6bee6ae9f0d512c7.tar.gz
Initial revision
Diffstat (limited to 'pango')
-rw-r--r--pango/.cvsignore5
-rw-r--r--pango/Makefile.am31
-rw-r--r--pango/break.c66
-rw-r--r--pango/fonts.c167
-rw-r--r--pango/glyphstring.c106
-rw-r--r--pango/gunicode.h21
-rw-r--r--pango/itemize.c234
-rw-r--r--pango/mapping.c275
-rw-r--r--pango/modules.c409
-rw-r--r--pango/modules.h55
-rw-r--r--pango/pango.h339
-rw-r--r--pango/pangox.c757
-rw-r--r--pango/pangox.h100
-rw-r--r--pango/querymodules.c102
-rw-r--r--pango/reorder-items.c104
-rw-r--r--pango/shape.c48
-rw-r--r--pango/utils.c153
-rw-r--r--pango/utils.h34
18 files changed, 3006 insertions, 0 deletions
diff --git a/pango/.cvsignore b/pango/.cvsignore
new file mode 100644
index 00000000..417f2d5d
--- /dev/null
+++ b/pango/.cvsignore
@@ -0,0 +1,5 @@
+*.lo
+*.la
+.deps
+.libs
+gscript-querymodules
diff --git a/pango/Makefile.am b/pango/Makefile.am
new file mode 100644
index 00000000..e134358b
--- /dev/null
+++ b/pango/Makefile.am
@@ -0,0 +1,31 @@
+## Process this file with automake to create Makefile.in.
+
+lib_LTLIBRARIES = libpango.la
+bin_PROGRAMS = pango-querymodules
+
+libpango_la_SOURCES = \
+ break.c \
+ fonts.c \
+ glyphstring.c \
+ pangox.c \
+ itemize.c \
+ mapping.c \
+ modules.c \
+ modules.h \
+ reorder-items.c \
+ shape.c \
+ utils.c \
+ utils.h
+
+# We use the -release flag for now until the API settles
+# down at which point we'll either use the GTK+ versioning
+# scheme or the standard libtool scheme.
+#
+libpango_la_LDFLAGS = -release $(VERSION)
+
+include_HEADERS = pango.h pangox.h
+
+pango_querymodules_SOURCES = \
+ querymodules.c
+pango_querymodules_LDADD = libpango.la $(GTK_LIBS) -lfribidi $(UNICODE_LIBS)
+
diff --git a/pango/break.c b/pango/break.c
new file mode 100644
index 00000000..997635b3
--- /dev/null
+++ b/pango/break.c
@@ -0,0 +1,66 @@
+/* Pango
+ * break.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 <pango.h>
+#include <unicode.h>
+#include "utils.h"
+
+/**
+ * pango_break:
+ * @text: the text to process
+ * @length: the length (in bytes) of @text
+ * @analysis: #PangoAnalysis structure from PangoItemize
+ * @attrs: an array to store character information in
+ *
+ * Determines possible line, word, and character breaks
+ * for a string of Unicode text.
+ */
+void pango_break (gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs)
+{
+ /* Pseudo-implementation */
+
+ gchar *cur = text;
+ gchar *next;
+ gint i = 0;
+ GUChar4 wc;
+
+ while (*cur)
+ {
+ next = unicode_get_utf8 (cur, &wc);
+ if (!next)
+ return; /* FIXME: ERROR */
+ if (cur == next)
+ break;
+ if ((next - text) > length)
+ 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++;
+ }
+}
diff --git a/pango/fonts.c b/pango/fonts.c
new file mode 100644
index 00000000..473d3936
--- /dev/null
+++ b/pango/fonts.c
@@ -0,0 +1,167 @@
+/* Pango
+ * fonts.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 "pango.h"
+
+/**
+ * pango_font_init:
+ * @font: a #PangoFont
+ *
+ * Initialize a #PangoFont structure. This should
+ * only be called from the "new" routine of code which
+ * is implementing a "subclass" of #PangoFont
+ */
+void
+pango_font_init (PangoFont *font)
+{
+ g_return_if_fail (font != NULL);
+
+ g_datalist_init (&font->data);
+ font->ref_count = 1;
+}
+
+/**
+ * pango_font_ref:
+ * @font: a #PangoFont
+ *
+ * Increase the reference count of a #PangoFont.
+ */
+void
+pango_font_ref (PangoFont *font)
+{
+ g_return_if_fail (font != NULL);
+
+ font->ref_count++;
+}
+
+
+/**
+ * pango_font_unref:
+ * @font: a #PangoFont
+ *
+ * Decrease the reference count of a #PangoFont.
+ * if the result is zero, destroy the font
+ * and free the associated memory.
+ */
+void
+pango_font_unref (PangoFont *font)
+{
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (font->ref_count > 0);
+
+ font->ref_count--;
+ if (font->ref_count == 0)
+ {
+ g_datalist_clear (&font->data);
+ font->klass->destroy (font);
+ }
+}
+
+/**
+ * pango_font_set_data:
+ * @font: a #PangoCFont
+ * @key: a string identifying the type of user data.
+ * @data: the data to store. If %NULL, the current
+ * data for the key will be removed.
+ * @destroy_func: a function to call when the data is no
+ * longer stored, either because the font has
+ * been destroyed, or because the data has
+ * been replaced. This can be %NULL, in which
+ * case no function will be called.
+ *
+ * Associate user data, tagged with a string id, with a particular
+ * font.
+ */
+void
+pango_font_set_data (PangoFont *font,
+ gchar *key,
+ gpointer data,
+ GDestroyNotify destroy_func)
+{
+ g_datalist_set_data_full (&font->data, key, data, destroy_func);
+}
+
+/**
+ * pango_font_get_data:
+ * @font: a #PangoCFont
+ * @key: a string identifying the type of user data.
+ *
+ * Look up user data tagged with a particular key.
+ *
+ * Returns the data, or NULL if that key does not exist.
+ */
+gpointer
+pango_font_get_data (PangoFont *font,
+ gchar *key)
+{
+ return g_datalist_get_data (&font->data, key);
+}
+
+/**
+ * pango_cfont_init:
+ * @font: a #PangoCFont
+ *
+ * Initialize a #PangoCFont structure. This should
+ * only be called from the "new" routine of code which
+ * is implementing a "subclass" of #PangoCFont
+ */
+void
+pango_cfont_init (PangoCFont *font)
+{
+ g_return_if_fail (font != NULL);
+
+ font->ref_count = 1;
+}
+
+/**
+ * pango_cfont_ref:
+ * @font: a #PangoCFont
+ *
+ * Increase the reference count of a #GScripCFont.
+ */
+void
+pango_cfont_ref (PangoCFont *font)
+{
+ g_return_if_fail (font != NULL);
+
+ font->ref_count++;
+}
+
+/**
+ * pango_cfont_unref:
+ * @font: a #PangoCFont
+ *
+ * Decrease the reference count of a #PangoXFont.
+ * if the result is zero, destroy the font component
+ * and free the associated memory.
+ */
+void
+pango_cfont_unref (PangoCFont *font)
+{
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (font->ref_count > 0);
+
+ font->ref_count--;
+ if (font->ref_count == 0)
+ font->klass->destroy (font);
+}
+
+
diff --git a/pango/glyphstring.c b/pango/glyphstring.c
new file mode 100644
index 00000000..d965ceb8
--- /dev/null
+++ b/pango/glyphstring.c
@@ -0,0 +1,106 @@
+/* Pango
+ * glyphstring.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 <glib.h>
+#include <pango.h>
+
+/**
+ * pango_glyph_string_new:
+ *
+ * Create a new PangoGlyphString.
+ *
+ * Returns the new PangoGlyphString
+ */
+PangoGlyphString *
+pango_glyph_string_new (void)
+{
+ PangoGlyphString *string = g_new (PangoGlyphString, 1);
+
+ string->num_glyphs = 0;
+ string->space = 0;
+ string->glyphs = NULL;
+ string->geometry = NULL;
+ string->attrs = NULL;
+ string->log_clusters = NULL;
+
+ return string;
+}
+
+/**
+ * pango_glyph_string_set_size:
+ * @string: a PangoGlyphString.
+ * @new_len: the new length of the string.
+ *
+ * Resize a glyph string to the given length.
+ */
+void
+pango_glyph_string_set_size (PangoGlyphString *string, gint new_len)
+{
+ g_return_if_fail (new_len >= 0);
+
+ while (new_len > string->space)
+ {
+ if (string->space == 0)
+ string->space = 1;
+ else
+ string->space *= 2;
+
+ if (string->space < 0)
+ string->space = G_MAXINT;
+ }
+
+ string->glyphs = g_realloc (string->glyphs, string->space * sizeof (PangoGlyph));
+ string->geometry = g_realloc (string->geometry, string->space * sizeof (PangoGlyphGeometry));
+ string->attrs = g_realloc (string->attrs, string->space * sizeof (PangoGlyphVisAttr));
+ string->log_clusters = g_realloc (string->log_clusters, string->space * sizeof (gint));
+ string->num_glyphs = new_len;
+}
+
+/**
+ * pango_glyph_string_free:
+ * @string: a PangoGlyphString.
+ *
+ * Free a glyph string and associated storage.
+ */
+void
+pango_glyph_string_free (PangoGlyphString *string)
+{
+ int i;
+ PangoCFont *last_cfont = NULL;
+
+ for (i=0; i<string->num_glyphs; i++)
+ {
+ if (last_cfont && string->glyphs[i].font != last_cfont)
+ {
+ pango_cfont_unref (last_cfont);
+ last_cfont = string->glyphs[i].font;
+ }
+ }
+
+ if (last_cfont)
+ pango_cfont_unref (last_cfont);
+
+ g_free (string->glyphs);
+ g_free (string->geometry);
+ g_free (string->attrs);
+ g_free (string->log_clusters);
+ g_free (string);
+}
diff --git a/pango/gunicode.h b/pango/gunicode.h
new file mode 100644
index 00000000..6d089880
--- /dev/null
+++ b/pango/gunicode.h
@@ -0,0 +1,21 @@
+/* Pango
+ * gunicode.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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.
+ */
+
diff --git a/pango/itemize.c b/pango/itemize.c
new file mode 100644
index 00000000..bc7c9bd8
--- /dev/null
+++ b/pango/itemize.c
@@ -0,0 +1,234 @@
+/* Pango
+ * itemize.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 <fribidi/fribidi.h>
+#include <unicode.h>
+#include "pango.h"
+#include "iconv.h"
+#include "utils.h"
+#include "modules.h"
+
+static void add_engines (PangoContext *context,
+ gchar *text,
+ gint length,
+ PangoLangRange *lang_info,
+ gint n_langs,
+ gboolean force_exact,
+ PangoEngineInfo **shape_engines,
+ PangoEngineInfo **lang_engines);
+
+/**
+ * pango_itemize:
+ * @context: a structure holding information that affects
+ the itemization process.
+ * @text: the text to itemize.
+ * @length: the number of bytes (not characters) in text.
+ * This must be >= 0.
+ * @lang_info: an array of language tagging information.
+ * @n_langs: the number of elements in @lang_info.
+ *
+ * Breaks a piece of text into segments with consistent
+ * directional level and shaping engine.
+ *
+ * Returns a GList of PangoItem structures.
+ */
+GList *
+pango_itemize (PangoContext *context,
+ gchar *text,
+ gint length,
+ PangoLangRange *lang_info,
+ gint n_langs)
+{
+ guint16 *text_ucs2;
+ gint n_chars;
+ guint8 *embedding_levels;
+ FriBidiCharType base_dir;
+ gint i;
+ PangoItem *item;
+ char *p, *next;
+ GList *result = NULL;
+
+ PangoEngineInfo **shape_engines;
+ PangoEngineInfo **lang_engines;
+
+ g_return_val_if_fail (context != NULL, NULL);
+ g_return_val_if_fail (text != NULL, NULL);
+ g_return_val_if_fail (length >= 0, NULL);
+
+
+ if (context->direction == PANGO_DIRECTION_RTL)
+ base_dir = FRIBIDI_TYPE_RTL;
+ else
+ base_dir = FRIBIDI_TYPE_LTR;
+
+ if (length == 0)
+ return NULL;
+
+ /* First, apply the bidirectional algorithm to break
+ * the text into directional runs.
+ */
+ text_ucs2 = _pango_utf8_to_ucs2 (text, length);
+ if (!text_ucs2)
+ return NULL;
+
+ n_chars = unicode_strlen (text, length);
+ embedding_levels = g_new (guint8, n_chars);
+
+ /* Storing these as ranges would be a lot more efficient,
+ * but also more complicated... we take the simple
+ * approach for now.
+ */
+ shape_engines = g_new0 (PangoEngineInfo *, n_chars);
+ lang_engines = g_new0 (PangoEngineInfo *, n_chars);
+
+ fribidi_log2vis_get_embedding_levels (text_ucs2, n_chars, &base_dir,
+ embedding_levels);
+
+ /* Now, make shaping-engine affilitations for characters in
+ * each run that have high-affinity. This means that there
+ * is a shaping engine specific to the current
+ * language/character pair.
+ */
+
+ add_engines (context, text, length, lang_info, n_langs,
+ TRUE, shape_engines, lang_engines);
+
+ /* Fill in low-affinity shaping-engine affiliations for
+ * remainder of characters.
+ */
+
+ add_engines (context, text, length, lang_info, n_langs,
+ FALSE, shape_engines, lang_engines);
+
+ /* Make a GList of PangoItems out of the above results
+ */
+
+ item = NULL;
+ p = text;
+ for (i=0; i<n_chars; i++)
+ {
+ next = unicode_next_utf8 (p);
+
+ if (i == 0 ||
+ embedding_levels[i] != embedding_levels[i-1] ||
+ shape_engines[i] != shape_engines[i-1] ||
+ lang_engines[i] != lang_engines[i-1])
+ {
+ if (item)
+ result = g_list_prepend (result, item);
+ item = g_new (PangoItem, 1);
+ item->offset = p - text;
+ item->num_chars = 0;
+ item->analysis.level = embedding_levels[i];
+
+ if (shape_engines[i])
+ item->analysis.shape_engine = (PangoEngineShape *)_pango_load_engine (shape_engines[i]->id);
+ else
+ item->analysis.shape_engine = NULL;
+
+ if (lang_engines[i])
+ item->analysis.lang_engine = (PangoEngineLang *)_pango_load_engine (lang_engines[i]->id);
+ else
+ item->analysis.lang_engine = NULL;
+ }
+
+ item->length = (next - text) - item->offset;
+ item->num_chars++;
+ p = next;
+ }
+
+ if (item)
+ result = g_list_prepend (result, item);
+
+ g_free (text_ucs2);
+
+ return g_list_reverse (result);
+}
+
+static void
+add_engines (PangoContext *context,
+ gchar *text,
+ gint length,
+ PangoLangRange *lang_info,
+ gint n_langs,
+ gboolean force_exact,
+ PangoEngineInfo **shape_engines,
+ PangoEngineInfo **lang_engines)
+{
+ char *pos;
+ char *last_lang = NULL;
+ gint n_chars;
+ PangoMap *shape_map = NULL;
+ PangoMap *lang_map = NULL;
+ GUChar4 wc;
+ int i, j;
+
+ n_chars = unicode_strlen (text, length);
+
+ pos = text;
+ last_lang = NULL;
+ for (i=0, j=0; i<n_chars; i++)
+ {
+ char *lang;
+ PangoSubmap *submap;
+ PangoMapEntry *entry;
+
+ while (j < n_langs && lang_info[j].start < pos - text)
+ j++;
+
+ if (j < n_langs && (pos - text) < lang_info[j].start + lang_info[j].length)
+ lang = lang_info[j].lang;
+ else
+ lang = context->lang;
+
+ if (last_lang != lang ||
+ last_lang == 0 || lang == 0 ||
+ strcmp (lang, last_lang) != 0)
+ {
+ lang_map = _pango_find_map (lang, PANGO_ENGINE_TYPE_LANG,
+ PANGO_RENDER_TYPE_NONE);
+ shape_map = _pango_find_map (lang, PANGO_ENGINE_TYPE_SHAPE,
+ context->render_type);
+ last_lang = lang;
+ }
+
+ pos = unicode_get_utf8 (pos, &wc);
+
+ if (!lang_engines[i])
+ {
+ submap = &lang_map->submaps[wc / 256];
+ entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
+
+ if (entry->info && (!force_exact || entry->is_exact))
+ lang_engines[i] = entry->info;
+ }
+
+ if (!shape_engines[i])
+ {
+ submap = &shape_map->submaps[wc / 256];
+ entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
+
+ if (entry->info && (!force_exact || entry->is_exact))
+ shape_engines[i] = entry->info;
+ }
+ }
+}
+
diff --git a/pango/mapping.c b/pango/mapping.c
new file mode 100644
index 00000000..bd0cb3de
--- /dev/null
+++ b/pango/mapping.c
@@ -0,0 +1,275 @@
+/* Pango
+ * itemize.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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.
+ */
+
+/* The initial implementation here is script independent,
+ * but it might actually need to be virtualized into the
+ * rendering modules. Otherwise, we probably will end up
+ * enforcing unnatural cursor behavior for some languages.
+ *
+ * The only distinction that Uniscript makes is whether
+ * cursor positioning is allowed within clusters or not.
+ */
+
+#include <pango.h>
+#include <unicode.h>
+
+/**
+ * pango_cp_to_x:
+ * @text: the text for the run
+ * @length: the number of bytes (not characters) in @text.
+ * @analysis: the analysis information return from pango_itemize()
+ * @glyphs: the glyphs return from pango_shape()
+ * @char_pos: the character position
+ * @trailing: whether we should compute the result for the beginning
+ * or end of the character (or cluster - the decision
+ * for which may be script dependent).
+ * @x_pos: location to store result
+ *
+ * Converts from character position to x position. (X position
+ * is measured from the left edge of the run)
+ */
+
+void
+pango_cp_to_x (gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs,
+ gint char_pos,
+ gboolean trailing,
+ gint *x_pos)
+{
+ gint i;
+ gint start_xpos = 0;
+ gint end_xpos = 0;
+ gint width = 0;
+
+ gint start_char = -1;
+ gint end_char = -1;
+
+ g_return_if_fail (glyphs != NULL);
+ g_return_if_fail (length >= 0);
+ g_return_if_fail (length == 0 || text != NULL);
+
+ if (!x_pos) /* Allow the user to do the useless */
+ return;
+
+ if (glyphs->num_glyphs == 0)
+ {
+ *x_pos = 0;
+ return;
+ }
+
+ /* Calculate the starting and ending character positions
+ * and x positions for the cluster
+ */
+ if (analysis->level % 2) /* Right to left */
+ {
+ for (i = glyphs->num_glyphs - 1; i >= 0; i--)
+ width += glyphs->geometry[i].width;
+
+ for (i = glyphs->num_glyphs - 1; i >= 0; i--)
+ {
+ if (glyphs->log_clusters[i] > char_pos)
+ {
+ end_char = glyphs->log_clusters[i];
+ end_xpos = width;
+ break;
+ }
+
+ if (start_char == -1 || glyphs->log_clusters[i] != start_char)
+ {
+ start_char = glyphs->log_clusters[i];
+ start_xpos = width;
+ }
+
+ width -= glyphs->geometry[i].width;
+ }
+ }
+ else /* Left to right */
+ {
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ if (glyphs->log_clusters[i] > char_pos)
+ {
+ end_char = glyphs->log_clusters[i];
+ end_xpos = width;
+ break;
+ }
+
+ if (start_char == -1 || glyphs->log_clusters[i] != start_char)
+ {
+ start_char = glyphs->log_clusters[i];
+ start_xpos = width;
+ }
+
+ width += glyphs->geometry[i].width;
+ }
+ }
+
+ /* We need the character index of one past the end of the
+ * string, and so we have to recalculate the entire length
+ * of the string...
+ */
+ if (end_char == -1)
+ {
+ end_char = unicode_strlen (text, length);
+ end_xpos = (analysis->level % 2) ? 0 : width;
+ }
+
+ /* Now interpolate the result. For South Asian languages
+ * we actually shouldn't iterpolate
+ */
+
+ if (trailing)
+ char_pos += 1;
+
+ *x_pos = (((double)(end_char - char_pos)) * start_xpos +
+ ((double)(char_pos - start_char)) * end_xpos) /
+ (end_char - start_char);
+}
+
+/**
+ * pango_x_to_cp:
+ * @text: the text for the run
+ * @length: the number of bytes (not characters) in text.
+ * @analysis: the analysis information return from pango_itemize()
+ * @glyphs: the glyphs return from pango_shape()
+ * @x_pos: location to store the returned x character position
+ * @char_pos: location to store calculated character position.
+ * @trailing: location to store a integer indicating where
+ * in the cluster the user clicked. If the script
+ * allows positioning within the cluster, it is either
+ * 0 or 1; otherwise it is either 0 or the number
+ * of characters in the cluster. In either case
+ * 0 represents the trailing edge of the cluster.
+ *
+ * Converts from x position to x character. (X position
+ * is measured from the left edge of the run)
+ */
+void
+pango_x_to_cp (gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs,
+ gint x_pos,
+ gint *char_pos,
+ gint *trailing)
+{
+ gint i;
+ gint start_xpos = 0;
+ gint end_xpos = 0;
+ gint width = 0;
+
+ gint start_char = -1;
+ gint end_char = -1;
+
+ gboolean found = FALSE;
+
+ /* Find the cluster containing the position */
+
+ width = 0;
+
+ if (analysis->level % 2) /* Right to left */
+ {
+ for (i = glyphs->num_glyphs - 1; i >= 0; i--)
+ width += glyphs->geometry[i].width;
+
+ for (i = glyphs->num_glyphs - 1; i >= 0; i--)
+ {
+ if (start_char == -1 || glyphs->log_clusters[i] != start_char)
+ {
+ if (found)
+ {
+ end_char = glyphs->log_clusters[i];
+ end_xpos = width;
+ break;
+ }
+ else
+ {
+ start_char = glyphs->log_clusters[i];
+ start_xpos = width;
+ }
+ }
+
+ width -= glyphs->geometry[i].width;
+
+ if (width <= x_pos && x_pos < width + glyphs->geometry[i].width)
+ found = TRUE;
+ }
+ }
+ else /* Left to right */
+ {
+ for (i = 0; i < glyphs->num_glyphs; i++)
+ {
+ if (start_char == -1 || glyphs->log_clusters[i] != start_char)
+ {
+ if (found)
+ {
+ end_char = glyphs->log_clusters[i];
+ end_xpos = width;
+ break;
+ }
+ else
+ {
+ start_char = glyphs->log_clusters[i];
+ start_xpos = width;
+ }
+ }
+
+ if (width <= x_pos && x_pos < width + glyphs->geometry[i].width)
+ found = TRUE;
+
+ width += glyphs->geometry[i].width;
+ }
+ }
+
+ /* We need the character index of one past the end of the
+ * string, and so we have to recalculate the entire length
+ * of the string...
+ */
+ if (end_char == -1)
+ {
+ end_char = unicode_strlen (text, length);
+ end_xpos = (analysis->level % 2) ? 0 : width;
+ }
+
+ if (start_xpos == end_xpos)
+ {
+ if (char_pos)
+ *char_pos = start_char;
+ if (trailing)
+ trailing = 0;
+ }
+ else
+ {
+ double cp = (((double)(end_xpos - x_pos)) * start_char +
+ ((double)(x_pos - start_xpos)) * end_char) /
+ (end_xpos - start_xpos);
+
+ if (char_pos)
+ *char_pos = (int)cp;
+ if (trailing)
+ *trailing = (cp - (int)cp) > 0.5 ? 1 : 0;
+ }
+}
+
+
+
diff --git a/pango/modules.c b/pango/modules.c
new file mode 100644
index 00000000..0016df1f
--- /dev/null
+++ b/pango/modules.c
@@ -0,0 +1,409 @@
+/* Pango
+ * modules.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gmodule.h>
+#include <pango.h>
+
+#include "modules.h"
+#include "utils.h"
+
+typedef struct _PangoMapInfo PangoMapInfo;
+typedef struct _PangoEnginePair PangoEnginePair;
+
+struct _PangoMapInfo
+{
+ gchar *lang;
+ gchar *engine_type;
+ gchar *render_type;
+};
+
+struct _PangoEnginePair
+{
+ gchar *module;
+ PangoEngineInfo info;
+};
+
+GList *engines;
+
+static PangoMap *build_map (PangoMapInfo *info);
+static void read_modules (void);
+static guint map_info_hash (const PangoMapInfo *map);
+static gboolean map_info_equal (const PangoMapInfo *map_a,
+ const PangoMapInfo *map_b);
+
+PangoMap *
+_pango_find_map (gchar *lang,
+ gchar *engine_type,
+ gchar *render_type)
+{
+ PangoMapInfo map_info;
+ PangoMap *map;
+
+ static GHashTable *map_hash = NULL;
+
+ if (!map_hash)
+ map_hash = g_hash_table_new ((GHashFunc)map_info_hash,
+ (GCompareFunc)map_info_equal);
+
+ map_info.lang = lang;
+ map_info.engine_type = engine_type;
+ map_info.render_type = render_type;
+
+ map = g_hash_table_lookup (map_hash, &map_info);
+ if (!map)
+ {
+ PangoMapInfo *new_info = g_new (PangoMapInfo, 1);
+ *new_info = map_info;
+
+ map = build_map (new_info);
+ g_hash_table_insert (map_hash, new_info, map);
+ }
+
+ return map;
+}
+
+PangoEngine *
+_pango_load_engine (gchar *id)
+{
+ GList *tmp_list;
+
+ read_modules();
+
+ tmp_list = engines;
+ while (tmp_list)
+ {
+ PangoEnginePair *pair = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (!strcmp (pair->info.id, id))
+ {
+ GModule *module;
+ PangoEngine *(*load) (const gchar *id);
+ PangoEngine *engine;
+
+ module = g_module_open (pair->module, 0);
+ if (!module)
+ {
+ fprintf(stderr, "Cannot load module %s: %s\n",
+ pair->module, g_module_error());
+ return NULL;
+ }
+
+ g_module_symbol (module, "script_engine_load", (gpointer)&load);
+ if (!load)
+ {
+ fprintf(stderr, "cannot retrieve script_engine_load from %s: %s\n",
+ pair->module, g_module_error());
+ g_module_close (module);
+ return NULL;
+ }
+
+ engine = (*load) (id);
+
+ return engine;
+ }
+ }
+
+ return NULL;
+}
+
+
+static guint
+map_info_hash (const PangoMapInfo *map)
+{
+ return g_str_hash (map->lang) |
+ g_str_hash (map->engine_type) |
+ g_str_hash (map->render_type);
+}
+
+static gboolean
+map_info_equal (const PangoMapInfo *map_a, const PangoMapInfo *map_b)
+{
+ return (strcmp (map_a->lang, map_b->lang) == 0 &&
+ strcmp (map_a->engine_type, map_b->engine_type) == 0 &&
+ strcmp (map_a->render_type, map_b->render_type) == 0);
+}
+
+static char *
+readline(FILE *file)
+{
+ static GString *bufstring = NULL;
+ int c;
+
+ if (!bufstring)
+ bufstring = g_string_new (NULL);
+ else
+ g_string_truncate (bufstring, 0);
+
+ while ((c = getc(file)) != EOF)
+ {
+ g_string_append_c (bufstring, c);
+ if (c == '\n')
+ break;
+ }
+
+ if (bufstring->len == 0)
+ return NULL;
+ else
+ return g_strdup (bufstring->str);
+}
+
+static char *
+my_strdupn (char *p, gint n)
+{
+ gchar *result;
+
+ if (n == 0)
+ return NULL;
+
+ result = g_malloc (n + 1);
+ strncpy (result, p, n);
+ result[n] = '\0';
+
+ return result;
+}
+
+static void
+read_modules (void)
+{
+ FILE *module_file;
+ static gboolean init = FALSE;
+ char *line;
+
+ if (init)
+ return;
+ else
+ init = TRUE;
+
+ module_file = fopen ("pango.modules", "r");
+ if (!module_file)
+ {
+ fprintf(stderr, "Cannot load module file!\n");
+ return; /* FIXME: Error */
+ }
+
+ engines = NULL;
+ while ((line = readline (module_file)))
+ {
+ PangoEnginePair *pair = g_new (PangoEnginePair, 1);
+ PangoEngineRange *range;
+ GList *ranges;
+ GList *tmp_list;
+ char *p, *q;
+ int i;
+ int start;
+ int end;
+
+ p = line;
+ q = line;
+ ranges = NULL;
+
+ /* Break line into words on whitespace */
+ i = 0;
+ while (1)
+ {
+ if (!*p || isspace(*p))
+ {
+ switch (i)
+ {
+ case 0:
+ pair->module = my_strdupn (q, p-q);
+ break;
+ case 1:
+ pair->info.id = my_strdupn (q, p-q);
+ break;
+ case 2:
+ pair->info.engine_type = my_strdupn (q, p-q);
+ break;
+ case 3:
+ pair->info.render_type = my_strdupn (q, p-q);
+ break;
+ default:
+ range = g_new (PangoEngineRange, 1);
+ if (sscanf(q, "%d-%d:", &start, &end) != 2)
+ {
+ fprintf(stderr, "Error reading pango.modules");
+ return;
+ }
+ q = strchr (q, ':');
+ if (!q)
+ {
+ fprintf(stderr, "Error reading pango.modules");
+ return;
+ }
+ q++;
+ range->start = start;
+ range->end = end;
+ range->langs = my_strdupn (q, p-q);
+
+ ranges = g_list_prepend (ranges, range);
+ }
+
+ i++;
+
+ do
+ p++;
+ while (*p && isspace(*p));
+
+ if (!*p)
+ break;
+
+ q = p;
+ }
+ else
+ p++;
+ }
+
+ if (i<3)
+ {
+ fprintf(stderr, "Error reading pango.modules");
+ return;
+ }
+
+ ranges = g_list_reverse (ranges);
+ pair->info.n_ranges = g_list_length (ranges);
+ pair->info.ranges = g_new (PangoEngineRange, pair->info.n_ranges);
+
+ tmp_list = ranges;
+ for (i=0; i<pair->info.n_ranges; i++)
+ {
+ pair->info.ranges[i] = *(PangoEngineRange *)tmp_list->data;
+ tmp_list = tmp_list->next;
+ }
+
+ g_list_foreach (ranges, (GFunc)g_free, NULL);
+ g_list_free (ranges);
+ g_free (line);
+
+ engines = g_list_prepend (engines, pair);
+ }
+ engines = g_list_reverse (engines);
+}
+
+static void
+set_entry (PangoMapEntry *entry, gboolean is_exact, PangoEngineInfo *info)
+{
+ if ((is_exact && !entry->is_exact) ||
+ !entry->info)
+ {
+ entry->is_exact = is_exact;
+ entry->info = info;
+ }
+}
+
+static PangoMap *
+build_map (PangoMapInfo *info)
+{
+ GList *tmp_list;
+ int i, j;
+ PangoMap *map;
+
+ read_modules();
+
+ map = g_new (PangoMap, 1);
+ for (i=0; i<256; i++)
+ {
+ map->submaps[i].is_leaf = TRUE;
+ map->submaps[i].d.entry.info = NULL;
+ map->submaps[i].d.entry.is_exact = FALSE;
+ }
+
+ tmp_list = engines;
+ while (tmp_list)
+ {
+ PangoEnginePair *pair = tmp_list->data;
+ tmp_list = tmp_list->next;
+
+ if (strcmp (pair->info.engine_type, info->engine_type) == 0 &&
+ strcmp (pair->info.render_type, info->render_type) == 0)
+ {
+ int submap;
+
+ for (i=0; i<pair->info.n_ranges; i++)
+ {
+ gchar **langs;
+ gboolean is_exact = FALSE;
+
+ if (pair->info.ranges[i].langs)
+ {
+ langs = g_strsplit (pair->info.ranges[i].langs, ";", -1);
+ for (j=0; langs[j]; j++)
+ if (strcmp (langs[j], "*") == 0 ||
+ strcmp (langs[j], info->lang) == 0)
+ {
+ is_exact = TRUE;
+ break;
+ }
+ g_strfreev (langs);
+ }
+
+ for (submap = pair->info.ranges[i].start / 256;
+ submap <= pair->info.ranges[i].end / 256;
+ submap ++)
+ {
+ GUChar4 start;
+ GUChar4 end;
+
+ if (submap == pair->info.ranges[i].start / 256)
+ start = pair->info.ranges[i].start % 256;
+ else
+ start = 0;
+
+ if (submap == pair->info.ranges[i].end / 256)
+ end = pair->info.ranges[i].end % 256;
+ else
+ end = 255;
+
+ if (map->submaps[submap].is_leaf &&
+ start == 0 && end == 255)
+ {
+ set_entry (&map->submaps[submap].d.entry,
+ is_exact, &pair->info);
+ }
+ else
+ {
+ if (map->submaps[submap].is_leaf)
+ {
+ map->submaps[submap].is_leaf = FALSE;
+ map->submaps[submap].d.leaves = g_new (PangoMapEntry, 256);
+ for (j=0; j<256; j++)
+ {
+ map->submaps[submap].d.leaves[j].info = NULL;
+ map->submaps[submap].d.leaves[j].is_exact = FALSE;
+ }
+ }
+
+ for (j=start; j<=end; j++)
+ set_entry (&map->submaps[submap].d.leaves[j],
+ is_exact, &pair->info);
+
+ }
+ }
+ }
+ }
+ }
+
+ return map;
+}
diff --git a/pango/modules.h b/pango/modules.h
new file mode 100644
index 00000000..14617461
--- /dev/null
+++ b/pango/modules.h
@@ -0,0 +1,55 @@
+/* Pango
+ * modules.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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.
+ */
+
+#ifndef __MODULES_H__
+#define __MODULES_H__
+
+typedef struct _PangoMap PangoMap;
+typedef struct _PangoSubmap PangoSubmap;
+typedef struct _PangoMapEntry PangoMapEntry;
+
+struct _PangoMapEntry
+{
+ PangoEngineInfo *info;
+ gboolean is_exact;
+};
+
+struct _PangoSubmap
+{
+ gboolean is_leaf;
+ union {
+ PangoMapEntry entry;
+ PangoMapEntry *leaves;
+ } d;
+};
+
+struct _PangoMap
+{
+ gint n_submaps;
+ PangoSubmap submaps[256];
+};
+
+PangoMap *_pango_find_map (gchar *lang,
+ gchar *engine_type,
+ gchar *render_type);
+PangoEngine *_pango_load_engine (gchar *id);
+
+#endif /* __MODULES_H__ */
diff --git a/pango/pango.h b/pango/pango.h
new file mode 100644
index 00000000..0b375a96
--- /dev/null
+++ b/pango/pango.h
@@ -0,0 +1,339 @@
+/* Pango
+ * pango.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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.
+ */
+
+/* The API here is based fairly closely on Microsoft's Uniscript
+ * API. Differences here:
+ *
+ * - Memory management is more convenient (Pango handles
+ * all buffer reallocation)
+ * - Unicode strings are represented in UTF-8
+ * - Representation of fonts and glyphs is abstracted to be
+ * rendering-system dependent.
+ */
+
+#ifndef __PANGO_H__
+#define __PANGO_H__
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct _PangoAnalysis PangoAnalysis;
+typedef struct _PangoItem PangoItem;
+typedef struct _PangoContext PangoContext;
+typedef struct _PangoLangRange PangoLangRange;
+typedef struct _PangoLogAttr PangoLogAttr;
+
+typedef struct _PangoFont PangoFont;
+typedef struct _PangoFontClass PangoFontClass;
+typedef struct _PangoCFont PangoCFont;
+typedef struct _PangoCFontClass PangoCFontClass;
+
+typedef struct _PangoGlyph PangoGlyph;
+typedef struct _PangoGlyphGeometry PangoGlyphGeometry;
+typedef struct _PangoGlyphVisAttr PangoGlyphVisAttr;
+typedef struct _PangoGlyphString PangoGlyphString;
+
+typedef struct _PangoEngineInfo PangoEngineInfo;
+typedef struct _PangoEngineRange PangoEngineRange;
+typedef struct _PangoEngine PangoEngine;
+typedef struct _PangoEngineLang PangoEngineLang;
+typedef struct _PangoEngineShape PangoEngineShape;
+
+/* 64'ths of a point - 1/4608 in, 5.51 * 10^-5 in. */
+typedef guint32 PangoGlyphUnit;
+
+/* Information about a segment of text with a consistent
+ * shaping/language engine and bidirectional level
+ */
+struct _PangoAnalysis {
+ PangoEngineShape *shape_engine;
+ PangoEngineLang *lang_engine;
+ guint8 level;
+};
+
+struct _PangoItem {
+ gint offset;
+ gint length;
+ gint num_chars;
+ PangoAnalysis analysis;
+};
+
+/* Sort of like a GC - application set information about how
+ * to handle scripts
+ */
+
+typedef enum {
+ PANGO_DIRECTION_LTR,
+ PANGO_DIRECTION_RTL,
+ PANGO_DIRECTION_TTB
+} PangoDirection;
+
+struct _PangoContext {
+ gchar *lang;
+ gchar *render_type;
+ PangoDirection direction;
+};
+
+/* Language tagging information
+ */
+struct _PangoLangRange
+{
+ gint start;
+ gint length;
+ gchar *lang;
+};
+
+/* Break a string of Unicode characters into segments with
+ * consistent shaping/language engine and bidrectional level.
+ * Returns a GList of PangoItem's
+ */
+GList *pango_itemize (PangoContext *context,
+ gchar *text,
+ gint length,
+ PangoLangRange *lang_info,
+ gint n_langs);
+
+/* Logical attributes of a character
+ */
+struct _PangoLogAttr {
+ guint is_break : 1; /* Break in front of character */
+ guint is_white : 1;
+ guint is_char_stop : 1;
+ guint is_word_stop : 1;
+ /* Uniscript has is_invalid */
+};
+
+/* Determine information about cluster/word/line breaks in a string
+ * of Unicode text.
+ */
+void pango_break (gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs);
+
+/*
+ * FONT OPERATIONS
+ */
+
+/* This structure represents a logical font */
+struct _PangoFont {
+ PangoFontClass *klass;
+
+ /*< private >*/
+ gint ref_count;
+ GData *data;
+};
+
+struct _PangoFontClass {
+ void (*destroy) (PangoFont *font);
+};
+
+void pango_font_init (PangoFont *font);
+void pango_font_ref (PangoFont *font);
+void pango_font_unref (PangoFont *font);
+gpointer pango_font_get_data (PangoFont *font,
+ gchar *key);
+void pango_font_set_data (PangoFont *font,
+ gchar *key,
+ gpointer data,
+ GDestroyNotify destroy_func);
+
+/* A component of a font. The contents of this are completely
+ * rendering system dependent
+ */
+struct _PangoCFont {
+ PangoCFontClass *klass;
+
+ /*< private >*/
+ gint ref_count;
+};
+
+struct _PangoCFontClass {
+ void (*destroy) (PangoCFont *cfont);
+};
+
+void pango_cfont_init (PangoCFont *font);
+void pango_cfont_ref (PangoCFont *font);
+void pango_cfont_unref (PangoCFont *font);
+
+
+/*
+ * GLYPH STORAGE
+ */
+
+/* A index of a glyph into a PangoCFont. Rendering system dependent
+ */
+typedef guint32 PangoGlyphIndex;
+
+/* A single glyph
+ */
+struct _PangoGlyph
+{
+ PangoGlyphIndex glyph;
+ PangoCFont *font;
+};
+
+/* Positioning information about a glyph
+ */
+struct _PangoGlyphGeometry
+{
+ PangoGlyphUnit width;
+ PangoGlyphUnit x_offset;
+ PangoGlyphUnit y_offset;
+};
+
+/* Visual attributes of a glyph
+ */
+struct _PangoGlyphVisAttr
+{
+ guint is_cluster_start : 1;
+};
+
+/* A string of glyphs with positional information and visual attributes -
+ * ready for drawing
+ */
+struct _PangoGlyphString {
+ gint num_glyphs;
+ PangoGlyph *glyphs;
+ PangoGlyphGeometry *geometry;
+ PangoGlyphVisAttr *attrs;
+
+ /* This is a memory inefficient way of representing the
+ * information here - each value gives the character index
+ * of the start of the cluster to which the glyph belongs.
+ */
+ gint *log_clusters;
+
+ /*< private >*/
+ gint space;
+};
+
+PangoGlyphString *pango_glyph_string_new (void);
+void pango_glyph_string_set_size (PangoGlyphString *string,
+ gint new_len);
+void pango_glyph_string_free (PangoGlyphString *string);
+
+/* Turn a string of characters into a string of glyphs
+ */
+void pango_shape (PangoFont *font,
+ gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs);
+
+/* [ pango_place - subsume into g_script_shape? ] */
+
+GList *pango_reorder_items (GList *logical_items);
+
+/* Take a PangoGlyphString and add justification to fill to a
+ * given width
+ */
+void pango_justify (PangoGlyphString *glyphs,
+ gint new_line_width,
+ gint min_kashida_width);
+
+/* For selection/cursor positioning - turn a character position into a
+ * X position.
+ */
+void pango_cp_to_x (gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs,
+ gint char_pos,
+ gboolean trailing,
+ gint *x_pos);
+
+
+/* For selection/cursor positioning - turn a X position into a
+ * character position
+ */
+void pango_x_to_cp (gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs,
+ gint x_pos,
+ gint *char_pos,
+ gint *trailing);
+
+/* Module API */
+
+#define PANGO_ENGINE_TYPE_LANG "PangoEngineLang"
+#define PANGO_ENGINE_TYPE_SHAPE "PangoEngineShape"
+
+#define PANGO_RENDER_TYPE_NONE "PangoRenderNone"
+
+struct _PangoEngineRange
+{
+ guint32 start;
+ guint32 end;
+ gchar *langs;
+};
+
+struct _PangoEngineInfo
+{
+ gchar *id;
+ gchar *engine_type;
+ gchar *render_type;
+ PangoEngineRange *ranges;
+ gint n_ranges;
+};
+
+struct _PangoEngine
+{
+ gchar *id;
+ gchar *type;
+ gint length;
+};
+
+struct _PangoEngineLang
+{
+ PangoEngine engine;
+ void (*script_break) (gchar *text,
+ gint len,
+ PangoAnalysis *analysis,
+ PangoLogAttr *attrs);
+};
+
+struct _PangoEngineShape {
+ PangoEngine engine;
+ void (*script_shape) (PangoFont *font,
+ gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs);
+};
+
+/* A module should export the following functions */
+
+void script_engine_list (PangoEngineInfo **engines,
+ gint *n_engines);
+PangoEngine *script_engine_load (const gchar *id);
+void script_engine_unload (PangoEngine *engine);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __PANGO_H__ */
diff --git a/pango/pangox.c b/pango/pangox.c
new file mode 100644
index 00000000..21c2d24d
--- /dev/null
+++ b/pango/pangox.c
@@ -0,0 +1,757 @@
+/* Pango
+ * gscriptx.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 <X11/Xlib.h>
+#include "pangox.h"
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+typedef struct _PangoXFont PangoXFont;
+typedef struct _XLFDInfo XLFDInfo;
+
+struct _PangoXFont {
+ PangoFont font;
+ Display *display;
+ gchar **fonts;
+ gint n_fonts;
+ GHashTable *name_hash;
+ GHashTable *xlfd_hash;
+};
+
+struct _XLFDInfo {
+ XFontStruct *font_struct;
+ PangoCFont *cfont;
+};
+
+static void pango_x_font_destroy (PangoFont *font);
+static void pango_x_cfont_destroy (PangoCFont *cfont);
+
+PangoFontClass pango_x_font_class = {
+ pango_x_font_destroy
+};
+
+PangoCFontClass pango_x_cfont_class = {
+ pango_x_cfont_destroy
+};
+
+/**
+ * pango_x_load_font:
+ * @display: the X display
+ * @spec: a comma-separated list of XLFD's
+ *
+ * Load up a logical font based on a "fontset" style
+ * text specification.
+ *
+ * Returns a new #PangoFont
+ */
+PangoFont *
+pango_x_load_font (Display *display,
+ gchar *spec)
+{
+ PangoXFont *result;
+
+ g_return_val_if_fail (display != NULL, NULL);
+ g_return_val_if_fail (spec != NULL, NULL);
+
+ result = g_new (PangoXFont, 1);
+
+ result->display = display;
+
+ pango_font_init (&result->font);
+ result->font.klass = &pango_x_font_class;
+
+ result->fonts = g_strsplit(spec, ",", -1);
+ result->n_fonts = 0;
+ while (result->fonts[result->n_fonts])
+ result->n_fonts++;
+
+ result->name_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ result->xlfd_hash = g_hash_table_new (g_str_hash, g_str_equal);
+
+ return (PangoFont *)result;
+}
+
+/**
+ * pango_x_render:
+ * @display: the X display
+ * @d: the drawable on which to draw string
+ * @gc: the graphics context
+ * @glyphs: the glyph string to draw
+ * @x: the x position of start of string
+ * @y: the y position of baseline
+ *
+ * Render a PangoGlyphString onto an X drawable
+ */
+void
+pango_x_render (Display *display,
+ Drawable d,
+ GC gc,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y)
+{
+ /* Slow initial implementation. For speed, it should really
+ * collect the characters into runs, and draw multiple
+ * characters with each XDrawString16 call.
+ */
+ XChar2b c;
+ PangoXCFont *cfont;
+ Font old_fid = None;
+ XFontStruct *fs;
+ int i;
+
+ for (i=0; i<glyphs->num_glyphs; i++)
+ {
+ c.byte1 = glyphs->glyphs[i].glyph / 256;
+ c.byte2 = glyphs->glyphs[i].glyph % 256;
+ cfont = (PangoXCFont *)glyphs->glyphs[i].font;
+ fs = cfont->font_struct;
+
+ if (fs->fid != old_fid)
+ {
+ XSetFont (display, gc, fs->fid);
+ old_fid = fs->fid;
+ }
+
+ XDrawString16 (display, d, gc,
+ x + glyphs->geometry[i].x_offset / 72,
+ y + glyphs->geometry[i].y_offset / 72,
+ &c, 1);
+
+ x += glyphs->geometry[i].width / 72;
+
+ }
+}
+
+/**
+ * pango_x_glyph_extents:
+ * @glyph: the glyph to measure
+ * @lbearing: left bearing of glyph (result)
+ * @rbearing: right bearing of glyph (result)
+ * @width: width of glyph (result)
+ * @ascent: ascent of glyph (result)
+ * @descent: descent of glyph (result)
+ * @logical_ascent: The vertical distance from the baseline to the
+ * bottom of the line above.
+ * @logical_descent: The vertical distance from the baseline to the
+ * top of the line below.
+ *
+ * Compute the measurements of a single glyph in pixels.
+ */
+void
+pango_x_glyph_extents (PangoGlyph *glyph,
+ gint *lbearing,
+ gint *rbearing,
+ gint *width,
+ gint *ascent,
+ gint *descent,
+ gint *logical_ascent,
+ gint *logical_descent)
+{
+ int index;
+
+ PangoXCFont *cfont;
+ XFontStruct *fs;
+ XCharStruct *cs;
+ XChar2b c;
+
+ c.byte1 = glyph->glyph / 256;
+ c.byte2 = glyph->glyph % 256;
+ cfont = (PangoXCFont *)glyph->font;
+ fs = cfont->font_struct;
+
+ if ((fs->min_byte1 == 0) && (fs->max_byte1 == 0))
+ index = c.byte2 - fs->min_char_or_byte2;
+ else
+ {
+ index = ((c.byte1 - fs->min_byte1) *
+ (fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1)) +
+ c.byte2 - fs->min_char_or_byte2;
+ }
+
+ if (fs->per_char)
+ cs = &fs->per_char[index];
+ else
+ cs = &fs->min_bounds;
+
+ if (lbearing)
+ *lbearing = cs->lbearing;
+ if (rbearing)
+ *rbearing = cs->rbearing;
+ if (width)
+ *width = cs->width;
+ if (ascent)
+ *ascent = cs->ascent;
+ if (descent)
+ *descent = cs->descent;
+ if (logical_ascent)
+ *logical_ascent = fs->ascent;
+ if (logical_descent)
+ *logical_descent = fs->descent;
+}
+
+/**
+ * pango_x_extents:
+ * @glyphs: the glyph string to measure
+ * @lbearing: left bearing of string (result)
+ * @rbearing: right bearing of string (result)
+ * @width: width of string (result)
+ * @ascent: ascent of string (result)
+ * @descent: descent of string (result)
+ * @logical_ascent: The vertical distance from the baseline to the
+ * bottom of the line above.
+ * @logical_descent: The vertical distance from the baseline to the
+ * top of the line below.
+ *
+ * Compute the measurements of a glyph string in pixels.
+ * The number of parameters here is clunky - it might be
+ * nicer to use structures as in XmbTextExtents.
+ */
+void
+pango_x_extents (PangoGlyphString *glyphs,
+ gint *lbearing,
+ gint *rbearing,
+ gint *width,
+ gint *ascent,
+ gint *descent,
+ gint *logical_ascent,
+ gint *logical_descent)
+{
+ int index;
+
+ PangoXCFont *cfont;
+ XFontStruct *fs;
+ XCharStruct *cs;
+ PangoGlyphGeometry *geometry;
+ XChar2b c;
+
+ int i;
+
+ int t_lbearing = 0;
+ int t_rbearing = 0;
+ int t_ascent = 0;
+ int t_descent = 0;
+ int t_logical_ascent = 0;
+ int t_logical_descent = 0;
+ int t_width = 0;
+
+ for (i=0; i<glyphs->num_glyphs; i++)
+ {
+ c.byte1 = glyphs->glyphs[i].glyph / 256;
+ c.byte2 = glyphs->glyphs[i].glyph % 256;
+ cfont = (PangoXCFont *)glyphs->glyphs[i].font;
+ fs = cfont->font_struct;
+
+ if ((fs->min_byte1 == 0) && (fs->min_byte1 == 0))
+ index = c.byte2 - fs->min_char_or_byte2;
+ else
+ {
+ index = ((c.byte1 - fs->min_byte1) *
+ (fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1)) +
+ c.byte2 - fs->min_char_or_byte2;
+ }
+
+ if (fs->per_char)
+ cs = &fs->per_char[index];
+ else
+ cs = &fs->min_bounds;
+
+ geometry = &glyphs->geometry[i];
+
+ if (i == 0)
+ {
+ t_lbearing = cs->lbearing - geometry->x_offset / 72;
+ t_rbearing = cs->rbearing + geometry->x_offset / 72;
+ t_ascent = cs->ascent + geometry->y_offset / 72;
+ t_descent = cs->descent - geometry->y_offset / 72;
+ t_logical_ascent = fs->ascent + geometry->y_offset / 72;
+ t_logical_descent = fs->descent - geometry->y_offset / 72;
+ }
+ else
+ {
+ t_lbearing = MAX (t_lbearing,
+ cs->lbearing - geometry->x_offset / 72 - t_width);
+ t_rbearing = MAX (t_rbearing,
+ t_width + cs->rbearing + geometry->x_offset / 72);
+ t_ascent = MAX (t_ascent, cs->ascent + geometry->y_offset / 72);
+ t_descent = MAX (t_descent, cs->descent - geometry->y_offset / 72);
+ t_logical_ascent = MAX (t_logical_ascent, fs->ascent + geometry->y_offset / 72);
+ t_logical_descent = MAX (t_logical_descent, fs->descent - geometry->y_offset / 72);
+ }
+
+ t_width += geometry->width / 72;
+ }
+
+ if (lbearing)
+ *lbearing = t_lbearing;
+ if (rbearing)
+ *rbearing = t_rbearing;
+ if (width)
+ *width = t_width;
+ if (ascent)
+ *ascent = t_ascent;
+ if (descent)
+ *descent = t_descent;
+ if (logical_ascent)
+ *logical_ascent = t_logical_ascent;
+ if (logical_descent)
+ *logical_descent = t_logical_descent;
+}
+
+/* Compare the tail of a to b */
+static gboolean
+match_end (char *a, char *b)
+{
+ size_t len_a = strlen (a);
+ size_t len_b = strlen (b);
+
+ if (len_b > len_a)
+ return FALSE;
+ else
+ return (strcmp (a + len_a - len_b, b) == 0);
+}
+
+/* Substitute in a charset into an XLFD. Return the
+ * (g_malloc'd) new name, or NULL if the XLFD cannot
+ * match the charset
+ */
+static gchar *
+name_for_charset (char *xlfd, char *charset)
+{
+ char *p;
+ char *dash_charset = g_strconcat ("-", charset, NULL);
+ char *result = NULL;
+ gint ndashes = 0;
+
+ for (p = xlfd; *p; p++)
+ if (*p == '-')
+ ndashes++;
+
+ if (ndashes == 14) /* Complete XLFD */
+ {
+ if (match_end (xlfd, "-*-*"))
+ {
+ result = g_malloc (strlen (xlfd) - 4 + strlen (dash_charset) + 1);
+ strncpy (result, xlfd, strlen (xlfd) - 4);
+ strcpy (result + strlen (xlfd) - 4, dash_charset);
+ }
+ if (match_end (xlfd, dash_charset))
+ result = g_strdup (xlfd);
+ }
+ else if (ndashes == 13)
+ {
+ if (match_end (xlfd, "-*"))
+ {
+ result = g_malloc (strlen (xlfd) - 2 + strlen (dash_charset) + 1);
+ strncpy (result, xlfd, strlen (xlfd) - 2);
+ strcpy (result + strlen (xlfd) - 2, dash_charset);
+ }
+ if (match_end (xlfd, dash_charset))
+ result = g_strdup (xlfd);
+ }
+ else
+ {
+ if (match_end (xlfd, "*"))
+ {
+ result = g_malloc (strlen (xlfd) + strlen (dash_charset) + 1);
+ strcpy (result, xlfd);
+ strcpy (result + strlen (xlfd), dash_charset);
+ }
+ if (match_end (xlfd, dash_charset))
+ result = g_strdup (xlfd);
+ }
+
+ g_free (dash_charset);
+ return result;
+}
+
+/**
+ * pango_x_load_xlfd:
+ * @font: a #PangoFont
+ * @xlfd: the XLFD of a component font to load
+ *
+ * Create a component font from a XLFD. It is assumed that
+ * the xlfd matches a font matching one of the names
+ * of @font, but this is not currently required.
+ *
+ * Returns the new #PangoXCFont
+ */
+PangoCFont *
+pango_x_load_xlfd (PangoFont *font,
+ gchar *xlfd)
+{
+ XFontStruct *fs;
+ PangoXFont *xfont = (PangoXFont *)font;
+ XLFDInfo *info;
+
+ g_return_val_if_fail (font != NULL, NULL);
+
+ info = g_hash_table_lookup (xfont->xlfd_hash, xlfd);
+ if (!info)
+ {
+ info = g_new (XLFDInfo, 1);
+ info->cfont = NULL;
+ info->font_struct = NULL;
+
+ g_hash_table_insert (xfont->xlfd_hash, g_strdup(xlfd), info);
+ }
+
+ if (!info->cfont)
+ {
+ fs = XLoadQueryFont (xfont->display, xlfd);
+ if (fs)
+ {
+ PangoXCFont *cfont = g_new (PangoXCFont, 1);
+ cfont->display = xfont->display;
+ cfont->font_struct = fs;
+ cfont->font.klass = &pango_x_cfont_class;
+
+ info->cfont = (PangoCFont *)cfont;
+
+ pango_cfont_init (info->cfont);
+ pango_cfont_ref (info->cfont);
+
+ if (info->font_struct)
+ XFreeFontInfo (NULL, info->font_struct, 1);
+
+ info->font_struct = fs;
+ }
+ }
+
+ return info->cfont;
+}
+
+static gchar **
+find_cfonts (PangoFont *font, gchar *charset)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+ gchar **cfonts;
+ int i;
+
+ cfonts = g_hash_table_lookup (xfont->name_hash, charset);
+ if (!cfonts)
+ {
+ cfonts = g_new (gchar *, xfont->n_fonts + 1);
+ for (i=0; i<xfont->n_fonts; i++)
+ {
+ char *xlfd = name_for_charset (xfont->fonts[i], charset);
+ gchar **names;
+ gint count;
+
+ cfonts[i] = NULL;
+ if (xlfd)
+ {
+ names = XListFonts (xfont->display, xlfd, 1, &count);
+ if (count > 0)
+ cfonts[i] = g_strdup (names[0]);
+
+ XFreeFontNames (names);
+ g_free (xlfd);
+ }
+ }
+
+ g_hash_table_insert (xfont->name_hash, g_strdup(charset), cfonts);
+ }
+
+ return cfonts;
+}
+
+/**
+ * pango_x_find_cfont:
+ * @font: A font from pango_x_load_font()
+ * @charset: characterset descript (last two components of XLFD)
+ *
+ * Find a component font of a #PangoFont.
+ *
+ * Returns the #PangoCFont for @charset, or NULL, if no appropriate
+ * font could be found.
+ */
+PangoCFont *
+pango_x_find_cfont (PangoFont *font,
+ gchar *charset)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+ gchar **names;
+ int i;
+
+ names = find_cfonts (font, charset);
+ for (i=0; i<xfont->n_fonts; i++)
+ if (names[i])
+ return pango_x_load_xlfd (font, names[i]);
+
+ return NULL;
+}
+
+void
+font_struct_get_ranges (Display *display,
+ XFontStruct *fs,
+ gint **ranges,
+ gint *n_ranges)
+{
+ gint i, j;
+ static Atom bounds_atom = None;
+ gint *range_buf = NULL;
+ size_t range_buf_size = 8;
+
+ if (bounds_atom == None)
+ bounds_atom = XInternAtom (display, "_XFREE86_GLYPH_RANGES", False);
+
+ j = 0;
+ for (i=0; i<fs->n_properties; i++)
+ {
+ if (fs->properties[i].name == bounds_atom)
+ {
+ char *val = XGetAtomName (display, fs->properties[i].card32);
+ char *p;
+ guint start, end;
+
+ p = val;
+ while (*p)
+ {
+ int count;
+
+ while (*p && isspace (*p))
+ p++;
+
+ count = sscanf (p, "%u_%u", &start, &end);
+
+ if (count > 0)
+ {
+ if (count == 1)
+ end = start;
+
+ if (!range_buf || (2*j+1) >= range_buf_size)
+ {
+ size_t new_size = range_buf_size * 2;
+ if (new_size < range_buf_size) /* Paranoia */
+ {
+ XFree (val);
+ *ranges = NULL;
+ *n_ranges = 0;
+
+ return;
+ }
+ range_buf_size = new_size;
+ range_buf = g_realloc (range_buf, sizeof(gint) * range_buf_size);
+ }
+
+ range_buf[2*j] = start;
+ range_buf[2*j + 1] = end;
+ j++;
+ }
+ else
+ {
+ goto error;
+ }
+
+ while (*p && !isspace (*p))
+ p++;
+ }
+
+ error:
+ XFree (val);
+ }
+
+ }
+
+ if (j > 0)
+ {
+ *n_ranges = j;
+ *ranges = g_malloc (sizeof(gint) * 2*j);
+ memcpy (*ranges, range_buf, sizeof(gint) * 2*j);
+ }
+ else
+ {
+ *n_ranges = 1;
+ *ranges = g_malloc (sizeof(gint) * 2);
+
+ (*ranges)[0] = fs->min_byte1 * 256 + fs->min_char_or_byte2;
+ (*ranges)[1] = fs->max_byte1 * 256 + fs->max_char_or_byte2;
+ }
+
+ g_free (range_buf);
+}
+
+/**
+ * pango_x_xlfd_get_ranges:
+ * @font: a #PangoFont.
+ * @xlfd: a XLFD of a component font.
+ * @ranges: location to store returned ranges.
+ * @n_ranges: location to store the number of ranges.
+ *
+ * Find the range of valid characters for a particular
+ * XLFD representing a component of the given font.
+ *
+ * Returns %TRUE if the XLFD matches a font, FALSE otherwise.
+ * in the latter case, @ranges and @n_ranges are unchanged.
+ */
+gboolean
+pango_x_xlfd_get_ranges (PangoFont *font,
+ gchar *xlfd,
+ gint **ranges,
+ gint *n_ranges)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+ gchar **names;
+ gint count;
+ XLFDInfo *info;
+
+ info = g_hash_table_lookup (xfont->xlfd_hash, xlfd);
+ if (!info)
+ {
+ info = g_new (XLFDInfo, 1);
+ info->cfont = NULL;
+ info->font_struct = NULL;
+ g_hash_table_insert (xfont->xlfd_hash, g_strdup(xlfd), info);
+ }
+
+ if (!info->font_struct)
+ {
+ names = XListFontsWithInfo (xfont->display, xlfd, 1, &count, &info->font_struct);
+
+ if (count == 0)
+ info->font_struct = NULL;
+
+ XFreeFontNames (names);
+ }
+
+ if (info->font_struct)
+ {
+ font_struct_get_ranges (xfont->display, info->font_struct, ranges, n_ranges);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * pango_x_xlfd_list_cfonts:
+ * @font: a #PangoFont.
+ * @charsets: the list of character sets to match against.
+ * @n_charsets: the number of elements in @charsets.
+ * @xlfds: location to store a pointer to an array of returned XLFDs.
+ * @n_xlfds: location to store the number of XLFDs.
+ *
+ * List all possible XLFDs that can match a particular set
+ * of character sets for the given #PangoFont. The
+ * returned values are sorted at highest priority by
+ * the order of the names in fontlist used to create
+ * the #PangoFont, and then sorted by the ordering
+ * of the character sets in @charsets.
+ *
+ */
+void
+pango_x_list_cfonts (PangoFont *font,
+ gchar **charsets,
+ gint n_charsets,
+ gchar ***xlfds,
+ gint *n_xlfds)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+
+ int i, j;
+
+ GSList *result = NULL;
+ GSList *tmp_list;
+
+ gchar ***names = g_new (gchar **, n_charsets);
+
+ *n_xlfds = 0;
+ for (j=0; j<n_charsets; j++)
+ names[j] = find_cfonts (font, charsets[j]);
+
+ for (i=0; i < xfont->n_fonts; i++)
+ for (j=0; j < n_charsets; j++)
+ if (names[j][i] != 0)
+ {
+ (*n_xlfds)++;
+ result = g_slist_prepend (result, g_strdup (names[j][i]));
+ }
+
+ result = g_slist_reverse (result);
+ *xlfds = g_new (gchar *, *n_xlfds);
+
+ tmp_list = result;
+ for (i=0; i< *n_xlfds; i++)
+ {
+ (*xlfds)[i] = tmp_list->data;
+ tmp_list = tmp_list->next;
+ }
+
+ g_slist_free (result);
+ g_free (names);
+}
+
+void
+name_hash_foreach (gpointer key, gpointer value, gpointer data)
+{
+ gchar *charset = key;
+ gchar **names = value;
+ PangoXFont *xfont = data;
+ int i;
+
+ for (i=0; i<xfont->n_fonts; i++)
+ g_free (names[i]);
+ g_free (names);
+ g_free (charset);
+}
+
+void
+xlfd_hash_foreach (gpointer key, gpointer value, gpointer data)
+{
+ gchar *xlfd = key;
+ XLFDInfo *info = value;
+
+ if (info->cfont)
+ pango_cfont_unref (info->cfont);
+ else if (info->font_struct)
+ XFreeFontInfo (NULL, info->font_struct, 1);
+
+ g_free (info);
+
+ g_free (xlfd);
+}
+
+static void
+pango_x_font_destroy (PangoFont *font)
+{
+ PangoXFont *xfont = (PangoXFont *)font;
+
+ g_hash_table_foreach (xfont->name_hash, name_hash_foreach, xfont);
+ g_hash_table_destroy (xfont->name_hash);
+
+ g_hash_table_foreach (xfont->xlfd_hash, xlfd_hash_foreach, xfont);
+ g_hash_table_destroy (xfont->xlfd_hash);
+
+ g_strfreev (xfont->fonts);
+ g_free (font);
+}
+
+static void
+pango_x_cfont_destroy (PangoCFont *font)
+{
+ PangoXCFont *xcfont = (PangoXCFont *)font;
+
+ XFreeFont (xcfont->display, xcfont->font_struct);
+
+ g_free (font);
+}
diff --git a/pango/pangox.h b/pango/pangox.h
new file mode 100644
index 00000000..731ced79
--- /dev/null
+++ b/pango/pangox.h
@@ -0,0 +1,100 @@
+/* Pango
+ * pangox.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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.
+ */
+
+#ifndef __PANGOX_H__
+#define __PANGOX_H__
+
+#include <glib.h>
+#include <pango.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <X11/Xlib.h>
+
+#define PANGO_RENDER_TYPE_X "PangoRenderX"
+
+typedef struct _PangoXCFont PangoXCFont;
+
+struct _PangoXCFont {
+ /*< private >*/
+ PangoCFont font;
+
+ /*< public >*/
+ Display *display;
+ XFontStruct *font_struct;
+};
+
+/* Calls for applications
+ */
+PangoFont *pango_x_load_font (Display *display,
+ gchar *spec);
+void pango_x_render (Display *display,
+ Drawable d,
+ GC gc,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+void pango_x_extents (PangoGlyphString *glyphs,
+ gint *lbearing,
+ gint *rbearing,
+ gint *width,
+ gint *ascent,
+ gint *descent,
+ gint *logical_ascent,
+ gint *logical_descent);
+void pango_x_glyph_extents (PangoGlyph *glyph,
+ gint *lbearing,
+ gint *rbearing,
+ gint *width,
+ gint *ascent,
+ gint *descent,
+ gint *logical_ascent,
+ gint *logical_descent);
+
+
+/* Calls for rendering modules
+ */
+PangoCFont *pango_x_find_cfont (PangoFont *font,
+ gchar *charset);
+void pango_x_list_cfonts (PangoFont *font,
+ gchar **charsets,
+ gint n_charsets,
+ gchar ***xlfds,
+ gint *n_xlfds);
+gboolean pango_x_xlfd_get_ranges (PangoFont *font,
+ gchar *xlfd,
+ gint **ranges,
+ gint *n_ranges);
+PangoCFont *pango_x_load_xlfd (PangoFont *font,
+ gchar *xlfd);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __PANGOX_H__ */
+
+
+
+
diff --git a/pango/querymodules.c b/pango/querymodules.c
new file mode 100644
index 00000000..8d643f44
--- /dev/null
+++ b/pango/querymodules.c
@@ -0,0 +1,102 @@
+/* Pango
+ * querymodules.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 <glib.h>
+#include <gmodule.h>
+#include "pango.h"
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+
+void
+query_module (GModule *module, gchar *name)
+{
+ void (*list) (PangoEngineInfo **engines, gint *n_engines);
+ PangoEngine *(*load) (const gchar *id);
+ void (*unload) (PangoEngine *engine);
+
+ if (g_module_symbol (module, "script_engine_list", (gpointer)&list) &&
+ g_module_symbol (module, "script_engine_load", (gpointer)&load) &&
+ g_module_symbol (module, "script_engine_unload", (gpointer)&unload))
+ {
+ gint i,j;
+ PangoEngineInfo *engines;
+ gint n_engines;
+
+ (*list) (&engines, &n_engines);
+
+ for (i=0; i<n_engines; i++)
+ {
+ g_print ("%s %s %s %s ", name, engines[i].id, engines[i].engine_type, engines[i].render_type);
+ for (j=0; j < engines[i].n_ranges; j++)
+ {
+ if (j != 0)
+ g_print (" ");
+ g_print ("%d-%d:%s",
+ engines[i].ranges[j].start,
+ engines[i].ranges[j].end,
+ engines[i].ranges[j].langs);
+ }
+ g_print ("\n");
+ }
+ }
+ else
+ {
+ fprintf (stderr, "%s does not export Pango module API\n", name);
+ }
+}
+
+int main (int argc, char **argv)
+{
+ char cwd[PATH_MAX];
+ int i;
+
+ getcwd (cwd, PATH_MAX);
+
+ for (i=1; i<argc; i++)
+ {
+ GModule *module;
+ gchar *tmp;
+
+ if (argv[i][0] == '/')
+ tmp = g_strdup (argv[i]);
+ else
+ tmp = g_strconcat (cwd, "/", argv[i], NULL);
+
+ module = g_module_open (tmp, G_MODULE_BIND_LAZY);
+ if (module)
+ {
+ query_module (module, tmp);
+ g_module_close (module);
+ }
+ else
+ {
+ fprintf(stderr, "Cannot load module %s: %s\n",
+ tmp, g_module_error());
+ }
+
+ g_free (tmp);
+ }
+
+ return 0;
+}
diff --git a/pango/reorder-items.c b/pango/reorder-items.c
new file mode 100644
index 00000000..bbe415b7
--- /dev/null
+++ b/pango/reorder-items.c
@@ -0,0 +1,104 @@
+/* Pango
+ * reorder-items.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 <pango.h>
+
+static GList *reorder_items_recurse (GList *items, int n_items);
+
+/**
+ * pango_reorder_items:
+ * @logical_items: a GList of #PangoItem in logical order.
+ *
+ * From a list of items in logical order and the associated
+ * directional levels, produce a list in visual order.
+ * The original list is unmodified.
+ *
+ * Returns a GList of PangoItem structures in visual order.
+ */
+GList *
+pango_reorder_items (GList *logical_items)
+{
+ return reorder_items_recurse (logical_items, g_list_length (logical_items));
+}
+
+static GList *
+reorder_items_recurse (GList *items, int n_items)
+{
+ GList *tmp_list, *level_start_node;
+ int i, level_start_i;
+ int min_level = G_MAXINT;
+ GList *result = NULL;
+
+ if (n_items == 0)
+ return NULL;
+
+ tmp_list = items;
+ for (i=0; i<n_items; i++)
+ {
+ PangoItem *item = tmp_list->data;
+
+ min_level = MIN (min_level, item->analysis.level);
+
+ tmp_list = tmp_list->next;
+ }
+
+ level_start_i = 0;
+ level_start_node = items;
+ tmp_list = items;
+ for (i=0; i<n_items; i++)
+ {
+ PangoItem *item = tmp_list->data;
+
+ if (item->analysis.level == min_level)
+ {
+ if (min_level % 2)
+ {
+ if (i > level_start_i)
+ result = g_list_concat (reorder_items_recurse (level_start_node, i - level_start_i), result);
+ result = g_list_prepend (result, item);
+ }
+ else
+ {
+ if (i > level_start_i)
+ result = g_list_concat (result, reorder_items_recurse (level_start_node, i - level_start_i));
+ result = g_list_append (result, item);
+ }
+
+ level_start_i = i + 1;
+ level_start_node = tmp_list->next;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (min_level % 2)
+ {
+ if (i > level_start_i)
+ result = g_list_concat (reorder_items_recurse (level_start_node, i - level_start_i), result);
+ }
+ else
+ {
+ if (i > level_start_i)
+ result = g_list_concat (result, reorder_items_recurse (level_start_node, i - level_start_i));
+ }
+
+ return result;
+}
diff --git a/pango/shape.c b/pango/shape.c
new file mode 100644
index 00000000..0f5efb39
--- /dev/null
+++ b/pango/shape.c
@@ -0,0 +1,48 @@
+/* Pango
+ * shape.c: Convert characters into glyphs.
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 <pango.h>
+#include "utils.h"
+
+/**
+ * pango_shape:
+ * @font: font to use for shaping
+ * @text: the text to process
+ * @length: the length (in bytes) of @text
+ * @analysis: #PangoAnalysis structure from PangoItemize
+ * @glyphs: glyph string in which to store results
+ *
+ * Given a segment of text and the corresponding
+ * #PangoAnalysis structure returned from pango_itemize(),
+ * convert the characters into glyphs. You may also pass
+ * in only a substring of the item from pango_itemize().
+ */
+void pango_shape (PangoFont *font,
+ gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
+{
+ if (analysis->shape_engine)
+ analysis->shape_engine->script_shape (font, text, length, analysis, glyphs);
+ else
+ pango_glyph_string_set_size (glyphs, 0);
+}
diff --git a/pango/utils.c b/pango/utils.c
new file mode 100644
index 00000000..d3ab9fdd
--- /dev/null
+++ b/pango/utils.c
@@ -0,0 +1,153 @@
+/* Pango
+ * utils.c:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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 "utils.h"
+#include <iconv.h>
+#include <errno.h>
+#include <unicode.h>
+
+gboolean
+_pango_utf8_iterate (gchar *cur, char **next, GUChar4 *wc_out)
+{
+ gchar *p = cur;
+ gchar c = *p;
+ GUChar4 wc;
+ gint length;
+
+ if ((c & 0x80) == 0)
+ {
+ length = 1;
+ wc = c;
+ }
+ else if ((c & 0xc0) == 0x80)
+ {
+ return FALSE;
+ }
+ else if ((c & 0xe0) == 0xc0)
+ {
+ length = 2;
+ wc = c & 0x1f;
+ }
+ else if ((c & 0xf0) == 0xe0)
+ {
+ length = 3;
+ wc = c & 0x0f;
+ }
+ else
+ return FALSE;
+
+ p++;
+ while (--length > 0)
+ {
+ if (*p == 0) /* Incomplete character */
+ {
+ if (next)
+ *next = cur;
+ if (wc_out)
+ *wc_out = 0;
+ return TRUE;
+ }
+
+ if ((*p & 0xc0) != 0x80)
+ return FALSE;
+
+ wc <<= 6;
+ wc |= (*p) & 0x3f;
+
+ p++;
+ }
+
+ if (wc_out)
+ *wc_out = wc;
+ if (next)
+ *next = p;
+
+ return TRUE;
+}
+
+gint
+_pango_utf8_len (gchar *str, gint limit)
+{
+ gchar *cur = str;
+ gchar *next;
+ gint len = 0;
+
+ while (*cur)
+ {
+ if (!_pango_utf8_iterate (cur, &next, NULL))
+ return -1;
+ if (cur == next)
+ break;
+ if (limit >= 0 && (next - str) > limit)
+ return len;
+ cur = next;
+ len++;
+ }
+
+ return len;
+}
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+#define UCS2_CHARSET "UNICODELITTLE"
+#else
+#define UCS2_CHARSET "UNICODE"
+#endif
+
+GUChar2 *
+_pango_utf8_to_ucs2 (gchar *str, gint len)
+{
+ iconv_t cd;
+ gchar *outbuf, *result;
+ gchar *inbuf;
+ size_t inbytesleft;
+ size_t outbytesleft;
+ gint outlen;
+
+ gint count;
+
+ cd = iconv_open (UCS2_CHARSET, "UTF8");
+
+ if (cd == (iconv_t)-1)
+ g_error ("No converter from UTF8 to " UCS2_CHARSET);
+
+ if (len < 0)
+ len = strlen (str);
+
+ outlen = unicode_strlen (str, len) * sizeof(GUChar2);
+ result = g_malloc (outlen);
+
+ inbuf = str;
+ inbytesleft = len;
+ outbuf = result;
+ outbytesleft = outlen;
+
+ count = iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+
+ if (count < 0 && (errno != E2BIG))
+ {
+ g_free (result);
+ result = NULL;
+ }
+
+ iconv_close (cd);
+
+ return (GUChar2 *)result;
+}
diff --git a/pango/utils.h b/pango/utils.h
new file mode 100644
index 00000000..2777b5d9
--- /dev/null
+++ b/pango/utils.h
@@ -0,0 +1,34 @@
+/* Pango
+ * utils.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ *
+ * 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.
+ */
+
+#ifndef __UTILS_H__
+#define __UTILS_H__
+
+#include <glib.h>
+
+typedef guint16 GUChar2;
+typedef guint32 GUChar4;
+
+gboolean _pango_utf8_iterate (gchar *cur, char **next, GUChar4 *wc_out);
+GUChar2 *_pango_utf8_to_ucs2 (gchar *str, gint len);
+gint _pango_utf8_len (gchar *str, gint limit);
+
+#endif /* __UTILS_H__ */