summaryrefslogtreecommitdiff
path: root/pango
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2000-02-16 22:05:43 +0000
committerOwen Taylor <otaylor@src.gnome.org>2000-02-16 22:05:43 +0000
commit7f846326d416e9ab3eadca9f02b9a0129095f30b (patch)
tree4b2812b858cd830ca1282e3697d029ca347df24a /pango
parent4f335d6e4a3f5b4e6ddd1cd78f919aa80c990262 (diff)
downloadpango-7f846326d416e9ab3eadca9f02b9a0129095f30b.tar.gz
Make refcounted.
Wed Feb 16 16:39:46 2000 Owen Taylor <otaylor@redhat.com> * libpango/pango-coverage.c (pango_coverage_get): Make refcounted. * libpango/modules.c (struct _PangoEnginePair): Since we don't currently unload engines, cache loaded engines. (Not really quite satisfactory, but should work OK) * libpango/pango-context.c (pango_context_get_font_description): Added a global font description. * libpango/modules.c (_pango_find_map): Allow NULL language tags. * libpango/pango-context.c (pango_itemize) examples/viewer.c: Switch itemize over to take a PangoAttrList. * examples/viewer.c: Conform to changes in itemization interface * libpango/font.[ch]: Add a compare function for FontDescription * libpango/pango-attributes.[ch]: Change the iteration iterface to be more convenient. * libpango/pango-context.[ch]: Add the ability to set a default font. * libpango/pango-context.[ch]: Take the font for itemization from the attributes on the text. * libpango/pangox.c: Cache currently loaded fonts, and cache coverages.
Diffstat (limited to 'pango')
-rw-r--r--pango/fonts.c34
-rw-r--r--pango/modules.c55
-rw-r--r--pango/pango-attributes.c107
-rw-r--r--pango/pango-attributes.h5
-rw-r--r--pango/pango-context.c347
-rw-r--r--pango/pango-context.h59
-rw-r--r--pango/pango-coverage.c51
-rw-r--r--pango/pango-coverage.h5
-rw-r--r--pango/pango-font.h45
-rw-r--r--pango/pango-types.h5
-rw-r--r--pango/pango.h14
-rw-r--r--pango/pangox.c91
-rw-r--r--pango/shape.c12
13 files changed, 569 insertions, 261 deletions
diff --git a/pango/fonts.c b/pango/fonts.c
index b52742aa..a66fde54 100644
--- a/pango/fonts.c
+++ b/pango/fonts.c
@@ -31,7 +31,7 @@
* must be freed using pango_font_description_free().
**/
PangoFontDescription *
-pango_font_description_copy (PangoFontDescription *desc)
+pango_font_description_copy (const PangoFontDescription *desc)
{
PangoFontDescription *result = g_new (PangoFontDescription, 1);
@@ -43,6 +43,32 @@ pango_font_description_copy (PangoFontDescription *desc)
}
/**
+ * pango_font_description_compare:
+ * @desc1: a #PangoFontDescription
+ * @desc2: another #PangoFontDescription
+ *
+ * Compare two font descriptions for equality.
+ *
+ * Return value: %TRUE if the two font descriptions are proveably
+ * identical. (Two font descriptions may result in
+ * identical fonts being loaded, but still compare
+ * %FALSE.)
+ **/
+gboolean
+pango_font_description_compare (const PangoFontDescription *desc1,
+ const PangoFontDescription *desc2)
+{
+ g_return_val_if_fail (desc1 != NULL, FALSE);
+ g_return_val_if_fail (desc2 != NULL, FALSE);
+
+ return (desc1->style == desc2->style &&
+ desc1->variant == desc2->variant &&
+ desc1->weight == desc2->weight &&
+ desc1->stretch == desc2->stretch &&
+ g_strcasecmp (desc1->family_name, desc2->family_name));
+}
+
+/**
* pango_font_description_free:
* @desc: a #PangoFontDescription
*
@@ -278,9 +304,9 @@ pango_font_map_unref (PangoFontMap *fontmap)
* Returns the font loaded, or %NULL if no font matched.
**/
PangoFont *
-pango_font_map_load_font (PangoFontMap *fontmap,
- PangoFontDescription *desc,
- double size)
+pango_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *desc,
+ double size)
{
g_return_val_if_fail (fontmap != NULL, NULL);
diff --git a/pango/modules.c b/pango/modules.c
index 36040000..f2433ca8 100644
--- a/pango/modules.c
+++ b/pango/modules.c
@@ -34,15 +34,16 @@ typedef struct _PangoEnginePair PangoEnginePair;
struct _PangoMapInfo
{
- gchar *lang;
- gchar *engine_type;
- gchar *render_type;
+ const gchar *lang;
+ const gchar *engine_type;
+ const gchar *render_type;
};
struct _PangoEnginePair
{
- gchar *module;
PangoEngineInfo info;
+ gchar *module;
+ PangoEngine *engine;
};
GList *engines;
@@ -67,9 +68,9 @@ _pango_find_map (const char *lang,
map_hash = g_hash_table_new ((GHashFunc)map_info_hash,
(GCompareFunc)map_info_equal);
- map_info.lang = (char *)lang;
- map_info.engine_type = (char *)engine_type;
- map_info.render_type = (char *)render_type;
+ map_info.lang = lang ? lang : "NONE";
+ map_info.engine_type = engine_type;
+ map_info.render_type = render_type;
map = g_hash_table_lookup (map_hash, &map_info);
if (!map)
@@ -103,28 +104,30 @@ _pango_load_engine (const char *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)
+ if (!pair->engine)
{
- fprintf(stderr, "cannot retrieve script_engine_load from %s: %s\n",
- pair->module, g_module_error());
- g_module_close (module);
- return NULL;
+ 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;
+ }
+
+ pair->engine = (*load) (id);
}
- engine = (*load) (id);
-
- return engine;
+ return pair->engine;
}
}
@@ -291,6 +294,8 @@ read_modules (void)
g_list_free (ranges);
g_free (line);
+ pair->engine = NULL;
+
engines = g_list_prepend (engines, pair);
}
engines = g_list_reverse (engines);
diff --git a/pango/pango-attributes.c b/pango/pango-attributes.c
index 35f353db..cdbbbbbb 100644
--- a/pango/pango-attributes.c
+++ b/pango/pango-attributes.c
@@ -32,6 +32,8 @@ struct _PangoAttrIterator
{
GSList *next_attribute;
GList *attribute_stack;
+ int start_index;
+ int end_index;
};
static PangoAttribute *pango_attr_color_new (const PangoAttrClass *klass,
@@ -550,6 +552,8 @@ pango_attr_list_unref (PangoAttrList *list)
}
g_slist_free (list->attributes);
+
+ g_free (list);
}
}
@@ -726,22 +730,42 @@ pango_attr_list_change (PangoAttrList *list,
PangoAttrIterator *
pango_attr_list_get_iterator (PangoAttrList *list)
{
- PangoAttrIterator *result;
+ PangoAttrIterator *iterator;
g_return_val_if_fail (list != NULL, NULL);
- result = g_new (PangoAttrIterator, 1);
- result->next_attribute = list->attributes;
- result->attribute_stack = NULL;
+ iterator = g_new (PangoAttrIterator, 1);
+ iterator->next_attribute = list->attributes;
+ iterator->attribute_stack = NULL;
- while (result->next_attribute &&
- ((PangoAttribute *)result->next_attribute->data)->start_index == 0)
- {
- result->attribute_stack = g_list_prepend (result->attribute_stack, result->next_attribute->data);
- result->next_attribute = result->next_attribute->next;
- }
+ iterator->start_index = 0;
+ iterator->end_index = 0;
- return result;
+ if (!pango_attr_iterator_next (iterator))
+ iterator->end_index = G_MAXINT;
+
+ return iterator;
+}
+
+/**
+ * pango_attr_iterator_range:
+ * @iterator: a #PangoAttrIterator
+ * @start: location to store the start of the range
+ * @end: location to store the end of the range
+ *
+ * Get the range of the current segment.
+ **/
+void
+pango_attr_iterator_range (PangoAttrIterator *iterator,
+ gint *start,
+ gint *end)
+{
+ g_return_if_fail (iterator != NULL);
+
+ if (start)
+ *start = iterator->start_index;
+ if (end)
+ *end = iterator->end_index;
}
/**
@@ -750,63 +774,52 @@ pango_attr_list_get_iterator (PangoAttrList *list)
*
* Advance the iterator until the next change of style.
*
- * Return value: the index of the next change of position, or -1 if iterator
- * is at the end of the list.
+ * Return value: %FALSE if the iterator is at the end of the list, otherwise %TRUE
**/
-int
+gboolean
pango_attr_iterator_next (PangoAttrIterator *iterator)
{
- int next_index = G_MAXINT;
GList *tmp_list;
g_return_val_if_fail (iterator != NULL, -1);
if (!iterator->next_attribute && !iterator->attribute_stack)
- return -1;
-
- tmp_list = iterator->attribute_stack;
- while (tmp_list)
- {
- PangoAttribute *attr = tmp_list->data;
- if (attr->end_index < next_index)
- next_index = attr->end_index;
- }
+ return FALSE;
- tmp_list = iterator->attribute_stack;
+ iterator->start_index = iterator->end_index;
+ iterator->end_index = G_MAXINT;
- if (iterator->next_attribute)
- {
- int next_start = ((PangoAttribute *)iterator->next_attribute->data)->start_index;
-
- if (next_start <= next_index)
- {
- do
- {
- iterator->attribute_stack = g_list_prepend (iterator->attribute_stack, iterator->next_attribute->data);
- iterator->next_attribute = iterator->next_attribute->next;
- }
- while (iterator->next_attribute &&
- ((PangoAttribute *)iterator->next_attribute->data)->start_index == next_start);
- }
-
- if (next_start < next_index)
- return next_start;
- }
-
+ tmp_list = iterator->attribute_stack;
while (tmp_list)
{
GList *next = tmp_list->next;
+ PangoAttribute *attr = tmp_list->data;
- if (((PangoAttribute *)tmp_list->data)->start_index == next_index)
+ if (attr->end_index == iterator->start_index)
{
iterator->attribute_stack = g_list_remove_link (iterator->attribute_stack, tmp_list);
g_list_free_1 (tmp_list);
}
+ else
+ {
+ iterator->end_index = MIN (iterator->end_index, attr->end_index);
+ }
tmp_list = next;
}
-
- return next_index;
+
+ while (iterator->next_attribute &&
+ ((PangoAttribute *)iterator->next_attribute->data)->start_index == iterator->start_index)
+ {
+ iterator->attribute_stack = g_list_prepend (iterator->attribute_stack, iterator->next_attribute->data);
+ iterator->end_index = MIN (iterator->end_index, ((PangoAttribute *)iterator->next_attribute->data)->end_index);
+ iterator->next_attribute = iterator->next_attribute->next;
+ }
+
+ if (iterator->next_attribute)
+ iterator->end_index = MIN (iterator->end_index, ((PangoAttribute *)iterator->next_attribute->data)->start_index);
+
+ return TRUE;
}
/**
diff --git a/pango/pango-attributes.h b/pango/pango-attributes.h
index 322c5c75..8c72d750 100644
--- a/pango/pango-attributes.h
+++ b/pango/pango-attributes.h
@@ -121,7 +121,10 @@ void pango_attr_list_change (PangoAttrList *list,
PangoAttribute *attr);
PangoAttrIterator * pango_attr_list_get_iterator (PangoAttrList *list);
-int pango_attr_iterator_next (PangoAttrIterator *iterator);
+void pango_attr_iterator_range (PangoAttrIterator *iterator,
+ gint *start,
+ gint *end);
+gboolean pango_attr_iterator_next (PangoAttrIterator *iterator);
void pango_attr_iterator_destroy (PangoAttrIterator *iterator);
PangoAttribute *pango_attr_iterator_get (PangoAttrIterator *iterator,
PangoAttrType type);
diff --git a/pango/pango-context.c b/pango/pango-context.c
index 2e8c6700..fe8d955e 100644
--- a/pango/pango-context.c
+++ b/pango/pango-context.c
@@ -26,17 +26,26 @@
#include "utils.h"
#include "modules.h"
-
struct _PangoContext
{
gint ref_count;
char *lang;
PangoDirection base_dir;
+ PangoFontDescription *font_desc;
+ int size;
GSList *font_maps;
};
+static void add_engines (PangoContext *context,
+ gchar *text,
+ gint length,
+ PangoAttrList *attrs,
+ PangoEngineShape **shape_engines,
+ PangoEngineInfo **lang_engines,
+ PangoFont **fonts);
+
/**
* pango_context_new:
*
@@ -48,11 +57,21 @@ PangoContext *
pango_context_new (void)
{
PangoContext *result = g_new (PangoContext, 1);
+ PangoFontDescription desc;
+
result->ref_count = 1;
result->base_dir = PANGO_DIRECTION_LTR;
result->lang = NULL;
result->font_maps = NULL;
+ desc.family_name = "serif";
+ desc.style = PANGO_STYLE_NORMAL;
+ desc.variant = PANGO_VARIANT_NORMAL;
+ desc.weight = PANGO_WEIGHT_NORMAL;
+ desc.stretch = PANGO_STRETCH_NORMAL;
+
+ result->font_desc = pango_font_description_copy (&desc);
+
return result;
}
@@ -311,9 +330,9 @@ pango_context_list_families (PangoContext *context,
* Returns the font loaded, or %NULL if no font matched.
**/
PangoFont *
-pango_context_load_font (PangoContext *context,
- PangoFontDescription *desc,
- gdouble size)
+pango_context_load_font (PangoContext *context,
+ const PangoFontDescription *desc,
+ gdouble size)
{
GSList *tmp_list;
@@ -335,6 +354,41 @@ pango_context_load_font (PangoContext *context,
}
/**
+ * pango_context_set_font_description:
+ * @context: a #PangoContext
+ * @desc: the new pango font description
+ *
+ * Set the default font description for the context
+ **/
+void
+pango_context_set_font_description (PangoContext *context,
+ const PangoFontDescription *desc)
+{
+ g_return_if_fail (context != NULL);
+ g_return_if_fail (desc != NULL);
+
+ pango_font_description_free (context->font_desc);
+ context->font_desc = pango_font_description_copy (desc);
+}
+
+/**
+ * pango_context_get_font_description:
+ * @context: a #PangoContext
+ *
+ * Retrieve the default font description for the context.
+ *
+ * Return value: a newly allocated copy of the contexts default font description.
+ * This value must be free with pango_font_description_free()
+ **/
+PangoFontDescription *
+pango_context_get_font_description (PangoContext *context)
+{
+ g_return_val_if_fail (context != NULL, NULL);
+
+ return pango_font_description_copy (context->font_desc);
+}
+
+/**
* pango_context_set_lang:
* @context: a #PangoContext
* @lang: the new language tag.
@@ -370,6 +424,38 @@ pango_context_get_lang (PangoContext *context)
}
/**
+ * pango_context_get_size:
+ * @context: a #PangoContext
+ *
+ * Retrieves the default font size for the context.
+ *
+ * Return value: the default font size in 1000ths of a point.
+ **/
+int
+pango_context_get_size (PangoContext *context)
+{
+ g_return_val_if_fail (context != NULL, 0);
+
+ return context->size;
+}
+
+/**
+ * pango_context_set_size:
+ * @context: a #PangoContext
+ * @lang: the new default font size in points in 1000ths of a point.
+ *
+ * Sets the default font size for the context.
+ **/
+void
+pango_context_set_size (PangoContext *context,
+ int size)
+{
+ g_return_if_fail (context != NULL);
+
+ context->size = size;
+}
+
+/**
* pango_context_set_base_dir:
* @context: a #PangoContext
* @direction: the new base direction
@@ -401,15 +487,6 @@ pango_context_get_base_dir (PangoContext *context)
return context->base_dir;
}
-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
@@ -417,8 +494,7 @@ static void add_engines (PangoContext *context,
* @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.
+ * @attr: the set of attributes that apply to @text.
*
* Breaks a piece of text into segments with consistent
* directional level and shaping engine.
@@ -427,10 +503,9 @@ static void add_engines (PangoContext *context,
*/
GList *
pango_itemize (PangoContext *context,
- gchar *text,
- gint length,
- PangoLangRange *lang_info,
- gint n_langs)
+ gchar *text,
+ gint length,
+ PangoAttrList *attrs)
{
guint16 *text_ucs2;
gint n_chars;
@@ -441,8 +516,9 @@ pango_itemize (PangoContext *context,
char *p, *next;
GList *result = NULL;
- PangoEngineInfo **shape_engines;
+ PangoEngineShape **shape_engines;
PangoEngineInfo **lang_engines;
+ PangoFont **fonts;
g_return_val_if_fail (context != NULL, NULL);
g_return_val_if_fail (text != NULL, NULL);
@@ -471,27 +547,19 @@ pango_itemize (PangoContext *context,
* but also more complicated... we take the simple
* approach for now.
*/
- shape_engines = g_new0 (PangoEngineInfo *, n_chars);
+ shape_engines = g_new0 (PangoEngineShape *, n_chars);
lang_engines = g_new0 (PangoEngineInfo *, n_chars);
+ fonts = g_new0 (PangoFont *, 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.
+ /* Now, fill in the appropriate shapers, language engines and fonts for
+ * each character.
*/
- add_engines (context, text, length, lang_info, n_langs,
- TRUE, shape_engines, lang_engines);
+ add_engines (context, text, length, attrs, shape_engines, lang_engines, fonts);
- /* 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
*/
@@ -505,105 +573,214 @@ pango_itemize (PangoContext *context,
if (i == 0 ||
embedding_levels[i] != embedding_levels[i-1] ||
shape_engines[i] != shape_engines[i-1] ||
- lang_engines[i] != lang_engines[i-1])
+ lang_engines[i] != lang_engines[i-1] ||
+ fonts[i] != fonts[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;
+ item->analysis.shape_engine = shape_engines[i];
if (lang_engines[i])
item->analysis.lang_engine = (PangoEngineLang *)_pango_load_engine (lang_engines[i]->id);
else
item->analysis.lang_engine = NULL;
+
+ item->analysis.font = fonts[i];
+
+ result = g_list_prepend (result, item);
}
+ else
+ pango_font_unref (fonts[i]);
item->length = (next - text) - item->offset;
item->num_chars++;
p = next;
}
- if (item)
- result = g_list_prepend (result, item);
-
+ g_free (embedding_levels);
+ g_free (shape_engines);
+ g_free (lang_engines);
+ g_free (fonts);
+
g_free (text_ucs2);
return g_list_reverse (result);
}
+static PangoFont *
+get_font (PangoFont **fonts,
+ PangoCoverage **coverages,
+ int n_families,
+ GUChar4 wc)
+{
+ PangoFont *result = NULL;
+ PangoCoverageLevel best_level = PANGO_COVERAGE_NONE;
+
+ int i;
+
+ for (i=0; i<n_families; i++)
+ {
+ if (fonts[i])
+ {
+ PangoCoverageLevel level = pango_coverage_get (coverages[i], wc);
+
+ if (!result || level > best_level)
+ {
+ result = fonts[i];
+ best_level = level;
+ }
+ }
+ }
+
+ if (result)
+ pango_font_ref (result);
+
+ return 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)
+add_engines (PangoContext *context,
+ gchar *text,
+ gint length,
+ PangoAttrList *attrs,
+ PangoEngineShape **shape_engines,
+ PangoEngineInfo **lang_engines,
+ PangoFont **fonts)
{
char *pos;
- char *last_lang = NULL;
+ char *lang = NULL;
+ int next_index = 0;
gint n_chars;
PangoMap *shape_map = NULL;
PangoMap *lang_map = NULL;
+ PangoFontDescription current_desc = { 0 };
+ int current_size = 0;
+ int next_size = 0;
+
+ /* FIXME: Remove this artificial limit */
+
+ int n_families = 0;
+#define MAX_FAMILIES 16
+ PangoFont *current_fonts[MAX_FAMILIES];
+ PangoCoverage *current_coverages[MAX_FAMILIES];
+
+ PangoAttrIterator *iterator;
+ PangoAttribute *attr;
+
GUChar4 wc;
int i, j;
n_chars = unicode_strlen (text, length);
+ iterator = pango_attr_list_get_iterator (attrs);
+
pos = text;
- last_lang = NULL;
- for (i=0, j=0; i<n_chars; i++)
+ for (i=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)
+ if (i == next_index)
{
- lang_map = _pango_find_map (lang, PANGO_ENGINE_TYPE_LANG,
- PANGO_RENDER_TYPE_NONE);
- shape_map = _pango_find_map (lang, PANGO_ENGINE_TYPE_SHAPE,
- "PangoRenderX");
- last_lang = lang;
- }
+ char *next_lang;
+ PangoFontDescription next_desc;
+
+ attr = pango_attr_iterator_get (iterator, PANGO_ATTR_LANG);
+ if (attr)
+ next_lang = ((PangoAttrString *)attr)->value;
+ else
+ next_lang = context->lang;
- pos = unicode_get_utf8 (pos, &wc);
+ if (i == 0 ||
+ (lang != next_lang &&
+ (lang == NULL || next_lang == NULL || strcmp (lang, next_lang) != 0)))
+ {
+ lang = next_lang;
+
+ lang_map = _pango_find_map (next_lang, PANGO_ENGINE_TYPE_LANG,
+ PANGO_RENDER_TYPE_NONE);
+ shape_map = _pango_find_map (next_lang, PANGO_ENGINE_TYPE_SHAPE,
+ "PangoRenderX");
+ }
- if (!lang_engines[i])
- {
- submap = &lang_map->submaps[wc / 256];
- entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
+ pango_attr_iterator_get_font (iterator, context->font_desc, &next_desc);
+
+ attr = pango_attr_iterator_get (iterator, PANGO_ATTR_SIZE);
+ if (attr)
+ next_size = ((PangoAttrInt *)attr)->value;
+ else
+ next_size = context->size;
- if (entry->info && (!force_exact || entry->is_exact))
- lang_engines[i] = entry->info;
+ if (i == 0 ||
+ !pango_font_description_compare (&current_desc, &next_desc) ||
+ current_size != next_size)
+ {
+ char **families;
+
+ current_desc = next_desc;
+ current_size = next_size;
+
+ for (j=0; j<n_families; j++)
+ {
+ if (current_fonts[j])
+ {
+ pango_font_unref (current_fonts[j]);
+ pango_coverage_unref (current_coverages[j]);
+ }
+ }
+
+ families = g_strsplit (current_desc.family_name, ",", -1);
+ n_families = 0;
+ while (families[n_families])
+ n_families++;
+
+ if (n_families > MAX_FAMILIES)
+ n_families = MAX_FAMILIES;
+
+ for (j=0; j<n_families; j++)
+ {
+ next_desc.family_name = families[j];
+ current_fonts[j] = pango_context_load_font (context, &next_desc, next_size / 1000.);
+
+ if (current_fonts[j])
+ current_coverages[j] = pango_font_get_coverage (current_fonts[j], lang);
+ }
+
+ g_strfreev (families);
+ }
+
+ pango_attr_iterator_range (iterator, NULL, &next_index);
+ pango_attr_iterator_next (iterator);
}
- if (!shape_engines[i])
- {
- submap = &shape_map->submaps[wc / 256];
- entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
+ pos = unicode_get_utf8 (pos, &wc);
+
+ submap = &lang_map->submaps[wc / 256];
+ entry = submap->is_leaf ? &submap->d.entry : &submap->d.leaves[wc % 256];
+
+ lang_engines[i] = entry->info;
+
+ fonts[i] = get_font (current_fonts, current_coverages, n_families, wc);
- if (entry->info && (!force_exact || entry->is_exact))
- shape_engines[i] = entry->info;
+ /* FIXME: handle reference counting properly on the shapers */
+ if (fonts[i])
+ shape_engines[i] = pango_font_find_shaper (fonts[i], lang, wc);
+ else
+ shape_engines[i] = NULL;
+ }
+
+ for (j=0; j<n_families; j++)
+ {
+ if (current_fonts[j])
+ {
+ pango_font_unref (current_fonts[j]);
+ pango_coverage_unref (current_coverages[j]);
}
}
+
+ pango_attr_iterator_destroy (iterator);
}
diff --git a/pango/pango-context.h b/pango/pango-context.h
index 64fe06ac..bc8badf9 100644
--- a/pango/pango-context.h
+++ b/pango/pango-context.h
@@ -23,6 +23,7 @@
#define __PANGO_CONTEXT_H__
#include <pango-font.h>
+#include <pango-attributes.h>
#ifdef __cplusplus
extern "C" {
@@ -33,31 +34,43 @@ extern "C" {
*/
typedef struct _PangoContext PangoContext;
-PangoContext * pango_context_new (void);
-void pango_context_ref (PangoContext *context);
-void pango_context_unref (PangoContext *context);
+PangoContext *pango_context_new (void);
+void pango_context_ref (PangoContext *context);
+void pango_context_unref (PangoContext *context);
+void pango_context_add_font_map (PangoContext *context,
+ PangoFontMap *font_map);
+void pango_context_list_fonts (PangoContext *context,
+ const char *family,
+ PangoFontDescription ***descs,
+ int *n_descs);
+void pango_context_list_families (PangoContext *context,
+ gchar ***families,
+ int *n_families);
+PangoFont * pango_context_load_font (PangoContext *context,
+ const PangoFontDescription *desc,
+ gdouble size);
-void pango_context_add_font_map (PangoContext *context,
- PangoFontMap *font_map);
-
-void pango_context_list_fonts (PangoContext *context,
- const char *family,
- PangoFontDescription ***descs,
- int *n_descs);
-void pango_context_list_families (PangoContext *context,
- gchar ***families,
- int *n_families);
-PangoFont * pango_context_load_font (PangoContext *context,
- PangoFontDescription *desc,
- gdouble size);
-
-void pango_context_set_lang (PangoContext *context,
- const char *lang);
-char * pango_context_get_lang (PangoContext *context);
-void pango_context_set_base_dir (PangoContext *context,
- PangoDirection direction);
-PangoDirection pango_context_get_base_dir (PangoContext *context);
+void pango_context_set_font_description (PangoContext *context,
+ const PangoFontDescription *desc);
+PangoFontDescription *pango_context_get_font_description (PangoContext *context);
+char * pango_context_get_lang (PangoContext *context);
+void pango_context_set_lang (PangoContext *context,
+ const char *lang);
+int pango_context_get_size (PangoContext *context);
+void pango_context_set_size (PangoContext *context,
+ int size);
+void pango_context_set_base_dir (PangoContext *context,
+ PangoDirection direction);
+PangoDirection pango_context_get_base_dir (PangoContext *context);
+/* 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,
+ PangoAttrList *attrs);
#ifdef __cplusplus
}
diff --git a/pango/pango-coverage.c b/pango/pango-coverage.c
index d6ce8812..cc9ca246 100644
--- a/pango/pango-coverage.c
+++ b/pango/pango-coverage.c
@@ -39,6 +39,7 @@ struct _PangoBlockInfo
struct _PangoCoverage
{
+ guint ref_count;
int n_blocks;
int data_size;
@@ -50,7 +51,8 @@ struct _PangoCoverage
*
* Create a new #PangoCoverage
*
- * Return value: a new PangoCoverage object, initialized to PANGO_COVERAGE_NONE
+ * Return value: a new PangoCoverage object, initialized to %PANGO_COVERAGE_NONE
+ * with a reference count of 0.
**/
PangoCoverage *
pango_coverage_new (void)
@@ -60,6 +62,7 @@ pango_coverage_new (void)
coverage->n_blocks = N_BLOCKS_INCREMENT;
coverage->blocks = g_new (PangoBlockInfo, coverage->n_blocks);
+ coverage->ref_count = 1;
for (i=0; i<coverage->n_blocks; i++)
{
@@ -74,9 +77,11 @@ pango_coverage_new (void)
* pango_coverage_copy:
* @coverage: a #PangoCoverage
*
- * Copy an existing #PangoCoverage
+ * Copy an existing #PangoCoverage. (This function may now be unecessary
+ * since we refcount the structure. Mail otaylor@redhat.com if you
+ * use it.)
*
- * Return value: a copy of @coverage
+ * Return value: a copy of @coverage with a reference count of 1
**/
PangoCoverage *
pango_coverage_copy (PangoCoverage *coverage)
@@ -88,6 +93,7 @@ pango_coverage_copy (PangoCoverage *coverage)
result->n_blocks = coverage->n_blocks;
result->blocks = g_new (PangoBlockInfo, coverage->n_blocks);
+ result->ref_count = 1;
for (i=0; i<coverage->n_blocks; i++)
{
@@ -106,24 +112,47 @@ pango_coverage_copy (PangoCoverage *coverage)
}
/**
- * pango_coverage_destroy:
+ * pango_coverage_ref:
* @coverage: a #PangoCoverage
*
- * Destroy a #PangoCoverage object, freeing associated memory
+ * Increase the reference count on the #PangoCoverage by one
**/
-void pango_coverage_destroy (PangoCoverage *coverage)
+void
+pango_coverage_ref (PangoCoverage *coverage)
+{
+ g_return_if_fail (coverage != NULL);
+
+ coverage->ref_count++;
+}
+
+/**
+ * pango_coverage_unref:
+ * @coverage: a #PangoCoverage
+ *
+ * Increase the reference count on the #PangoCoverage by one.
+ * if the result is zero, free the coverage and all associated memory.
+ **/
+void
+pango_coverage_unref (PangoCoverage *coverage)
{
int i;
g_return_if_fail (coverage != NULL);
+ g_return_if_fail (coverage->ref_count > 0);
- for (i=0; i<coverage->n_blocks; i++)
+ coverage->ref_count--;
+
+ if (coverage->ref_count == 0)
{
- if (coverage->blocks[i].data)
- g_free (coverage->blocks[i].data);
+ for (i=0; i<coverage->n_blocks; i++)
+ {
+ if (coverage->blocks[i].data)
+ g_free (coverage->blocks[i].data);
+ }
+
+ g_free (coverage->blocks);
+ g_free (coverage);
}
-
- g_free (coverage);
}
/**
diff --git a/pango/pango-coverage.h b/pango/pango-coverage.h
index 2b613f94..08febeb7 100644
--- a/pango/pango-coverage.h
+++ b/pango/pango-coverage.h
@@ -38,8 +38,9 @@ typedef enum {
} PangoCoverageLevel;
PangoCoverage * pango_coverage_new (void);
+void pango_coverage_ref (PangoCoverage *coverage);
+void pango_coverage_unref (PangoCoverage *coverage);
PangoCoverage * pango_coverage_copy (PangoCoverage *coverage);
-void pango_coverage_destroy (PangoCoverage *coverage);
PangoCoverageLevel pango_coverage_get (PangoCoverage *coverage,
int index);
void pango_coverage_set (PangoCoverage *coverage,
@@ -53,3 +54,5 @@ void pango_coverage_max (PangoCoverage *coverage,
#endif /* __cplusplus */
#endif __PANGO_COVERAGE_H__
+
+
diff --git a/pango/pango-font.h b/pango/pango-font.h
index 161236e6..1c262609 100644
--- a/pango/pango-font.h
+++ b/pango/pango-font.h
@@ -30,7 +30,6 @@ extern "C" {
#include <pango-types.h>
typedef struct _PangoFontDescription PangoFontDescription;
-typedef struct _PangoFont PangoFont;
typedef struct _PangoFontClass PangoFontClass;
typedef struct _PangoFontMap PangoFontMap;
typedef struct _PangoFontMapClass PangoFontMapClass;
@@ -72,10 +71,12 @@ struct _PangoFontDescription {
PangoStretch stretch;
};
-PangoFontDescription *pango_font_description_copy (PangoFontDescription *desc);
-void pango_font_description_free (PangoFontDescription *desc);
-void pango_font_descriptions_free (PangoFontDescription **descs,
- int n_descs);
+PangoFontDescription *pango_font_description_copy (const PangoFontDescription *desc);
+gboolean pango_font_description_compare (const PangoFontDescription *desc1,
+ const PangoFontDescription *desc2);
+void pango_font_description_free (PangoFontDescription *desc);
+void pango_font_descriptions_free (PangoFontDescription **descs,
+ int n_descs);
/* Logical fonts
*/
@@ -130,25 +131,25 @@ struct _PangoFontMap
struct _PangoFontMapClass
{
- void (*destroy) (PangoFontMap *fontmap);
- PangoFont *(*load_font) (PangoFontMap *fontmap,
- PangoFontDescription *desc,
- double size);
- void (*list_fonts) (PangoFontMap *fontmap,
- const gchar *family,
- PangoFontDescription ***descs,
- int *n_descs);
- void (*list_families) (PangoFontMap *fontmap,
- gchar ***families,
- int *n_families);
+ void (*destroy) (PangoFontMap *fontmap);
+ PangoFont *(*load_font) (PangoFontMap *fontmap,
+ const PangoFontDescription *desc,
+ double size);
+ void (*list_fonts) (PangoFontMap *fontmap,
+ const gchar *family,
+ PangoFontDescription ***descs,
+ int *n_descs);
+ void (*list_families) (PangoFontMap *fontmap,
+ gchar ***families,
+ int *n_families);
};
-void pango_font_map_init (PangoFontMap *fontmap);
-void pango_font_map_ref (PangoFontMap *fontmap);
-void pango_font_map_unref (PangoFontMap *fontmap);
-PangoFont *pango_font_map_load_font (PangoFontMap *fontmap,
- PangoFontDescription *desc,
- double size);
+void pango_font_map_init (PangoFontMap *fontmap);
+void pango_font_map_ref (PangoFontMap *fontmap);
+void pango_font_map_unref (PangoFontMap *fontmap);
+PangoFont *pango_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *desc,
+ double size);
void pango_font_map_list_fonts (PangoFontMap *fontmap,
const gchar *family,
diff --git a/pango/pango-types.h b/pango/pango-types.h
index 46dc794b..33ef0195 100644
--- a/pango/pango-types.h
+++ b/pango/pango-types.h
@@ -38,13 +38,16 @@ typedef struct _PangoLogAttr PangoLogAttr;
typedef struct _PangoEngineLang PangoEngineLang;
typedef struct _PangoEngineShape PangoEngineShape;
+typedef struct _PangoFont PangoFont;
+
/* Information about a segment of text with a consistent
* shaping/language engine and bidirectional level
*/
struct _PangoAnalysis {
PangoEngineShape *shape_engine;
- PangoEngineLang *lang_engine;
+ PangoEngineLang *lang_engine;
+ PangoFont *font;
guint8 level;
};
diff --git a/pango/pango.h b/pango/pango.h
index 60993938..f06c52cd 100644
--- a/pango/pango.h
+++ b/pango/pango.h
@@ -28,6 +28,7 @@
extern "C" {
#endif /* __cplusplus */
+#include <pango-attributes.h>
#include <pango-context.h>
#include <pango-coverage.h>
#include <pango-engine.h>
@@ -36,16 +37,6 @@ extern "C" {
#include <pango-layout.h>
#include <pango-types.h>
-/* 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 {
@@ -66,8 +57,7 @@ void pango_break (gchar *text,
/* Turn a string of characters into a string of glyphs
*/
-void pango_shape (PangoFont *font,
- gchar *text,
+void pango_shape (gchar *text,
gint length,
PangoAnalysis *analysis,
PangoGlyphString *glyphs);
diff --git a/pango/pangox.c b/pango/pangox.c
index bcc175d1..80b18395 100644
--- a/pango/pangox.c
+++ b/pango/pangox.c
@@ -49,6 +49,9 @@ struct _PangoXFontEntry
{
char *xlfd;
PangoFontDescription description;
+ PangoCoverage *coverage;
+
+ GSList *cached_fonts;
};
struct _PangoXFamilyEntry
@@ -81,6 +84,8 @@ struct _PangoXFont
int n_subfonts;
int max_subfonts;
+
+ PangoXFontEntry *entry; /* Used to remove cached fonts */
};
struct _PangoXFontMap
@@ -155,18 +160,18 @@ const struct {
{ "condensed", PANGO_STRETCH_CONDENSED },
};
-static void pango_x_font_map_destroy (PangoFontMap *fontmap);
-static PangoFont *pango_x_font_map_load_font (PangoFontMap *fontmap,
- PangoFontDescription *desc,
- double size);
-static void pango_x_font_map_list_fonts (PangoFontMap *fontmap,
- const gchar *family,
- PangoFontDescription ***descs,
- int *n_descs);
-static void pango_x_font_map_list_families (PangoFontMap *fontmap,
- gchar ***families,
- int *n_families);
-static void pango_x_font_map_read_aliases (PangoXFontMap *xfontmap);
+static void pango_x_font_map_destroy (PangoFontMap *fontmap);
+static PangoFont *pango_x_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *desc,
+ double size);
+static void pango_x_font_map_list_fonts (PangoFontMap *fontmap,
+ const gchar *family,
+ PangoFontDescription ***descs,
+ int *n_descs);
+static void pango_x_font_map_list_families (PangoFontMap *fontmap,
+ gchar ***families,
+ int *n_families);
+static void pango_x_font_map_read_aliases (PangoXFontMap *xfontmap);
static void pango_x_font_destroy (PangoFont *font);
static PangoFontDescription *pango_x_font_describe (PangoFont *font);
@@ -296,9 +301,9 @@ pango_x_get_family_entry (PangoXFontMap *xfontmap,
}
static PangoFont *
-pango_x_font_map_load_font (PangoFontMap *fontmap,
- PangoFontDescription *description,
- double size)
+pango_x_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *description,
+ double size)
{
PangoXFontMap *xfontmap = (PangoXFontMap *)fontmap;
PangoXFamilyEntry *family_entry;
@@ -339,8 +344,27 @@ pango_x_font_map_load_font (PangoFontMap *fontmap,
if (best_match)
{
- /* FIXME: cache fonts */
- result = pango_x_load_font_with_size (xfontmap->display, best_match->xlfd, size);
+ GSList *tmp_list = best_match->cached_fonts;
+
+ while (tmp_list)
+ {
+ PangoXFont *xfont = tmp_list->data;
+ if (xfont->size == size)
+ {
+ result = (PangoFont *)xfont;
+ pango_font_ref (result);
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ if (!result)
+ {
+ result = pango_x_load_font_with_size (xfontmap->display, best_match->xlfd, size);
+ ((PangoXFont *)result)->entry = best_match;
+ best_match->cached_fonts = g_slist_prepend (best_match->cached_fonts, result);
+ }
+
}
}
@@ -853,6 +877,8 @@ pango_x_font_map_read_alias_file (PangoXFontMap *xfontmap,
g_free (font_entry->description.family_name);
font_entry->description.family_name = family_entry->family_name;
+ font_entry->cached_fonts = NULL;
+ font_entry->coverage = NULL;
}
if (ferror (infile))
@@ -1137,6 +1163,8 @@ pango_x_insert_font (PangoXFontMap *xfontmap,
font_entry = g_new (PangoXFontEntry, 1);
font_entry->description = description;
font_entry->description.family_name = family_entry->family_name;
+ font_entry->cached_fonts = NULL;
+ font_entry->coverage = NULL;
font_entry->xlfd = g_strconcat ("-*-",
family_buffer,
@@ -1194,7 +1222,7 @@ pango_x_load_font (Display *display,
result->fonts = g_strsplit(spec, ",", -1);
for (result->n_fonts = 0; result->fonts[result->n_fonts]; result->n_fonts++)
- /* Nothing */
+ ; /* Nothing */
result->subfonts_by_charset = g_hash_table_new (g_str_hash, g_str_equal);
result->subfonts = g_new (PangoXSubfontInfo *, 1);
@@ -1203,6 +1231,7 @@ pango_x_load_font (Display *display,
result->max_subfonts = 1;
result->size = -1;
+ result->entry = NULL;
return (PangoFont *)result;
}
@@ -1238,7 +1267,7 @@ pango_x_load_font_with_size (Display *display,
result->fonts = g_strsplit(spec, ",", -1);
for (result->n_fonts = 0; result->fonts[result->n_fonts]; result->n_fonts++)
- /* Nothing */
+ ; /* Nothing */
result->subfonts_by_charset = g_hash_table_new (g_str_hash, g_str_equal);
result->subfonts = g_new (PangoXSubfontInfo *, 1);
@@ -1247,6 +1276,7 @@ pango_x_load_font_with_size (Display *display,
result->max_subfonts = 1;
result->size = size;
+ result->entry = NULL;
return (PangoFont *)result;
}
@@ -1637,7 +1667,7 @@ pango_x_make_matching_xlfd (PangoXFontMap *xfontmap, char *xlfd, const char *cha
}
}
- /* g_free (dash_charset); */
+ g_free (dash_charset);
return result;
}
@@ -1803,6 +1833,9 @@ pango_x_font_destroy (PangoFont *font)
g_hash_table_foreach (xfont->subfonts_by_charset, subfonts_foreach, NULL);
g_hash_table_destroy (xfont->subfonts_by_charset);
+ if (xfont->entry)
+ xfont->entry->cached_fonts = g_slist_remove (xfont->entry->cached_fonts, xfont);
+
g_strfreev (xfont->fonts);
g_free (font);
}
@@ -1819,7 +1852,7 @@ free_coverages_foreach (gpointer key,
gpointer value,
gpointer data)
{
- pango_coverage_destroy (value);
+ pango_coverage_unref (value);
}
static PangoCoverage *
@@ -1834,7 +1867,15 @@ pango_x_font_get_coverage (PangoFont *font,
PangoCoverage *result;
PangoCoverageLevel font_level;
GHashTable *coverage_hash;
-
+ PangoXFont *xfont = (PangoXFont *)font;
+
+ if (xfont->entry)
+ if (xfont->entry->coverage)
+ {
+ pango_coverage_ref (xfont->entry->coverage);
+ return xfont->entry->coverage;
+ }
+
result = pango_coverage_new ();
coverage_hash = g_hash_table_new (g_str_hash, g_str_equal);
@@ -1869,6 +1910,12 @@ pango_x_font_get_coverage (PangoFont *font,
g_hash_table_foreach (coverage_hash, free_coverages_foreach, NULL);
g_hash_table_destroy (coverage_hash);
+ if (xfont->entry)
+ {
+ xfont->entry->coverage = result;
+ pango_coverage_ref (result);
+ }
+
return result;
}
diff --git a/pango/shape.c b/pango/shape.c
index 0f5efb39..04a966e0 100644
--- a/pango/shape.c
+++ b/pango/shape.c
@@ -24,7 +24,6 @@
/**
* 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
@@ -35,14 +34,13 @@
* 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)
+void pango_shape (gchar *text,
+ gint length,
+ PangoAnalysis *analysis,
+ PangoGlyphString *glyphs)
{
if (analysis->shape_engine)
- analysis->shape_engine->script_shape (font, text, length, analysis, glyphs);
+ analysis->shape_engine->script_shape (analysis->font, text, length, analysis, glyphs);
else
pango_glyph_string_set_size (glyphs, 0);
}