w32font.c 85 KB
Newer Older
Jason Rumney's avatar
Jason Rumney committed
1
/* Font backend for the Microsoft W32 API.
2
   Copyright (C) 2007-2012 Free Software Foundation, Inc.
Jason Rumney's avatar
Jason Rumney committed
3 4 5

This file is part of GNU Emacs.

6
GNU Emacs is free software: you can redistribute it and/or modify
Jason Rumney's avatar
Jason Rumney committed
7
it under the terms of the GNU General Public License as published by
8 9
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jason Rumney's avatar
Jason Rumney committed
10 11 12 13 14 15 16

GNU Emacs 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 General Public License for more details.

You should have received a copy of the GNU General Public License
17
along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
Jason Rumney's avatar
Jason Rumney committed
18 19 20

#include <config.h>
#include <windows.h>
Juanma Barranquero's avatar
Juanma Barranquero committed
21
#include <math.h>
Juanma Barranquero's avatar
Juanma Barranquero committed
22
#include <ctype.h>
23
#include <commdlg.h>
24
#include <setjmp.h>
Jason Rumney's avatar
Jason Rumney committed
25 26 27 28 29 30 31

#include "lisp.h"
#include "w32term.h"
#include "frame.h"
#include "dispextern.h"
#include "character.h"
#include "charset.h"
32
#include "coding.h"
Jason Rumney's avatar
Jason Rumney committed
33 34
#include "fontset.h"
#include "font.h"
Jason Rumney's avatar
Jason Rumney committed
35
#include "w32font.h"
Jason Rumney's avatar
Jason Rumney committed
36

37 38 39 40 41 42 43 44 45 46 47
/* Cleartype available on Windows XP, cleartype_natural from XP SP1.
   The latter does not try to fit cleartype smoothed fonts into the
   same bounding box as the non-antialiased version of the font.
 */
#ifndef CLEARTYPE_QUALITY
#define CLEARTYPE_QUALITY 5
#endif
#ifndef CLEARTYPE_NATURAL_QUALITY
#define CLEARTYPE_NATURAL_QUALITY 6
#endif

48 49 50 51 52 53 54 55 56
/* VIETNAMESE_CHARSET and JOHAB_CHARSET are not defined in some versions
   of MSVC headers.  */
#ifndef VIETNAMESE_CHARSET
#define VIETNAMESE_CHARSET 163
#endif
#ifndef JOHAB_CHARSET
#define JOHAB_CHARSET 130
#endif

57
Lisp_Object Qgdi;
58 59
Lisp_Object Quniscribe;
static Lisp_Object QCformat;
60 61 62
static Lisp_Object Qmonospace, Qsansserif, Qmono, Qsans, Qsans_serif;
static Lisp_Object Qserif, Qscript, Qdecorative;
static Lisp_Object Qraster, Qoutline, Qunknown;
63

64 65 66 67
/* antialiasing  */
extern Lisp_Object Qnone; /* reuse from w32fns.c  */
static Lisp_Object Qstandard, Qsubpixel, Qnatural;

Jason Rumney's avatar
Jason Rumney committed
68
/* languages */
69
static Lisp_Object Qzh;
Jason Rumney's avatar
Jason Rumney committed
70

71
/* scripts */
Juanma Barranquero's avatar
Juanma Barranquero committed
72
static Lisp_Object Qgreek, Qcoptic, Qcyrillic, Qarmenian, Qhebrew;
73 74 75 76 77 78 79 80
static Lisp_Object Qarabic, Qsyriac, Qnko, Qthaana, Qdevanagari, Qbengali;
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 Qideographic_description, Qcjk_misc, Qkana, Qbopomofo;
static Lisp_Object Qkanbun, Qyi, Qbyzantine_musical_symbol;
Jason Rumney's avatar
Jason Rumney committed
81
static Lisp_Object Qmusical_symbol, Qmathematical, Qcham, Qphonetic;
82 83 84 85 86 87
/* Not defined in characters.el, but referenced in fontset.el.  */
static Lisp_Object Qbalinese, Qbuginese, Qbuhid, Qcuneiform, Qcypriot;
static Lisp_Object Qdeseret, Qglagolitic, Qgothic, Qhanunoo, Qkharoshthi;
static Lisp_Object Qlimbu, Qlinear_b, Qold_italic, Qold_persian, Qosmanya;
static Lisp_Object Qphags_pa, Qphoenician, Qshavian, Qsyloti_nagri;
static Lisp_Object Qtagalog, Qtagbanwa, Qtai_le, Qtifinagh, Qugaritic;
88

