aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJan D2015-02-11 16:14:35 +0100
committerJan D2015-02-11 16:14:35 +0100
commitdddcc0e78452f2186c132823a33a174d2596ba33 (patch)
tree8369d54925d9ea4b60ecf6a53c6a321dffd194f9 /src
parent061c7e2b5a5a5854b2b85f2ace5b1d9222dd7f11 (diff)
downloademacs-dddcc0e78452f2186c132823a33a174d2596ba33.tar.gz
emacs-dddcc0e78452f2186c132823a33a174d2596ba33.zip
Add cairo drawing.
* configure.ac (with-cairo): New option. (USE_CAIRO): Default to yes for Gtk+ 3. Add code to test for cairo, set CAIRO_CFLAGS, CAIRO_LIBS. Add ftcrfonto to FONT_OBJ if cairo. Output "Does Emacs use cairo?". * lisp/version.el (emacs-version): Add cairo version. * src/Makefile.in (CAIRO_CFLAGS, CAIRO_LIBS): New variables. (FONT_OBJ): Add comment about ftcrfont. (ALL_CFLAGS): Add CAIRO_CFLAGS. (LIBES): Add CAIRO_LIBS. * src/dispextern.h (struct image): Add cr_data for cairo. (x_cr_init_fringe): Declare. * src/font.c (syms_of_font): Call syms_of_ftcrfont for cairo. * src/font.h (ftcrfont_driver, syms_of_ftcrfont): Declare * src/fringe.c (x_cr_init_fringe): New function name that shares code with w32_init_fringe. * src/ftcrfont.c: New font driver for cairo, based on the ftfont driver. * src/ftfont.c (ftfont_info_size); New global variable. (ftfont_open2): New extern function almost the same as old ftfont_open, but takes the font_object as argument. (ftfont_open): Build font object and call ftfont_open2. * src/ftfont.h (ftfont_open2, ftfont_info_size): Declare. * src/gtkutil.c (xg_clear_under_internal_border) (xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos): Only queue_draw if not cairo. Change args to x_clear_area. (xg_get_font): Use Qftcr when using cairo, Qxft otherwise. (xg_page_setup_dialog, xg_get_page_setup, draw_page) (xg_print_frames_dialog): New functions for printing. * src/gtkutil.h (xg_page_setup_dialog, xg_get_page_setup) (xg_print_frames_dialog): Declare. * src/image.c: Add defined (USE_CAIRO) for PNG. Add !defined USE_CAIRO for W32 PNG code. (x_clear_image): If cairo, destroy the surface in cr_data. (png_load): Add new cairo compatible implementation. (lookup_image_type): Add defined (USE_CAIRO) for define png_type. * src/xfns.c: New section Printing. (x-export-frames, x-page-setup-dialog, x-get-page-setup) (x-print-frames-dialog): New printing functions. (Fx_create_frame, x_create_tip_frame): Register ftcrfont if cairo. (syms_of_xfns): Defsym Qorientation, Qtop_margin, Qbottom_margin, Qportrait, Qlandscape, Qreverse_portrait, Qreverse_landscape). (syms_of_xfns): Provide cairo and defvar cairo-version-string. defsubr Sx_page_setup_dialog, Sx_get_page_setup, Sx_print_frames_dialog. * src/xterm.c (x_clear_area1, x_prepare_for_xlibdraw) (x_set_clip_rectangles, x_reset_clip_rectangles, x_fill_rectangle) (x_draw_rectangle, x_fill_trapezoid_for_relief, x_clear_window) (x_gc_get_ext_data, x_extension_initialize, x_cr_accumulate_data): Declare. (FRAME_CR_CONTEXT, FRAME_CR_SURFACE): New macros. (max_fringe_bmp, fringe_bmp): New variables. (x_gc_get_ext_data, x_extension_initialize) (x_cr_destroy_surface, x_begin_cr_clip, x_end_cr_clip) (x_set_cr_source_with_gc_foreground) (x_set_cr_source_with_gc_background, x_cr_define_fringe_bitmap) (x_cr_destroy_fringe_bitmap, x_cr_draw_image, x_cr_draw_frame) (x_cr_accumulate_data, x_cr_destroy, x_cr_export_frames) (x_prepare_for_xlibdraw, x_set_clip_rectangles) (x_reset_clip_rectangles, x_fill_rectangle, x_draw_rectangle) (x_clear_window, x_fill_trapezoid_for_relief): New functions. (x_update_begin): Create cairo surface if needed. (x_draw_vertical_window_border): Call x_fill_rectangle for cairo. (x_update_end): Paint cairo drawing surface to xlib surface. (x_clear_under_internal_border, x_after_update_window_line): Adjust arguments to x_clear_area. (x_draw_fringe_bitmap): Call x_fill_rectangle. Get GC values and call x_cr_draw_image for cairo. Call x_reset_clip_rectangles instead of XSetClipMask. (x_set_glyph_string_clipping) (x_set_glyph_string_clipping_exactly): Use x_set_clip_rectangles instead of XSetClipRectangles. (x_clear_glyph_string_rect, x_draw_glyph_string_background): Use x_fill_rectangle instead of XFillRectangle. (x_draw_glyph_string_foreground) (x_draw_composite_glyph_string_foreground) (x_draw_glyphless_glyph_string_foreground): Use x_draw_rectangle instead of XDrawRectangle. (x_draw_relief_rect): Add code for USE_CAIRO. Call x_reset_clip_rectangles instead of XSetClipMask. (x_draw_box_rect): x_set_clip_rectangles instead of XSetClipRectangles, x_fill_rectangle instead of XFillRectangle, x_reset_clip_rectangles instead of XSetClipMask. (x_draw_image_foreground, x_draw_image_foreground_1): x_draw_rectangle instead of XDrawRectangle. (x_draw_glyph_string_bg_rect): x_fill_rectangle instead of XFillRectangle. (x_draw_image_glyph_string): If img has cr_data, use it as a cairo surface. (x_draw_stretch_glyph_string): x_set_clip_rectangles instead of XSetClipRectangles, x_fill_rectangle instead of XFillRectangle. (x_draw_glyph_string): x_fill_rectangle instead of XFillRectangle., x_reset_clip_rectangles instead of XSetClipMask. (x_shift_glyphs_for_insert): Call x_prepare_for_xlibdraw. (x_clear_area1): New function that calls XClearArea. (x_clear_area): Takes frame as parameter, calls x_clear_area1 for non-cairo. (x_clear_frame): x_clear_window instead of XClearWindow. (x_scroll_run): Set frame garbaged if cairo. (XTmouse_position): Initialize *part to 0. (x_scroll_bar_create): Adjust arguments to x_clear_area. (x_scroll_bar_set_handle): x_clear_area1 instead of x_clear_area, x_fill_rectangle instead of XFillRectangle. (XTset_vertical_scroll_bar, XTset_horizontal_scroll_bar): Adjust arguments to x_clear_area. (x_scroll_bar_expose): x_draw_rectangle instead of XDrawRectangle. (handle_one_xevent): Adjust arguments to x_clear_area. Destroy cairo surface for frame if ConfigureNotify. (x_clip_to_row): x_set_clip_rectangles instead of XSetClipRectangles. (x_draw_hollow_cursor): x_draw_rectangle instead of XDrawRectangle, x_reset_clip_rectangles instead of XSetClipMask. (x_draw_bar_cursor): x_fill_rectangle instead of XFillRectangle, x_reset_clip_rectangles instead of XSetClipMask. (x_clear_frame_area): Adjust arguments to x_clear_area. (x_free_frame_resources): Call x_prepare_for_xlibdraw. (x_term_init): Call x_extension_initialize if cairo. (x_redisplay_interface): Add x_cr_define_fringe_bitmap, x_cr_destroy_fringe_bitmap for cairo. (x_initialize): Call x_cr_init_fringe for cairo. * src/xterm.h: Add include of cairo header files. (x_bitmap_record): Add img if cairo. (x_gc_ext_data): New struct for cairo. (x_display_info): Add ext_codes for cairo. (x_output): Add cr_context and cr_surface for cairo. (x_clear_area): Change arguments from Display*/Window to frame pointer. (x_query_color, x_begin_cr_clip, x_end_cr_clip) (x_set_cr_source_with_gc_foreground, x_set_cr_source_with_gc_background) (x_cr_draw_frame, x_cr_export_frames): Declare.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog138
-rw-r--r--src/Makefile.in8
-rw-r--r--src/dispextern.h6
-rw-r--r--src/font.c4
-rw-r--r--src/font.h4
-rw-r--r--src/fringe.c8
-rw-r--r--src/ftcrfont.c314
-rw-r--r--src/ftfont.c26
-rw-r--r--src/ftfont.h5
-rw-r--r--src/gtkutil.c131
-rw-r--r--src/gtkutil.h6
-rw-r--r--src/image.c55
-rw-r--r--src/xfns.c195
-rw-r--r--src/xterm.c895
-rw-r--r--src/xterm.h53
15 files changed, 1746 insertions, 102 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index f8e65d5d91d..e361fe286e4 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,141 @@
12015-02-11 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
2 Jan Djärv <jan.h.d@swipnet.se>
3
4 * xterm.h: Add include of cairo header files.
5 (x_bitmap_record): Add img if cairo.
6 (x_gc_ext_data): New struct for cairo.
7 (x_display_info): Add ext_codes for cairo.
8 (x_output): Add cr_context and cr_surface for cairo.
9 (x_clear_area): Change arguments from Display*/Window to frame pointer.
10 (x_query_color, x_begin_cr_clip, x_end_cr_clip)
11 (x_set_cr_source_with_gc_foreground, x_set_cr_source_with_gc_background)
12 (x_cr_draw_frame, x_cr_export_frames): Declare.
13
14 * xterm.c (x_clear_area1, x_prepare_for_xlibdraw)
15 (x_set_clip_rectangles, x_reset_clip_rectangles, x_fill_rectangle)
16 (x_draw_rectangle, x_fill_trapezoid_for_relief, x_clear_window)
17 (x_gc_get_ext_data, x_extension_initialize, x_cr_accumulate_data):
18 Declare.
19 (FRAME_CR_CONTEXT, FRAME_CR_SURFACE): New macros.
20 (max_fringe_bmp, fringe_bmp): New variables.
21 (x_gc_get_ext_data, x_extension_initialize)
22 (x_cr_destroy_surface, x_begin_cr_clip, x_end_cr_clip)
23 (x_set_cr_source_with_gc_foreground)
24 (x_set_cr_source_with_gc_background, x_cr_define_fringe_bitmap)
25 (x_cr_destroy_fringe_bitmap, x_cr_draw_image, x_cr_draw_frame)
26 (x_cr_accumulate_data, x_cr_destroy, x_cr_export_frames)
27 (x_prepare_for_xlibdraw, x_set_clip_rectangles)
28 (x_reset_clip_rectangles, x_fill_rectangle, x_draw_rectangle)
29 (x_clear_window, x_fill_trapezoid_for_relief): New functions.
30 (x_update_begin): Create cairo surface if needed.
31 (x_draw_vertical_window_border): Call x_fill_rectangle for cairo.
32 (x_update_end): Paint cairo drawing surface to xlib surface.
33 (x_clear_under_internal_border, x_after_update_window_line): Adjust
34 arguments to x_clear_area.
35 (x_draw_fringe_bitmap): Call x_fill_rectangle. Get GC values and
36 call x_cr_draw_image for cairo. Call x_reset_clip_rectangles instead
37 of XSetClipMask.
38 (x_set_glyph_string_clipping)
39 (x_set_glyph_string_clipping_exactly): Use x_set_clip_rectangles
40 instead of XSetClipRectangles.
41 (x_clear_glyph_string_rect, x_draw_glyph_string_background): Use
42 x_fill_rectangle instead of XFillRectangle.
43 (x_draw_glyph_string_foreground)
44 (x_draw_composite_glyph_string_foreground)
45 (x_draw_glyphless_glyph_string_foreground): Use x_draw_rectangle instead
46 of XDrawRectangle.
47 (x_draw_relief_rect): Add code for USE_CAIRO.
48 Call x_reset_clip_rectangles instead of XSetClipMask.
49 (x_draw_box_rect): x_set_clip_rectangles instead of XSetClipRectangles,
50 x_fill_rectangle instead of XFillRectangle, x_reset_clip_rectangles
51 instead of XSetClipMask.
52 (x_draw_image_foreground, x_draw_image_foreground_1):
53 x_draw_rectangle instead of XDrawRectangle.
54 (x_draw_glyph_string_bg_rect): x_fill_rectangle instead of
55 XFillRectangle.
56 (x_draw_image_glyph_string): If img has cr_data, use it as
57 a cairo surface.
58 (x_draw_stretch_glyph_string): x_set_clip_rectangles instead of
59 XSetClipRectangles, x_fill_rectangle instead of XFillRectangle.
60 (x_draw_glyph_string): x_fill_rectangle instead of XFillRectangle.,
61 x_reset_clip_rectangles instead of XSetClipMask.
62 (x_shift_glyphs_for_insert): Call x_prepare_for_xlibdraw.
63 (x_clear_area1): New function that calls XClearArea.
64 (x_clear_area): Takes frame as parameter, calls x_clear_area1 for
65 non-cairo.
66 (x_clear_frame): x_clear_window instead of XClearWindow.
67 (x_scroll_run): Set frame garbaged if cairo.
68 (XTmouse_position): Initialize *part to 0.
69 (x_scroll_bar_create): Adjust arguments to x_clear_area.
70 (x_scroll_bar_set_handle): x_clear_area1 instead of x_clear_area,
71 x_fill_rectangle instead of XFillRectangle.
72 (XTset_vertical_scroll_bar, XTset_horizontal_scroll_bar): Adjust
73 arguments to x_clear_area.
74 (x_scroll_bar_expose): x_draw_rectangle instead of XDrawRectangle.
75 (handle_one_xevent): Adjust arguments to x_clear_area.
76 Destroy cairo surface for frame if ConfigureNotify.
77 (x_clip_to_row): x_set_clip_rectangles instead of XSetClipRectangles.
78 (x_draw_hollow_cursor): x_draw_rectangle instead of XDrawRectangle,
79 x_reset_clip_rectangles instead of XSetClipMask.
80 (x_draw_bar_cursor): x_fill_rectangle instead of XFillRectangle,
81 x_reset_clip_rectangles instead of XSetClipMask.
82 (x_clear_frame_area): Adjust arguments to x_clear_area.
83 (x_free_frame_resources): Call x_prepare_for_xlibdraw.
84 (x_term_init): Call x_extension_initialize if cairo.
85 (x_redisplay_interface): Add x_cr_define_fringe_bitmap,
86 x_cr_destroy_fringe_bitmap for cairo.
87 (x_initialize): Call x_cr_init_fringe for cairo.
88
89 * xfns.c: New section Printing.
90 (x-export-frames, x-page-setup-dialog, x-get-page-setup)
91 (x-print-frames-dialog): New printing functions.
92 (Fx_create_frame, x_create_tip_frame): Register ftcrfont if
93 cairo.
94 (syms_of_xfns): Defsym Qorientation, Qtop_margin, Qbottom_margin,
95 Qportrait, Qlandscape, Qreverse_portrait, Qreverse_landscape).
96 (syms_of_xfns): Provide cairo and defvar cairo-version-string.
97 defsubr Sx_page_setup_dialog, Sx_get_page_setup, Sx_print_frames_dialog.
98
99 * image.c: Add defined (USE_CAIRO) for PNG.
100 Add !defined USE_CAIRO for W32 PNG code.
101 (x_clear_image): If cairo, destroy the surface in cr_data.
102 (png_load): Add new cairo compatible implementation.
103 (lookup_image_type): Add defined (USE_CAIRO) for define png_type.
104
105 * gtkutil.h (xg_page_setup_dialog, xg_get_page_setup)
106 (xg_print_frames_dialog): Declare.
107
108 * gtkutil.c (xg_clear_under_internal_border)
109 (xg_update_scrollbar_pos, xg_update_horizontal_scrollbar_pos): Only
110 queue_draw if not cairo. Change args to x_clear_area.
111 (xg_get_font): Use Qftcr when using cairo, Qxft otherwise.
112 (xg_page_setup_dialog, xg_get_page_setup, draw_page)
113 (xg_print_frames_dialog): New functions for printing.
114
115 * ftfont.h (ftfont_open2, ftfont_info_size): Declare.
116
117 * ftfont.c (ftfont_info_size); New global variable.
118 (ftfont_open2): New extern function almost the same as old ftfont_open,
119 but takes the font_object as argument.
120 (ftfont_open): Build font object and call ftfont_open2.
121
122 * ftcrfont.c: New font driver for cairo, based on the ftfont driver.
123
124 * fringe.c (x_cr_init_fringe): New function name that shares code
125 with w32_init_fringe.
126
127 * font.h (ftcrfont_driver, syms_of_ftcrfont): Declare
128
129 * font.c (syms_of_font): Call syms_of_ftcrfont for cairo.
130
131 * dispextern.h (struct image): Add cr_data for cairo.
132 (x_cr_init_fringe): Declare.
133
134 * Makefile.in (CAIRO_CFLAGS, CAIRO_LIBS): New variables.
135 (FONT_OBJ): Add comment about ftcrfont.
136 (ALL_CFLAGS): Add CAIRO_CFLAGS.
137 (LIBES): Add CAIRO_LIBS.
138
12015-02-11 Martin Rudalics <rudalics@gmx.at> 1392015-02-11 Martin Rudalics <rudalics@gmx.at>
2 140
3 * w32term.c (w32_read_socket): In SIZE_MAXIMIZED and 141 * w32term.c (w32_read_socket): In SIZE_MAXIMIZED and
diff --git a/src/Makefile.in b/src/Makefile.in
index 32615c848a7..9e7a8a79915 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -218,6 +218,9 @@ CFLAGS_SOUND= @CFLAGS_SOUND@
218RSVG_LIBS= @RSVG_LIBS@ 218RSVG_LIBS= @RSVG_LIBS@
219RSVG_CFLAGS= @RSVG_CFLAGS@ 219RSVG_CFLAGS= @RSVG_CFLAGS@
220 220
221CAIRO_LIBS= @CAIRO_LIBS@
222CAIRO_CFLAGS= @CAIRO_CFLAGS@
223
221IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@ 224IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@
222IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@ 225IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@
223 226
@@ -273,6 +276,7 @@ W32_RES_LINK=@W32_RES_LINK@
273## Empty if !HAVE_X_WINDOWS 276## Empty if !HAVE_X_WINDOWS
274## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT 277## xfont.o ftfont.o xftfont.o ftxfont.o if HAVE_XFT
275## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE 278## xfont.o ftfont.o ftxfont.o if HAVE_FREETYPE
279## ftfont.o ftcrfont.o if USE_CAIRO
276## else xfont.o 280## else xfont.o
277FONT_OBJ=@FONT_OBJ@ 281FONT_OBJ=@FONT_OBJ@
278 282
@@ -345,7 +349,7 @@ ALL_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
345 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \ 349 $(XRANDR_CFLAGS) $(XINERAMA_CFLAGS) $(XFIXES_CFLAGS) \
346 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \ 350 $(SETTINGS_CFLAGS) $(FREETYPE_CFLAGS) $(FONTCONFIG_CFLAGS) \
347 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \ 351 $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
348 $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) \ 352 $(LIBGNUTLS_CFLAGS) $(GFILENOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
349 $(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS) 353 $(WARN_CFLAGS) $(WERROR_CFLAGS) $(CFLAGS)
350ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS) 354ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS)
351 355
@@ -423,7 +427,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
423 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \ 427 $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
424 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \ 428 $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
425 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \ 429 $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) $(XFIXES_LIBS) \
426 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \ 430 $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) $(CAIRO_LIBS) \
427 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \ 431 $(LIBS_TERMCAP) $(GETLOADAVG_LIBS) $(SETTINGS_LIBS) $(LIBSELINUX_LIBS) \
428 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \ 432 $(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
429 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \ 433 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) \
diff --git a/src/dispextern.h b/src/dispextern.h
index 5f730df514b..b9db3f808b5 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2939,6 +2939,9 @@ struct image
2939 /* Pixmaps of the image. */ 2939 /* Pixmaps of the image. */
2940 Pixmap pixmap, mask; 2940 Pixmap pixmap, mask;
2941 2941
2942#ifdef USE_CAIRO
2943 void *cr_data;
2944#endif
2942#ifdef HAVE_X_WINDOWS 2945#ifdef HAVE_X_WINDOWS
2943 /* X images of the image, corresponding to the above Pixmaps. 2946 /* X images of the image, corresponding to the above Pixmaps.
2944 Non-NULL means it and its Pixmap counterpart may be out of sync 2947 Non-NULL means it and its Pixmap counterpart may be out of sync
@@ -3300,6 +3303,9 @@ bool update_window_fringes (struct window *, bool);
3300void w32_init_fringe (struct redisplay_interface *); 3303void w32_init_fringe (struct redisplay_interface *);
3301void w32_reset_fringes (void); 3304void w32_reset_fringes (void);
3302#endif 3305#endif
3306#ifdef USE_CAIRO
3307void x_cr_init_fringe (struct redisplay_interface *);
3308#endif
3303 3309
3304extern unsigned row_hash (struct glyph_row *); 3310extern unsigned row_hash (struct glyph_row *);
3305 3311
diff --git a/src/font.c b/src/font.c
index b2b43c79713..603e998ed3f 100644
--- a/src/font.c
+++ b/src/font.c
@@ -5280,11 +5280,15 @@ EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5280#ifdef HAVE_FREETYPE 5280#ifdef HAVE_FREETYPE
5281 syms_of_ftfont (); 5281 syms_of_ftfont ();
5282#ifdef HAVE_X_WINDOWS 5282#ifdef HAVE_X_WINDOWS
5283#ifdef USE_CAIRO
5284 syms_of_ftcrfont ();
5285#else
5283 syms_of_xfont (); 5286 syms_of_xfont ();
5284 syms_of_ftxfont (); 5287 syms_of_ftxfont ();
5285#ifdef HAVE_XFT 5288#ifdef HAVE_XFT
5286 syms_of_xftfont (); 5289 syms_of_xftfont ();
5287#endif /* HAVE_XFT */ 5290#endif /* HAVE_XFT */
5291#endif /* not USE_CAIRO */
5288#endif /* HAVE_X_WINDOWS */ 5292#endif /* HAVE_X_WINDOWS */
5289#else /* not HAVE_FREETYPE */ 5293#else /* not HAVE_FREETYPE */
5290#ifdef HAVE_X_WINDOWS 5294#ifdef HAVE_X_WINDOWS
diff --git a/src/font.h b/src/font.h
index efc184eef77..43e67e98c06 100644
--- a/src/font.h
+++ b/src/font.h
@@ -844,6 +844,10 @@ extern struct font_driver nsfont_driver;
844extern void syms_of_nsfont (void); 844extern void syms_of_nsfont (void);
845extern void syms_of_macfont (void); 845extern void syms_of_macfont (void);
846#endif /* HAVE_NS */ 846#endif /* HAVE_NS */
847#ifdef USE_CAIRO
848extern struct font_driver ftcrfont_driver;
849extern void syms_of_ftcrfont (void);
850#endif
847 851
848#ifndef FONT_DEBUG 852#ifndef FONT_DEBUG
849#define FONT_DEBUG 853#define FONT_DEBUG
diff --git a/src/fringe.c b/src/fringe.c
index 5e5ec60a48f..27b10035556 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -1731,10 +1731,14 @@ init_fringe (void)
1731 fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces); 1731 fringe_faces = xzalloc (max_fringe_bitmaps * sizeof *fringe_faces);
1732} 1732}
1733 1733
1734#ifdef HAVE_NTGUI 1734#if defined (HAVE_NTGUI) || defined (USE_CAIRO)
1735 1735
1736void 1736void
1737#ifdef HAVE_NTGUI
1737w32_init_fringe (struct redisplay_interface *rif) 1738w32_init_fringe (struct redisplay_interface *rif)
1739#else
1740x_cr_init_fringe (struct redisplay_interface *rif)
1741#endif
1738{ 1742{
1739 int bt; 1743 int bt;
1740 1744
@@ -1747,7 +1751,9 @@ w32_init_fringe (struct redisplay_interface *rif)
1747 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width); 1751 rif->define_fringe_bitmap (bt, fb->bits, fb->height, fb->width);
1748 } 1752 }
1749} 1753}
1754#endif
1750 1755
1756#ifdef HAVE_NTGUI
1751void 1757void
1752w32_reset_fringes (void) 1758w32_reset_fringes (void)
1753{ 1759{
diff --git a/src/ftcrfont.c b/src/ftcrfont.c
new file mode 100644
index 00000000000..d60c1202b9d
--- /dev/null
+++ b/src/ftcrfont.c
@@ -0,0 +1,314 @@
1/* ftcrfont.c -- FreeType font driver on cairo.
2 Copyright (C) 2015 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
18
19
20#include <config.h>
21#include <stdio.h>
22#include <cairo-ft.h>
23
24#include "lisp.h"
25#include "dispextern.h"
26#include "xterm.h"
27#include "frame.h"
28#include "blockinput.h"
29#include "character.h"
30#include "charset.h"
31#include "fontset.h"
32#include "font.h"
33#include "ftfont.h"
34
35/* FTCR font driver. */
36
37/* The actual structure for ftcr font that can be casted to struct
38 font. */
39
40struct ftcrfont_info
41{
42 struct font font;
43 /* The following six members must be here in this order to be
44 compatible with struct ftfont_info (in ftfont.c). */
45#ifdef HAVE_LIBOTF
46 bool maybe_otf; /* Flag to tell if this may be OTF or not. */
47 OTF *otf;
48#endif /* HAVE_LIBOTF */
49 FT_Size ft_size;
50 int index;
51 FT_Matrix matrix;
52
53 cairo_font_face_t *cr_font_face;
54 /* To prevent cairo from cluttering the activated FT_Size maintained
55 in ftfont.c, we activate this special FT_Size before drawing. */
56 FT_Size ft_size_draw;
57 /* Font metrics cache. */
58 struct font_metrics **metrics;
59 short metrics_nrows;
60};
61
62#define METRICS_NCOLS_PER_ROW (128)
63
64enum metrics_status
65 {
66 METRICS_INVALID = -1, /* metrics entry is invalid */
67 };
68
69#define METRICS_STATUS(metrics) ((metrics)->ascent + (metrics)->descent)
70#define METRICS_SET_STATUS(metrics, status) \
71 ((metrics)->ascent = 0, (metrics)->descent = (status))
72
73/* Prototypes for helper function. */
74static int ftcrfont_glyph_extents (struct font *, unsigned,
75 struct font_metrics *);
76
77/* Prototypes for font-driver methods. */
78static Lisp_Object ftcrfont_list (struct frame*, Lisp_Object);
79static Lisp_Object ftcrfont_match (struct frame*, Lisp_Object);
80static Lisp_Object ftcrfont_open (struct frame*, Lisp_Object, int);
81static void ftcrfont_close (struct font *);
82static void ftcrfont_text_extents (struct font *, unsigned *, int,
83 struct font_metrics *);
84static int ftcrfont_draw (struct glyph_string *, int, int, int, int, bool);
85
86struct font_driver ftcrfont_driver;
87
88static int
89ftcrfont_glyph_extents (struct font *font,
90 unsigned glyph,
91 struct font_metrics *metrics)
92{
93 struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font;
94 int row, col;
95 struct font_metrics *cache;
96
97 row = glyph / METRICS_NCOLS_PER_ROW;
98 col = glyph % METRICS_NCOLS_PER_ROW;
99 if (row >= ftcrfont_info->metrics_nrows)
100 {
101 ftcrfont_info->metrics =
102 xrealloc (ftcrfont_info->metrics,
103 sizeof (struct font_metrics *) * (row + 1));
104 bzero (ftcrfont_info->metrics + ftcrfont_info->metrics_nrows,
105 (sizeof (struct font_metrics *)
106 * (row + 1 - ftcrfont_info->metrics_nrows)));
107 ftcrfont_info->metrics_nrows = row + 1;
108 }
109 if (ftcrfont_info->metrics[row] == NULL)
110 {
111 struct font_metrics *new;
112 int i;
113
114 new = xmalloc (sizeof (struct font_metrics) * METRICS_NCOLS_PER_ROW);
115 for (i = 0; i < METRICS_NCOLS_PER_ROW; i++)
116 METRICS_SET_STATUS (new + i, METRICS_INVALID);
117 ftcrfont_info->metrics[row] = new;
118 }
119 cache = ftcrfont_info->metrics[row] + col;
120
121 if (METRICS_STATUS (cache) == METRICS_INVALID)
122 ftfont_driver.text_extents (font, &glyph, 1, cache);
123
124 if (metrics)
125 *metrics = *cache;
126
127 return cache->width;
128}
129
130static Lisp_Object
131ftcrfont_list (struct frame *f, Lisp_Object spec)
132{
133 Lisp_Object list = ftfont_driver.list (f, spec), tail;
134
135 for (tail = list; CONSP (tail); tail = XCDR (tail))
136 ASET (XCAR (tail), FONT_TYPE_INDEX, Qftcr);
137 return list;
138}
139
140static Lisp_Object
141ftcrfont_match (struct frame *f, Lisp_Object spec)
142{
143 Lisp_Object entity = ftfont_driver.match (f, spec);
144
145 if (VECTORP (entity))
146 ASET (entity, FONT_TYPE_INDEX, Qftcr);
147 return entity;
148}
149
150extern FT_Face ftfont_get_ft_face (Lisp_Object);
151
152static Lisp_Object
153ftcrfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
154{
155 Lisp_Object font_object;
156 struct font *font;
157 struct ftcrfont_info *ftcrfont_info;
158 FT_Face ft_face;
159 FT_UInt size;
160
161 block_input ();
162 size = XINT (AREF (entity, FONT_SIZE_INDEX));
163 if (size == 0)
164 size = pixel_size;
165 font_object = font_build_object (VECSIZE (struct ftcrfont_info),
166 Qftcr, entity, size);
167 font_object = ftfont_open2 (f, entity, pixel_size, font_object);
168 if (NILP (font_object)) return Qnil;
169
170 font = XFONT_OBJECT (font_object);
171 font->driver = &ftcrfont_driver;
172 ftcrfont_info = (struct ftcrfont_info *) font;
173 ft_face = ftcrfont_info->ft_size->face;
174 FT_New_Size (ft_face, &ftcrfont_info->ft_size_draw);
175 FT_Activate_Size (ftcrfont_info->ft_size_draw);
176 FT_Set_Pixel_Sizes (ft_face, 0, font->pixel_size);
177 ftcrfont_info->cr_font_face =
178 cairo_ft_font_face_create_for_ft_face (ft_face, 0);
179 ftcrfont_info->metrics = NULL;
180 ftcrfont_info->metrics_nrows = 0;
181 unblock_input ();
182
183 return font_object;
184}
185
186static void
187ftcrfont_close (struct font *font)
188{
189 struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) font;
190 int i;
191
192 block_input ();
193 for (i = 0; i < ftcrfont_info->metrics_nrows; i++)
194 if (ftcrfont_info->metrics[i])
195 xfree (ftcrfont_info->metrics[i]);
196 if (ftcrfont_info->metrics)
197 xfree (ftcrfont_info->metrics);
198 FT_Done_Size (ftcrfont_info->ft_size_draw);
199 cairo_font_face_destroy (ftcrfont_info->cr_font_face);
200 unblock_input ();
201
202 ftfont_driver.close (font);
203}
204
205static void
206ftcrfont_text_extents (struct font *font,
207 unsigned *code,
208 int nglyphs,
209 struct font_metrics *metrics)
210{
211 int width, i;
212
213 block_input ();
214 width = ftcrfont_glyph_extents (font, code[0], metrics);
215 for (i = 1; i < nglyphs; i++)
216 {
217 struct font_metrics m;
218 int w = ftcrfont_glyph_extents (font, code[i], metrics ? &m : NULL);
219
220 if (metrics)
221 {
222 if (width + m.lbearing < metrics->lbearing)
223 metrics->lbearing = width + m.lbearing;
224 if (width + m.rbearing > metrics->rbearing)
225 metrics->rbearing = width + m.rbearing;
226 if (m.ascent > metrics->ascent)
227 metrics->ascent = m.ascent;
228 if (m.descent > metrics->descent)
229 metrics->descent = m.descent;
230 }
231 width += w;
232 }
233 unblock_input ();
234
235 if (metrics)
236 metrics->width = width;
237}
238
239static int
240ftcrfont_draw (struct glyph_string *s,
241 int from, int to, int x, int y, bool with_background)
242{
243 struct frame *f = s->f;
244 struct face *face = s->face;
245 struct ftcrfont_info *ftcrfont_info = (struct ftcrfont_info *) s->font;
246 cairo_t *cr;
247 cairo_glyph_t *glyphs;
248 cairo_surface_t *surface;
249 int len = to - from;
250 int i;
251
252 block_input ();
253
254 cr = x_begin_cr_clip (f, s->gc);
255
256 if (with_background)
257 {
258 x_set_cr_source_with_gc_background (f, s->gc);
259 cairo_rectangle (cr, x, y - FONT_BASE (face->font),
260 s->width, FONT_HEIGHT (face->font));
261 cairo_fill (cr);
262 }
263
264 glyphs = alloca (sizeof (cairo_glyph_t) * len);
265 for (i = 0; i < len; i++)
266 {
267 unsigned code = ((XCHAR2B_BYTE1 (s->char2b + from + i) << 8)
268 | XCHAR2B_BYTE2 (s->char2b + from + i));
269
270 glyphs[i].index = code;
271 glyphs[i].x = x;
272 glyphs[i].y = y;
273 x += (s->padding_p ? 1 : ftcrfont_glyph_extents (s->font, code, NULL));
274 }
275
276 x_set_cr_source_with_gc_foreground (f, s->gc);
277 cairo_set_font_face (cr, ftcrfont_info->cr_font_face);
278 cairo_set_font_size (cr, s->font->pixel_size);
279 /* cairo_set_font_matrix */
280 /* cairo_set_font_options */
281
282 FT_Activate_Size (ftcrfont_info->ft_size_draw);
283 cairo_show_glyphs (cr, glyphs, len);
284 surface = cairo_get_target (cr);
285 if (cairo_surface_get_type (surface) != CAIRO_SURFACE_TYPE_XLIB)
286 cairo_surface_flush (surface);
287
288 x_end_cr_clip (f);
289
290 unblock_input ();
291
292 return len;
293}
294
295
296
297void
298syms_of_ftcrfont (void)
299{
300 if (ftfont_info_size != offsetof (struct ftcrfont_info, cr_font_face))
301 abort ();
302
303 DEFSYM (Qftcr, "ftcr");
304
305 ftcrfont_driver = ftfont_driver;
306 ftcrfont_driver.type = Qftcr;
307 ftcrfont_driver.list = ftcrfont_list;
308 ftcrfont_driver.match = ftcrfont_match;
309 ftcrfont_driver.open = ftcrfont_open;
310 ftcrfont_driver.close = ftcrfont_close;
311 ftcrfont_driver.text_extents = ftcrfont_text_extents;
312 ftcrfont_driver.draw = ftcrfont_draw;
313 register_font_driver (&ftcrfont_driver, NULL);
314}
diff --git a/src/ftfont.c b/src/ftfont.c
index adf188815de..75d59c16294 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -67,6 +67,8 @@ struct ftfont_info
67 FT_Matrix matrix; 67 FT_Matrix matrix;
68}; 68};
69 69
70size_t ftfont_info_size = sizeof (struct ftfont_info);
71
70enum ftfont_cache_for 72enum ftfont_cache_for
71 { 73 {
72 FTFONT_CACHE_FOR_FACE, 74 FTFONT_CACHE_FOR_FACE,
@@ -1161,8 +1163,11 @@ ftfont_list_family (struct frame *f)
1161} 1163}
1162 1164
1163 1165
1164static Lisp_Object 1166Lisp_Object
1165ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) 1167ftfont_open2 (struct frame *f,
1168 Lisp_Object entity,
1169 int pixel_size,
1170 Lisp_Object font_object)
1166{ 1171{
1167 struct ftfont_info *ftfont_info; 1172 struct ftfont_info *ftfont_info;
1168 struct font *font; 1173 struct font *font;
@@ -1170,7 +1175,7 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1170 FT_Face ft_face; 1175 FT_Face ft_face;
1171 FT_Size ft_size; 1176 FT_Size ft_size;
1172 FT_UInt size; 1177 FT_UInt size;
1173 Lisp_Object val, filename, idx, cache, font_object; 1178 Lisp_Object val, filename, idx, cache;
1174 bool scalable; 1179 bool scalable;
1175 int spacing; 1180 int spacing;
1176 int i; 1181 int i;
@@ -1210,8 +1215,6 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1210 return Qnil; 1215 return Qnil;
1211 } 1216 }
1212 1217
1213 font_object = font_build_object (VECSIZE (struct ftfont_info),
1214 Qfreetype, entity, size);
1215 ASET (font_object, FONT_FILE_INDEX, filename); 1218 ASET (font_object, FONT_FILE_INDEX, filename);
1216 font = XFONT_OBJECT (font_object); 1219 font = XFONT_OBJECT (font_object);
1217 ftfont_info = (struct ftfont_info *) font; 1220 ftfont_info = (struct ftfont_info *) font;
@@ -1294,6 +1297,19 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1294 return font_object; 1297 return font_object;
1295} 1298}
1296 1299
1300static Lisp_Object
1301ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
1302{
1303 Lisp_Object font_object;
1304 FT_UInt size;
1305 size = XINT (AREF (entity, FONT_SIZE_INDEX));
1306 if (size == 0)
1307 size = pixel_size;
1308 font_object = font_build_object (VECSIZE (struct ftfont_info),
1309 Qfreetype, entity, size);
1310 return ftfont_open2 (f, entity, pixel_size, font_object);
1311}
1312
1297static void 1313static void
1298ftfont_close (struct font *font) 1314ftfont_close (struct font *font)
1299{ 1315{
diff --git a/src/ftfont.h b/src/ftfont.h
index 210b634c094..0cfa0ae3e33 100644
--- a/src/ftfont.h
+++ b/src/ftfont.h
@@ -37,6 +37,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
37#endif /* HAVE_LIBOTF */ 37#endif /* HAVE_LIBOTF */
38 38
39extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); 39extern FcCharSet *ftfont_get_fc_charset (Lisp_Object);
40extern Lisp_Object ftfont_open2 (struct frame *f,
41 Lisp_Object entity,
42 int pixel_size,
43 Lisp_Object font_object);
44extern size_t ftfont_info_size;
40 45
41#endif /* EMACS_FTFONT_H */ 46#endif /* EMACS_FTFONT_H */
42 47
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 6f1707894c1..f111ea80cef 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -845,22 +845,23 @@ xg_clear_under_internal_border (struct frame *f)
845{ 845{
846 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) 846 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
847 { 847 {
848#ifndef USE_CAIRO
848 GtkWidget *wfixed = f->output_data.x->edit_widget; 849 GtkWidget *wfixed = f->output_data.x->edit_widget;
849 850
850 gtk_widget_queue_draw (wfixed); 851 gtk_widget_queue_draw (wfixed);
851 gdk_window_process_all_updates (); 852 gdk_window_process_all_updates ();
852 853#endif
853 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 0, 854 x_clear_area (f, 0, 0,
854 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); 855 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
855 856
856 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 0, 857 x_clear_area (f, 0, 0,
857 FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); 858 FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
858 859
859 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, 860 x_clear_area (f, 0,
860 FRAME_PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f), 861 FRAME_PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f),
861 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f)); 862 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
862 863
863 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 864 x_clear_area (f,
864 FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f), 865 FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f),
865 0, FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f)); 866 0, FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
866 } 867 }
@@ -2125,12 +2126,18 @@ xg_get_font (struct frame *f, const char *default_name)
2125 PangoWeight weight = pango_font_description_get_weight (desc); 2126 PangoWeight weight = pango_font_description_get_weight (desc);
2126 PangoStyle style = pango_font_description_get_style (desc); 2127 PangoStyle style = pango_font_description_get_style (desc);
2127 2128
2129#ifdef USE_CAIRO
2130#define FONT_TYPE_WANTED (Qftcr)
2131#else
2132#define FONT_TYPE_WANTED (Qxft)
2133#endif
2128 font = CALLN (Ffont_spec, 2134 font = CALLN (Ffont_spec,
2129 QCname, build_string (name), 2135 QCname, build_string (name),
2130 QCsize, make_float (pango_units_to_double (size)), 2136 QCsize, make_float (pango_units_to_double (size)),
2131 QCweight, XG_WEIGHT_TO_SYMBOL (weight), 2137 QCweight, XG_WEIGHT_TO_SYMBOL (weight),
2132 QCslant, XG_STYLE_TO_SYMBOL (style), 2138 QCslant, XG_STYLE_TO_SYMBOL (style),
2133 QCtype, Qxft); 2139 QCtype,
2140 FONT_TYPE_WANTED);
2134 2141
2135 pango_font_description_free (desc); 2142 pango_font_description_free (desc);
2136 dupstring (&x_last_font_name, name); 2143 dupstring (&x_last_font_name, name);
@@ -3784,13 +3791,15 @@ xg_update_scrollbar_pos (struct frame *f,
3784 gtk_widget_show_all (wparent); 3791 gtk_widget_show_all (wparent);
3785 gtk_widget_set_size_request (wscroll, width, height); 3792 gtk_widget_set_size_request (wscroll, width, height);
3786 } 3793 }
3794#ifndef USE_CAIRO
3787 gtk_widget_queue_draw (wfixed); 3795 gtk_widget_queue_draw (wfixed);
3788 gdk_window_process_all_updates (); 3796 gdk_window_process_all_updates ();
3797#endif
3789 if (oldx != -1 && oldw > 0 && oldh > 0) 3798 if (oldx != -1 && oldw > 0 && oldh > 0)
3790 /* Clear under old scroll bar position. This must be done after 3799 /* Clear under old scroll bar position. This must be done after
3791 the gtk_widget_queue_draw and gdk_window_process_all_updates 3800 the gtk_widget_queue_draw and gdk_window_process_all_updates
3792 above. */ 3801 above. */
3793 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3802 x_clear_area (f,
3794 oldx, oldy, oldw, oldh); 3803 oldx, oldy, oldw, oldh);
3795 3804
3796 /* GTK does not redraw until the main loop is entered again, but 3805 /* GTK does not redraw until the main loop is entered again, but
@@ -3856,7 +3865,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
3856 /* Clear under old scroll bar position. This must be done after 3865 /* Clear under old scroll bar position. This must be done after
3857 the gtk_widget_queue_draw and gdk_window_process_all_updates 3866 the gtk_widget_queue_draw and gdk_window_process_all_updates
3858 above. */ 3867 above. */
3859 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3868 x_clear_area (f,
3860 oldx, oldy, oldw, oldh); 3869 oldx, oldy, oldw, oldh);
3861 3870
3862 /* GTK does not redraw until the main loop is entered again, but 3871 /* GTK does not redraw until the main loop is entered again, but
@@ -4033,6 +4042,112 @@ xg_event_is_for_scrollbar (struct frame *f, const XEvent *event)
4033 return retval; 4042 return retval;
4034} 4043}
4035 4044
4045
4046/***********************************************************************
4047 Printing
4048 ***********************************************************************/
4049#ifdef USE_CAIRO
4050static GtkPrintSettings *print_settings = NULL;
4051static GtkPageSetup *page_setup = NULL;
4052
4053void
4054xg_page_setup_dialog ()
4055{
4056 GtkPageSetup *new_page_setup = NULL;
4057
4058 if (print_settings == NULL)
4059 print_settings = gtk_print_settings_new ();
4060 new_page_setup = gtk_print_run_page_setup_dialog (NULL, page_setup,
4061 print_settings);
4062 if (page_setup)
4063 g_object_unref (page_setup);
4064 page_setup = new_page_setup;
4065}
4066
4067Lisp_Object
4068xg_get_page_setup ()
4069{
4070 Lisp_Object result, orientation_symbol;
4071 GtkPageOrientation orientation;
4072
4073 if (page_setup == NULL)
4074 page_setup = gtk_page_setup_new ();
4075 result = list4 (Fcons (Qleft_margin,
4076 make_float (gtk_page_setup_get_left_margin (page_setup,
4077 GTK_UNIT_POINTS))),
4078 Fcons (Qright_margin,
4079 make_float (gtk_page_setup_get_right_margin (page_setup,
4080 GTK_UNIT_POINTS))),
4081 Fcons (Qtop_margin,
4082 make_float (gtk_page_setup_get_top_margin (page_setup,
4083 GTK_UNIT_POINTS))),
4084 Fcons (Qbottom_margin,
4085 make_float (gtk_page_setup_get_bottom_margin (page_setup,
4086 GTK_UNIT_POINTS))));
4087 result = Fcons (Fcons (Qheight,
4088 make_float (gtk_page_setup_get_page_height (page_setup,
4089 GTK_UNIT_POINTS))),
4090 result);
4091 result = Fcons (Fcons (Qwidth,
4092 make_float (gtk_page_setup_get_page_width (page_setup,
4093 GTK_UNIT_POINTS))),
4094 result);
4095 orientation = gtk_page_setup_get_orientation (page_setup);
4096 if (orientation == GTK_PAGE_ORIENTATION_PORTRAIT)
4097 orientation_symbol = Qportrait;
4098 else if (orientation == GTK_PAGE_ORIENTATION_LANDSCAPE)
4099 orientation_symbol = Qlandscape;
4100 else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_PORTRAIT)
4101 orientation_symbol = Qreverse_portrait;
4102 else if (orientation == GTK_PAGE_ORIENTATION_REVERSE_LANDSCAPE)
4103 orientation_symbol = Qreverse_landscape;
4104 result = Fcons (Fcons (Qorientation, orientation_symbol), result);
4105
4106 return result;
4107}
4108
4109static void
4110draw_page (operation, context, page_nr, user_data)
4111 GtkPrintOperation *operation;
4112 GtkPrintContext *context;
4113 gint page_nr;
4114 gpointer user_data;
4115{
4116 Lisp_Object frames = *((Lisp_Object *) user_data);
4117 struct frame *f = XFRAME (Fnth (make_number (page_nr), frames));
4118 cairo_t *cr = gtk_print_context_get_cairo_context (context);
4119
4120 x_cr_draw_frame (cr, f);
4121}
4122
4123void
4124xg_print_frames_dialog (frames)
4125 Lisp_Object frames;
4126{
4127 GtkPrintOperation *print;
4128 GtkPrintOperationResult res;
4129
4130 print = gtk_print_operation_new ();
4131 if (print_settings != NULL)
4132 gtk_print_operation_set_print_settings (print, print_settings);
4133 if (page_setup != NULL)
4134 gtk_print_operation_set_default_page_setup (print, page_setup);
4135 gtk_print_operation_set_n_pages (print, XINT (Flength (frames)));
4136 g_signal_connect (print, "draw-page", G_CALLBACK (draw_page), &frames);
4137 res = gtk_print_operation_run (print, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
4138 NULL, NULL);
4139 if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
4140 {
4141 if (print_settings != NULL)
4142 g_object_unref (print_settings);
4143 print_settings =
4144 g_object_ref (gtk_print_operation_get_print_settings (print));
4145 }
4146 g_object_unref (print);
4147}
4148
4149#endif /* USE_CAIRO */
4150
4036 4151
4037 4152
4038/*********************************************************************** 4153/***********************************************************************
diff --git a/src/gtkutil.h b/src/gtkutil.h
index 0ac49ca7db5..34338db58fb 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -180,6 +180,12 @@ extern bool xg_prepare_tooltip (struct frame *f,
180extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); 180extern void xg_show_tooltip (struct frame *f, int root_x, int root_y);
181extern bool xg_hide_tooltip (struct frame *f); 181extern bool xg_hide_tooltip (struct frame *f);
182 182
183#ifdef USE_CAIRO
184extern void xg_page_setup_dialog (void);
185extern Lisp_Object xg_get_page_setup (void);
186extern void xg_print_frames_dialog (Lisp_Object);
187#endif
188
183/* Mark all callback data that are Lisp_object:s during GC. */ 189/* Mark all callback data that are Lisp_object:s during GC. */
184extern void xg_mark_data (void); 190extern void xg_mark_data (void);
185 191
diff --git a/src/image.c b/src/image.c
index df299bbd164..09d068725d7 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1299,6 +1299,14 @@ static void
1299x_clear_image (struct frame *f, struct image *img) 1299x_clear_image (struct frame *f, struct image *img)
1300{ 1300{
1301 block_input (); 1301 block_input ();
1302#ifdef USE_CAIRO
1303 if (img->cr_data)
1304 {
1305 cairo_surface_destroy ((cairo_surface_t *)img->cr_data);
1306 unblock_input ();
1307 return;
1308 }
1309#endif
1302 x_clear_image_1 (f, img, 1310 x_clear_image_1 (f, img,
1303 CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS); 1311 CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS);
1304 unblock_input (); 1312 unblock_input ();
@@ -5403,7 +5411,7 @@ pbm_load (struct frame *f, struct image *img)
5403 PNG 5411 PNG
5404 ***********************************************************************/ 5412 ***********************************************************************/
5405 5413
5406#if defined (HAVE_PNG) || defined (HAVE_NS) 5414#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
5407 5415
5408/* Function prototypes. */ 5416/* Function prototypes. */
5409 5417
@@ -5477,10 +5485,10 @@ png_image_p (Lisp_Object object)
5477 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1; 5485 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
5478} 5486}
5479 5487
5480#endif /* HAVE_PNG || HAVE_NS */ 5488#endif /* HAVE_PNG || HAVE_NS || USE_CAIRO */
5481 5489
5482 5490
5483#if defined HAVE_PNG && !defined HAVE_NS 5491#if defined HAVE_PNG && !defined HAVE_NS && !defined USE_CAIRO
5484 5492
5485# ifdef WINDOWSNT 5493# ifdef WINDOWSNT
5486/* PNG library details. */ 5494/* PNG library details. */
@@ -6049,7 +6057,44 @@ png_load (struct frame *f, struct image *img)
6049 image_spec_value (img->spec, QCdata, NULL)); 6057 image_spec_value (img->spec, QCdata, NULL));
6050} 6058}
6051 6059
6052#endif /* HAVE_NS */ 6060#elif defined USE_CAIRO
6061
6062static bool
6063png_load (struct frame *f, struct image *img)
6064{
6065 Lisp_Object file;
6066 Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL);
6067 cairo_surface_t *surface;
6068
6069 if (! STRINGP (specified_file))
6070 {
6071 image_error ("Invalid image spec, file missing `%s'", img->spec, Qnil);
6072 return false;
6073 }
6074
6075 file = x_find_image_file (specified_file);
6076 if (! STRINGP (file))
6077 {
6078 image_error ("Cannot find image file `%s'", specified_file, Qnil);
6079 return false;
6080 }
6081
6082 surface = cairo_image_surface_create_from_png (SSDATA (file));
6083 if (! surface)
6084 {
6085 image_error ("Error creating surface from file `%s'",
6086 specified_file, Qnil);
6087 return false;
6088 }
6089 img->width = cairo_image_surface_get_width (surface);
6090 img->height = cairo_image_surface_get_height (surface);
6091 img->cr_data = surface;
6092 img->pixmap = 0;
6093
6094 return true;
6095}
6096
6097#endif /* USE_CAIRO */
6053 6098
6054 6099
6055 6100
@@ -9353,7 +9398,7 @@ lookup_image_type (Lisp_Object type)
9353 return define_image_type (&gif_type); 9398 return define_image_type (&gif_type);
9354#endif 9399#endif
9355 9400
9356#if defined (HAVE_PNG) || defined (HAVE_NS) 9401#if defined (HAVE_PNG) || defined (HAVE_NS) || defined (USE_CAIRO)
9357 if (EQ (type, Qpng)) 9402 if (EQ (type, Qpng))
9358 return define_image_type (&png_type); 9403 return define_image_type (&png_type);
9359#endif 9404#endif
diff --git a/src/xfns.c b/src/xfns.c
index 629ac4b26ff..23af4388e5f 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3052,6 +3052,9 @@ This function is an internal primitive--use `make-frame' instead. */)
3052 specbind (Qx_resource_name, name); 3052 specbind (Qx_resource_name, name);
3053 } 3053 }
3054 3054
3055#ifdef USE_CAIRO
3056 register_font_driver (&ftcrfont_driver, f);
3057#else
3055#ifdef HAVE_FREETYPE 3058#ifdef HAVE_FREETYPE
3056#ifdef HAVE_XFT 3059#ifdef HAVE_XFT
3057 register_font_driver (&xftfont_driver, f); 3060 register_font_driver (&xftfont_driver, f);
@@ -3060,6 +3063,7 @@ This function is an internal primitive--use `make-frame' instead. */)
3060#endif /* not HAVE_XFT */ 3063#endif /* not HAVE_XFT */
3061#endif /* HAVE_FREETYPE */ 3064#endif /* HAVE_FREETYPE */
3062 register_font_driver (&xfont_driver, f); 3065 register_font_driver (&xfont_driver, f);
3066#endif /* not USE_CAIRO */
3063 3067
3064 x_default_parameter (f, parms, Qfont_backend, Qnil, 3068 x_default_parameter (f, parms, Qfont_backend, Qnil,
3065 "fontBackend", "FontBackend", RES_TYPE_STRING); 3069 "fontBackend", "FontBackend", RES_TYPE_STRING);
@@ -5049,6 +5053,9 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
5049 specbind (Qx_resource_name, name); 5053 specbind (Qx_resource_name, name);
5050 } 5054 }
5051 5055
5056#ifdef USE_CAIRO
5057 register_font_driver (&ftcrfont_driver, f);
5058#else
5052 register_font_driver (&xfont_driver, f); 5059 register_font_driver (&xfont_driver, f);
5053#ifdef HAVE_FREETYPE 5060#ifdef HAVE_FREETYPE
5054#ifdef HAVE_XFT 5061#ifdef HAVE_XFT
@@ -5057,6 +5064,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
5057 register_font_driver (&ftxfont_driver, f); 5064 register_font_driver (&ftxfont_driver, f);
5058#endif /* not HAVE_XFT */ 5065#endif /* not HAVE_XFT */
5059#endif /* HAVE_FREETYPE */ 5066#endif /* HAVE_FREETYPE */
5067#endif /* not USE_CAIRO */
5060 5068
5061 x_default_parameter (f, parms, Qfont_backend, Qnil, 5069 x_default_parameter (f, parms, Qfont_backend, Qnil,
5062 "fontBackend", "FontBackend", RES_TYPE_STRING); 5070 "fontBackend", "FontBackend", RES_TYPE_STRING);
@@ -6140,6 +6148,160 @@ present and mapped to the usual X keysyms. */)
6140 6148
6141 6149
6142/*********************************************************************** 6150/***********************************************************************
6151 Printing
6152 ***********************************************************************/
6153
6154#ifdef USE_CAIRO
6155DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0,
6156 doc: /* XXX Experimental. Return image data of FRAMES in TYPE format.
6157FRAMES should be nil (the selected frame), a frame, or a list of
6158frames (each of which corresponds to one page). Optional arg TYPE
6159should be either `pdf' (default), `png', `ps', or `svg'. Supported
6160types are determined by the compile-time configuration of cairo. */)
6161 (frames, type)
6162 Lisp_Object frames, type;
6163{
6164 Lisp_Object result, rest, tmp;
6165 cairo_surface_type_t surface_type;
6166
6167 if (NILP (frames))
6168 frames = selected_frame;
6169 if (!CONSP (frames))
6170 frames = list1 (frames);
6171
6172 tmp = Qnil;
6173 for (rest = frames; CONSP (rest); rest = XCDR (rest))
6174 {
6175 struct frame *f = XFRAME (XCAR (rest));
6176
6177 if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
6178 error ("Invalid frame");
6179
6180 Lisp_Object frame;
6181
6182 XSETFRAME (frame, f);
6183 tmp = Fcons (frame, tmp);
6184 }
6185 frames = Fnreverse (tmp);
6186
6187#ifdef CAIRO_HAS_PDF_SURFACE
6188 if (NILP (type) || EQ (type, intern ("pdf"))) /* XXX: Qpdf */
6189 surface_type = CAIRO_SURFACE_TYPE_PDF;
6190 else
6191#endif
6192#ifdef CAIRO_HAS_PNG_FUNCTIONS
6193 if (EQ (type, intern ("png")))
6194 {
6195 if (!NILP (XCDR (frames)))
6196 error ("PNG export cannot handle multiple frames.");
6197 surface_type = CAIRO_SURFACE_TYPE_IMAGE;
6198 }
6199 else
6200#endif
6201#ifdef CAIRO_HAS_PS_SURFACE
6202 if (EQ (type, intern ("ps")))
6203 surface_type = CAIRO_SURFACE_TYPE_PS;
6204 else
6205#endif
6206#ifdef CAIRO_HAS_SVG_SURFACE
6207 if (EQ (type, intern ("svg")))
6208 {
6209 /* For now, we stick to SVG 1.1. */
6210 if (!NILP (XCDR (frames)))
6211 error ("SVG export cannot handle multiple frames.");
6212 surface_type = CAIRO_SURFACE_TYPE_SVG;
6213 }
6214 else
6215#endif
6216 error ("Unsupported export type");
6217
6218 result = x_cr_export_frames (frames, surface_type);
6219
6220 return result;
6221}
6222
6223#ifdef USE_GTK
6224DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0,
6225 doc: /* Pop up a page setup dialog.
6226The current page setup can be obtained using `x-get-page-setup'. */)
6227 ()
6228{
6229 block_input ();
6230 xg_page_setup_dialog ();
6231 unblock_input ();
6232
6233 return Qnil;
6234}
6235
6236DEFUN ("x-get-page-setup", Fx_get_page_setup, Sx_get_page_setup, 0, 0, 0,
6237 doc: /* Return the value of the current page setup.
6238The return value is an alist containing the following keys:
6239
6240 orientation: page orientation (symbol `portrait', `landscape',
6241 `reverse-portrait', or `reverse-landscape').
6242 width, height: page width/height in points not including margins.
6243 left-margin, right-margin, top-margin, bottom-margin: print margins,
6244 which is the parts of the page that the printer cannot print
6245 on, in points.
6246
6247The paper width can be obtained as the sum of width, left-margin, and
6248right-margin values. Likewise, the paper height is the sum of height,
6249top-margin, and bottom-margin values. */)
6250 ()
6251{
6252 Lisp_Object result;
6253
6254 block_input ();
6255 result = xg_get_page_setup ();
6256 unblock_input ();
6257
6258 return result;
6259}
6260
6261DEFUN ("x-print-frames-dialog", Fx_print_frames_dialog, Sx_print_frames_dialog, 0, 1, "",
6262 doc: /* Pop up a print dialog to print the current contents of FRAMES.
6263FRAMES should be nil (the selected frame), a frame, or a list of
6264frames (each of which corresponds to one page). Each frame should be
6265visible. */)
6266 (frames)
6267 Lisp_Object frames;
6268{
6269 Lisp_Object rest, tmp;
6270
6271 if (NILP (frames))
6272 frames = selected_frame;
6273 if (!CONSP (frames))
6274 frames = list1 (frames);
6275
6276 tmp = Qnil;
6277 for (rest = frames; CONSP (rest); rest = XCDR (rest))
6278 {
6279 struct frame *f = XFRAME (XCAR (rest));
6280 if (! FRAME_LIVE_P (f) || ! FRAME_X_P (f) || ! FRAME_LIVE_P (f))
6281 error ("Invalid frame");
6282 Lisp_Object frame;
6283
6284 XSETFRAME (frame, f);
6285 if (!EQ (Fframe_visible_p (frame), Qt))
6286 error ("Frames to be printed must be visible.");
6287 tmp = Fcons (frame, tmp);
6288 }
6289 frames = Fnreverse (tmp);
6290
6291 /* Make sure the current matrices are up-to-date. */
6292 Fredisplay (Qt);
6293
6294 block_input ();
6295 xg_print_frames_dialog (frames);
6296 unblock_input ();
6297
6298 return Qnil;
6299}
6300#endif /* USE_GTK */
6301#endif /* USE_CAIRO */
6302
6303
6304/***********************************************************************
6143 Initialization 6305 Initialization
6144 ***********************************************************************/ 6306 ***********************************************************************/
6145 6307
@@ -6195,6 +6357,16 @@ syms_of_xfns (void)
6195 DEFSYM (Qcancel_timer, "cancel-timer"); 6357 DEFSYM (Qcancel_timer, "cancel-timer");
6196 DEFSYM (Qfont_param, "font-parameter"); 6358 DEFSYM (Qfont_param, "font-parameter");
6197 6359
6360#ifdef USE_CAIRO
6361 DEFSYM (Qorientation, "orientation");
6362 DEFSYM (Qtop_margin, "top-margin");
6363 DEFSYM (Qbottom_margin, "bottom-margin");
6364 DEFSYM (Qportrait, "portrait");
6365 DEFSYM (Qlandscape, "landscape");
6366 DEFSYM (Qreverse_portrait, "reverse-portrait");
6367 DEFSYM (Qreverse_landscape, "reverse-landscape");
6368#endif
6369
6198 Fput (Qundefined_color, Qerror_conditions, 6370 Fput (Qundefined_color, Qerror_conditions,
6199 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror)); 6371 listn (CONSTYPE_PURE, 2, Qundefined_color, Qerror));
6200 Fput (Qundefined_color, Qerror_message, 6372 Fput (Qundefined_color, Qerror_message,
@@ -6335,6 +6507,20 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
6335 } 6507 }
6336#endif /* USE_GTK */ 6508#endif /* USE_GTK */
6337 6509
6510#ifdef USE_CAIRO
6511 Fprovide (intern_c_string ("cairo"), Qnil);
6512
6513 DEFVAR_LISP ("cairo-version-string", Vcairo_version_string,
6514 doc: /* Version info for cairo. */);
6515 {
6516 char cairo_version[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
6517 int len = sprintf (cairo_version, "%d.%d.%d",
6518 CAIRO_VERSION_MAJOR, CAIRO_VERSION_MINOR,
6519 CAIRO_VERSION_MICRO);
6520 Vcairo_version_string = make_pure_string (cairo_version, len, len, false);
6521 }
6522#endif
6523
6338 /* X window properties. */ 6524 /* X window properties. */
6339 defsubr (&Sx_change_window_property); 6525 defsubr (&Sx_change_window_property);
6340 defsubr (&Sx_delete_window_property); 6526 defsubr (&Sx_delete_window_property);
@@ -6385,4 +6571,13 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
6385#if defined (USE_GTK) && defined (HAVE_FREETYPE) 6571#if defined (USE_GTK) && defined (HAVE_FREETYPE)
6386 defsubr (&Sx_select_font); 6572 defsubr (&Sx_select_font);
6387#endif 6573#endif
6574
6575#ifdef USE_CAIRO
6576 defsubr (&Sx_export_frames);
6577#ifdef USE_GTK
6578 defsubr (&Sx_page_setup_dialog);
6579 defsubr (&Sx_get_page_setup);
6580 defsubr (&Sx_print_frames_dialog);
6581#endif
6582#endif
6388} 6583}
diff --git a/src/xterm.c b/src/xterm.c
index 0b3efe7b4b6..1074862ca3c 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -220,6 +220,7 @@ static int x_io_error_quitter (Display *);
220static struct terminal *x_create_terminal (struct x_display_info *); 220static struct terminal *x_create_terminal (struct x_display_info *);
221static void x_update_end (struct frame *); 221static void x_update_end (struct frame *);
222static void XTframe_up_to_date (struct frame *); 222static void XTframe_up_to_date (struct frame *);
223static void x_clear_area1 (Display *, Window, int, int, int, int, int);
223static void x_clear_frame (struct frame *); 224static void x_clear_frame (struct frame *);
224static _Noreturn void x_ins_del_lines (struct frame *, int, int); 225static _Noreturn void x_ins_del_lines (struct frame *, int, int);
225static void frame_highlight (struct frame *); 226static void frame_highlight (struct frame *);
@@ -325,6 +326,555 @@ record_event (char *locus, int type)
325 326
326#endif 327#endif
327 328
329static void x_prepare_for_xlibdraw (struct frame *);
330static void x_set_clip_rectangles (struct frame *, GC, XRectangle *, int);
331static void x_reset_clip_rectangles (struct frame *, GC);
332static void x_fill_rectangle (struct frame *, GC, int, int,
333 unsigned int, unsigned int);
334static void x_draw_rectangle (struct frame *, GC, int, int,
335 unsigned int, unsigned int);
336static void x_fill_trapezoid_for_relief (struct frame *, GC, int, int,
337 unsigned int, unsigned int, int);
338static void x_clear_window (struct frame *);
339
340#ifdef USE_CAIRO
341static struct x_gc_ext_data *x_gc_get_ext_data (struct frame *, GC, int);
342static void x_extension_initialize (struct x_display_info *);
343static cairo_status_t x_cr_accumulate_data (void *,
344 const unsigned char *,
345 unsigned int);
346
347#define FRAME_CR_CONTEXT(f) ((f)->output_data.x->cr_context)
348#define FRAME_CR_SURFACE(f) ((f)->output_data.x->cr_surface)
349
350static struct x_gc_ext_data *
351x_gc_get_ext_data (f, gc, create_if_not_found_p)
352 struct frame *f;
353 GC gc;
354 int create_if_not_found_p;
355{
356 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
357 XEDataObject object;
358 XExtData **head, *ext_data;
359
360 object.gc = gc;
361 head = XEHeadOfExtensionList (object);
362 ext_data = XFindOnExtensionList (head, dpyinfo->ext_codes->extension);
363 if (ext_data == NULL)
364 {
365 if (!create_if_not_found_p)
366 return NULL;
367 else
368 {
369 ext_data = xzalloc (sizeof (*ext_data));
370 ext_data->number = dpyinfo->ext_codes->extension;
371 ext_data->private_data = xzalloc (sizeof (struct x_gc_ext_data));
372 XAddToExtensionList (head, ext_data);
373 }
374 }
375 return (struct x_gc_ext_data *) ext_data->private_data;
376}
377
378static void
379x_extension_initialize (dpyinfo)
380 struct x_display_info *dpyinfo;
381{
382 XExtCodes *ext_codes = XAddExtension (dpyinfo->display);
383
384 dpyinfo->ext_codes = ext_codes;
385}
386
387static void
388x_cr_destroy_surface (struct frame *f)
389{
390 if (FRAME_CR_SURFACE (f))
391 {
392 cairo_t *cr = FRAME_CR_CONTEXT (f);
393 cairo_surface_destroy (FRAME_CR_SURFACE (f));
394 FRAME_CR_SURFACE (f) = 0;
395 if (cr) cairo_destroy (cr);
396 FRAME_CR_CONTEXT (f) = NULL;
397 }
398}
399
400cairo_t *
401x_begin_cr_clip (f, gc)
402 struct frame *f;
403 GC gc;
404{
405 cairo_t *cr = FRAME_CR_CONTEXT (f);
406
407 if (!cr)
408 {
409
410 if (! FRAME_CR_SURFACE (f))
411 {
412 cairo_surface_t *surface;
413 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
414 FRAME_X_WINDOW (f),
415 FRAME_DISPLAY_INFO (f)->visual,
416 FRAME_PIXEL_WIDTH (f),
417 FRAME_PIXEL_HEIGHT (f));
418 cr = cairo_create (surface);
419 cairo_surface_destroy (surface);
420 }
421 else
422 cr = cairo_create (FRAME_CR_SURFACE (f));
423 FRAME_CR_CONTEXT (f) = cr;
424 }
425 cairo_save (cr);
426
427 if (gc)
428 {
429 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
430
431 if (gc_ext && gc_ext->n_clip_rects)
432 {
433 int i;
434
435 for (i = 0; i < gc_ext->n_clip_rects; i++)
436 cairo_rectangle (cr, gc_ext->clip_rects[i].x,
437 gc_ext->clip_rects[i].y,
438 gc_ext->clip_rects[i].width,
439 gc_ext->clip_rects[i].height);
440 cairo_clip (cr);
441 }
442 }
443
444 return cr;
445}
446
447void
448x_end_cr_clip (f)
449 struct frame *f;
450{
451 cairo_restore (FRAME_CR_CONTEXT (f));
452}
453
454void
455x_set_cr_source_with_gc_foreground (f, gc)
456 struct frame *f;
457 GC gc;
458{
459 XGCValues xgcv;
460 XColor color;
461
462 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCForeground, &xgcv);
463 color.pixel = xgcv.foreground;
464 x_query_color (f, &color);
465 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
466 color.green / 65535.0, color.blue / 65535.0);
467}
468
469void
470x_set_cr_source_with_gc_background (f, gc)
471 struct frame *f;
472 GC gc;
473{
474 XGCValues xgcv;
475 XColor color;
476
477 XGetGCValues (FRAME_X_DISPLAY (f), gc, GCBackground, &xgcv);
478 color.pixel = xgcv.background;
479 x_query_color (f, &color);
480 cairo_set_source_rgb (FRAME_CR_CONTEXT (f), color.red / 65535.0,
481 color.green / 65535.0, color.blue / 65535.0);
482}
483
484/* Fringe bitmaps. */
485
486static int max_fringe_bmp = 0;
487static cairo_pattern_t **fringe_bmp = 0;
488
489static void
490x_cr_define_fringe_bitmap (which, bits, h, wd)
491 int which;
492 unsigned short *bits;
493 int h, wd;
494{
495 int i, stride;
496 cairo_surface_t *surface;
497 unsigned char *data;
498 cairo_pattern_t *pattern;
499
500 if (which >= max_fringe_bmp)
501 {
502 i = max_fringe_bmp;
503 max_fringe_bmp = which + 20;
504 fringe_bmp = (cairo_pattern_t **) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (cairo_pattern_t *));
505 while (i < max_fringe_bmp)
506 fringe_bmp[i++] = 0;
507 }
508
509 block_input ();
510
511 surface = cairo_image_surface_create (CAIRO_FORMAT_A1, wd, h);
512 stride = cairo_image_surface_get_stride (surface);
513 data = cairo_image_surface_get_data (surface);
514
515 for (i = 0; i < h; i++)
516 {
517 *((unsigned short *) data) = bits[i];
518 data += stride;
519 }
520
521 pattern = cairo_pattern_create_for_surface (surface);
522 cairo_surface_destroy (surface);
523
524 unblock_input ();
525
526 fringe_bmp[which] = pattern;
527}
528
529static void
530x_cr_destroy_fringe_bitmap (which)
531 int which;
532{
533 if (which >= max_fringe_bmp)
534 return;
535
536 if (fringe_bmp[which])
537 {
538 block_input ();
539 cairo_pattern_destroy (fringe_bmp[which]);
540 unblock_input ();
541 }
542 fringe_bmp[which] = 0;
543}
544
545static void
546x_cr_draw_image (struct frame *f,
547 GC gc,
548 cairo_pattern_t *image,
549 int src_x,
550 int src_y,
551 unsigned int width,
552 unsigned int height,
553 int dest_x,
554 int dest_y,
555 bool overlay_p)
556{
557 cairo_t *cr;
558 cairo_matrix_t matrix;
559 cairo_surface_t *surface;
560 cairo_format_t format;
561
562 cr = x_begin_cr_clip (f, gc);
563 if (overlay_p)
564 cairo_rectangle (cr, dest_x, dest_y, width, height);
565 else
566 {
567 x_set_cr_source_with_gc_background (f, gc);
568 cairo_rectangle (cr, dest_x, dest_y, width, height);
569 cairo_fill_preserve (cr);
570 }
571 cairo_clip (cr);
572 cairo_matrix_init_translate (&matrix, src_x - dest_x, src_y - dest_y);
573 cairo_pattern_set_matrix (image, &matrix);
574 cairo_pattern_get_surface (image, &surface);
575 format = cairo_image_surface_get_format (surface);
576 if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
577 {
578 cairo_set_source (cr, image);
579 cairo_fill (cr);
580 }
581 else
582 {
583 x_set_cr_source_with_gc_foreground (f, gc);
584 cairo_mask (cr, image);
585 }
586 x_end_cr_clip (f);
587}
588
589void
590x_cr_draw_frame (cr, f)
591 cairo_t *cr;
592 struct frame *f;
593{
594 int width, height;
595
596 width = FRAME_PIXEL_WIDTH (f);
597 height = FRAME_PIXEL_HEIGHT (f);
598
599 x_prepare_for_xlibdraw (f);
600 FRAME_CR_CONTEXT (f) = cr;
601 x_clear_area (f, 0, 0, width, height);
602 expose_frame (f, 0, 0, width, height);
603 FRAME_CR_CONTEXT (f) = NULL;
604}
605
606static cairo_status_t
607x_cr_accumulate_data (closure, data, length)
608 void *closure;
609 const unsigned char *data;
610 unsigned int length;
611{
612 Lisp_Object *acc = (Lisp_Object *) closure;
613
614 *acc = Fcons (make_unibyte_string (data, length), *acc);
615
616 return CAIRO_STATUS_SUCCESS;
617}
618
619static void
620x_cr_destroy (arg)
621 Lisp_Object arg;
622{
623 cairo_t *cr = (cairo_t *) XSAVE_POINTER (arg, 0);
624
625 block_input ();
626 cairo_destroy (cr);
627 unblock_input ();
628}
629
630Lisp_Object
631x_cr_export_frames (frames, surface_type)
632 Lisp_Object frames;
633 cairo_surface_type_t surface_type;
634{
635 struct frame *f;
636 cairo_surface_t *surface;
637 cairo_t *cr;
638 int width, height;
639 void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
640 Lisp_Object acc = Qnil, args[2];
641 int count = SPECPDL_INDEX ();
642
643 Fredisplay (Qt);
644
645 f = XFRAME (XCAR (frames));
646 frames = XCDR (frames);
647 width = FRAME_PIXEL_WIDTH (f);
648 height = FRAME_PIXEL_HEIGHT (f);
649
650 block_input ();
651#ifdef CAIRO_HAS_PDF_SURFACE
652 if (surface_type == CAIRO_SURFACE_TYPE_PDF)
653 {
654 surface = cairo_pdf_surface_create_for_stream (x_cr_accumulate_data, &acc,
655 width, height);
656 surface_set_size_func = cairo_pdf_surface_set_size;
657 }
658 else
659#endif
660#ifdef CAIRO_HAS_PNG_FUNCTIONS
661 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
662 surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, width, height);
663 else
664#endif
665#ifdef CAIRO_HAS_PS_SURFACE
666 if (surface_type == CAIRO_SURFACE_TYPE_PS)
667 {
668 surface = cairo_ps_surface_create_for_stream (x_cr_accumulate_data, &acc,
669 width, height);
670 surface_set_size_func = cairo_ps_surface_set_size;
671 }
672 else
673#endif
674#ifdef CAIRO_HAS_SVG_SURFACE
675 if (surface_type == CAIRO_SURFACE_TYPE_SVG)
676 surface = cairo_svg_surface_create_for_stream (x_cr_accumulate_data, &acc,
677 width, height);
678 else
679#endif
680 abort ();
681
682 cr = cairo_create (surface);
683 cairo_surface_destroy (surface);
684 record_unwind_protect (x_cr_destroy, make_save_ptr (cr));
685 unblock_input ();
686
687 while (1)
688 {
689 QUIT;
690
691 block_input ();
692 x_prepare_for_xlibdraw (f);
693 FRAME_CR_CONTEXT (f) = cr;
694 x_clear_area (f, 0, 0, width, height);
695 expose_frame (f, 0, 0, width, height);
696 FRAME_CR_CONTEXT (f) = NULL;
697 unblock_input ();
698
699 if (NILP (frames))
700 break;
701
702 block_input ();
703 cairo_surface_show_page (surface);
704 f = XFRAME (XCAR (frames));
705 frames = XCDR (frames);
706 width = FRAME_PIXEL_WIDTH (f);
707 height = FRAME_PIXEL_HEIGHT (f);
708 if (surface_set_size_func)
709 (*surface_set_size_func) (surface, width, height);
710 unblock_input ();
711 }
712
713#ifdef CAIRO_HAS_PNG_FUNCTIONS
714 if (surface_type == CAIRO_SURFACE_TYPE_IMAGE)
715 {
716 block_input ();
717 cairo_surface_flush (surface);
718 cairo_surface_write_to_png_stream (surface, x_cr_accumulate_data, &acc);
719 unblock_input ();
720 }
721#endif
722 unbind_to (count, Qnil);
723
724 args[0] = intern ("concat");
725 args[1] = Fnreverse (acc);
726 return Fapply (2, args);
727}
728
729#endif /* USE_CAIRO */
730
731static void
732x_prepare_for_xlibdraw (f)
733 struct frame *f;
734{
735#ifdef USE_CAIRO
736 if (f == NULL)
737 {
738 Lisp_Object rest, frame;
739 FOR_EACH_FRAME (rest, frame)
740 if (FRAME_X_P (XFRAME (frame)))
741 x_prepare_for_xlibdraw (XFRAME (frame));
742 }
743 else
744 {
745 cairo_t *cr = FRAME_CR_CONTEXT (f);
746
747 if (cr)
748 {
749 cairo_surface_t *surface = cairo_get_target (cr);
750
751 if (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB)
752 {
753 cairo_destroy (cr);
754 FRAME_CR_CONTEXT (f) = NULL;
755 }
756 }
757 }
758#endif
759}
760
761static void
762x_set_clip_rectangles (f, gc, rectangles, n)
763 struct frame *f;
764 GC gc;
765 XRectangle *rectangles;
766 int n;
767{
768 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, rectangles, n, Unsorted);
769#ifdef USE_CAIRO
770 eassert (n >= 0 && n <= MAX_CLIP_RECTS);
771
772 {
773 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 1);
774
775 gc_ext->n_clip_rects = n;
776 memcpy (gc_ext->clip_rects, rectangles, sizeof (XRectangle) * n);
777 }
778#endif
779}
780
781static void
782x_reset_clip_rectangles (f, gc)
783 struct frame *f;
784 GC gc;
785{
786 XSetClipMask (FRAME_X_DISPLAY (f), gc, None);
787#ifdef USE_CAIRO
788 {
789 struct x_gc_ext_data *gc_ext = x_gc_get_ext_data (f, gc, 0);
790
791 if (gc_ext)
792 gc_ext->n_clip_rects = 0;
793 }
794#endif
795}
796
797static void
798x_fill_rectangle (f, gc, x, y, width, height)
799 struct frame *f;
800 GC gc;
801 int x, y;
802 unsigned int width, height;
803{
804#ifdef USE_CAIRO
805 cairo_t *cr;
806
807 cr = x_begin_cr_clip (f, gc);
808 x_set_cr_source_with_gc_foreground (f, gc);
809 cairo_rectangle (cr, x, y, width, height);
810 cairo_fill (cr);
811 x_end_cr_clip (f);
812#else
813 XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
814 gc, x, y, width, height);
815#endif
816}
817
818static void
819x_draw_rectangle (f, gc, x, y, width, height)
820 struct frame *f;
821 GC gc;
822 int x, y;
823 unsigned int width, height;
824{
825#ifdef USE_CAIRO
826 cairo_t *cr;
827
828 cr = x_begin_cr_clip (f, gc);
829 x_set_cr_source_with_gc_foreground (f, gc);
830 cairo_rectangle (cr, x + 0.5, y + 0.5, width, height);
831 cairo_set_line_width (cr, 1);
832 cairo_stroke (cr);
833 x_end_cr_clip (f);
834#else
835 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
836 gc, x, y, width, height);
837#endif
838}
839
840static void
841x_clear_window (f)
842 struct frame *f;
843{
844#ifdef USE_CAIRO
845 cairo_t *cr;
846
847 cr = x_begin_cr_clip (f, NULL);
848 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
849 cairo_paint (cr);
850 x_end_cr_clip (f);
851#else
852 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
853#endif
854}
855
856#ifdef USE_CAIRO
857static void
858x_fill_trapezoid_for_relief (f, gc, x, y, width, height, top_p)
859 struct frame *f;
860 GC gc;
861 int x, y;
862 unsigned int width, height;
863 int top_p;
864{
865 cairo_t *cr;
866
867 cr = x_begin_cr_clip (f, gc);
868 x_set_cr_source_with_gc_foreground (f, gc);
869 cairo_move_to (cr, top_p ? x : x + height, y);
870 cairo_line_to (cr, x, y + height);
871 cairo_line_to (cr, top_p ? x + width - height : x + width, y + height);
872 cairo_line_to (cr, x + width, y);
873 cairo_close_path (cr);
874 cairo_fill (cr);
875 x_end_cr_clip (f);
876}
877#endif
328 878
329 879
330/* Return the struct x_display_info corresponding to DPY. */ 880/* Return the struct x_display_info corresponding to DPY. */
@@ -452,9 +1002,38 @@ x_set_frame_alpha (struct frame *f)
452static void 1002static void
453x_update_begin (struct frame *f) 1003x_update_begin (struct frame *f)
454{ 1004{
455 /* Nothing to do. */ 1005#ifdef USE_CAIRO
456} 1006 if (! FRAME_CR_SURFACE (f))
1007 {
1008 int width, height;
1009#ifdef USE_GTK
1010 if (FRAME_GTK_WIDGET (f))
1011 {
1012 GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
1013 width = gdk_window_get_width (w);
1014 height = gdk_window_get_height (w);
1015 }
1016 else
1017#endif
1018 {
1019 width = FRAME_PIXEL_WIDTH (f);
1020 height = FRAME_PIXEL_HEIGHT (f);
1021 if (! FRAME_EXTERNAL_TOOL_BAR (f))
1022 height += FRAME_TOOL_BAR_HEIGHT (f);
1023 if (! FRAME_EXTERNAL_MENU_BAR (f))
1024 height += FRAME_MENU_BAR_HEIGHT (f);
1025 }
457 1026
1027 if (width > 0 && height > 0)
1028 {
1029 block_input();
1030 FRAME_CR_SURFACE (f) = cairo_image_surface_create
1031 (CAIRO_FORMAT_ARGB32, width, height);
1032 unblock_input();
1033 }
1034 }
1035#endif /* USE_CAIRO */
1036}
458 1037
459/* Start update of window W. */ 1038/* Start update of window W. */
460 1039
@@ -496,8 +1075,12 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
496 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc, 1075 XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
497 face->foreground); 1076 face->foreground);
498 1077
1078#ifdef USE_CAIRO
1079 x_fill_rectangle (f, f->output_data.x->normal_gc, x, y0, 1, y1 - y0);
1080#else
499 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 1081 XDrawLine (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
500 f->output_data.x->normal_gc, x, y0, x, y1); 1082 f->output_data.x->normal_gc, x, y0, x, y1);
1083#endif
501} 1084}
502 1085
503/* Draw a window divider from (x0,y0) to (x1,y1) */ 1086/* Draw a window divider from (x0,y0) to (x1,y1) */
@@ -612,6 +1195,43 @@ x_update_end (struct frame *f)
612 /* Mouse highlight may be displayed again. */ 1195 /* Mouse highlight may be displayed again. */
613 MOUSE_HL_INFO (f)->mouse_face_defer = false; 1196 MOUSE_HL_INFO (f)->mouse_face_defer = false;
614 1197
1198#ifdef USE_CAIRO
1199 if (FRAME_CR_SURFACE (f))
1200 {
1201 cairo_t *cr = 0;
1202 block_input();
1203#if defined (USE_GTK) && defined (HAVE_GTK3)
1204 if (FRAME_GTK_WIDGET (f))
1205 {
1206 GdkWindow *w = gtk_widget_get_window (FRAME_GTK_WIDGET (f));
1207 cr = gdk_cairo_create (w);
1208 }
1209 else
1210#endif
1211 {
1212 cairo_surface_t *surface;
1213 int width = FRAME_PIXEL_WIDTH (f);
1214 int height = FRAME_PIXEL_HEIGHT (f);
1215 if (! FRAME_EXTERNAL_TOOL_BAR (f))
1216 height += FRAME_TOOL_BAR_HEIGHT (f);
1217 if (! FRAME_EXTERNAL_MENU_BAR (f))
1218 height += FRAME_MENU_BAR_HEIGHT (f);
1219 surface = cairo_xlib_surface_create (FRAME_X_DISPLAY (f),
1220 FRAME_X_WINDOW (f),
1221 FRAME_DISPLAY_INFO (f)->visual,
1222 width,
1223 height);
1224 cr = cairo_create (surface);
1225 cairo_surface_destroy (surface);
1226 }
1227
1228 cairo_set_source_surface (cr, FRAME_CR_SURFACE (f), 0, 0);
1229 cairo_paint (cr);
1230 cairo_destroy (cr);
1231 unblock_input ();
1232 }
1233#endif /* USE_CAIRO */
1234
615#ifndef XFlush 1235#ifndef XFlush
616 block_input (); 1236 block_input ();
617 XFlush (FRAME_X_DISPLAY (f)); 1237 XFlush (FRAME_X_DISPLAY (f));
@@ -638,18 +1258,16 @@ x_clear_under_internal_border (struct frame *f)
638{ 1258{
639 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0) 1259 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
640 { 1260 {
641 Display *display = FRAME_X_DISPLAY (f);
642 Window window = FRAME_X_WINDOW (f);
643 int border = FRAME_INTERNAL_BORDER_WIDTH (f); 1261 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
644 int width = FRAME_PIXEL_WIDTH (f); 1262 int width = FRAME_PIXEL_WIDTH (f);
645 int height = FRAME_PIXEL_HEIGHT (f); 1263 int height = FRAME_PIXEL_HEIGHT (f);
646 int margin = FRAME_TOP_MARGIN_HEIGHT (f); 1264 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
647 1265
648 block_input (); 1266 block_input ();
649 x_clear_area (display, window, 0, 0, border, height); 1267 x_clear_area (f, 0, 0, border, height);
650 x_clear_area (display, window, 0, margin, width, border); 1268 x_clear_area (f, 0, margin, width, border);
651 x_clear_area (display, window, width - border, 0, border, height); 1269 x_clear_area (f, width - border, 0, border, height);
652 x_clear_area (display, window, 0, height - border, width, border); 1270 x_clear_area (f, 0, height - border, width, border);
653 unblock_input (); 1271 unblock_input ();
654 } 1272 }
655} 1273}
@@ -691,11 +1309,8 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
691 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); 1309 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
692 1310
693 block_input (); 1311 block_input ();
694 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 1312 x_clear_area (f, 0, y, width, height);
695 0, y, width, height); 1313 x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
696 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
697 FRAME_PIXEL_WIDTH (f) - width,
698 y, width, height);
699 unblock_input (); 1314 unblock_input ();
700 } 1315 }
701 } 1316 }
@@ -725,13 +1340,29 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
725 else 1340 else
726 XSetForeground (display, face->gc, face->background); 1341 XSetForeground (display, face->gc, face->background);
727 1342
728 XFillRectangle (display, window, face->gc, 1343 x_fill_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny);
729 p->bx, p->by, p->nx, p->ny);
730 1344
731 if (!face->stipple) 1345 if (!face->stipple)
732 XSetForeground (display, face->gc, face->foreground); 1346 XSetForeground (display, face->gc, face->foreground);
733 } 1347 }
734 1348
1349#ifdef USE_CAIRO
1350 if (p->which && p->which < max_fringe_bmp)
1351 {
1352 XGCValues gcv;
1353
1354 XGetGCValues (display, gc, GCForeground | GCBackground, &gcv);
1355 XSetForeground (display, gc, (p->cursor_p
1356 ? (p->overlay_p ? face->background
1357 : f->output_data.x->cursor_pixel)
1358 : face->foreground));
1359 XSetBackground (display, gc, face->background);
1360 x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
1361 p->wd, p->h, p->x, p->y, p->overlay_p);
1362 XSetForeground (display, gc, gcv.foreground);
1363 XSetBackground (display, gc, gcv.background);
1364 }
1365#else /* not USE_CAIRO */
735 if (p->which) 1366 if (p->which)
736 { 1367 {
737 char *bits; 1368 char *bits;
@@ -776,8 +1407,9 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
776 XFreePixmap (display, clipmask); 1407 XFreePixmap (display, clipmask);
777 } 1408 }
778 } 1409 }
1410#endif /* not USE_CAIRO */
779 1411
780 XSetClipMask (display, gc, None); 1412 x_reset_clip_rectangles (f, gc);
781} 1413}
782 1414
783/*********************************************************************** 1415/***********************************************************************
@@ -985,7 +1617,7 @@ x_set_glyph_string_clipping (struct glyph_string *s)
985 int n = get_glyph_string_clip_rects (s, r, 2); 1617 int n = get_glyph_string_clip_rects (s, r, 2);
986 1618
987 if (n > 0) 1619 if (n > 0)
988 XSetClipRectangles (s->display, s->gc, 0, 0, r, n, Unsorted); 1620 x_set_clip_rectangles (s->f, s->gc, r, n);
989 s->num_clips = n; 1621 s->num_clips = n;
990} 1622}
991 1623
@@ -1005,7 +1637,7 @@ x_set_glyph_string_clipping_exactly (struct glyph_string *src, struct glyph_stri
1005 r.height = src->height; 1637 r.height = src->height;
1006 dst->clip[0] = r; 1638 dst->clip[0] = r;
1007 dst->num_clips = 1; 1639 dst->num_clips = 1;
1008 XSetClipRectangles (dst->display, dst->gc, 0, 0, &r, 1, Unsorted); 1640 x_set_clip_rectangles (dst->f, dst->gc, &r, 1);
1009} 1641}
1010 1642
1011 1643
@@ -1057,7 +1689,7 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h)
1057 XGCValues xgcv; 1689 XGCValues xgcv;
1058 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv); 1690 XGetGCValues (s->display, s->gc, GCForeground | GCBackground, &xgcv);
1059 XSetForeground (s->display, s->gc, xgcv.background); 1691 XSetForeground (s->display, s->gc, xgcv.background);
1060 XFillRectangle (s->display, s->window, s->gc, x, y, w, h); 1692 x_fill_rectangle (s->f, s->gc, x, y, w, h);
1061 XSetForeground (s->display, s->gc, xgcv.foreground); 1693 XSetForeground (s->display, s->gc, xgcv.foreground);
1062} 1694}
1063 1695
@@ -1081,7 +1713,7 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p)
1081 { 1713 {
1082 /* Fill background with a stipple pattern. */ 1714 /* Fill background with a stipple pattern. */
1083 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); 1715 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
1084 XFillRectangle (s->display, s->window, s->gc, s->x, 1716 x_fill_rectangle (s->f, s->gc, s->x,
1085 s->y + box_line_width, 1717 s->y + box_line_width,
1086 s->background_width, 1718 s->background_width,
1087 s->height - 2 * box_line_width); 1719 s->height - 2 * box_line_width);
@@ -1124,7 +1756,7 @@ x_draw_glyph_string_foreground (struct glyph_string *s)
1124 for (i = 0; i < s->nchars; ++i) 1756 for (i = 0; i < s->nchars; ++i)
1125 { 1757 {
1126 struct glyph *g = s->first_glyph + i; 1758 struct glyph *g = s->first_glyph + i;
1127 XDrawRectangle (s->display, s->window, 1759 x_draw_rectangle (s->f,
1128 s->gc, x, s->y, g->pixel_width - 1, 1760 s->gc, x, s->y, g->pixel_width - 1,
1129 s->height - 1); 1761 s->height - 1);
1130 x += g->pixel_width; 1762 x += g->pixel_width;
@@ -1176,7 +1808,7 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
1176 if (s->font_not_found_p) 1808 if (s->font_not_found_p)
1177 { 1809 {
1178 if (s->cmp_from == 0) 1810 if (s->cmp_from == 0)
1179 XDrawRectangle (s->display, s->window, s->gc, x, s->y, 1811 x_draw_rectangle (s->f, s->gc, x, s->y,
1180 s->width - 1, s->height - 1); 1812 s->width - 1, s->height - 1);
1181 } 1813 }
1182 else if (! s->first_glyph->u.cmp.automatic) 1814 else if (! s->first_glyph->u.cmp.automatic)
@@ -1310,7 +1942,7 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1310 false); 1942 false);
1311 } 1943 }
1312 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE) 1944 if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
1313 XDrawRectangle (s->display, s->window, s->gc, 1945 x_draw_rectangle (s->f, s->gc,
1314 x, s->ybase - glyph->ascent, 1946 x, s->ybase - glyph->ascent,
1315 glyph->pixel_width - 1, 1947 glyph->pixel_width - 1,
1316 glyph->ascent + glyph->descent - 1); 1948 glyph->ascent + glyph->descent - 1);
@@ -1882,6 +2514,52 @@ x_draw_relief_rect (struct frame *f,
1882 bool left_p, bool right_p, 2514 bool left_p, bool right_p,
1883 XRectangle *clip_rect) 2515 XRectangle *clip_rect)
1884{ 2516{
2517#ifdef USE_CAIRO
2518 GC top_left_gc, bottom_right_gc;
2519
2520 if (raised_p)
2521 {
2522 top_left_gc = f->output_data.x->white_relief.gc;
2523 bottom_right_gc = f->output_data.x->black_relief.gc;
2524 }
2525 else
2526 {
2527 top_left_gc = f->output_data.x->black_relief.gc;
2528 bottom_right_gc = f->output_data.x->white_relief.gc;
2529 }
2530
2531 x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
2532 x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
2533
2534 if (left_p)
2535 x_fill_rectangle (f, top_left_gc, left_x, top_y,
2536 width, bottom_y + 1 - top_y);
2537 if (right_p)
2538 x_fill_rectangle (f, bottom_right_gc, right_x + 1 - width, top_y,
2539 width, bottom_y + 1 - top_y);
2540 if (top_p)
2541 {
2542 if (!right_p)
2543 x_fill_rectangle (f, top_left_gc, left_x, top_y,
2544 right_x + 1 - left_x, width);
2545 else
2546 x_fill_trapezoid_for_relief (f, top_left_gc, left_x, top_y,
2547 right_x + 1 - left_x, width, 1);
2548 }
2549 if (bot_p)
2550 {
2551 if (!left_p)
2552 x_fill_rectangle (f, bottom_right_gc, left_x, bottom_y + 1 - width,
2553 right_x + 1 - left_x, width);
2554 else
2555 x_fill_trapezoid_for_relief (f, bottom_right_gc,
2556 left_x, bottom_y + 1 - width,
2557 right_x + 1 - left_x, width, 0);
2558 }
2559
2560 x_set_clip_rectangles (f, top_left_gc, clip_rect, 1);
2561 x_set_clip_rectangles (f, bottom_right_gc, clip_rect, 1);
2562#else
1885 Display *dpy = FRAME_X_DISPLAY (f); 2563 Display *dpy = FRAME_X_DISPLAY (f);
1886 Window window = FRAME_X_WINDOW (f); 2564 Window window = FRAME_X_WINDOW (f);
1887 int i; 2565 int i;
@@ -1970,7 +2648,9 @@ x_draw_relief_rect (struct frame *f,
1970 right_x - i, bottom_y + 1 - (i + 1) * bot_p); 2648 right_x - i, bottom_y + 1 - (i + 1) * bot_p);
1971 } 2649 }
1972 2650
1973 XSetClipMask (dpy, gc, None); 2651 x_reset_clip_rectangles (f, gc);
2652
2653#endif
1974} 2654}
1975 2655
1976 2656
@@ -1990,28 +2670,28 @@ x_draw_box_rect (struct glyph_string *s,
1990 2670
1991 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 2671 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
1992 XSetForeground (s->display, s->gc, s->face->box_color); 2672 XSetForeground (s->display, s->gc, s->face->box_color);
1993 XSetClipRectangles (s->display, s->gc, 0, 0, clip_rect, 1, Unsorted); 2673 x_set_clip_rectangles (s->f, s->gc, clip_rect, 1);
1994 2674
1995 /* Top. */ 2675 /* Top. */
1996 XFillRectangle (s->display, s->window, s->gc, 2676 x_fill_rectangle (s->f, s->gc,
1997 left_x, top_y, right_x - left_x + 1, width); 2677 left_x, top_y, right_x - left_x + 1, width);
1998 2678
1999 /* Left. */ 2679 /* Left. */
2000 if (left_p) 2680 if (left_p)
2001 XFillRectangle (s->display, s->window, s->gc, 2681 x_fill_rectangle (s->f, s->gc,
2002 left_x, top_y, width, bottom_y - top_y + 1); 2682 left_x, top_y, width, bottom_y - top_y + 1);
2003 2683
2004 /* Bottom. */ 2684 /* Bottom. */
2005 XFillRectangle (s->display, s->window, s->gc, 2685 x_fill_rectangle (s->f, s->gc,
2006 left_x, bottom_y - width + 1, right_x - left_x + 1, width); 2686 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2007 2687
2008 /* Right. */ 2688 /* Right. */
2009 if (right_p) 2689 if (right_p)
2010 XFillRectangle (s->display, s->window, s->gc, 2690 x_fill_rectangle (s->f, s->gc,
2011 right_x - width + 1, top_y, width, bottom_y - top_y + 1); 2691 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2012 2692
2013 XSetForeground (s->display, s->gc, xgcv.foreground); 2693 XSetForeground (s->display, s->gc, xgcv.foreground);
2014 XSetClipMask (s->display, s->gc, None); 2694 x_reset_clip_rectangles (s->f, s->gc);
2015} 2695}
2016 2696
2017 2697
@@ -2142,7 +2822,7 @@ x_draw_image_foreground (struct glyph_string *s)
2142 if (s->hl == DRAW_CURSOR) 2822 if (s->hl == DRAW_CURSOR)
2143 { 2823 {
2144 int relief = eabs (s->img->relief); 2824 int relief = eabs (s->img->relief);
2145 XDrawRectangle (s->display, s->window, s->gc, 2825 x_draw_rectangle (s->f, s->gc,
2146 x - relief, y - relief, 2826 x - relief, y - relief,
2147 s->slice.width + relief*2 - 1, 2827 s->slice.width + relief*2 - 1,
2148 s->slice.height + relief*2 - 1); 2828 s->slice.height + relief*2 - 1);
@@ -2151,7 +2831,7 @@ x_draw_image_foreground (struct glyph_string *s)
2151 } 2831 }
2152 else 2832 else
2153 /* Draw a rectangle if image could not be loaded. */ 2833 /* Draw a rectangle if image could not be loaded. */
2154 XDrawRectangle (s->display, s->window, s->gc, x, y, 2834 x_draw_rectangle (s->f, s->gc, x, y,
2155 s->slice.width - 1, s->slice.height - 1); 2835 s->slice.width - 1, s->slice.height - 1);
2156} 2836}
2157 2837
@@ -2290,7 +2970,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
2290 if (s->hl == DRAW_CURSOR) 2970 if (s->hl == DRAW_CURSOR)
2291 { 2971 {
2292 int r = eabs (s->img->relief); 2972 int r = eabs (s->img->relief);
2293 XDrawRectangle (s->display, s->window, s->gc, x - r, y - r, 2973 x_draw_rectangle (s->f, s->gc, x - r, y - r,
2294 s->slice.width + r*2 - 1, 2974 s->slice.width + r*2 - 1,
2295 s->slice.height + r*2 - 1); 2975 s->slice.height + r*2 - 1);
2296 } 2976 }
@@ -2298,7 +2978,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
2298 } 2978 }
2299 else 2979 else
2300 /* Draw a rectangle if image could not be loaded. */ 2980 /* Draw a rectangle if image could not be loaded. */
2301 XDrawRectangle (s->display, pixmap, s->gc, x, y, 2981 x_draw_rectangle (s->f, s->gc, x, y,
2302 s->slice.width - 1, s->slice.height - 1); 2982 s->slice.width - 1, s->slice.height - 1);
2303} 2983}
2304 2984
@@ -2313,7 +2993,7 @@ x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h)
2313 { 2993 {
2314 /* Fill background with a stipple pattern. */ 2994 /* Fill background with a stipple pattern. */
2315 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); 2995 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2316 XFillRectangle (s->display, s->window, s->gc, x, y, w, h); 2996 x_fill_rectangle (s->f, s->gc, x, y, w, h);
2317 XSetFillStyle (s->display, s->gc, FillSolid); 2997 XSetFillStyle (s->display, s->gc, FillSolid);
2318 } 2998 }
2319 else 2999 else
@@ -2422,7 +3102,22 @@ x_draw_image_glyph_string (struct glyph_string *s)
2422 } 3102 }
2423 3103
2424 /* Draw the foreground. */ 3104 /* Draw the foreground. */
2425 if (pixmap != None) 3105 if (s->img->cr_data)
3106 {
3107 cairo_t *cr = x_begin_cr_clip (s->f, s->gc);
3108
3109 int x = s->x + s->img->hmargin;
3110 int y = s->y + s->img->vmargin;
3111 int width = s->background_width;
3112
3113 cairo_set_source_surface (cr, s->img->cr_data,
3114 x - s->slice.x,
3115 y - s->slice.y);
3116 cairo_rectangle (cr, x, y, width, height);
3117 cairo_fill (cr);
3118 x_end_cr_clip (s->f);
3119 }
3120 else if (pixmap != None)
2426 { 3121 {
2427 x_draw_image_foreground_1 (s, pixmap); 3122 x_draw_image_foreground_1 (s, pixmap);
2428 x_set_glyph_string_clipping (s); 3123 x_set_glyph_string_clipping (s);
@@ -2505,13 +3200,13 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
2505 gc = s->face->gc; 3200 gc = s->face->gc;
2506 3201
2507 get_glyph_string_clip_rect (s, &r); 3202 get_glyph_string_clip_rect (s, &r);
2508 XSetClipRectangles (s->display, gc, 0, 0, &r, 1, Unsorted); 3203 x_set_clip_rectangles (s->f, gc, &r, 1);
2509 3204
2510 if (s->face->stipple) 3205 if (s->face->stipple)
2511 { 3206 {
2512 /* Fill background with a stipple pattern. */ 3207 /* Fill background with a stipple pattern. */
2513 XSetFillStyle (s->display, gc, FillOpaqueStippled); 3208 XSetFillStyle (s->display, gc, FillOpaqueStippled);
2514 XFillRectangle (s->display, s->window, gc, x, y, w, h); 3209 x_fill_rectangle (s->f, gc, x, y, w, h);
2515 XSetFillStyle (s->display, gc, FillSolid); 3210 XSetFillStyle (s->display, gc, FillSolid);
2516 } 3211 }
2517 else 3212 else
@@ -2519,7 +3214,7 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
2519 XGCValues xgcv; 3214 XGCValues xgcv;
2520 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv); 3215 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
2521 XSetForeground (s->display, gc, xgcv.background); 3216 XSetForeground (s->display, gc, xgcv.background);
2522 XFillRectangle (s->display, s->window, gc, x, y, w, h); 3217 x_fill_rectangle (s->f, gc, x, y, w, h);
2523 XSetForeground (s->display, gc, xgcv.foreground); 3218 XSetForeground (s->display, gc, xgcv.foreground);
2524 } 3219 }
2525 3220
@@ -2778,14 +3473,14 @@ x_draw_glyph_string (struct glyph_string *s)
2778 s->underline_position = position; 3473 s->underline_position = position;
2779 y = s->ybase + position; 3474 y = s->ybase + position;
2780 if (s->face->underline_defaulted_p) 3475 if (s->face->underline_defaulted_p)
2781 XFillRectangle (s->display, s->window, s->gc, 3476 x_fill_rectangle (s->f, s->gc,
2782 s->x, y, s->width, thickness); 3477 s->x, y, s->width, thickness);
2783 else 3478 else
2784 { 3479 {
2785 XGCValues xgcv; 3480 XGCValues xgcv;
2786 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3481 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2787 XSetForeground (s->display, s->gc, s->face->underline_color); 3482 XSetForeground (s->display, s->gc, s->face->underline_color);
2788 XFillRectangle (s->display, s->window, s->gc, 3483 x_fill_rectangle (s->f, s->gc,
2789 s->x, y, s->width, thickness); 3484 s->x, y, s->width, thickness);
2790 XSetForeground (s->display, s->gc, xgcv.foreground); 3485 XSetForeground (s->display, s->gc, xgcv.foreground);
2791 } 3486 }
@@ -2797,14 +3492,14 @@ x_draw_glyph_string (struct glyph_string *s)
2797 unsigned long dy = 0, h = 1; 3492 unsigned long dy = 0, h = 1;
2798 3493
2799 if (s->face->overline_color_defaulted_p) 3494 if (s->face->overline_color_defaulted_p)
2800 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, 3495 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
2801 s->width, h); 3496 s->width, h);
2802 else 3497 else
2803 { 3498 {
2804 XGCValues xgcv; 3499 XGCValues xgcv;
2805 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3500 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2806 XSetForeground (s->display, s->gc, s->face->overline_color); 3501 XSetForeground (s->display, s->gc, s->face->overline_color);
2807 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, 3502 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
2808 s->width, h); 3503 s->width, h);
2809 XSetForeground (s->display, s->gc, xgcv.foreground); 3504 XSetForeground (s->display, s->gc, xgcv.foreground);
2810 } 3505 }
@@ -2817,14 +3512,14 @@ x_draw_glyph_string (struct glyph_string *s)
2817 unsigned long dy = (s->height - h) / 2; 3512 unsigned long dy = (s->height - h) / 2;
2818 3513
2819 if (s->face->strike_through_color_defaulted_p) 3514 if (s->face->strike_through_color_defaulted_p)
2820 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, 3515 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
2821 s->width, h); 3516 s->width, h);
2822 else 3517 else
2823 { 3518 {
2824 XGCValues xgcv; 3519 XGCValues xgcv;
2825 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3520 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
2826 XSetForeground (s->display, s->gc, s->face->strike_through_color); 3521 XSetForeground (s->display, s->gc, s->face->strike_through_color);
2827 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy, 3522 x_fill_rectangle (s->f, s->gc, s->x, s->y + dy,
2828 s->width, h); 3523 s->width, h);
2829 XSetForeground (s->display, s->gc, xgcv.foreground); 3524 XSetForeground (s->display, s->gc, xgcv.foreground);
2830 } 3525 }
@@ -2853,7 +3548,7 @@ x_draw_glyph_string (struct glyph_string *s)
2853 x_draw_glyph_string_foreground (prev); 3548 x_draw_glyph_string_foreground (prev);
2854 else 3549 else
2855 x_draw_composite_glyph_string_foreground (prev); 3550 x_draw_composite_glyph_string_foreground (prev);
2856 XSetClipMask (prev->display, prev->gc, None); 3551 x_reset_clip_rectangles (prev->f, prev->gc);
2857 prev->hl = save; 3552 prev->hl = save;
2858 prev->num_clips = 0; 3553 prev->num_clips = 0;
2859 } 3554 }
@@ -2878,7 +3573,7 @@ x_draw_glyph_string (struct glyph_string *s)
2878 x_draw_glyph_string_foreground (next); 3573 x_draw_glyph_string_foreground (next);
2879 else 3574 else
2880 x_draw_composite_glyph_string_foreground (next); 3575 x_draw_composite_glyph_string_foreground (next);
2881 XSetClipMask (next->display, next->gc, None); 3576 x_reset_clip_rectangles (next->f, next->gc);
2882 next->hl = save; 3577 next->hl = save;
2883 next->num_clips = 0; 3578 next->num_clips = 0;
2884 next->clip_head = s->next; 3579 next->clip_head = s->next;
@@ -2887,7 +3582,7 @@ x_draw_glyph_string (struct glyph_string *s)
2887 } 3582 }
2888 3583
2889 /* Reset clipping. */ 3584 /* Reset clipping. */
2890 XSetClipMask (s->display, s->gc, None); 3585 x_reset_clip_rectangles (s->f, s->gc);
2891 s->num_clips = 0; 3586 s->num_clips = 0;
2892} 3587}
2893 3588
@@ -2896,6 +3591,7 @@ x_draw_glyph_string (struct glyph_string *s)
2896static void 3591static void
2897x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by) 3592x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by)
2898{ 3593{
3594 x_prepare_for_xlibdraw (f);
2899 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), 3595 XCopyArea (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
2900 f->output_data.x->normal_gc, 3596 f->output_data.x->normal_gc,
2901 x, y, width, height, 3597 x, y, width, height,
@@ -2915,11 +3611,35 @@ x_delete_glyphs (struct frame *f, register int n)
2915/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable. 3611/* Like XClearArea, but check that WIDTH and HEIGHT are reasonable.
2916 If they are <= 0, this is probably an error. */ 3612 If they are <= 0, this is probably an error. */
2917 3613
3614static void
3615x_clear_area1 (Display *dpy, Window window,
3616 int x, int y, int width, int height, int exposures)
3617{
3618 eassert (width > 0 && height > 0);
3619 XClearArea (dpy, window, x, y, width, height, exposures);
3620}
3621
3622
2918void 3623void
2919x_clear_area (Display *dpy, Window window, int x, int y, int width, int height) 3624x_clear_area (f, x, y, width, height)
3625 struct frame *f;
3626 int x, y;
3627 int width, height;
2920{ 3628{
3629#ifdef USE_CAIRO
3630 cairo_t *cr;
3631
2921 eassert (width > 0 && height > 0); 3632 eassert (width > 0 && height > 0);
2922 XClearArea (dpy, window, x, y, width, height, False); 3633
3634 cr = x_begin_cr_clip (f, NULL);
3635 x_set_cr_source_with_gc_background (f, f->output_data.x->normal_gc);
3636 cairo_rectangle (cr, x, y, width, height);
3637 cairo_fill (cr);
3638 x_end_cr_clip (f);
3639#else
3640 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3641 x, y, width, height, False);
3642#endif
2923} 3643}
2924 3644
2925 3645
@@ -2934,7 +3654,7 @@ x_clear_frame (struct frame *f)
2934 3654
2935 block_input (); 3655 block_input ();
2936 3656
2937 XClearWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f)); 3657 x_clear_window (f);
2938 3658
2939 /* We have to clear the scroll bars. If we have changed colors or 3659 /* We have to clear the scroll bars. If we have changed colors or
2940 something like that, then they should be notified. */ 3660 something like that, then they should be notified. */
@@ -3240,12 +3960,16 @@ x_scroll_run (struct window *w, struct run *run)
3240 /* Cursor off. Will be switched on again in x_update_window_end. */ 3960 /* Cursor off. Will be switched on again in x_update_window_end. */
3241 x_clear_cursor (w); 3961 x_clear_cursor (w);
3242 3962
3963#ifdef USE_CAIRO
3964 SET_FRAME_GARBAGED (f);
3965#else
3243 XCopyArea (FRAME_X_DISPLAY (f), 3966 XCopyArea (FRAME_X_DISPLAY (f),
3244 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f), 3967 FRAME_X_WINDOW (f), FRAME_X_WINDOW (f),
3245 f->output_data.x->normal_gc, 3968 f->output_data.x->normal_gc,
3246 x, from_y, 3969 x, from_y,
3247 width, height, 3970 width, height,
3248 x, to_y); 3971 x, to_y);
3972#endif
3249 3973
3250 unblock_input (); 3974 unblock_input ();
3251} 3975}
@@ -4154,7 +4878,7 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
4154 dpyinfo->last_mouse_glyph_frame = f1; 4878 dpyinfo->last_mouse_glyph_frame = f1;
4155 4879
4156 *bar_window = Qnil; 4880 *bar_window = Qnil;
4157 *part = scroll_bar_above_handle; 4881 *part = 0;
4158 *fp = f1; 4882 *fp = f1;
4159 XSETINT (*x, win_x); 4883 XSETINT (*x, win_x);
4160 XSETINT (*y, win_y); 4884 XSETINT (*y, win_y);
@@ -4248,7 +4972,7 @@ x_window_to_menu_bar (Window window)
4248#ifdef USE_TOOLKIT_SCROLL_BARS 4972#ifdef USE_TOOLKIT_SCROLL_BARS
4249 4973
4250static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part, 4974static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part,
4251 int, int, bool); 4975 int, int, bool);
4252 4976
4253/* Lisp window being scrolled. Set when starting to interact with 4977/* Lisp window being scrolled. Set when starting to interact with
4254 a toolkit scroll bar, reset to nil when ending the interaction. */ 4978 a toolkit scroll bar, reset to nil when ending the interaction. */
@@ -5505,8 +6229,7 @@ x_scroll_bar_create (struct window *w, int top, int left,
5505 for the case that a window has been split horizontally. In 6229 for the case that a window has been split horizontally. In
5506 this case, no clear_frame is generated to reduce flickering. */ 6230 this case, no clear_frame is generated to reduce flickering. */
5507 if (width > 0 && window_box_height (w) > 0) 6231 if (width > 0 && window_box_height (w) > 0)
5508 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6232 x_clear_area (f, left, top, width, window_box_height (w));
5509 left, top, width, window_box_height (w));
5510 6233
5511 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6234 window = XCreateWindow (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5512 /* Position and size of scroll bar. */ 6235 /* Position and size of scroll bar. */
@@ -5638,7 +6361,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
5638 /* Draw the empty space above the handle. Note that we can't clear 6361 /* Draw the empty space above the handle. Note that we can't clear
5639 zero-height areas; that means "clear to end of window." */ 6362 zero-height areas; that means "clear to end of window." */
5640 if ((inside_width > 0) && (start > 0)) 6363 if ((inside_width > 0) && (start > 0))
5641 x_clear_area (FRAME_X_DISPLAY (f), w, 6364 x_clear_area1 (FRAME_X_DISPLAY (f), w,
5642 VERTICAL_SCROLL_BAR_LEFT_BORDER, 6365 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5643 VERTICAL_SCROLL_BAR_TOP_BORDER, 6366 VERTICAL_SCROLL_BAR_TOP_BORDER,
5644 inside_width, start); 6367 inside_width, start);
@@ -5649,7 +6372,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
5649 f->output_data.x->scroll_bar_foreground_pixel); 6372 f->output_data.x->scroll_bar_foreground_pixel);
5650 6373
5651 /* Draw the handle itself. */ 6374 /* Draw the handle itself. */
5652 XFillRectangle (FRAME_X_DISPLAY (f), w, gc, 6375 x_fill_rectangle (f, gc,
5653 /* x, y, width, height */ 6376 /* x, y, width, height */
5654 VERTICAL_SCROLL_BAR_LEFT_BORDER, 6377 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5655 VERTICAL_SCROLL_BAR_TOP_BORDER + start, 6378 VERTICAL_SCROLL_BAR_TOP_BORDER + start,
@@ -5663,7 +6386,7 @@ x_scroll_bar_set_handle (struct scroll_bar *bar, int start, int end,
5663 /* Draw the empty space below the handle. Note that we can't 6386 /* Draw the empty space below the handle. Note that we can't
5664 clear zero-height areas; that means "clear to end of window." */ 6387 clear zero-height areas; that means "clear to end of window." */
5665 if ((inside_width > 0) && (end < inside_height)) 6388 if ((inside_width > 0) && (end < inside_height))
5666 x_clear_area (FRAME_X_DISPLAY (f), w, 6389 x_clear_area1 (FRAME_X_DISPLAY (f), w,
5667 VERTICAL_SCROLL_BAR_LEFT_BORDER, 6390 VERTICAL_SCROLL_BAR_LEFT_BORDER,
5668 VERTICAL_SCROLL_BAR_TOP_BORDER + end, 6391 VERTICAL_SCROLL_BAR_TOP_BORDER + end,
5669 inside_width, inside_height - end); 6392 inside_width, inside_height - end);
@@ -5730,8 +6453,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
5730 if (width > 0 && height > 0) 6453 if (width > 0 && height > 0)
5731 { 6454 {
5732 block_input (); 6455 block_input ();
5733 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6456 x_clear_area (f, left, top, width, height);
5734 left, top, width, height);
5735 unblock_input (); 6457 unblock_input ();
5736 } 6458 }
5737 6459
@@ -5763,8 +6485,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
5763 /* Since toolkit scroll bars are smaller than the space reserved 6485 /* Since toolkit scroll bars are smaller than the space reserved
5764 for them on the frame, we have to clear "under" them. */ 6486 for them on the frame, we have to clear "under" them. */
5765 if (width > 0 && height > 0) 6487 if (width > 0 && height > 0)
5766 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6488 x_clear_area (f, left, top, width, height);
5767 left, top, width, height);
5768#ifdef USE_GTK 6489#ifdef USE_GTK
5769 xg_update_scrollbar_pos (f, bar->x_window, top, 6490 xg_update_scrollbar_pos (f, bar->x_window, top,
5770 left, width, max (height, 1)); 6491 left, width, max (height, 1));
@@ -5850,8 +6571,7 @@ XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int posit
5850 6571
5851 /* Clear also part between window_width and 6572 /* Clear also part between window_width and
5852 WINDOW_PIXEL_WIDTH. */ 6573 WINDOW_PIXEL_WIDTH. */
5853 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6574 x_clear_area (f, left, top, pixel_width, height);
5854 left, top, pixel_width, height);
5855 unblock_input (); 6575 unblock_input ();
5856 } 6576 }
5857 6577
@@ -5882,7 +6602,7 @@ XTset_horizontal_scroll_bar (struct window *w, int portion, int whole, int posit
5882 /* Since toolkit scroll bars are smaller than the space reserved 6602 /* Since toolkit scroll bars are smaller than the space reserved
5883 for them on the frame, we have to clear "under" them. */ 6603 for them on the frame, we have to clear "under" them. */
5884 if (width > 0 && height > 0) 6604 if (width > 0 && height > 0)
5885 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6605 x_clear_area (f,
5886 WINDOW_LEFT_EDGE_X (w), top, 6606 WINDOW_LEFT_EDGE_X (w), top,
5887 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height); 6607 pixel_width - WINDOW_RIGHT_DIVIDER_WIDTH (w), height);
5888#ifdef USE_GTK 6608#ifdef USE_GTK
@@ -6128,7 +6848,7 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
6128 f->output_data.x->scroll_bar_foreground_pixel); 6848 f->output_data.x->scroll_bar_foreground_pixel);
6129 6849
6130 /* Draw a one-pixel border just inside the edges of the scroll bar. */ 6850 /* Draw a one-pixel border just inside the edges of the scroll bar. */
6131 XDrawRectangle (FRAME_X_DISPLAY (f), w, gc, 6851 x_draw_rectangle (f, gc,
6132 /* x, y, width, height */ 6852 /* x, y, width, height */
6133 0, 0, bar->width - 1, bar->height - 1); 6853 0, 0, bar->width - 1, bar->height - 1);
6134 6854
@@ -6912,11 +7632,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
6912 } 7632 }
6913 else 7633 else
6914 { 7634 {
6915#ifdef USE_GTK 7635#if defined (USE_GTK) && ! defined (HAVE_GTK3) && ! defined (USE_CAIRO)
6916 /* This seems to be needed for GTK 2.6 and later, see 7636 /* This seems to be needed for GTK 2.6 and later, see
6917 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */ 7637 http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15398. */
6918 x_clear_area (event->xexpose.display, 7638 x_clear_area (f,
6919 event->xexpose.window,
6920 event->xexpose.x, event->xexpose.y, 7639 event->xexpose.x, event->xexpose.y,
6921 event->xexpose.width, event->xexpose.height); 7640 event->xexpose.width, event->xexpose.height);
6922#endif 7641#endif
@@ -7530,6 +8249,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7530 8249
7531 case ConfigureNotify: 8250 case ConfigureNotify:
7532 f = x_top_window_to_frame (dpyinfo, event->xconfigure.window); 8251 f = x_top_window_to_frame (dpyinfo, event->xconfigure.window);
8252#ifdef USE_CAIRO
8253 if (f) x_cr_destroy_surface (f);
8254#endif
7533#ifdef USE_GTK 8255#ifdef USE_GTK
7534 if (!f 8256 if (!f
7535 && (f = any) 8257 && (f = any)
@@ -7537,6 +8259,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7537 { 8259 {
7538 xg_frame_resized (f, event->xconfigure.width, 8260 xg_frame_resized (f, event->xconfigure.width,
7539 event->xconfigure.height); 8261 event->xconfigure.height);
8262 x_cr_destroy_surface (f);
7540 f = 0; 8263 f = 0;
7541 } 8264 }
7542#endif 8265#endif
@@ -7946,7 +8669,7 @@ x_clip_to_row (struct window *w, struct glyph_row *row,
7946 clip_rect.width = window_width; 8669 clip_rect.width = window_width;
7947 clip_rect.height = row->visible_height; 8670 clip_rect.height = row->visible_height;
7948 8671
7949 XSetClipRectangles (FRAME_X_DISPLAY (f), gc, 0, 0, &clip_rect, 1, Unsorted); 8672 x_set_clip_rectangles (f, gc, &clip_rect, 1);
7950} 8673}
7951 8674
7952 8675
@@ -7995,8 +8718,8 @@ x_draw_hollow_cursor (struct window *w, struct glyph_row *row)
7995 } 8718 }
7996 /* Set clipping, draw the rectangle, and reset clipping again. */ 8719 /* Set clipping, draw the rectangle, and reset clipping again. */
7997 x_clip_to_row (w, row, TEXT_AREA, gc); 8720 x_clip_to_row (w, row, TEXT_AREA, gc);
7998 XDrawRectangle (dpy, FRAME_X_WINDOW (f), gc, x, y, wd, h - 1); 8721 x_draw_rectangle (f, gc, x, y, wd, h - 1);
7999 XSetClipMask (dpy, gc, None); 8722 x_reset_clip_rectangles (f, gc);
8000} 8723}
8001 8724
8002 8725
@@ -8074,7 +8797,7 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
8074 if ((cursor_glyph->resolved_level & 1) != 0) 8797 if ((cursor_glyph->resolved_level & 1) != 0)
8075 x += cursor_glyph->pixel_width - width; 8798 x += cursor_glyph->pixel_width - width;
8076 8799
8077 XFillRectangle (dpy, window, gc, x, 8800 x_fill_rectangle (f, gc, x,
8078 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), 8801 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
8079 width, row->height); 8802 width, row->height);
8080 } 8803 }
@@ -8094,13 +8817,13 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row, int width, enum text
8094 if ((cursor_glyph->resolved_level & 1) != 0 8817 if ((cursor_glyph->resolved_level & 1) != 0
8095 && cursor_glyph->pixel_width > w->phys_cursor_width - 1) 8818 && cursor_glyph->pixel_width > w->phys_cursor_width - 1)
8096 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1; 8819 x += cursor_glyph->pixel_width - w->phys_cursor_width + 1;
8097 XFillRectangle (dpy, window, gc, x, 8820 x_fill_rectangle (f, gc, x,
8098 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + 8821 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
8099 row->height - width), 8822 row->height - width),
8100 w->phys_cursor_width - 1, width); 8823 w->phys_cursor_width - 1, width);
8101 } 8824 }
8102 8825
8103 XSetClipMask (dpy, gc, None); 8826 x_reset_clip_rectangles (f, gc);
8104 } 8827 }
8105} 8828}
8106 8829
@@ -8122,7 +8845,7 @@ x_define_frame_cursor (struct frame *f, Cursor cursor)
8122static void 8845static void
8123x_clear_frame_area (struct frame *f, int x, int y, int width, int height) 8846x_clear_frame_area (struct frame *f, int x, int y, int width, int height)
8124{ 8847{
8125 x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), x, y, width, height); 8848 x_clear_area (f, x, y, width, height);
8126#ifdef USE_GTK 8849#ifdef USE_GTK
8127 /* Must queue a redraw, because scroll bars might have been cleared. */ 8850 /* Must queue a redraw, because scroll bars might have been cleared. */
8128 if (FRAME_GTK_WIDGET (f)) 8851 if (FRAME_GTK_WIDGET (f))
@@ -10235,6 +10958,7 @@ x_free_frame_resources (struct frame *f)
10235 free_frame_xic (f); 10958 free_frame_xic (f);
10236#endif 10959#endif
10237 10960
10961 x_prepare_for_xlibdraw (f);
10238#ifdef USE_X_TOOLKIT 10962#ifdef USE_X_TOOLKIT
10239 if (f->output_data.x->widget) 10963 if (f->output_data.x->widget)
10240 { 10964 {
@@ -11312,6 +12036,10 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
11312 x_session_initialize (dpyinfo); 12036 x_session_initialize (dpyinfo);
11313#endif 12037#endif
11314 12038
12039#ifdef USE_CAIRO
12040 x_extension_initialize (dpyinfo);
12041#endif
12042
11315 unblock_input (); 12043 unblock_input ();
11316 12044
11317 return dpyinfo; 12045 return dpyinfo;
@@ -11423,8 +12151,13 @@ static struct redisplay_interface x_redisplay_interface =
11423 x_get_glyph_overhangs, 12151 x_get_glyph_overhangs,
11424 x_fix_overlapping_area, 12152 x_fix_overlapping_area,
11425 x_draw_fringe_bitmap, 12153 x_draw_fringe_bitmap,
12154#ifdef USE_CAIRO
12155 x_cr_define_fringe_bitmap,
12156 x_cr_destroy_fringe_bitmap,
12157#else
11426 0, /* define_fringe_bitmap */ 12158 0, /* define_fringe_bitmap */
11427 0, /* destroy_fringe_bitmap */ 12159 0, /* destroy_fringe_bitmap */
12160#endif
11428 x_compute_glyph_string_overhangs, 12161 x_compute_glyph_string_overhangs,
11429 x_draw_glyph_string, 12162 x_draw_glyph_string,
11430 x_define_frame_cursor, 12163 x_define_frame_cursor,
@@ -11602,6 +12335,10 @@ x_initialize (void)
11602#endif 12335#endif
11603#endif 12336#endif
11604 12337
12338#ifdef USE_CAIRO
12339 x_cr_init_fringe (&x_redisplay_interface);
12340#endif
12341
11605 /* Note that there is no real way portable across R3/R4 to get the 12342 /* Note that there is no real way portable across R3/R4 to get the
11606 original error handler. */ 12343 original error handler. */
11607 XSetErrorHandler (x_error_handler); 12344 XSetErrorHandler (x_error_handler);
diff --git a/src/xterm.h b/src/xterm.h
index e597227c81c..eb8eaae5de5 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -70,6 +70,19 @@ typedef GtkWidget *xt_or_gtk_widget;
70#define USE_GTK_TOOLTIP 70#define USE_GTK_TOOLTIP
71#endif 71#endif
72 72
73#ifdef USE_CAIRO
74#include <cairo-xlib.h>
75#ifdef CAIRO_HAS_PDF_SURFACE
76#include <cairo-pdf.h>
77#endif
78#ifdef CAIRO_HAS_PS_SURFACE
79#include <cairo-ps.h>
80#endif
81#ifdef CAIRO_HAS_SVG_SURFACE
82#include <cairo-svg.h>
83#endif
84#endif
85
73#ifdef HAVE_X_I18N 86#ifdef HAVE_X_I18N
74#include <X11/Xlocale.h> 87#include <X11/Xlocale.h>
75#endif 88#endif
@@ -115,6 +128,9 @@ struct xim_inst_t
115 128
116struct x_bitmap_record 129struct x_bitmap_record
117{ 130{
131#ifdef USE_CAIRO
132 void *img;
133#endif
118 Pixmap pixmap; 134 Pixmap pixmap;
119 bool have_mask; 135 bool have_mask;
120 Pixmap mask; 136 Pixmap mask;
@@ -124,6 +140,19 @@ struct x_bitmap_record
124 int height, width, depth; 140 int height, width, depth;
125}; 141};
126 142
143#ifdef USE_CAIRO
144struct x_gc_ext_data
145{
146#define MAX_CLIP_RECTS 2
147 /* Number of clipping rectangles. */
148 int n_clip_rects;
149
150 /* Clipping rectangles. */
151 XRectangle clip_rects[MAX_CLIP_RECTS];
152};
153#endif
154
155
127/* For each X display, we have a structure that records 156/* For each X display, we have a structure that records
128 information about it. */ 157 information about it. */
129 158
@@ -411,6 +440,10 @@ struct x_display_info
411 440
412 /* SM */ 441 /* SM */
413 Atom Xatom_SM_CLIENT_ID; 442 Atom Xatom_SM_CLIENT_ID;
443
444#ifdef USE_CAIRO
445 XExtCodes *ext_codes;
446#endif
414}; 447};
415 448
416#ifdef HAVE_X_I18N 449#ifdef HAVE_X_I18N
@@ -645,7 +678,6 @@ struct x_output
645 /* The offset we need to add to compensate for type A WMs. */ 678 /* The offset we need to add to compensate for type A WMs. */
646 int move_offset_top; 679 int move_offset_top;
647 int move_offset_left; 680 int move_offset_left;
648};
649 681
650/* Extreme 'short' and 'long' values suitable for libX11. */ 682/* Extreme 'short' and 'long' values suitable for libX11. */
651#define X_SHRT_MAX 0x7fff 683#define X_SHRT_MAX 0x7fff
@@ -654,6 +686,14 @@ struct x_output
654#define X_LONG_MIN (-1 - X_LONG_MAX) 686#define X_LONG_MIN (-1 - X_LONG_MAX)
655#define X_ULONG_MAX 0xffffffffUL 687#define X_ULONG_MAX 0xffffffffUL
656 688
689#ifdef USE_CAIRO
690 /* Cairo drawing context. */
691 cairo_t *cr_context;
692 /* Cairo surface for double buffering */
693 cairo_surface_t *cr_surface;
694#endif
695};
696
657#define No_Cursor (None) 697#define No_Cursor (None)
658 698
659enum 699enum
@@ -1000,7 +1040,8 @@ extern bool x_alloc_lighter_color_for_widget (Widget, Display *, Colormap,
1000 double, int); 1040 double, int);
1001#endif 1041#endif
1002extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *); 1042extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *);
1003extern void x_clear_area (Display *, Window, int, int, int, int); 1043extern void x_query_color (struct frame *f, XColor *);
1044extern void x_clear_area (struct frame *f, int, int, int, int);
1004#if !defined USE_X_TOOLKIT && !defined USE_GTK 1045#if !defined USE_X_TOOLKIT && !defined USE_GTK
1005extern void x_mouse_leave (struct x_display_info *); 1046extern void x_mouse_leave (struct x_display_info *);
1006#endif 1047#endif
@@ -1009,6 +1050,14 @@ extern void x_mouse_leave (struct x_display_info *);
1009extern int x_dispatch_event (XEvent *, Display *); 1050extern int x_dispatch_event (XEvent *, Display *);
1010#endif 1051#endif
1011extern int x_x_to_emacs_modifiers (struct x_display_info *, int); 1052extern int x_x_to_emacs_modifiers (struct x_display_info *, int);
1053#ifdef USE_CAIRO
1054extern cairo_t *x_begin_cr_clip (struct frame *, GC);
1055extern void x_end_cr_clip (struct frame *);
1056extern void x_set_cr_source_with_gc_foreground (struct frame *, GC);
1057extern void x_set_cr_source_with_gc_background (struct frame *, GC);
1058extern void x_cr_draw_frame (cairo_t *, struct frame *);
1059extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t);
1060#endif
1012 1061
1013INLINE int 1062INLINE int
1014x_display_pixel_height (struct x_display_info *dpyinfo) 1063x_display_pixel_height (struct x_display_info *dpyinfo)