diff options
author | Owen Taylor <otaylor@redhat.com> | 2000-04-05 00:31:59 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2000-04-05 00:31:59 +0000 |
commit | 613302136667231bcefd772b419369516eb3bf45 (patch) | |
tree | 919ed907f3ca69f79210d0778c65df8bec97d4d0 | |
parent | 52f2e805bf993f711d09ba6fe4972c7f7ee33eae (diff) | |
download | pango-613302136667231bcefd772b419369516eb3bf45.tar.gz |
Add user data to PangoContext
Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com>
* pango/pango-context.h: Add user data to PangoContext
* pango/pangox.[ch] examples/viewer.c: Rework system for create GC's
so that the necessary information is stored on the PangoContext
instead of being passed to layout_render()
* pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9
wants UCS-4 not UCS2; switch accordingly.
* pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions
to get overall font metrics, possibly per-language. (Right now,
just font ascent, descent.) The implementation of this for
X is horribly complex.
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | ChangeLog.pre-1-0 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-1-10 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-1-2 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-1-4 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-1-6 | 13 | ||||
-rw-r--r-- | ChangeLog.pre-1-8 | 13 | ||||
-rw-r--r-- | TODO | 22 | ||||
-rw-r--r-- | examples/viewer.c | 15 | ||||
-rw-r--r-- | pango/fonts.c | 36 | ||||
-rw-r--r-- | pango/pango-context.c | 51 | ||||
-rw-r--r-- | pango/pango-context.h | 7 | ||||
-rw-r--r-- | pango/pango-font.h | 38 | ||||
-rw-r--r-- | pango/pango-layout.c | 18 | ||||
-rw-r--r-- | pango/pango-layout.h | 2 | ||||
-rw-r--r-- | pango/pangox.c | 377 | ||||
-rw-r--r-- | pango/pangox.h | 20 | ||||
-rw-r--r-- | pango/utils.c | 53 |
18 files changed, 595 insertions, 135 deletions
@@ -1,8 +1,19 @@ -Tue Apr 4 12:01:37 2000 Owen Taylor <otaylor@redhat.com> +Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-context.h: Add user data to PangoContext + + * pango/pangox.[ch] examples/viewer.c: Rework system for create GC's + so that the necessary information is stored on the PangoContext + instead of being passed to layout_render() * pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9 wants UCS-4 not UCS2; switch accordingly. + * pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions + to get overall font metrics, possibly per-language. (Right now, + just font ascent, descent.) The implementation of this for + X is horribly complex. + Mon Apr 3 20:30:20 2000 Owen Taylor <otaylor@redhat.com> * pango/mapping.c (pango_glyph_string_x_to_index): Fix handling diff --git a/ChangeLog.pre-1-0 b/ChangeLog.pre-1-0 index e7eaf6e1..c63102c2 100644 --- a/ChangeLog.pre-1-0 +++ b/ChangeLog.pre-1-0 @@ -1,8 +1,19 @@ -Tue Apr 4 12:01:37 2000 Owen Taylor <otaylor@redhat.com> +Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-context.h: Add user data to PangoContext + + * pango/pangox.[ch] examples/viewer.c: Rework system for create GC's + so that the necessary information is stored on the PangoContext + instead of being passed to layout_render() * pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9 wants UCS-4 not UCS2; switch accordingly. + * pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions + to get overall font metrics, possibly per-language. (Right now, + just font ascent, descent.) The implementation of this for + X is horribly complex. + Mon Apr 3 20:30:20 2000 Owen Taylor <otaylor@redhat.com> * pango/mapping.c (pango_glyph_string_x_to_index): Fix handling diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10 index e7eaf6e1..c63102c2 100644 --- a/ChangeLog.pre-1-10 +++ b/ChangeLog.pre-1-10 @@ -1,8 +1,19 @@ -Tue Apr 4 12:01:37 2000 Owen Taylor <otaylor@redhat.com> +Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-context.h: Add user data to PangoContext + + * pango/pangox.[ch] examples/viewer.c: Rework system for create GC's + so that the necessary information is stored on the PangoContext + instead of being passed to layout_render() * pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9 wants UCS-4 not UCS2; switch accordingly. + * pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions + to get overall font metrics, possibly per-language. (Right now, + just font ascent, descent.) The implementation of this for + X is horribly complex. + Mon Apr 3 20:30:20 2000 Owen Taylor <otaylor@redhat.com> * pango/mapping.c (pango_glyph_string_x_to_index): Fix handling diff --git a/ChangeLog.pre-1-2 b/ChangeLog.pre-1-2 index e7eaf6e1..c63102c2 100644 --- a/ChangeLog.pre-1-2 +++ b/ChangeLog.pre-1-2 @@ -1,8 +1,19 @@ -Tue Apr 4 12:01:37 2000 Owen Taylor <otaylor@redhat.com> +Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-context.h: Add user data to PangoContext + + * pango/pangox.[ch] examples/viewer.c: Rework system for create GC's + so that the necessary information is stored on the PangoContext + instead of being passed to layout_render() * pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9 wants UCS-4 not UCS2; switch accordingly. + * pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions + to get overall font metrics, possibly per-language. (Right now, + just font ascent, descent.) The implementation of this for + X is horribly complex. + Mon Apr 3 20:30:20 2000 Owen Taylor <otaylor@redhat.com> * pango/mapping.c (pango_glyph_string_x_to_index): Fix handling diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4 index e7eaf6e1..c63102c2 100644 --- a/ChangeLog.pre-1-4 +++ b/ChangeLog.pre-1-4 @@ -1,8 +1,19 @@ -Tue Apr 4 12:01:37 2000 Owen Taylor <otaylor@redhat.com> +Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-context.h: Add user data to PangoContext + + * pango/pangox.[ch] examples/viewer.c: Rework system for create GC's + so that the necessary information is stored on the PangoContext + instead of being passed to layout_render() * pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9 wants UCS-4 not UCS2; switch accordingly. + * pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions + to get overall font metrics, possibly per-language. (Right now, + just font ascent, descent.) The implementation of this for + X is horribly complex. + Mon Apr 3 20:30:20 2000 Owen Taylor <otaylor@redhat.com> * pango/mapping.c (pango_glyph_string_x_to_index): Fix handling diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6 index e7eaf6e1..c63102c2 100644 --- a/ChangeLog.pre-1-6 +++ b/ChangeLog.pre-1-6 @@ -1,8 +1,19 @@ -Tue Apr 4 12:01:37 2000 Owen Taylor <otaylor@redhat.com> +Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-context.h: Add user data to PangoContext + + * pango/pangox.[ch] examples/viewer.c: Rework system for create GC's + so that the necessary information is stored on the PangoContext + instead of being passed to layout_render() * pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9 wants UCS-4 not UCS2; switch accordingly. + * pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions + to get overall font metrics, possibly per-language. (Right now, + just font ascent, descent.) The implementation of this for + X is horribly complex. + Mon Apr 3 20:30:20 2000 Owen Taylor <otaylor@redhat.com> * pango/mapping.c (pango_glyph_string_x_to_index): Fix handling diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8 index e7eaf6e1..c63102c2 100644 --- a/ChangeLog.pre-1-8 +++ b/ChangeLog.pre-1-8 @@ -1,8 +1,19 @@ -Tue Apr 4 12:01:37 2000 Owen Taylor <otaylor@redhat.com> +Tue Apr 4 20:13:06 2000 Owen Taylor <otaylor@redhat.com> + + * pango/pango-context.h: Add user data to PangoContext + + * pango/pangox.[ch] examples/viewer.c: Rework system for create GC's + so that the necessary information is stored on the PangoContext + instead of being passed to layout_render() * pango/utils.[ch] pango/pango-context.c: fribidi-0.1.9 wants UCS-4 not UCS2; switch accordingly. + * pango/fonts.c pango/pango-font.h pango/pangox.c: Add functions + to get overall font metrics, possibly per-language. (Right now, + just font ascent, descent.) The implementation of this for + X is horribly complex. + Mon Apr 3 20:30:20 2000 Owen Taylor <otaylor@redhat.com> * pango/mapping.c (pango_glyph_string_x_to_index): Fix handling @@ -38,6 +38,23 @@ X rendering as we are. There is a bit of fudging in the underline drawing code to deal with this and make the underlines look symetric. +* pangox.c/get_font_metrics_from_string() needs to gutted and + replaced with using pango_itemize(); to support this, we need + the ability to specifiy a particular font to use when itemizing. + This probably means adding a attribute type which contains + a PangoFont *, and overrides the description. + +* pangox.c needs to be split into at least two separate files. + + ( + Probably along the lines of + + 1) font map + 2) font + 3) rendering + ) + + Other rendering engines ======================= @@ -132,3 +149,8 @@ General characters in the glyph. (Trailing is currently a boolean for us.) +* pango_font_get_metrics() currently takes a language tag, but + really uses that to find out one or more _scripts_; should we + define script tags and put those (optionally?) in the + interface? + diff --git a/examples/viewer.c b/examples/viewer.c index c966865f..ccff0b77 100644 --- a/examples/viewer.c +++ b/examples/viewer.c @@ -289,17 +289,6 @@ size_allocate (GtkWidget *layout, GtkAllocation *allocation) gtk_adjustment_set_value (GTK_LAYOUT (layout)->vadjustment, height - allocation->height); } -GC -get_gc_func (PangoAttrColor *fg_color, void *data) -{ - return GDK_GC_XGC (data); -} - -void -free_gc_func (GC gc, void *data) -{ -} - /* Handle a draw/expose by finding the paragraphs that intersect * the region and reexposing them. */ @@ -326,8 +315,8 @@ draw (GtkWidget *layout, GdkRectangle *area) if (height + para->height >= GTK_LAYOUT (layout)->yoffset + area->y) pango_x_render_layout (GDK_DISPLAY(), GDK_WINDOW_XWINDOW (GTK_LAYOUT (layout)->bin_window), - para->layout, 0, height - GTK_LAYOUT (layout)->yoffset, - get_gc_func, free_gc_func, layout->style->text_gc[GTK_STATE_NORMAL]); + GDK_GC_XGC (layout->style->text_gc[GTK_STATE_NORMAL]), + para->layout, 0, height - GTK_LAYOUT (layout)->yoffset); height += para->height; } diff --git a/pango/fonts.c b/pango/fonts.c index 5b74a0f7..ad6de117 100644 --- a/pango/fonts.c +++ b/pango/fonts.c @@ -431,11 +431,13 @@ pango_font_unref (PangoFont *font) * font. */ void -pango_font_set_data (PangoFont *font, - gchar *key, +pango_font_set_data (PangoFont *font, + const gchar *key, gpointer data, GDestroyNotify destroy_func) { + g_return_if_fail (font != NULL); + g_datalist_set_data_full (&font->data, key, data, destroy_func); } @@ -449,9 +451,11 @@ pango_font_set_data (PangoFont *font, * Returns the data, or NULL if that key does not exist. */ gpointer -pango_font_get_data (PangoFont *font, - gchar *key) +pango_font_get_data (PangoFont *font, + const gchar *key) { + g_return_val_if_fail (font != NULL, NULL); + return g_datalist_get_data (&font->data, key); } @@ -521,7 +525,31 @@ pango_font_get_glyph_extents (PangoFont *font, font->klass->get_glyph_extents (font, glyph, ink_rect, logical_rect); } + +/** + * pango_font_get_metrics: + * @font: a #PangoFont + * @lang: language tag used to determine which script to get the metrics + * for, or %NULL to indicate to get the metrics for the entire + * font. + * @metrics: Structure to fill in with the metrics of the font + * + * Get overall metric information for a font. Since the metrics may be + * substantially different for different scripts, a language tag can + * be provided to indicate that the metrics should be retrieved that + * correspond to the script(s) used by that language. + **/ +void +pango_font_get_metrics (PangoFont *font, + const gchar *lang, + PangoFontMetrics *metrics) +{ + g_return_if_fail (font != NULL); + + font->klass->get_metrics (font, lang, metrics); +} + /** * pango_font_map_init: * @fontmap: a #PangoFontMap diff --git a/pango/pango-context.c b/pango/pango-context.c index 95c5bab2..c768c7d5 100644 --- a/pango/pango-context.c +++ b/pango/pango-context.c @@ -35,6 +35,7 @@ struct _PangoContext PangoFontDescription *font_desc; GSList *font_maps; + GData *data; }; static void add_engines (PangoContext *context, @@ -63,6 +64,7 @@ pango_context_new (void) result->base_dir = PANGO_DIRECTION_LTR; result->lang = NULL; result->font_maps = NULL; + result->data = NULL; desc.family_name = "serif"; desc.style = PANGO_STYLE_NORMAL; @@ -454,6 +456,44 @@ pango_context_get_base_dir (PangoContext *context) } /** + * pango_context_set_data: + * @context: a #PangoContext + * @key: the string key that identifies the data + * @data: the data to store + * @destroy_func: the function to free @data when it is no longer needed (may be %NULL) + * + * Adds user data to a #PangoContext. + **/ +void +pango_context_set_data (PangoContext *context, + const char *key, + gpointer data, + GDestroyNotify destroy_func) +{ + g_return_if_fail (context != NULL); + + g_datalist_set_data_full (&context->data, key, data, destroy_func); +} + +/** + * pango_context_get_data: + * @context: a #PangoContext + * @key: the string key that identifies the data + * + * Retrieves user data from a #PangoContext + * + * Return value: the data, if @key was found, or %NULL. + **/ +gpointer +pango_context_get_data (PangoContext *context, + const char *key) +{ + g_return_val_if_fail (context != NULL, NULL); + + return g_datalist_get_data (&context->data, key); +} + +/** * pango_itemize: * @context: a structure holding information that affects the itemization process. @@ -474,10 +514,9 @@ pango_itemize (PangoContext *context, PangoAttrList *attrs) { GUChar4 *text_ucs4; - gint n_chars; + int n_chars, i; guint8 *embedding_levels; FriBidiCharType base_dir; - gint i; PangoItem *item; const char *p; const char *next; @@ -502,7 +541,7 @@ pango_itemize (PangoContext *context, if (length == 0) return NULL; - + /* First, apply the bidirectional algorithm to break * the text into directional runs. */ @@ -513,6 +552,9 @@ pango_itemize (PangoContext *context, n_chars = unicode_strlen (text, length); embedding_levels = g_new (guint8, n_chars); + fribidi_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir, + embedding_levels); + /* Storing these as ranges would be a lot more efficient, * but also more complicated... we take the simple * approach for now. @@ -522,9 +564,6 @@ pango_itemize (PangoContext *context, fonts = g_new0 (PangoFont *, n_chars); extra_attr_lists = g_new0 (GSList *, n_chars); - fribidi_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir, - embedding_levels); - /* Now, fill in the appropriate shapers, language engines and fonts for * each character. */ diff --git a/pango/pango-context.h b/pango/pango-context.h index 9a5885c5..26228b1c 100644 --- a/pango/pango-context.h +++ b/pango/pango-context.h @@ -59,6 +59,13 @@ void pango_context_set_base_dir (PangoContext PangoDirection direction); PangoDirection pango_context_get_base_dir (PangoContext *context); +void pango_context_set_data (PangoContext *context, + const char *key, + gpointer data, + GDestroyNotify destroy_func); +gpointer pango_context_get_data (PangoContext *context, + const char *key); + /* Break a string of Unicode characters into segments with * consistent shaping/language engine and bidrectional level. * Returns a GList of PangoItem's diff --git a/pango/pango-font.h b/pango/pango-font.h index f6fd7ea4..063b0cea 100644 --- a/pango/pango-font.h +++ b/pango/pango-font.h @@ -33,6 +33,7 @@ typedef struct _PangoFontDescription PangoFontDescription; typedef struct _PangoFontClass PangoFontClass; typedef struct _PangoFontMap PangoFontMap; typedef struct _PangoFontMapClass PangoFontMapClass; +typedef struct _PangoFontMetrics PangoFontMetrics; typedef enum { PANGO_STYLE_NORMAL, @@ -74,6 +75,12 @@ struct _PangoFontDescription int size; }; +struct _PangoFontMetrics +{ + int ascent; + int descent; +}; + PangoFontDescription *pango_font_description_copy (const PangoFontDescription *desc); gboolean pango_font_description_compare (const PangoFontDescription *desc1, const PangoFontDescription *desc2); @@ -109,28 +116,35 @@ struct _PangoFontClass PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect); + void (*get_metrics) (PangoFont *font, + const gchar *lang, + PangoFontMetrics *metrics); }; 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); + const gchar *key); void pango_font_set_data (PangoFont *font, - gchar *key, + const gchar *key, gpointer data, GDestroyNotify destroy_func); -PangoFontDescription *pango_font_describe (PangoFont *font); -PangoCoverage * pango_font_get_coverage (PangoFont *font, - const char *lang); -PangoEngineShape * pango_font_find_shaper (PangoFont *font, - const char *lang, - guint32 ch); -void pango_font_get_glyph_extents (PangoFont *font, - PangoGlyph glyph, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); + +PangoFontDescription *pango_font_describe (PangoFont *font); +PangoCoverage * pango_font_get_coverage (PangoFont *font, + const char *lang); +PangoEngineShape * pango_font_find_shaper (PangoFont *font, + const char *lang, + guint32 ch); +void pango_font_get_metrics (PangoFont *font, + const gchar *lang, + PangoFontMetrics *metrics); +void pango_font_get_glyph_extents (PangoFont *font, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); /* * Font Map diff --git a/pango/pango-layout.c b/pango/pango-layout.c index ae499232..12076d33 100644 --- a/pango/pango-layout.c +++ b/pango/pango-layout.c @@ -144,6 +144,24 @@ pango_layout_unref (PangoLayout *layout) } /** + * pango_layout_get_context: + * @layout: a #PangoLayout + * + * Retrieves the #PangoContext used for this layout. + * + * Return value: The #PangoContext for the layout. This does not + * have an additional refcount added, so if you want to keep + * a copy of this around, you must reference it yourself. + **/ +PangoContext * +pango_layout_get_context (PangoLayout *layout) +{ + g_return_if_fail (layout != NULL); + + return layout->context; +} + +/** * pango_layout_set_width: * @layout: a #PangoLayout. * @width: the desired width, or -1 to indicate that no wrapping should be diff --git a/pango/pango-layout.h b/pango/pango-layout.h index c9a2f432..b1a9bf1e 100644 --- a/pango/pango-layout.h +++ b/pango/pango-layout.h @@ -58,6 +58,8 @@ void pango_layout_ref (PangoLayout *layout); void pango_layout_unref (PangoLayout *layout); +PangoContext *pango_layout_get_context (PangoLayout *layout); + void pango_layout_set_attributes (PangoLayout *layout, PangoAttrList *attrs); void pango_layout_set_text (PangoLayout *layout, diff --git a/pango/pangox.c b/pango/pangox.c index 64721c4c..1cfcd004 100644 --- a/pango/pangox.c +++ b/pango/pangox.c @@ -20,8 +20,11 @@ */ #include <X11/Xlib.h> +#include <fribidi/fribidi.h> +#include <unicode.h> #include "modules.h" #include "pangox.h" +#include "utils.h" #include <ctype.h> #include <math.h> #include <stdio.h> @@ -36,9 +39,12 @@ typedef struct _PangoXFontMap PangoXFontMap; typedef struct _PangoXSubfontInfo PangoXSubfontInfo; typedef struct _PangoXSizeInfo PangoXSizeInfo; +typedef struct _PangoXMetricsInfo PangoXMetricsInfo; typedef struct _PangoXFamilyEntry PangoXFamilyEntry; typedef struct _PangoXFontEntry PangoXFontEntry; +typedef struct _PangoXContextInfo PangoXContextInfo; + struct _PangoXSizeInfo { char *identifier; @@ -66,6 +72,12 @@ struct _PangoXSubfontInfo XFontStruct *font_struct; }; +struct _PangoXMetricsInfo +{ + const char *lang; + PangoFontMetrics metrics; +}; + struct _PangoXFont { PangoFont font; @@ -85,6 +97,8 @@ struct _PangoXFont int n_subfonts; int max_subfonts; + GSList *metrics_by_lang; + PangoXFontEntry *entry; /* Used to remove cached fonts */ }; @@ -102,6 +116,12 @@ struct _PangoXFontMap double resolution; /* (points / pixel) * PANGO_SCALE */ }; +struct _PangoXContextInfo +{ + PangoGetGCFunc get_gc_func; + PangoFreeGCFunc free_gc_func; +}; + /* This is the largest field length we will accept. If a fontname has a field larger than this we will skip it. */ #define XLFD_MAX_FIELD_LEN 64 @@ -174,17 +194,20 @@ static void pango_x_font_map_list_families (PangoFontMap * 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); -static PangoCoverage * pango_x_font_get_coverage (PangoFont *font, - const char *lang); -static PangoEngineShape * pango_x_font_find_shaper (PangoFont *font, - const char *lang, - guint32 ch); -static void pango_x_font_get_glyph_extents (PangoFont *font, - PangoGlyph glyph, - PangoRectangle *ink_rect, - PangoRectangle *logical_rect); +static void pango_x_font_destroy (PangoFont *font); +static PangoFontDescription *pango_x_font_describe (PangoFont *font); +static PangoCoverage * pango_x_font_get_coverage (PangoFont *font, + const char *lang); +static PangoEngineShape * pango_x_font_find_shaper (PangoFont *font, + const char *lang, + guint32 ch); +static void pango_x_font_get_glyph_extents (PangoFont *font, + PangoGlyph glyph, + PangoRectangle *ink_rect, + PangoRectangle *logical_rect); +static void pango_x_font_get_metrics (PangoFont *font, + const gchar *lang, + PangoFontMetrics *metrics); static PangoXSubfontInfo * pango_x_find_subfont (PangoFont *font, PangoXSubfont subfont_index); @@ -225,7 +248,8 @@ PangoFontClass pango_x_font_class = { pango_x_font_describe, pango_x_font_get_coverage, pango_x_font_find_shaper, - pango_x_font_get_glyph_extents + pango_x_font_get_glyph_extents, + pango_x_font_get_metrics }; PangoFontMapClass pango_x_font_map_class = { @@ -1206,23 +1230,64 @@ pango_x_insert_font (PangoXFontMap *xfontmap, } +/** + * pango_x_get_context: + * @display: an X display (As returned by XOpenDisplay().) + * + * Retrieves a #PangoContext appropriate for rendering with X fonts on the given display. + * + * Return value: the new #PangoContext + **/ PangoContext * pango_x_get_context (Display *display) { PangoContext *result; + PangoXContextInfo *info; + + g_return_val_if_fail (display != NULL, NULL); result = pango_context_new (); + + info = g_new (PangoXContextInfo, 1); + info->get_gc_func = NULL; + info->free_gc_func = NULL; + pango_context_set_data (result, "pango-x-info", info, (GDestroyNotify)g_free); + pango_context_add_font_map (result, pango_x_font_map_for_display (display)); return result; } /** + * pango_x_context_set_funcs: + * @context: a #PangoContext. + * @get_gc_func: function called to create a new GC for a given color. + * @free_gc_func: function called to free a GC created with @get_gc_func. + * + * Sets the functions that will be used to get GC's in various colors when + * rendering layouts with this context. + **/ +void +pango_x_context_set_funcs (PangoContext *context, + PangoGetGCFunc get_gc_func, + PangoFreeGCFunc free_gc_func) +{ + PangoXContextInfo *info; + + g_return_if_fail (context != NULL); + + info = pango_context_get_data (context, "pango-x-info"); + + info->get_gc_func = get_gc_func; + info->free_gc_func = free_gc_func; +} + +/** * 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 + * Loads up a logical font based on a "fontset" style * text specification. * * Returns a new #PangoFont @@ -1254,6 +1319,8 @@ pango_x_load_font (Display *display, result->n_subfonts = 0; result->max_subfonts = 1; + result->metrics_by_lang = NULL; + result->size = -1; result->entry = NULL; @@ -1299,6 +1366,8 @@ pango_x_load_font_with_size (Display *display, result->n_subfonts = 0; result->max_subfonts = 1; + result->metrics_by_lang = NULL; + result->size = size; result->entry = NULL; @@ -1417,6 +1486,236 @@ pango_x_font_get_glyph_extents (PangoFont *font, } } +/* Get composite font metrics for all subfonts in list + */ +static void +get_font_metrics_from_subfonts (PangoFont *font, + GSList *subfonts, + PangoFontMetrics *metrics) +{ + GSList *tmp_list = subfonts; + gboolean first = TRUE; + + metrics->ascent = 0; + metrics->descent = 0; + + while (tmp_list) + { + PangoXSubfontInfo *subfont = pango_x_find_subfont (font, GPOINTER_TO_UINT (tmp_list->data)); + + if (subfont) + { + XFontStruct *fs = pango_x_get_font_struct (font, subfont); + if (fs) + { + if (first) + { + metrics->ascent = fs->ascent * PANGO_SCALE; + metrics->descent = fs->descent * PANGO_SCALE; + first = FALSE; + } + else + { + metrics->ascent = MAX (fs->ascent * PANGO_SCALE, metrics->ascent); + metrics->descent = MAX (fs->descent * PANGO_SCALE, metrics->descent); + } + } + } + else + g_warning ("Invalid subfont %d in get_font_metrics_from_subfonts", GPOINTER_TO_UINT (tmp_list->data)); + + tmp_list = tmp_list->next; + } +} + +/* Get composite font metrics for all subfonts resulting from shaping + * string str with the given font + * + * This duplicates quite a bit of code from pango_itemize. This function + * should die and we should simply add the ability to specify particular + * fonts when itemizing. + */ +static void +get_font_metrics_from_string (PangoFont *font, + const char *lang, + const char *str, + PangoFontMetrics *metrics) +{ + const char *start, *p; + PangoGlyphString *glyph_str = pango_glyph_string_new (); + PangoEngineShape *shaper, *last_shaper; + int last_level; + GUChar4 *text_ucs4; + int n_chars, i; + guint8 *embedding_levels; + FriBidiCharType base_dir = PANGO_DIRECTION_LTR; + GSList *subfonts = NULL; + + n_chars = unicode_strlen (str, -1); + + text_ucs4 = _pango_utf8_to_ucs4 (str, strlen (str)); + if (!text_ucs4) + return; + + embedding_levels = g_new (guint8, n_chars); + fribidi_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir, + embedding_levels); + g_free (text_ucs4); + + last_shaper = NULL; + last_level = 0; + + i = 0; + p = start = str; + while (*p) + { + unicode_char_t wc; + p = unicode_get_utf8 (p, &wc); + + shaper = pango_font_find_shaper (font, lang, wc); + if (p > start && + (shaper != last_shaper || last_level != embedding_levels[i])) + { + PangoAnalysis analysis; + int j; + + analysis.shape_engine = shaper; + analysis.lang_engine = NULL; + analysis.font = font; + analysis.level = last_level; + + pango_shape (start, p - start, &analysis, glyph_str); + + for (j = 0; j < glyph_str->num_glyphs; j++) + { + PangoXSubfont subfont = PANGO_X_GLYPH_SUBFONT (glyph_str->glyphs[j].glyph); + if (!g_slist_find (subfonts, GUINT_TO_POINTER ((guint)subfont))) + subfonts = g_slist_prepend (subfonts, GUINT_TO_POINTER ((guint)subfont)); + } + + start = p; + } + + last_shaper = shaper; + last_level = embedding_levels[i]; + i++; + } + + get_font_metrics_from_subfonts (font, subfonts, metrics); + g_slist_free (subfonts); + + pango_glyph_string_free (glyph_str); + g_free (embedding_levels); +} + +typedef struct { + const char *lang; + const char *str; +} LangInfo; + +int +lang_info_compare (const void *key, const void *val) +{ + const LangInfo *lang_info = val; + + return strncmp (key, lang_info->lang, 2); +} + +/* The following array is supposed to contain enough text to tickle all necessary fonts for each + * of the languages in the following. Yes, it's pretty lame. Not all of the languages + * in the following have sufficient text to excercise all the accents for the language, and + * there are obviously many more languages to include as well. + */ +LangInfo lang_texts[] = { + { "ar", "Arabic السلام عليكم" }, + { "cs", "Czech (česky) Dobrý den" }, + { "da", "Danish (Dansk) Hej, Goddag" }, + { "el", "Greek (Ελληνικά) Γειά σας" }, + { "en", "English Hello" }, + { "eo", "Esperanto Saluton" }, + { "es", "Spanish (Español) ¡Hola!" }, + { "et", "Estonian Tere, Tervist" }, + { "fi", "Finnish (Suomi) Hei" }, + { "fr", "French (Français)" }, + { "de", "German Grüß Gott" }, + { "iw", "Hebrew שלום" }, + { "il", "Italiano Ciao, Buon giorno" }, + { "ja", "Japanese (日本語) こんにちは, コンニチハ" }, + { "ko", "Korean (한글) 안녕하세요, 안녕하십니까" }, + { "mt", "Maltese Ċaw, Saħħa" }, + { "nl", "Nederlands, Vlaams Hallo, Dag" }, + { "no", "Norwegian (Norsk) Hei, God dag" }, + { "pl", "Polish Dzień dobry, Hej" }, + { "ru", "Russian (Русский)" }, + { "sk", "Slovak Dobrý deň" }, + { "sv", "Swedish (Svenska) Hej, Goddag" }, + { "tr", "Turkish (Türkçe) Merhaba" }, + { "zh", "Chinese (中文,普通话,汉语)" } +}; + +static void +pango_x_font_get_metrics (PangoFont *font, + const gchar *lang, + PangoFontMetrics *metrics) +{ + PangoXMetricsInfo *info; + PangoXFont *xfont = (PangoXFont *)font; + GSList *tmp_list; + + const char *lookup_lang; + const char *str; + + if (lang) + { + LangInfo *lang_info = bsearch (lang, lang_texts, + G_N_ELEMENTS (lang_texts), sizeof (LangInfo), + lang_info_compare); + + if (lang_info) + { + lookup_lang = lang_info->lang; + str = lang_info->str; + } + else + { + lookup_lang = "UNKNOWN"; + str = "French (Français)"; /* Assume iso-8859-1 */ + } + } + else + { + lookup_lang = "NONE"; + + /* Complete junk + */ + str = "السلام عليكم česky Ελληνικά Français 日本語 한글 Русский 中文,普通话,汉语 Türkçe"; + } + + tmp_list = xfont->metrics_by_lang; + while (tmp_list) + { + info = tmp_list->data; + + if (info->lang == lookup_lang) /* We _don't_ need strcmp */ + break; + + tmp_list = tmp_list->next; + } + + if (!tmp_list) + { + info = g_new (PangoXMetricsInfo, 1); + info->lang = lookup_lang; + + xfont->metrics_by_lang = g_slist_prepend (xfont->metrics_by_lang, info); + + get_font_metrics_from_string (font, lang, str, &info->metrics); + } + + *metrics = info->metrics; + return; +} + /* Compare the tail of a to b */ static gboolean match_end (char *a, char *b) @@ -1753,6 +2052,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); + g_slist_foreach (xfont->metrics_by_lang, (GFunc)g_free, NULL); + g_slist_free (xfont->metrics_by_lang); + if (xfont->entry) xfont->entry->cached_fonts = g_slist_remove (xfont->entry->cached_fonts, xfont); @@ -2013,32 +2315,31 @@ pango_x_get_unknown_glyph (PangoFont *font) * pango_x_render_layout_line: * @display: the X display * @drawable: the drawable on which to draw string + * @gc: GC to use for uncolored drawing * @line: a #PangoLayoutLine * @x: the x position of start of string (in pixels) * @y: the y position of baseline (in pixels) - * @get_gc: function to call to retrieve a GC for a particular color - * @free_gc: function to call to free a GC retrieved from get_gc - * @user_data: extra data to pass to get_gc and free_gc * * Render a #PangoLayoutLine onto an X drawable */ void pango_x_render_layout_line (Display *display, Drawable drawable, + GC gc, PangoLayoutLine *line, int x, - int y, - PangoGetGCFunc get_gc, - PangoFreeGCFunc free_gc, - gpointer user_data) + int y) { GSList *tmp_list = line->runs; + PangoRectangle overall_rect; PangoRectangle logical_rect; PangoRectangle ink_rect; + PangoContext *context = pango_layout_get_context (line->layout); + PangoXContextInfo *info = pango_context_get_data (context, "pango-x-info"); int x_off = 0; - pango_layout_line_get_extents (line,NULL, &logical_rect); + pango_layout_line_get_extents (line,NULL, &overall_rect); while (tmp_list) { @@ -2052,10 +2353,10 @@ pango_x_render_layout_line (Display *display, pango_x_get_item_properties (run->item, &uline, &fg_color, &fg_set, &bg_color, &bg_set); - if (fg_set) - fg_gc = (*get_gc) (&fg_color, user_data); + if (fg_set && info->get_gc_func) + fg_gc = info->get_gc_func (context, &fg_color, gc); else - fg_gc = (*get_gc) (NULL, user_data); + fg_gc = gc; if (uline == PANGO_UNDERLINE_NONE) pango_glyph_string_extents (run->glyphs, run->item->analysis.font, @@ -2064,17 +2365,18 @@ pango_x_render_layout_line (Display *display, pango_glyph_string_extents (run->glyphs, run->item->analysis.font, &ink_rect, &logical_rect); - if (bg_set) + if (bg_set && info->get_gc_func) { - GC bg_gc = (*get_gc) (&bg_color, user_data); + GC bg_gc = info->get_gc_func (context, &bg_color, gc); XFillRectangle (display, drawable, bg_gc, x + (x_off + logical_rect.x) / PANGO_SCALE, - y + logical_rect.y / PANGO_SCALE, + y + overall_rect.y / PANGO_SCALE, logical_rect.width / PANGO_SCALE, - logical_rect.height / PANGO_SCALE); + overall_rect.height / PANGO_SCALE); - (*free_gc) (bg_gc, user_data); + if (info->free_gc_func) + info->free_gc_func (context, bg_gc); } pango_x_render (display, drawable, fg_gc, run->item->analysis.font, run->glyphs, @@ -2101,7 +2403,8 @@ pango_x_render_layout_line (Display *display, break; } - (*free_gc) (fg_gc, user_data); + if (fg_set && info->get_gc_func && info->free_gc_func) + info->free_gc_func (context, fg_gc); x_off += logical_rect.width; } @@ -2111,11 +2414,10 @@ pango_x_render_layout_line (Display *display, * pango_x_render_layout: * @display: the X display * @drawable: the drawable on which to draw string + * @gc: GC to use for uncolored drawing * @layout: a #PangoLayout * @x: the X position of the left of the layout (in pixels) * @y: the Y position of the top of the layout (in pixels) - * @get_gc: function to call to retrieve a GC for a particular color - * @free_gc: function to call to free a GC retrieved from get_gc * @user_data: extra data to pass to get_gc and free_gc * * Render a #PangoLayoutLine onto an X drawable @@ -2123,12 +2425,10 @@ pango_x_render_layout_line (Display *display, void pango_x_render_layout (Display *display, Drawable drawable, + GC gc, PangoLayout *layout, int x, - int y, - PangoGetGCFunc get_gc, - PangoFreeGCFunc free_gc, - gpointer user_data) + int y) { PangoRectangle logical_rect; GSList *tmp_list; @@ -2190,9 +2490,8 @@ pango_x_render_layout (Display *display, } } - pango_x_render_layout_line (display, drawable, - line, x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE, - get_gc, free_gc, user_data); + pango_x_render_layout_line (display, drawable, gc, + line, x + x_offset / PANGO_SCALE, y + (y_offset - logical_rect.y) / PANGO_SCALE); y_offset += logical_rect.height; tmp_list = tmp_list->next; diff --git a/pango/pangox.h b/pango/pangox.h index 3460263d..abdf148f 100644 --- a/pango/pangox.h +++ b/pango/pangox.h @@ -33,12 +33,16 @@ extern "C" { #define PANGO_RENDER_TYPE_X "PangoRenderX" -typedef GC (*PangoGetGCFunc) (PangoAttrColor *color, void *user_data); -typedef void (*PangoFreeGCFunc) (GC gc, void *user_data); +typedef GC (*PangoGetGCFunc) (PangoContext *context, PangoAttrColor *color, GC base_gc); +typedef void (*PangoFreeGCFunc) (PangoContext *context, GC gc); /* Calls for applications */ PangoContext * pango_x_get_context (Display *display); +void pango_x_context_set_funcs (PangoContext *context, + PangoGetGCFunc get_gc_func, + PangoFreeGCFunc free_gc_func); + PangoFont * pango_x_load_font (Display *display, gchar *spec); void pango_x_render (Display *display, @@ -50,20 +54,16 @@ void pango_x_render (Display *display, gint y); void pango_x_render_layout_line (Display *display, Drawable drawable, + GC gc, PangoLayoutLine *line, int x, - int y, - PangoGetGCFunc get_gc, - PangoFreeGCFunc free_gc, - gpointer user_data); + int y); void pango_x_render_layout (Display *display, Drawable drawable, + GC gc, PangoLayout *layout, int x, - int y, - PangoGetGCFunc get_gc, - PangoFreeGCFunc free_gc, - gpointer user_data); + int y); /* API for rendering modules */ diff --git a/pango/utils.c b/pango/utils.c index 5a04ccc7..6f7ff8ca 100644 --- a/pango/utils.c +++ b/pango/utils.c @@ -153,56 +153,21 @@ _pango_utf8_to_ucs2 (const char *str, int len) } -#ifdef __GLIBC__ -# define UCS4_CHARSET "UNICODELITTLE" -#else -# if G_BYTE_ORDER == G_LITTLE_ENDIAN -# define UCS4_CHARSET "UCS-4-LE" -# else -# define UCS4_CHARSET "UCS-4-BE" -# endif -#endif - GUChar4 * _pango_utf8_to_ucs4 (const char *str, int len) { - iconv_t cd; - char *outbuf, *result; - const char *inbuf; - size_t inbytesleft; - size_t outbytesleft; - gint outlen; - - gint count; - - cd = iconv_open (UCS4_CHARSET, "UTF-8"); + GUChar4 *result; + int n_chars, i; + const char *p; - if (cd == (iconv_t)-1) - g_error ("No converter from UTF-8 to " UCS4_CHARSET); - - if (len < 0) - len = strlen (str); - - outlen = unicode_strlen (str, len) * sizeof(GUChar4); - 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); + n_chars = unicode_strlen (str, len); + result = g_new (GUChar4, n_chars); - return (GUChar4 *)result; + p = str; + for (i=0; i < n_chars; i++) + p = unicode_get_utf8 (p, &result[i]); + return result; } /** |