89 90 91 92 93 94 95 96 97 98 99
/* W32 charsets: for use in Vw32_charset_info_alist.  */
static Lisp_Object Qw32_charset_ansi, Qw32_charset_default;
static Lisp_Object Qw32_charset_symbol, Qw32_charset_shiftjis;
static Lisp_Object Qw32_charset_hangeul, Qw32_charset_gb2312;
static Lisp_Object Qw32_charset_chinesebig5, Qw32_charset_oem;
static Lisp_Object Qw32_charset_easteurope, Qw32_charset_turkish;
static Lisp_Object Qw32_charset_baltic, Qw32_charset_russian;
static Lisp_Object Qw32_charset_arabic, Qw32_charset_greek;
static Lisp_Object Qw32_charset_hebrew, Qw32_charset_vietnamese;
static Lisp_Object Qw32_charset_thai, Qw32_charset_johab, Qw32_charset_mac;

100 101
/* Font spacing symbols - defined in font.c.  */
extern Lisp_Object Qc, Qp, Qm;
Jason Rumney's avatar
Jason Rumney committed
102

103
static void fill_in_logfont (FRAME_PTR, LOGFONT *, Lisp_Object);
Jason Rumney's avatar
Jason Rumney committed
104

105 106
static BYTE w32_antialias_type (Lisp_Object);
static Lisp_Object lispy_antialias_type (BYTE);
107

108 109 110 111
static Lisp_Object font_supported_scripts (FONTSIGNATURE *);
static int w32font_full_name (LOGFONT *, Lisp_Object, int, char *, int);
static void compute_metrics (HDC, struct w32font_info *, unsigned int,
                             struct w32_metric_cache *);
Jason Rumney's avatar
Jason Rumney committed
112

113
static Lisp_Object w32_registry (LONG, DWORD);
Jason Rumney's avatar
Jason Rumney committed
114 115

/* EnumFontFamiliesEx callbacks.  */
116 117 118 119
static int CALLBACK add_font_entity_to_list (ENUMLOGFONTEX *,
                                             NEWTEXTMETRICEX *,
                                             DWORD, LPARAM);
static int CALLBACK add_one_font_entity_to_list (ENUMLOGFONTEX *,
Jason Rumney's avatar
Jason Rumney committed
120
                                                 NEWTEXTMETRICEX *,
121 122 123 124
                                                 DWORD, LPARAM);
static int CALLBACK add_font_name_to_list (ENUMLOGFONTEX *,
                                           NEWTEXTMETRICEX *,
                                           DWORD, LPARAM);
Jason Rumney's avatar
Jason Rumney committed
125

126 127 128 129 130 131 132 133 134 135 136 137 138 139
/* struct passed in as LPARAM arg to EnumFontFamiliesEx, for keeping track
   of what we really want.  */
struct font_callback_data
{
  /* The logfont we are matching against. EnumFontFamiliesEx only matches
     face name and charset, so we need to manually match everything else
     in the callback function.  */
  LOGFONT pattern;
  /* The original font spec or entity.  */
  Lisp_Object orig_font_spec;
  /* The frame the font is being loaded on.  */
  Lisp_Object frame;
  /* The list to add matches to.  */
  Lisp_Object list;
Jason Rumney's avatar
Jason Rumney committed
140 141
  /* Whether to match only opentype fonts.  */
  int opentype_only;
142 143 144 145
};

/* Handles the problem that EnumFontFamiliesEx will not return all
   style variations if the font name is not specified.  */
146
static void list_all_matching_fonts (struct font_callback_data *);
147

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
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");
219
  return ret;
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
}

/* 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");
    }
  if (s_pfn_Get_Outline_Text_MetricsW == NULL)
    abort ();	/* cannot happen */
  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");
    }
  if (s_pfn_Get_Text_MetricsW == NULL)
    abort ();	/* cannot happen */
  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");
    }
  if (s_pfn_Get_Glyph_OutlineW == NULL)
    abort ();	/* cannot happen */
  return s_pfn_Get_Glyph_OutlineW (hdc, uChar, uFormat, lpgm, cbBuffer,
				   lpvBuffer, lpmat2);
}
Jason Rumney's avatar
Jason Rumney committed
280 281

static int
282
memq_no_quit (Lisp_Object elt, Lisp_Object list)
Jason Rumney's avatar
Jason Rumney committed
283 284 285 286 287 288
{
  while (CONSP (list) && ! EQ (XCAR (list), elt))
    list = XCDR (list);
  return (CONSP (list));
}

289
Lisp_Object
290
intern_font_name (char * string)
291
{
292 293 294 295 296 297
  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);
298 299
}

Jason Rumney's avatar
Jason Rumney committed
300 301 302
/* 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.  */
Jason Rumney's avatar
Jason Rumney committed
303
Lisp_Object
304
w32font_get_cache (FRAME_PTR f)
Jason Rumney's avatar
Jason Rumney committed
305
{
306
  struct w32_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Jason Rumney's avatar
Jason Rumney committed
307 308 309 310 311 312 313 314

  return (dpyinfo->name_list_element);
}

/* w32 implementation of list for font backend.
   List fonts exactly matching with FONT_SPEC on FRAME.  The value
   is a vector of font-entities.  This is the sole API that
   allocates font-entities.  */
