X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/657d08d30a63536174fe9ec60b7f2cb8de541eb5..017a270078be5ae39301e3205afad80d23facbbc:/src/w32font.c
diff --git a/src/w32font.c b/src/w32font.c
index f47b7a46b1..833b7cdfb2 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -1,5 +1,5 @@
-/* Font backend for the Microsoft W32 API.
- Copyright (C) 2007-2011 Free Software Foundation, Inc.
+/* Font backend for the Microsoft Windows API.
+ Copyright (C) 2007-2012 Free Software Foundation, Inc.
This file is part of GNU Emacs.
@@ -21,7 +21,6 @@ along with GNU Emacs. If not, see . */
#include
#include
#include
-#include
#include "lisp.h"
#include "w32term.h"
@@ -62,7 +61,6 @@ static Lisp_Object Qserif, Qscript, Qdecorative;
static Lisp_Object Qraster, Qoutline, Qunknown;
/* antialiasing */
-extern Lisp_Object Qnone; /* reuse from w32fns.c */
static Lisp_Object Qstandard, Qsubpixel, Qnatural;
/* languages */
@@ -75,7 +73,7 @@ static Lisp_Object Qgurmukhi, Qgujarati, Qoriya, Qtamil, Qtelugu;
static Lisp_Object Qkannada, Qmalayalam, Qsinhala, Qthai, Qlao;
static Lisp_Object Qtibetan, Qmyanmar, Qgeorgian, Qhangul, Qethiopic;
static Lisp_Object Qcherokee, Qcanadian_aboriginal, Qogham, Qrunic;
-static Lisp_Object Qkhmer, Qmongolian, Qsymbol, Qbraille, Qhan;
+static Lisp_Object Qkhmer, Qmongolian, Qbraille, Qhan;
static Lisp_Object Qideographic_description, Qcjk_misc, Qkana, Qbopomofo;
static Lisp_Object Qkanbun, Qyi, Qbyzantine_musical_symbol;
static Lisp_Object Qmusical_symbol, Qmathematical, Qcham, Qphonetic;
@@ -145,6 +143,135 @@ struct font_callback_data
style variations if the font name is not specified. */
static void list_all_matching_fonts (struct font_callback_data *);
+static BOOL g_b_init_is_w9x;
+static BOOL g_b_init_get_outline_metrics_w;
+static BOOL g_b_init_get_text_metrics_w;
+static BOOL g_b_init_get_glyph_outline_w;
+static BOOL g_b_init_get_glyph_outline_w;
+
+typedef UINT (WINAPI * GetOutlineTextMetricsW_Proc) (
+ HDC hdc,
+ UINT cbData,
+ LPOUTLINETEXTMETRICW lpotmw);
+typedef BOOL (WINAPI * GetTextMetricsW_Proc) (
+ HDC hdc,
+ LPTEXTMETRICW lptmw);
+typedef DWORD (WINAPI * GetGlyphOutlineW_Proc) (
+ HDC hdc,
+ UINT uChar,
+ UINT uFormat,
+ LPGLYPHMETRICS lpgm,
+ DWORD cbBuffer,
+ LPVOID lpvBuffer,
+ const MAT2 *lpmat2);
+
+/* Several "wide" functions we use to support the font backends are
+ unavailable on Windows 9X, unless UNICOWS.DLL is installed (their
+ versions in the default libraries are non-functional stubs). On NT
+ and later systems, these functions are in GDI32.DLL. The following
+ helper function attempts to load UNICOWS.DLL on Windows 9X, and
+ refuses to let Emacs start up if that library is not found. On NT
+ and later versions, it simply loads GDI32.DLL, which should always
+ be available. */
+static HMODULE
+w32_load_unicows_or_gdi32 (void)
+{
+ static BOOL is_9x = 0;
+ OSVERSIONINFO os_ver;
+ HMODULE ret;
+ if (g_b_init_is_w9x == 0)
+ {
+ g_b_init_is_w9x = 1;
+ ZeroMemory (&os_ver, sizeof (OSVERSIONINFO));
+ os_ver.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+ if (GetVersionEx (&os_ver))
+ is_9x = (os_ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS);
+ }
+ if (is_9x)
+ {
+ ret = LoadLibrary ("Unicows.dll");
+ if (!ret)
+ {
+ int button;
+
+ button = MessageBox (NULL,
+ "Emacs cannot load the UNICOWS.DLL library.\n"
+ "This library is essential for using Emacs\n"
+ "on this system. You need to install it.\n\n"
+ "However, you can still use Emacs by invoking\n"
+ "it with the '-nw' command-line option.\n\n"
+ "Emacs will exit when you click OK.",
+ "Emacs cannot load UNICOWS.DLL",
+ MB_ICONERROR | MB_TASKMODAL
+ | MB_SETFOREGROUND | MB_OK);
+ switch (button)
+ {
+ case IDOK:
+ default:
+ exit (1);
+ }
+ }
+ }
+ else
+ ret = LoadLibrary ("Gdi32.dll");
+ return ret;
+}
+
+/* The following 3 functions call the problematic "wide" APIs via
+ function pointers, to avoid linking against the non-standard
+ libunicows on W9X. */
+static UINT WINAPI
+get_outline_metrics_w(HDC hdc, UINT cbData, LPOUTLINETEXTMETRICW lpotmw)
+{
+ static GetOutlineTextMetricsW_Proc s_pfn_Get_Outline_Text_MetricsW = NULL;
+ HMODULE hm_unicows = NULL;
+ if (g_b_init_get_outline_metrics_w == 0)
+ {
+ g_b_init_get_outline_metrics_w = 1;
+ hm_unicows = w32_load_unicows_or_gdi32 ();
+ if (hm_unicows)
+ s_pfn_Get_Outline_Text_MetricsW = (GetOutlineTextMetricsW_Proc)
+ GetProcAddress (hm_unicows, "GetOutlineTextMetricsW");
+ }
+ eassert (s_pfn_Get_Outline_Text_MetricsW != NULL);
+ return s_pfn_Get_Outline_Text_MetricsW (hdc, cbData, lpotmw);
+}
+
+static BOOL WINAPI
+get_text_metrics_w(HDC hdc, LPTEXTMETRICW lptmw)
+{
+ static GetTextMetricsW_Proc s_pfn_Get_Text_MetricsW = NULL;
+ HMODULE hm_unicows = NULL;
+ if (g_b_init_get_text_metrics_w == 0)
+ {
+ g_b_init_get_text_metrics_w = 1;
+ hm_unicows = w32_load_unicows_or_gdi32 ();
+ if (hm_unicows)
+ s_pfn_Get_Text_MetricsW = (GetTextMetricsW_Proc)
+ GetProcAddress (hm_unicows, "GetTextMetricsW");
+ }
+ eassert (s_pfn_Get_Text_MetricsW != NULL);
+ return s_pfn_Get_Text_MetricsW (hdc, lptmw);
+}
+
+static DWORD WINAPI
+get_glyph_outline_w (HDC hdc, UINT uChar, UINT uFormat, LPGLYPHMETRICS lpgm,
+ DWORD cbBuffer, LPVOID lpvBuffer, const MAT2 *lpmat2)
+{
+ static GetGlyphOutlineW_Proc s_pfn_Get_Glyph_OutlineW = NULL;
+ HMODULE hm_unicows = NULL;
+ if (g_b_init_get_glyph_outline_w == 0)
+ {
+ g_b_init_get_glyph_outline_w = 1;
+ hm_unicows = w32_load_unicows_or_gdi32 ();
+ if (hm_unicows)
+ s_pfn_Get_Glyph_OutlineW = (GetGlyphOutlineW_Proc)
+ GetProcAddress (hm_unicows, "GetGlyphOutlineW");
+ }
+ eassert (s_pfn_Get_Glyph_OutlineW != NULL);
+ return s_pfn_Get_Glyph_OutlineW (hdc, uChar, uFormat, lpgm, cbBuffer,
+ lpvBuffer, lpmat2);
+}
static int
memq_no_quit (Lisp_Object elt, Lisp_Object list)
@@ -157,20 +284,12 @@ memq_no_quit (Lisp_Object elt, Lisp_Object list)
Lisp_Object
intern_font_name (char * string)
{
- Lisp_Object obarray, tem, str;
- int len;
-
- str = DECODE_SYSTEM (build_string (string));
- len = SCHARS (str);
-
- /* The following code is copied from the function intern (in lread.c). */
- obarray = Vobarray;
- if (!VECTORP (obarray) || ASIZE (obarray) == 0)
- obarray = check_obarray (obarray);
- tem = oblookup (obarray, SDATA (str), len, len);
- if (SYMBOLP (tem))
- return tem;
- return Fintern (str, obarray);
+ Lisp_Object str = DECODE_SYSTEM (build_string (string));
+ int len = SCHARS (str);
+ Lisp_Object obarray = check_obarray (Vobarray);
+ Lisp_Object tem = oblookup (obarray, SDATA (str), len, len);
+ /* This code is similar to intern function from lread.c. */
+ return SYMBOLP (tem) ? tem : Fintern (str, obarray);
}
/* w32 implementation of get_cache for font backend.
@@ -198,7 +317,7 @@ w32font_list (Lisp_Object frame, Lisp_Object font_spec)
/* w32 implementation of match for font backend.
Return a font entity most closely matching with FONT_SPEC on
- FRAME. The closeness is detemined by the font backend, thus
+ FRAME. The closeness is determined by the font backend, thus
`face-font-selection-order' is ignored here. */
static Lisp_Object
w32font_match (Lisp_Object frame, Lisp_Object font_spec)
@@ -330,7 +449,7 @@ w32font_has_char (Lisp_Object entity, int c)
Return a glyph code of FONT for character C (Unicode code point).
If FONT doesn't have such a glyph, return FONT_INVALID_CODE.
- For speed, the gdi backend uses unicode (Emacs calls encode_char
+ For speed, the gdi backend uses Unicode (Emacs calls encode_char
far too often for it to be efficient). But we still need to detect
which characters are not supported by the font.
*/
@@ -397,9 +516,7 @@ w32font_text_extents (struct font *font, unsigned *code,
if (!w32_font->cached_metrics[block])
{
w32_font->cached_metrics[block]
- = xmalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
- memset (w32_font->cached_metrics[block], 0,
- CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
+ = xzalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
}
char_metric = w32_font->cached_metrics[block] + pos_in_block;
@@ -488,7 +605,7 @@ w32font_text_extents (struct font *font, unsigned *code,
total_width = size.cx;
}
- /* On 95/98/ME, only some unicode functions are available, so fallback
+ /* On 95/98/ME, only some Unicode functions are available, so fallback
on doing a dummy draw to find the total width. */
if (!total_width)
{
@@ -517,9 +634,9 @@ w32font_text_extents (struct font *font, unsigned *code,
/* w32 implementation of draw for font backend.
Optional.
Draw glyphs between FROM and TO of S->char2b at (X Y) pixel
- position of frame F with S->FACE and S->GC. If WITH_BACKGROUND
- is nonzero, fill the background in advance. It is assured that
- WITH_BACKGROUND is zero when (FROM > 0 || TO < S->nchars).
+ position of frame F with S->FACE and S->GC. If WITH_BACKGROUND,
+ fill the background in advance. It is assured that WITH_BACKGROUND
+ is false when (FROM > 0 || TO < S->nchars).
TODO: Currently this assumes that the colors and fonts are already
set in the DC. This seems to be true now, but maybe only due to
@@ -529,7 +646,7 @@ w32font_text_extents (struct font *font, unsigned *code,
int
w32font_draw (struct glyph_string *s, int from, int to,
- int x, int y, int with_background)
+ int x, int y, bool with_background)
{
UINT options;
HRGN orig_clip = NULL;
@@ -654,7 +771,7 @@ w32font_free_outline (struct font *font, void *outline);
Optional.
Get coordinates of the INDEXth anchor point of the glyph whose
code is CODE. Store the coordinates in *X and *Y. Return 0 if
- the operations was successfull. Otherwise return -1.
+ the operations was successful. Otherwise return -1.
static int
w32font_anchor_point (struct font *font, unsigned code,
int index, int *x, int *y);
@@ -686,7 +803,7 @@ static int
w32font_otf_drive (struct font *font, Lisp_Object features,
Lisp_Object gstring_in, int from, int to,
Lisp_Object gstring_out, int idx,
- int alternate_subst);
+ bool alternate_subst);
*/
/* Internal implementation of w32font_list.
@@ -816,11 +933,11 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
old_font = SelectObject (dc, hfont);
/* Try getting the outline metrics (only works for truetype fonts). */
- len = GetOutlineTextMetricsW (dc, 0, NULL);
+ len = get_outline_metrics_w (dc, 0, NULL);
if (len)
{
metrics = (OUTLINETEXTMETRICW *) alloca (len);
- if (GetOutlineTextMetricsW (dc, len, metrics))
+ if (get_outline_metrics_w (dc, len, metrics))
memcpy (&w32_font->metrics, &metrics->otmTextMetrics,
sizeof (TEXTMETRICW));
else
@@ -828,7 +945,7 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
}
if (!metrics)
- GetTextMetricsW (dc, &w32_font->metrics);
+ get_text_metrics_w (dc, &w32_font->metrics);
w32_font->cached_metrics = NULL;
w32_font->n_cache_blocks = 0;
@@ -869,7 +986,6 @@ w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
font->space_width = font->average_width = w32_font->metrics.tmAveCharWidth;
font->vertical_centering = 0;
- font->encoding_type = 0;
font->baseline_offset = 0;
font->relative_compose = 0;
font->default_ascent = w32_font->metrics.tmAscent;
@@ -1021,7 +1137,7 @@ w32_enumfont_pattern_entity (Lisp_Object frame,
else
ASET (entity, FONT_SIZE_INDEX, make_number (0));
- /* Cache unicode codepoints covered by this font, as there is no other way
+ /* Cache Unicode codepoints covered by this font, as there is no other way
of getting this information easily. */
if (font_type & TRUETYPE_FONTTYPE)
{
@@ -1152,14 +1268,23 @@ font_matches_spec (DWORD type, NEWTEXTMETRICEX *font,
{
/* Only truetype fonts will have information about what
scripts they support. This probably means the user
- will have to force Emacs to use raster, postscript
- or atm fonts for non-ASCII text. */
+ will have to force Emacs to use raster, PostScript
+ or ATM fonts for non-ASCII text. */
if (type & TRUETYPE_FONTTYPE)
{
Lisp_Object support
= font_supported_scripts (&font->ntmFontSig);
if (! memq_no_quit (val, support))
return 0;
+
+ /* Avoid using non-Japanese fonts for Japanese, even
+ if they claim they are capable, due to known
+ breakage in Vista and Windows 7 fonts
+ (bug#6029). */
+ if (EQ (val, Qkana)
+ && (font->ntmTm.tmCharSet != SHIFTJIS_CHARSET
+ || !(font->ntmFontSig.fsCsb[0] & CSB_JAPANESE)))
+ return 0;
}
else
{
@@ -1263,7 +1388,7 @@ font_matches_spec (DWORD type, NEWTEXTMETRICEX *font,
currently appear in fontset.el, so it isn't worth
creating a mapping table of codepages/scripts to languages
or opening the font to see if there are any language tags
- in it that the W32 API does not expose. Fontset
+ in it that the Windows API does not expose. Fontset
spec should have a fallback, as some backends do
not recognize language at all. */
return 0;
@@ -1323,7 +1448,7 @@ check_face_name (LOGFONT *font, char *full_name)
/* Helvetica is mapped to Arial in Windows, but if a Type-1 Helvetica is
installed, we run into problems with the Uniscribe backend which tries
to avoid non-truetype fonts, and ends up mixing the Type-1 Helvetica
- with Arial's characteristics, since that attempt to use Truetype works
+ with Arial's characteristics, since that attempt to use TrueType works
some places, but not others. */
if (!xstrcasecmp (font->lfFaceName, "helvetica"))
{
@@ -1351,7 +1476,7 @@ check_face_name (LOGFONT *font, char *full_name)
/* Callback function for EnumFontFamiliesEx.
- * Checks if a font matches everything we are trying to check agaist,
+ * Checks if a font matches everything we are trying to check against,
* and if so, adds it to a list. Both the data we are checking against
* and the list to which the fonts are added are passed in via the
* lparam argument, in the form of a font_callback_data struct. */
@@ -1373,9 +1498,9 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
/* Skip non matching fonts. */
/* For uniscribe backend, consider only truetype or opentype fonts
- that have some unicode coverage. */
+ that have some Unicode coverage. */
if (match_data->opentype_only
- && ((!physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE
+ && ((!(physical_font->ntmTm.ntmFlags & NTMFLAGS_OPENTYPE)
&& !(font_type & TRUETYPE_FONTTYPE))
|| !is_unicode))
return 1;
@@ -1416,7 +1541,7 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
Lisp_Object spec_charset = AREF (match_data->orig_font_spec,
FONT_REGISTRY_INDEX);
- /* iso10646-1 fonts must contain unicode mapping tables. */
+ /* iso10646-1 fonts must contain Unicode mapping tables. */
if (EQ (spec_charset, Qiso10646_1))
{
if (!is_unicode)
@@ -1431,13 +1556,13 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
&& !(physical_font->ntmFontSig.fsUsb[0] & 0x007F001F))
return 1;
}
- /* unicode-sip fonts must contain characters in unicode plane 2.
+ /* unicode-sip fonts must contain characters in Unicode plane 2.
so look for bit 57 (surrogates) in the Unicode subranges, plus
the bits for CJK ranges that include those characters. */
else if (EQ (spec_charset, Qunicode_sip))
{
- if (!physical_font->ntmFontSig.fsUsb[1] & 0x02000000
- || !physical_font->ntmFontSig.fsUsb[1] & 0x28000000)
+ if (!(physical_font->ntmFontSig.fsUsb[1] & 0x02000000)
+ || !(physical_font->ntmFontSig.fsUsb[1] & 0x28000000))
return 1;
}
@@ -1445,10 +1570,18 @@ add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
/* If registry was specified, ensure it is reported as the same. */
if (!NILP (spec_charset))
- ASET (entity, FONT_REGISTRY_INDEX, spec_charset);
-
+ {
+ /* Avoid using non-Japanese fonts for Japanese, even if they
+ claim they are capable, due to known breakage in Vista
+ and Windows 7 fonts (bug#6029). */
+ if (logical_font->elfLogFont.lfCharSet == SHIFTJIS_CHARSET
+ && !(physical_font->ntmFontSig.fsCsb[0] & CSB_JAPANESE))
+ return 1;
+ else
+ ASET (entity, FONT_REGISTRY_INDEX, spec_charset);
+ }
/* Otherwise if using the uniscribe backend, report ANSI and DEFAULT
- fonts as unicode and skip other charsets. */
+ fonts as Unicode and skip other charsets. */
else if (match_data->opentype_only)
{
if (logical_font->elfLogFont.lfCharSet == ANSI_CHARSET
@@ -1491,7 +1624,7 @@ x_to_w32_charset (char * lpcs)
if (strncmp (lpcs, "*-#", 3) == 0)
return atoi (lpcs + 3);
- /* All Windows fonts qualify as unicode. */
+ /* All Windows fonts qualify as Unicode. */
if (!strncmp (lpcs, "iso10646", 8))
return DEFAULT_CHARSET;
@@ -1776,7 +1909,7 @@ w32_registry (LONG w32_charset, DWORD font_type)
{
char *charset;
- /* If charset is defaulted, charset is unicode or unknown, depending on
+ /* If charset is defaulted, charset is Unicode or unknown, depending on
font type. */
if (w32_charset == DEFAULT_CHARSET)
return font_type == TRUETYPE_FONTTYPE ? Qiso10646_1 : Qunknown;
@@ -1896,8 +2029,11 @@ fill_in_logfont (FRAME_PTR f, LOGFONT *logfont, Lisp_Object font_spec)
/* Font families are interned, but allow for strings also in case of
user input. */
else if (SYMBOLP (tmp))
- strncpy (logfont->lfFaceName,
- SDATA (ENCODE_SYSTEM (SYMBOL_NAME (tmp))), LF_FACESIZE);
+ {
+ strncpy (logfont->lfFaceName,
+ SDATA (ENCODE_SYSTEM (SYMBOL_NAME (tmp))), LF_FACESIZE);
+ logfont->lfFaceName[LF_FACESIZE-1] = '\0';
+ }
}
tmp = AREF (font_spec, FONT_ADSTYLE_INDEX);
@@ -1931,7 +2067,7 @@ fill_in_logfont (FRAME_PTR f, LOGFONT *logfont, Lisp_Object font_spec)
{
Lisp_Object key, val;
key = XCAR (tmp), val = XCDR (tmp);
- /* Only use QCscript if charset is not provided, or is unicode
+ /* Only use QCscript if charset is not provided, or is Unicode
and a single script is specified. This is rather crude,
and is only used to narrow down the fonts returned where
there is a definite match. Some scripts, such as latin, han,
@@ -2072,7 +2208,7 @@ font_supported_scripts (FONTSIGNATURE * sig)
so don't need to mark them separately. */
/* 1: Latin-1 supplement, 2: Latin Extended A, 3: Latin Extended B. */
SUBRANGE (4, Qphonetic);
- /* 5: Spacing and tone modifiers, 6: Combining Diacriticals. */
+ /* 5: Spacing and tone modifiers, 6: Combining Diacritical Marks. */
SUBRANGE (7, Qgreek);
SUBRANGE (8, Qcoptic);
SUBRANGE (9, Qcyrillic);
@@ -2162,7 +2298,7 @@ font_supported_scripts (FONTSIGNATURE * sig)
/* 115: Saurashtra, 116: Kayah Li, 117: Rejang. */
SUBRANGE (118, Qcham);
/* 119: Ancient symbols, 120: Phaistos Disc. */
- /* 121: Carian, Lycian, Lydian, 122: Dominos, Mah Jong tiles. */
+ /* 121: Carian, Lycian, Lydian, 122: Dominoes, Mahjong tiles. */
/* 123-127: Reserved. */
/* There isn't really a main symbol range, so include symbol if any
@@ -2306,7 +2442,7 @@ compute_metrics (HDC dc, struct w32font_info *w32_font, unsigned int code,
transform.eM11.value = 1;
transform.eM22.value = 1;
- if (GetGlyphOutlineW (dc, code, options, &gm, 0, NULL, &transform)
+ if (get_glyph_outline_w (dc, code, options, &gm, 0, NULL, &transform)
!= GDI_ERROR)
{
metrics->lbearing = gm.gmptGlyphOrigin.x;
@@ -2492,7 +2628,6 @@ syms_of_w32font (void)
DEFSYM (Qrunic, "runic");
DEFSYM (Qkhmer, "khmer");
DEFSYM (Qmongolian, "mongolian");
- DEFSYM (Qsymbol, "symbol");
DEFSYM (Qbraille, "braille");
DEFSYM (Qhan, "han");
DEFSYM (Qideographic_description, "ideographic-description");
@@ -2581,3 +2716,12 @@ versions of Windows) characters. */);
w32font_driver.type = Qgdi;
register_font_driver (&w32font_driver, NULL);
}
+
+void
+globals_of_w32font (void)
+{
+ g_b_init_is_w9x = 0;
+ g_b_init_get_outline_metrics_w = 0;
+ g_b_init_get_text_metrics_w = 0;
+ g_b_init_get_glyph_outline_w = 0;
+}