diff options
| author | Jan D | 2015-02-11 16:14:35 +0100 |
|---|---|---|
| committer | Jan D | 2015-02-11 16:14:35 +0100 |
| commit | dddcc0e78452f2186c132823a33a174d2596ba33 (patch) | |
| tree | 8369d54925d9ea4b60ecf6a53c6a321dffd194f9 /src | |
| parent | 061c7e2b5a5a5854b2b85f2ace5b1d9222dd7f11 (diff) | |
| download | emacs-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/ChangeLog | 138 | ||||
| -rw-r--r-- | src/Makefile.in | 8 | ||||
| -rw-r--r-- | src/dispextern.h | 6 | ||||
| -rw-r--r-- | src/font.c | 4 | ||||
| -rw-r--r-- | src/font.h | 4 | ||||
| -rw-r--r-- | src/fringe.c | 8 | ||||
| -rw-r--r-- | src/ftcrfont.c | 314 | ||||
| -rw-r--r-- | src/ftfont.c | 26 | ||||
| -rw-r--r-- | src/ftfont.h | 5 | ||||
| -rw-r--r-- | src/gtkutil.c | 131 | ||||
| -rw-r--r-- | src/gtkutil.h | 6 | ||||
| -rw-r--r-- | src/image.c | 55 | ||||
| -rw-r--r-- | src/xfns.c | 195 | ||||
| -rw-r--r-- | src/xterm.c | 895 | ||||
| -rw-r--r-- | src/xterm.h | 53 |
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 @@ | |||
| 1 | 2015-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 | |||
| 1 | 2015-02-11 Martin Rudalics <rudalics@gmx.at> | 139 | 2015-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@ | |||
| 218 | RSVG_LIBS= @RSVG_LIBS@ | 218 | RSVG_LIBS= @RSVG_LIBS@ |
| 219 | RSVG_CFLAGS= @RSVG_CFLAGS@ | 219 | RSVG_CFLAGS= @RSVG_CFLAGS@ |
| 220 | 220 | ||
| 221 | CAIRO_LIBS= @CAIRO_LIBS@ | ||
| 222 | CAIRO_CFLAGS= @CAIRO_CFLAGS@ | ||
| 223 | |||
| 221 | IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@ | 224 | IMAGEMAGICK_LIBS= @IMAGEMAGICK_LIBS@ |
| 222 | IMAGEMAGICK_CFLAGS= @IMAGEMAGICK_CFLAGS@ | 225 | IMAGEMAGICK_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 |
| 277 | FONT_OBJ=@FONT_OBJ@ | 281 | FONT_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) |
| 350 | ALL_OBJC_CFLAGS=$(ALL_CFLAGS) $(GNU_OBJC_CFLAGS) | 354 | ALL_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); | |||
| 3300 | void w32_init_fringe (struct redisplay_interface *); | 3303 | void w32_init_fringe (struct redisplay_interface *); |
| 3301 | void w32_reset_fringes (void); | 3304 | void w32_reset_fringes (void); |
| 3302 | #endif | 3305 | #endif |
| 3306 | #ifdef USE_CAIRO | ||
| 3307 | void x_cr_init_fringe (struct redisplay_interface *); | ||
| 3308 | #endif | ||
| 3303 | 3309 | ||
| 3304 | extern unsigned row_hash (struct glyph_row *); | 3310 | extern 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; | |||
| 844 | extern void syms_of_nsfont (void); | 844 | extern void syms_of_nsfont (void); |
| 845 | extern void syms_of_macfont (void); | 845 | extern void syms_of_macfont (void); |
| 846 | #endif /* HAVE_NS */ | 846 | #endif /* HAVE_NS */ |
| 847 | #ifdef USE_CAIRO | ||
| 848 | extern struct font_driver ftcrfont_driver; | ||
| 849 | extern 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 | ||
| 1736 | void | 1736 | void |
| 1737 | #ifdef HAVE_NTGUI | ||
| 1737 | w32_init_fringe (struct redisplay_interface *rif) | 1738 | w32_init_fringe (struct redisplay_interface *rif) |
| 1739 | #else | ||
| 1740 | x_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 | ||
| 1751 | void | 1757 | void |
| 1752 | w32_reset_fringes (void) | 1758 | w32_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 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 3 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 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 | |||
| 40 | struct 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 | |||
| 64 | enum 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. */ | ||
| 74 | static int ftcrfont_glyph_extents (struct font *, unsigned, | ||
| 75 | struct font_metrics *); | ||
| 76 | |||
| 77 | /* Prototypes for font-driver methods. */ | ||
| 78 | static Lisp_Object ftcrfont_list (struct frame*, Lisp_Object); | ||
| 79 | static Lisp_Object ftcrfont_match (struct frame*, Lisp_Object); | ||
| 80 | static Lisp_Object ftcrfont_open (struct frame*, Lisp_Object, int); | ||
| 81 | static void ftcrfont_close (struct font *); | ||
| 82 | static void ftcrfont_text_extents (struct font *, unsigned *, int, | ||
| 83 | struct font_metrics *); | ||
| 84 | static int ftcrfont_draw (struct glyph_string *, int, int, int, int, bool); | ||
| 85 | |||
| 86 | struct font_driver ftcrfont_driver; | ||
| 87 | |||
| 88 | static int | ||
| 89 | ftcrfont_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 | |||
| 130 | static Lisp_Object | ||
| 131 | ftcrfont_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 | |||
| 140 | static Lisp_Object | ||
| 141 | ftcrfont_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 | |||
| 150 | extern FT_Face ftfont_get_ft_face (Lisp_Object); | ||
| 151 | |||
| 152 | static Lisp_Object | ||
| 153 | ftcrfont_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 | |||
| 186 | static void | ||
| 187 | ftcrfont_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 | |||
| 205 | static void | ||
| 206 | ftcrfont_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 | |||
| 239 | static int | ||
| 240 | ftcrfont_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 | |||
| 297 | void | ||
| 298 | syms_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 | ||
| 70 | size_t ftfont_info_size = sizeof (struct ftfont_info); | ||
| 71 | |||
| 70 | enum ftfont_cache_for | 72 | enum 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 | ||
| 1164 | static Lisp_Object | 1166 | Lisp_Object |
| 1165 | ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size) | 1167 | ftfont_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 | ||
| 1300 | static Lisp_Object | ||
| 1301 | ftfont_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 | |||
| 1297 | static void | 1313 | static void |
| 1298 | ftfont_close (struct font *font) | 1314 | ftfont_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 | ||
| 39 | extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); | 39 | extern FcCharSet *ftfont_get_fc_charset (Lisp_Object); |
| 40 | extern Lisp_Object ftfont_open2 (struct frame *f, | ||
| 41 | Lisp_Object entity, | ||
| 42 | int pixel_size, | ||
| 43 | Lisp_Object font_object); | ||
| 44 | extern 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 | ||
| 4050 | static GtkPrintSettings *print_settings = NULL; | ||
| 4051 | static GtkPageSetup *page_setup = NULL; | ||
| 4052 | |||
| 4053 | void | ||
| 4054 | xg_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 | |||
| 4067 | Lisp_Object | ||
| 4068 | xg_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 | |||
| 4109 | static void | ||
| 4110 | draw_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 | |||
| 4123 | void | ||
| 4124 | xg_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, | |||
| 180 | extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); | 180 | extern void xg_show_tooltip (struct frame *f, int root_x, int root_y); |
| 181 | extern bool xg_hide_tooltip (struct frame *f); | 181 | extern bool xg_hide_tooltip (struct frame *f); |
| 182 | 182 | ||
| 183 | #ifdef USE_CAIRO | ||
| 184 | extern void xg_page_setup_dialog (void); | ||
| 185 | extern Lisp_Object xg_get_page_setup (void); | ||
| 186 | extern 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. */ |
| 184 | extern void xg_mark_data (void); | 190 | extern 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 | |||
| 1299 | x_clear_image (struct frame *f, struct image *img) | 1299 | x_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 | |||
| 6062 | static bool | ||
| 6063 | png_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 | ||
| 6155 | DEFUN ("x-export-frames", Fx_export_frames, Sx_export_frames, 0, 2, 0, | ||
| 6156 | doc: /* XXX Experimental. Return image data of FRAMES in TYPE format. | ||
| 6157 | FRAMES should be nil (the selected frame), a frame, or a list of | ||
| 6158 | frames (each of which corresponds to one page). Optional arg TYPE | ||
| 6159 | should be either `pdf' (default), `png', `ps', or `svg'. Supported | ||
| 6160 | types 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 | ||
| 6224 | DEFUN ("x-page-setup-dialog", Fx_page_setup_dialog, Sx_page_setup_dialog, 0, 0, 0, | ||
| 6225 | doc: /* Pop up a page setup dialog. | ||
| 6226 | The 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 | |||
| 6236 | DEFUN ("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. | ||
| 6238 | The 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 | |||
| 6247 | The paper width can be obtained as the sum of width, left-margin, and | ||
| 6248 | right-margin values. Likewise, the paper height is the sum of height, | ||
| 6249 | top-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 | |||
| 6261 | DEFUN ("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. | ||
| 6263 | FRAMES should be nil (the selected frame), a frame, or a list of | ||
| 6264 | frames (each of which corresponds to one page). Each frame should be | ||
| 6265 | visible. */) | ||
| 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 *); | |||
| 220 | static struct terminal *x_create_terminal (struct x_display_info *); | 220 | static struct terminal *x_create_terminal (struct x_display_info *); |
| 221 | static void x_update_end (struct frame *); | 221 | static void x_update_end (struct frame *); |
| 222 | static void XTframe_up_to_date (struct frame *); | 222 | static void XTframe_up_to_date (struct frame *); |
| 223 | static void x_clear_area1 (Display *, Window, int, int, int, int, int); | ||
| 223 | static void x_clear_frame (struct frame *); | 224 | static void x_clear_frame (struct frame *); |
| 224 | static _Noreturn void x_ins_del_lines (struct frame *, int, int); | 225 | static _Noreturn void x_ins_del_lines (struct frame *, int, int); |
| 225 | static void frame_highlight (struct frame *); | 226 | static void frame_highlight (struct frame *); |
| @@ -325,6 +326,555 @@ record_event (char *locus, int type) | |||
| 325 | 326 | ||
| 326 | #endif | 327 | #endif |
| 327 | 328 | ||
| 329 | static void x_prepare_for_xlibdraw (struct frame *); | ||
| 330 | static void x_set_clip_rectangles (struct frame *, GC, XRectangle *, int); | ||
| 331 | static void x_reset_clip_rectangles (struct frame *, GC); | ||
| 332 | static void x_fill_rectangle (struct frame *, GC, int, int, | ||
| 333 | unsigned int, unsigned int); | ||
| 334 | static void x_draw_rectangle (struct frame *, GC, int, int, | ||
| 335 | unsigned int, unsigned int); | ||
| 336 | static void x_fill_trapezoid_for_relief (struct frame *, GC, int, int, | ||
| 337 | unsigned int, unsigned int, int); | ||
| 338 | static void x_clear_window (struct frame *); | ||
| 339 | |||
| 340 | #ifdef USE_CAIRO | ||
| 341 | static struct x_gc_ext_data *x_gc_get_ext_data (struct frame *, GC, int); | ||
| 342 | static void x_extension_initialize (struct x_display_info *); | ||
| 343 | static 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 | |||
| 350 | static struct x_gc_ext_data * | ||
| 351 | x_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 | |||
| 378 | static void | ||
| 379 | x_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 | |||
| 387 | static void | ||
| 388 | x_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 | |||
| 400 | cairo_t * | ||
| 401 | x_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 | |||
| 447 | void | ||
| 448 | x_end_cr_clip (f) | ||
| 449 | struct frame *f; | ||
| 450 | { | ||
| 451 | cairo_restore (FRAME_CR_CONTEXT (f)); | ||
| 452 | } | ||
| 453 | |||
| 454 | void | ||
| 455 | x_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 | |||
| 469 | void | ||
| 470 | x_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 | |||
| 486 | static int max_fringe_bmp = 0; | ||
| 487 | static cairo_pattern_t **fringe_bmp = 0; | ||
| 488 | |||
| 489 | static void | ||
| 490 | x_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 | |||
| 529 | static void | ||
| 530 | x_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 | |||
| 545 | static void | ||
| 546 | x_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 | |||
| 589 | void | ||
| 590 | x_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 | |||
| 606 | static cairo_status_t | ||
| 607 | x_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 | |||
| 619 | static void | ||
| 620 | x_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 | |||
| 630 | Lisp_Object | ||
| 631 | x_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 | |||
| 731 | static void | ||
| 732 | x_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 | |||
| 761 | static void | ||
| 762 | x_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 | |||
| 781 | static void | ||
| 782 | x_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 | |||
| 797 | static void | ||
| 798 | x_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 | |||
| 818 | static void | ||
| 819 | x_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 | |||
| 840 | static void | ||
| 841 | x_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 | ||
| 857 | static void | ||
| 858 | x_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) | |||
| 452 | static void | 1002 | static void |
| 453 | x_update_begin (struct frame *f) | 1003 | x_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) | |||
| 2896 | static void | 3591 | static void |
| 2897 | x_shift_glyphs_for_insert (struct frame *f, int x, int y, int width, int height, int shift_by) | 3592 | x_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 | ||
| 3614 | static void | ||
| 3615 | x_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 | |||
| 2918 | void | 3623 | void |
| 2919 | x_clear_area (Display *dpy, Window window, int x, int y, int width, int height) | 3624 | x_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 | ||
| 4250 | static void x_send_scroll_bar_event (Lisp_Object, enum scroll_bar_part, | 4974 | static 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) | |||
| 8122 | static void | 8845 | static void |
| 8123 | x_clear_frame_area (struct frame *f, int x, int y, int width, int height) | 8846 | x_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 | ||
| 116 | struct x_bitmap_record | 129 | struct 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 | ||
| 144 | struct 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 | ||
| 659 | enum | 699 | enum |
| @@ -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 |
| 1002 | extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *); | 1042 | extern bool x_alloc_nearest_color (struct frame *, Colormap, XColor *); |
| 1003 | extern void x_clear_area (Display *, Window, int, int, int, int); | 1043 | extern void x_query_color (struct frame *f, XColor *); |
| 1044 | extern 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 |
| 1005 | extern void x_mouse_leave (struct x_display_info *); | 1046 | extern 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 *); | |||
| 1009 | extern int x_dispatch_event (XEvent *, Display *); | 1050 | extern int x_dispatch_event (XEvent *, Display *); |
| 1010 | #endif | 1051 | #endif |
| 1011 | extern int x_x_to_emacs_modifiers (struct x_display_info *, int); | 1052 | extern int x_x_to_emacs_modifiers (struct x_display_info *, int); |
| 1053 | #ifdef USE_CAIRO | ||
| 1054 | extern cairo_t *x_begin_cr_clip (struct frame *, GC); | ||
| 1055 | extern void x_end_cr_clip (struct frame *); | ||
| 1056 | extern void x_set_cr_source_with_gc_foreground (struct frame *, GC); | ||
| 1057 | extern void x_set_cr_source_with_gc_background (struct frame *, GC); | ||
| 1058 | extern void x_cr_draw_frame (cairo_t *, struct frame *); | ||
| 1059 | extern Lisp_Object x_cr_export_frames (Lisp_Object, cairo_surface_type_t); | ||
| 1060 | #endif | ||
| 1012 | 1061 | ||
| 1013 | INLINE int | 1062 | INLINE int |
| 1014 | x_display_pixel_height (struct x_display_info *dpyinfo) | 1063 | x_display_pixel_height (struct x_display_info *dpyinfo) |