315
static Lisp_Object
316
w32font_list (Lisp_Object frame, Lisp_Object font_spec)
Jason Rumney's avatar
Jason Rumney committed
317
{
318
  Lisp_Object fonts = w32font_list_internal (frame, font_spec, 0);
319
  FONT_ADD_LOG ("w32font-list", font_spec, fonts);
320
  return fonts;
Jason Rumney's avatar
Jason Rumney committed
321 322 323 324
}

/* w32 implementation of match for font backend.
   Return a font entity most closely matching with FONT_SPEC on
Paul Eggert's avatar
Paul Eggert committed
325
   FRAME.  The closeness is determined by the font backend, thus
Jason Rumney's avatar
Jason Rumney committed
326
   `face-font-selection-order' is ignored here.  */
327
static Lisp_Object
328
w32font_match (Lisp_Object frame, Lisp_Object font_spec)
Jason Rumney's avatar
Jason Rumney committed
329
{
330
  Lisp_Object entity = w32font_match_internal (frame, font_spec, 0);
331
  FONT_ADD_LOG ("w32font-match", font_spec, entity);
332
  return entity;
Jason Rumney's avatar
Jason Rumney committed
333 334 335 336 337
}

/* w32 implementation of list_family for font backend.
   List available families.  The value is a list of family names
   (symbols).  */
338
static Lisp_Object
339
w32font_list_family (Lisp_Object frame)
Jason Rumney's avatar
Jason Rumney committed
340 341 342 343 344 345
{
  Lisp_Object list = Qnil;
  LOGFONT font_match_pattern;
  HDC dc;
  FRAME_PTR f = XFRAME (frame);

346
  memset (&font_match_pattern, 0, sizeof (font_match_pattern));
347
  font_match_pattern.lfCharSet = DEFAULT_CHARSET;
Jason Rumney's avatar
Jason Rumney committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361

  dc = get_frame_dc (f);

  EnumFontFamiliesEx (dc, &font_match_pattern,
                      (FONTENUMPROC) add_font_name_to_list,
                      (LPARAM) &list, 0);
  release_frame_dc (f, dc);

  return list;
}

/* w32 implementation of open for font backend.
   Open a font specified by FONT_ENTITY on frame F.
   If the font is scalable, open it with PIXEL_SIZE.  */
362
static Lisp_Object
363
w32font_open (FRAME_PTR f, Lisp_Object font_entity, int pixel_size)
Jason Rumney's avatar
Jason Rumney committed
364
{
365 366 367 368 369
  Lisp_Object font_object
    = font_make_object (VECSIZE (struct w32font_info),
                        font_entity, pixel_size);
  struct w32font_info *w32_font
    = (struct w32font_info *) XFONT_OBJECT (font_object);
Jason Rumney's avatar
Jason Rumney committed
370

371
  ASET (font_object, FONT_TYPE_INDEX, Qgdi);
Jason Rumney's avatar
Jason Rumney committed
372

373
  if (!w32font_open_internal (f, font_entity, pixel_size, font_object))
Jason Rumney's avatar
Jason Rumney committed
374
    {
375
      return Qnil;
Jason Rumney's avatar
Jason Rumney committed
376 377
    }

378 379 380
  /* GDI backend does not use glyph indices.  */
  w32_font->glyph_idx = 0;

381
  return font_object;
Jason Rumney's avatar
Jason Rumney committed
382 383 384 385
}

/* w32 implementation of close for font_backend.
   Close FONT on frame F.  */
Jason Rumney's avatar
Jason Rumney committed
386
void
387
w32font_close (FRAME_PTR f, struct font *font)
Jason Rumney's avatar
Jason Rumney committed
388
{
389
  int i;
390
  struct w32font_info *w32_font = (struct w32font_info *) font;
391 392

  /* Delete the GDI font object.  */
393
  DeleteObject (w32_font->hfont);
394 395 396 397 398 399

  /* Free all the cached metrics.  */
  if (w32_font->cached_metrics)
    {
      for (i = 0; i < w32_font->n_cache_blocks; i++)
        {
400
          xfree (w32_font->cached_metrics[i]);
401 402 403 404
        }
      xfree (w32_font->cached_metrics);
      w32_font->cached_metrics = NULL;
    }
Jason Rumney's avatar
Jason Rumney committed
405 406 407 408 409 410 411
}

/* w32 implementation of has_char for font backend.
   Optional.
   If FONT_ENTITY has a glyph for character C (Unicode code point),
   return 1.  If not, return 0.  If a font must be opened to check
   it, return -1.  */
