diff options
Diffstat (limited to 'pango')
-rw-r--r-- | pango/.cvsignore | 5 | ||||
-rw-r--r-- | pango/Makefile.am | 31 | ||||
-rw-r--r-- | pango/break.c | 66 | ||||
-rw-r--r-- | pango/fonts.c | 167 | ||||
-rw-r--r-- | pango/glyphstring.c | 106 | ||||
-rw-r--r-- | pango/gunicode.h | 21 | ||||
-rw-r--r-- | pango/itemize.c | 234 | ||||
-rw-r--r-- | pango/mapping.c | 275 | ||||
-rw-r--r-- | pango/modules.c | 409 | ||||
-rw-r--r-- | pango/modules.h | 55 | ||||
-rw-r--r-- | pango/pango.h | 339 | ||||
-rw-r--r-- | pango/pangox.c | 757 | ||||
-rw-r--r-- | pango/pangox.h | 100 | ||||
-rw-r--r-- | pango/querymodules.c | 102 | ||||
-rw-r--r-- | pango/reorder-items.c | 104 | ||||
-rw-r--r-- | pango/shape.c | 48 | ||||
-rw-r--r-- | pango/utils.c | 153 | ||||
-rw-r--r-- | pango/utils.h | 34 |
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__ */ |