diff options
author | Tor Lillqvist <tml@src.gnome.org> | 1999-11-10 00:04:17 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 1999-11-10 00:04:17 +0000 |
commit | 84477de7fcc559a85506c603315ea8927be831d1 (patch) | |
tree | c6dad2e2cea14806b577e199142a4e555ca7e0e0 /gdk/win32/gdkfont-win32.c | |
parent | 78141c328fc16852f88d22e0ce3fb98ea5114a5d (diff) | |
download | gdk-pixbuf-84477de7fcc559a85506c603315ea8927be831d1.tar.gz |
Just renamed the Win32 backend files to *-win32.
Diffstat (limited to 'gdk/win32/gdkfont-win32.c')
-rw-r--r-- | gdk/win32/gdkfont-win32.c | 1501 |
1 files changed, 0 insertions, 1501 deletions
diff --git a/gdk/win32/gdkfont-win32.c b/gdk/win32/gdkfont-win32.c deleted file mode 100644 index 3cee42da8..000000000 --- a/gdk/win32/gdkfont-win32.c +++ /dev/null @@ -1,1501 +0,0 @@ -/* GDK - The GIMP Drawing Kit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Modified by the GTK+ Team and others 1997-1999. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#include "config.h" - -#include <stdio.h> -#include <ctype.h> - -#include "gdkfont.h" -#include "gdkx.h" - -static GHashTable *font_name_hash = NULL; -static GHashTable *fontset_name_hash = NULL; - -static void -gdk_font_hash_insert (GdkFontType type, - GdkFont *font, - const gchar *font_name) -{ - GdkFontPrivate *private = (GdkFontPrivate *) font; - GHashTable **hashp = (type == GDK_FONT_FONT) ? - &font_name_hash : &fontset_name_hash; - - if (!*hashp) - *hashp = g_hash_table_new (g_str_hash, g_str_equal); - - private->names = g_slist_prepend (private->names, g_strdup (font_name)); - g_hash_table_insert (*hashp, private->names->data, font); -} - -static void -gdk_font_hash_remove (GdkFontType type, - GdkFont *font) -{ - GdkFontPrivate *private = (GdkFontPrivate *) font; - GSList *tmp_list; - GHashTable *hash = (type == GDK_FONT_FONT) ? - font_name_hash : fontset_name_hash; - - tmp_list = private->names; - while (tmp_list) - { - g_hash_table_remove (hash, tmp_list->data); - g_free (tmp_list->data); - - tmp_list = tmp_list->next; - } - - g_slist_free (private->names); - private->names = NULL; -} - -static GdkFont * -gdk_font_hash_lookup (GdkFontType type, - const gchar *font_name) -{ - GdkFont *result; - GHashTable *hash = (type == GDK_FONT_FONT) ? - font_name_hash : fontset_name_hash; - - if (!hash) - return NULL; - else - { - result = g_hash_table_lookup (hash, font_name); - if (result) - gdk_font_ref (result); - - return result; - } -} - -static const char * -charset_name (DWORD charset) -{ - switch (charset) - { - case ANSI_CHARSET: return "ansi"; - case DEFAULT_CHARSET: return "default"; - case SYMBOL_CHARSET: return "symbol"; - case SHIFTJIS_CHARSET: return "shiftjis"; - case HANGEUL_CHARSET: return "hangeul"; - case GB2312_CHARSET: return "gb2312"; - case CHINESEBIG5_CHARSET: return "big5"; - case JOHAB_CHARSET: return "johab"; - case HEBREW_CHARSET: return "hebrew"; - case ARABIC_CHARSET: return "arabic"; - case GREEK_CHARSET: return "greek"; - case TURKISH_CHARSET: return "turkish"; - case VIETNAMESE_CHARSET: return "vietnamese"; - case THAI_CHARSET: return "thai"; - case EASTEUROPE_CHARSET: return "easteurope"; - case RUSSIAN_CHARSET: return "russian"; - case MAC_CHARSET: return "mac"; - case BALTIC_CHARSET: return "baltic"; - } - return "unknown"; -} - -static gint num_fonts; -static gint font_names_size; -static gchar **xfontnames; - -static gchar * -logfont_to_xlfd (const LOGFONT *lfp, - int size, - int res, - int avg_width) -{ - const gchar *weight; - const gchar *registry, *encoding; - int point_size; - static int logpixelsy = 0; - gchar facename[LF_FACESIZE*3]; - gchar *p; - const gchar *q; - - if (logpixelsy == 0) - { - logpixelsy = GetDeviceCaps (gdk_DC, LOGPIXELSY); - } - - if (lfp->lfWeight >= FW_HEAVY) - weight = "heavy"; - else if (lfp->lfWeight >= FW_EXTRABOLD) - weight = "extrabold"; - else if (lfp->lfWeight >= FW_BOLD) - weight = "bold"; -#ifdef FW_DEMIBOLD - else if (lfp->lfWeight >= FW_DEMIBOLD) - weight = "demibold"; -#endif - else if (lfp->lfWeight >= FW_MEDIUM) - weight = "medium"; - else if (lfp->lfWeight >= FW_NORMAL) - weight = "normal"; - else if (lfp->lfWeight >= FW_LIGHT) - weight = "light"; - else if (lfp->lfWeight >= FW_EXTRALIGHT) - weight = "extralight"; - else if (lfp->lfWeight >= FW_THIN) - weight = "thin"; - else - weight = "regular"; - - switch (lfp->lfCharSet) - { - case ANSI_CHARSET: - registry = "iso8859"; - encoding = "1"; - break; - case SHIFTJIS_CHARSET: - registry = "jisx0208.1983"; - encoding = "0"; - break; - case HANGEUL_CHARSET: - registry = "ksc5601.1987"; - encoding = "0"; - break; - case GB2312_CHARSET: - registry = "gb2312.1980"; - encoding = "0"; - break; - case CHINESEBIG5_CHARSET: - registry = "big5"; - encoding = "0"; - break; - case GREEK_CHARSET: - registry = "iso8859"; - encoding = "7"; - break; - case TURKISH_CHARSET: - registry = "iso8859"; - encoding = "9"; - break; -#if 0 /* Not a good idea, I think, to use ISO8859-8 and -6 for the Windows - * hebrew and arabic codepages, they differ too much. - */ - case HEBREW_CHARSET: - registry = "iso8859"; - encoding = "8"; - break; - case ARABIC_CHARSET: - registry = "iso8859"; - encoding = "6"; - break; -#endif - default: - registry = "microsoft"; - encoding = charset_name (lfp->lfCharSet); - } - - point_size = (int) (((double) size/logpixelsy) * 720.); - - if (res == -1) - res = logpixelsy; - - /* Replace illegal characters with hex escapes. */ - p = facename; - q = lfp->lfFaceName; - while (*q) - { - if (*q == '-' || *q == '*' || *q == '?' || *q == '%') - p += sprintf (p, "%%%.02x", *q); - else - *p++ = *q; - q++; - } - *p = '\0'; - - return g_strdup_printf - ("-%s-%s-%s-%s-%s-%s-%d-%d-%d-%d-%s-%d-%s-%s", - "unknown", - facename, - weight, - (lfp->lfItalic ? - ((lfp->lfPitchAndFamily & 0xF0) == FF_ROMAN - || (lfp->lfPitchAndFamily & 0xF0) == FF_SCRIPT ? - "i" : "o") : "r"), - "normal", - "", - size, - point_size, - res, - res, - ((lfp->lfPitchAndFamily & 0x03) == FIXED_PITCH ? "m" : "p"), - avg_width, - registry, encoding); -} - -gchar * -gdk_font_xlfd_create (GdkFont *font) -{ - GdkFontPrivate *private; - GdkWin32SingleFont *singlefont; - GSList *list; - GString *string; - gchar *result; - LOGFONT logfont; - - g_return_val_if_fail (font != NULL, NULL); - - private = (GdkFontPrivate *) font; - - list = private->fonts; - string = g_string_new (""); - - while (list) - { - singlefont = (GdkWin32SingleFont *) list->data; - - if (GetObject (singlefont->xfont, sizeof (LOGFONT), &logfont) == 0) - { - g_warning ("gdk_win32_font_xlfd: GetObject failed"); - return NULL; - } - - string = - g_string_append (string, - logfont_to_xlfd (&logfont, logfont.lfHeight, -1, 0)); - list = list->next; - if (list) - string = g_string_append_c (string, ','); - } - result = string->str; - g_string_free (string, FALSE); - return result; -} - -void -gdk_font_xlfd_free (gchar *xlfd) -{ - g_free (xlfd); -} - -static gboolean -pattern_match (const gchar *pattern, - const gchar *string) -{ - const gchar *p = pattern, *n = string; - gchar c, c1; - - /* Common case first */ - if ((pattern[0] == '*' - && pattern[1] == '\0') - || (pattern[0] == '-' - && pattern[1] == '*' - && pattern[2] == '\0')) - return TRUE; - - while ((c = *p++) != '\0') - { - c = tolower (c); - - switch (c) - { - case '?': - if (*n == '\0') - return FALSE; - break; - - case '*': - for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) - if (c == '?' && *n == '\0') - return FALSE; - - if (c == '\0') - return TRUE; - - c1 = tolower (c); - for (--p; *n != '\0'; ++n) - if (tolower (*n) == c1 - && pattern_match (p, n)) - return TRUE; - return FALSE; - - default: - if (c != tolower (*n)) - return FALSE; - } - - ++n; - } - - if (*n == '\0') - return TRUE; - - return FALSE; -} - -int CALLBACK -InnerEnumFontFamExProc (const LOGFONT *lfp, - const TEXTMETRIC *metrics, - DWORD fontType, - LPARAM lParam) -{ - int size; - gchar *xlfd; - - if (fontType == TRUETYPE_FONTTYPE) - { - size = 0; - } - else - { - size = lfp->lfHeight; - } - - xlfd = logfont_to_xlfd (lfp, size, 0, 0); - - if (!pattern_match ((gchar *) lParam, xlfd)) - { - g_free (xlfd); - return 1; - } - - num_fonts++; - if (num_fonts == font_names_size) - { - font_names_size *= 2; - xfontnames = g_realloc (xfontnames, font_names_size * sizeof (gchar *)); - } - xfontnames[num_fonts-1] = xlfd; - - return 1; -} - -int CALLBACK -EnumFontFamExProc (const LOGFONT *lfp, - const TEXTMETRIC *metrics, - DWORD fontType, - LPARAM lParam) -{ - if (fontType == TRUETYPE_FONTTYPE) - { - LOGFONT lf; - - lf = *lfp; - - EnumFontFamiliesEx (gdk_DC, &lf, InnerEnumFontFamExProc, lParam, 0); - } - else - InnerEnumFontFamExProc (lfp, metrics, fontType, lParam); - - return 1; -} - -gchar ** -gdk_font_list_new (const gchar *font_pattern, - gint *n_returned) -{ - LOGFONT logfont; - gchar **result; - - num_fonts = 0; - font_names_size = 100; - xfontnames = g_new (gchar *, font_names_size); - memset (&logfont, 0, sizeof (logfont)); - logfont.lfCharSet = DEFAULT_CHARSET; - EnumFontFamiliesEx (gdk_DC, &logfont, EnumFontFamExProc, - (LPARAM) font_pattern, 0); - - result = g_new (gchar *, num_fonts + 1); - memmove (result, xfontnames, num_fonts * sizeof (gchar *)); - result[num_fonts] = NULL; - g_free (xfontnames); - - *n_returned = num_fonts; - return result; -} - -void -gdk_font_list_free (gchar **font_list) -{ - g_strfreev (font_list); -} - -GdkWin32SingleFont* -gdk_font_load_internal (const gchar *font_name) -{ - GdkWin32SingleFont *singlefont; - HFONT hfont; - LOGFONT logfont; - CHARSETINFO csi; - DWORD fdwItalic, fdwUnderline, fdwStrikeOut, fdwCharSet, - fdwOutputPrecision, fdwClipPrecision, fdwQuality, fdwPitchAndFamily; - const char *lpszFace; - - int numfields, n1, n2, tries; - char foundry[32], family[100], weight[32], slant[32], set_width[32], - spacing[32], registry[32], encoding[32]; - char pixel_size[10], point_size[10], res_x[10], res_y[10], avg_width[10]; - int c; - char *p; - int nHeight, nWidth, nEscapement, nOrientation, fnWeight; - int logpixelsy; - - g_return_val_if_fail (font_name != NULL, NULL); - - GDK_NOTE (MISC, g_print ("gdk_font_load_internal: %s\n", font_name)); - - numfields = sscanf (font_name, - "-%30[^-]-%100[^-]-%30[^-]-%30[^-]-%30[^-]-%n", - foundry, - family, - weight, - slant, - set_width, - &n1); - if (numfields == 0) - { - /* Probably a plain Windows font name */ - nHeight = 0; - nWidth = 0; - nEscapement = 0; - nOrientation = 0; - fnWeight = FW_DONTCARE; - fdwItalic = FALSE; - fdwUnderline = FALSE; - fdwStrikeOut = FALSE; - fdwCharSet = ANSI_CHARSET; - fdwOutputPrecision = OUT_TT_PRECIS; - fdwClipPrecision = CLIP_DEFAULT_PRECIS; - fdwQuality = PROOF_QUALITY; - fdwPitchAndFamily = DEFAULT_PITCH; - lpszFace = font_name; - } - else if (numfields != 5) - { - g_warning ("gdk_font_load: font name %s illegal", font_name); - return NULL; - } - else - { - /* It must be a XLFD name */ - - /* Check for hex escapes in the font family, - * put in there by gtkfontsel. - */ - p = family; - while (*p) - { - if (*p == '%' && isxdigit (p[1]) && isxdigit (p[2])) - { - sscanf (p+1, "%2x", &c); - *p = c; - strcpy (p+1, p+3); - } - p++; - } - - /* Skip add_style which often is empty in the requested font name */ - while (font_name[n1] && font_name[n1] != '-') - n1++; - numfields++; - - numfields += sscanf (font_name + n1, - "-%8[^-]-%8[^-]-%8[^-]-%8[^-]-%30[^-]-%8[^-]-%30[^-]-%30[^-]%n", - pixel_size, - point_size, - res_x, - res_y, - spacing, - avg_width, - registry, - encoding, - &n2); - - if (numfields != 14 || font_name[n1 + n2] != '\0') - { - g_warning ("gdk_font_load: font name %s illegal", font_name); - return NULL; - } - - logpixelsy = GetDeviceCaps (gdk_DC, LOGPIXELSY); - - if (strcmp (pixel_size, "*") == 0) - if (strcmp (point_size, "*") == 0) - nHeight = 0; - else - nHeight = (int) (((double) atoi (point_size))/720.*logpixelsy); - else - nHeight = atoi (pixel_size); - - nWidth = 0; - nEscapement = 0; - nOrientation = 0; - - if (g_strcasecmp (weight, "thin") == 0) - fnWeight = FW_THIN; - else if (g_strcasecmp (weight, "extralight") == 0) - fnWeight = FW_EXTRALIGHT; - else if (g_strcasecmp (weight, "ultralight") == 0) -#ifdef FW_ULTRALIGHT - fnWeight = FW_ULTRALIGHT; -#else - fnWeight = FW_EXTRALIGHT; /* In fact, FW_ULTRALIGHT really is - * defined as FW_EXTRALIGHT anyway. - */ -#endif - else if (g_strcasecmp (weight, "light") == 0) - fnWeight = FW_LIGHT; - else if (g_strcasecmp (weight, "normal") == 0) - fnWeight = FW_NORMAL; - else if (g_strcasecmp (weight, "regular") == 0) - fnWeight = FW_REGULAR; - else if (g_strcasecmp (weight, "medium") == 0) - fnWeight = FW_MEDIUM; - else if (g_strcasecmp (weight, "semibold") == 0) - fnWeight = FW_SEMIBOLD; - else if (g_strcasecmp (weight, "demibold") == 0) -#ifdef FW_DEMIBOLD - fnWeight = FW_DEMIBOLD; -#else - fnWeight = FW_SEMIBOLD; /* As above */ -#endif - else if (g_strcasecmp (weight, "bold") == 0) - fnWeight = FW_BOLD; - else if (g_strcasecmp (weight, "extrabold") == 0) - fnWeight = FW_EXTRABOLD; - else if (g_strcasecmp (weight, "ultrabold") == 0) -#ifdef FW_ULTRABOLD - fnWeight = FW_ULTRABOLD; -#else - fnWeight = FW_EXTRABOLD; /* As above */ -#endif - else if (g_strcasecmp (weight, "heavy") == 0) - fnWeight = FW_HEAVY; - else if (g_strcasecmp (weight, "black") == 0) -#ifdef FW_BLACK - fnWeight = FW_BLACK; -#else - fnWeight = FW_HEAVY; /* As above */ -#endif - else - fnWeight = FW_DONTCARE; - - if (g_strcasecmp (slant, "italic") == 0 - || g_strcasecmp (slant, "oblique") == 0 - || g_strcasecmp (slant, "i") == 0 - || g_strcasecmp (slant, "o") == 0) - fdwItalic = TRUE; - else - fdwItalic = FALSE; - fdwUnderline = FALSE; - fdwStrikeOut = FALSE; - if (g_strcasecmp (registry, "iso8859") == 0) - if (strcmp (encoding, "1") == 0) - fdwCharSet = ANSI_CHARSET; - else if (strcmp (encoding, "2") == 0) - fdwCharSet = EASTEUROPE_CHARSET; - else if (strcmp (encoding, "7") == 0) - fdwCharSet = GREEK_CHARSET; - else if (strcmp (encoding, "8") == 0) - fdwCharSet = HEBREW_CHARSET; - else if (strcmp (encoding, "9") == 0) - fdwCharSet = TURKISH_CHARSET; - else - fdwCharSet = ANSI_CHARSET; /* XXX ??? */ - else if (g_strcasecmp (registry, "jisx0208.1983") == 0) - fdwCharSet = SHIFTJIS_CHARSET; - else if (g_strcasecmp (registry, "ksc5601.1987") == 0) - fdwCharSet = HANGEUL_CHARSET; - else if (g_strcasecmp (registry, "gb2312.1980") == 0) - fdwCharSet = GB2312_CHARSET; - else if (g_strcasecmp (registry, "big5") == 0) - fdwCharSet = CHINESEBIG5_CHARSET; - else if (g_strcasecmp (registry, "windows") == 0 - || g_strcasecmp (registry, "microsoft") == 0) - if (g_strcasecmp (encoding, "symbol") == 0) - fdwCharSet = SYMBOL_CHARSET; - else if (g_strcasecmp (encoding, "shiftjis") == 0) - fdwCharSet = SHIFTJIS_CHARSET; - else if (g_strcasecmp (encoding, "gb2312") == 0) - fdwCharSet = GB2312_CHARSET; - else if (g_strcasecmp (encoding, "hangeul") == 0) - fdwCharSet = HANGEUL_CHARSET; - else if (g_strcasecmp (encoding, "big5") == 0) - fdwCharSet = CHINESEBIG5_CHARSET; - else if (g_strcasecmp (encoding, "johab") == 0) - fdwCharSet = JOHAB_CHARSET; - else if (g_strcasecmp (encoding, "hebrew") == 0) - fdwCharSet = HEBREW_CHARSET; - else if (g_strcasecmp (encoding, "arabic") == 0) - fdwCharSet = ARABIC_CHARSET; - else if (g_strcasecmp (encoding, "greek") == 0) - fdwCharSet = GREEK_CHARSET; - else if (g_strcasecmp (encoding, "turkish") == 0) - fdwCharSet = TURKISH_CHARSET; - else if (g_strcasecmp (encoding, "easteurope") == 0) - fdwCharSet = EASTEUROPE_CHARSET; - else if (g_strcasecmp (encoding, "russian") == 0) - fdwCharSet = RUSSIAN_CHARSET; - else if (g_strcasecmp (encoding, "mac") == 0) - fdwCharSet = MAC_CHARSET; - else if (g_strcasecmp (encoding, "baltic") == 0) - fdwCharSet = BALTIC_CHARSET; - else if (g_strcasecmp (encoding, "cp1251") == 0) - fdwCharSet = RUSSIAN_CHARSET; - else - fdwCharSet = ANSI_CHARSET; /* XXX ??? */ - else - fdwCharSet = ANSI_CHARSET; /* XXX ??? */ - fdwOutputPrecision = OUT_TT_PRECIS; - fdwClipPrecision = CLIP_DEFAULT_PRECIS; - fdwQuality = PROOF_QUALITY; - if (g_strcasecmp (spacing, "m") == 0) - fdwPitchAndFamily = FIXED_PITCH; - else if (g_strcasecmp (spacing, "p") == 0) - fdwPitchAndFamily = VARIABLE_PITCH; - else - fdwPitchAndFamily = DEFAULT_PITCH; - lpszFace = family; - } - - for (tries = 0; ; tries++) - { - GDK_NOTE (MISC, g_print ("...trying CreateFont(%d,%d,%d,%d," - "%d,%d,%d,%d," - "%d,%d,%d," - "%d,%#.02x,\"%s\")\n", - nHeight, nWidth, nEscapement, nOrientation, - fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut, - fdwCharSet, fdwOutputPrecision, fdwClipPrecision, - fdwQuality, fdwPitchAndFamily, lpszFace)); - if ((hfont = - CreateFont (nHeight, nWidth, nEscapement, nOrientation, - fnWeight, fdwItalic, fdwUnderline, fdwStrikeOut, - fdwCharSet, fdwOutputPrecision, fdwClipPrecision, - fdwQuality, fdwPitchAndFamily, lpszFace)) != NULL) - break; - - /* If we fail, try some similar fonts often found on Windows. */ - - if (tries == 0) - { - if (g_strcasecmp (family, "helvetica") == 0) - lpszFace = "arial"; - else if (g_strcasecmp (family, "new century schoolbook") == 0) - lpszFace = "century schoolbook"; - else if (g_strcasecmp (family, "courier") == 0) - lpszFace = "courier new"; - else if (g_strcasecmp (family, "lucida") == 0) - lpszFace = "lucida sans unicode"; - else if (g_strcasecmp (family, "lucidatypewriter") == 0) - lpszFace = "lucida console"; - else if (g_strcasecmp (family, "times") == 0) - lpszFace = "times new roman"; - } - else if (tries == 1) - { - if (g_strcasecmp (family, "courier") == 0) - { - lpszFace = ""; - fdwPitchAndFamily |= FF_MODERN; - } - else if (g_strcasecmp (family, "times new roman") == 0) - { - lpszFace = ""; - fdwPitchAndFamily |= FF_ROMAN; - } - else if (g_strcasecmp (family, "helvetica") == 0 - || g_strcasecmp (family, "lucida") == 0) - { - lpszFace = ""; - fdwPitchAndFamily |= FF_SWISS; - } - else - { - lpszFace = ""; - fdwPitchAndFamily = (fdwPitchAndFamily & 0x0F) | FF_DONTCARE; - } - } - else - break; - tries++; - } - - if (!hfont) - return NULL; - - singlefont = g_new (GdkWin32SingleFont, 1); - singlefont->xfont = hfont; - GetObject (singlefont->xfont, sizeof (logfont), &logfont); - TranslateCharsetInfo ((DWORD *) singlefont->charset, &csi, TCI_SRCCHARSET); - singlefont->codepage = csi.ciACP; - GetCPInfo (singlefont->codepage, &singlefont->cpinfo); - - return singlefont; -} - -GdkFont* -gdk_font_load (const gchar *font_name) -{ - GdkFont *font; - GdkFontPrivate *private; - GdkWin32SingleFont *singlefont; - HGDIOBJ oldfont; - HANDLE *f; - TEXTMETRIC textmetric; - - g_return_val_if_fail (font_name != NULL, NULL); - - font = gdk_font_hash_lookup (GDK_FONT_FONTSET, font_name); - if (font) - return font; - - singlefont = gdk_font_load_internal (font_name); - - private = g_new (GdkFontPrivate, 1); - font = (GdkFont*) private; - - private->ref_count = 1; - private->names = NULL; - private->fonts = g_slist_append (NULL, singlefont); - - /* Pretend all fonts are fontsets... Gtktext and gtkentry work better - * that way, they use wide chars, which is necessary for non-ASCII - * chars to work. (Yes, even Latin-1, as we use Unicode internally.) - */ - font->type = GDK_FONT_FONTSET; - oldfont = SelectObject (gdk_DC, singlefont->xfont); - GetTextMetrics (gdk_DC, &textmetric); - singlefont->charset = GetTextCharsetInfo (gdk_DC, &singlefont->fs, 0); - SelectObject (gdk_DC, oldfont); - font->ascent = textmetric.tmAscent; - font->descent = textmetric.tmDescent; - - GDK_NOTE (MISC, g_print ("... = %#x charset %s codepage %d " - "asc %d desc %d\n", - singlefont->xfont, - charset_name (singlefont->charset), - singlefont->codepage, - font->ascent, font->descent)); - - gdk_font_hash_insert (GDK_FONT_FONTSET, font, font_name); - - return font; -} - -GdkFont* -gdk_fontset_load (gchar *fontset_name) -{ - GdkFont *font; - GdkFontPrivate *private; - GdkWin32SingleFont *singlefont; - HGDIOBJ oldfont; - HANDLE *f; - TEXTMETRIC textmetric; - GSList *base_font_list = NULL; - gchar *fs; - gchar *b, *p, *s; - - g_return_val_if_fail (fontset_name != NULL, NULL); - - font = gdk_font_hash_lookup (GDK_FONT_FONTSET, fontset_name); - if (font) - return font; - - s = fs = g_strdup (fontset_name); - while (*s && isspace (*s)) - s++; - - g_return_val_if_fail (*s, NULL); - - private = g_new (GdkFontPrivate, 1); - font = (GdkFont*) private; - - private->ref_count = 1; - private->names = NULL; - private->fonts = NULL; - - font->type = GDK_FONT_FONTSET; - font->ascent = 0; - font->descent = 0; - - while (TRUE) - { - if ((p = strchr (s, ',')) != NULL) - b = p; - else - b = s + strlen (s); - - while (isspace (b[-1])) - b--; - *b = '\0'; - singlefont = gdk_font_load_internal (s); - if (singlefont) - { - GDK_NOTE - (MISC, g_print ("... = %#x charset %s codepage %d\n", - singlefont->xfont, - charset_name (singlefont->charset), - singlefont->codepage)); - private->fonts = g_slist_append (private->fonts, singlefont); - oldfont = SelectObject (gdk_DC, singlefont->xfont); - GetTextMetrics (gdk_DC, &textmetric); - singlefont->charset = - GetTextCharsetInfo (gdk_DC, &singlefont->fs, 0); - SelectObject (gdk_DC, oldfont); - font->ascent = MAX (font->ascent, textmetric.tmAscent); - font->descent = MAX (font->descent, textmetric.tmDescent); - } - if (p) - { - s = p + 1; - while (*s && isspace (*s)) - s++; - } - else - break; - if (!*s) - break; - } - - g_free (fs); - - gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name); - - return font; -} - -GdkFont* -gdk_font_ref (GdkFont *font) -{ - GdkFontPrivate *private; - - g_return_val_if_fail (font != NULL, NULL); - - private = (GdkFontPrivate*) font; - private->ref_count += 1; - - GDK_NOTE (MISC, - g_print ("gdk_font_ref %#x %d\n", - ((GdkWin32SingleFont *) private->fonts->data)->xfont, - private->ref_count)); - return font; -} - -void -gdk_font_unref (GdkFont *font) -{ - GdkFontPrivate *private; - GdkWin32SingleFont *singlefont; - GSList *list; - private = (GdkFontPrivate*) font; - - g_return_if_fail (font != NULL); - g_return_if_fail (private->ref_count > 0); - - private->ref_count -= 1; - - singlefont = (GdkWin32SingleFont *) private->fonts->data; - GDK_NOTE (MISC, g_print ("gdk_font_unref %#x %d%s\n", - singlefont->xfont, private->ref_count, - (private->ref_count == 0 ? " freeing" : ""))); - - if (private->ref_count == 0) - { - gdk_font_hash_remove (font->type, font); - - switch (font->type) - { - case GDK_FONT_FONT: - DeleteObject (singlefont->xfont); - break; - - case GDK_FONT_FONTSET: - list = private->fonts; - while (list) - { - singlefont = (GdkWin32SingleFont *) list->data; - DeleteObject (singlefont->xfont); - - list = list->next; - } - g_slist_free (private->fonts); - break; - - default: - g_assert_not_reached (); - } - g_free (font); - } -} - -gint -gdk_font_id (const GdkFont *font) -{ - const GdkFontPrivate *font_private; - - g_return_val_if_fail (font != NULL, 0); - - font_private = (const GdkFontPrivate*) font; - - if (font->type == GDK_FONT_FONT) - return (gint) ((GdkWin32SingleFont *) font_private->fonts->data)->xfont; - else - return 0; -} - -gint -gdk_font_equal (const GdkFont *fonta, - const GdkFont *fontb) -{ - const GdkFontPrivate *privatea; - const GdkFontPrivate *privateb; - - g_return_val_if_fail (fonta != NULL, FALSE); - g_return_val_if_fail (fontb != NULL, FALSE); - - privatea = (const GdkFontPrivate*) fonta; - privateb = (const GdkFontPrivate*) fontb; - - if (fonta->type == GDK_FONT_FONT && fontb->type == GDK_FONT_FONT) - return (((GdkWin32SingleFont *) privatea->fonts->data)->xfont - == ((GdkWin32SingleFont *) privateb->fonts->data)->xfont); - else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET) - { - GSList *lista = privatea->fonts; - GSList *listb = privateb->fonts; - - while (lista && listb) - { - if (((GdkWin32SingleFont *) lista->data)->xfont - != ((GdkWin32SingleFont *) listb->data)->xfont) - return 0; - lista = lista->next; - listb = listb->next; - } - if (lista || listb) - return 0; - else - return 1; - } - else - return 0; -} - -gint -gdk_string_width (GdkFont *font, - const gchar *string) -{ - return gdk_text_width (font, string, strlen (string)); -} - -/* This table classifies Unicode characters according to the Microsoft - * Unicode subset numbering. This is from the table in "Developing - * International Software for Windows 95 and Windows NT". This is almost, - * but not quite, the same as the official Unicode block table in - * Blocks.txt from ftp.unicode.org. The bit number field is the bitfield - * number as in the FONTSIGNATURE struct's fsUsb field. - */ -static struct { - wchar_t low, high; - guint bit; - gchar *name; -} utab[] = -{ - { 0x0000, 0x007E, 0, "Basic Latin" }, - { 0x00A0, 0x00FF, 1, "Latin-1 Supplement" }, - { 0x0100, 0x017F, 2, "Latin Extended-A" }, - { 0x0180, 0x024F, 3, "Latin Extended-B" }, - { 0x0250, 0x02AF, 4, "IPA Extensions" }, - { 0x02B0, 0x02FF, 5, "Spacing Modifier Letters" }, - { 0x0300, 0x036F, 6, "Combining Diacritical Marks" }, - { 0x0370, 0x03CF, 7, "Basic Greek" }, - { 0x03D0, 0x03FF, 8, "Greek Symbols and Coptic" }, - { 0x0400, 0x04FF, 9, "Cyrillic" }, - { 0x0530, 0x058F, 10, "Armenian" }, - { 0x0590, 0x05CF, 12, "Hebrew Extended" }, - { 0x05D0, 0x05FF, 11, "Basic Hebrew" }, - { 0x0600, 0x0652, 13, "Basic Arabic" }, - { 0x0653, 0x06FF, 14, "Arabic Extended" }, - { 0x0900, 0x097F, 15, "Devanagari" }, - { 0x0980, 0x09FF, 16, "Bengali" }, - { 0x0A00, 0x0A7F, 17, "Gurmukhi" }, - { 0x0A80, 0x0AFF, 18, "Gujarati" }, - { 0x0B00, 0x0B7F, 19, "Oriya" }, - { 0x0B80, 0x0BFF, 20, "Tamil" }, - { 0x0C00, 0x0C7F, 21, "Telugu" }, - { 0x0C80, 0x0CFF, 22, "Kannada" }, - { 0x0D00, 0x0D7F, 23, "Malayalam" }, - { 0x0E00, 0x0E7F, 24, "Thai" }, - { 0x0E80, 0x0EFF, 25, "Lao" }, - { 0x10A0, 0x10CF, 27, "Georgian Extended" }, - { 0x10D0, 0x10FF, 26, "Basic Georgian" }, - { 0x1100, 0x11FF, 28, "Hangul Jamo" }, - { 0x1E00, 0x1EFF, 29, "Latin Extended Additional" }, - { 0x1F00, 0x1FFF, 30, "Greek Extended" }, - { 0x2000, 0x206F, 31, "General Punctuation" }, - { 0x2070, 0x209F, 32, "Superscripts and Subscripts" }, - { 0x20A0, 0x20CF, 33, "Currency Symbols" }, - { 0x20D0, 0x20FF, 34, "Combining Diacritical Marks for Symbols" }, - { 0x2100, 0x214F, 35, "Letterlike Symbols" }, - { 0x2150, 0x218F, 36, "Number Forms" }, - { 0x2190, 0x21FF, 37, "Arrows" }, - { 0x2200, 0x22FF, 38, "Mathematical Operators" }, - { 0x2300, 0x23FF, 39, "Miscellaneous Technical" }, - { 0x2400, 0x243F, 40, "Control Pictures" }, - { 0x2440, 0x245F, 41, "Optical Character Recognition" }, - { 0x2460, 0x24FF, 42, "Enclosed Alphanumerics" }, - { 0x2500, 0x257F, 43, "Box Drawing" }, - { 0x2580, 0x259F, 44, "Block Elements" }, - { 0x25A0, 0x25FF, 45, "Geometric Shapes" }, - { 0x2600, 0x26FF, 46, "Miscellaneous Symbols" }, - { 0x2700, 0x27BF, 47, "Dingbats" }, - { 0x3000, 0x303F, 48, "CJK Symbols and Punctuation" }, - { 0x3040, 0x309F, 49, "Hiragana" }, - { 0x30A0, 0x30FF, 50, "Katakana" }, - { 0x3100, 0x312F, 51, "Bopomofo" }, - { 0x3130, 0x318F, 52, "Hangul Compatibility Jamo" }, - { 0x3190, 0x319F, 53, "CJK Miscellaneous" }, - { 0x3200, 0x32FF, 54, "Enclosed CJK" }, - { 0x3300, 0x33FF, 55, "CJK Compatibility" }, - { 0x3400, 0x3D2D, 56, "Hangul" }, - { 0x3D2E, 0x44B7, 57, "Hangul Supplementary-A" }, - { 0x44B8, 0x4DFF, 58, "Hangul Supplementary-B" }, - { 0x4E00, 0x9FFF, 59, "CJK Unified Ideographs" }, - { 0xE000, 0xF8FF, 60, "Private Use Area" }, - { 0xF900, 0xFAFF, 61, "CJK Compatibility Ideographs" }, - { 0xFB00, 0xFB4F, 62, "Alphabetic Presentation Forms" }, - { 0xFB50, 0xFDFF, 63, "Arabic Presentation Forms-A" }, - { 0xFE20, 0xFE2F, 64, "Combining Half Marks" }, - { 0xFE30, 0xFE4F, 65, "CJK Compatibility Forms" }, - { 0xFE50, 0xFE6F, 66, "Small Form Variants" }, - { 0xFE70, 0xFEFE, 67, "Arabic Presentation Forms-B" }, - { 0xFEFF, 0xFEFF, 69, "Specials" }, - { 0xFF00, 0xFFEF, 68, "Halfwidth and Fullwidth Forms" }, - { 0xFFF0, 0xFFFD, 69, "Specials" } -}; - -/* Return the Unicode Subset bitfield number for a Unicode character */ - -static int -unicode_classify (wchar_t wc) -{ - int min = 0; - int max = sizeof (utab) / sizeof (utab[0]) - 1; - int mid; - - while (max >= min) - { - mid = (min + max) / 2; - if (utab[mid].high < wc) - min = mid + 1; - else if (wc < utab[mid].low) - max = mid - 1; - else if (utab[mid].low <= wc && wc <= utab[mid].high) - return utab[mid].bit; - else - return -1; - } -} - -void -gdk_wchar_text_handle (GdkFont *font, - const wchar_t *wcstr, - int wclen, - void (*handler)(GdkWin32SingleFont *, - const wchar_t *, - int, - void *), - void *arg) -{ - GdkFontPrivate *private; - GdkWin32SingleFont *singlefont; - GSList *list; - int i, block; - const wchar_t *start, *end, *wcp; - - wcp = wcstr; - end = wcp + wclen; - private = (GdkFontPrivate *) font; - - g_assert (private->ref_count > 0); - - while (wcp < end) - { - /* Split Unicode string into pieces of the same class */ - start = wcp; - block = unicode_classify (*wcp); - while (wcp + 1 < end && unicode_classify (wcp[1]) == block) - wcp++; - - /* Find a font in the fontset that can handle this class */ - list = private->fonts; - while (list) - { - singlefont = (GdkWin32SingleFont *) list->data; - - if (singlefont->fs.fsUsb[block/32] & (1 << (block % 32))) - break; - - list = list->next; - } - - if (!list) - singlefont = NULL; - - /* Call the callback function */ - (*handler) (singlefont, start, wcp+1 - start, arg); - wcp++; - } -} - -typedef struct -{ - SIZE total; - SIZE max; -} gdk_text_size_arg; - -static void -gdk_text_size_handler (GdkWin32SingleFont *singlefont, - const wchar_t *wcstr, - int wclen, - void *argp) -{ - SIZE this_size; - HGDIOBJ oldfont; - gdk_text_size_arg *arg = (gdk_text_size_arg *) argp; - - if (!singlefont) - return; - - if ((oldfont = SelectObject (gdk_DC, singlefont->xfont)) == NULL) - { - g_warning ("gdk_text_size_handler: SelectObject failed"); - return; - } - GetTextExtentPoint32W (gdk_DC, wcstr, wclen, &this_size); - SelectObject (gdk_DC, oldfont); - - arg->total.cx += this_size.cx; - arg->total.cy += this_size.cy; - arg->max.cx = MAX (this_size.cx, arg->max.cx); - arg->max.cy = MAX (this_size.cy, arg->max.cy); -} - -static gboolean -gdk_text_size (GdkFont *font, - const gchar *text, - gint text_length, - gdk_text_size_arg *arg) -{ - gint wlen; - wchar_t *wcstr; - - g_return_val_if_fail (font != NULL, FALSE); - g_return_val_if_fail (text != NULL, FALSE); - - if (text_length == 0) - return 0; - - g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET); - - wcstr = g_new (wchar_t, text_length); - if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1) - g_warning ("gdk_text_size: gdk_nmbstowchar_ts failed"); - else - gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, arg); - - g_free (wcstr); - - return TRUE; -} - -gint -gdk_text_width (GdkFont *font, - const gchar *text, - gint text_length) -{ - gdk_text_size_arg arg; - - arg.total.cx = arg.total.cy = 0; - arg.max.cx = arg.max.cy = 0; - - if (!gdk_text_size (font, text, text_length, &arg)) - return -1; - - return arg.total.cx; -} - -gint -gdk_text_width_wc (GdkFont *font, - const GdkWChar *text, - gint text_length) -{ - gdk_text_size_arg arg; - wchar_t *wcstr; - gint i; - - g_return_val_if_fail (font != NULL, -1); - g_return_val_if_fail (text != NULL, -1); - - if (text_length == 0) - return 0; - - g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET); - - if (sizeof (wchar_t) != sizeof (GdkWChar)) - { - wcstr = g_new (wchar_t, text_length); - for (i = 0; i < text_length; i++) - wcstr[i] = text[i]; - } - else - wcstr = (wchar_t *) text; - - arg.total.cx = arg.total.cy = 0; - arg.max.cx = arg.max.cy = 0; - - gdk_wchar_text_handle (font, wcstr, text_length, - gdk_text_size_handler, &arg); - - if (sizeof (wchar_t) != sizeof (GdkWChar)) - g_free (wcstr); - - return arg.total.cx; -} - -gint -gdk_char_width (GdkFont *font, - gchar character) -{ - if (((guchar) character) >= 128) - { - /* gtktext calls us with non-ASCII characters, sigh */ - GdkWChar wc = (guchar) character; - return gdk_text_width_wc (font, &wc, 1); - } - return gdk_text_width (font, &character, 1); -} - -gint -gdk_char_width_wc (GdkFont *font, - GdkWChar character) -{ - return gdk_text_width_wc (font, &character, 1); -} - -gint -gdk_string_measure (GdkFont *font, - const gchar *string) -{ - g_return_val_if_fail (font != NULL, -1); - g_return_val_if_fail (string != NULL, -1); - - return gdk_text_measure (font, string, strlen (string)); -} - -void -gdk_text_extents (GdkFont *font, - const gchar *text, - gint text_length, - gint *lbearing, - gint *rbearing, - gint *width, - gint *ascent, - gint *descent) -{ - gdk_text_size_arg arg; - gint wlen; - wchar_t *wcstr; - - g_return_if_fail (font != NULL); - g_return_if_fail (text != NULL); - - if (text_length == 0) - { - if (lbearing) - *lbearing = 0; - if (rbearing) - *rbearing = 0; - if (width) - *width = 0; - if (ascent) - *ascent = 0; - if (descent) - *descent = 0; - return; - } - - g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET); - - arg.total.cx = arg.total.cy = 0; - arg.max.cx = arg.max.cy = 0; - - wcstr = g_new (wchar_t, text_length); - if ((wlen = gdk_nmbstowchar_ts (wcstr, text, text_length, text_length)) == -1) - g_warning ("gdk_text_extents: gdk_nmbstowchar_ts failed"); - else - gdk_wchar_text_handle (font, wcstr, wlen, gdk_text_size_handler, &arg); - - g_free (wcstr); - - /* XXX This is quite bogus */ - if (lbearing) - *lbearing = 0; - if (rbearing) - *rbearing = 0; - if (width) - *width = arg.total.cx; - if (ascent) - *ascent = arg.max.cy + 1; - if (descent) - *descent = font->descent + 1; -} - -void -gdk_text_extents_wc (GdkFont *font, - const GdkWChar *text, - gint text_length, - gint *lbearing, - gint *rbearing, - gint *width, - gint *ascent, - gint *descent) -{ - gdk_text_size_arg arg; - wchar_t *wcstr; - gint i; - - g_return_if_fail (font != NULL); - g_return_if_fail (text != NULL); - - if (text_length == 0) - { - if (lbearing) - *lbearing = 0; - if (rbearing) - *rbearing = 0; - if (width) - *width = 0; - if (ascent) - *ascent = 0; - if (descent) - *descent = 0; - return; - } - - g_assert (font->type == GDK_FONT_FONT || font->type == GDK_FONT_FONTSET); - - if (sizeof (wchar_t) != sizeof (GdkWChar)) - { - wcstr = g_new (wchar_t, text_length); - for (i = 0; i < text_length; i++) - wcstr[i] = text[i]; - } - else - wcstr = (wchar_t *) text; - - arg.total.cx = arg.total.cy = 0; - arg.max.cx = arg.max.cy = 0; - - gdk_wchar_text_handle (font, wcstr, text_length, - gdk_text_size_handler, &arg); - - if (sizeof (wchar_t) != sizeof (GdkWChar)) - g_free (wcstr); - - /* XXX This is quite bogus */ - if (lbearing) - *lbearing = 0; - if (rbearing) - *rbearing = 0; - if (width) - *width = arg.total.cx; - if (ascent) - *ascent = arg.max.cy + 1; - if (descent) - *descent = font->descent + 1; -} - -void -gdk_string_extents (GdkFont *font, - const gchar *string, - gint *lbearing, - gint *rbearing, - gint *width, - gint *ascent, - gint *descent) -{ - g_return_if_fail (font != NULL); - g_return_if_fail (string != NULL); - - gdk_text_extents (font, string, strlen (string), - lbearing, rbearing, width, ascent, descent); -} - - -gint -gdk_text_measure (GdkFont *font, - const gchar *text, - gint text_length) -{ - return gdk_text_width (font, text, text_length); /* ??? */ -} - -gint -gdk_char_measure (GdkFont *font, - gchar character) -{ - return gdk_text_measure (font, &character, 1); -} - -gint -gdk_string_height (GdkFont *font, - const gchar *string) -{ - g_return_val_if_fail (font != NULL, -1); - g_return_val_if_fail (string != NULL, -1); - - return gdk_text_height (font, string, strlen (string)); -} - -gint -gdk_text_height (GdkFont *font, - const gchar *text, - gint text_length) -{ - gdk_text_size_arg arg; - - arg.total.cx = arg.total.cy = 0; - arg.max.cx = arg.max.cy = 0; - - if (!gdk_text_size (font, text, text_length, &arg)) - return -1; - - return arg.max.cy; -} - -gint -gdk_char_height (GdkFont *font, - gchar character) -{ - return gdk_text_height (font, &character, 1); -} |