Jason Rumney's avatar
Jason Rumney committed
412
int
413
w32font_has_char (Lisp_Object entity, int c)
Jason Rumney's avatar
Jason Rumney committed
414
{
415 416 417 418 419 420
  /* We can't be certain about which characters a font will support until
     we open it.  Checking the scripts that the font supports turns out
     to not be reliable.  */
  return -1;

#if 0
421
  Lisp_Object supported_scripts, extra, script;
Jason Rumney's avatar
Jason Rumney committed
422 423
  DWORD mask;

424 425 426 427
  extra = AREF (entity, FONT_EXTRA_INDEX);
  if (!CONSP (extra))
    return -1;

428
  supported_scripts = assq_no_quit (QCscript, extra);
429 430
  /* If font doesn't claim to support any scripts, then we can't be certain
     until we open it.  */
431
  if (!CONSP (supported_scripts))
Jason Rumney's avatar
Jason Rumney committed
432 433
    return -1;

434
  supported_scripts = XCDR (supported_scripts);
Jason Rumney's avatar
Jason Rumney committed
435

436
  script = CHAR_TABLE_REF (Vchar_script_table, c);
Jason Rumney's avatar
Jason Rumney committed
437

438 439 440 441 442 443 444 445
  /* If we don't know what script the character is from, then we can't be
     certain until we open it.  Also if the font claims support for the script
     the character is from, it may only have partial coverage, so we still
     can't be certain until we open the font.  */
  if (NILP (script) || memq_no_quit (script, supported_scripts))
    return -1;

  /* Font reports what scripts it supports, and none of them are the script
446 447 448 449 450
     the character is from. But we still can't be certain, as some fonts
     will contain some/most/all of the characters in that script without
     claiming support for it.  */
  return -1;
#endif
Jason Rumney's avatar
Jason Rumney committed
451 452 453
}

/* w32 implementation of encode_char for font backend.
454
   Return a glyph code of FONT for character C (Unicode code point).
455 456
   If FONT doesn't have such a glyph, return FONT_INVALID_CODE.

Juanma Barranquero's avatar
Juanma Barranquero committed
457
   For speed, the gdi backend uses Unicode (Emacs calls encode_char
458 459 460
   far too often for it to be efficient). But we still need to detect
   which characters are not supported by the font.
  */
461
static unsigned
462
w32font_encode_char (struct font *font, int c)
Jason Rumney's avatar
Jason Rumney committed
463
{
464
  struct w32font_info * w32_font = (struct w32font_info *)font;
465

466 467 468
  if (c < w32_font->metrics.tmFirstChar
      || c > w32_font->metrics.tmLastChar)
    return FONT_INVALID_CODE;
469
  else
470
    return c;
Jason Rumney's avatar
Jason Rumney committed
471 472 473 474 475
}

/* w32 implementation of text_extents for font backend.
   Perform the size computation of glyphs of FONT and fillin members
   of METRICS.  The glyphs are specified by their glyph codes in
476
   CODE (length NGLYPHS).  Apparently metrics can be NULL, in this
Jason Rumney's avatar
Jason Rumney committed
477
   case just return the overall width.  */
Jason Rumney's avatar
Jason Rumney committed
478
int
479 480
w32font_text_extents (struct font *font, unsigned *code,
		      int nglyphs, struct font_metrics *metrics)
Jason Rumney's avatar
Jason Rumney committed
481 482
{
  int i;
483 484
  HFONT old_font = NULL;
  HDC dc = NULL;
Jason Rumney's avatar
Jason Rumney committed
485
  struct frame * f;
Jason Rumney's avatar
Jason Rumney committed
486
  int total_width = 0;
487
  WORD *wcode;
488
  SIZE size;
Jason Rumney's avatar
Jason Rumney committed
489

490 491
  struct w32font_info *w32_font = (struct w32font_info *) font;

Jason Rumney's avatar
Jason Rumney committed
492 493
  if (metrics)
    {
494
      memset (metrics, 0, sizeof (struct font_metrics));
495 496
      metrics->ascent = font->ascent;
      metrics->descent = font->descent;
Jason Rumney's avatar
Jason Rumney committed
497 498 499

      for (i = 0; i < nglyphs; i++)
        {
Jason Rumney's avatar
Jason Rumney committed
500 501 502 503 504 505 506 507 508
	  struct w32_metric_cache *char_metric;
	  int block = *(code + i) / CACHE_BLOCKSIZE;
	  int pos_in_block = *(code + i) % CACHE_BLOCKSIZE;

	  if (block >= w32_font->n_cache_blocks)
	    {
	      if (!w32_font->cached_metrics)
		w32_font->cached_metrics
		  = xmalloc ((block + 1)
509
			     * sizeof (struct w32_metric_cache *));
Jason Rumney's avatar
Jason Rumney committed
510 511 512 513
	      else
		w32_font->cached_metrics
		  = xrealloc (w32_font->cached_metrics,
			      (block + 1)
514
			      * sizeof (struct w32_metric_cache *));
515 516 517
	      memset (w32_font->cached_metrics + w32_font->n_cache_blocks, 0,
		      ((block + 1 - w32_font->n_cache_blocks)
		       * sizeof (struct w32_metric_cache *)));
Jason Rumney's avatar
Jason Rumney committed
518 519 520 521 522 523
	      w32_font->n_cache_blocks = block + 1;
	    }

	  if (!w32_font->cached_metrics[block])
	    {
	      w32_font->cached_metrics[block]
Dmitry Antipov's avatar
Dmitry Antipov committed
524
		= xzalloc (CACHE_BLOCKSIZE * sizeof (struct w32_metric_cache));
Jason Rumney's avatar
Jason Rumney committed
525 526 527 528 529 530 531 532 533 534 535 536 537
	    }

	  char_metric = w32_font->cached_metrics[block] + pos_in_block;

	  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);
538

539
                  dc = get_frame_dc (f);
540
                  old_font = SelectObject (dc, w32_font->hfont);
Jason Rumney's avatar
Jason Rumney committed
541 542 543
		}
	      compute_metrics (dc, w32_font, *(code + i), char_metric);
	    }
