mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2025-01-31 20:02:42 +00:00
Implement drawing text with DirectWrite on MS-Windows.
This adds support for color fonts. * configure.ac: Add src/w32drite to W32_OBJ. * src/w32dwrite.c: New file. (w32-initialize-direct-write): New function, initialize the DirectWrite library if it is available, and required global variables. (w32_use_direct_write): New function, check if DirectWrite is available and activated by the user. (w32_dwrite_encode_char): New function, replacement for HarfBuzz's 'encode_char'. (w32_dwrite_text_extents): New function, replacement for w32font text_extents. (w32_dwrite_draw): New function, replacement for w32font draw. (w32_dwrite_free_cached_face): New function, used in the font deletion process to also delete DirectWrite data. (verify_hr): New function, verify COM method results. (release_com): New function, release a COM object. (w32-dwrite-available): New function, returns true if DirectWrite is available. (w32-dwrite-reinit): New function, reinitialize DirectWrite, optionally setting some rendering parameters. * src/w32font.c (w32font_text_extents): If DirectWrite is enabled, call 'w32_dwrite_text_extents'. (w32font_draw): If DirectWrite is enabled, call 'w32_dwrite_draw'. * src/w32uniscribe.c: (w32hb_encode_char): If DirectWrite is enabled, call 'w32_dwrite_encode_char'. (syms_of_w32uniscribe_for_pdumper): Initialize DirectWrite. (uniscribe_close): Free DirectWrite data for the font. Bug#73730
This commit is contained in:
parent
517711c373
commit
edf37e811c
@ -3172,7 +3172,7 @@ if test "${HAVE_W32}" = "yes"; then
|
||||
AC_CHECK_TOOL([WINDRES], [windres],
|
||||
[AC_MSG_ERROR([No resource compiler found.])])
|
||||
W32_OBJ="w32fns.o w32menu.o w32reg.o w32font.o w32term.o"
|
||||
W32_OBJ="$W32_OBJ w32xfns.o w32select.o w32uniscribe.o w32cygwinx.o"
|
||||
W32_OBJ="$W32_OBJ w32xfns.o w32select.o w32uniscribe.o w32dwrite.o w32cygwinx.o"
|
||||
EMACSRES="emacs.res"
|
||||
case "$canonical" in
|
||||
x86_64-*-*) EMACS_MANIFEST="emacs-x64.manifest" ;;
|
||||
|
8
etc/NEWS
8
etc/NEWS
@ -785,6 +785,14 @@ This is in addition to drag-n-drop of files, that was already
|
||||
supported. As on X, the user options 'dnd-scroll-margin' and
|
||||
'dnd-indicate-insertion-point' can be used to customize the process.
|
||||
|
||||
---
|
||||
** Emacs on MS-Windows now supports color fonts.
|
||||
On Windows 8.1 and later versions Emacs now uses DirectWrite to draw
|
||||
text, which supports color fonts. This can be disabled by setting the
|
||||
variable 'w32-inhibit-dwrite' to t. Also see 'w32-dwrite-available' and
|
||||
'w32-dwrite-reinit' to check availability and to configure render
|
||||
parameters.
|
||||
|
||||
|
||||
----------------------------------------------------------------------
|
||||
This file is part of GNU Emacs.
|
||||
|
1099
src/w32dwrite.c
Normal file
1099
src/w32dwrite.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -452,6 +452,10 @@ w32font_text_extents (struct font *font, const unsigned *code,
|
||||
|
||||
memset (metrics, 0, sizeof (struct font_metrics));
|
||||
|
||||
if (w32_use_direct_write (w32_font))
|
||||
if (w32_dwrite_text_extents (font, code, nglyphs, metrics))
|
||||
return;
|
||||
|
||||
for (i = 0, first = true; i < nglyphs; i++)
|
||||
{
|
||||
struct w32_metric_cache *char_metric;
|
||||
@ -706,22 +710,31 @@ w32font_draw (struct glyph_string *s, int from, int to,
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
WCHAR c = s->char2b[from + i] & 0xFFFF;
|
||||
ExtTextOutW (s->hdc, x + i, y, options, NULL, &c, 1, NULL);
|
||||
}
|
||||
if (!w32_use_direct_write (w32font) ||
|
||||
!w32_dwrite_draw (s->hdc, x, y, s->char2b + from, 1,
|
||||
GetTextColor(s->hdc), s->font))
|
||||
{
|
||||
WCHAR c = s->char2b[from + i] & 0xFFFF;
|
||||
ExtTextOutW (s->hdc, x + i, y, options, NULL, &c, 1, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The number of glyphs in a glyph_string cannot be larger than
|
||||
the maximum value of the 'used' member of a glyph_row, so we
|
||||
are OK using alloca here. */
|
||||
eassert (len <= SHRT_MAX);
|
||||
WCHAR *chars = alloca (len * sizeof (WCHAR));
|
||||
int j;
|
||||
for (j = 0; j < len; j++)
|
||||
chars[j] = s->char2b[from + j] & 0xFFFF;
|
||||
ExtTextOutW (s->hdc, x, y, options, NULL, chars, len, NULL);
|
||||
if (!w32_use_direct_write (w32font) ||
|
||||
!w32_dwrite_draw (s->hdc, x, y,
|
||||
s->char2b + from, len, GetTextColor(s->hdc),
|
||||
s->font))
|
||||
{
|
||||
/* The number of glyphs in a glyph_string cannot be larger than
|
||||
the maximum value of the 'used' member of a glyph_row, so we
|
||||
are OK using alloca here. */
|
||||
eassert (len <= SHRT_MAX);
|
||||
WCHAR *chars = alloca (len * sizeof (WCHAR));
|
||||
int j;
|
||||
for (j = 0; j < len; j++)
|
||||
chars[j] = s->char2b[from + j] & 0xFFFF;
|
||||
ExtTextOutW (s->hdc, x, y, options, NULL, chars, len, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore clip region. */
|
||||
|
@ -57,6 +57,26 @@ struct w32font_info
|
||||
HFONT hfont;
|
||||
};
|
||||
|
||||
/* Extension of w32font_info used by Uniscribe and HarfBuzz backends. */
|
||||
struct uniscribe_font_info
|
||||
{
|
||||
struct w32font_info w32_font;
|
||||
/* This is used by the Uniscribe backend as a pointer to the script
|
||||
cache, and by the HarfBuzz backend as a pointer to a hb_font_t
|
||||
object. */
|
||||
void *cache;
|
||||
/* This is used by the HarfBuzz backend to store the font scale. */
|
||||
double scale;
|
||||
/* This is used by DirectWrite to store the FontFace object.
|
||||
DirectWrite works on top of the HarfBuzz backend, modifying some
|
||||
calls. If there are problems manipulating this font,
|
||||
dwrite_skip_font is set to true. Future operations will not use
|
||||
DirectWrite and fall back to the HarfBuzz backend. */
|
||||
void *dwrite_cache;
|
||||
float dwrite_font_size;
|
||||
bool dwrite_skip_font;
|
||||
};
|
||||
|
||||
/* Macros for getting OS specific information from a font struct. */
|
||||
#define FONT_HANDLE(f) (((struct w32font_info *)(f))->hfont)
|
||||
#define FONT_TEXTMETRIC(f) (((struct w32font_info *)(f))->metrics)
|
||||
@ -84,6 +104,17 @@ int uniscribe_check_otf (LOGFONT *font, Lisp_Object otf_spec);
|
||||
|
||||
Lisp_Object intern_font_name (char *);
|
||||
|
||||
/* Function prototypes for DirectWrite. */
|
||||
void w32_initialize_direct_write (void);
|
||||
bool w32_use_direct_write (struct w32font_info *w32font);
|
||||
bool w32_dwrite_draw (HDC hdc, int x, int y, unsigned *glyphs, int len,
|
||||
COLORREF color, struct font *font );
|
||||
bool w32_dwrite_text_extents (struct font *font, const unsigned *code,
|
||||
int nglyphs, struct font_metrics *metrics);
|
||||
unsigned w32_dwrite_encode_char (struct font *font, int c);
|
||||
void w32_dwrite_free_cached_face(void *cache);
|
||||
void syms_of_w32dwrite (void);
|
||||
|
||||
extern void globals_of_w32font (void);
|
||||
|
||||
#endif
|
||||
|
@ -44,18 +44,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
||||
#include "pdumper.h"
|
||||
#include "w32common.h"
|
||||
|
||||
/* Extension of w32font_info used by Uniscribe and HarfBuzz backends. */
|
||||
struct uniscribe_font_info
|
||||
{
|
||||
struct w32font_info w32_font;
|
||||
/* This is used by the Uniscribe backend as a pointer to the script
|
||||
cache, and by the HarfBuzz backend as a pointer to a hb_font_t
|
||||
object. */
|
||||
void *cache;
|
||||
/* This is used by the HarfBuzz backend to store the font scale. */
|
||||
double scale;
|
||||
};
|
||||
|
||||
int uniscribe_available = 0;
|
||||
|
||||
/* EnumFontFamiliesEx callback. */
|
||||
@ -200,6 +188,9 @@ uniscribe_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
|
||||
|
||||
/* Initialize the cache for this font. */
|
||||
uniscribe_font->cache = NULL;
|
||||
uniscribe_font->dwrite_cache = NULL;
|
||||
|
||||
uniscribe_font->dwrite_skip_font = false;
|
||||
|
||||
/* Uniscribe and HarfBuzz backends use glyph indices. */
|
||||
uniscribe_font->w32_font.glyph_idx = ETO_GLYPH_INDEX;
|
||||
@ -221,6 +212,7 @@ uniscribe_close (struct font *font)
|
||||
= (struct uniscribe_font_info *) font;
|
||||
|
||||
#ifdef HAVE_HARFBUZZ
|
||||
w32_dwrite_free_cached_face (uniscribe_font->dwrite_cache);
|
||||
if (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver
|
||||
&& uniscribe_font->cache)
|
||||
hb_font_destroy ((hb_font_t *) uniscribe_font->cache);
|
||||
@ -1372,6 +1364,17 @@ w32hb_encode_char (struct font *font, int c)
|
||||
struct uniscribe_font_info *uniscribe_font
|
||||
= (struct uniscribe_font_info *) font;
|
||||
eassert (uniscribe_font->w32_font.font.driver == &harfbuzz_font_driver);
|
||||
|
||||
if (w32_use_direct_write (&uniscribe_font->w32_font))
|
||||
{
|
||||
unsigned encoded = w32_dwrite_encode_char (font, c);
|
||||
|
||||
/* The call to w32_dwrite_encode_char may fail, disabling
|
||||
DirectWrite for this font. So check again. */
|
||||
if (w32_use_direct_write (&uniscribe_font->w32_font))
|
||||
return encoded;
|
||||
}
|
||||
|
||||
hb_font_t *hb_font = uniscribe_font->cache;
|
||||
|
||||
/* First time we use this font with HarfBuzz, create the hb_font_t
|
||||
@ -1510,6 +1513,7 @@ static void syms_of_w32uniscribe_for_pdumper (void);
|
||||
void
|
||||
syms_of_w32uniscribe (void)
|
||||
{
|
||||
syms_of_w32dwrite ();
|
||||
pdumper_do_now_and_after_load (syms_of_w32uniscribe_for_pdumper);
|
||||
}
|
||||
|
||||
@ -1624,5 +1628,8 @@ syms_of_w32uniscribe_for_pdumper (void)
|
||||
harfbuzz_font_driver.combining_capability = hbfont_combining_capability;
|
||||
harfbuzz_font_driver.begin_hb_font = w32hb_begin_font;
|
||||
register_font_driver (&harfbuzz_font_driver, NULL);
|
||||
|
||||
w32_initialize_direct_write ();
|
||||
|
||||
#endif /* HAVE_HARFBUZZ */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user