forked from AuroraMiddleware/gtk
b1c28ea656
1999-10-21 Tor Lillqvist <tml@iki.fi> * gdk/win32/gdkprivate.h: Add more font private data. * gdk/win32/gdkfont.c * gdk/win32/gdkdraw.c: Revamped handling of multi-byte charset fonts and strings. Now works much better. You still have to have a correct font selected, though. No fontset emulation yet.
952 lines
23 KiB
C
952 lines
23 KiB
C
/* 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 "gdkprivate.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 "CHINESEBIG5";
|
|
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";
|
|
}
|
|
|
|
GdkFont*
|
|
gdk_font_load (const gchar *font_name)
|
|
{
|
|
GdkFont *font;
|
|
GdkFontPrivate *private;
|
|
HFONT hfont;
|
|
LOGFONT logfont;
|
|
HGDIOBJ oldfont;
|
|
TEXTMETRIC textmetric;
|
|
CHARSETINFO csi;
|
|
HANDLE *f;
|
|
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: %s\n", font_name));
|
|
|
|
font = gdk_font_hash_lookup (GDK_FONT_FONT, font_name);
|
|
if (font)
|
|
return font;
|
|
|
|
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);
|
|
g_free (font);
|
|
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);
|
|
g_free (font);
|
|
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
|
|
fdwCharSet = ANSI_CHARSET; /* XXX ??? */
|
|
else if (g_strcasecmp (registry, "windows") == 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, "chinesebig5") == 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
|
|
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;
|
|
|
|
private = g_new (GdkFontPrivate, 1);
|
|
font = (GdkFont*) private;
|
|
|
|
private->xfont = hfont;
|
|
private->ref_count = 1;
|
|
private->names = NULL;
|
|
font->type = GDK_FONT_FONT;
|
|
GetObject (private->xfont, sizeof (logfont), &logfont);
|
|
oldfont = SelectObject (gdk_DC, private->xfont);
|
|
GetTextMetrics (gdk_DC, &textmetric);
|
|
private->charset = GetTextCharsetInfo (gdk_DC, &private->fs, 0);
|
|
SelectObject (gdk_DC, oldfont);
|
|
TranslateCharsetInfo ((DWORD *) private->charset, &csi, TCI_SRCCHARSET);
|
|
private->codepage = csi.ciACP;
|
|
GetCPInfo (private->codepage, &private->cpinfo);
|
|
font->ascent = textmetric.tmAscent;
|
|
font->descent = textmetric.tmDescent;
|
|
|
|
GDK_NOTE (MISC, g_print ("... = %#x charset %s codepage %d (max %d bytes) "
|
|
"asc %d desc %d\n",
|
|
private->xfont,
|
|
charset_name (private->charset),
|
|
private->codepage,
|
|
private->cpinfo.MaxCharSize,
|
|
font->ascent, font->descent));
|
|
|
|
/* This memory is leaked, so shoot me. */
|
|
f = g_new (HANDLE, 1);
|
|
*f = (HANDLE) ((guint) private->xfont + HFONT_DITHER);
|
|
gdk_xid_table_insert (f, font);
|
|
|
|
gdk_font_hash_insert (GDK_FONT_FONT, font, font_name);
|
|
|
|
return font;
|
|
}
|
|
|
|
GdkFont*
|
|
gdk_fontset_load (gchar *fontset_name)
|
|
{
|
|
g_warning ("gdk_fontset_load: Not implemented");
|
|
|
|
return NULL;
|
|
}
|
|
|
|
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",
|
|
private->xfont, private->ref_count));
|
|
return font;
|
|
}
|
|
|
|
void
|
|
gdk_font_unref (GdkFont *font)
|
|
{
|
|
GdkFontPrivate *private;
|
|
private = (GdkFontPrivate*) font;
|
|
|
|
g_return_if_fail (font != NULL);
|
|
g_return_if_fail (private->ref_count > 0);
|
|
|
|
private->ref_count -= 1;
|
|
|
|
GDK_NOTE (MISC, g_print ("gdk_font_unref %#x %d%s\n",
|
|
private->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:
|
|
gdk_xid_table_remove ((HANDLE) ((guint) private->xfont + HFONT_DITHER));
|
|
DeleteObject (private->xfont);
|
|
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) font_private->xfont;
|
|
|
|
g_assert_not_reached ();
|
|
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 (privatea->xfont == privateb->xfont);
|
|
|
|
g_assert_not_reached ();
|
|
return 0;
|
|
}
|
|
|
|
gint
|
|
gdk_string_width (GdkFont *font,
|
|
const gchar *string)
|
|
{
|
|
return gdk_text_width (font, string, strlen (string));
|
|
}
|
|
|
|
gint
|
|
gdk_text_width (GdkFont *font,
|
|
const gchar *text,
|
|
gint text_length)
|
|
{
|
|
GdkFontPrivate *private;
|
|
HGDIOBJ oldfont;
|
|
SIZE size;
|
|
gint width, wlen;
|
|
wchar_t *wcstr;
|
|
|
|
g_return_val_if_fail (font != NULL, -1);
|
|
g_return_val_if_fail (text != NULL, -1);
|
|
|
|
if (text_length == 0)
|
|
return 0;
|
|
|
|
private = (GdkFontPrivate*) font;
|
|
|
|
switch (font->type)
|
|
{
|
|
case GDK_FONT_FONT:
|
|
oldfont = SelectObject (gdk_DC, private->xfont);
|
|
if (private->cpinfo.MaxCharSize > 1)
|
|
{
|
|
wcstr = g_new (wchar_t, text_length);
|
|
if ((wlen = MultiByteToWideChar (private->codepage, 0,
|
|
text, text_length,
|
|
wcstr, text_length)) == 0)
|
|
{
|
|
g_warning ("gdk_text_width: MultiByteToWideChar failed");
|
|
size.cx = 0;
|
|
}
|
|
else
|
|
GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
|
|
g_free (wcstr);
|
|
}
|
|
else
|
|
{
|
|
GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
|
|
}
|
|
SelectObject (gdk_DC, oldfont);
|
|
width = size.cx;
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
return width;
|
|
}
|
|
|
|
gint
|
|
gdk_text_width_wc (GdkFont *font,
|
|
const GdkWChar *text,
|
|
gint text_length)
|
|
{
|
|
GdkFontPrivate *private;
|
|
HGDIOBJ oldfont;
|
|
SIZE size;
|
|
wchar_t *wcstr;
|
|
guchar *str;
|
|
gint i, width, wlen;
|
|
|
|
g_return_val_if_fail (font != NULL, -1);
|
|
g_return_val_if_fail (text != NULL, -1);
|
|
|
|
if (text_length == 0)
|
|
return 0;
|
|
|
|
private = (GdkFontPrivate*) font;
|
|
|
|
switch (font->type)
|
|
{
|
|
case GDK_FONT_FONT:
|
|
oldfont = SelectObject (gdk_DC, private->xfont);
|
|
#if 0 /* No. Don't assume Unicode here either.
|
|
* (Read the comments in gdk_draw_text_wc.)
|
|
*/
|
|
wcstr = g_new (wchar_t, text_length);
|
|
for (i = 0; i < text_length; i++)
|
|
wcstr[i] = text[i];
|
|
GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
|
|
g_free (wcstr);
|
|
#else
|
|
str = g_new (guchar, text_length);
|
|
for (i = 0; i < text_length; i++)
|
|
str[i] = text[i];
|
|
if (private->cpinfo.MaxCharSize > 1)
|
|
{
|
|
wcstr = g_new (wchar_t, text_length);
|
|
if ((wlen = MultiByteToWideChar (private->codepage, 0,
|
|
str, text_length,
|
|
wcstr, text_length)) == 0)
|
|
{
|
|
g_warning ("gdk_text_width_wc: MultiByteToWideChar failed");
|
|
size.cx = 0;
|
|
}
|
|
else
|
|
GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
|
|
g_free (wcstr);
|
|
}
|
|
else
|
|
{
|
|
GetTextExtentPoint32A (gdk_DC, str, text_length, &size);
|
|
}
|
|
g_free (str);
|
|
#endif
|
|
SelectObject (gdk_DC, oldfont);
|
|
width = size.cx;
|
|
break;
|
|
|
|
default:
|
|
width = 0;
|
|
}
|
|
return width;
|
|
}
|
|
|
|
gint
|
|
gdk_char_width (GdkFont *font,
|
|
gchar character)
|
|
{
|
|
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)
|
|
{
|
|
GdkFontPrivate *private;
|
|
HGDIOBJ oldfont;
|
|
SIZE size;
|
|
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;
|
|
}
|
|
|
|
private = (GdkFontPrivate*) font;
|
|
|
|
switch (font->type)
|
|
{
|
|
case GDK_FONT_FONT:
|
|
oldfont = SelectObject (gdk_DC, private->xfont);
|
|
if (private->cpinfo.MaxCharSize > 1)
|
|
{
|
|
wcstr = g_new (wchar_t, text_length);
|
|
if ((wlen = MultiByteToWideChar (private->codepage, 0,
|
|
text, text_length,
|
|
wcstr, text_length)) == 0)
|
|
{
|
|
g_warning ("gdk_text_extents: MultiByteToWideChar failed");
|
|
size.cx = 0;
|
|
size.cy = 0;
|
|
}
|
|
else
|
|
GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
|
|
g_free (wcstr);
|
|
}
|
|
else
|
|
{
|
|
GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
|
|
}
|
|
SelectObject (gdk_DC, oldfont);
|
|
/* XXX This is all quite bogus */
|
|
if (lbearing)
|
|
*lbearing = 0;
|
|
if (rbearing)
|
|
*rbearing = 0;
|
|
if (width)
|
|
*width = size.cx;
|
|
if (ascent)
|
|
*ascent = size.cy + 1;
|
|
if (descent)
|
|
*descent = font->descent + 1;
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
void
|
|
gdk_text_extents_wc (GdkFont *font,
|
|
const GdkWChar *text,
|
|
gint text_length,
|
|
gint *lbearing,
|
|
gint *rbearing,
|
|
gint *width,
|
|
gint *ascent,
|
|
gint *descent)
|
|
{
|
|
GdkFontPrivate *private;
|
|
HGDIOBJ oldfont;
|
|
SIZE size;
|
|
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;
|
|
}
|
|
|
|
private = (GdkFontPrivate*) font;
|
|
|
|
switch (font->type)
|
|
{
|
|
case GDK_FONT_FONT:
|
|
wcstr = g_new (wchar_t, text_length);
|
|
for (i = 0; i < text_length; i++)
|
|
wcstr[i] = text[i];
|
|
oldfont = SelectObject (gdk_DC, private->xfont);
|
|
GetTextExtentPoint32W (gdk_DC, wcstr, text_length, &size);
|
|
g_free (wcstr);
|
|
SelectObject (gdk_DC, oldfont);
|
|
|
|
/* XXX This is all quite bogus */
|
|
if (lbearing)
|
|
*lbearing = 0;
|
|
if (rbearing)
|
|
*rbearing = 0;
|
|
if (width)
|
|
*width = size.cx;
|
|
if (ascent)
|
|
*ascent = size.cy + 1;
|
|
if (descent)
|
|
*descent = font->descent + 1;
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
GdkFontPrivate *private;
|
|
gint width;
|
|
|
|
g_return_val_if_fail (font != NULL, -1);
|
|
g_return_val_if_fail (text != NULL, -1);
|
|
|
|
private = (GdkFontPrivate*) font;
|
|
|
|
switch (font->type)
|
|
{
|
|
case GDK_FONT_FONT:
|
|
return gdk_text_width (font, text, text_length); /* ??? */
|
|
break;
|
|
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
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)
|
|
{
|
|
GdkFontPrivate *private;
|
|
HGDIOBJ oldfont;
|
|
SIZE size;
|
|
gint height, wlen;
|
|
wchar_t *wcstr;
|
|
|
|
g_return_val_if_fail (font != NULL, -1);
|
|
g_return_val_if_fail (text != NULL, -1);
|
|
|
|
if (text_length == 0)
|
|
return 0;
|
|
|
|
private = (GdkFontPrivate*) font;
|
|
|
|
switch (font->type)
|
|
{
|
|
case GDK_FONT_FONT:
|
|
oldfont = SelectObject (gdk_DC, private->xfont);
|
|
if (private->cpinfo.MaxCharSize > 1)
|
|
{
|
|
wcstr = g_new (wchar_t, text_length);
|
|
if ((wlen = MultiByteToWideChar (private->codepage, 0,
|
|
text, text_length,
|
|
wcstr, text_length)) == 0)
|
|
{
|
|
g_warning ("gdk_text_height: MultiByteToWideChar failed "
|
|
"text = %.*s (%d)",
|
|
text_length, text, text_length);
|
|
size.cy = 0;
|
|
}
|
|
else
|
|
GetTextExtentPoint32W (gdk_DC, wcstr, wlen, &size);
|
|
g_free (wcstr);
|
|
}
|
|
else
|
|
{
|
|
GetTextExtentPoint32A (gdk_DC, text, text_length, &size);
|
|
}
|
|
SelectObject (gdk_DC, oldfont);
|
|
height = size.cy;
|
|
break;
|
|
|
|
default:
|
|
g_error ("font->type = %d", font->type);
|
|
}
|
|
return height;
|
|
}
|
|
|
|
gint
|
|
gdk_char_height (GdkFont *font,
|
|
gchar character)
|
|
{
|
|
return gdk_text_height (font, &character, 1);
|
|
}
|