544

Jason Rumney's avatar
Jason Rumney committed
545 546 547 548 549 550 551 552 553 554 555 556 557
	  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;
	}
558 559 560
      /* If we got through everything, return.  */
      if (i == nglyphs)
        {
561 562 563 564 565 566
          if (dc != NULL)
            {
              /* Restore state and release DC.  */
              SelectObject (dc, old_font);
              release_frame_dc (f, dc);
            }
567 568 569

          return metrics->width;
        }
Jason Rumney's avatar
Jason Rumney committed
570
    }
571

572 573 574
  /* For non-truetype fonts, GetGlyphOutlineW is not supported, so
     fallback on other methods that will at least give some of the metric
     information.  */
575

576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
  /* Make array big enough to hold surrogates.  */
  wcode = alloca (nglyphs * sizeof (WORD) * 2);
  for (i = 0; i < nglyphs; i++)
    {
      if (code[i] < 0x10000)
        wcode[i] = code[i];
      else
        {
          DWORD surrogate = code[i] - 0x10000;

          /* High surrogate: U+D800 - U+DBFF.  */
          wcode[i++] = 0xD800 + ((surrogate >> 10) & 0x03FF);
          /* Low surrogate: U+DC00 - U+DFFF.  */
          wcode[i] = 0xDC00 + (surrogate & 0x03FF);
          /* An extra glyph. wcode is already double the size of code to
             cope with this.  */
          nglyphs++;
        }
    }

596 597
  if (dc == NULL)
    {
Jason Rumney's avatar
Jason Rumney committed
598 599 600 601 602 603
      /* 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);

604
      dc = get_frame_dc (f);
605
      old_font = SelectObject (dc, w32_font->hfont);
606 607
    }

608
  if (GetTextExtentPoint32W (dc, wcode, nglyphs, &size))
Jason Rumney's avatar
Jason Rumney committed
609
    {
610
      total_width = size.cx;
Jason Rumney's avatar
Jason Rumney committed
611 612
    }

Juanma Barranquero's avatar
Juanma Barranquero committed
613
  /* On 95/98/ME, only some Unicode functions are available, so fallback
614
     on doing a dummy draw to find the total width.  */
615
  if (!total_width)
Jason Rumney's avatar
Jason Rumney committed
616 617
    {
      RECT rect;
618
      rect.top = 0; rect.bottom = font->height; rect.left = 0; rect.right = 1;
Jason Rumney's avatar
Jason Rumney committed
619 620 621 622
      DrawTextW (dc, wcode, nglyphs, &rect,
                 DT_CALCRECT | DT_NOPREFIX | DT_SINGLELINE);
      total_width = rect.right;
    }
623

624
  /* Give our best estimate of the metrics, based on what we know.  */
625 626
  if (metrics)
    {
627
      metrics->width = total_width - w32_font->metrics.tmOverhang;
628
      metrics->lbearing = 0;
629
      metrics->rbearing = total_width;
630 631
    }

Jason Rumney's avatar
Jason Rumney committed
632 633
  /* Restore state and release DC.  */
  SelectObject (dc, old_font);
Jason Rumney's avatar
Jason Rumney committed
634
  release_frame_dc (f, dc);
Jason Rumney's avatar
Jason Rumney committed
635 636 637 638 639 640 641 642 643

  return total_width;
}

/* 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
644 645 646 647 648 649 650 651
   WITH_BACKGROUND is zero 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
   the old font code setting it up. It may be safer to resolve faces
   and fonts in here and set them explicitly
*/

Jason Rumney's avatar
Jason Rumney committed
652
int
653 654
w32font_draw (struct glyph_string *s, int from, int to,
	      int x, int y, int with_background)
