diff options
Diffstat (limited to 'pango/pangox.c')
-rw-r--r-- | pango/pangox.c | 1331 |
1 files changed, 15 insertions, 1316 deletions
diff --git a/pango/pangox.c b/pango/pangox.c index d45989bf..407aa574 100644 --- a/pango/pangox.c +++ b/pango/pangox.c @@ -19,53 +19,23 @@ * Boston, MA 02111-1307, USA. */ +#include <string.h> +#include <math.h> + #include <X11/Xlib.h> #include <fribidi/fribidi.h> #include <unicode.h> -#include "modules.h" #include "pangox.h" +#include "pangox-private.h" + #include "utils.h" -#include <ctype.h> -#include <math.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> #include <config.h> -typedef struct _PangoXFont PangoXFont; -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; - GSList *xlfds; -}; - -struct _PangoXFontEntry -{ - char *xlfd; - PangoFontDescription description; - PangoCoverage *coverage; - - GSList *cached_fonts; -}; - -struct _PangoXFamilyEntry -{ - char *family_name; - GSList *font_entries; -}; - struct _PangoXSubfontInfo { char *xlfd; @@ -81,122 +51,12 @@ struct _PangoXMetricsInfo PangoFontMetrics metrics; }; -struct _PangoXFont -{ - PangoFont font; - Display *display; - - char **fonts; - int n_fonts; - int size; - - /* hash table mapping from charset-name to array of PangoXSubfont ids, - * of length n_fonts - */ - GHashTable *subfonts_by_charset; - - PangoXSubfontInfo **subfonts; - - int n_subfonts; - int max_subfonts; - - GSList *metrics_by_lang; - - PangoXFontEntry *entry; /* Used to remove cached fonts */ -}; - -struct _PangoXFontMap -{ - PangoFontMap fontmap; - - Display *display; - - GHashTable *families; - GHashTable *size_infos; - - int n_fonts; - - 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 -#define MAX_FONTS 32767 - -/* These are the field numbers in the X Logical Font Description fontnames, - e.g. -adobe-courier-bold-o-normal--25-180-100-100-m-150-iso8859-1 */ -typedef enum -{ - XLFD_FOUNDRY = 0, - XLFD_FAMILY = 1, - XLFD_WEIGHT = 2, - XLFD_SLANT = 3, - XLFD_SET_WIDTH = 4, - XLFD_ADD_STYLE = 5, - XLFD_PIXELS = 6, - XLFD_POINTS = 7, - XLFD_RESOLUTION_X = 8, - XLFD_RESOLUTION_Y = 9, - XLFD_SPACING = 10, - XLFD_AVERAGE_WIDTH = 11, - XLFD_CHARSET = 12, - XLFD_NUM_FIELDS -} FontField; - -const struct { - const gchar *text; - PangoWeight value; -} weights_map[] = { - { "light", 300 }, - { "regular", 400 }, - { "book", 400 }, - { "medium", 500 }, - { "semibold", 600 }, - { "demibold", 600 }, - { "bold", 700 }, - { "extrabold", 800 }, - { "ultrabold", 800 }, - { "heavy", 900 }, - { "black", 900 } -}; - -const struct { - const gchar *text; - PangoStyle value; -} styles_map[] = { - { "r", PANGO_STYLE_NORMAL }, - { "i", PANGO_STYLE_ITALIC }, - { "o", PANGO_STYLE_OBLIQUE } -}; - -const struct { - const gchar *text; - PangoStretch value; -} stretches_map[] = { - { "normal", PANGO_STRETCH_NORMAL }, - { "semicondensed", PANGO_STRETCH_SEMI_CONDENSED }, - { "condensed", PANGO_STRETCH_CONDENSED }, -}; - -static void pango_x_font_map_destroy (PangoFontMap *fontmap); -static PangoFont *pango_x_font_map_load_font (PangoFontMap *fontmap, - const PangoFontDescription *desc); -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); static PangoCoverage * pango_x_font_get_coverage (PangoFont *font, @@ -224,19 +84,6 @@ static gboolean pango_x_find_glyph (PangoFont *font, static XFontStruct * pango_x_get_font_struct (PangoFont *font, PangoXSubfontInfo *info); -static PangoFont *pango_x_load_font_with_size (Display *display, - char *spec, - int size); - -static gboolean pango_x_is_xlfd_font_name (const char *fontname); -static char * pango_x_get_xlfd_field (const char *fontname, - FontField field_num, - char *buffer); -static char * pango_x_get_identifier (const char *fontname); -static gint pango_x_get_size (PangoXFontMap *fontmap, - const char *fontname); -static void pango_x_insert_font (PangoXFontMap *fontmap, - const char *fontname); static void pango_x_get_item_properties (PangoItem *item, PangoUnderline *uline, PangoAttrColor *fg_color, @@ -244,8 +91,6 @@ static void pango_x_get_item_properties (PangoItem *item, PangoAttrColor *bg_color, gboolean *bg_set); -static GList *fontmaps; - PangoFontClass pango_x_font_class = { pango_x_font_destroy, pango_x_font_describe, @@ -255,13 +100,6 @@ PangoFontClass pango_x_font_class = { pango_x_font_get_metrics }; -PangoFontMapClass pango_x_font_map_class = { - pango_x_font_map_destroy, - pango_x_font_map_load_font, - pango_x_font_map_list_fonts, - pango_x_font_map_list_families -}; - static inline PangoXSubfontInfo * pango_x_find_subfont (PangoFont *font, PangoXSubfont subfont_index) @@ -300,981 +138,6 @@ pango_x_get_font_struct (PangoFont *font, PangoXSubfontInfo *info) return info->font_struct; } -static PangoFontMap * -pango_x_font_map_for_display (Display *display) -{ - PangoXFontMap *xfontmap; - GList *tmp_list = fontmaps; - char **xfontnames; - int num_fonts, i; - int screen; - - while (tmp_list) - { - xfontmap = tmp_list->data; - - if (xfontmap->display == display) - { - pango_font_map_ref ((PangoFontMap *)xfontmap); - return (PangoFontMap *)xfontmap; - } - } - - xfontmap = g_new (PangoXFontMap, 1); - - xfontmap->fontmap.klass = &pango_x_font_map_class; - xfontmap->display = display; - xfontmap->families = g_hash_table_new (g_str_hash, g_str_equal); - xfontmap->size_infos = g_hash_table_new (g_str_hash, g_str_equal); - xfontmap->n_fonts = 0; - - pango_font_map_init ((PangoFontMap *)xfontmap); - - /* Get a maximum of MAX_FONTS fontnames from the X server. - Use "-*" as the pattern rather than "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" since - the latter may result in fonts being returned which don't actually exist. - xlsfonts also uses "*" so I think it's OK. "-*" gets rid of aliases. */ - xfontnames = XListFonts (xfontmap->display, "-*", MAX_FONTS, &num_fonts); - if (num_fonts == MAX_FONTS) - g_warning("MAX_FONTS exceeded. Some fonts may be missing."); - - /* Insert the font families into the main table */ - for (i = 0; i < num_fonts; i++) - { - if (pango_x_is_xlfd_font_name (xfontnames[i])) - pango_x_insert_font (xfontmap, xfontnames[i]); - } - - XFreeFontNames (xfontnames); - - pango_x_font_map_read_aliases (xfontmap); - - fontmaps = g_list_prepend (fontmaps, xfontmap); - - /* This is a little screwed up, since different screens on the same display - * might have different resolutions - */ - screen = DefaultScreen (xfontmap->display); - xfontmap->resolution = (PANGO_SCALE * 72.27 / 25.4) * ((double) DisplayWidthMM (xfontmap->display, screen) / - DisplayWidth (xfontmap->display, screen)); - - return (PangoFontMap *)xfontmap; -} - -static void -pango_x_font_map_destroy (PangoFontMap *fontmap) -{ - fontmaps = g_list_remove (fontmaps, fontmap); - - g_free (fontmap); -} - -static PangoXFamilyEntry * -pango_x_get_family_entry (PangoXFontMap *xfontmap, - const char *family_name) -{ - PangoXFamilyEntry *family_entry = g_hash_table_lookup (xfontmap->families, family_name); - if (!family_entry) - { - family_entry = g_new (PangoXFamilyEntry, 1); - family_entry->family_name = g_strdup (family_name); - family_entry->font_entries = NULL; - - g_hash_table_insert (xfontmap->families, family_entry->family_name, family_entry); - } - - return family_entry; -} - -static PangoFont * -pango_x_font_map_load_font (PangoFontMap *fontmap, - const PangoFontDescription *description) -{ - PangoXFontMap *xfontmap = (PangoXFontMap *)fontmap; - PangoXFamilyEntry *family_entry; - PangoFont *result = NULL; - GSList *tmp_list; - gchar *name; - - g_return_val_if_fail (description != NULL, NULL); - g_return_val_if_fail (description->size > 0, NULL); - - name = g_strdup (description->family_name); - g_strdown (name); - - family_entry = g_hash_table_lookup (xfontmap->families, name); - if (family_entry) - { - PangoXFontEntry *best_match = NULL; - - tmp_list = family_entry->font_entries; - while (tmp_list) - { - PangoXFontEntry *font_entry = tmp_list->data; - - if (font_entry->description.style == description->style && - font_entry->description.variant == description->variant && - font_entry->description.stretch == description->stretch) - { - int distance = abs(font_entry->description.weight - description->weight); - int old_distance = best_match ? abs(best_match->description.weight - description->weight) : G_MAXINT; - - if (distance < old_distance) - { - best_match = font_entry; - } - } - - tmp_list = tmp_list->next; - } - - if (best_match) - { - GSList *tmp_list = best_match->cached_fonts; - - while (tmp_list) - { - PangoXFont *xfont = tmp_list->data; - if (xfont->size == description->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, description->size); - ((PangoXFont *)result)->entry = best_match; - best_match->cached_fonts = g_slist_prepend (best_match->cached_fonts, result); - } - - /* HORRIBLE performance hack until some better caching scheme is arrived at - */ - if (result) - pango_font_ref (result); - } - } - - g_free (name); - return result; -} - -typedef struct -{ - int n_found; - PangoFontDescription **descs; -} ListFontsInfo; - -static void -list_fonts_foreach (gpointer key, gpointer value, gpointer user_data) -{ - PangoXFamilyEntry *entry = value; - ListFontsInfo *info = user_data; - - GSList *tmp_list = entry->font_entries; - - while (tmp_list) - { - PangoXFontEntry *font_entry = tmp_list->data; - - info->descs[info->n_found++] = pango_font_description_copy (&font_entry->description); - tmp_list = tmp_list->next; - } -} - -static void -pango_x_font_map_list_fonts (PangoFontMap *fontmap, - const gchar *family, - PangoFontDescription ***descs, - int *n_descs) -{ - PangoXFontMap *xfontmap = (PangoXFontMap *)fontmap; - ListFontsInfo info; - - if (!n_descs) - return; - - if (family) - { - PangoXFamilyEntry *entry = g_hash_table_lookup (xfontmap->families, family); - if (entry) - { - *n_descs = g_slist_length (entry->font_entries); - if (descs) - { - *descs = g_new (PangoFontDescription *, *n_descs); - - info.descs = *descs; - info.n_found = 0; - - list_fonts_foreach ((gpointer)family, (gpointer)entry, &info); - } - } - else - { - *n_descs = 0; - if (descs) - *descs = NULL; - } - } - else - { - *n_descs = xfontmap->n_fonts; - if (descs) - { - *descs = g_new (PangoFontDescription *, xfontmap->n_fonts); - - info.descs = *descs; - info.n_found = 0; - - g_hash_table_foreach (xfontmap->families, list_fonts_foreach, &info); - } - } -} - -static void -list_families_foreach (gpointer key, gpointer value, gpointer user_data) -{ - GSList **list = user_data; - - *list = g_slist_prepend (*list, key); -} - -static void -pango_x_font_map_list_families (PangoFontMap *fontmap, - gchar ***families, - int *n_families) -{ - GSList *family_list = NULL; - GSList *tmp_list; - PangoXFontMap *xfontmap = (PangoXFontMap *)fontmap; - - if (!n_families) - return; - - g_hash_table_foreach (xfontmap->families, list_families_foreach, &family_list); - - *n_families = g_slist_length (family_list); - - if (families) - { - int i = 0; - - *families = g_new (gchar *, *n_families); - - tmp_list = family_list; - while (tmp_list) - { - (*families)[i] = g_strdup (tmp_list->data); - i++; - tmp_list = tmp_list->next; - } - } - - g_slist_free (family_list); -} - -/* Similar to GNU libc's getline, but buffer is g_malloc'd */ -static size_t -pango_getline (char **lineptr, size_t *n, FILE *stream) -{ -#define EXPAND_CHUNK 16 - - int n_read = 0; - int result = -1; - - g_return_val_if_fail (lineptr != NULL, -1); - g_return_val_if_fail (n != NULL, -1); - g_return_val_if_fail (*lineptr != NULL || *n == 0, -1); - -#ifdef HAVE_FLOCKFILE - flockfile (stream); -#endif - - while (1) - { - int c; - -#ifdef HAVE_FLOCKFILE - c = getc_unlocked (stream); -#else - c = getc (stream); -#endif - - if (c == EOF) - { - if (n_read > 0) - { - result = n_read; - (*lineptr)[n_read] = '\0'; - } - break; - } - - if (n_read + 2 >= *n) - { - *n += EXPAND_CHUNK; - *lineptr = g_realloc (*lineptr, *n); - } - - (*lineptr)[n_read] = c; - n_read++; - - if (c == '\n' || c == '\r') - { - result = n_read; - (*lineptr)[n_read] = '\0'; - break; - } - } - -#ifdef HAVE_FLOCKFILE - funlockfile (stream); -#endif - - return n_read - 1; -} - -static int -find_tok (char **start, char **tok) -{ - char *p = *start; - - while (*p && (*p == ' ' || *p == '\t')) - p++; - - if (*p == 0 || *p == '\n' || *p == '\r') - return -1; - - if (*p == '"') - { - p++; - *tok = p; - - while (*p && *p != '"') - p++; - - if (*p != '"') - return -1; - - *start = p + 1; - return p - *tok; - } - else - { - *tok = p; - - while (*p && *p != ' ' && *p != '\t' && *p != '\r' && *p != '\n') - p++; - - *start = p; - return p - *tok; - } -} - -static gboolean -get_style (char *tok, int toksize, PangoFontDescription *desc) -{ - if (toksize == 0) - return FALSE; - - switch (tok[0]) - { - case 'n': - case 'N': - if (strncasecmp (tok, "normal", toksize) == 0) - { - desc->style = PANGO_STYLE_NORMAL; - return TRUE; - } - break; - case 'i': - if (strncasecmp (tok, "italic", toksize) == 0) - { - desc->style = PANGO_STYLE_ITALIC; - return TRUE; - } - break; - case 'o': - if (strncasecmp (tok, "oblique", toksize) == 0) - { - desc->style = PANGO_STYLE_OBLIQUE; - return TRUE; - } - break; - } - g_warning ("Style must be normal, italic, or oblique"); - - return FALSE; -} - -static gboolean -get_variant (char *tok, int toksize, PangoFontDescription *desc) -{ - if (toksize == 0) - return FALSE; - - switch (tok[0]) - { - case 'n': - case 'N': - if (strncasecmp (tok, "normal", toksize) == 0) - { - desc->variant = PANGO_VARIANT_NORMAL; - return TRUE; - } - break; - case 's': - case 'S': - if (strncasecmp (tok, "small_caps", toksize) == 0) - { - desc->variant = PANGO_VARIANT_SMALL_CAPS; - return TRUE; - } - break; - } - - g_warning ("Variant must be normal, or small_caps"); - return FALSE; -} - -static gboolean -get_weight (char *tok, int toksize, PangoFontDescription *desc) -{ - if (toksize == 0) - return FALSE; - - switch (tok[0]) - { - case 'n': - case 'N': - if (strncasecmp (tok, "normal", toksize) == 0) - { - desc->weight = PANGO_WEIGHT_NORMAL; - return TRUE; - } - break; - case 'b': - case 'B': - if (strncasecmp (tok, "bold", toksize) == 0) - { - desc->weight = PANGO_WEIGHT_BOLD; - return TRUE; - } - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - char *numstr, *end; - - numstr = g_strndup (tok, toksize); - - desc->weight = strtol (numstr, &end, 0); - if (*end != '\0') - { - g_warning ("Cannot parse numerical weight '%s'", numstr); - g_free (numstr); - return FALSE; - } - - g_free (numstr); - return TRUE; - } - } - - g_warning ("Weight must be normal, bold, or an integer"); - return FALSE; -} - -static gboolean -get_stretch (char *tok, int toksize, PangoFontDescription *desc) -{ - if (toksize == 0) - return FALSE; - - switch (tok[0]) - { - case 'c': - case 'C': - if (strncasecmp (tok, "condensed", toksize) == 0) - { - desc->stretch = PANGO_STRETCH_CONDENSED; - return TRUE; - } - break; - case 'e': - case 'E': - if (strncasecmp (tok, "extra_condensed", toksize) == 0) - { - desc->stretch = PANGO_STRETCH_EXTRA_CONDENSED; - return TRUE; - } - if (strncasecmp (tok, "extra_expanded", toksize) == 0) - { - desc->stretch = PANGO_STRETCH_EXTRA_EXPANDED; - return TRUE; - } - if (strncasecmp (tok, "expanded", toksize) == 0) - { - desc->stretch = PANGO_STRETCH_EXPANDED; - return TRUE; - } - break; - case 'n': - case 'N': - if (strncasecmp (tok, "normal", toksize) == 0) - { - desc->stretch = PANGO_STRETCH_NORMAL; - return TRUE; - } - break; - case 's': - case 'S': - if (strncasecmp (tok, "semi_condensed", toksize) == 0) - { - desc->stretch = PANGO_STRETCH_SEMI_CONDENSED; - return TRUE; - } - if (strncasecmp (tok, "semi_expanded", toksize) == 0) - { - desc->stretch = PANGO_STRETCH_SEMI_EXPANDED; - return TRUE; - } - break; - case 'u': - case 'U': - if (strncasecmp (tok, "ultra_condensed", toksize) == 0) - { - desc->stretch = PANGO_STRETCH_ULTRA_CONDENSED; - return TRUE; - } - if (strncasecmp (tok, "ultra_expanded", toksize) == 0) - { - desc->variant = PANGO_STRETCH_ULTRA_EXPANDED; - return TRUE; - } - break; - } - - g_warning ("Stretch must be ultra_condensed, extra_condensed, condensed, semi_condensed, normal, semi_expanded, expanded, extra_expanded, or ultra_expanded"); - return FALSE; -} - -static void -pango_x_font_map_read_alias_file (PangoXFontMap *xfontmap, - const char *filename) -{ - FILE *infile; - char **xlfds; - char *buf = NULL; - size_t bufsize = 0; - int lineno = 0; - int i; - PangoXFontEntry *font_entry = NULL; - - infile = fopen (filename, "r"); - if (infile) - { - while (pango_getline (&buf, &bufsize, infile) != EOF) - { - PangoXFamilyEntry *family_entry; - - char *tok; - char *p = buf; - - int toksize; - lineno++; - - while (*p && (*p == ' ' || *p == '\t')) - p++; - - if (*p == 0 || *p == '#' || *p == '\n' || *p == '\r') - continue; - - toksize = find_tok (&p, &tok); - if (toksize == -1) - goto error; - - font_entry = g_new (PangoXFontEntry, 1); - font_entry->xlfd = NULL; - font_entry->description.family_name = g_strndup (tok, toksize); - g_strdown (font_entry->description.family_name); - - toksize = find_tok (&p, &tok); - if (toksize == -1) - goto error; - - if (!get_style (tok, toksize, &font_entry->description)) - goto error; - - toksize = find_tok (&p, &tok); - if (toksize == -1) - goto error; - - if (!get_variant (tok, toksize, &font_entry->description)) - goto error; - - toksize = find_tok (&p, &tok); - if (toksize == -1) - goto error; - - if (!get_weight (tok, toksize, &font_entry->description)) - goto error; - - toksize = find_tok (&p, &tok); - if (toksize == -1) - goto error; - - if (!get_stretch (tok, toksize, &font_entry->description)) - goto error; - - toksize = find_tok (&p, &tok); - if (toksize == -1) - goto error; - - font_entry->xlfd = g_strndup (tok, toksize); - - /* Check for complete fields */ - - xlfds = g_strsplit (font_entry->xlfd, ",", -1); - for (i=0; xlfds[i]; i++) - if (!pango_x_is_xlfd_font_name (xlfds[i])) - { - g_warning ("XLFD '%s' must be complete (14 fields)", xlfds[i]); - g_strfreev (xlfds); - goto error; - } - - g_strfreev (xlfds); - - - /* Insert the font entry into our structures */ - - family_entry = pango_x_get_family_entry (xfontmap, font_entry->description.family_name); - family_entry->font_entries = g_slist_prepend (family_entry->font_entries, font_entry); - xfontmap->n_fonts++; - - 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)) - g_warning ("Error reading '%s': %s", filename, g_strerror(errno)); - - goto out; - - error: - if (font_entry) - { - if (font_entry->xlfd) - g_free (font_entry->xlfd); - if (font_entry->description.family_name) - g_free (font_entry->description.family_name); - g_free (font_entry); - } - - g_warning ("Error parsing line %d of alias file '%s'", lineno, filename); - - out: - g_free (buf); - fclose (infile); - return; - } - -} - -static void -pango_x_font_map_read_aliases (PangoXFontMap *xfontmap) -{ - char *filename; - - pango_x_font_map_read_alias_file (xfontmap, SYSCONFDIR "/pango/pangox_aliases"); - - filename = g_strconcat (g_get_home_dir(), "/.pangox_aliases", NULL); - pango_x_font_map_read_alias_file (xfontmap, filename); - g_free (filename); - - /* FIXME: Remove this one */ - pango_x_font_map_read_alias_file (xfontmap, "pangox_aliases"); -} - - -/* - * Returns TRUE if the fontname is a valid XLFD. - * (It just checks if the number of dashes is 14, and that each - * field < XLFD_MAX_FIELD_LEN characters long - that's not in the XLFD but it - * makes it easier for me). - */ -static gboolean -pango_x_is_xlfd_font_name (const char *fontname) -{ - int i = 0; - int field_len = 0; - - while (*fontname) - { - if (*fontname++ == '-') - { - if (field_len > XLFD_MAX_FIELD_LEN) return FALSE; - field_len = 0; - i++; - } - else - field_len++; - } - - return (i == 14) ? TRUE : FALSE; -} - -static int -pango_x_get_size (PangoXFontMap *xfontmap, const char *fontname) -{ - char size_buffer[XLFD_MAX_FIELD_LEN]; - int size; - - if (!pango_x_get_xlfd_field (fontname, XLFD_PIXELS, size_buffer)) - return -1; - - size = atoi (size_buffer); - if (size != 0) - { - return (int)(0.5 + size * xfontmap->resolution); - } - else - { - /* We use the trick that scaled bitmaps have a non-zero RESOLUTION_X, while - * actual scaleable fonts have a zero RESOLUTION_X */ - if (!pango_x_get_xlfd_field (fontname, XLFD_RESOLUTION_X, size_buffer)) - return -1; - - if (atoi (size_buffer) == 0) - return 0; - else - return -1; - } -} - -static char * -pango_x_get_identifier (const char *fontname) -{ - const char *p = fontname; - const char *start; - int n_dashes = 0; - - while (n_dashes < 2) - { - if (*p == '-') - n_dashes++; - p++; - } - - start = p; - - while (n_dashes < 6) - { - if (*p == '-') - n_dashes++; - p++; - } - - return g_strndup (start, (p - 1 - start)); -} - -/* - * This fills the buffer with the specified field from the X Logical Font - * Description name, and returns it. If fontname is NULL or the field is - * longer than XFLD_MAX_FIELD_LEN it returns NULL. - * Note: For the charset field, we also return the encoding, e.g. 'iso8859-1'. - */ -static char* -pango_x_get_xlfd_field (const char *fontname, - FontField field_num, - char *buffer) -{ - const char *t1, *t2; - int countdown, len, num_dashes; - - if (!fontname) - return NULL; - - /* we assume this is a valid fontname...that is, it has 14 fields */ - - countdown = field_num; - t1 = fontname; - while (*t1 && (countdown >= 0)) - if (*t1++ == '-') - countdown--; - - num_dashes = (field_num == XLFD_CHARSET) ? 2 : 1; - for (t2 = t1; *t2; t2++) - { - if (*t2 == '-' && --num_dashes == 0) - break; - } - - if (t1 != t2) - { - /* Check we don't overflow the buffer */ - len = (long) t2 - (long) t1; - if (len > XLFD_MAX_FIELD_LEN - 1) - return NULL; - strncpy (buffer, t1, len); - buffer[len] = 0; - /* Convert to lower case. */ - g_strdown (buffer); - } - else - strcpy(buffer, "(nil)"); - - return buffer; -} - -/* This inserts the given fontname into the FontInfo table. - If a FontInfo already exists with the same family and foundry, then the - fontname is added to the FontInfos list of fontnames, else a new FontInfo - is created and inserted in alphabetical order in the table. */ -static void -pango_x_insert_font (PangoXFontMap *xfontmap, - const char *fontname) -{ - PangoFontDescription description; - char family_buffer[XLFD_MAX_FIELD_LEN]; - char weight_buffer[XLFD_MAX_FIELD_LEN]; - char slant_buffer[XLFD_MAX_FIELD_LEN]; - char set_width_buffer[XLFD_MAX_FIELD_LEN]; - GSList *tmp_list; - PangoXFamilyEntry *family_entry; - PangoXFontEntry *font_entry; - PangoXSizeInfo *size_info; - char *identifier; - int i; - - description.size = 0; - - /* First insert the XLFD into the list of XLFDs for the "identifier" - which - * is the 2-4th fields of the XLFD - */ - identifier = pango_x_get_identifier (fontname); - size_info = g_hash_table_lookup (xfontmap->size_infos, identifier); - if (!size_info) - { - size_info = g_new (PangoXSizeInfo, 1); - size_info->identifier = identifier; - size_info->xlfds = NULL; - - g_hash_table_insert (xfontmap->size_infos, identifier, size_info); - } - else - g_free (identifier); - - size_info->xlfds = g_slist_prepend (size_info->xlfds, g_strdup (fontname)); - - /* Convert the XLFD into a PangoFontDescription */ - - description.family_name = pango_x_get_xlfd_field (fontname, XLFD_FAMILY, family_buffer); - g_strdown (description.family_name); - - if (!description.family_name) - return; - - description.style = PANGO_STYLE_NORMAL; - if (pango_x_get_xlfd_field (fontname, XLFD_SLANT, slant_buffer)) - { - for (i=0; i<G_N_ELEMENTS(styles_map); i++) - { - if (!strcmp (styles_map[i].text, slant_buffer)) - { - description.style = styles_map[i].value; - break; - } - } - } - else - strcpy (slant_buffer, "*"); - - description.variant = PANGO_VARIANT_NORMAL; - - description.weight = PANGO_WEIGHT_NORMAL; - if (pango_x_get_xlfd_field (fontname, XLFD_WEIGHT, weight_buffer)) - { - for (i=0; i<G_N_ELEMENTS(weights_map); i++) - { - if (!strcmp (weights_map[i].text, weight_buffer)) - { - description.weight = weights_map[i].value; - break; - } - } - } - else - strcpy (weight_buffer, "*"); - - description.stretch = PANGO_STRETCH_NORMAL; - if (pango_x_get_xlfd_field (fontname, XLFD_SET_WIDTH, set_width_buffer)) - { - for (i=0; i<G_N_ELEMENTS(stretches_map); i++) - { - if (!strcmp (stretches_map[i].text, set_width_buffer)) - { - description.stretch = stretches_map[i].value; - break; - } - } - } - else - strcpy (set_width_buffer, "*"); - - family_entry = pango_x_get_family_entry (xfontmap, description.family_name); - - tmp_list = family_entry->font_entries; - while (tmp_list) - { - font_entry = tmp_list->data; - - if (font_entry->description.style == description.style && - font_entry->description.variant == description.variant && - font_entry->description.weight == description.weight && - font_entry->description.stretch == description.stretch) - return; - - tmp_list = tmp_list->next; - } - - 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, - "-", - weight_buffer, - "-", - slant_buffer, - "-", - set_width_buffer, - "--*-*-*-*-*-*-*-*", - NULL); - - family_entry->font_entries = g_slist_append (family_entry->font_entries, font_entry); - xfontmap->n_fonts++; -} - - /** * pango_x_get_context: * @display: an X display (As returned by XOpenDisplay().) @@ -1383,7 +246,7 @@ pango_x_load_font (Display *display, * * Returns a new #PangoFont */ -static PangoFont * +PangoFont * pango_x_load_font_with_size (Display *display, char *spec, int size) @@ -1831,114 +694,6 @@ name_for_charset (char *xlfd, char *charset) return result; } -/* Given a xlfd, charset and size, find the best matching installed X font. - * The XLFD must be a full XLFD (14 fields) - */ -static char * -pango_x_make_matching_xlfd (PangoXFontMap *xfontmap, char *xlfd, const char *charset, int size) -{ - GSList *tmp_list; - PangoXSizeInfo *size_info; - char *identifier; - char *closest_match = NULL; - gint match_distance = 0; - gboolean match_scaleable = FALSE; - char *result = NULL; - - char *dash_charset; - - dash_charset = g_strconcat ("-", charset, NULL); - - if (!match_end (xlfd, "-*-*") && !match_end (xlfd, dash_charset)) - { - g_free (dash_charset); - return NULL; - } - - identifier = pango_x_get_identifier (xlfd); - size_info = g_hash_table_lookup (xfontmap->size_infos, identifier); - g_free (identifier); - - if (!size_info) - { - g_free (dash_charset); - return NULL; - } - - tmp_list = size_info->xlfds; - while (tmp_list) - { - char *tmp_xlfd = tmp_list->data; - - if (match_end (tmp_xlfd, dash_charset)) - { - int font_size = pango_x_get_size (xfontmap, tmp_xlfd); - - if (size != -1) - { - int new_distance = (font_size == 0) ? 0 : abs (font_size - size); - - if (!closest_match || - new_distance < match_distance || - (new_distance < PANGO_SCALE && match_scaleable && font_size != 0)) - { - closest_match = tmp_xlfd; - match_scaleable = (font_size == 0); - match_distance = new_distance; - } - } - } - - tmp_list = tmp_list->next; - } - - if (closest_match) - { - if (match_scaleable) - { - char *prefix_end, *p; - char *size_end; - int n_dashes = 0; - int target_size; - char *prefix; - - /* OK, we have a match; let's modify it to fit this size and charset */ - - p = closest_match; - while (n_dashes < 6) - { - if (*p == '-') - n_dashes++; - p++; - } - - prefix_end = p - 1; - - while (n_dashes < 9) - { - if (*p == '-') - n_dashes++; - p++; - } - - size_end = p - 1; - - target_size = (int)((double)size / xfontmap->resolution + 0.5); - prefix = g_strndup (closest_match, prefix_end - closest_match); - result = g_strdup_printf ("%s--%d-*-*-*-*-*-%s", prefix, target_size, charset); - g_free (prefix); - } - else - { - result = g_strdup (closest_match); - } - } - - g_free (dash_charset); - - return result; -} - static PangoXSubfont pango_x_insert_subfont (PangoFont *font, const char *xlfd) { @@ -1984,14 +739,14 @@ pango_x_list_subfonts (PangoFont *font, { PangoXFont *xfont = (PangoXFont *)font; PangoXSubfont **subfont_lists; - PangoXFontMap *xfontmap; + PangoFontMap *fontmap; int i, j; int n_subfonts = 0; g_return_val_if_fail (font != NULL, 0); g_return_val_if_fail (n_charsets == 0 || charsets != NULL, 0); - xfontmap = (PangoXFontMap *)pango_x_font_map_for_display (xfont->display); + fontmap = pango_x_font_map_for_display (xfont->display); subfont_lists = g_new (PangoXSubfont *, n_charsets); @@ -2024,7 +779,7 @@ pango_x_list_subfonts (PangoFont *font, } else { - xlfd = pango_x_make_matching_xlfd (xfontmap, xfont->fonts[i], charsets[j], xfont->size); + xlfd = pango_x_make_matching_xlfd (fontmap, xfont->fonts[i], charsets[j], xfont->size); if (xlfd) { subfont = pango_x_insert_subfont (font, xlfd); @@ -2117,7 +872,7 @@ pango_x_font_destroy (PangoFont *font) g_slist_free (xfont->metrics_by_lang); if (xfont->entry) - xfont->entry->cached_fonts = g_slist_remove (xfont->entry->cached_fonts, xfont); + pango_x_font_entry_remove (xfont->entry, font); g_strfreev (xfont->fonts); g_free (font); @@ -2130,15 +885,7 @@ pango_x_font_describe (PangoFont *font) return NULL; } -static void -free_coverages_foreach (gpointer key, - gpointer value, - gpointer data) -{ - pango_coverage_unref (value); -} - -static PangoMap * +PangoMap * pango_x_get_shaper_map (const char *lang) { static guint engine_type_id = 0; @@ -2157,60 +904,9 @@ static PangoCoverage * pango_x_font_get_coverage (PangoFont *font, const char *lang) { - guint32 ch; - PangoMap *shape_map; - PangoCoverage *coverage; - PangoCoverage *result; - PangoCoverageLevel font_level; - PangoMapEntry *entry; - 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); - - shape_map = pango_x_get_shaper_map (lang); - - for (ch = 0; ch < 65536; ch++) - { - entry = _pango_map_get_entry (shape_map, ch); - if (entry->info) - { - coverage = g_hash_table_lookup (coverage_hash, entry->info->id); - if (!coverage) - { - PangoEngineShape *engine = (PangoEngineShape *)_pango_map_get_engine (shape_map, ch); - coverage = engine->get_coverage (font, lang); - g_hash_table_insert (coverage_hash, entry->info->id, coverage); - } - - font_level = pango_coverage_get (coverage, ch); - if (font_level == PANGO_COVERAGE_EXACT && !entry->is_exact) - font_level = PANGO_COVERAGE_APPROXIMATE; - - if (font_level != PANGO_COVERAGE_NONE) - pango_coverage_set (result, ch, font_level); - } - } - - 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; + return pango_x_font_entry_get_coverage (xfont->entry, font, lang); } static PangoEngineShape * @@ -2578,3 +1274,6 @@ pango_x_get_item_properties (PangoItem *item, tmp_list = tmp_list->next; } } + + + |