aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYAMAMOTO Mitsuharu2019-06-08 14:05:49 +0900
committerYAMAMOTO Mitsuharu2019-06-08 14:05:49 +0900
commitfaf10bd8eb3272880b774fe220fa9916ed1f00c0 (patch)
treef933e9f012e0c96effefb02daa31ead9acc22aed /src
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.
Diffstat (limited to 'src')
-rw-r--r--src/font.c2
-rw-r--r--src/xfns.c2
-rw-r--r--src/xterm.c341
3 files changed, 261 insertions, 84 deletions
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