Jason Rumney's avatar
Jason Rumney committed
655
{
656
  UINT options;
657
  HRGN orig_clip = NULL;
658
  int len = to - from;
659
  struct w32font_info *w32font = (struct w32font_info *) s->font;
660 661

  options = w32font->glyph_idx;
662 663 664 665 666

  if (s->num_clips > 0)
    {
      HRGN new_clip = CreateRectRgnIndirect (s->clip);

667 668
      /* Save clip region for later restoration.  */
      orig_clip = CreateRectRgn (0, 0, 0, 0);
669
      if (!GetClipRgn (s->hdc, orig_clip))
670 671 672 673 674
	{
	  DeleteObject (orig_clip);
	  orig_clip = NULL;
	}

675 676 677 678 679 680 681 682 683 684 685
      if (s->num_clips > 1)
        {
          HRGN clip2 = CreateRectRgnIndirect (s->clip + 1);

          CombineRgn (new_clip, new_clip, clip2, RGN_OR);
          DeleteObject (clip2);
        }

      SelectClipRgn (s->hdc, new_clip);
      DeleteObject (new_clip);
    }
Jason Rumney's avatar
Jason Rumney committed
686

687 688 689
  /* Using OPAQUE background mode can clear more background than expected
     when Cleartype is used.  Draw the background manually to avoid this.  */
  SetBkMode (s->hdc, TRANSPARENT);
Jason Rumney's avatar
Jason Rumney committed
690 691
  if (with_background)
    {
692 693
      HBRUSH brush;
      RECT rect;
694
      struct font *font = s->font;
695 696 697

      brush = CreateSolidBrush (s->gc->background);
      rect.left = x;
698
      rect.top = y - font->ascent;
699
      rect.right = x + s->width;
700
      rect.bottom = y + font->descent;
701
      FillRect (s->hdc, &rect, brush);
702
      DeleteObject (brush);
Jason Rumney's avatar
Jason Rumney committed
703
    }
704

705 706
  if (s->padding_p)
    {
707
      int i;
708 709 710

      for (i = 0; i < len; i++)
	ExtTextOutW (s->hdc, x + i, y, options, NULL,
711
		     s->char2b + from + i, 1, NULL);
712 713
    }
  else
714
    ExtTextOutW (s->hdc, x, y, options, NULL, s->char2b + from, len, NULL);
715 716 717

  /* Restore clip region.  */
  if (s->num_clips > 0)
718 719 720 721
    SelectClipRgn (s->hdc, orig_clip);

  if (orig_clip)
    DeleteObject (orig_clip);
722 723

  return len;
Jason Rumney's avatar
Jason Rumney committed
724 725 726 727 728
}

/* w32 implementation of free_entity for font backend.
   Optional (if FONT_EXTRA_INDEX is not Lisp_Save_Value).
   Free FONT_EXTRA_INDEX field of FONT_ENTITY.
729 730
static void
w32font_free_entity (Lisp_Object entity);
Jason Rumney's avatar
Jason Rumney committed
731 732 733 734 735 736 737
  */

/* w32 implementation of prepare_face for font backend.
   Optional (if FACE->extra is not used).
   Prepare FACE for displaying characters by FONT on frame F by
   storing some data in FACE->extra.  If successful, return 0.
   Otherwise, return -1.
738 739
static int
w32font_prepare_face (FRAME_PTR f, struct face *face);
Jason Rumney's avatar
Jason Rumney committed
740 741 742 743
  */
/* w32 implementation of done_face for font backend.
   Optional.
   Done FACE for displaying characters by FACE->font on frame F.
744 745
static void
w32font_done_face (FRAME_PTR f, struct face *face);  */
Jason Rumney's avatar
Jason Rumney committed
746 747 748 749

/* w32 implementation of get_bitmap for font backend.
   Optional.
   Store bitmap data for glyph-code CODE of FONT in BITMAP.  It is
750
   intended that this method is called from the other font-driver
Jason Rumney's avatar
Jason Rumney committed
751
   for actual drawing.
752 753 754
static int
w32font_get_bitmap (struct font *font, unsigned code,
                    struct font_bitmap *bitmap, int bits_per_pixel);
Jason Rumney's avatar
Jason Rumney committed
755 756 757 758
  */
/* w32 implementation of free_bitmap for font backend.
   Optional.
   Free bitmap data in BITMAP.
759 760
static void
w32font_free_bitmap (struct font *font, struct font_bitmap *bitmap);
Jason Rumney's avatar
Jason Rumney committed
761 762 763 764 765
  */
/* 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.
766 767
static void *
w32font_get_outline (struct font *font, unsigned code);
Jason Rumney's avatar
Jason Rumney committed
768 769 770 771
  */
/* w32 implementation of free_outline for font backend.
   Optional.
   Free OUTLINE (that is obtained by the above method).
772 773
static void
w32font_free_outline (struct font *font, void *outline);
Jason Rumney's avatar
Jason Rumney committed
774 775 776 777 778
  */
/* w32 implementation of anchor_point for font backend.
   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
Paul Eggert's avatar
Paul Eggert committed
779
   the operations was successful.  Otherwise return -1.
780 781
static int
w32font_anchor_point (struct font *font, unsigned code,
Jason Rumney's avatar
Jason Rumney committed
782 783 784 785 786 787
                                 int index, int *x, int *y);
  */
