📄 dw_style.c
字号:
/* * File: dw_style.c * * Copyright (C) 2001-2003 Sebastian Geerken <S.Geerken@ping.de> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */#include "dw_style.h"#include "dw_widget.h"#include <gdk/gdk.h>#include <stdio.h>#include <string.h>#include <ctype.h>/*#define DEBUG_LEVEL 1*/#include "debug.h"#define EQUIV(a, b) (((a) && (b)) || (!(a) && !(b)))#define Dw_style_font_ref(font) ((font)->ref_count++)#define Dw_style_font_unref(font) if (--((font)->ref_count) == 0) \ Dw_style_font_remove (font)#define Dw_style_color_ref(color) ((color)->ref_count++)#define Dw_style_color_unref(color) if (--((color)->ref_count) == 0) \ Dw_style_color_remove (color)#define Dw_style_shaded_color_ref(color) ((color)->ref_count++)#define Dw_style_shaded_color_unref(color) if (--((color)->ref_count) == 0) \ Dw_style_shaded_color_remove \ (color) \static GHashTable *fonts_table;static GHashTable *colors_table;static GHashTable *shaded_colors_table;static gint styles_num = 0;/* Used by a_Dw_style_numtostr(). */static const char *roman_I0[] ={"I","II","III","IV","V","VI","VII","VIII","IX"}, *roman_I1[] ={"X","XX","XXX","XL","L","LX","LXX","LXXX","XC"}, *roman_I2[] ={"C","CC","CCC","CD","D","DC","DCC","DCCC","CM"}, *roman_I3[] ={"M","MM","MMM","MMMM"};static gint Dw_style_font_equal (gconstpointer v1, gconstpointer v2);static guint Dw_style_font_hash (gconstpointer key);static void Dw_style_font_remove (DwStyleFont *font);static void Dw_style_color_remove (DwStyleColor *color);static void Dw_style_shaded_color_remove (DwStyleShadedColor *color);/* ---------------------------------------------------------------------- * * Initialization / Cleaning up * * ---------------------------------------------------------------------- *//* * Initialize the DwStyle submodule. */void a_Dw_style_init (void){ fonts_table = g_hash_table_new (Dw_style_font_hash, Dw_style_font_equal); colors_table = g_hash_table_new (g_direct_hash, g_direct_equal); shaded_colors_table = g_hash_table_new (g_direct_hash, g_direct_equal);}/* * Called by a_Dw_style_freeall. */static void Dw_style_count_fonts (gpointer key, gpointer value, gpointer user_data){ DwStyleFont *font = (DwStyleFont*) key; gint *count = (int*)user_data; count[0]++; count[1] += font->ref_count;}/* * Called by a_Dw_style_freeall. */static void Dw_style_count_colors (gpointer key, gpointer value, gpointer user_data){ DwStyleColor *color = (DwStyleColor*) value; gint *count = (int*)user_data; count[0]++; count[1] += color->ref_count;}/* * Called by a_Dw_style_freeall. */static void Dw_style_count_shaded_colors (gpointer key, gpointer value, gpointer user_data){ DwStyleShadedColor *color = (DwStyleShadedColor*) value; gint *count = (int*)user_data; count[0]++; count[1] += color->ref_count;}/* * Free variables used by DwStyle, and do a check whether memory * management works properly. */void a_Dw_style_freeall (void){ gint count[2]; if (styles_num) g_warning ("%d styles left", styles_num); count[0] = count[1] = 0; g_hash_table_foreach (fonts_table, Dw_style_count_fonts, count); if (count[0] || count[1]) g_warning ("%d fonts (%d references) left", count[0], count[1]); count[0] = count[1] = 0; g_hash_table_foreach (colors_table, Dw_style_count_colors, count); if (count[0] || count[1]) g_warning ("%d colors (%d references) left", count[0], count[1]); count[0] = count[1] = 0; g_hash_table_foreach (shaded_colors_table, Dw_style_count_shaded_colors, count); if (count[0] || count[1]) g_warning ("%d shaded colors (%d references) left", count[0], count[1]); g_hash_table_destroy (fonts_table); g_hash_table_destroy (colors_table);}/* ---------------------------------------------------------------------- * * Styles * * ---------------------------------------------------------------------- *//* * Set all style fields except font and color to reasonable defaults. */void a_Dw_style_init_values (DwStyle *style_attrs, GdkWindow *window){ style_attrs->x_link = -1; style_attrs->x_tooltip = NULL; style_attrs->text_decoration = 0; style_attrs->text_align = DW_STYLE_TEXT_ALIGN_LEFT; style_attrs->list_style_type = DW_STYLE_LIST_STYLE_TYPE_DISC; style_attrs->valign = DW_STYLE_VALIGN_MIDDLE; style_attrs->background_color = NULL; style_attrs->width = DW_STYLE_LENGTH_AUTO; style_attrs->height = DW_STYLE_LENGTH_AUTO; a_Dw_style_box_set_val (&style_attrs->margin, 0); a_Dw_style_box_set_val (&style_attrs->border_width, 0); a_Dw_style_box_set_val (&style_attrs->padding, 0); a_Dw_style_box_set_border_color (style_attrs, NULL); a_Dw_style_box_set_border_style (style_attrs, DW_STYLE_BORDER_NONE); style_attrs->border_spacing = 0; style_attrs->display = DW_STYLE_DISPLAY_INLINE; style_attrs->white_space = DW_STYLE_WHITE_SPACE_NORMAL;}/* * Reset those style attributes to their standard values, which are * not inherited, according to CSS. */void a_Dw_style_reset_values (DwStyle *style_attrs, GdkWindow *window){ style_attrs->x_link = -1; style_attrs->background_color = NULL; style_attrs->x_tooltip = NULL; style_attrs->text_align = DW_STYLE_TEXT_ALIGN_LEFT; /* ??? */ style_attrs->valign = DW_STYLE_VALIGN_MIDDLE; style_attrs->text_align_char = '.'; style_attrs->background_color = NULL; style_attrs->width = DW_STYLE_LENGTH_AUTO; style_attrs->height = DW_STYLE_LENGTH_AUTO; a_Dw_style_box_set_val (&style_attrs->margin, 0); a_Dw_style_box_set_val (&style_attrs->border_width, 0); a_Dw_style_box_set_val (&style_attrs->padding, 0); a_Dw_style_box_set_border_color (style_attrs, NULL); a_Dw_style_box_set_border_style (style_attrs, DW_STYLE_BORDER_NONE); style_attrs->border_spacing = 0; style_attrs->display = DW_STYLE_DISPLAY_INLINE; style_attrs->white_space = DW_STYLE_WHITE_SPACE_NORMAL;}/* * Return a new DwStyle, with increased reference pointer. */DwStyle* a_Dw_style_new (DwStyle *style_attrs, GdkWindow *window){ DwStyle *style; style = g_new (DwStyle, 1); *style = *style_attrs; style->ref_count = 1; Dw_style_font_ref (style->font); Dw_style_color_ref (style->color); if (style->background_color) Dw_style_color_ref (style->background_color); if (style->border_color.top) Dw_style_shaded_color_ref (style->border_color.top); if (style->border_color.right) Dw_style_shaded_color_ref (style->border_color.right); if (style->border_color.bottom) Dw_style_shaded_color_ref (style->border_color.bottom); if (style->border_color.left) Dw_style_shaded_color_ref (style->border_color.left); if (style->x_tooltip) a_Dw_tooltip_ref (style->x_tooltip); styles_num++; return style;}/* * Remove a style (called when ref_count == 0). */void Dw_style_remove (DwStyle *style){ Dw_style_font_unref (style->font); Dw_style_color_unref (style->color); if (style->background_color) Dw_style_color_unref (style->background_color); if (style->border_color.top) Dw_style_shaded_color_unref (style->border_color.top); if (style->border_color.right) Dw_style_shaded_color_unref (style->border_color.right); if (style->border_color.bottom) Dw_style_shaded_color_unref (style->border_color.bottom); if (style->border_color.left) Dw_style_shaded_color_unref (style->border_color.left); if (style->x_tooltip) a_Dw_tooltip_unref (style->x_tooltip); g_free (style); styles_num--;}/* ---------------------------------------------------------------------- * * Fonts * * ---------------------------------------------------------------------- *//* * Create the GdkFont. font->name contains one name. If try_all is * TRUE, try also standard fonts, if anything else fails. */static void Dw_style_font_realize (DwStyleFont *font, gboolean try_all){ char fontname[256], *style_char_1 = NULL, *style_char_2 = NULL; switch (font->style) { case DW_STYLE_FONT_STYLE_NORMAL: style_char_1 = style_char_2 = "r"; break; case DW_STYLE_FONT_STYLE_ITALIC: style_char_1 = "i"; style_char_2 = "o"; break; case DW_STYLE_FONT_STYLE_OBLIQUE: style_char_1 = "o"; style_char_2 = "i"; break; } sprintf (fontname, "-*-%s-%s-%s-*-*-%d-*-75-75-*-*-iso8859-1", font->name, (font->weight >= 500) ? "bold" : "medium", style_char_1, font->size); font->font = gdk_font_load (fontname); if (font->font == NULL && font->style != DW_STYLE_FONT_STYLE_NORMAL) { sprintf (fontname, "-*-%s-%s-%s-*-*-%d-*-75-75-*-*-iso8859-1", font->name, (font->weight >= 500) ? "bold" : "medium", style_char_2, font->size); font->font = gdk_font_load (fontname); } if (try_all) { if (font->font == NULL) { /* Can't load the font - substitute the default instead. */ font->font = gdk_font_load ("-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-iso8859-1"); } if (font->font == NULL) { /* Try another platform-font that should be available. (iPaq) */ font->font = gdk_font_load ("-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso8859-1"); } if (font->font == NULL) { /* Can't load any suitable font! */ g_warning ("Can't load any ISO8859-1 font!?! :("); font->font = gdk_font_load ("-adobe-helvetica-*-*-*--*-*-*-*-*-*-*-*"); } } if (font->font) { font->space_width = gdk_char_width (font->font, ' '); font->x_height = gdk_char_height (font->font, 'x'); }}/* * Used for the font_table hash table. */static gint Dw_style_font_equal (gconstpointer v1, gconstpointer v2){ const DwStyleFont *font1 = (DwStyleFont*) v1, *font2 = (DwStyleFont*) v2; return (font1->size == font2->size && font1->weight == font2->weight && font1->style == font2->style && strcmp (font1->name, font2->name) == 0);}/* * Used for the font_table hash table. */static guint Dw_style_font_hash (gconstpointer key){ const DwStyleFont *font = (DwStyleFont*) key; guint h; h = g_str_hash (font->name); h = (h << 5) - h + font->size; h = (h << 5) - h + font->weight; h = (h << 5) - h + font->style; return h;}/* * Returns a new or already existing font. This function is only used * internally, and called by a_Dw_style_font_new and * a_Dw_style_font_new_from_list. * * Note that the reference counter is not increased/set to zero, it * will be increased by a_Dw_style_new. If 'try_all' is TRUE, try also * standard fonts, if anything else fails. */static DwStyleFont* Dw_style_font_new_internal (DwStyleFont *font_attrs, gboolean try_all){ DwStyleFont *font; g_return_val_if_fail (font_attrs->name != NULL, NULL); if ((font = g_hash_table_lookup (fonts_table, font_attrs))) { return font; } else { font = g_new (DwStyleFont, 1); font->size = font_attrs->size; font->weight = font_attrs->weight; font->style = font_attrs->style; font->name = g_strdup (font_attrs->name); font->ref_count = 0; Dw_style_font_realize (font, try_all); if (font->font) { g_hash_table_insert (fonts_table, font, font); return font; } else { g_free (font->name); g_free (font); return NULL; } }}/* * Return a new or already existing font, with one name in * font_attrs->name. See also Dw_style_font_new_internal. */DwStyleFont* a_Dw_style_font_new (DwStyleFont *font_attrs){ DwStyleFont *font; font = Dw_style_font_new_internal (font_attrs, TRUE); if (font == NULL) g_error ("Could not find any font."); return font;}/* * Return a new or already existing font, with font_attrs->name * containing a comma separated list of names. See also * Dw_style_font_new_internal. */DwStyleFont* a_Dw_style_font_new_from_list (DwStyleFont *font_attrs, gchar *default_family){ DwStyleFont *font = NULL, font_attrs2; char *comma, *list, *current; font_attrs2 = *font_attrs; current = list = g_strdup (font_attrs->name); while (current && (font == NULL)) { comma = strchr (current, ','); if (comma) *comma = 0; font_attrs2.name = current; font = Dw_style_font_new_internal (&font_attrs2, FALSE); if (font) break; if (comma) { current = comma + 1; while (isspace (*current)) current++; } else current = NULL; } g_free (list); if (font == NULL) { font_attrs2.name = default_family; font = Dw_style_font_new_internal (&font_attrs2, TRUE); } if (font == NULL) g_error ("Could not find any font."); return font;}/* * Remove a font (called when ref_count == 0). */static void Dw_style_font_remove (DwStyleFont *font){ g_hash_table_remove (fonts_table, font); g_free (font->name); gdk_font_unref (font->font); g_free (font);}/* ---------------------------------------------------------------------- * * Colors * * ---------------------------------------------------------------------- *//* * Copied from gtkstyle.c. * Convert RGB into HLS. */static void Dw_style_rgb_to_hls (gdouble *r, gdouble *g, gdouble *b){ gdouble min; gdouble max; gdouble red; gdouble green; gdouble blue; gdouble h, l, s; gdouble delta; red = *r; green = *g; blue = *b; if (red > green) { if (red > blue) max = red; else max = blue; if (green < blue)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -