aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2019-06-08 14:05:49 +0900
committerYAMAMOTO Mitsuharu2019-06-08 14:05:49 +0900
commitfaf10bd8eb3272880b774fe220fa9916ed1f00c0 (patch)
treef933e9f012e0c96effefb02daa31ead9acc22aed
parent88c49ac31898e7b2c29338ca55cae292c450f7be (diff)
downloademacs-faf10bd8eb3272880b774fe220fa9916ed1f00c0.tar.gz
emacs-faf10bd8eb3272880b774fe220fa9916ed1f00c0.zip
Support X core font driver on cairo (Bug#28236)
* configure.ac (HAVE_X_WINDOWS): Add xfont.o to FONT_OBJ if HAVE_CAIRO. * doc/lispref/frames.texi (Font and Color Parameters): Mention X core font driver with Cairo drawing. * src/font.c (syms_of_font) [HAVE_X_WINDOWS && USE_CAIRO]: Call syms_of_xfont. * src/xfns.c (x_create_tip_frame) [USE_CAIRO]: Register xfont_driver. * src/xterm.c (x_cr_gc_clip) [USE_CAIRO]: New function extracted from x_begin_cr_clip. (x_begin_cr_clip) [USE_CAIRO]: Use it. (xlib_surface_key, saved_drawable_key) [USE_CAIRO]: New variables. (x_cr_destroy_xlib_surface, x_try_cr_xlib_drawable) (x_end_cr_xlib_drawable) [USE_CAIRO]: New functions. (x_draw_composite_glyph_string_foreground) (x_draw_glyph_string_foreground) [USE_CAIRO]: Get Xlib surface when drawing text with X core fonts into bitmap surfaces. Add fallback code for drawing into outline surfaces.
-rw-r--r--configure.ac2
-rw-r--r--doc/lispref/frames.texi10
-rw-r--r--src/font.c2
-rw-r--r--src/xfns.c2
-rw-r--r--src/xterm.c341
5 files changed, 267 insertions, 90 deletions
diff --git a/configure.ac b/configure.ac
index bd51f54212c..5c96f4231ee 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5261,7 +5261,7 @@ if test "${HAVE_X_WINDOWS}" = "yes" ; then
5261 XOBJ="xterm.o xfns.o xselect.o xrdb.o xsmfns.o xsettings.o" 5261 XOBJ="xterm.o xfns.o xselect.o xrdb.o xsmfns.o xsettings.o"
5262 FONT_OBJ=xfont.o 5262 FONT_OBJ=xfont.o
5263 if test "$HAVE_CAIRO" = "yes"; then 5263 if test "$HAVE_CAIRO" = "yes"; then
5264 FONT_OBJ="ftfont.o ftcrfont.o" 5264 FONT_OBJ="$FONT_OBJ ftfont.o ftcrfont.o"
5265 elif test "$HAVE_XFT" = "yes"; then 5265 elif test "$HAVE_XFT" = "yes"; then
5266 FONT_OBJ="$FONT_OBJ ftfont.o xftfont.o ftxfont.o" 5266 FONT_OBJ="$FONT_OBJ ftfont.o xftfont.o ftxfont.o"
5267 elif test "$HAVE_FREETYPE" = "yes"; then 5267 elif test "$HAVE_FREETYPE" = "yes"; then
diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 336075a1ca2..629cec3c5fe 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2282,11 +2282,11 @@ drawing characters on the frame, in order of priority. In Emacs built
2282without Cairo drawing on X, there are currently three available font 2282without Cairo drawing on X, there are currently three available font
2283backends: @code{x} (the X core font driver), @code{xft} (the Xft font 2283backends: @code{x} (the X core font driver), @code{xft} (the Xft font
2284driver), and @code{xfthb} (the Xft font driver with HarfBuzz text 2284driver), and @code{xfthb} (the Xft font driver with HarfBuzz text
2285shaping). If built with the Cairo drawing, there are two available 2285shaping). If built with the Cairo drawing, there are also three
2286font backends on X: @code{ftcr} (the FreeType font driver on Cairo) 2286available font backends on X: @code{x}, @code{ftcr} (the FreeType font
2287and @code{ftcrhb} (the FreeType font driver on Cairo with HarfBuzz 2287driver on Cairo), and @code{ftcrhb} (the FreeType font driver on Cairo
2288text shaping). On MS-Windows, there are currently three available 2288with HarfBuzz text shaping). On MS-Windows, there are currently three
2289font backends: @code{gdi} (the core MS-Windows font driver), 2289available font backends: @code{gdi} (the core MS-Windows font driver),
2290@code{uniscribe} (font driver for OTF and TTF fonts with text shaping 2290@code{uniscribe} (font driver for OTF and TTF fonts with text shaping
2291by the Uniscribe engine), and @code{harfbuzz} (font driver for OTF and 2291by the Uniscribe engine), and @code{harfbuzz} (font driver for OTF and
2292TTF fonts with HarfBuzz text shaping) (@pxref{Windows Fonts,,, emacs, 2292TTF fonts with HarfBuzz text shaping) (@pxref{Windows Fonts,,, emacs,
diff --git a/src/font.c b/src/font.c
index 6ab4923c3d2..5705758b99f 100644
--- a/src/font.c
+++ b/src/font.c
@@ -5497,10 +5497,10 @@ cause Xft crashes. Only has an effect in Xft builds. */);
5497#ifdef HAVE_FREETYPE 5497#ifdef HAVE_FREETYPE
5498 syms_of_ftfont (); 5498 syms_of_ftfont ();
5499#ifdef HAVE_X_WINDOWS 5499#ifdef HAVE_X_WINDOWS
5500 syms_of_xfont ();
5500#ifdef USE_CAIRO 5501#ifdef USE_CAIRO
5501 syms_of_ftcrfont (); 5502 syms_of_ftcrfont ();
5502#else 5503#else
5503 syms_of_xfont ();
5504 syms_of_ftxfont (); 5504 syms_of_ftxfont ();
5505#ifdef HAVE_XFT 5505#ifdef HAVE_XFT
5506 syms_of_xftfont (); 5506 syms_of_xftfont ();
diff --git a/src/xfns.c b/src/xfns.c
index 460dd1316e6..46f19ff82ac 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3794,8 +3794,8 @@ This function is an internal primitive--use `make-frame' instead. */)
3794 register_font_driver (&ftxfont_driver, f); 3794 register_font_driver (&ftxfont_driver, f);
3795#endif /* not HAVE_XFT */ 3795#endif /* not HAVE_XFT */
3796#endif /* HAVE_FREETYPE */ 3796#endif /* HAVE_FREETYPE */
3797 register_font_driver (&xfont_driver, f);
3798#endif /* not USE_CAIRO */ 3797#endif /* not USE_CAIRO */
3798 register_font_driver (&xfont_driver, f);
3799 3799
3800 image_cache_refcount = 3800 image_cache_refcount =
3801 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0; 3801 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
diff --git a/src/xterm.c b/src/xterm.c
index e0edd9c1a40..3cd95b7a65d 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -357,6 +357,25 @@ x_cr_update_surface_desired_size (struct frame *f, int width, int height)
357 } 357 }
358} 358}
359 359
360static void
361x_cr_gc_clip (cairo_t *cr, struct frame *f, GC gc)
362{
363 if (gc)
364 {
365 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
366
367 if (gc_ext && gc_ext->n_clip_rects)
368 {
369 for (int i = 0; i < gc_ext->n_clip_rects; i++)
370 cairo_rectangle (cr, gc_ext->clip_rects[i].x,
371 gc_ext->clip_rects[i].y,
372 gc_ext->clip_rects[i].width,
373 gc_ext->clip_rects[i].height);
374 cairo_clip (cr);
375 }
376 }
377}
378
360cairo_t * 379cairo_t *
361x_begin_cr_clip (struct frame *f, GC gc) 380x_begin_cr_clip (struct frame *f, GC gc)
362{ 381{
@@ -379,23 +398,7 @@ x_begin_cr_clip (struct frame *f, GC gc)
379 cairo_surface_destroy (surface); 398 cairo_surface_destroy (surface);
380 } 399 }
381 cairo_save (cr); 400 cairo_save (cr);
382 401 x_cr_gc_clip (cr, f, gc);
383 if (gc)
384 {
385 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
386
387 if (gc_ext && gc_ext->n_clip_rects)
388 {
389 int i;
390
391 for (i = 0; i < gc_ext->n_clip_rects; i++)
392 cairo_rectangle (cr, gc_ext->clip_rects[i].x,
393 gc_ext->clip_rects[i].y,
394 gc_ext->clip_rects[i].width,
395 gc_ext->clip_rects[i].height);
396 cairo_clip (cr);
397 }
398 }
399 402
400 return cr; 403 return cr;
401} 404}
@@ -434,6 +437,116 @@ x_set_cr_source_with_gc_background (struct frame *f, GC gc)
434 color.green / 65535.0, color.blue / 65535.0); 437 color.green / 65535.0, color.blue / 65535.0);
435} 438}
436 439
440static const cairo_user_data_key_t xlib_surface_key, saved_drawable_key;
441
442static void
443x_cr_destroy_xlib_surface (cairo_surface_t *xlib_surface)
444{
445 if (xlib_surface)
446 {
447 XFreePixmap (cairo_xlib_surface_get_display (xlib_surface),
448 cairo_xlib_surface_get_drawable (xlib_surface));
449 cairo_surface_destroy (xlib_surface);
450 }
451}
452
453static bool
454x_try_cr_xlib_drawable (struct frame *f, GC gc)
455{
456 cairo_t *cr = FRAME_CR_CONTEXT (f);
457 if (!cr)
458 return true;
459
460 cairo_surface_t *surface = cairo_get_target (cr);
461 switch (cairo_surface_get_type (surface))
462 {
463 case CAIRO_SURFACE_TYPE_XLIB:
464 cairo_surface_flush (surface);
465 return true;
466
467 case CAIRO_SURFACE_TYPE_IMAGE:
468 break;
469
470 default:
471 return false;
472 }
473
474 /* FRAME_CR_CONTEXT (f) is an image surface we can not draw into
475 directly with Xlib. Set up a Pixmap so we can copy back the
476 result later in x_end_cr_xlib_drawable. */
477 cairo_surface_t *xlib_surface = cairo_get_user_data (cr, &xlib_surface_key);
478 int width = FRAME_CR_SURFACE_DESIRED_WIDTH (f);
479 int height = FRAME_CR_SURFACE_DESIRED_HEIGHT (f);
480 Pixmap pixmap;
481 if (xlib_surface
482 && cairo_xlib_surface_get_width (xlib_surface) == width
483 && cairo_xlib_surface_get_height (xlib_surface) == height)
484 pixmap = cairo_xlib_surface_get_drawable (xlib_surface);
485 else
486 {
487 pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_RAW_DRAWABLE (f),
488 width, height,
489 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
490 xlib_surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
491 pixmap, FRAME_X_VISUAL (f),
492 width, height);
493 cairo_set_user_data (cr, &xlib_surface_key, xlib_surface,
494 (cairo_destroy_func_t) x_cr_destroy_xlib_surface);
495 }
496
497 cairo_t *buf = cairo_create (xlib_surface);
498 cairo_set_source_surface (buf, surface, 0, 0);
499 cairo_matrix_t matrix;
500 cairo_get_matrix (cr, &matrix);
501 cairo_pattern_set_matrix (cairo_get_source (cr), &matrix);
502 cairo_set_operator (buf, CAIRO_OPERATOR_SOURCE);
503 x_cr_gc_clip (buf, f, gc);
504 cairo_paint (buf);
505 cairo_destroy (buf);
506
507 cairo_set_user_data (cr, &saved_drawable_key,
508 (void *) (uintptr_t) FRAME_X_RAW_DRAWABLE (f), NULL);
509 FRAME_X_RAW_DRAWABLE (f) = pixmap;
510 cairo_surface_flush (xlib_surface);
511
512 return true;
513}
514
515static void
516x_end_cr_xlib_drawable (struct frame *f, GC gc)
517{
518 cairo_t *cr = FRAME_CR_CONTEXT (f);
519 if (!cr)
520 return;
521
522 Drawable saved_drawable
523 = (uintptr_t) cairo_get_user_data (cr, &saved_drawable_key);
524 cairo_surface_t *surface = (saved_drawable
525 ? cairo_get_user_data (cr, &xlib_surface_key)
526 : cairo_get_target (cr));
527 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
528 if (gc_ext && gc_ext->n_clip_rects)
529 for (int i = 0; i < gc_ext->n_clip_rects; i++)
530 cairo_surface_mark_dirty_rectangle (surface, gc_ext->clip_rects[i].x,
531 gc_ext->clip_rects[i].y,
532 gc_ext->clip_rects[i].width,
533 gc_ext->clip_rects[i].height);
534 else
535 cairo_surface_mark_dirty (surface);
536 if (!saved_drawable)
537 return;
538
539 cairo_save (cr);
540 cairo_set_source_surface (cr, surface, 0, 0);
541 cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
542 x_cr_gc_clip (cr, f, gc);
543 cairo_paint (cr);
544 cairo_restore (cr);
545
546 FRAME_X_RAW_DRAWABLE (f) = saved_drawable;
547 cairo_set_user_data (cr, &saved_drawable_key, NULL, NULL);
548}
549
437/* Fringe bitmaps. */ 550/* Fringe bitmaps. */
438 551
439static int max_fringe_bmp = 0; 552static int max_fringe_bmp = 0;
@@ -1732,20 +1845,65 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
1732 else 1845 else
1733 { 1846 {
1734 struct font *font = s->font; 1847 struct font *font = s->font;
1735 int boff = font->baseline_offset; 1848#ifdef USE_CAIRO
1736 int y; 1849 if (!EQ (font->driver->type, Qx)
1850 || x_try_cr_xlib_drawable (s->f, s->gc))
1851 {
1852#endif /* USE_CAIRO */
1853 int boff = font->baseline_offset;
1854 int y;
1737 1855
1738 if (font->vertical_centering) 1856 if (font->vertical_centering)
1739 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff; 1857 boff = VCENTER_BASELINE_OFFSET (font, s->f) - boff;
1740 1858
1741 y = s->ybase - boff; 1859 y = s->ybase - boff;
1742 if (s->for_overlaps 1860 if (s->for_overlaps
1743 || (s->background_filled_p && s->hl != DRAW_CURSOR)) 1861 || (s->background_filled_p && s->hl != DRAW_CURSOR))
1744 font->driver->draw (s, 0, s->nchars, x, y, false); 1862 font->driver->draw (s, 0, s->nchars, x, y, false);
1863 else
1864 font->driver->draw (s, 0, s->nchars, x, y, true);
1865 if (s->face->overstrike)
1866 font->driver->draw (s, 0, s->nchars, x + 1, y, false);
1867#ifdef USE_CAIRO
1868 if (EQ (font->driver->type, Qx))
1869 x_end_cr_xlib_drawable (s->f, s->gc);
1870 }
1745 else 1871 else
1746 font->driver->draw (s, 0, s->nchars, x, y, true); 1872 {
1747 if (s->face->overstrike) 1873 /* Fallback for the case that no Xlib Drawable is available
1748 font->driver->draw (s, 0, s->nchars, x + 1, y, false); 1874 for drawing text with X core fonts. */
1875 if (!(s->for_overlaps
1876 || (s->background_filled_p && s->hl != DRAW_CURSOR)))
1877 {
1878 int box_line_width = max (s->face->box_line_width, 0);
1879
1880 if (s->stippled_p)
1881 {
1882 Display *display = FRAME_X_DISPLAY (s->f);
1883
1884 /* Fill background with a stipple pattern. */
1885 XSetFillStyle (display, s->gc, FillOpaqueStippled);
1886 x_fill_rectangle (s->f, s->gc, s->x,
1887 s->y + box_line_width,
1888 s->background_width,
1889 s->height - 2 * box_line_width);
1890 XSetFillStyle (display, s->gc, FillSolid);
1891 }
1892 else
1893 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
1894 s->background_width,
1895 s->height - 2 * box_line_width);
1896 }
1897 for (i = 0; i < s->nchars; ++i)
1898 {
1899 struct glyph *g = s->first_glyph + i;
1900 x_draw_rectangle (s->f,
1901 s->gc, x, s->y, g->pixel_width - 1,
1902 s->height - 1);
1903 x += g->pixel_width;
1904 }
1905 }
1906#endif /* USE_CAIRO */
1749 } 1907 }
1750} 1908}
1751 1909
@@ -1778,65 +1936,84 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1778 x_draw_rectangle (s->f, s->gc, x, s->y, 1936 x_draw_rectangle (s->f, s->gc, x, s->y,
1779 s->width - 1, s->height - 1); 1937 s->width - 1, s->height - 1);
1780 } 1938 }
1781 else if (! s->first_glyph->u.cmp.automatic)
1782 {
1783 int y = s->ybase;
1784
1785 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1786 /* TAB in a composition means display glyphs with padding
1787 space on the left or right. */
1788 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1789 {
1790 int xx = x + s->cmp->offsets[j * 2];
1791 int yy = y - s->cmp->offsets[j * 2 + 1];
1792
1793 font->driver->draw (s, j, j + 1, xx, yy, false);
1794 if (s->face->overstrike)
1795 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1796 }
1797 }
1798 else 1939 else
1799 { 1940#ifdef USE_CAIRO
1800 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id); 1941 if (!EQ (font->driver->type, Qx)
1801 Lisp_Object glyph; 1942 || x_try_cr_xlib_drawable (s->f, s->gc))
1802 int y = s->ybase; 1943 {
1803 int width = 0; 1944#endif /* USE_CAIRO */
1804 1945 if (! s->first_glyph->u.cmp.automatic)
1805 for (i = j = s->cmp_from; i < s->cmp_to; i++) 1946 {
1806 { 1947 int y = s->ybase;
1807 glyph = LGSTRING_GLYPH (gstring, i);
1808 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1809 width += LGLYPH_WIDTH (glyph);
1810 else
1811 {
1812 int xoff, yoff, wadjust;
1813 1948
1814 if (j < i) 1949 for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
1950 /* TAB in a composition means display glyphs with
1951 padding space on the left or right. */
1952 if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
1815 { 1953 {
1816 font->driver->draw (s, j, i, x, y, false); 1954 int xx = x + s->cmp->offsets[j * 2];
1955 int yy = y - s->cmp->offsets[j * 2 + 1];
1956
1957 font->driver->draw (s, j, j + 1, xx, yy, false);
1817 if (s->face->overstrike) 1958 if (s->face->overstrike)
1818 font->driver->draw (s, j, i, x + 1, y, false); 1959 font->driver->draw (s, j, j + 1, xx + 1, yy, false);
1819 x += width;
1820 } 1960 }
1821 xoff = LGLYPH_XOFF (glyph); 1961 }
1822 yoff = LGLYPH_YOFF (glyph); 1962 else
1823 wadjust = LGLYPH_WADJUST (glyph); 1963 {
1824 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false); 1964 Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
1825 if (s->face->overstrike) 1965 Lisp_Object glyph;
1826 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff, 1966 int y = s->ybase;
1827 false); 1967 int width = 0;
1828 x += wadjust; 1968
1829 j = i + 1; 1969 for (i = j = s->cmp_from; i < s->cmp_to; i++)
1830 width = 0; 1970 {
1831 } 1971 glyph = LGSTRING_GLYPH (gstring, i);
1832 } 1972 if (NILP (LGLYPH_ADJUSTMENT (glyph)))
1833 if (j < i) 1973 width += LGLYPH_WIDTH (glyph);
1834 { 1974 else
1835 font->driver->draw (s, j, i, x, y, false); 1975 {
1836 if (s->face->overstrike) 1976 int xoff, yoff, wadjust;
1837 font->driver->draw (s, j, i, x + 1, y, false); 1977
1838 } 1978 if (j < i)
1839 } 1979 {
1980 font->driver->draw (s, j, i, x, y, false);
1981 if (s->face->overstrike)
1982 font->driver->draw (s, j, i, x + 1, y, false);
1983 x += width;
1984 }
1985 xoff = LGLYPH_XOFF (glyph);
1986 yoff = LGLYPH_YOFF (glyph);
1987 wadjust = LGLYPH_WADJUST (glyph);
1988 font->driver->draw (s, i, i + 1, x + xoff, y + yoff, false);
1989 if (s->face->overstrike)
1990 font->driver->draw (s, i, i + 1, x + xoff + 1, y + yoff,
1991 false);
1992 x += wadjust;
1993 j = i + 1;
1994 width = 0;
1995 }
1996 }
1997 if (j < i)
1998 {
1999 font->driver->draw (s, j, i, x, y, false);
2000 if (s->face->overstrike)
2001 font->driver->draw (s, j, i, x + 1, y, false);
2002 }
2003 }
2004#ifdef USE_CAIRO
2005 if (EQ (font->driver->type, Qx))
2006 x_end_cr_xlib_drawable (s->f, s->gc);
2007 }
2008 else
2009 {
2010 /* Fallback for the case that no Xlib Drawable is available
2011 for drawing text with X core fonts. */
2012 if (s->cmp_from == 0)
2013 x_draw_rectangle (s->f, s->gc, x, s->y,
2014 s->width - 1, s->height - 1);
2015 }
2016#endif /* USE_CAIRO */
1840} 2017}
1841 2018
1842 2019