fonts.c
来自「ANFY特效」· C语言 代码 · 共 927 行 · 第 1/2 页
C
927 行
// // Fonts... I miss Windows :)//#include <stdlib.h>#include <stdio.h>#include <string.h>#include <ctype.h>#include <X11/Xlib.h>#include <gtk/gtk.h>#include <gdk/gdkx.h>#include "support.h"/* The maximum number of fontnames requested with XListFonts(). */#define MAX_FONTS 32767/* 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/* These are what we use as the standard font sizes, for the size clist. Note that when using points we still show these integer point values but we work internally in decipoints (and decipoint values can be typed in). */static const guint16 font_sizes[] = { 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 22, 24, 26, 28, 32, 36, 40, 48, 56, 64, 72};/* Initial font metric & size (Remember point sizes are in decipoints). The font size should match one of those in the font_sizes array. */#define INITIAL_METRIC GTK_FONT_METRIC_POINTS#define INITIAL_FONT_SIZE 140/* This is the default text shown in the preview entry, though the user can set it. Remember that some fonts only have capital letters. */#define PREVIEW_TEXT "abcdefghijk ABCDEFGHIJK"/* This is the initial and maximum height of the preview entry (it expands when large font sizes are selected). Initial height is also the minimum. */#define INITIAL_PREVIEW_HEIGHT 44#define MAX_PREVIEW_HEIGHT 300/* These are the sizes of the font, style & size clists. */#define FONT_LIST_HEIGHT 136#define FONT_LIST_WIDTH 190#define FONT_STYLE_LIST_WIDTH 170#define FONT_SIZE_LIST_WIDTH 60/* This is the number of fields in an X Logical Font Description font name. Note that we count the registry & encoding as 1. */#define GTK_XLFD_NUM_FIELDS 13typedef struct _GtkFontSelInfo GtkFontSelInfo;typedef struct _FontInfo FontInfo;typedef struct _FontStyle FontStyle;/* This struct represents one family of fonts (with one foundry), e.g. adobe courier or sony fixed. It stores the family name, the index of the foundry name, and the index of and number of available styles. */struct _FontInfo{ gchar *family; guint16 foundry; gint style_index; guint16 nstyles;};/* This represents one style, as displayed in the Font Style clist. It can have a number of available pixel sizes and point sizes. The indexes point into the two big fontsel_info->pixel_sizes & fontsel_info->point_sizes arrays. The displayed flag is used when displaying styles to remember which styles have already been displayed. Note that it is combined with the GtkFontType in the flags field. */#define GTK_FONT_DISPLAYED (1 << 7)struct _FontStyle{ guint16 properties[GTK_NUM_STYLE_PROPERTIES]; gint pixel_sizes_index; guint16 npixel_sizes; gint point_sizes_index; guint16 npoint_sizes; guint8 flags;};struct _GtkFontSelInfo { /* This is a table with each FontInfo representing one font family+foundry */ FontInfo *font_info; gint nfonts; /* This stores all the valid combinations of properties for every family. Each FontInfo holds an index into its own space in this one big array. */ FontStyle *font_styles; gint nstyles; /* This stores all the font sizes available for every style. Each style holds an index into these arrays. */ guint16 *pixel_sizes; guint16 *point_sizes; /* These are the arrays of strings of all possible weights, slants, set widths, spacings, charsets & foundries, and the amount of space allocated for each array. */ gchar **properties[GTK_NUM_FONT_PROPERTIES]; guint16 nproperties[GTK_NUM_FONT_PROPERTIES]; guint16 space_allocated[GTK_NUM_FONT_PROPERTIES];};/* 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} FontField;/* These are the names of the fields, used on the info & filter page. *//*static const gchar* xlfd_field_names[GTK_XLFD_NUM_FIELDS] = { N_("Foundry:"), N_("Family:"), N_("Weight:"), N_("Slant:"), N_("Set Width:"), N_("Add Style:"), N_("Pixel Size:"), N_("Point Size:"), N_("Resolution X:"), N_("Resolution Y:"), N_("Spacing:"), N_("Average Width:"), N_("Charset:"),};*//* These are the array indices of the font properties used in several arrays, and should match the xlfd_index array below. */typedef enum{ WEIGHT = 0, SLANT = 1, SET_WIDTH = 2, SPACING = 3, CHARSET = 4, FOUNDRY = 5} PropertyIndexType;/* This is used to look up a field in a fontname given one of the above property indices. */static const FontField xlfd_index[GTK_NUM_FONT_PROPERTIES] = { XLFD_WEIGHT, XLFD_SLANT, XLFD_SET_WIDTH, XLFD_SPACING, XLFD_CHARSET, XLFD_FOUNDRY};/* These are the positions of the properties in the filter table - x, y. */static const gint filter_positions[GTK_NUM_FONT_PROPERTIES][2] = { { 1, 0 }, { 0, 2 }, { 1, 2 }, { 2, 2 }, { 2, 0 }, { 0, 0 }};static const gint filter_heights[GTK_NUM_FONT_PROPERTIES] = { 100, 70, 70, 40, 100, 100};/* This is returned by gtk_font_selection_filter_state to describe if a property value is filtered. e.g. if 'bold' has been selected on the filter page, then that will return 'FILTERED' and 'black' will be 'NOT_FILTERED'. If none of the weight values are selected, they all return 'NOT_SET'. */typedef enum{ FILTERED, NOT_FILTERED, NOT_SET} GtkFontPropertyFilterState;static GtkFontSelInfo *fontsel_info = NULL;/* The initial size and increment of each of the arrays of property values. */#define PROPERTY_ARRAY_INCREMENT 16// =========================================================static void gtk_font_selection_insert_font (GSList *fontnames[], gint *ntable, gchar *fontname);static gint gtk_font_selection_insert_field (gchar *fontname, gint prop);static gboolean gtk_font_selection_is_xlfd_font_name (const gchar *fontname);static char* gtk_font_selection_get_xlfd_field (const gchar *fontname, FontField field_num, gchar *buffer);// =========================================================/* * 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 gbooleangtk_font_selection_is_xlfd_font_name (const gchar *fontname){ gint i = 0; gint 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;}/* * 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 gchar*gtk_font_selection_get_xlfd_field (const gchar *fontname, FontField field_num, gchar *buffer){ const gchar *t1, *t2; gint 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 voidgtk_font_selection_insert_font (GSList *fontnames[], gint *ntable, gchar *fontname){ FontInfo *table; FontInfo temp_info; GSList *temp_fontname; gchar *family; gboolean family_exists = FALSE; gint foundry; gint lower, upper; gint middle, cmp; gchar family_buffer[XLFD_MAX_FIELD_LEN]; table = fontsel_info->font_info; /* insert a fontname into a table */ family = gtk_font_selection_get_xlfd_field (fontname, XLFD_FAMILY, family_buffer); if (!family) return; foundry = gtk_font_selection_insert_field (fontname, FOUNDRY); lower = 0; if (*ntable > 0) { /* Do a binary search to determine if we have already encountered * a font with this family & foundry. */ upper = *ntable; while (lower < upper) { middle = (lower + upper) >> 1; cmp = strcmp (family, table[middle].family); /* If the family matches we sort by the foundry. */ if (cmp == 0) { family_exists = TRUE; family = table[middle].family; cmp = strcmp(fontsel_info->properties[FOUNDRY][foundry], fontsel_info->properties[FOUNDRY][table[middle].foundry]); } if (cmp == 0) { fontnames[middle] = g_slist_prepend (fontnames[middle], fontname); return; } else if (cmp < 0) upper = middle; else lower = middle+1; } } /* Add another entry to the table for this new font family */ temp_info.family = family_exists ? family : g_strdup(family); temp_info.foundry = foundry; temp_fontname = g_slist_prepend (NULL, fontname); (*ntable)++; /* Quickly insert the entry into the table in sorted order * using a modification of insertion sort and the knowledge * that the entries proper position in the table was determined * above in the binary search and is contained in the "lower" * variable. */ if (*ntable > 1) { upper = *ntable - 1; while (lower != upper) { table[upper] = table[upper-1]; fontnames[upper] = fontnames[upper-1]; upper--; } } table[lower] = temp_info; fontnames[lower] = temp_fontname;}/* This checks that the specified field of the given fontname is in the appropriate properties array. If not it is added. Thus eventually we get arrays of all possible weights/slants etc. It returns the array index. */static gintgtk_font_selection_insert_field (gchar *fontname, gint prop){ gchar field_buffer[XLFD_MAX_FIELD_LEN]; gchar *field; guint16 index; field = gtk_font_selection_get_xlfd_field (fontname, xlfd_index[prop], field_buffer); if (!field) return 0; /* If the field is already in the array just return its index. */ for (index = 0; index < fontsel_info->nproperties[prop]; index++) if (!strcmp(field, fontsel_info->properties[prop][index])) return index; /* Make sure we have enough space to add the field. */ if (fontsel_info->nproperties[prop] == fontsel_info->space_allocated[prop]) { fontsel_info->space_allocated[prop] += PROPERTY_ARRAY_INCREMENT; fontsel_info->properties[prop] = g_realloc(fontsel_info->properties[prop], sizeof(gchar*) * fontsel_info->space_allocated[prop]); } /* Add the new field. */ index = fontsel_info->nproperties[prop]; fontsel_info->properties[prop][index] = g_strdup(field); fontsel_info->nproperties[prop]++; return index;}// =========================================================#if 0static int find_index (char* name){ FontInfo *font_info, *font; gint nfonts, i; gchar font_buffer[XLFD_MAX_FIELD_LEN * 2 + 4]; font_info = fontsel_info->font_info; nfonts = fontsel_info->nfonts; /* Filter the list of fonts. */ for (i = 0; i < nfonts; i++) { font = &font_info[i]; /* Insert the font in the clist. */ if ((i > 0 && font->family == font_info[i-1].family) || (i < nfonts - 1 && font->family == font_info[i+1].family)) { sprintf(font_buffer, "%s (%s)", font->family, fontsel_info->properties[FOUNDRY][font->foundry]); if (strcmp (font_buffer, name) == 0) return i; } else { if (strcmp (font->family, name) == 0) return i; } } return 0;}#endif/* This shows all the available fonts in the font clist. */void fill_fonts_combo (GtkWidget* combo){ FontInfo *font_info, *font; gint nfonts, i; gchar font_buffer[XLFD_MAX_FIELD_LEN * 2 + 4]; GList *list = NULL; font_info = fontsel_info->font_info; nfonts = fontsel_info->nfonts; /* Filter the list of fonts. */ for (i = 0; i < nfonts; i++) { font = &font_info[i]; /* Insert the font in the clist. */ if ((i > 0 && font->family == font_info[i-1].family) || (i < nfonts - 1 && font->family == font_info[i+1].family)) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?