/* w32 implementation of otf_capability for font backend.
   Optional.
   Return a list describing which scripts/languages FONT
   supports by which GSUB/GPOS features of OpenType tables.
788 789
static Lisp_Object
w32font_otf_capability (struct font *font);
Jason Rumney's avatar
Jason Rumney committed
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806
  */
/* w32 implementation of otf_drive for font backend.
   Optional.
   Apply FONT's OTF-FEATURES to the glyph string.

   FEATURES specifies which OTF features to apply in this format:
      (SCRIPT LANGSYS GSUB-FEATURE GPOS-FEATURE)
   See the documentation of `font-drive-otf' for the detail.

   This method applies the specified features to the codes in the
   elements of GSTRING-IN (between FROMth and TOth).  The output
   codes are stored in GSTRING-OUT at the IDXth element and the
   following elements.

   Return the number of output codes.  If none of the features are
   applicable to the input data, return 0.  If GSTRING-OUT is too
   short, return -1.
807 808 809 810 811
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);
Jason Rumney's avatar
Jason Rumney committed
812 813
  */

Jason Rumney's avatar
Jason Rumney committed
814 815 816 817
/* Internal implementation of w32font_list.
   Additional parameter opentype_only restricts the returned fonts to
   opentype fonts, which can be used with the Uniscribe backend.  */
Lisp_Object
818
w32font_list_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_only)
Jason Rumney's avatar
Jason Rumney committed
819 820 821 822 823 824 825 826 827
{
  struct font_callback_data match_data;
  HDC dc;
  FRAME_PTR f = XFRAME (frame);

  match_data.orig_font_spec = font_spec;
  match_data.list = Qnil;
  match_data.frame = frame;

828
  memset (&match_data.pattern, 0, sizeof (LOGFONT));
Jason Rumney's avatar
Jason Rumney committed
829 830
  fill_in_logfont (f, &match_data.pattern, font_spec);

831 832 833 834 835 836 837 838 839 840 841 842 843
  /* If the charset is unrecognized, then we won't find a font, so don't
     waste time looking for one.  */
  if (match_data.pattern.lfCharSet == DEFAULT_CHARSET)
    {
      Lisp_Object spec_charset = AREF (font_spec, FONT_REGISTRY_INDEX);
      if (!NILP (spec_charset)
	  && !EQ (spec_charset, Qiso10646_1)
	  && !EQ (spec_charset, Qunicode_bmp)
	  && !EQ (spec_charset, Qunicode_sip)
	  && !EQ (spec_charset, Qunknown))
	return Qnil;
    }

Jason Rumney's avatar
Jason Rumney committed
844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
  match_data.opentype_only = opentype_only;
  if (opentype_only)
    match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;

  if (match_data.pattern.lfFaceName[0] == '\0')
    {
      /* EnumFontFamiliesEx does not take other fields into account if
         font name is blank, so need to use two passes.  */
      list_all_matching_fonts (&match_data);
    }
  else
    {
      dc = get_frame_dc (f);

      EnumFontFamiliesEx (dc, &match_data.pattern,
                          (FONTENUMPROC) add_font_entity_to_list,
                          (LPARAM) &match_data, 0);
      release_frame_dc (f, dc);
    }

864
  return match_data.list;
Jason Rumney's avatar
Jason Rumney committed
865 866 867 868 869 870
}

/* Internal implementation of w32font_match.
   Additional parameter opentype_only restricts the returned fonts to
   opentype fonts, which can be used with the Uniscribe backend.  */
Lisp_Object
871
w32font_match_internal (Lisp_Object frame, Lisp_Object font_spec, int opentype_only)
Jason Rumney's avatar
Jason Rumney committed
872 873 874 875 876 877 878 879 880
{
  struct font_callback_data match_data;
  HDC dc;
  FRAME_PTR f = XFRAME (frame);

  match_data.orig_font_spec = font_spec;
  match_data.frame = frame;
  match_data.list = Qnil;

881
  memset (&match_data.pattern, 0, sizeof (LOGFONT));
Jason Rumney's avatar
Jason Rumney committed
882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
  fill_in_logfont (f, &match_data.pattern, font_spec);

  match_data.opentype_only = opentype_only;
  if (opentype_only)
    match_data.pattern.lfOutPrecision = OUT_OUTLINE_PRECIS;

  dc = get_frame_dc (f);

  EnumFontFamiliesEx (dc, &match_data.pattern,
                      (FONTENUMPROC) add_one_font_entity_to_list,
                      (LPARAM) &match_data, 0);
  release_frame_dc (f, dc);

  return NILP (match_data.list) ? Qnil : XCAR (match_data.list);
}

898
int
899 900
w32font_open_internal (FRAME_PTR f, Lisp_Object font_entity,
		       int pixel_size, Lisp_Object font_object)
