/* Font backend for the Microsoft Windows API.
- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Copyright (C) 2007-2014 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "fontset.h"
#include "font.h"
#include "w32font.h"
+#ifdef WINDOWSNT
+#include "w32.h"
+#endif
/* Cleartype available on Windows XP, cleartype_natural from XP SP1.
The latter does not try to fit cleartype smoothed fonts into the
/* Font spacing symbols - defined in font.c. */
extern Lisp_Object Qc, Qp, Qm;
-static void fill_in_logfont (FRAME_PTR, LOGFONT *, Lisp_Object);
+static void fill_in_logfont (struct frame *, LOGFONT *, Lisp_Object);
static BYTE w32_antialias_type (Lisp_Object);
static Lisp_Object lispy_antialias_type (BYTE);
static Lisp_Object w32_registry (LONG, DWORD);
/* EnumFontFamiliesEx callbacks. */
-static int CALLBACK add_font_entity_to_list (ENUMLOGFONTEX *,
- NEWTEXTMETRICEX *,
- DWORD, LPARAM);
-static int CALLBACK add_one_font_entity_to_list (ENUMLOGFONTEX *,
- NEWTEXTMETRICEX *,
- DWORD, LPARAM);
-static int CALLBACK add_font_name_to_list (ENUMLOGFONTEX *,
- NEWTEXTMETRICEX *,
- DWORD, LPARAM);
+static int CALLBACK ALIGN_STACK add_font_entity_to_list (ENUMLOGFONTEX *,
+ NEWTEXTMETRICEX *,
+ DWORD, LPARAM);
+static int CALLBACK ALIGN_STACK add_one_font_entity_to_list (ENUMLOGFONTEX *,
+ NEWTEXTMETRICEX *,
+ DWORD, LPARAM);
+static int CALLBACK ALIGN_STACK add_font_name_to_list (ENUMLOGFONTEX *,
+ NEWTEXTMETRICEX *,
+ DWORD, LPARAM);
/* struct passed in as LPARAM arg to EnumFontFamiliesEx, for keeping track
of what we really want. */
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;
+#ifdef WINDOWSNT
+
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;
+static BOOL g_b_init_get_char_width_32_w;
typedef UINT (WINAPI * GetOutlineTextMetricsW_Proc) (
HDC hdc,
DWORD cbBuffer,
LPVOID lpvBuffer,
const MAT2 *lpmat2);
+typedef BOOL (WINAPI * GetCharWidth32W_Proc) (
+ HDC hdc,
+ UINT uFirstChar,
+ UINT uLastChar,
+ LPINT lpBuffer);
/* Several "wide" functions we use to support the font backends are
unavailable on Windows 9X, unless UNICOWS.DLL is installed (their
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;
+ return maybe_load_unicows_dll ();
}
/* The following 3 functions call the problematic "wide" APIs via
lpvBuffer, lpmat2);
}
+static DWORD WINAPI
+get_char_width_32_w (HDC hdc, UINT uFirstChar, UINT uLastChar, LPINT lpBuffer)
+{
+ static GetCharWidth32W_Proc s_pfn_Get_Char_Width_32W = NULL;
+ HMODULE hm_unicows = NULL;
+ if (g_b_init_get_char_width_32_w == 0)
+ {
+ g_b_init_get_char_width_32_w = 1;
+ hm_unicows = w32_load_unicows_or_gdi32 ();
+ if (hm_unicows)
+ s_pfn_Get_Char_Width_32W = (GetCharWidth32W_Proc)
+ GetProcAddress (hm_unicows, "GetCharWidth32W");
+ }
+ eassert (s_pfn_Get_Char_Width_32W != NULL);
+ return s_pfn_Get_Char_Width_32W (hdc, uFirstChar, uLastChar, lpBuffer);
+}
+
+#else /* Cygwin */
+
+/* Cygwin doesn't support Windows 9X, and links against GDI32.DLL, so
+ it can just call these functions directly. */
+#define get_outline_metrics_w(h,d,o) GetOutlineTextMetricsW(h,d,o)
+#define get_text_metrics_w(h,t) GetTextMetricsW(h,t)
+#define get_glyph_outline_w(h,uc,f,gm,b,v,m) \
+ GetGlyphOutlineW(h,uc,f,gm,b,v,m)
+#define get_char_width_32_w(h,fc,lc,b) GetCharWidth32W(h,fc,lc,b)
+
+#endif /* Cygwin */
+
static int
memq_no_quit (Lisp_Object elt, Lisp_Object list)
{
intern_font_name (char * string)
{
Lisp_Object str = DECODE_SYSTEM (build_string (string));
- int len = SCHARS (str);
+ ptrdiff_t 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);
+ return SYMBOLP (tem) ? tem : intern_driver (str, obarray, XINT (tem));
}
/* w32 implementation of get_cache for font backend.
Return a cache of font-entities on FRAME. The cache must be a
cons whose cdr part is the actual cache area. */
Lisp_Object
-w32font_get_cache (FRAME_PTR f)
+w32font_get_cache (struct frame *f)
{
- struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+ struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
return (dpyinfo->name_list_element);
}
Open a font specified by FONT_ENTITY on frame F.
If the font is scalable, open it with PIXEL_SIZE. */
static Lisp_Object
-w32font_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
+w32font_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
{
Lisp_Object font_object
= font_make_object (VECSIZE (struct w32font_info),
return font_object;
}
-/* w32 implementation of close for font_backend.
- Close FONT on frame F. */
+/* w32 implementation of close for font_backend. */
void
-w32font_close (FRAME_PTR f, struct font *font)
+w32font_close (struct font *font)
{
- int i;
struct w32font_info *w32_font = (struct w32font_info *) font;
- /* Delete the GDI font object. */
- DeleteObject (w32_font->hfont);
-
- /* Free all the cached metrics. */
- if (w32_font->cached_metrics)
+ if (w32_font->hfont)
{
- for (i = 0; i < w32_font->n_cache_blocks; i++)
- {
- xfree (w32_font->cached_metrics[i]);
- }
- xfree (w32_font->cached_metrics);
- w32_font->cached_metrics = NULL;
+ /* Delete the GDI font object. */
+ DeleteObject (w32_font->hfont);
+ w32_font->hfont = NULL;
+
+ /* Free all the cached metrics. */
+ if (w32_font->cached_metrics)
+ {
+ int i;
+
+ for (i = 0; i < w32_font->n_cache_blocks; i++)
+ xfree (w32_font->cached_metrics[i]);
+ xfree (w32_font->cached_metrics);
+ w32_font->cached_metrics = NULL;
+ }
}
}
of METRICS. The glyphs are specified by their glyph codes in
CODE (length NGLYPHS). Apparently metrics can be NULL, in this
case just return the overall width. */
-int
+void
w32font_text_extents (struct font *font, unsigned *code,
int nglyphs, struct font_metrics *metrics)
{
struct w32font_info *w32_font = (struct w32font_info *) font;
- if (metrics)
- {
- memset (metrics, 0, sizeof (struct font_metrics));
- metrics->ascent = font->ascent;
- metrics->descent = font->descent;
-
- for (i = 0; i < nglyphs; i++)
- {
- struct w32_metric_cache *char_metric;
- int block = *(code + i) / CACHE_BLOCKSIZE;
- int pos_in_block = *(code + i) % CACHE_BLOCKSIZE;
+ memset (metrics, 0, sizeof (struct font_metrics));
+ metrics->ascent = font->ascent;
+ metrics->descent = font->descent;
- if (block >= w32_font->n_cache_blocks)
- {
- if (!w32_font->cached_metrics)
- w32_font->cached_metrics
- = xmalloc ((block + 1)
- * sizeof (struct w32_metric_cache *));
- else
- w32_font->cached_metrics
- = xrealloc (w32_font->cached_metrics,
- (block + 1)
- * sizeof (struct w32_metric_cache *));
- memset (w32_font->cached_metrics + w32_font->n_cache_blocks, 0,
- ((block + 1 - w32_font->n_cache_blocks)
- * sizeof (struct w32_metric_cache *)));
- w32_font->n_cache_blocks = block + 1;
- }
+ for (i = 0; i < nglyphs; i++)
+ {
+ struct w32_metric_cache *char_metric;
+ int block = *(code + i) / CACHE_BLOCKSIZE;
+ int pos_in_block = *(code + i) % CACHE_BLOCKSIZE;
- if (!w32_font->cached_metrics[block])
- {
- w32_font->cached_metrics[block]
- = xzalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
- }
+ if (block >= w32_font->n_cache_blocks)
+ {
+ if (!w32_font->cached_metrics)
+ w32_font->cached_metrics
+ = xmalloc ((block + 1)
+ * sizeof (struct w32_metric_cache *));
+ else
+ w32_font->cached_metrics
+ = xrealloc (w32_font->cached_metrics,
+ (block + 1)
+ * sizeof (struct w32_metric_cache *));
+ memset (w32_font->cached_metrics + w32_font->n_cache_blocks, 0,
+ ((block + 1 - w32_font->n_cache_blocks)
+ * sizeof (struct w32_metric_cache *)));
+ w32_font->n_cache_blocks = block + 1;
+ }
- char_metric = w32_font->cached_metrics[block] + pos_in_block;
+ if (!w32_font->cached_metrics[block])
+ {
+ w32_font->cached_metrics[block]
+ = xzalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
+ }
- if (char_metric->status == W32METRIC_NO_ATTEMPT)
- {
- if (dc == NULL)
- {
- /* TODO: Frames can come and go, and their fonts
- outlive them. So we can't cache the frame in the
- font structure. Use selected_frame until the API
- is updated to pass in a frame. */
- f = XFRAME (selected_frame);
-
- dc = get_frame_dc (f);
- old_font = SelectObject (dc, w32_font->hfont);
- }
- compute_metrics (dc, w32_font, *(code + i), char_metric);
- }
+ char_metric = w32_font->cached_metrics[block] + pos_in_block;
- if (char_metric->status == W32METRIC_SUCCESS)
+ if (char_metric->status == W32METRIC_NO_ATTEMPT)
+ {
+ if (dc == NULL)
{
- metrics->lbearing = min (metrics->lbearing,
- metrics->width + char_metric->lbearing);
- metrics->rbearing = max (metrics->rbearing,
- metrics->width + char_metric->rbearing);
- metrics->width += char_metric->width;
+ /* TODO: Frames can come and go, and their fonts
+ outlive them. So we can't cache the frame in the
+ font structure. Use selected_frame until the API
+ is updated to pass in a frame. */
+ f = XFRAME (selected_frame);
+
+ dc = get_frame_dc (f);
+ old_font = SelectObject (dc, w32_font->hfont);
}
- else
- /* If we couldn't get metrics for a char,
- use alternative method. */
- break;
+ compute_metrics (dc, w32_font, *(code + i), char_metric);
}
- /* If we got through everything, return. */
- if (i == nglyphs)
- {
- if (dc != NULL)
- {
- /* Restore state and release DC. */
- SelectObject (dc, old_font);
- release_frame_dc (f, dc);
- }
- return metrics->width;
- }
+ if (char_metric->status == W32METRIC_SUCCESS)
+ {
+ metrics->lbearing = min (metrics->lbearing,
+ metrics->width + char_metric->lbearing);
+ metrics->rbearing = max (metrics->rbearing,
+ metrics->width + char_metric->rbearing);
+ metrics->width += char_metric->width;
+ }
+ else
+ /* If we couldn't get metrics for a char,
+ use alternative method. */
+ break;
+ }
+ /* If we got through everything, return. */
+ if (i == nglyphs)
+ {
+ if (dc != NULL)
+ {
+ /* Restore state and release DC. */
+ SelectObject (dc, old_font);
+ release_frame_dc (f, dc);
+ }
+ return;
}
/* For non-truetype fonts, GetGlyphOutlineW is not supported, so
}
/* Give our best estimate of the metrics, based on what we know. */
- if (metrics)
- {
- metrics->width = total_width - w32_font->metrics.tmOverhang;
- metrics->lbearing = 0;
- metrics->rbearing = total_width;
- }
+ metrics->width = total_width - w32_font->metrics.tmOverhang;
+ metrics->lbearing = 0;
+ metrics->rbearing = total_width;
/* Restore state and release DC. */
SelectObject (dc, old_font);
release_frame_dc (f, dc);
-
- return total_width;
}
/* w32 implementation of draw for font backend.
storing some data in FACE->extra. If successful, return 0.
Otherwise, return -1.
static int
-w32font_prepare_face (FRAME_PTR f, struct face *face);
+w32font_prepare_face (struct frame *f, struct face *face);
*/
/* w32 implementation of done_face for font backend.
Optional.
Done FACE for displaying characters by FACE->font on frame F.
static void
-w32font_done_face (FRAME_PTR f, struct face *face); */
+w32font_done_face (struct frame *f, struct face *face); */
/* w32 implementation of get_bitmap for font backend.
Optional.
static void
w32font_free_bitmap (struct font *font, struct font_bitmap *bitmap);
*/
-/* w32 implementation of get_outline for font backend.
- Optional.
- Return an outline data for glyph-code CODE of FONT. The format
- of the outline data depends on the font-driver.
-static void *
-w32font_get_outline (struct font *font, unsigned code);
- */
-/* w32 implementation of free_outline for font backend.
- Optional.
- Free OUTLINE (that is obtained by the above method).
-static void
-w32font_free_outline (struct font *font, void *outline);
- */
/* w32 implementation of anchor_point for font backend.
Optional.
Get coordinates of the INDEXth anchor point of the glyph whose
}
int
-w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
+w32font_open_internal (struct frame *f, Lisp_Object font_entity,
int pixel_size, Lisp_Object font_object)
{
int len, size;
LOGFONT logfont;
HDC dc;
HFONT hfont, old_font;
- Lisp_Object val, extra;
+ Lisp_Object val;
struct w32font_info *w32_font;
struct font * font;
OUTLINETEXTMETRICW* metrics = NULL;
font->baseline_offset = 0;
font->relative_compose = 0;
font->default_ascent = w32_font->metrics.tmAscent;
- font->font_encoder = NULL;
font->pixel_size = size;
font->driver = &w32font_driver;
- /* Use format cached during list, as the information we have access to
- here is incomplete. */
- extra = AREF (font_entity, FONT_EXTRA_INDEX);
- if (CONSP (extra))
- {
- val = assq_no_quit (QCformat, extra);
- if (CONSP (val))
- font->props[FONT_FORMAT_INDEX] = XCDR (val);
- else
- font->props[FONT_FORMAT_INDEX] = Qunknown;
- }
- else
- font->props[FONT_FORMAT_INDEX] = Qunknown;
-
- font->props[FONT_FILE_INDEX] = Qnil;
font->encoding_charset = -1;
font->repertory_charset = -1;
/* TODO: do we really want the minimum width here, which could be negative? */
/* Callback function for EnumFontFamiliesEx.
* Adds the name of a font to a Lisp list (passed in as the lParam arg). */
-static int CALLBACK
+static int CALLBACK ALIGN_STACK
add_font_name_to_list (ENUMLOGFONTEX *logical_font,
NEWTEXTMETRICEX *physical_font,
DWORD font_type, LPARAM list_object)
* 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. */
-static int CALLBACK
+static int CALLBACK ALIGN_STACK
add_font_entity_to_list (ENUMLOGFONTEX *logical_font,
NEWTEXTMETRICEX *physical_font,
DWORD font_type, LPARAM lParam)
/* Callback function for EnumFontFamiliesEx.
* Terminates the search once we have a match. */
-static int CALLBACK
+static int CALLBACK ALIGN_STACK
add_one_font_entity_to_list (ENUMLOGFONTEX *logical_font,
NEWTEXTMETRICEX *physical_font,
DWORD font_type, LPARAM lParam)
/* Fill in all the available details of LOGFONT from FONT_SPEC. */
static void
-fill_in_logfont (FRAME_PTR f, LOGFONT *logfont, Lisp_Object font_spec)
+fill_in_logfont (struct frame *f, LOGFONT *logfont, Lisp_Object font_spec)
{
Lisp_Object tmp, extra;
int dpi = FRAME_RES_Y (f);
GLYPHMETRICS gm;
MAT2 transform;
unsigned int options = GGO_METRICS;
+ INT width;
if (w32_font->glyph_idx)
options |= GGO_GLYPH_INDEX;
metrics->width = gm.gmCellIncX;
metrics->status = W32METRIC_SUCCESS;
}
+ else if (get_char_width_32_w (dc, code, code, &width) != 0)
+ {
+ metrics->lbearing = 0;
+ metrics->rbearing = width;
+ metrics->width = width;
+ metrics->status = W32METRIC_SUCCESS;
+ }
else
metrics->status = W32METRIC_FAIL;
}
in the font selection dialog. */)
(Lisp_Object frame, Lisp_Object exclude_proportional)
{
- FRAME_PTR f = decode_window_system_frame (frame);
+ struct frame *f = decode_window_system_frame (frame);
CHOOSEFONT cf;
LOGFONT lf;
TEXTMETRIC tm;
struct font_driver w32font_driver =
{
- 0, /* Qgdi */
+ LISP_INITIALLY_ZERO, /* Qgdi */
0, /* case insensitive */
w32font_get_cache,
w32font_list,
w32font_draw,
NULL, /* get_bitmap */
NULL, /* free_bitmap */
- NULL, /* get_outline */
- NULL, /* free_outline */
NULL, /* anchor_point */
NULL, /* otf_capability */
NULL, /* otf_drive */
void
globals_of_w32font (void)
{
- g_b_init_is_w9x = 0;
+#ifdef WINDOWSNT
g_b_init_get_outline_metrics_w = 0;
g_b_init_get_text_metrics_w = 0;
g_b_init_get_glyph_outline_w = 0;
+ g_b_init_get_char_width_32_w = 0;
+#endif
}