901
{
902
  int len, size;
903 904 905 906
  LOGFONT logfont;
  HDC dc;
  HFONT hfont, old_font;
  Lisp_Object val, extra;
907 908
  struct w32font_info *w32_font;
  struct font * font;
909
  OUTLINETEXTMETRICW* metrics = NULL;
910 911 912

  w32_font = (struct w32font_info *) XFONT_OBJECT (font_object);
  font = (struct font *) w32_font;
913 914 915 916

  if (!font)
    return 0;

917
  memset (&logfont, 0, sizeof (logfont));
918 919
  fill_in_logfont (f, &logfont, font_entity);

920 921 922 923 924 925
  /* Prefer truetype fonts, to avoid known problems with type1 fonts, and
     limitations in bitmap fonts.  */
  val = AREF (font_entity, FONT_FOUNDRY_INDEX);
  if (!EQ (val, Qraster))
    logfont.lfOutPrecision = OUT_TT_PRECIS;

926 927 928 929 930 931 932 933 934 935 936 937 938 939
  size = XINT (AREF (font_entity, FONT_SIZE_INDEX));
  if (!size)
    size = pixel_size;

  logfont.lfHeight = -size;
  hfont = CreateFontIndirect (&logfont);

  if (hfont == NULL)
    return 0;

  /* Get the metrics for this font.  */
  dc = get_frame_dc (f);
  old_font = SelectObject (dc, hfont);

940
  /* Try getting the outline metrics (only works for truetype fonts).  */
941
  len = get_outline_metrics_w (dc, 0, NULL);
942 943
  if (len)
    {
944
      metrics = (OUTLINETEXTMETRICW *) alloca (len);
945
      if (get_outline_metrics_w (dc, len, metrics))
946 947
        memcpy (&w32_font->metrics, &metrics->otmTextMetrics,
		sizeof (TEXTMETRICW));
948 949 950
      else
        metrics = NULL;
    }
951

952
  if (!metrics)
953
    get_text_metrics_w (dc, &w32_font->metrics);
954

Jason Rumney's avatar
Jason Rumney committed
955 956
  w32_font->cached_metrics = NULL;
  w32_font->n_cache_blocks = 0;
957

958 959
  SelectObject (dc, old_font);
  release_frame_dc (f, dc);
960

961
  w32_font->hfont = hfont;
962

963 964 965 966 967 968
  {
    char *name;

    /* We don't know how much space we need for the full name, so start with
       96 bytes and go up in steps of 32.  */
    len = 96;
969
    name = alloca (len);
970 971
    while (name && w32font_full_name (&logfont, font_entity, pixel_size,
                                      name, len) < 0)
972
      {
973 974
        len += 32;
        name = alloca (len);
975 976
      }
    if (name)
977
      font->props[FONT_FULLNAME_INDEX]
978
        = DECODE_SYSTEM (build_string (name));
979
    else
980 981
      font->props[FONT_FULLNAME_INDEX]
	= DECODE_SYSTEM (build_string (logfont.lfFaceName));
982
  }
983 984

  font->max_width = w32_font->metrics.tmMaxCharWidth;
985
  /* Parts of Emacs display assume that height = ascent + descent...
986
     so height is defined later, after ascent and descent.
987
  font->height = w32_font->metrics.tmHeight
988
    + w32_font->metrics.tmExternalLeading;
989 990
  */

991 992 993 994 995 996 997 998
  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;
  font->font_encoder = NULL;
999 1000
  font->pixel_size = size;
  font->driver = &w32font_driver;
1001 1002 1003 1004 1005 1006 1007
  /* 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))
1008
        font->props[FONT_FORMAT_INDEX] = XCDR (val);
1009
      else
1010
        font->props[FONT_FORMAT_INDEX] = Qunknown;
1011 1012
    }
  else
1013
    font->props[FONT_FORMAT_INDEX] = Qunknown;
1014

1015
  font->props[FONT_FILE_INDEX] = Qnil;
1016 1017
  font->encoding_charset = -1;
  font->repertory_charset = -1;
1018
  /* TODO: do we really want the minimum width here, which could be negative? */
1019
  font->min_width = font->space_width;
1020 1021
  font->ascent = w32_font->metrics.tmAscent;
  font->descent = w32_font->metrics.tmDescent;
1022
  font->height = font->ascent + font->descent;
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033

  if (metrics)
    {
      font->underline_thickness = metrics->otmsUnderscoreSize;
      font->underline_position = -metrics->otmsUnderscorePosition;
    }
  else
    {
      font->underline_thickness = 0;
      font->underline_position = -1;
    }
1034

1035 1036 1037 1038
  /* For temporary compatibility with legacy code that expects the
     name to be usable in x-list-fonts. Eventually we expect to change
     x-list-fonts and other places that use fonts so that this can be
     an fcname or similar.  */
Kenichi Handa's avatar
Kenichi Handa committed
1039
  font->props[FONT_NAME_INDEX] = Ffont_xlfd_name (font_object, Qnil);
1040

1041 1042 1043
  return 1;
}